From 3bee4d9855e27a61bcf7d5a2344bc0c9b1884490 Mon Sep 17 00:00:00 2001 From: "cr.zoidberg" Date: Sat, 6 Apr 2024 18:23:32 +0200 Subject: [PATCH] removed copy of zano --- src/common/atomics_boost_serialization.h | 32 - src/common/base58.cpp | 248 - src/common/base58.h | 22 - src/common/boost_serialization_helper.h | 104 - src/common/callstack_helper.cpp | 184 - src/common/callstack_helper.h | 24 - src/common/command_line.cpp | 42 - src/common/command_line.h | 227 - src/common/config_encrypt_helper.h | 66 - src/common/crypto_boost_serialization.h | 57 - src/common/crypto_stream_operators.cpp | 18 - src/common/crypto_stream_operators.h | 44 - src/common/db_abstract_accessor.h | 1102 - src/common/db_backend_base.h | 53 - src/common/db_backend_leveldb.cpp | 109 - src/common/db_backend_leveldb.h | 46 - src/common/db_backend_lmdb.cpp | 401 - src/common/db_backend_lmdb.h | 65 - src/common/db_backend_mdbx.cpp | 413 - src/common/db_backend_mdbx.h | 67 - src/common/db_backend_selector.cpp | 132 - src/common/db_backend_selector.h | 43 - src/common/difficulty_boost_serialization.h | 69 - src/common/encryption_filter.cpp | 7 - src/common/encryption_filter.h | 244 - src/common/error_codes.h | 43 - src/common/general_purpose_commands_defs.h | 40 - src/common/int-util.h | 247 - src/common/make_hashable.h | 57 - src/common/median_db_cache.h | 133 - src/common/miniupnp_helper.h | 185 - src/common/mnemonic-encoding.cpp | 3395 ---- src/common/mnemonic-encoding.h | 51 - src/common/ntp.cpp | 265 - src/common/ntp.h | 18 - src/common/pod-class.h | 9 - src/common/pod_array_file_container.h | 127 - src/common/pre_download.h | 227 - ...unordered_containers_boost_serialization.h | 119 - src/common/util.cpp | 754 - src/common/util.h | 287 - src/common/varint.h | 86 - src/contrib/db/CMakeLists.txt | 20 - src/contrib/db/liblmdb/.gitignore | 23 - src/contrib/db/liblmdb/CHANGES | 192 - src/contrib/db/liblmdb/CMakeLists.txt | 19 - src/contrib/db/liblmdb/COPYRIGHT | 20 - src/contrib/db/liblmdb/Doxyfile | 1631 -- src/contrib/db/liblmdb/LICENSE | 47 - src/contrib/db/liblmdb/Makefile | 116 - src/contrib/db/liblmdb/intro.doc | 192 - src/contrib/db/liblmdb/lmdb.h | 1618 -- src/contrib/db/liblmdb/mdb.c | 10945 ---------- src/contrib/db/liblmdb/mdb_copy.1 | 60 - src/contrib/db/liblmdb/mdb_copy.c | 84 - src/contrib/db/liblmdb/mdb_dump.1 | 81 - src/contrib/db/liblmdb/mdb_dump.c | 330 - src/contrib/db/liblmdb/mdb_load.1 | 84 - src/contrib/db/liblmdb/mdb_load.c | 499 - src/contrib/db/liblmdb/mdb_stat.1 | 70 - src/contrib/db/liblmdb/mdb_stat.c | 276 - src/contrib/db/liblmdb/midl.c | 420 - src/contrib/db/liblmdb/midl.h | 204 - src/contrib/db/liblmdb/mtest.c | 177 - src/contrib/db/liblmdb/mtest2.c | 124 - src/contrib/db/liblmdb/mtest3.c | 133 - src/contrib/db/liblmdb/mtest4.c | 168 - src/contrib/db/liblmdb/mtest5.c | 135 - src/contrib/db/liblmdb/mtest6.c | 141 - src/contrib/db/liblmdb/sample-bdb.txt | 73 - src/contrib/db/liblmdb/sample-mdb.txt | 62 - src/contrib/db/liblmdb/tooltag | 22 - src/contrib/db/libmdbx/.circleci/config.yml | 20 - src/contrib/db/libmdbx/.clang-format | 3 - src/contrib/db/libmdbx/.gitignore | 35 - src/contrib/db/libmdbx/.travis.yml | 61 - src/contrib/db/libmdbx/AUTHORS | 32 - .../db/libmdbx/CMakeLists.dist-minimal | 192 - src/contrib/db/libmdbx/CMakeLists.txt | 342 - src/contrib/db/libmdbx/COPYRIGHT | 22 - src/contrib/db/libmdbx/GNUmakefile | 362 - src/contrib/db/libmdbx/LICENSE | 47 - src/contrib/db/libmdbx/README.md | 591 - src/contrib/db/libmdbx/appveyor.yml | 99 - src/contrib/db/libmdbx/cmake/compiler.cmake | 666 - src/contrib/db/libmdbx/cmake/profile.cmake | 45 - src/contrib/db/libmdbx/cmake/utils.cmake | 183 - src/contrib/db/libmdbx/example/CMakeLists.txt | 6 - src/contrib/db/libmdbx/example/README.md | 1 - src/contrib/db/libmdbx/example/example-mdbx.c | 112 - src/contrib/db/libmdbx/example/sample-bdb.txt | 77 - src/contrib/db/libmdbx/mdbx.h | 3497 ---- .../db/libmdbx/packages/rpm/CMakeLists.txt | 184 - src/contrib/db/libmdbx/packages/rpm/build.sh | 18 - .../db/libmdbx/packages/rpm/package.sh | 25 - src/contrib/db/libmdbx/src/CMakeLists.txt | 225 - src/contrib/db/libmdbx/src/alloy.c | 26 - .../db/libmdbx/src/elements/config.h.in | 56 - src/contrib/db/libmdbx/src/elements/core.c | 16709 ---------------- src/contrib/db/libmdbx/src/elements/defs.h | 450 - .../db/libmdbx/src/elements/internals.h | 1367 -- .../db/libmdbx/src/elements/lck-posix.c | 551 - .../db/libmdbx/src/elements/lck-windows.c | 777 - src/contrib/db/libmdbx/src/elements/ntdll.def | 1244 -- src/contrib/db/libmdbx/src/elements/osal.c | 1899 -- src/contrib/db/libmdbx/src/elements/osal.h | 959 - .../db/libmdbx/src/elements/version.c.in | 46 - src/contrib/db/libmdbx/src/man1/mdbx_chk.1 | 87 - src/contrib/db/libmdbx/src/man1/mdbx_copy.1 | 60 - src/contrib/db/libmdbx/src/man1/mdbx_dump.1 | 80 - src/contrib/db/libmdbx/src/man1/mdbx_load.1 | 89 - src/contrib/db/libmdbx/src/man1/mdbx_stat.1 | 69 - .../db/libmdbx/src/tools/CMakeLists.txt | 42 - src/contrib/db/libmdbx/src/tools/mdbx_chk.c | 1430 -- src/contrib/db/libmdbx/src/tools/mdbx_copy.c | 130 - src/contrib/db/libmdbx/src/tools/mdbx_dump.c | 352 - src/contrib/db/libmdbx/src/tools/mdbx_load.c | 567 - src/contrib/db/libmdbx/src/tools/mdbx_stat.c | 436 - src/contrib/db/libmdbx/src/tools/wingetopt.c | 95 - src/contrib/db/libmdbx/src/tools/wingetopt.h | 30 - src/contrib/db/libmdbx/test/CMakeLists.txt | 53 - src/contrib/db/libmdbx/test/append.cc | 164 - src/contrib/db/libmdbx/test/base.h | 116 - src/contrib/db/libmdbx/test/cases.cc | 99 - src/contrib/db/libmdbx/test/chrono.cc | 136 - src/contrib/db/libmdbx/test/chrono.h | 99 - src/contrib/db/libmdbx/test/config.cc | 602 - src/contrib/db/libmdbx/test/config.h | 326 - src/contrib/db/libmdbx/test/copy.cc | 26 - src/contrib/db/libmdbx/test/darwin/LICENSE | 24 - src/contrib/db/libmdbx/test/darwin/README.md | 8 - .../db/libmdbx/test/darwin/pthread_barrier.c | 110 - .../db/libmdbx/test/darwin/pthread_barrier.h | 83 - src/contrib/db/libmdbx/test/dead.cc | 35 - src/contrib/db/libmdbx/test/hill.cc | 409 - src/contrib/db/libmdbx/test/jitter.cc | 59 - src/contrib/db/libmdbx/test/keygen.cc | 275 - src/contrib/db/libmdbx/test/keygen.h | 130 - src/contrib/db/libmdbx/test/log.cc | 371 - src/contrib/db/libmdbx/test/log.h | 104 - .../db/libmdbx/test/long_stochastic.sh | 220 - src/contrib/db/libmdbx/test/main.cc | 617 - src/contrib/db/libmdbx/test/nested.cc | 284 - src/contrib/db/libmdbx/test/osal-unix.cc | 368 - src/contrib/db/libmdbx/test/osal-windows.cc | 461 - src/contrib/db/libmdbx/test/osal.h | 49 - .../db/libmdbx/test/pcrf/CMakeLists.txt | 5 - src/contrib/db/libmdbx/test/pcrf/README.md | 2 - src/contrib/db/libmdbx/test/pcrf/pcrf_test.c | 413 - src/contrib/db/libmdbx/test/test.cc | 736 - src/contrib/db/libmdbx/test/test.h | 314 - src/contrib/db/libmdbx/test/try.cc | 20 - src/contrib/db/libmdbx/test/ttl.cc | 172 - src/contrib/db/libmdbx/test/utils.cc | 370 - src/contrib/db/libmdbx/test/utils.h | 362 - .../db/libmdbx/test/valgrind_suppress.txt | 24 - src/contrib/eos_portable_archive/.DS_Store | Bin 6148 -> 0 bytes .../eos_portable_archive/change_log.txt | 36 - .../eos/polymorphic_portable_archive.hpp | 35 - .../eos/portable_archive.hpp | 36 - .../eos/portable_archive_exception.hpp | 96 - .../eos/portable_iarchive.hpp | 501 - .../eos/portable_oarchive.hpp | 488 - .../eos_portable_archive/release_notes.txt | 36 - .../eos_portable_archive/tutorial/.DS_Store | Bin 6148 -> 0 bytes .../eos_portable_archive/tutorial/._.DS_Store | Bin 4096 -> 0 bytes .../eos_portable_archive/tutorial/._code | Bin 4096 -> 0 bytes .../eos_portable_archive/tutorial/._images | Bin 4096 -> 0 bytes .../eos_portable_archive/tutorial/._scripts | Bin 4096 -> 0 bytes .../eos_portable_archive/tutorial/._styles | Bin 4096 -> 0 bytes .../tutorial/._tutorial.html | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_0.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_1.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_10.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_10b.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_11.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_2.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_3.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_4.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_5.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_6.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_7.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_8.cpp | Bin 4096 -> 0 bytes .../tutorial/code/._tutorial_pba_9.cpp | Bin 4096 -> 0 bytes .../tutorial/code/tutorial_pba_0.cpp | 56 - .../tutorial/code/tutorial_pba_1.cpp | 68 - .../tutorial/code/tutorial_pba_10.cpp | 162 - .../tutorial/code/tutorial_pba_10b.cpp | 198 - .../tutorial/code/tutorial_pba_11.cpp | 187 - .../tutorial/code/tutorial_pba_2.cpp | 105 - .../tutorial/code/tutorial_pba_3.cpp | 70 - .../tutorial/code/tutorial_pba_4.cpp | 105 - .../tutorial/code/tutorial_pba_5.cpp | 111 - .../tutorial/code/tutorial_pba_6.cpp | 112 - .../tutorial/code/tutorial_pba_7.cpp | 54 - .../tutorial/code/tutorial_pba_8.cpp | 118 - .../tutorial/code/tutorial_pba_9.cpp | 134 - .../tutorial/images/._boost.png | Bin 4096 -> 0 bytes .../tutorial/images/._c++-source-code.png | Bin 4096 -> 0 bytes .../tutorial/images/boost.png | Bin 6308 -> 0 bytes .../tutorial/images/c++-source-code.png | Bin 1296 -> 0 bytes .../tutorial/scripts/._jquery-1.4.min.js | Bin 4096 -> 0 bytes .../tutorial/scripts/jquery-1.4.min.js | 151 - .../tutorial/styles/._boost.css | Bin 4096 -> 0 bytes .../tutorial/styles/._style.css | Bin 4096 -> 0 bytes .../tutorial/styles/boost.css | 39 - .../tutorial/styles/style.css | 92 - .../tutorial/tutorial.html | 2348 --- src/contrib/epee/LICENSE.txt | 25 - src/contrib/epee/README.md | 1 - src/contrib/epee/demo/.gitignore | 1 - src/contrib/epee/demo/CMakeLists.txt | 49 - src/contrib/epee/demo/README.txt | 0 .../demo_http_server/demo_http_server.cpp | 217 - .../demo/demo_http_server/demo_http_server.h | 103 - .../epee/demo/demo_http_server/stdafx.cpp | 8 - .../epee/demo/demo_http_server/stdafx.h | 40 - .../epee/demo/demo_http_server/targetver.h | 13 - .../demo_levin_server/demo_levin_server.cpp | 200 - .../demo_levin_server/demo_levin_server.h | 76 - .../epee/demo/demo_levin_server/stdafx.cpp | 30 - .../epee/demo/demo_levin_server/stdafx.h | 40 - .../epee/demo/demo_levin_server/targetver.h | 13 - src/contrib/epee/demo/generate_gcc.sh | 4 - src/contrib/epee/demo/generate_vc_proj.bat | 7 - src/contrib/epee/demo/iface/transport_defs.h | 221 - src/contrib/epee/include/auto_val_init.h | 34 - src/contrib/epee/include/cache_helper.h | 260 - src/contrib/epee/include/console_handler.h | 526 - src/contrib/epee/include/copyable_atomic.h | 54 - src/contrib/epee/include/file_io_utils.h | 585 - .../epee/include/global_stream_operators.h | 35 - src/contrib/epee/include/gzip_encoding.h | 370 - src/contrib/epee/include/hmac-md5.h | 93 - src/contrib/epee/include/include_base_utils.h | 34 - src/contrib/epee/include/math_helper.h | 284 - src/contrib/epee/include/md5_l.h | 97 - src/contrib/epee/include/md5_l.inl | 563 - src/contrib/epee/include/md5global.h | 77 - src/contrib/epee/include/misc_helpers.h | 116 - src/contrib/epee/include/misc_language.h | 484 - src/contrib/epee/include/misc_log_ex.h | 1764 -- src/contrib/epee/include/misc_os_dependent.h | 167 - .../epee/include/net/abstract_tcp_server2.h | 322 - .../epee/include/net/abstract_tcp_server2.inl | 805 - src/contrib/epee/include/net/http_base.h | 186 - src/contrib/epee/include/net/http_client.h | 1043 - .../include/net/http_client_abstract_invoke.h | 98 - .../epee/include/net/http_client_base.h | 73 - .../include/net/http_client_via_api_helper.h | 177 - .../epee/include/net/http_protocol_handler.h | 214 - .../include/net/http_protocol_handler.inl | 696 - src/contrib/epee/include/net/http_server_cp.h | 48 - .../epee/include/net/http_server_cp2.h | 47 - .../include/net/http_server_handlers_map2.h | 354 - .../epee/include/net/http_server_impl_base.h | 112 - .../net/http_server_thread_per_connect.h | 48 - src/contrib/epee/include/net/levin_base.h | 131 - src/contrib/epee/include/net/levin_client.h | 89 - src/contrib/epee/include/net/levin_client.inl | 206 - .../epee/include/net/levin_client_async.h | 577 - .../epee/include/net/levin_client_async.inl | 0 src/contrib/epee/include/net/levin_helper.h | 137 - .../epee/include/net/levin_protocol_handler.h | 176 - .../net/levin_protocol_handler_async.h | 900 - .../epee/include/net/levin_server_cp.h | 47 - .../epee/include/net/levin_server_cp2.h | 49 - src/contrib/epee/include/net/local_ip.h | 72 - .../epee/include/net/multiprotocols_server.h | 47 - .../include/net/munin_connection_handler.h | 376 - .../epee/include/net/munin_node_server.h | 49 - src/contrib/epee/include/net/net_helper.h | 690 - .../epee/include/net/net_parse_helpers.h | 168 - src/contrib/epee/include/net/net_utils_base.h | 185 - .../epee/include/net/protocol_switcher.h | 121 - .../epee/include/net/rpc_method_name.h | 32 - src/contrib/epee/include/net/smtp.h | 181 - src/contrib/epee/include/net/smtp.inl | 1569 -- src/contrib/epee/include/net/smtp_helper.h | 88 - src/contrib/epee/include/os_defenitions.h | 49 - .../epee/include/print_fixed_point_helper.h | 46 - src/contrib/epee/include/profile_tools.h | 156 - src/contrib/epee/include/readwrite_lock.h | 225 - src/contrib/epee/include/reg_exp_definer.h | 89 - src/contrib/epee/include/reg_utils.h | 249 - .../serialization/keyvalue_helper_structs.h | 40 - .../include/serialization/keyvalue_helpers.h | 95 - .../serialization/keyvalue_hexemizer.h | 41 - .../serialization/keyvalue_serialization.h | 133 - .../keyvalue_serialization_boost_variant.h | 67 - .../keyvalue_serialization_overloads.h | 433 - .../include/serialization/serialize_base.h | 2 - src/contrib/epee/include/service_impl_base.h | 323 - src/contrib/epee/include/sha1.h | 51 - src/contrib/epee/include/sha1.inl | 179 - src/contrib/epee/include/singleton.h | 84 - src/contrib/epee/include/soci_helper.h | 142 - src/contrib/epee/include/static_helpers.h | 101 - src/contrib/epee/include/static_initializer.h | 84 - .../epee/include/storages/activity_notifier.h | 132 - .../epee/include/storages/crypted_storage.h | 62 - .../include/storages/gzipped_inmemstorage.h | 68 - .../include/storages/http_abstract_invoke.h | 145 - .../include/storages/levin_abstract_invoke2.h | 313 - .../include/storages/parserse_base_utils.h | 337 - .../epee/include/storages/portable_storage.h | 480 - .../include/storages/portable_storage_base.h | 163 - .../storages/portable_storage_from_bin.h | 281 - .../storages/portable_storage_from_json.h | 379 - .../portable_storage_template_helper.h | 123 - .../storages/portable_storage_to_bin.h | 212 - .../storages/portable_storage_to_json.h | 203 - .../portable_storage_val_converters.h | 181 - src/contrib/epee/include/string_coding.h | 318 - src/contrib/epee/include/string_tools.h | 808 - src/contrib/epee/include/sync_locked_object.h | 133 - src/contrib/epee/include/syncobj.h | 714 - src/contrib/epee/include/time_helper.h | 164 - src/contrib/epee/include/tiny_ini.h | 75 - .../epee/include/to_nonconst_iterator.h | 52 - src/contrib/epee/include/warnings.h | 42 - src/contrib/epee/include/zlib_helper.h | 150 - src/contrib/epee/tests/.gitignore | 1 - .../tests/data/storages/invalid_storage_1.bin | Bin 109577 -> 0 bytes .../tests/data/storages/invalid_storage_2.bin | Bin 20 -> 0 bytes .../tests/data/storages/invalid_storage_3.bin | 1 - .../tests/data/storages/invalid_storage_4.bin | Bin 18 -> 0 bytes .../tests/data/storages/valid_storage.bin | Bin 180345 -> 0 bytes src/contrib/epee/tests/generate_vc_proj.bat | 5 - src/contrib/epee/tests/src/CMakeLists.txt | 34 - src/contrib/epee/tests/src/misc/test_math.h | 82 - src/contrib/epee/tests/src/net/test_net.h | 403 - .../src/storages/portable_storages_test.h | 232 - .../epee/tests/src/storages/storage_tests.h | 142 - src/contrib/epee/tests/src/tests.cpp | 59 - src/contrib/ethereum/CMakeLists.txt | 10 - src/contrib/ethereum/libethash/CMakeLists.txt | 33 - .../ethereum/libethash/bit_manipulation.h | 82 - src/contrib/ethereum/libethash/builtins.h | 43 - src/contrib/ethereum/libethash/endianness.hpp | 98 - .../ethereum/libethash/ethash-internal.hpp | 69 - src/contrib/ethereum/libethash/ethash.cpp | 474 - .../ethereum/libethash/ethash/ethash.h | 99 - .../ethereum/libethash/ethash/ethash.hpp | 191 - .../ethereum/libethash/ethash/hash_types.h | 46 - .../ethereum/libethash/ethash/hash_types.hpp | 15 - .../ethereum/libethash/ethash/keccak.h | 49 - .../ethereum/libethash/ethash/keccak.hpp | 35 - .../ethereum/libethash/ethash/progpow.hpp | 47 - .../ethereum/libethash/ethash/version.h | 18 - src/contrib/ethereum/libethash/keccak.c | 123 - src/contrib/ethereum/libethash/keccakf1600.c | 255 - src/contrib/ethereum/libethash/keccakf800.c | 253 - src/contrib/ethereum/libethash/kiss99.hpp | 64 - src/contrib/ethereum/libethash/managed.cpp | 100 - src/contrib/ethereum/libethash/primes.c | 43 - src/contrib/ethereum/libethash/primes.h | 25 - src/contrib/ethereum/libethash/progpow.cpp | 360 - .../ethereum/libethash/support/attributes.h | 33 - src/contrib/miniupnp/.travis.yml | 49 - src/contrib/miniupnp/CODE_OF_CONDUCT | 1 - src/contrib/miniupnp/CONTRIBUTING | 11 - src/contrib/miniupnp/LICENSE | 26 - src/contrib/miniupnp/README | 61 - src/contrib/miniupnp/appveyor.yml | 21 - src/contrib/miniupnp/minissdpd/.gitignore | 9 - src/contrib/miniupnp/minissdpd/Changelog.txt | 158 - src/contrib/miniupnp/minissdpd/LICENSE | 26 - src/contrib/miniupnp/minissdpd/Makefile | 127 - src/contrib/miniupnp/minissdpd/README | 70 - src/contrib/miniupnp/minissdpd/README.fr | 49 - src/contrib/miniupnp/minissdpd/VERSION | 1 - src/contrib/miniupnp/minissdpd/asyncsendto.c | 348 - src/contrib/miniupnp/minissdpd/asyncsendto.h | 51 - src/contrib/miniupnp/minissdpd/codelength.h | 54 - src/contrib/miniupnp/minissdpd/config.h | 33 - src/contrib/miniupnp/minissdpd/daemonize.c | 129 - src/contrib/miniupnp/minissdpd/daemonize.h | 35 - src/contrib/miniupnp/minissdpd/getifaddr.c | 261 - src/contrib/miniupnp/minissdpd/getifaddr.h | 32 - src/contrib/miniupnp/minissdpd/getroute.c | 282 - src/contrib/miniupnp/minissdpd/getroute.h | 17 - src/contrib/miniupnp/minissdpd/ifacewatch.c | 345 - src/contrib/miniupnp/minissdpd/ifacewatch.h | 17 - src/contrib/miniupnp/minissdpd/listifaces.c | 120 - src/contrib/miniupnp/minissdpd/minissdpd.1 | 43 - src/contrib/miniupnp/minissdpd/minissdpd.c | 1646 -- .../minissdpd/minissdpd.init.d.script | 39 - .../miniupnp/minissdpd/minissdpdtypes.h | 28 - .../miniupnp/minissdpd/openssdpsocket.c | 233 - .../miniupnp/minissdpd/openssdpsocket.h | 33 - .../miniupnp/minissdpd/printresponse.c | 90 - .../miniupnp/minissdpd/printresponse.h | 12 - .../miniupnp/minissdpd/showminissdpdnotif.c | 85 - .../miniupnp/minissdpd/testcodelength.c | 31 - .../miniupnp/minissdpd/testminissdpd.c | 196 - .../miniupnp/minissdpd/testminissdpd.sh | 18 - .../miniupnp/minissdpd/testminissdpdnotif.sh | 26 - src/contrib/miniupnp/minissdpd/upnputils.c | 172 - src/contrib/miniupnp/minissdpd/upnputils.h | 53 - src/contrib/miniupnp/miniupnp.podspec | 54 - .../miniupnp/miniupnpc-async/.gitignore | 3 - .../miniupnp/miniupnpc-async/Changelog.txt | 4 - src/contrib/miniupnp/miniupnpc-async/Makefile | 115 - src/contrib/miniupnp/miniupnpc-async/README | 10 - src/contrib/miniupnp/miniupnpc-async/config.h | 5 - .../miniupnp/miniupnpc-async/declspec.h | 15 - .../miniupnp/miniupnpc-async/igd_desc_parse.c | 123 - .../miniupnp/miniupnpc-async/igd_desc_parse.h | 49 - .../miniupnpc-async/miniupnpc-async.c | 1044 - .../miniupnpc-async/miniupnpc-async.h | 118 - .../miniupnp/miniupnpc-async/minixml.c | 229 - .../miniupnp/miniupnpc-async/minixml.h | 37 - .../miniupnp/miniupnpc-async/parsessdpreply.c | 80 - .../miniupnp/miniupnpc-async/parsessdpreply.h | 32 - .../miniupnp/miniupnpc-async/testasync.c | 153 - .../miniupnp/miniupnpc-async/upnpreplyparse.c | 197 - .../miniupnp/miniupnpc-async/upnpreplyparse.h | 63 - .../miniupnp/miniupnpc-async/upnputils.c | 87 - .../miniupnp/miniupnpc-async/upnputils.h | 27 - .../miniupnp/miniupnpc-libevent/.gitignore | 3 - .../miniupnp/miniupnpc-libevent/Makefile | 69 - .../miniupnp/miniupnpc-libevent/README | 13 - .../miniupnp/miniupnpc-libevent/declspec.h | 15 - .../miniupnpc-libevent/igd_desc_parse.c | 123 - .../miniupnpc-libevent/igd_desc_parse.h | 49 - .../miniupnpc-libevent/miniupnpc-libevent.c | 1026 - .../miniupnpc-libevent/miniupnpc-libevent.h | 132 - .../miniupnp/miniupnpc-libevent/minixml.c | 229 - .../miniupnp/miniupnpc-libevent/minixml.h | 37 - .../miniupnpc-libevent/upnpc-libevent.c | 252 - .../miniupnpc-libevent/upnpreplyparse.c | 197 - .../miniupnpc-libevent/upnpreplyparse.h | 63 - src/contrib/miniupnp/miniupnpc/.gitignore | 37 - src/contrib/miniupnp/miniupnpc/CMakeLists.txt | 190 - src/contrib/miniupnp/miniupnpc/Changelog.txt | 711 - src/contrib/miniupnp/miniupnpc/LICENSE | 27 - src/contrib/miniupnp/miniupnpc/MANIFEST.in | 9 - src/contrib/miniupnp/miniupnpc/Makefile | 404 - src/contrib/miniupnp/miniupnpc/Makefile.mingw | 121 - src/contrib/miniupnp/miniupnpc/README | 63 - src/contrib/miniupnp/miniupnpc/VERSION | 1 - .../miniupnp/miniupnpc/apiversions.txt | 178 - src/contrib/miniupnp/miniupnpc/codelength.h | 54 - .../miniupnp/miniupnpc/connecthostport.c | 264 - .../miniupnp/miniupnpc/connecthostport.h | 20 - src/contrib/miniupnp/miniupnpc/external-ip.sh | 4 - .../miniupnp/miniupnpc/igd_desc_parse.c | 123 - .../miniupnp/miniupnpc/igd_desc_parse.h | 49 - .../miniupnp/miniupnpc/java/.gitignore | 2 - .../miniupnpc/java/JavaBridgeTest.java | 97 - .../miniupnp/miniupnpc/java/testjava.bat | 8 - .../miniupnp/miniupnpc/java/testjava.sh | 8 - src/contrib/miniupnp/miniupnpc/listdevices.c | 197 - .../miniupnp/miniupnpc/man3/miniupnpc.3 | 55 - .../miniupnp/miniupnpc/mingw32make.bat | 8 - .../miniupnp/miniupnpc/minihttptestserver.c | 675 - src/contrib/miniupnp/miniupnpc/minisoap.c | 124 - src/contrib/miniupnp/miniupnpc/minisoap.h | 17 - src/contrib/miniupnp/miniupnpc/minissdpc.c | 888 - src/contrib/miniupnp/miniupnpc/minissdpc.h | 58 - src/contrib/miniupnp/miniupnpc/miniupnpc.c | 727 - src/contrib/miniupnp/miniupnpc/miniupnpc.def | 45 - src/contrib/miniupnp/miniupnpc/miniupnpc.h | 153 - .../miniupnp/miniupnpc/miniupnpc_declspec.h | 21 - .../miniupnp/miniupnpc/miniupnpc_socketdef.h | 37 - .../miniupnp/miniupnpc/miniupnpcmodule.c | 703 - .../miniupnpc/miniupnpcstrings.h.cmake | 15 - .../miniupnp/miniupnpc/miniupnpcstrings.h.in | 23 - .../miniupnp/miniupnpc/miniupnpctypes.h | 19 - src/contrib/miniupnp/miniupnpc/miniwget.c | 662 - src/contrib/miniupnp/miniupnpc/miniwget.h | 27 - .../miniupnp/miniupnpc/miniwget_private.h | 15 - src/contrib/miniupnp/miniupnpc/minixml.c | 231 - src/contrib/miniupnp/miniupnpc/minixml.h | 37 - src/contrib/miniupnp/miniupnpc/minixmlvalid.c | 163 - .../miniupnp/miniupnpc/msvc/.gitignore | 8 - .../miniupnpc/msvc/genminiupnpcstrings.vbs | 53 - .../miniupnp/miniupnpc/msvc/miniupnpc.sln | 29 - .../miniupnp/miniupnpc/msvc/miniupnpc.vcproj | 283 - .../miniupnp/miniupnpc/msvc/miniupnpc.vcxproj | 117 - .../miniupnpc/msvc/miniupnpc.vcxproj.filters | 108 - .../miniupnpc/msvc/miniupnpc_vs2010.sln | 26 - .../miniupnpc/msvc/miniupnpc_vs2010.vcxproj | 118 - .../msvc/miniupnpc_vs2010.vcxproj.filters | 111 - .../miniupnpc/msvc/miniupnpc_vs2015.sln | 28 - .../miniupnpc/msvc/upnpc-static.vcproj | 195 - .../miniupnpc/msvc/upnpc-static.vcxproj | 103 - .../msvc/upnpc-static.vcxproj.filters | 22 - .../msvc/upnpc-static_vs2010.vcxproj | 101 - .../miniupnp/miniupnpc/portlistingparse.c | 172 - .../miniupnp/miniupnpc/portlistingparse.h | 65 - .../miniupnp/miniupnpc/pymoduletest.py | 88 - .../miniupnp/miniupnpc/pymoduletest3.py | 52 - src/contrib/miniupnp/miniupnpc/receivedata.c | 99 - src/contrib/miniupnp/miniupnpc/receivedata.h | 21 - src/contrib/miniupnp/miniupnpc/setup.py | 35 - .../miniupnp/miniupnpc/setupmingw32.py | 28 - .../testdesc/linksys_WAG200G_desc.values | 14 - .../testdesc/linksys_WAG200G_desc.xml | 110 - .../testdesc/new_LiveBox_desc.values | 20 - .../miniupnpc/testdesc/new_LiveBox_desc.xml | 90 - .../miniupnp/miniupnpc/testigddescparse.c | 187 - src/contrib/miniupnp/miniupnpc/testminiwget.c | 56 - .../miniupnp/miniupnpc/testminiwget.sh | 111 - src/contrib/miniupnp/miniupnpc/testminixml.c | 89 - .../miniupnp/miniupnpc/testportlistingparse.c | 151 - .../DeletePortMapping.namevalue | 3 - .../testreplyparse/DeletePortMapping.xml | 6 - .../GetExternalIPAddress.namevalue | 2 - .../testreplyparse/GetExternalIPAddress.xml | 2 - .../GetSpecificPortMappingEntryReq.namevalue | 3 - .../GetSpecificPortMappingEntryReq.xml | 3 - .../GetSpecificPortMappingEntryResp.namevalue | 5 - .../GetSpecificPortMappingEntryResp.xml | 2 - .../SetDefaultConnectionService.namevalue | 1 - .../SetDefaultConnectionService.xml | 1 - .../miniupnpc/testreplyparse/readme.txt | 7 - src/contrib/miniupnp/miniupnpc/testupnpigd.py | 88 - .../miniupnp/miniupnpc/testupnpreplyparse.c | 115 - .../miniupnp/miniupnpc/testupnpreplyparse.sh | 14 - .../miniupnpc/updateminiupnpcstrings.sh | 53 - src/contrib/miniupnp/miniupnpc/upnpc.c | 861 - src/contrib/miniupnp/miniupnpc/upnpcommands.c | 1241 -- src/contrib/miniupnp/miniupnpc/upnpcommands.h | 348 - src/contrib/miniupnp/miniupnpc/upnpdev.c | 23 - src/contrib/miniupnp/miniupnpc/upnpdev.h | 36 - src/contrib/miniupnp/miniupnpc/upnperrors.c | 107 - src/contrib/miniupnp/miniupnpc/upnperrors.h | 26 - .../miniupnp/miniupnpc/upnpreplyparse.c | 196 - .../miniupnp/miniupnpc/upnpreplyparse.h | 63 - .../miniupnpc/wingenminiupnpcstrings.c | 83 - src/contrib/miniupnp/miniupnpd/.gitignore | 26 - src/contrib/miniupnp/miniupnpd/Changelog.txt | 1270 -- src/contrib/miniupnp/miniupnpd/INSTALL | 195 - src/contrib/miniupnp/miniupnpd/LICENSE | 27 - src/contrib/miniupnp/miniupnpd/Makefile | 274 - src/contrib/miniupnp/miniupnpd/Makefile.linux | 343 - .../miniupnp/miniupnpd/Makefile.linux_nft | 231 - .../miniupnp/miniupnpd/Makefile.macosx | 132 - src/contrib/miniupnp/miniupnpd/Makefile.sunos | 202 - src/contrib/miniupnp/miniupnpd/README | 37 - src/contrib/miniupnp/miniupnpd/TODO | 24 - src/contrib/miniupnp/miniupnpd/VERSION | 1 - src/contrib/miniupnp/miniupnpd/asyncsendto.c | 348 - src/contrib/miniupnp/miniupnpd/asyncsendto.h | 51 - src/contrib/miniupnp/miniupnpd/bsd/Makefile | 20 - .../miniupnp/miniupnpd/bsd/getifstats.c | 77 - src/contrib/miniupnp/miniupnpd/bsd/getroute.c | 145 - .../miniupnp/miniupnpd/bsd/ifacewatcher.c | 125 - .../miniupnp/miniupnpd/bsd/testgetifstats.c | 32 - .../miniupnp/miniupnpd/bsd/testifacewatcher.c | 32 - src/contrib/miniupnp/miniupnpd/codelength.h | 54 - src/contrib/miniupnp/miniupnpd/commonrdr.h | 67 - src/contrib/miniupnp/miniupnpd/daemonize.c | 129 - src/contrib/miniupnp/miniupnpd/daemonize.h | 35 - src/contrib/miniupnp/miniupnpd/genconfig.sh | 634 - .../miniupnp/miniupnpd/getconnstatus.c | 74 - .../miniupnp/miniupnpd/getconnstatus.h | 30 - src/contrib/miniupnp/miniupnpd/getifaddr.c | 261 - src/contrib/miniupnp/miniupnpd/getifaddr.h | 32 - src/contrib/miniupnp/miniupnpd/getifstats.h | 25 - src/contrib/miniupnp/miniupnpd/getroute.h | 17 - src/contrib/miniupnp/miniupnpd/ifacewatcher.h | 48 - src/contrib/miniupnp/miniupnpd/ipf/Makefile | 16 - src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.c | 831 - src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.h | 55 - .../miniupnp/miniupnpd/ipf/testipfrdr.c | 74 - src/contrib/miniupnp/miniupnpd/ipfw/Makefile | 17 - src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.c | 107 - src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.h | 29 - src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.c | 548 - src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.h | 79 - .../miniupnp/miniupnpd/ipfw/testipfwrdr.c | 87 - .../miniupnp/miniupnpd/linux/getifstats.c | 135 - .../miniupnp/miniupnpd/linux/getroute.c | 197 - .../miniupnp/miniupnpd/linux/ifacewatcher.c | 350 - .../miniupnpd/linux/miniupnpd.init.d.script | 57 - src/contrib/miniupnp/miniupnpd/mac/Makefile | 14 - .../miniupnp/miniupnpd/mac/getifstats.c | 94 - .../mac/org.tuxfamily.miniupnpd.plist.before | 16 - .../miniupnp/miniupnpd/mac/testgetifstats.c | 29 - src/contrib/miniupnp/miniupnpd/macros.h | 47 - src/contrib/miniupnp/miniupnpd/minissdp.c | 1566 -- src/contrib/miniupnp/miniupnpd/minissdp.h | 58 - src/contrib/miniupnp/miniupnpd/miniupnpd.8 | 89 - src/contrib/miniupnp/miniupnpd/miniupnpd.c | 2741 --- src/contrib/miniupnp/miniupnpd/miniupnpd.conf | 152 - .../miniupnpd/miniupnpd.rc.once.d.script | 11 - src/contrib/miniupnp/miniupnpd/miniupnpdctl.c | 83 - .../miniupnp/miniupnpd/miniupnpdctl.txt | 18 - .../miniupnp/miniupnpd/miniupnpdpath.h | 49 - .../miniupnp/miniupnpd/miniupnpdtypes.h | 30 - src/contrib/miniupnp/miniupnpd/minixml.c | 231 - src/contrib/miniupnp/miniupnpd/minixml.h | 37 - src/contrib/miniupnp/miniupnpd/natpmp.c | 486 - src/contrib/miniupnp/miniupnpd/natpmp.h | 35 - .../miniupnp/miniupnpd/netfilter/Makefile | 79 - .../miniupnpd/netfilter/ip6tables_display.sh | 9 - .../miniupnpd/netfilter/ip6tables_flush.sh | 8 - .../miniupnpd/netfilter/ip6tables_init.sh | 22 - .../netfilter/ip6tables_removeall.sh | 16 - .../miniupnpd/netfilter/iptables_display.sh | 14 - .../netfilter/iptables_display_miniupnpd.sh | 10 - .../miniupnpd/netfilter/iptables_flush.sh | 10 - .../miniupnpd/netfilter/iptables_init.sh | 37 - .../miniupnpd/netfilter/iptables_removeall.sh | 46 - .../miniupnp/miniupnpd/netfilter/iptcrdr.c | 1948 -- .../miniupnp/miniupnpd/netfilter/iptcrdr.h | 65 - .../miniupnp/miniupnpd/netfilter/iptpinhole.c | 484 - .../miniupnp/miniupnpd/netfilter/iptpinhole.h | 43 - .../netfilter/miniupnpd_functions.sh | 64 - .../miniupnp/miniupnpd/netfilter/nfct_get.c | 258 - .../miniupnpd/netfilter/test_nfct_get.c | 50 - .../miniupnpd/netfilter/testiptcrdr.c | 91 - .../miniupnpd/netfilter/testiptcrdr_dscp.c | 73 - .../miniupnpd/netfilter/testiptcrdr_peer.c | 74 - .../miniupnpd/netfilter/testiptpinhole.c | 27 - .../miniupnpd/netfilter/tiny_nf_nat.h | 37 - .../miniupnp/miniupnpd/netfilter_nft/Makefile | 33 - .../miniupnpd/netfilter_nft/README.md | 21 - .../miniupnpd/netfilter_nft/nfct_get.c | 258 - .../miniupnpd/netfilter_nft/nftnlrdr.c | 499 - .../miniupnpd/netfilter_nft/nftnlrdr.h | 84 - .../miniupnpd/netfilter_nft/nftnlrdr_misc.c | 1145 -- .../miniupnpd/netfilter_nft/nftnlrdr_misc.h | 91 - .../netfilter_nft/scripts/nft_delete_chain.sh | 5 - .../netfilter_nft/scripts/nft_flush.sh | 5 - .../netfilter_nft/scripts/nft_init.sh | 47 - .../netfilter_nft/scripts/nft_removeall.sh | 5 - .../miniupnpd/netfilter_nft/test_nfct_get.c | 50 - .../miniupnpd/netfilter_nft/testnftnlrdr.c | 91 - .../miniupnpd/netfilter_nft/tiny_nf_nat.h | 37 - src/contrib/miniupnp/miniupnpd/options.c | 323 - src/contrib/miniupnp/miniupnpd/options.h | 98 - .../miniupnp/miniupnpd/pcp_msg_struct.h | 319 - src/contrib/miniupnp/miniupnpd/pcplearndscp.c | 298 - src/contrib/miniupnp/miniupnpd/pcplearndscp.h | 51 - src/contrib/miniupnp/miniupnpd/pcpserver.c | 1700 -- src/contrib/miniupnp/miniupnpd/pcpserver.h | 65 - src/contrib/miniupnp/miniupnpd/pf/Makefile | 25 - src/contrib/miniupnp/miniupnpd/pf/obsdrdr.c | 1160 -- src/contrib/miniupnp/miniupnpd/pf/obsdrdr.h | 70 - src/contrib/miniupnp/miniupnpd/pf/pfpinhole.c | 445 - src/contrib/miniupnp/miniupnpd/pf/pfpinhole.h | 41 - .../miniupnp/miniupnpd/pf/testobsdrdr.c | 147 - .../miniupnp/miniupnpd/pf/testpfpinhole.c | 105 - src/contrib/miniupnp/miniupnpd/portinuse.c | 409 - src/contrib/miniupnp/miniupnpd/portinuse.h | 23 - .../miniupnp/miniupnpd/solaris/getifstats.c | 97 - .../miniupnp/miniupnpd/testasyncsendto.c | 129 - .../miniupnp/miniupnpd/testgetifaddr.c | 54 - .../miniupnp/miniupnpd/testgetifaddr.sh | 29 - .../miniupnp/miniupnpd/testgetifstats.c | 41 - src/contrib/miniupnp/miniupnpd/testgetroute.c | 101 - src/contrib/miniupnp/miniupnpd/testminissdp.c | 82 - .../miniupnp/miniupnpd/testportinuse.c | 54 - .../miniupnp/miniupnpd/testssdppktgen.c | 100 - .../miniupnp/miniupnpd/testupnpdescgen.c | 267 - .../miniupnp/miniupnpd/testupnppermissions.c | 62 - .../miniupnp/miniupnpd/testupnppermissions.sh | 56 - src/contrib/miniupnp/miniupnpd/upnpdescgen.c | 1362 -- src/contrib/miniupnp/miniupnpd/upnpdescgen.h | 102 - .../miniupnp/miniupnpd/upnpdescstrings.h | 41 - src/contrib/miniupnp/miniupnpd/upnpevents.c | 670 - src/contrib/miniupnp/miniupnpd/upnpevents.h | 52 - .../miniupnp/miniupnpd/upnpglobalvars.c | 170 - .../miniupnp/miniupnpd/upnpglobalvars.h | 168 - src/contrib/miniupnp/miniupnpd/upnphttp.c | 1307 -- src/contrib/miniupnp/miniupnpd/upnphttp.h | 165 - .../miniupnp/miniupnpd/upnppermissions.c | 264 - .../miniupnp/miniupnpd/upnppermissions.h | 55 - src/contrib/miniupnp/miniupnpd/upnppinhole.c | 545 - src/contrib/miniupnp/miniupnpd/upnppinhole.h | 89 - src/contrib/miniupnp/miniupnpd/upnpredirect.c | 782 - src/contrib/miniupnp/miniupnpd/upnpredirect.h | 123 - .../miniupnp/miniupnpd/upnpreplyparse.c | 196 - .../miniupnp/miniupnpd/upnpreplyparse.h | 63 - src/contrib/miniupnp/miniupnpd/upnpsoap.c | 2322 --- src/contrib/miniupnp/miniupnpd/upnpsoap.h | 23 - src/contrib/miniupnp/miniupnpd/upnpurns.h | 30 - src/contrib/miniupnp/miniupnpd/upnputils.c | 238 - src/contrib/miniupnp/miniupnpd/upnputils.h | 74 - src/contrib/miniupnpc/CMakeLists.txt | 176 - src/contrib/miniupnpc/Changelog.txt | 585 - src/contrib/miniupnpc/LICENSE | 27 - src/contrib/miniupnpc/MANIFEST.in | 5 - src/contrib/miniupnpc/Makefile | 319 - src/contrib/miniupnpc/Makefile.mingw | 91 - src/contrib/miniupnpc/README | 66 - src/contrib/miniupnpc/VERSION | 1 - src/contrib/miniupnpc/apiversions.txt | 127 - src/contrib/miniupnpc/bsdqueue.h | 531 - src/contrib/miniupnpc/codelength.h | 31 - src/contrib/miniupnpc/connecthostport.c | 261 - src/contrib/miniupnpc/connecthostport.h | 18 - src/contrib/miniupnpc/declspec.h | 21 - src/contrib/miniupnpc/external-ip.sh | 4 - src/contrib/miniupnpc/igd_desc_parse.c | 125 - src/contrib/miniupnpc/igd_desc_parse.h | 48 - .../miniupnpc/java/JavaBridgeTest.java | 97 - src/contrib/miniupnpc/java/testjava.bat | 8 - src/contrib/miniupnpc/java/testjava.sh | 8 - src/contrib/miniupnpc/man3/miniupnpc.3 | 52 - src/contrib/miniupnpc/mingw32make.bat | 8 - src/contrib/miniupnpc/minihttptestserver.c | 486 - src/contrib/miniupnpc/minisoap.c | 121 - src/contrib/miniupnpc/minisoap.h | 15 - src/contrib/miniupnpc/minissdpc.c | 133 - src/contrib/miniupnpc/minissdpc.h | 15 - src/contrib/miniupnpc/miniupnpc.c | 1046 - src/contrib/miniupnpc/miniupnpc.def | 43 - src/contrib/miniupnpc/miniupnpc.h | 130 - src/contrib/miniupnpc/miniupnpcmodule.c | 545 - .../miniupnpc/miniupnpcstrings.h.cmake | 7 - src/contrib/miniupnpc/miniupnpcstrings.h.in | 15 - src/contrib/miniupnpc/miniupnpctypes.h | 19 - src/contrib/miniupnpc/miniwget.c | 575 - src/contrib/miniupnpc/miniwget.h | 30 - src/contrib/miniupnpc/minixml.c | 229 - src/contrib/miniupnpc/minixml.h | 37 - src/contrib/miniupnpc/minixmlvalid.c | 158 - src/contrib/miniupnpc/msvc/miniupnpc.sln | 29 - src/contrib/miniupnpc/msvc/miniupnpc.vcproj | 271 - .../miniupnpc/msvc/upnpc-static.vcproj | 195 - src/contrib/miniupnpc/portlistingparse.c | 159 - src/contrib/miniupnpc/portlistingparse.h | 71 - src/contrib/miniupnpc/pymoduletest.py | 52 - src/contrib/miniupnpc/receivedata.c | 109 - src/contrib/miniupnpc/receivedata.h | 19 - src/contrib/miniupnpc/setup.py | 18 - src/contrib/miniupnpc/setupmingw32.py | 18 - src/contrib/miniupnpc/testigddescparse.c | 64 - src/contrib/miniupnpc/testminiwget.c | 53 - src/contrib/miniupnpc/testminiwget.sh | 96 - src/contrib/miniupnpc/testminixml.c | 87 - .../DeletePortMapping.namevalue | 3 - .../testreplyparse/DeletePortMapping.xml | 6 - .../GetExternalIPAddress.namevalue | 2 - .../testreplyparse/GetExternalIPAddress.xml | 2 - .../GetSpecificPortMappingEntryReq.namevalue | 3 - .../GetSpecificPortMappingEntryReq.xml | 3 - .../GetSpecificPortMappingEntryResp.namevalue | 5 - .../GetSpecificPortMappingEntryResp.xml | 2 - .../SetDefaultConnectionService.namevalue | 1 - .../SetDefaultConnectionService.xml | 1 - .../miniupnpc/testreplyparse/readme.txt | 7 - src/contrib/miniupnpc/testupnpigd.py | 84 - src/contrib/miniupnpc/testupnpreplyparse.c | 96 - src/contrib/miniupnpc/testupnpreplyparse.sh | 14 - .../miniupnpc/updateminiupnpcstrings.sh | 53 - src/contrib/miniupnpc/upnpc.c | 720 - src/contrib/miniupnpc/upnpcommands.c | 1098 - src/contrib/miniupnpc/upnpcommands.h | 293 - src/contrib/miniupnpc/upnperrors.c | 104 - src/contrib/miniupnpc/upnperrors.h | 26 - src/contrib/miniupnpc/upnpreplyparse.c | 183 - src/contrib/miniupnpc/upnpreplyparse.h | 69 - .../miniupnpc/wingenminiupnpcstrings.c | 82 - src/contrib/zlib/CMakeLists.txt | 249 - src/contrib/zlib/ChangeLog | 1515 -- src/contrib/zlib/FAQ | 368 - src/contrib/zlib/INDEX | 68 - src/contrib/zlib/Makefile | 5 - src/contrib/zlib/Makefile.in | 410 - src/contrib/zlib/README | 115 - src/contrib/zlib/adler32.c | 186 - src/contrib/zlib/amiga/Makefile.pup | 69 - src/contrib/zlib/amiga/Makefile.sas | 68 - src/contrib/zlib/as400/bndsrc | 215 - src/contrib/zlib/as400/compile.clp | 110 - src/contrib/zlib/as400/readme.txt | 115 - src/contrib/zlib/as400/zlib.inc | 451 - src/contrib/zlib/compress.c | 86 - src/contrib/zlib/configure | 921 - src/contrib/zlib/contrib/README.contrib | 78 - src/contrib/zlib/contrib/ada/buffer_demo.adb | 106 - src/contrib/zlib/contrib/ada/mtest.adb | 156 - src/contrib/zlib/contrib/ada/read.adb | 156 - src/contrib/zlib/contrib/ada/readme.txt | 65 - src/contrib/zlib/contrib/ada/test.adb | 463 - src/contrib/zlib/contrib/ada/zlib-streams.adb | 225 - src/contrib/zlib/contrib/ada/zlib-streams.ads | 114 - src/contrib/zlib/contrib/ada/zlib-thin.adb | 141 - src/contrib/zlib/contrib/ada/zlib-thin.ads | 450 - src/contrib/zlib/contrib/ada/zlib.adb | 701 - src/contrib/zlib/contrib/ada/zlib.ads | 328 - src/contrib/zlib/contrib/ada/zlib.gpr | 20 - src/contrib/zlib/contrib/amd64/amd64-match.S | 452 - src/contrib/zlib/contrib/asm686/README.686 | 51 - src/contrib/zlib/contrib/asm686/match.S | 357 - src/contrib/zlib/contrib/blast/Makefile | 8 - src/contrib/zlib/contrib/blast/README | 4 - src/contrib/zlib/contrib/blast/blast.c | 466 - src/contrib/zlib/contrib/blast/blast.h | 83 - src/contrib/zlib/contrib/blast/test.pk | Bin 8 -> 0 bytes src/contrib/zlib/contrib/blast/test.txt | 1 - src/contrib/zlib/contrib/delphi/ZLib.pas | 557 - src/contrib/zlib/contrib/delphi/ZLibConst.pas | 11 - src/contrib/zlib/contrib/delphi/readme.txt | 76 - src/contrib/zlib/contrib/delphi/zlibd32.mak | 99 - .../zlib/contrib/dotzlib/DotZLib.build | 33 - src/contrib/zlib/contrib/dotzlib/DotZLib.chm | Bin 72726 -> 0 bytes src/contrib/zlib/contrib/dotzlib/DotZLib.sln | 21 - .../contrib/dotzlib/DotZLib/AssemblyInfo.cs | 58 - .../contrib/dotzlib/DotZLib/ChecksumImpl.cs | 202 - .../contrib/dotzlib/DotZLib/CircularBuffer.cs | 83 - .../zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 198 - .../zlib/contrib/dotzlib/DotZLib/Deflater.cs | 106 - .../zlib/contrib/dotzlib/DotZLib/DotZLib.cs | 288 - .../contrib/dotzlib/DotZLib/DotZLib.csproj | 141 - .../contrib/dotzlib/DotZLib/GZipStream.cs | 301 - .../zlib/contrib/dotzlib/DotZLib/Inflater.cs | 105 - .../zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 274 - .../zlib/contrib/dotzlib/LICENSE_1_0.txt | 23 - src/contrib/zlib/contrib/dotzlib/readme.txt | 58 - .../zlib/contrib/gcc_gvmat64/gvmat64.S | 574 - src/contrib/zlib/contrib/infback9/README | 1 - src/contrib/zlib/contrib/infback9/infback9.c | 615 - src/contrib/zlib/contrib/infback9/infback9.h | 37 - src/contrib/zlib/contrib/infback9/inffix9.h | 107 - src/contrib/zlib/contrib/infback9/inflate9.h | 47 - src/contrib/zlib/contrib/infback9/inftree9.c | 324 - src/contrib/zlib/contrib/infback9/inftree9.h | 61 - src/contrib/zlib/contrib/inflate86/inffas86.c | 1157 -- src/contrib/zlib/contrib/inflate86/inffast.S | 1368 -- src/contrib/zlib/contrib/iostream/test.cpp | 24 - .../zlib/contrib/iostream/zfstream.cpp | 329 - src/contrib/zlib/contrib/iostream/zfstream.h | 128 - src/contrib/zlib/contrib/iostream2/zstream.h | 307 - .../zlib/contrib/iostream2/zstream_test.cpp | 25 - src/contrib/zlib/contrib/iostream3/README | 35 - src/contrib/zlib/contrib/iostream3/TODO | 17 - src/contrib/zlib/contrib/iostream3/test.cc | 50 - .../zlib/contrib/iostream3/zfstream.cc | 479 - src/contrib/zlib/contrib/iostream3/zfstream.h | 466 - src/contrib/zlib/contrib/masmx64/bld_ml64.bat | 2 - src/contrib/zlib/contrib/masmx64/gvmat64.asm | 553 - src/contrib/zlib/contrib/masmx64/inffas8664.c | 186 - .../zlib/contrib/masmx64/inffasx64.asm | 396 - src/contrib/zlib/contrib/masmx64/readme.txt | 31 - src/contrib/zlib/contrib/masmx86/bld_ml32.bat | 2 - src/contrib/zlib/contrib/masmx86/inffas32.asm | 1080 - src/contrib/zlib/contrib/masmx86/match686.asm | 479 - src/contrib/zlib/contrib/masmx86/readme.txt | 27 - src/contrib/zlib/contrib/minizip/Makefile | 25 - src/contrib/zlib/contrib/minizip/Makefile.am | 45 - .../contrib/minizip/MiniZip64_Changes.txt | 6 - .../zlib/contrib/minizip/MiniZip64_info.txt | 74 - src/contrib/zlib/contrib/minizip/configure.ac | 32 - src/contrib/zlib/contrib/minizip/crypt.h | 131 - src/contrib/zlib/contrib/minizip/ioapi.c | 247 - src/contrib/zlib/contrib/minizip/ioapi.h | 208 - src/contrib/zlib/contrib/minizip/iowin32.c | 462 - src/contrib/zlib/contrib/minizip/iowin32.h | 28 - src/contrib/zlib/contrib/minizip/make_vms.com | 25 - src/contrib/zlib/contrib/minizip/miniunz.c | 660 - src/contrib/zlib/contrib/minizip/miniunzip.1 | 63 - src/contrib/zlib/contrib/minizip/minizip.1 | 46 - src/contrib/zlib/contrib/minizip/minizip.c | 520 - .../zlib/contrib/minizip/minizip.pc.in | 12 - src/contrib/zlib/contrib/minizip/mztools.c | 291 - src/contrib/zlib/contrib/minizip/mztools.h | 37 - src/contrib/zlib/contrib/minizip/unzip.c | 2125 -- src/contrib/zlib/contrib/minizip/unzip.h | 437 - src/contrib/zlib/contrib/minizip/zip.c | 2007 -- src/contrib/zlib/contrib/minizip/zip.h | 362 - src/contrib/zlib/contrib/pascal/example.pas | 599 - src/contrib/zlib/contrib/pascal/readme.txt | 76 - src/contrib/zlib/contrib/pascal/zlibd32.mak | 99 - src/contrib/zlib/contrib/pascal/zlibpas.pas | 276 - src/contrib/zlib/contrib/puff/Makefile | 42 - src/contrib/zlib/contrib/puff/README | 63 - src/contrib/zlib/contrib/puff/puff.c | 840 - src/contrib/zlib/contrib/puff/puff.h | 35 - src/contrib/zlib/contrib/puff/pufftest.c | 165 - src/contrib/zlib/contrib/puff/zeros.raw | Bin 2517 -> 0 bytes src/contrib/zlib/contrib/testzlib/testzlib.c | 275 - .../zlib/contrib/testzlib/testzlib.txt | 10 - src/contrib/zlib/contrib/untgz/Makefile | 14 - src/contrib/zlib/contrib/untgz/Makefile.msc | 17 - src/contrib/zlib/contrib/untgz/untgz.c | 674 - src/contrib/zlib/contrib/vstudio/readme.txt | 78 - .../zlib/contrib/vstudio/vc10/miniunz.vcxproj | 310 - .../vstudio/vc10/miniunz.vcxproj.filters | 22 - .../zlib/contrib/vstudio/vc10/minizip.vcxproj | 307 - .../vstudio/vc10/minizip.vcxproj.filters | 22 - .../contrib/vstudio/vc10/testzlib.vcxproj | 420 - .../vstudio/vc10/testzlib.vcxproj.filters | 58 - .../contrib/vstudio/vc10/testzlibdll.vcxproj | 310 - .../vstudio/vc10/testzlibdll.vcxproj.filters | 22 - src/contrib/zlib/contrib/vstudio/vc10/zlib.rc | 32 - .../contrib/vstudio/vc10/zlibstat.vcxproj | 473 - .../vstudio/vc10/zlibstat.vcxproj.filters | 77 - .../zlib/contrib/vstudio/vc10/zlibvc.def | 153 - .../zlib/contrib/vstudio/vc10/zlibvc.sln | 135 - .../zlib/contrib/vstudio/vc10/zlibvc.vcxproj | 657 - .../vstudio/vc10/zlibvc.vcxproj.filters | 118 - .../zlib/contrib/vstudio/vc11/miniunz.vcxproj | 314 - .../zlib/contrib/vstudio/vc11/minizip.vcxproj | 311 - .../contrib/vstudio/vc11/testzlib.vcxproj | 426 - .../contrib/vstudio/vc11/testzlibdll.vcxproj | 314 - src/contrib/zlib/contrib/vstudio/vc11/zlib.rc | 32 - .../contrib/vstudio/vc11/zlibstat.vcxproj | 464 - .../zlib/contrib/vstudio/vc11/zlibvc.def | 153 - .../zlib/contrib/vstudio/vc11/zlibvc.sln | 117 - .../zlib/contrib/vstudio/vc11/zlibvc.vcxproj | 688 - .../zlib/contrib/vstudio/vc12/miniunz.vcxproj | 316 - .../zlib/contrib/vstudio/vc12/minizip.vcxproj | 313 - .../contrib/vstudio/vc12/testzlib.vcxproj | 430 - .../contrib/vstudio/vc12/testzlibdll.vcxproj | 316 - src/contrib/zlib/contrib/vstudio/vc12/zlib.rc | 32 - .../contrib/vstudio/vc12/zlibstat.vcxproj | 467 - .../zlib/contrib/vstudio/vc12/zlibvc.def | 153 - .../zlib/contrib/vstudio/vc12/zlibvc.sln | 119 - .../zlib/contrib/vstudio/vc12/zlibvc.vcxproj | 692 - .../zlib/contrib/vstudio/vc14/miniunz.vcxproj | 316 - .../zlib/contrib/vstudio/vc14/minizip.vcxproj | 313 - .../contrib/vstudio/vc14/testzlib.vcxproj | 430 - .../contrib/vstudio/vc14/testzlibdll.vcxproj | 316 - src/contrib/zlib/contrib/vstudio/vc14/zlib.rc | 32 - .../contrib/vstudio/vc14/zlibstat.vcxproj | 467 - .../zlib/contrib/vstudio/vc14/zlibvc.def | 153 - .../zlib/contrib/vstudio/vc14/zlibvc.sln | 119 - .../zlib/contrib/vstudio/vc14/zlibvc.vcxproj | 692 - .../zlib/contrib/vstudio/vc9/miniunz.vcproj | 565 - .../zlib/contrib/vstudio/vc9/minizip.vcproj | 562 - .../zlib/contrib/vstudio/vc9/testzlib.vcproj | 852 - .../contrib/vstudio/vc9/testzlibdll.vcproj | 565 - src/contrib/zlib/contrib/vstudio/vc9/zlib.rc | 32 - .../zlib/contrib/vstudio/vc9/zlibstat.vcproj | 835 - .../zlib/contrib/vstudio/vc9/zlibvc.def | 153 - .../zlib/contrib/vstudio/vc9/zlibvc.sln | 144 - .../zlib/contrib/vstudio/vc9/zlibvc.vcproj | 1156 -- src/contrib/zlib/crc32.c | 442 - src/contrib/zlib/crc32.h | 441 - src/contrib/zlib/deflate.c | 2163 -- src/contrib/zlib/deflate.h | 349 - src/contrib/zlib/doc/algorithm.txt | 209 - src/contrib/zlib/doc/rfc1950.txt | 619 - src/contrib/zlib/doc/rfc1951.txt | 955 - src/contrib/zlib/doc/rfc1952.txt | 675 - src/contrib/zlib/doc/txtvsbin.txt | 107 - src/contrib/zlib/examples/README.examples | 49 - src/contrib/zlib/examples/enough.c | 572 - src/contrib/zlib/examples/fitblk.c | 233 - src/contrib/zlib/examples/gun.c | 702 - src/contrib/zlib/examples/gzappend.c | 504 - src/contrib/zlib/examples/gzjoin.c | 449 - src/contrib/zlib/examples/gzlog.c | 1059 - src/contrib/zlib/examples/gzlog.h | 91 - src/contrib/zlib/examples/zlib_how.html | 545 - src/contrib/zlib/examples/zpipe.c | 205 - src/contrib/zlib/examples/zran.c | 409 - src/contrib/zlib/gzclose.c | 25 - src/contrib/zlib/gzguts.h | 218 - src/contrib/zlib/gzlib.c | 637 - src/contrib/zlib/gzread.c | 654 - src/contrib/zlib/gzwrite.c | 665 - src/contrib/zlib/infback.c | 640 - src/contrib/zlib/inffast.c | 323 - src/contrib/zlib/inffast.h | 11 - src/contrib/zlib/inffixed.h | 94 - src/contrib/zlib/inflate.c | 1561 -- src/contrib/zlib/inflate.h | 125 - src/contrib/zlib/inftrees.c | 304 - src/contrib/zlib/inftrees.h | 62 - src/contrib/zlib/make_vms.com | 867 - src/contrib/zlib/msdos/Makefile.bor | 115 - src/contrib/zlib/msdos/Makefile.dj2 | 104 - src/contrib/zlib/msdos/Makefile.emx | 69 - src/contrib/zlib/msdos/Makefile.msc | 112 - src/contrib/zlib/msdos/Makefile.tc | 100 - src/contrib/zlib/nintendods/Makefile | 126 - src/contrib/zlib/nintendods/README | 5 - src/contrib/zlib/old/Makefile.emx | 69 - src/contrib/zlib/old/Makefile.riscos | 151 - src/contrib/zlib/old/README | 3 - src/contrib/zlib/old/descrip.mms | 48 - src/contrib/zlib/old/os2/Makefile.os2 | 136 - src/contrib/zlib/old/os2/zlib.def | 51 - src/contrib/zlib/old/visual-basic.txt | 160 - src/contrib/zlib/os400/README400 | 48 - src/contrib/zlib/os400/bndsrc | 119 - src/contrib/zlib/os400/make.sh | 366 - src/contrib/zlib/os400/zlib.inc | 527 - src/contrib/zlib/qnx/package.qpg | 141 - src/contrib/zlib/test/example.c | 602 - src/contrib/zlib/test/infcover.c | 671 - src/contrib/zlib/test/minigzip.c | 651 - src/contrib/zlib/treebuild.xml | 116 - src/contrib/zlib/trees.c | 1203 -- src/contrib/zlib/trees.h | 128 - src/contrib/zlib/uncompr.c | 93 - src/contrib/zlib/watcom/watcom_f.mak | 43 - src/contrib/zlib/watcom/watcom_l.mak | 43 - src/contrib/zlib/win32/DLL_FAQ.txt | 397 - src/contrib/zlib/win32/Makefile.bor | 110 - src/contrib/zlib/win32/Makefile.gcc | 182 - src/contrib/zlib/win32/Makefile.msc | 163 - src/contrib/zlib/win32/README-WIN32.txt | 103 - src/contrib/zlib/win32/VisualC.txt | 3 - src/contrib/zlib/win32/zlib.def | 94 - src/contrib/zlib/win32/zlib1.rc | 40 - src/contrib/zlib/zconf.h.cmakein | 536 - src/contrib/zlib/zconf.h.in | 534 - src/contrib/zlib/zconf.h.included | 511 - src/contrib/zlib/zlib.3 | 149 - src/contrib/zlib/zlib.3.pdf | Bin 19318 -> 0 bytes src/contrib/zlib/zlib.h | 1912 -- src/contrib/zlib/zlib.map | 94 - src/contrib/zlib/zlib.pc.cmakein | 13 - src/contrib/zlib/zlib.pc.in | 13 - src/contrib/zlib/zlib2ansi | 152 - src/contrib/zlib/zutil.c | 325 - src/contrib/zlib/zutil.h | 271 - src/crypto/RIPEMD160.c | 287 - src/crypto/RIPEMD160.h | 150 - src/crypto/RIPEMD160_helper.cpp | 67 - src/crypto/RIPEMD160_helper.h | 27 - src/crypto/bitcoin/byteswap.h | 59 - src/crypto/bitcoin/common.h | 110 - src/crypto/bitcoin/cpuid.h | 24 - src/crypto/bitcoin/endian.h | 241 - src/crypto/bitcoin/sha256.cpp | 719 - src/crypto/bitcoin/sha256.h | 41 - src/crypto/bitcoin/sha256_helper.h | 27 - src/crypto/blake2-impl.h | 160 - src/crypto/blake2.h | 200 - src/crypto/blake2b-ref.c | 379 - src/crypto/chacha8.c | 170 - src/crypto/chacha8.h | 114 - src/crypto/chacha8_stream.c | 115 - src/crypto/chacha8_stream.h | 289 - src/crypto/crypto-ops-data.c | 846 - src/crypto/crypto-ops.c | 4312 ---- src/crypto/crypto-ops.h | 145 - src/crypto/crypto-sugar.cpp | 26 - src/crypto/crypto-sugar.h | 1067 - src/crypto/crypto.cpp | 428 - src/crypto/crypto.h | 302 - src/crypto/ecrypt-config.h | 272 - src/crypto/ecrypt-machine.h | 46 - src/crypto/ecrypt-portable.h | 303 - src/crypto/ecrypt-sync.h | 258 - src/crypto/generic-ops.h | 60 - src/crypto/hash-ops.h | 63 - src/crypto/hash.c | 31 - src/crypto/hash.h | 56 - src/crypto/initializer.h | 32 - src/crypto/keccak.c | 112 - src/crypto/keccak.h | 26 - src/crypto/random.c | 187 - src/crypto/random.h | 37 - src/crypto/range_proofs.cpp | 12 - src/crypto/range_proofs.h | 823 - src/crypto/tree-hash.c | 40 - src/currency_core/account.cpp | 316 - src/currency_core/account.h | 117 - .../account_boost_serialization.h | 26 - src/currency_core/alias_helper.h | 73 - src/currency_core/basic_api_response_codes.h | 12 - src/currency_core/basic_kv_structs.h | 27 - src/currency_core/basic_pow_helpers.cpp | 102 - src/currency_core/basic_pow_helpers.h | 46 - src/currency_core/bc_attachments_helpers.h | 128 - .../bc_attachments_helpers_basic.h | 28 - .../bc_attachments_service_manager.cpp | 91 - .../bc_attachments_service_manager.h | 51 - src/currency_core/bc_block_datetime_service.h | 7 - src/currency_core/bc_escrow_service.h | 146 - src/currency_core/bc_offers_serialization.h | 83 - src/currency_core/bc_offers_service.cpp | 496 - src/currency_core/bc_offers_service.h | 250 - src/currency_core/bc_offers_service_basic.h | 12 - src/currency_core/bc_payments_id_service.h | 10 - src/currency_core/block_flags.h | 8 - src/currency_core/blockchain_storage.cpp | 6881 ------- src/currency_core/blockchain_storage.h | 889 - src/currency_core/blockchain_storage_basic.h | 159 - .../blockchain_storage_boost_serialization.h | 47 - src/currency_core/checkpoints.cpp | 94 - src/currency_core/checkpoints.h | 28 - src/currency_core/checkpoints_create.h | 33 - src/currency_core/connection_context.h | 76 - src/currency_core/core_runtime_config.h | 65 - src/currency_core/core_tools.h | 58 - src/currency_core/currency_basic.h | 819 - .../currency_boost_serialization.h | 309 - src/currency_core/currency_config.h | 254 - src/currency_core/currency_core.cpp | 706 - src/currency_core/currency_core.h | 158 - src/currency_core/currency_format_utils.cpp | 3285 --- src/currency_core/currency_format_utils.h | 765 - .../currency_format_utils_abstract.h | 257 - .../currency_format_utils_blocks.cpp | 68 - .../currency_format_utils_blocks.h | 25 - .../currency_format_utils_transactions.cpp | 275 - .../currency_format_utils_transactions.h | 133 - src/currency_core/currency_stat_info.h | 72 - src/currency_core/difficulty.cpp | 259 - src/currency_core/difficulty.h | 26 - src/currency_core/dispatch_core_events.h | 48 - .../etc_custom_serialization.cpp | 25 - src/currency_core/etc_custom_serialization.h | 17 - src/currency_core/genesis.cpp | 20 - src/currency_core/genesis.h | 32 - src/currency_core/genesis_acc.cpp | 60 - src/currency_core/genesis_acc.h | 48 - src/currency_core/miner.cpp | 375 - src/currency_core/miner.h | 127 - src/currency_core/miner_common.h | 8 - src/currency_core/offers_service_basics.h | 193 - src/currency_core/offers_services_helpers.cpp | 299 - src/currency_core/offers_services_helpers.h | 234 - src/currency_core/scratchpad_helper.cpp | 76 - src/currency_core/scratchpad_helper.h | 53 - src/currency_core/tx_pool.cpp | 1399 -- src/currency_core/tx_pool.h | 221 - src/currency_core/tx_semantic_validation.cpp | 100 - src/currency_core/tx_semantic_validation.h | 16 - src/currency_core/verification_context.h | 35 - src/currency_protocol/blobdatatype.h | 10 - .../currency_protocol_defs.h | 179 - .../currency_protocol_defs_print.h | 88 - .../currency_protocol_handler.h | 150 - .../currency_protocol_handler.inl | 953 - .../currency_protocol_handler_common.h | 55 - src/main.cc | 365 - .../maintainers_info_boost_serialization.h | 40 - src/p2p/net_node.h | 310 - src/p2p/net_node.inl | 1497 -- src/p2p/net_node_common.h | 84 - src/p2p/net_peerlist.h | 395 - src/p2p/net_peerlist_boost_serialization.h | 30 - src/p2p/p2p_networks.h | 21 - src/p2p/p2p_protocol_defs.h | 473 - src/rpc/core_rpc_server.cpp | 1370 -- src/rpc/core_rpc_server.h | 197 - src/rpc/core_rpc_server_commands_defs.h | 1613 -- src/rpc/core_rpc_server_error_codes.h | 23 - src/rpc/mining_protocol_defs.h | 153 - src/serialization/binary_archive.h | 175 - src/serialization/binary_utils.h | 29 - src/serialization/crypto.h | 63 - src/serialization/debug_archive.h | 29 - src/serialization/json_archive.h | 154 - src/serialization/json_utils.h | 20 - src/serialization/multiprecision.h | 34 - src/serialization/serialization.h | 220 - src/serialization/serialize_basic_types.h | 24 - src/serialization/stl_containers.h | 268 - src/serialization/string.h | 36 - src/serialization/variant.h | 111 - 1154 files changed, 291257 deletions(-) delete mode 100644 src/common/atomics_boost_serialization.h delete mode 100644 src/common/base58.cpp delete mode 100644 src/common/base58.h delete mode 100644 src/common/boost_serialization_helper.h delete mode 100644 src/common/callstack_helper.cpp delete mode 100644 src/common/callstack_helper.h delete mode 100644 src/common/command_line.cpp delete mode 100644 src/common/command_line.h delete mode 100644 src/common/config_encrypt_helper.h delete mode 100644 src/common/crypto_boost_serialization.h delete mode 100644 src/common/crypto_stream_operators.cpp delete mode 100644 src/common/crypto_stream_operators.h delete mode 100644 src/common/db_abstract_accessor.h delete mode 100644 src/common/db_backend_base.h delete mode 100644 src/common/db_backend_leveldb.cpp delete mode 100644 src/common/db_backend_leveldb.h delete mode 100644 src/common/db_backend_lmdb.cpp delete mode 100644 src/common/db_backend_lmdb.h delete mode 100644 src/common/db_backend_mdbx.cpp delete mode 100644 src/common/db_backend_mdbx.h delete mode 100644 src/common/db_backend_selector.cpp delete mode 100644 src/common/db_backend_selector.h delete mode 100644 src/common/difficulty_boost_serialization.h delete mode 100644 src/common/encryption_filter.cpp delete mode 100644 src/common/encryption_filter.h delete mode 100644 src/common/error_codes.h delete mode 100644 src/common/general_purpose_commands_defs.h delete mode 100644 src/common/int-util.h delete mode 100644 src/common/make_hashable.h delete mode 100644 src/common/median_db_cache.h delete mode 100644 src/common/miniupnp_helper.h delete mode 100644 src/common/mnemonic-encoding.cpp delete mode 100644 src/common/mnemonic-encoding.h delete mode 100644 src/common/ntp.cpp delete mode 100644 src/common/ntp.h delete mode 100644 src/common/pod-class.h delete mode 100644 src/common/pod_array_file_container.h delete mode 100644 src/common/pre_download.h delete mode 100644 src/common/unordered_containers_boost_serialization.h delete mode 100644 src/common/util.cpp delete mode 100644 src/common/util.h delete mode 100644 src/common/varint.h delete mode 100644 src/contrib/db/CMakeLists.txt delete mode 100644 src/contrib/db/liblmdb/.gitignore delete mode 100644 src/contrib/db/liblmdb/CHANGES delete mode 100644 src/contrib/db/liblmdb/CMakeLists.txt delete mode 100644 src/contrib/db/liblmdb/COPYRIGHT delete mode 100644 src/contrib/db/liblmdb/Doxyfile delete mode 100644 src/contrib/db/liblmdb/LICENSE delete mode 100644 src/contrib/db/liblmdb/Makefile delete mode 100644 src/contrib/db/liblmdb/intro.doc delete mode 100644 src/contrib/db/liblmdb/lmdb.h delete mode 100644 src/contrib/db/liblmdb/mdb.c delete mode 100644 src/contrib/db/liblmdb/mdb_copy.1 delete mode 100644 src/contrib/db/liblmdb/mdb_copy.c delete mode 100644 src/contrib/db/liblmdb/mdb_dump.1 delete mode 100644 src/contrib/db/liblmdb/mdb_dump.c delete mode 100644 src/contrib/db/liblmdb/mdb_load.1 delete mode 100644 src/contrib/db/liblmdb/mdb_load.c delete mode 100644 src/contrib/db/liblmdb/mdb_stat.1 delete mode 100644 src/contrib/db/liblmdb/mdb_stat.c delete mode 100644 src/contrib/db/liblmdb/midl.c delete mode 100644 src/contrib/db/liblmdb/midl.h delete mode 100644 src/contrib/db/liblmdb/mtest.c delete mode 100644 src/contrib/db/liblmdb/mtest2.c delete mode 100644 src/contrib/db/liblmdb/mtest3.c delete mode 100644 src/contrib/db/liblmdb/mtest4.c delete mode 100644 src/contrib/db/liblmdb/mtest5.c delete mode 100644 src/contrib/db/liblmdb/mtest6.c delete mode 100644 src/contrib/db/liblmdb/sample-bdb.txt delete mode 100644 src/contrib/db/liblmdb/sample-mdb.txt delete mode 100644 src/contrib/db/liblmdb/tooltag delete mode 100644 src/contrib/db/libmdbx/.circleci/config.yml delete mode 100644 src/contrib/db/libmdbx/.clang-format delete mode 100644 src/contrib/db/libmdbx/.gitignore delete mode 100644 src/contrib/db/libmdbx/.travis.yml delete mode 100644 src/contrib/db/libmdbx/AUTHORS delete mode 100644 src/contrib/db/libmdbx/CMakeLists.dist-minimal delete mode 100644 src/contrib/db/libmdbx/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/COPYRIGHT delete mode 100644 src/contrib/db/libmdbx/GNUmakefile delete mode 100644 src/contrib/db/libmdbx/LICENSE delete mode 100644 src/contrib/db/libmdbx/README.md delete mode 100644 src/contrib/db/libmdbx/appveyor.yml delete mode 100644 src/contrib/db/libmdbx/cmake/compiler.cmake delete mode 100644 src/contrib/db/libmdbx/cmake/profile.cmake delete mode 100644 src/contrib/db/libmdbx/cmake/utils.cmake delete mode 100644 src/contrib/db/libmdbx/example/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/example/README.md delete mode 100644 src/contrib/db/libmdbx/example/example-mdbx.c delete mode 100644 src/contrib/db/libmdbx/example/sample-bdb.txt delete mode 100644 src/contrib/db/libmdbx/mdbx.h delete mode 100644 src/contrib/db/libmdbx/packages/rpm/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/packages/rpm/build.sh delete mode 100644 src/contrib/db/libmdbx/packages/rpm/package.sh delete mode 100644 src/contrib/db/libmdbx/src/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/src/alloy.c delete mode 100644 src/contrib/db/libmdbx/src/elements/config.h.in delete mode 100644 src/contrib/db/libmdbx/src/elements/core.c delete mode 100644 src/contrib/db/libmdbx/src/elements/defs.h delete mode 100644 src/contrib/db/libmdbx/src/elements/internals.h delete mode 100644 src/contrib/db/libmdbx/src/elements/lck-posix.c delete mode 100644 src/contrib/db/libmdbx/src/elements/lck-windows.c delete mode 100644 src/contrib/db/libmdbx/src/elements/ntdll.def delete mode 100644 src/contrib/db/libmdbx/src/elements/osal.c delete mode 100644 src/contrib/db/libmdbx/src/elements/osal.h delete mode 100644 src/contrib/db/libmdbx/src/elements/version.c.in delete mode 100644 src/contrib/db/libmdbx/src/man1/mdbx_chk.1 delete mode 100644 src/contrib/db/libmdbx/src/man1/mdbx_copy.1 delete mode 100644 src/contrib/db/libmdbx/src/man1/mdbx_dump.1 delete mode 100644 src/contrib/db/libmdbx/src/man1/mdbx_load.1 delete mode 100644 src/contrib/db/libmdbx/src/man1/mdbx_stat.1 delete mode 100644 src/contrib/db/libmdbx/src/tools/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/src/tools/mdbx_chk.c delete mode 100644 src/contrib/db/libmdbx/src/tools/mdbx_copy.c delete mode 100644 src/contrib/db/libmdbx/src/tools/mdbx_dump.c delete mode 100644 src/contrib/db/libmdbx/src/tools/mdbx_load.c delete mode 100644 src/contrib/db/libmdbx/src/tools/mdbx_stat.c delete mode 100644 src/contrib/db/libmdbx/src/tools/wingetopt.c delete mode 100644 src/contrib/db/libmdbx/src/tools/wingetopt.h delete mode 100644 src/contrib/db/libmdbx/test/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/test/append.cc delete mode 100644 src/contrib/db/libmdbx/test/base.h delete mode 100644 src/contrib/db/libmdbx/test/cases.cc delete mode 100644 src/contrib/db/libmdbx/test/chrono.cc delete mode 100644 src/contrib/db/libmdbx/test/chrono.h delete mode 100644 src/contrib/db/libmdbx/test/config.cc delete mode 100644 src/contrib/db/libmdbx/test/config.h delete mode 100644 src/contrib/db/libmdbx/test/copy.cc delete mode 100644 src/contrib/db/libmdbx/test/darwin/LICENSE delete mode 100644 src/contrib/db/libmdbx/test/darwin/README.md delete mode 100644 src/contrib/db/libmdbx/test/darwin/pthread_barrier.c delete mode 100644 src/contrib/db/libmdbx/test/darwin/pthread_barrier.h delete mode 100644 src/contrib/db/libmdbx/test/dead.cc delete mode 100644 src/contrib/db/libmdbx/test/hill.cc delete mode 100644 src/contrib/db/libmdbx/test/jitter.cc delete mode 100644 src/contrib/db/libmdbx/test/keygen.cc delete mode 100644 src/contrib/db/libmdbx/test/keygen.h delete mode 100644 src/contrib/db/libmdbx/test/log.cc delete mode 100644 src/contrib/db/libmdbx/test/log.h delete mode 100644 src/contrib/db/libmdbx/test/long_stochastic.sh delete mode 100644 src/contrib/db/libmdbx/test/main.cc delete mode 100644 src/contrib/db/libmdbx/test/nested.cc delete mode 100644 src/contrib/db/libmdbx/test/osal-unix.cc delete mode 100644 src/contrib/db/libmdbx/test/osal-windows.cc delete mode 100644 src/contrib/db/libmdbx/test/osal.h delete mode 100644 src/contrib/db/libmdbx/test/pcrf/CMakeLists.txt delete mode 100644 src/contrib/db/libmdbx/test/pcrf/README.md delete mode 100644 src/contrib/db/libmdbx/test/pcrf/pcrf_test.c delete mode 100644 src/contrib/db/libmdbx/test/test.cc delete mode 100644 src/contrib/db/libmdbx/test/test.h delete mode 100644 src/contrib/db/libmdbx/test/try.cc delete mode 100644 src/contrib/db/libmdbx/test/ttl.cc delete mode 100644 src/contrib/db/libmdbx/test/utils.cc delete mode 100644 src/contrib/db/libmdbx/test/utils.h delete mode 100644 src/contrib/db/libmdbx/test/valgrind_suppress.txt delete mode 100644 src/contrib/eos_portable_archive/.DS_Store delete mode 100644 src/contrib/eos_portable_archive/change_log.txt delete mode 100644 src/contrib/eos_portable_archive/eos/polymorphic_portable_archive.hpp delete mode 100644 src/contrib/eos_portable_archive/eos/portable_archive.hpp delete mode 100644 src/contrib/eos_portable_archive/eos/portable_archive_exception.hpp delete mode 100644 src/contrib/eos_portable_archive/eos/portable_iarchive.hpp delete mode 100644 src/contrib/eos_portable_archive/eos/portable_oarchive.hpp delete mode 100644 src/contrib/eos_portable_archive/release_notes.txt delete mode 100644 src/contrib/eos_portable_archive/tutorial/.DS_Store delete mode 100644 src/contrib/eos_portable_archive/tutorial/._.DS_Store delete mode 100644 src/contrib/eos_portable_archive/tutorial/._code delete mode 100644 src/contrib/eos_portable_archive/tutorial/._images delete mode 100644 src/contrib/eos_portable_archive/tutorial/._scripts delete mode 100644 src/contrib/eos_portable_archive/tutorial/._styles delete mode 100644 src/contrib/eos_portable_archive/tutorial/._tutorial.html delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_0.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_1.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10b.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_11.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_2.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_3.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_4.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_5.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_6.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_7.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_8.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_9.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_0.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_1.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10b.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_11.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_2.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_3.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_4.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_5.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_6.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_7.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_8.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_9.cpp delete mode 100644 src/contrib/eos_portable_archive/tutorial/images/._boost.png delete mode 100644 src/contrib/eos_portable_archive/tutorial/images/._c++-source-code.png delete mode 100644 src/contrib/eos_portable_archive/tutorial/images/boost.png delete mode 100644 src/contrib/eos_portable_archive/tutorial/images/c++-source-code.png delete mode 100644 src/contrib/eos_portable_archive/tutorial/scripts/._jquery-1.4.min.js delete mode 100644 src/contrib/eos_portable_archive/tutorial/scripts/jquery-1.4.min.js delete mode 100644 src/contrib/eos_portable_archive/tutorial/styles/._boost.css delete mode 100644 src/contrib/eos_portable_archive/tutorial/styles/._style.css delete mode 100644 src/contrib/eos_portable_archive/tutorial/styles/boost.css delete mode 100644 src/contrib/eos_portable_archive/tutorial/styles/style.css delete mode 100644 src/contrib/eos_portable_archive/tutorial/tutorial.html delete mode 100644 src/contrib/epee/LICENSE.txt delete mode 100644 src/contrib/epee/README.md delete mode 100644 src/contrib/epee/demo/.gitignore delete mode 100644 src/contrib/epee/demo/CMakeLists.txt delete mode 100644 src/contrib/epee/demo/README.txt delete mode 100644 src/contrib/epee/demo/demo_http_server/demo_http_server.cpp delete mode 100644 src/contrib/epee/demo/demo_http_server/demo_http_server.h delete mode 100644 src/contrib/epee/demo/demo_http_server/stdafx.cpp delete mode 100644 src/contrib/epee/demo/demo_http_server/stdafx.h delete mode 100644 src/contrib/epee/demo/demo_http_server/targetver.h delete mode 100644 src/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp delete mode 100644 src/contrib/epee/demo/demo_levin_server/demo_levin_server.h delete mode 100644 src/contrib/epee/demo/demo_levin_server/stdafx.cpp delete mode 100644 src/contrib/epee/demo/demo_levin_server/stdafx.h delete mode 100644 src/contrib/epee/demo/demo_levin_server/targetver.h delete mode 100644 src/contrib/epee/demo/generate_gcc.sh delete mode 100644 src/contrib/epee/demo/generate_vc_proj.bat delete mode 100644 src/contrib/epee/demo/iface/transport_defs.h delete mode 100644 src/contrib/epee/include/auto_val_init.h delete mode 100644 src/contrib/epee/include/cache_helper.h delete mode 100644 src/contrib/epee/include/console_handler.h delete mode 100644 src/contrib/epee/include/copyable_atomic.h delete mode 100644 src/contrib/epee/include/file_io_utils.h delete mode 100644 src/contrib/epee/include/global_stream_operators.h delete mode 100644 src/contrib/epee/include/gzip_encoding.h delete mode 100644 src/contrib/epee/include/hmac-md5.h delete mode 100644 src/contrib/epee/include/include_base_utils.h delete mode 100644 src/contrib/epee/include/math_helper.h delete mode 100644 src/contrib/epee/include/md5_l.h delete mode 100644 src/contrib/epee/include/md5_l.inl delete mode 100644 src/contrib/epee/include/md5global.h delete mode 100644 src/contrib/epee/include/misc_helpers.h delete mode 100644 src/contrib/epee/include/misc_language.h delete mode 100644 src/contrib/epee/include/misc_log_ex.h delete mode 100644 src/contrib/epee/include/misc_os_dependent.h delete mode 100644 src/contrib/epee/include/net/abstract_tcp_server2.h delete mode 100644 src/contrib/epee/include/net/abstract_tcp_server2.inl delete mode 100644 src/contrib/epee/include/net/http_base.h delete mode 100644 src/contrib/epee/include/net/http_client.h delete mode 100644 src/contrib/epee/include/net/http_client_abstract_invoke.h delete mode 100644 src/contrib/epee/include/net/http_client_base.h delete mode 100644 src/contrib/epee/include/net/http_client_via_api_helper.h delete mode 100644 src/contrib/epee/include/net/http_protocol_handler.h delete mode 100644 src/contrib/epee/include/net/http_protocol_handler.inl delete mode 100644 src/contrib/epee/include/net/http_server_cp.h delete mode 100644 src/contrib/epee/include/net/http_server_cp2.h delete mode 100644 src/contrib/epee/include/net/http_server_handlers_map2.h delete mode 100644 src/contrib/epee/include/net/http_server_impl_base.h delete mode 100644 src/contrib/epee/include/net/http_server_thread_per_connect.h delete mode 100644 src/contrib/epee/include/net/levin_base.h delete mode 100644 src/contrib/epee/include/net/levin_client.h delete mode 100644 src/contrib/epee/include/net/levin_client.inl delete mode 100644 src/contrib/epee/include/net/levin_client_async.h delete mode 100644 src/contrib/epee/include/net/levin_client_async.inl delete mode 100644 src/contrib/epee/include/net/levin_helper.h delete mode 100644 src/contrib/epee/include/net/levin_protocol_handler.h delete mode 100644 src/contrib/epee/include/net/levin_protocol_handler_async.h delete mode 100644 src/contrib/epee/include/net/levin_server_cp.h delete mode 100644 src/contrib/epee/include/net/levin_server_cp2.h delete mode 100644 src/contrib/epee/include/net/local_ip.h delete mode 100644 src/contrib/epee/include/net/multiprotocols_server.h delete mode 100644 src/contrib/epee/include/net/munin_connection_handler.h delete mode 100644 src/contrib/epee/include/net/munin_node_server.h delete mode 100644 src/contrib/epee/include/net/net_helper.h delete mode 100644 src/contrib/epee/include/net/net_parse_helpers.h delete mode 100644 src/contrib/epee/include/net/net_utils_base.h delete mode 100644 src/contrib/epee/include/net/protocol_switcher.h delete mode 100644 src/contrib/epee/include/net/rpc_method_name.h delete mode 100644 src/contrib/epee/include/net/smtp.h delete mode 100644 src/contrib/epee/include/net/smtp.inl delete mode 100644 src/contrib/epee/include/net/smtp_helper.h delete mode 100644 src/contrib/epee/include/os_defenitions.h delete mode 100644 src/contrib/epee/include/print_fixed_point_helper.h delete mode 100644 src/contrib/epee/include/profile_tools.h delete mode 100644 src/contrib/epee/include/readwrite_lock.h delete mode 100644 src/contrib/epee/include/reg_exp_definer.h delete mode 100644 src/contrib/epee/include/reg_utils.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_helper_structs.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_helpers.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_hexemizer.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_serialization.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_serialization_boost_variant.h delete mode 100644 src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h delete mode 100644 src/contrib/epee/include/serialization/serialize_base.h delete mode 100644 src/contrib/epee/include/service_impl_base.h delete mode 100644 src/contrib/epee/include/sha1.h delete mode 100644 src/contrib/epee/include/sha1.inl delete mode 100644 src/contrib/epee/include/singleton.h delete mode 100644 src/contrib/epee/include/soci_helper.h delete mode 100644 src/contrib/epee/include/static_helpers.h delete mode 100644 src/contrib/epee/include/static_initializer.h delete mode 100644 src/contrib/epee/include/storages/activity_notifier.h delete mode 100644 src/contrib/epee/include/storages/crypted_storage.h delete mode 100644 src/contrib/epee/include/storages/gzipped_inmemstorage.h delete mode 100644 src/contrib/epee/include/storages/http_abstract_invoke.h delete mode 100644 src/contrib/epee/include/storages/levin_abstract_invoke2.h delete mode 100644 src/contrib/epee/include/storages/parserse_base_utils.h delete mode 100644 src/contrib/epee/include/storages/portable_storage.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_base.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_from_bin.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_from_json.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_template_helper.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_to_bin.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_to_json.h delete mode 100644 src/contrib/epee/include/storages/portable_storage_val_converters.h delete mode 100644 src/contrib/epee/include/string_coding.h delete mode 100644 src/contrib/epee/include/string_tools.h delete mode 100644 src/contrib/epee/include/sync_locked_object.h delete mode 100644 src/contrib/epee/include/syncobj.h delete mode 100644 src/contrib/epee/include/time_helper.h delete mode 100644 src/contrib/epee/include/tiny_ini.h delete mode 100644 src/contrib/epee/include/to_nonconst_iterator.h delete mode 100644 src/contrib/epee/include/warnings.h delete mode 100644 src/contrib/epee/include/zlib_helper.h delete mode 100644 src/contrib/epee/tests/.gitignore delete mode 100644 src/contrib/epee/tests/data/storages/invalid_storage_1.bin delete mode 100644 src/contrib/epee/tests/data/storages/invalid_storage_2.bin delete mode 100644 src/contrib/epee/tests/data/storages/invalid_storage_3.bin delete mode 100644 src/contrib/epee/tests/data/storages/invalid_storage_4.bin delete mode 100644 src/contrib/epee/tests/data/storages/valid_storage.bin delete mode 100644 src/contrib/epee/tests/generate_vc_proj.bat delete mode 100644 src/contrib/epee/tests/src/CMakeLists.txt delete mode 100644 src/contrib/epee/tests/src/misc/test_math.h delete mode 100644 src/contrib/epee/tests/src/net/test_net.h delete mode 100644 src/contrib/epee/tests/src/storages/portable_storages_test.h delete mode 100644 src/contrib/epee/tests/src/storages/storage_tests.h delete mode 100644 src/contrib/epee/tests/src/tests.cpp delete mode 100644 src/contrib/ethereum/CMakeLists.txt delete mode 100644 src/contrib/ethereum/libethash/CMakeLists.txt delete mode 100644 src/contrib/ethereum/libethash/bit_manipulation.h delete mode 100644 src/contrib/ethereum/libethash/builtins.h delete mode 100644 src/contrib/ethereum/libethash/endianness.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash-internal.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash.cpp delete mode 100644 src/contrib/ethereum/libethash/ethash/ethash.h delete mode 100644 src/contrib/ethereum/libethash/ethash/ethash.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash/hash_types.h delete mode 100644 src/contrib/ethereum/libethash/ethash/hash_types.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash/keccak.h delete mode 100644 src/contrib/ethereum/libethash/ethash/keccak.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash/progpow.hpp delete mode 100644 src/contrib/ethereum/libethash/ethash/version.h delete mode 100644 src/contrib/ethereum/libethash/keccak.c delete mode 100644 src/contrib/ethereum/libethash/keccakf1600.c delete mode 100644 src/contrib/ethereum/libethash/keccakf800.c delete mode 100644 src/contrib/ethereum/libethash/kiss99.hpp delete mode 100644 src/contrib/ethereum/libethash/managed.cpp delete mode 100644 src/contrib/ethereum/libethash/primes.c delete mode 100644 src/contrib/ethereum/libethash/primes.h delete mode 100644 src/contrib/ethereum/libethash/progpow.cpp delete mode 100644 src/contrib/ethereum/libethash/support/attributes.h delete mode 100644 src/contrib/miniupnp/.travis.yml delete mode 100644 src/contrib/miniupnp/CODE_OF_CONDUCT delete mode 100644 src/contrib/miniupnp/CONTRIBUTING delete mode 100644 src/contrib/miniupnp/LICENSE delete mode 100644 src/contrib/miniupnp/README delete mode 100644 src/contrib/miniupnp/appveyor.yml delete mode 100644 src/contrib/miniupnp/minissdpd/.gitignore delete mode 100644 src/contrib/miniupnp/minissdpd/Changelog.txt delete mode 100644 src/contrib/miniupnp/minissdpd/LICENSE delete mode 100644 src/contrib/miniupnp/minissdpd/Makefile delete mode 100644 src/contrib/miniupnp/minissdpd/README delete mode 100644 src/contrib/miniupnp/minissdpd/README.fr delete mode 100644 src/contrib/miniupnp/minissdpd/VERSION delete mode 100644 src/contrib/miniupnp/minissdpd/asyncsendto.c delete mode 100644 src/contrib/miniupnp/minissdpd/asyncsendto.h delete mode 100644 src/contrib/miniupnp/minissdpd/codelength.h delete mode 100644 src/contrib/miniupnp/minissdpd/config.h delete mode 100644 src/contrib/miniupnp/minissdpd/daemonize.c delete mode 100644 src/contrib/miniupnp/minissdpd/daemonize.h delete mode 100644 src/contrib/miniupnp/minissdpd/getifaddr.c delete mode 100644 src/contrib/miniupnp/minissdpd/getifaddr.h delete mode 100644 src/contrib/miniupnp/minissdpd/getroute.c delete mode 100644 src/contrib/miniupnp/minissdpd/getroute.h delete mode 100644 src/contrib/miniupnp/minissdpd/ifacewatch.c delete mode 100644 src/contrib/miniupnp/minissdpd/ifacewatch.h delete mode 100644 src/contrib/miniupnp/minissdpd/listifaces.c delete mode 100644 src/contrib/miniupnp/minissdpd/minissdpd.1 delete mode 100644 src/contrib/miniupnp/minissdpd/minissdpd.c delete mode 100644 src/contrib/miniupnp/minissdpd/minissdpd.init.d.script delete mode 100644 src/contrib/miniupnp/minissdpd/minissdpdtypes.h delete mode 100644 src/contrib/miniupnp/minissdpd/openssdpsocket.c delete mode 100644 src/contrib/miniupnp/minissdpd/openssdpsocket.h delete mode 100644 src/contrib/miniupnp/minissdpd/printresponse.c delete mode 100644 src/contrib/miniupnp/minissdpd/printresponse.h delete mode 100644 src/contrib/miniupnp/minissdpd/showminissdpdnotif.c delete mode 100644 src/contrib/miniupnp/minissdpd/testcodelength.c delete mode 100644 src/contrib/miniupnp/minissdpd/testminissdpd.c delete mode 100644 src/contrib/miniupnp/minissdpd/testminissdpd.sh delete mode 100644 src/contrib/miniupnp/minissdpd/testminissdpdnotif.sh delete mode 100644 src/contrib/miniupnp/minissdpd/upnputils.c delete mode 100644 src/contrib/miniupnp/minissdpd/upnputils.h delete mode 100644 src/contrib/miniupnp/miniupnp.podspec delete mode 100644 src/contrib/miniupnp/miniupnpc-async/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpc-async/Changelog.txt delete mode 100644 src/contrib/miniupnp/miniupnpc-async/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpc-async/README delete mode 100644 src/contrib/miniupnp/miniupnpc-async/config.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/declspec.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/minixml.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/minixml.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/parsessdpreply.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/parsessdpreply.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/testasync.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.h delete mode 100644 src/contrib/miniupnp/miniupnpc-async/upnputils.c delete mode 100644 src/contrib/miniupnp/miniupnpc-async/upnputils.h delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/README delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/declspec.h delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.c delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.h delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.c delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.h delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/minixml.c delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/minixml.h delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/upnpc-libevent.c delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.h delete mode 100644 src/contrib/miniupnp/miniupnpc/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpc/CMakeLists.txt delete mode 100644 src/contrib/miniupnp/miniupnpc/Changelog.txt delete mode 100644 src/contrib/miniupnp/miniupnpc/LICENSE delete mode 100644 src/contrib/miniupnp/miniupnpc/MANIFEST.in delete mode 100644 src/contrib/miniupnp/miniupnpc/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpc/Makefile.mingw delete mode 100644 src/contrib/miniupnp/miniupnpc/README delete mode 100644 src/contrib/miniupnp/miniupnpc/VERSION delete mode 100644 src/contrib/miniupnp/miniupnpc/apiversions.txt delete mode 100644 src/contrib/miniupnp/miniupnpc/codelength.h delete mode 100644 src/contrib/miniupnp/miniupnpc/connecthostport.c delete mode 100644 src/contrib/miniupnp/miniupnpc/connecthostport.h delete mode 100644 src/contrib/miniupnp/miniupnpc/external-ip.sh delete mode 100644 src/contrib/miniupnp/miniupnpc/igd_desc_parse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/igd_desc_parse.h delete mode 100644 src/contrib/miniupnp/miniupnpc/java/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpc/java/JavaBridgeTest.java delete mode 100644 src/contrib/miniupnp/miniupnpc/java/testjava.bat delete mode 100644 src/contrib/miniupnp/miniupnpc/java/testjava.sh delete mode 100644 src/contrib/miniupnp/miniupnpc/listdevices.c delete mode 100644 src/contrib/miniupnp/miniupnpc/man3/miniupnpc.3 delete mode 100644 src/contrib/miniupnp/miniupnpc/mingw32make.bat delete mode 100644 src/contrib/miniupnp/miniupnpc/minihttptestserver.c delete mode 100644 src/contrib/miniupnp/miniupnpc/minisoap.c delete mode 100644 src/contrib/miniupnp/miniupnpc/minisoap.h delete mode 100644 src/contrib/miniupnp/miniupnpc/minissdpc.c delete mode 100644 src/contrib/miniupnp/miniupnpc/minissdpc.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpc.c delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpc.def delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpc.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpc_declspec.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpc_socketdef.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpcmodule.c delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.cmake delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.in delete mode 100644 src/contrib/miniupnp/miniupnpc/miniupnpctypes.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniwget.c delete mode 100644 src/contrib/miniupnp/miniupnpc/miniwget.h delete mode 100644 src/contrib/miniupnp/miniupnpc/miniwget_private.h delete mode 100644 src/contrib/miniupnp/miniupnpc/minixml.c delete mode 100644 src/contrib/miniupnp/miniupnpc/minixml.h delete mode 100644 src/contrib/miniupnp/miniupnpc/minixmlvalid.c delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/genminiupnpcstrings.vbs delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.sln delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcproj delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj.filters delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.sln delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj.filters delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2015.sln delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcproj delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj.filters delete mode 100644 src/contrib/miniupnp/miniupnpc/msvc/upnpc-static_vs2010.vcxproj delete mode 100644 src/contrib/miniupnp/miniupnpc/portlistingparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/portlistingparse.h delete mode 100644 src/contrib/miniupnp/miniupnpc/pymoduletest.py delete mode 100644 src/contrib/miniupnp/miniupnpc/pymoduletest3.py delete mode 100644 src/contrib/miniupnp/miniupnpc/receivedata.c delete mode 100644 src/contrib/miniupnp/miniupnpc/receivedata.h delete mode 100644 src/contrib/miniupnp/miniupnpc/setup.py delete mode 100644 src/contrib/miniupnp/miniupnpc/setupmingw32.py delete mode 100644 src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.values delete mode 100644 src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.values delete mode 100644 src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testigddescparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/testminiwget.c delete mode 100644 src/contrib/miniupnp/miniupnpc/testminiwget.sh delete mode 100644 src/contrib/miniupnp/miniupnpc/testminixml.c delete mode 100644 src/contrib/miniupnp/miniupnpc/testportlistingparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.namevalue delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.xml delete mode 100644 src/contrib/miniupnp/miniupnpc/testreplyparse/readme.txt delete mode 100644 src/contrib/miniupnp/miniupnpc/testupnpigd.py delete mode 100644 src/contrib/miniupnp/miniupnpc/testupnpreplyparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/testupnpreplyparse.sh delete mode 100644 src/contrib/miniupnp/miniupnpc/updateminiupnpcstrings.sh delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpc.c delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpcommands.c delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpcommands.h delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpdev.c delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpdev.h delete mode 100644 src/contrib/miniupnp/miniupnpc/upnperrors.c delete mode 100644 src/contrib/miniupnp/miniupnpc/upnperrors.h delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpreplyparse.c delete mode 100644 src/contrib/miniupnp/miniupnpc/upnpreplyparse.h delete mode 100644 src/contrib/miniupnp/miniupnpc/wingenminiupnpcstrings.c delete mode 100644 src/contrib/miniupnp/miniupnpd/.gitignore delete mode 100644 src/contrib/miniupnp/miniupnpd/Changelog.txt delete mode 100644 src/contrib/miniupnp/miniupnpd/INSTALL delete mode 100644 src/contrib/miniupnp/miniupnpd/LICENSE delete mode 100644 src/contrib/miniupnp/miniupnpd/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/Makefile.linux delete mode 100644 src/contrib/miniupnp/miniupnpd/Makefile.linux_nft delete mode 100644 src/contrib/miniupnp/miniupnpd/Makefile.macosx delete mode 100644 src/contrib/miniupnp/miniupnpd/Makefile.sunos delete mode 100644 src/contrib/miniupnp/miniupnpd/README delete mode 100644 src/contrib/miniupnp/miniupnpd/TODO delete mode 100644 src/contrib/miniupnp/miniupnpd/VERSION delete mode 100644 src/contrib/miniupnp/miniupnpd/asyncsendto.c delete mode 100644 src/contrib/miniupnp/miniupnpd/asyncsendto.h delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/getifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/getroute.c delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/ifacewatcher.c delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/testgetifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/bsd/testifacewatcher.c delete mode 100644 src/contrib/miniupnp/miniupnpd/codelength.h delete mode 100644 src/contrib/miniupnp/miniupnpd/commonrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/daemonize.c delete mode 100644 src/contrib/miniupnp/miniupnpd/daemonize.h delete mode 100644 src/contrib/miniupnp/miniupnpd/genconfig.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/getconnstatus.c delete mode 100644 src/contrib/miniupnp/miniupnpd/getconnstatus.h delete mode 100644 src/contrib/miniupnp/miniupnpd/getifaddr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/getifaddr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/getifstats.h delete mode 100644 src/contrib/miniupnp/miniupnpd/getroute.h delete mode 100644 src/contrib/miniupnp/miniupnpd/ifacewatcher.h delete mode 100644 src/contrib/miniupnp/miniupnpd/ipf/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/ipf/testipfrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.c delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.h delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/ipfw/testipfwrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/linux/getifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/linux/getroute.c delete mode 100644 src/contrib/miniupnp/miniupnpd/linux/ifacewatcher.c delete mode 100644 src/contrib/miniupnp/miniupnpd/linux/miniupnpd.init.d.script delete mode 100644 src/contrib/miniupnp/miniupnpd/mac/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/mac/getifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/mac/org.tuxfamily.miniupnpd.plist.before delete mode 100644 src/contrib/miniupnp/miniupnpd/mac/testgetifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/macros.h delete mode 100644 src/contrib/miniupnp/miniupnpd/minissdp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/minissdp.h delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpd.8 delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpd.c delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpd.conf delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpd.rc.once.d.script delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpdctl.c delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpdctl.txt delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpdpath.h delete mode 100644 src/contrib/miniupnp/miniupnpd/miniupnpdtypes.h delete mode 100644 src/contrib/miniupnp/miniupnpd/minixml.c delete mode 100644 src/contrib/miniupnp/miniupnpd/minixml.h delete mode 100644 src/contrib/miniupnp/miniupnpd/natpmp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/natpmp.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_display.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_flush.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_init.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_removeall.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptables_display.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptables_display_miniupnpd.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptables_flush.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptables_init.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptables_removeall.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/miniupnpd_functions.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/nfct_get.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/test_nfct_get.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_dscp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_peer.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/testiptpinhole.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter/tiny_nf_nat.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/README.md delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/nfct_get.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.h delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_delete_chain.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_flush.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_init.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_removeall.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/test_nfct_get.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/testnftnlrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/netfilter_nft/tiny_nf_nat.h delete mode 100644 src/contrib/miniupnp/miniupnpd/options.c delete mode 100644 src/contrib/miniupnp/miniupnpd/options.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pcp_msg_struct.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pcplearndscp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/pcplearndscp.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pcpserver.c delete mode 100644 src/contrib/miniupnp/miniupnpd/pcpserver.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/Makefile delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/obsdrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/obsdrdr.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/pfpinhole.c delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/pfpinhole.h delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/testobsdrdr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/pf/testpfpinhole.c delete mode 100644 src/contrib/miniupnp/miniupnpd/portinuse.c delete mode 100644 src/contrib/miniupnp/miniupnpd/portinuse.h delete mode 100644 src/contrib/miniupnp/miniupnpd/solaris/getifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testasyncsendto.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testgetifaddr.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testgetifaddr.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/testgetifstats.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testgetroute.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testminissdp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testportinuse.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testssdppktgen.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testupnpdescgen.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testupnppermissions.c delete mode 100644 src/contrib/miniupnp/miniupnpd/testupnppermissions.sh delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpdescgen.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpdescgen.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpdescstrings.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpevents.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpevents.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpglobalvars.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpglobalvars.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnphttp.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnphttp.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnppermissions.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnppermissions.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnppinhole.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnppinhole.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpredirect.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpredirect.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpreplyparse.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpreplyparse.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpsoap.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpsoap.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnpurns.h delete mode 100644 src/contrib/miniupnp/miniupnpd/upnputils.c delete mode 100644 src/contrib/miniupnp/miniupnpd/upnputils.h delete mode 100644 src/contrib/miniupnpc/CMakeLists.txt delete mode 100644 src/contrib/miniupnpc/Changelog.txt delete mode 100644 src/contrib/miniupnpc/LICENSE delete mode 100644 src/contrib/miniupnpc/MANIFEST.in delete mode 100644 src/contrib/miniupnpc/Makefile delete mode 100644 src/contrib/miniupnpc/Makefile.mingw delete mode 100644 src/contrib/miniupnpc/README delete mode 100644 src/contrib/miniupnpc/VERSION delete mode 100644 src/contrib/miniupnpc/apiversions.txt delete mode 100644 src/contrib/miniupnpc/bsdqueue.h delete mode 100644 src/contrib/miniupnpc/codelength.h delete mode 100644 src/contrib/miniupnpc/connecthostport.c delete mode 100644 src/contrib/miniupnpc/connecthostport.h delete mode 100644 src/contrib/miniupnpc/declspec.h delete mode 100644 src/contrib/miniupnpc/external-ip.sh delete mode 100644 src/contrib/miniupnpc/igd_desc_parse.c delete mode 100644 src/contrib/miniupnpc/igd_desc_parse.h delete mode 100644 src/contrib/miniupnpc/java/JavaBridgeTest.java delete mode 100644 src/contrib/miniupnpc/java/testjava.bat delete mode 100644 src/contrib/miniupnpc/java/testjava.sh delete mode 100644 src/contrib/miniupnpc/man3/miniupnpc.3 delete mode 100644 src/contrib/miniupnpc/mingw32make.bat delete mode 100644 src/contrib/miniupnpc/minihttptestserver.c delete mode 100644 src/contrib/miniupnpc/minisoap.c delete mode 100644 src/contrib/miniupnpc/minisoap.h delete mode 100644 src/contrib/miniupnpc/minissdpc.c delete mode 100644 src/contrib/miniupnpc/minissdpc.h delete mode 100644 src/contrib/miniupnpc/miniupnpc.c delete mode 100644 src/contrib/miniupnpc/miniupnpc.def delete mode 100644 src/contrib/miniupnpc/miniupnpc.h delete mode 100644 src/contrib/miniupnpc/miniupnpcmodule.c delete mode 100644 src/contrib/miniupnpc/miniupnpcstrings.h.cmake delete mode 100644 src/contrib/miniupnpc/miniupnpcstrings.h.in delete mode 100644 src/contrib/miniupnpc/miniupnpctypes.h delete mode 100644 src/contrib/miniupnpc/miniwget.c delete mode 100644 src/contrib/miniupnpc/miniwget.h delete mode 100644 src/contrib/miniupnpc/minixml.c delete mode 100644 src/contrib/miniupnpc/minixml.h delete mode 100644 src/contrib/miniupnpc/minixmlvalid.c delete mode 100644 src/contrib/miniupnpc/msvc/miniupnpc.sln delete mode 100644 src/contrib/miniupnpc/msvc/miniupnpc.vcproj delete mode 100644 src/contrib/miniupnpc/msvc/upnpc-static.vcproj delete mode 100644 src/contrib/miniupnpc/portlistingparse.c delete mode 100644 src/contrib/miniupnpc/portlistingparse.h delete mode 100644 src/contrib/miniupnpc/pymoduletest.py delete mode 100644 src/contrib/miniupnpc/receivedata.c delete mode 100644 src/contrib/miniupnpc/receivedata.h delete mode 100644 src/contrib/miniupnpc/setup.py delete mode 100644 src/contrib/miniupnpc/setupmingw32.py delete mode 100644 src/contrib/miniupnpc/testigddescparse.c delete mode 100644 src/contrib/miniupnpc/testminiwget.c delete mode 100644 src/contrib/miniupnpc/testminiwget.sh delete mode 100644 src/contrib/miniupnpc/testminixml.c delete mode 100644 src/contrib/miniupnpc/testreplyparse/DeletePortMapping.namevalue delete mode 100644 src/contrib/miniupnpc/testreplyparse/DeletePortMapping.xml delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.xml delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue delete mode 100644 src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml delete mode 100644 src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue delete mode 100644 src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.xml delete mode 100644 src/contrib/miniupnpc/testreplyparse/readme.txt delete mode 100644 src/contrib/miniupnpc/testupnpigd.py delete mode 100644 src/contrib/miniupnpc/testupnpreplyparse.c delete mode 100644 src/contrib/miniupnpc/testupnpreplyparse.sh delete mode 100644 src/contrib/miniupnpc/updateminiupnpcstrings.sh delete mode 100644 src/contrib/miniupnpc/upnpc.c delete mode 100644 src/contrib/miniupnpc/upnpcommands.c delete mode 100644 src/contrib/miniupnpc/upnpcommands.h delete mode 100644 src/contrib/miniupnpc/upnperrors.c delete mode 100644 src/contrib/miniupnpc/upnperrors.h delete mode 100644 src/contrib/miniupnpc/upnpreplyparse.c delete mode 100644 src/contrib/miniupnpc/upnpreplyparse.h delete mode 100644 src/contrib/miniupnpc/wingenminiupnpcstrings.c delete mode 100644 src/contrib/zlib/CMakeLists.txt delete mode 100644 src/contrib/zlib/ChangeLog delete mode 100644 src/contrib/zlib/FAQ delete mode 100644 src/contrib/zlib/INDEX delete mode 100644 src/contrib/zlib/Makefile delete mode 100644 src/contrib/zlib/Makefile.in delete mode 100644 src/contrib/zlib/README delete mode 100644 src/contrib/zlib/adler32.c delete mode 100644 src/contrib/zlib/amiga/Makefile.pup delete mode 100644 src/contrib/zlib/amiga/Makefile.sas delete mode 100644 src/contrib/zlib/as400/bndsrc delete mode 100644 src/contrib/zlib/as400/compile.clp delete mode 100644 src/contrib/zlib/as400/readme.txt delete mode 100644 src/contrib/zlib/as400/zlib.inc delete mode 100644 src/contrib/zlib/compress.c delete mode 100644 src/contrib/zlib/configure delete mode 100644 src/contrib/zlib/contrib/README.contrib delete mode 100644 src/contrib/zlib/contrib/ada/buffer_demo.adb delete mode 100644 src/contrib/zlib/contrib/ada/mtest.adb delete mode 100644 src/contrib/zlib/contrib/ada/read.adb delete mode 100644 src/contrib/zlib/contrib/ada/readme.txt delete mode 100644 src/contrib/zlib/contrib/ada/test.adb delete mode 100644 src/contrib/zlib/contrib/ada/zlib-streams.adb delete mode 100644 src/contrib/zlib/contrib/ada/zlib-streams.ads delete mode 100644 src/contrib/zlib/contrib/ada/zlib-thin.adb delete mode 100644 src/contrib/zlib/contrib/ada/zlib-thin.ads delete mode 100644 src/contrib/zlib/contrib/ada/zlib.adb delete mode 100644 src/contrib/zlib/contrib/ada/zlib.ads delete mode 100644 src/contrib/zlib/contrib/ada/zlib.gpr delete mode 100644 src/contrib/zlib/contrib/amd64/amd64-match.S delete mode 100644 src/contrib/zlib/contrib/asm686/README.686 delete mode 100644 src/contrib/zlib/contrib/asm686/match.S delete mode 100644 src/contrib/zlib/contrib/blast/Makefile delete mode 100644 src/contrib/zlib/contrib/blast/README delete mode 100644 src/contrib/zlib/contrib/blast/blast.c delete mode 100644 src/contrib/zlib/contrib/blast/blast.h delete mode 100644 src/contrib/zlib/contrib/blast/test.pk delete mode 100644 src/contrib/zlib/contrib/blast/test.txt delete mode 100644 src/contrib/zlib/contrib/delphi/ZLib.pas delete mode 100644 src/contrib/zlib/contrib/delphi/ZLibConst.pas delete mode 100644 src/contrib/zlib/contrib/delphi/readme.txt delete mode 100644 src/contrib/zlib/contrib/delphi/zlibd32.mak delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib.build delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib.chm delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib.sln delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs delete mode 100644 src/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt delete mode 100644 src/contrib/zlib/contrib/dotzlib/readme.txt delete mode 100644 src/contrib/zlib/contrib/gcc_gvmat64/gvmat64.S delete mode 100644 src/contrib/zlib/contrib/infback9/README delete mode 100644 src/contrib/zlib/contrib/infback9/infback9.c delete mode 100644 src/contrib/zlib/contrib/infback9/infback9.h delete mode 100644 src/contrib/zlib/contrib/infback9/inffix9.h delete mode 100644 src/contrib/zlib/contrib/infback9/inflate9.h delete mode 100644 src/contrib/zlib/contrib/infback9/inftree9.c delete mode 100644 src/contrib/zlib/contrib/infback9/inftree9.h delete mode 100644 src/contrib/zlib/contrib/inflate86/inffas86.c delete mode 100644 src/contrib/zlib/contrib/inflate86/inffast.S delete mode 100644 src/contrib/zlib/contrib/iostream/test.cpp delete mode 100644 src/contrib/zlib/contrib/iostream/zfstream.cpp delete mode 100644 src/contrib/zlib/contrib/iostream/zfstream.h delete mode 100644 src/contrib/zlib/contrib/iostream2/zstream.h delete mode 100644 src/contrib/zlib/contrib/iostream2/zstream_test.cpp delete mode 100644 src/contrib/zlib/contrib/iostream3/README delete mode 100644 src/contrib/zlib/contrib/iostream3/TODO delete mode 100644 src/contrib/zlib/contrib/iostream3/test.cc delete mode 100644 src/contrib/zlib/contrib/iostream3/zfstream.cc delete mode 100644 src/contrib/zlib/contrib/iostream3/zfstream.h delete mode 100644 src/contrib/zlib/contrib/masmx64/bld_ml64.bat delete mode 100644 src/contrib/zlib/contrib/masmx64/gvmat64.asm delete mode 100644 src/contrib/zlib/contrib/masmx64/inffas8664.c delete mode 100644 src/contrib/zlib/contrib/masmx64/inffasx64.asm delete mode 100644 src/contrib/zlib/contrib/masmx64/readme.txt delete mode 100644 src/contrib/zlib/contrib/masmx86/bld_ml32.bat delete mode 100644 src/contrib/zlib/contrib/masmx86/inffas32.asm delete mode 100644 src/contrib/zlib/contrib/masmx86/match686.asm delete mode 100644 src/contrib/zlib/contrib/masmx86/readme.txt delete mode 100644 src/contrib/zlib/contrib/minizip/Makefile delete mode 100644 src/contrib/zlib/contrib/minizip/Makefile.am delete mode 100644 src/contrib/zlib/contrib/minizip/MiniZip64_Changes.txt delete mode 100644 src/contrib/zlib/contrib/minizip/MiniZip64_info.txt delete mode 100644 src/contrib/zlib/contrib/minizip/configure.ac delete mode 100644 src/contrib/zlib/contrib/minizip/crypt.h delete mode 100644 src/contrib/zlib/contrib/minizip/ioapi.c delete mode 100644 src/contrib/zlib/contrib/minizip/ioapi.h delete mode 100644 src/contrib/zlib/contrib/minizip/iowin32.c delete mode 100644 src/contrib/zlib/contrib/minizip/iowin32.h delete mode 100644 src/contrib/zlib/contrib/minizip/make_vms.com delete mode 100644 src/contrib/zlib/contrib/minizip/miniunz.c delete mode 100644 src/contrib/zlib/contrib/minizip/miniunzip.1 delete mode 100644 src/contrib/zlib/contrib/minizip/minizip.1 delete mode 100644 src/contrib/zlib/contrib/minizip/minizip.c delete mode 100644 src/contrib/zlib/contrib/minizip/minizip.pc.in delete mode 100644 src/contrib/zlib/contrib/minizip/mztools.c delete mode 100644 src/contrib/zlib/contrib/minizip/mztools.h delete mode 100644 src/contrib/zlib/contrib/minizip/unzip.c delete mode 100644 src/contrib/zlib/contrib/minizip/unzip.h delete mode 100644 src/contrib/zlib/contrib/minizip/zip.c delete mode 100644 src/contrib/zlib/contrib/minizip/zip.h delete mode 100644 src/contrib/zlib/contrib/pascal/example.pas delete mode 100644 src/contrib/zlib/contrib/pascal/readme.txt delete mode 100644 src/contrib/zlib/contrib/pascal/zlibd32.mak delete mode 100644 src/contrib/zlib/contrib/pascal/zlibpas.pas delete mode 100644 src/contrib/zlib/contrib/puff/Makefile delete mode 100644 src/contrib/zlib/contrib/puff/README delete mode 100644 src/contrib/zlib/contrib/puff/puff.c delete mode 100644 src/contrib/zlib/contrib/puff/puff.h delete mode 100644 src/contrib/zlib/contrib/puff/pufftest.c delete mode 100644 src/contrib/zlib/contrib/puff/zeros.raw delete mode 100644 src/contrib/zlib/contrib/testzlib/testzlib.c delete mode 100644 src/contrib/zlib/contrib/testzlib/testzlib.txt delete mode 100644 src/contrib/zlib/contrib/untgz/Makefile delete mode 100644 src/contrib/zlib/contrib/untgz/Makefile.msc delete mode 100644 src/contrib/zlib/contrib/untgz/untgz.c delete mode 100644 src/contrib/zlib/contrib/vstudio/readme.txt delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlib.rc delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibvc.def delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibvc.sln delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/zlib.rc delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/zlibvc.def delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/zlibvc.sln delete mode 100644 src/contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/zlib.rc delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/zlibvc.def delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/zlibvc.sln delete mode 100644 src/contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/zlib.rc delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/zlibvc.def delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/zlibvc.sln delete mode 100644 src/contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/minizip.vcproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/testzlibdll.vcproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/zlib.rc delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/zlibvc.def delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/zlibvc.sln delete mode 100644 src/contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj delete mode 100644 src/contrib/zlib/crc32.c delete mode 100644 src/contrib/zlib/crc32.h delete mode 100644 src/contrib/zlib/deflate.c delete mode 100644 src/contrib/zlib/deflate.h delete mode 100644 src/contrib/zlib/doc/algorithm.txt delete mode 100644 src/contrib/zlib/doc/rfc1950.txt delete mode 100644 src/contrib/zlib/doc/rfc1951.txt delete mode 100644 src/contrib/zlib/doc/rfc1952.txt delete mode 100644 src/contrib/zlib/doc/txtvsbin.txt delete mode 100644 src/contrib/zlib/examples/README.examples delete mode 100644 src/contrib/zlib/examples/enough.c delete mode 100644 src/contrib/zlib/examples/fitblk.c delete mode 100644 src/contrib/zlib/examples/gun.c delete mode 100644 src/contrib/zlib/examples/gzappend.c delete mode 100644 src/contrib/zlib/examples/gzjoin.c delete mode 100644 src/contrib/zlib/examples/gzlog.c delete mode 100644 src/contrib/zlib/examples/gzlog.h delete mode 100644 src/contrib/zlib/examples/zlib_how.html delete mode 100644 src/contrib/zlib/examples/zpipe.c delete mode 100644 src/contrib/zlib/examples/zran.c delete mode 100644 src/contrib/zlib/gzclose.c delete mode 100644 src/contrib/zlib/gzguts.h delete mode 100644 src/contrib/zlib/gzlib.c delete mode 100644 src/contrib/zlib/gzread.c delete mode 100644 src/contrib/zlib/gzwrite.c delete mode 100644 src/contrib/zlib/infback.c delete mode 100644 src/contrib/zlib/inffast.c delete mode 100644 src/contrib/zlib/inffast.h delete mode 100644 src/contrib/zlib/inffixed.h delete mode 100644 src/contrib/zlib/inflate.c delete mode 100644 src/contrib/zlib/inflate.h delete mode 100644 src/contrib/zlib/inftrees.c delete mode 100644 src/contrib/zlib/inftrees.h delete mode 100644 src/contrib/zlib/make_vms.com delete mode 100644 src/contrib/zlib/msdos/Makefile.bor delete mode 100644 src/contrib/zlib/msdos/Makefile.dj2 delete mode 100644 src/contrib/zlib/msdos/Makefile.emx delete mode 100644 src/contrib/zlib/msdos/Makefile.msc delete mode 100644 src/contrib/zlib/msdos/Makefile.tc delete mode 100644 src/contrib/zlib/nintendods/Makefile delete mode 100644 src/contrib/zlib/nintendods/README delete mode 100644 src/contrib/zlib/old/Makefile.emx delete mode 100644 src/contrib/zlib/old/Makefile.riscos delete mode 100644 src/contrib/zlib/old/README delete mode 100644 src/contrib/zlib/old/descrip.mms delete mode 100644 src/contrib/zlib/old/os2/Makefile.os2 delete mode 100644 src/contrib/zlib/old/os2/zlib.def delete mode 100644 src/contrib/zlib/old/visual-basic.txt delete mode 100644 src/contrib/zlib/os400/README400 delete mode 100644 src/contrib/zlib/os400/bndsrc delete mode 100644 src/contrib/zlib/os400/make.sh delete mode 100644 src/contrib/zlib/os400/zlib.inc delete mode 100644 src/contrib/zlib/qnx/package.qpg delete mode 100644 src/contrib/zlib/test/example.c delete mode 100644 src/contrib/zlib/test/infcover.c delete mode 100644 src/contrib/zlib/test/minigzip.c delete mode 100644 src/contrib/zlib/treebuild.xml delete mode 100644 src/contrib/zlib/trees.c delete mode 100644 src/contrib/zlib/trees.h delete mode 100644 src/contrib/zlib/uncompr.c delete mode 100644 src/contrib/zlib/watcom/watcom_f.mak delete mode 100644 src/contrib/zlib/watcom/watcom_l.mak delete mode 100644 src/contrib/zlib/win32/DLL_FAQ.txt delete mode 100644 src/contrib/zlib/win32/Makefile.bor delete mode 100644 src/contrib/zlib/win32/Makefile.gcc delete mode 100644 src/contrib/zlib/win32/Makefile.msc delete mode 100644 src/contrib/zlib/win32/README-WIN32.txt delete mode 100644 src/contrib/zlib/win32/VisualC.txt delete mode 100644 src/contrib/zlib/win32/zlib.def delete mode 100644 src/contrib/zlib/win32/zlib1.rc delete mode 100644 src/contrib/zlib/zconf.h.cmakein delete mode 100644 src/contrib/zlib/zconf.h.in delete mode 100644 src/contrib/zlib/zconf.h.included delete mode 100644 src/contrib/zlib/zlib.3 delete mode 100644 src/contrib/zlib/zlib.3.pdf delete mode 100644 src/contrib/zlib/zlib.h delete mode 100644 src/contrib/zlib/zlib.map delete mode 100644 src/contrib/zlib/zlib.pc.cmakein delete mode 100644 src/contrib/zlib/zlib.pc.in delete mode 100644 src/contrib/zlib/zlib2ansi delete mode 100644 src/contrib/zlib/zutil.c delete mode 100644 src/contrib/zlib/zutil.h delete mode 100644 src/crypto/RIPEMD160.c delete mode 100644 src/crypto/RIPEMD160.h delete mode 100644 src/crypto/RIPEMD160_helper.cpp delete mode 100644 src/crypto/RIPEMD160_helper.h delete mode 100644 src/crypto/bitcoin/byteswap.h delete mode 100644 src/crypto/bitcoin/common.h delete mode 100644 src/crypto/bitcoin/cpuid.h delete mode 100644 src/crypto/bitcoin/endian.h delete mode 100644 src/crypto/bitcoin/sha256.cpp delete mode 100644 src/crypto/bitcoin/sha256.h delete mode 100644 src/crypto/bitcoin/sha256_helper.h delete mode 100644 src/crypto/blake2-impl.h delete mode 100644 src/crypto/blake2.h delete mode 100644 src/crypto/blake2b-ref.c delete mode 100644 src/crypto/chacha8.c delete mode 100644 src/crypto/chacha8.h delete mode 100644 src/crypto/chacha8_stream.c delete mode 100644 src/crypto/chacha8_stream.h delete mode 100644 src/crypto/crypto-ops-data.c delete mode 100644 src/crypto/crypto-ops.c delete mode 100644 src/crypto/crypto-ops.h delete mode 100644 src/crypto/crypto-sugar.cpp delete mode 100644 src/crypto/crypto-sugar.h delete mode 100644 src/crypto/crypto.cpp delete mode 100644 src/crypto/crypto.h delete mode 100644 src/crypto/ecrypt-config.h delete mode 100644 src/crypto/ecrypt-machine.h delete mode 100644 src/crypto/ecrypt-portable.h delete mode 100644 src/crypto/ecrypt-sync.h delete mode 100644 src/crypto/generic-ops.h delete mode 100644 src/crypto/hash-ops.h delete mode 100644 src/crypto/hash.c delete mode 100644 src/crypto/hash.h delete mode 100644 src/crypto/initializer.h delete mode 100644 src/crypto/keccak.c delete mode 100644 src/crypto/keccak.h delete mode 100644 src/crypto/random.c delete mode 100644 src/crypto/random.h delete mode 100644 src/crypto/range_proofs.cpp delete mode 100644 src/crypto/range_proofs.h delete mode 100644 src/crypto/tree-hash.c delete mode 100644 src/currency_core/account.cpp delete mode 100644 src/currency_core/account.h delete mode 100644 src/currency_core/account_boost_serialization.h delete mode 100644 src/currency_core/alias_helper.h delete mode 100644 src/currency_core/basic_api_response_codes.h delete mode 100644 src/currency_core/basic_kv_structs.h delete mode 100644 src/currency_core/basic_pow_helpers.cpp delete mode 100644 src/currency_core/basic_pow_helpers.h delete mode 100644 src/currency_core/bc_attachments_helpers.h delete mode 100644 src/currency_core/bc_attachments_helpers_basic.h delete mode 100644 src/currency_core/bc_attachments_service_manager.cpp delete mode 100644 src/currency_core/bc_attachments_service_manager.h delete mode 100644 src/currency_core/bc_block_datetime_service.h delete mode 100644 src/currency_core/bc_escrow_service.h delete mode 100644 src/currency_core/bc_offers_serialization.h delete mode 100644 src/currency_core/bc_offers_service.cpp delete mode 100644 src/currency_core/bc_offers_service.h delete mode 100644 src/currency_core/bc_offers_service_basic.h delete mode 100644 src/currency_core/bc_payments_id_service.h delete mode 100644 src/currency_core/block_flags.h delete mode 100644 src/currency_core/blockchain_storage.cpp delete mode 100644 src/currency_core/blockchain_storage.h delete mode 100644 src/currency_core/blockchain_storage_basic.h delete mode 100644 src/currency_core/blockchain_storage_boost_serialization.h delete mode 100644 src/currency_core/checkpoints.cpp delete mode 100644 src/currency_core/checkpoints.h delete mode 100644 src/currency_core/checkpoints_create.h delete mode 100644 src/currency_core/connection_context.h delete mode 100644 src/currency_core/core_runtime_config.h delete mode 100644 src/currency_core/core_tools.h delete mode 100644 src/currency_core/currency_basic.h delete mode 100644 src/currency_core/currency_boost_serialization.h delete mode 100644 src/currency_core/currency_config.h delete mode 100644 src/currency_core/currency_core.cpp delete mode 100644 src/currency_core/currency_core.h delete mode 100644 src/currency_core/currency_format_utils.cpp delete mode 100644 src/currency_core/currency_format_utils.h delete mode 100644 src/currency_core/currency_format_utils_abstract.h delete mode 100644 src/currency_core/currency_format_utils_blocks.cpp delete mode 100644 src/currency_core/currency_format_utils_blocks.h delete mode 100644 src/currency_core/currency_format_utils_transactions.cpp delete mode 100644 src/currency_core/currency_format_utils_transactions.h delete mode 100644 src/currency_core/currency_stat_info.h delete mode 100644 src/currency_core/difficulty.cpp delete mode 100644 src/currency_core/difficulty.h delete mode 100644 src/currency_core/dispatch_core_events.h delete mode 100644 src/currency_core/etc_custom_serialization.cpp delete mode 100644 src/currency_core/etc_custom_serialization.h delete mode 100644 src/currency_core/genesis.cpp delete mode 100644 src/currency_core/genesis.h delete mode 100644 src/currency_core/genesis_acc.cpp delete mode 100644 src/currency_core/genesis_acc.h delete mode 100644 src/currency_core/miner.cpp delete mode 100644 src/currency_core/miner.h delete mode 100644 src/currency_core/miner_common.h delete mode 100644 src/currency_core/offers_service_basics.h delete mode 100644 src/currency_core/offers_services_helpers.cpp delete mode 100644 src/currency_core/offers_services_helpers.h delete mode 100644 src/currency_core/scratchpad_helper.cpp delete mode 100644 src/currency_core/scratchpad_helper.h delete mode 100644 src/currency_core/tx_pool.cpp delete mode 100644 src/currency_core/tx_pool.h delete mode 100644 src/currency_core/tx_semantic_validation.cpp delete mode 100644 src/currency_core/tx_semantic_validation.h delete mode 100644 src/currency_core/verification_context.h delete mode 100644 src/currency_protocol/blobdatatype.h delete mode 100644 src/currency_protocol/currency_protocol_defs.h delete mode 100644 src/currency_protocol/currency_protocol_defs_print.h delete mode 100644 src/currency_protocol/currency_protocol_handler.h delete mode 100644 src/currency_protocol/currency_protocol_handler.inl delete mode 100644 src/currency_protocol/currency_protocol_handler_common.h delete mode 100644 src/main.cc delete mode 100644 src/p2p/maintainers_info_boost_serialization.h delete mode 100644 src/p2p/net_node.h delete mode 100644 src/p2p/net_node.inl delete mode 100644 src/p2p/net_node_common.h delete mode 100644 src/p2p/net_peerlist.h delete mode 100644 src/p2p/net_peerlist_boost_serialization.h delete mode 100644 src/p2p/p2p_networks.h delete mode 100644 src/p2p/p2p_protocol_defs.h delete mode 100644 src/rpc/core_rpc_server.cpp delete mode 100644 src/rpc/core_rpc_server.h delete mode 100644 src/rpc/core_rpc_server_commands_defs.h delete mode 100644 src/rpc/core_rpc_server_error_codes.h delete mode 100644 src/rpc/mining_protocol_defs.h delete mode 100644 src/serialization/binary_archive.h delete mode 100644 src/serialization/binary_utils.h delete mode 100644 src/serialization/crypto.h delete mode 100644 src/serialization/debug_archive.h delete mode 100644 src/serialization/json_archive.h delete mode 100644 src/serialization/json_utils.h delete mode 100644 src/serialization/multiprecision.h delete mode 100644 src/serialization/serialization.h delete mode 100644 src/serialization/serialize_basic_types.h delete mode 100644 src/serialization/stl_containers.h delete mode 100644 src/serialization/string.h delete mode 100644 src/serialization/variant.h diff --git a/src/common/atomics_boost_serialization.h b/src/common/atomics_boost_serialization.h deleted file mode 100644 index e9aa979..0000000 --- a/src/common/atomics_boost_serialization.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include - -namespace boost -{ - namespace serialization - { - template - inline void save(Archive &a, const std::atomic &x, const boost::serialization::version_type ver) - { - a << x.load(); - } - - template - inline void load(Archive &a, std::atomic &x, const boost::serialization::version_type ver) - { - value_t s = AUTO_VAL_INIT(s); - a >> s; - x.store(s); - } - template - inline void serialize(Archive &a, std::atomic &x, const boost::serialization::version_type ver) - { - split_free(a, x, ver); - } - } -} diff --git a/src/common/base58.cpp b/src/common/base58.cpp deleted file mode 100644 index 76e277c..0000000 --- a/src/common/base58.cpp +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include - -#include "base58.h" -#include "crypto/hash.h" -#include "int-util.h" -#include "util.h" -#include "varint.h" - -namespace tools -{ - namespace base58 - { - namespace - { - const char alphabet[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - const size_t alphabet_size = sizeof(alphabet) - 1; - const size_t encoded_block_sizes[] = {0, 2, 3, 5, 6, 7, 9, 10, 11}; - const size_t full_block_size = sizeof(encoded_block_sizes) / sizeof(encoded_block_sizes[0]) - 1; - const size_t full_encoded_block_size = encoded_block_sizes[full_block_size]; - const size_t addr_checksum_size = 4; - - struct reverse_alphabet - { - reverse_alphabet() - { - m_data.resize(alphabet[alphabet_size - 1] - alphabet[0] + 1, -1); - - for (size_t i = 0; i < alphabet_size; ++i) - { - size_t idx = static_cast(alphabet[i] - alphabet[0]); - m_data[idx] = static_cast(i); - } - } - - int operator()(char letter) const - { - size_t idx = static_cast(letter - alphabet[0]); - return idx < m_data.size() ? m_data[idx] : -1; - } - - static reverse_alphabet instance; - - private: - std::vector m_data; - }; - - reverse_alphabet reverse_alphabet::instance; - - struct decoded_block_sizes - { - decoded_block_sizes() - { - m_data.resize(encoded_block_sizes[full_block_size] + 1, -1); - for (size_t i = 0; i <= full_block_size; ++i) - { - m_data[encoded_block_sizes[i]] = static_cast(i); - } - } - - int operator()(size_t encoded_block_size) const - { - assert(encoded_block_size <= full_encoded_block_size); - return m_data[encoded_block_size]; - } - - static decoded_block_sizes instance; - - private: - std::vector m_data; - }; - - decoded_block_sizes decoded_block_sizes::instance; - - uint64_t uint_8be_to_64(const uint8_t* data, size_t size) - { - assert(1 <= size && size <= sizeof(uint64_t)); - - uint64_t res = 0; - switch (9 - size) - { - case 1: res |= *data++; BOOST_FALLTHROUGH; - case 2: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 3: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 4: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 5: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 6: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 7: res <<= 8; res |= *data++; BOOST_FALLTHROUGH; - case 8: res <<= 8; res |= *data; break; - default: assert(false); - } - - return res; - } - - void uint_64_to_8be(uint64_t num, size_t size, uint8_t* data) - { - assert(1 <= size && size <= sizeof(uint64_t)); - - uint64_t num_be = SWAP64BE(num); - memcpy(data, reinterpret_cast(&num_be) + sizeof(uint64_t) - size, size); - } - - void encode_block(const char* block, size_t size, char* res) - { - assert(1 <= size && size <= full_block_size); - - uint64_t num = uint_8be_to_64(reinterpret_cast(block), size); - int i = static_cast(encoded_block_sizes[size]) - 1; - while (0 < num) - { - uint64_t remainder = num % alphabet_size; - num /= alphabet_size; - res[i] = alphabet[remainder]; - --i; - } - } - - bool decode_block(const char* block, size_t size, char* res) - { - assert(1 <= size && size <= full_encoded_block_size); - - int res_size = decoded_block_sizes::instance(size); - if (res_size <= 0) - return false; // Invalid block size - - uint64_t res_num = 0; - uint64_t order = 1; - for (size_t i = size - 1; i < size; --i) - { - int digit = reverse_alphabet::instance(block[i]); - if (digit < 0) - return false; // Invalid symbol - - //uint64_t product_hi; - boost::multiprecision::uint128_t tmp = res_num; - tmp += boost::multiprecision::uint128_t(order) * digit; - - if (tmp < res_num || tmp > std::numeric_limits::max() ) - return false; // Overflow - - res_num = tmp.convert_to(); - order *= alphabet_size; // Never overflows, 58^10 < 2^64 - } - - if (static_cast(res_size) < full_block_size && (UINT64_C(1) << (8 * res_size)) <= res_num) - return false; // Overflow - - uint_64_to_8be(res_num, res_size, reinterpret_cast(res)); - - return true; - } - } - - std::string encode(const std::string& data) - { - if (data.empty()) - return std::string(); - - size_t full_block_count = data.size() / full_block_size; - size_t last_block_size = data.size() % full_block_size; - size_t res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size]; - - std::string res(res_size, alphabet[0]); - for (size_t i = 0; i < full_block_count; ++i) - { - encode_block(data.data() + i * full_block_size, full_block_size, &res[i * full_encoded_block_size]); - } - - if (0 < last_block_size) - { - encode_block(data.data() + full_block_count * full_block_size, last_block_size, &res[full_block_count * full_encoded_block_size]); - } - - return res; - } - - bool decode(const std::string& enc, std::string& data) - { - if (enc.empty()) - { - data.clear(); - return true; - } - - size_t full_block_count = enc.size() / full_encoded_block_size; - size_t last_block_size = enc.size() % full_encoded_block_size; - int last_block_decoded_size = decoded_block_sizes::instance(last_block_size); - if (last_block_decoded_size < 0) - return false; // Invalid enc length - size_t data_size = full_block_count * full_block_size + last_block_decoded_size; - - data.resize(data_size, 0); - for (size_t i = 0; i < full_block_count; ++i) - { - if (!decode_block(enc.data() + i * full_encoded_block_size, full_encoded_block_size, &data[i * full_block_size])) - return false; - } - - if (0 < last_block_size) - { - if (!decode_block(enc.data() + full_block_count * full_encoded_block_size, last_block_size, - &data[full_block_count * full_block_size])) - return false; - } - - return true; - } - - std::string encode_addr(uint64_t tag, const std::string& data) - { - std::string buf = get_varint_data(tag); - buf += data; - crypto::hash hash = crypto::cn_fast_hash(buf.data(), buf.size()); - const char* hash_data = reinterpret_cast(&hash); - buf.append(hash_data, addr_checksum_size); - return encode(buf); - } - - bool decode_addr(std::string addr, uint64_t& tag, std::string& data) - { - std::string addr_data; - bool r = decode(addr, addr_data); - if (!r) return false; - if (addr_data.size() <= addr_checksum_size) return false; - - std::string checksum(addr_checksum_size, '\0'); - checksum = addr_data.substr(addr_data.size() - addr_checksum_size); - - addr_data.resize(addr_data.size() - addr_checksum_size); - crypto::hash hash = crypto::cn_fast_hash(addr_data.data(), addr_data.size()); - std::string expected_checksum(reinterpret_cast(&hash), addr_checksum_size); - if (expected_checksum != checksum) return false; - - int read = tools::read_varint(addr_data.begin(), addr_data.end(), tag); - if (read <= 0) return false; - - data = addr_data.substr(read); - return true; - } - } -} diff --git a/src/common/base58.h b/src/common/base58.h deleted file mode 100644 index be09658..0000000 --- a/src/common/base58.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -namespace tools -{ - namespace base58 - { - std::string encode(const std::string& data); - bool decode(const std::string& enc, std::string& data); - - std::string encode_addr(uint64_t tag, const std::string& data); - bool decode_addr(std::string addr, uint64_t& tag, std::string& data); - } -} diff --git a/src/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h deleted file mode 100644 index 5ad68a0..0000000 --- a/src/common/boost_serialization_helper.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - - - - -#define CHECK_PROJECT_NAME() std::string project_name = CURRENCY_NAME; ar & project_name; if(!(project_name == CURRENCY_NAME) ) {throw std::runtime_error(std::string("wrong storage file: project name in file: ") + project_name + ", expected: " + CURRENCY_NAME );} - - -namespace tools -{ - template - bool serialize_obj_to_file(t_object& obj, const std::string& file_path) - { - TRY_ENTRY(); - boost::filesystem::ofstream data_file; - data_file.open( epee::string_encoding::utf8_to_wstring(file_path) , std::ios_base::binary | std::ios_base::out| std::ios::trunc); - if(data_file.fail()) - return false; - - boost::archive::binary_oarchive a(data_file); - a << obj; - - return !data_file.fail(); - CATCH_ENTRY_L0("serialize_obj_to_file: could not serialize into " << file_path, false); - } - - - template - bool serialize_obj_to_buff(t_object& obj, std::string& buff) - { - TRY_ENTRY(); - std::stringstream data_buff; - - boost::archive::binary_oarchive a(data_buff); - a << obj; - buff = data_buff.str(); - return !data_buff.fail(); - CATCH_ENTRY_L0("serialize_obj_to_buff", false); - } - - template - bool portble_serialize_obj_to_stream(t_object& obj, t_stream& stream) - { - TRY_ENTRY(); - - eos::portable_oarchive a(stream); - a << obj; - - return !stream.fail(); - CATCH_ENTRY_L0("portble_serialize_obj_to_stream", false); - } - - template - bool unserialize_obj_from_file(t_object& obj, const std::string& file_path) - { - TRY_ENTRY(); - - boost::filesystem::ifstream data_file; - data_file.open( epee::string_encoding::utf8_to_wstring(file_path), std::ios_base::binary | std::ios_base::in); - if(data_file.fail()) - return false; - boost::archive::binary_iarchive a(data_file); - - a >> obj; - return !data_file.fail(); - CATCH_ENTRY_L0("unserialize_obj_from_file: could not load " << file_path, false); - } - - template - bool unserialize_obj_from_buff(t_object& obj, const std::string& buff) - { - TRY_ENTRY(); - - std::stringstream ss(buff); - boost::archive::binary_iarchive a(ss); - - a >> obj; - return !ss.fail(); - CATCH_ENTRY_L0("unserialize_obj_from_buff", false); - } - - - template - bool portable_unserialize_obj_from_stream(t_object& obj, t_stream& stream) - { - TRY_ENTRY(); - - eos::portable_iarchive a(stream); - - a >> obj; - return !stream.fail(); - CATCH_ENTRY_L0("portable_unserialize_obj_from_stream", false); - } -} diff --git a/src/common/callstack_helper.cpp b/src/common/callstack_helper.cpp deleted file mode 100644 index 74bcc55..0000000 --- a/src/common/callstack_helper.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#if defined(WIN32) - -#define WIN32_LEAN_AND_MEAN 1 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#include -#pragma comment(lib, "psapi.lib") -#pragma comment(lib, "dbghelp.lib") - -#pragma pack( push, before_imagehlp, 8 ) -#include -#pragma pack( pop, before_imagehlp ) - -#include "include_base_utils.h" -#include "callstack_helper.h" - -namespace -{ - struct module_data - { - std::string image_name; - std::string module_name; - void *base_address; - DWORD load_size; - }; - - - class get_mod_info - { - HANDLE process; - static const int buffer_length = 4096; - public: - get_mod_info(HANDLE h) : process(h) {} - - module_data operator()(HMODULE module) - { - module_data ret; - char temp[buffer_length]; - MODULEINFO mi; - - GetModuleInformation(process, module, &mi, sizeof(mi)); - ret.base_address = mi.lpBaseOfDll; - ret.load_size = mi.SizeOfImage; - - GetModuleFileNameEx(process, module, temp, sizeof(temp)); - ret.image_name = temp; - GetModuleBaseName(process, module, temp, sizeof(temp)); - ret.module_name = temp; - std::vector img(ret.image_name.begin(), ret.image_name.end()); - std::vector mod(ret.module_name.begin(), ret.module_name.end()); - SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size); - return ret; - } - }; - - std::string get_symbol_undecorated_name(HANDLE process, DWORD64 address, std::stringstream& ss) - { - SYMBOL_INFO* sym; - static const int max_name_len = 1024; - std::vector sym_buffer(sizeof(SYMBOL_INFO) + max_name_len, '\0'); - sym = (SYMBOL_INFO *)sym_buffer.data(); - sym->SizeOfStruct = sizeof(SYMBOL_INFO); - sym->MaxNameLen = max_name_len; - - DWORD64 displacement; - if (!SymFromAddr(process, address, &displacement, sym)) - return std::string("SymFromAddr failed1: ") + epee::string_tools::num_to_string_fast(GetLastError()); - - if (*sym->Name == '\0') - return std::string("SymFromAddr failed2: ") + epee::string_tools::num_to_string_fast(GetLastError()); - - /* - ss << " SizeOfStruct : " << sym->SizeOfStruct << ENDL; - ss << " TypeIndex : " << sym->TypeIndex << ENDL; // Type Index of symbol - ss << " Index : " << sym->Index << ENDL; - ss << " Size : " << sym->Size << ENDL; - ss << " ModBase : " << sym->ModBase << ENDL; // Base Address of module comtaining this symbol - ss << " Flags : " << sym->Flags << ENDL; - ss << " Value : " << sym->Value << ENDL; // Value of symbol, ValuePresent should be 1 - ss << " Address : " << sym->Address << ENDL; // Address of symbol including base address of module - ss << " Register : " << sym->Register << ENDL; // register holding value or pointer to value - ss << " Scope : " << sym->Scope << ENDL; // scope of the symbol - ss << " Tag : " << sym->Tag << ENDL; // pdb classification - ss << " NameLen : " << sym->NameLen << ENDL; // Actual length of name - ss << " MaxNameLen : " << sym->MaxNameLen << ENDL; - ss << " Name[1] : " << &sym->Name << ENDL; // Name of symbol - */ - - std::string und_name(max_name_len, '\0'); - DWORD chars_written = UnDecorateSymbolName(sym->Name, &und_name.front(), max_name_len, UNDNAME_COMPLETE); - und_name.resize(chars_written); - return und_name; - } - -} // namespace - -namespace tools -{ - - std::string get_callstack_win_x64() - { - // @TODO@ - // static epee::static_helpers::wrapper cs; - static std::recursive_mutex cs; - std::lock_guard lock(cs); - - HANDLE h_process = GetCurrentProcess(); - HANDLE h_thread = GetCurrentThread(); - - PCSTR user_search_path = NULL; // may be path to a pdb? - if (!SymInitialize(h_process, user_search_path, false)) - return ""; - - DWORD sym_options = SymGetOptions(); - sym_options |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; - SymSetOptions(sym_options); - - DWORD cb_needed; - std::vector module_handles(1); - EnumProcessModules(h_process, &module_handles[0], static_cast(module_handles.size() * sizeof(HMODULE)), &cb_needed); - module_handles.resize(cb_needed / sizeof(HMODULE)); - EnumProcessModules(h_process, &module_handles[0], static_cast(module_handles.size() * sizeof(HMODULE)), &cb_needed); - - std::vector modules; - std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(h_process)); - void *base = modules[0].base_address; - - CONTEXT context; - memset(&context, 0, sizeof context); - RtlCaptureContext( &context ); - - STACKFRAME64 frame; - memset(&frame, 0, sizeof frame); - frame.AddrPC.Offset = context.Rip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrStack.Offset = context.Rsp; - frame.AddrStack.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context.Rbp; - frame.AddrFrame.Mode = AddrModeFlat; - - IMAGEHLP_LINE64 line = { 0 }; - line.SizeOfStruct = sizeof line; - IMAGE_NT_HEADERS *image_nt_header = ImageNtHeader(base); - - std::stringstream ss; - ss << ENDL; - // ss << "main module loaded at 0x" << std::hex << std::setw(16) << std::setfill('0') << base << std::dec << " from " << modules[0].image_name << ENDL; - for (size_t n = 0; n < 250; ++n) - { - if (!StackWalk64(image_nt_header->FileHeader.Machine, h_process, h_thread, &frame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) - break; - if (frame.AddrReturn.Offset == 0) - break; - - std::string fnName = get_symbol_undecorated_name(h_process, frame.AddrPC.Offset, ss); - ss << "0x" << std::setw(16) << std::setfill('0') << std::hex << frame.AddrPC.Offset << " " << std::dec << fnName; - DWORD offset_from_line = 0; - if (SymGetLineFromAddr64(h_process, frame.AddrPC.Offset, &offset_from_line, &line)) - ss << "+" << offset_from_line << " " << line.FileName << "(" << line.LineNumber << ")"; - - for (auto el : modules) - { - if ((DWORD64)el.base_address <= frame.AddrPC.Offset && frame.AddrPC.Offset < (DWORD64)el.base_address + (DWORD64)el.load_size) - { - ss << " : " << el.module_name << " @ 0x" << std::setw(0) << std::hex << (DWORD64)el.base_address << ENDL; - break; - } - } - - } - SymCleanup(h_process); - - return ss.str(); - } - -} // namespace tools - -#endif // #if defined(WIN32) diff --git a/src/common/callstack_helper.h b/src/common/callstack_helper.h deleted file mode 100644 index 3853d14..0000000 --- a/src/common/callstack_helper.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#pragma once -#include - -namespace tools -{ -#if defined(WIN32) - extern std::string get_callstack_win_x64(); -#endif - - inline std::string get_callstack() - { -#if defined(__GNUC__) - return epee::misc_utils::print_trace_default(); -#elif defined(WIN32) - return get_callstack_win_x64(); -#else - return ""; -#endif - } - -} // namespace tools diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp deleted file mode 100644 index 92a59b6..0000000 --- a/src/common/command_line.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#include "command_line.h" -#include "currency_core/currency_config.h" - -namespace command_line -{ - const arg_descriptor arg_help = {"help", "Produce help message"}; - const arg_descriptor arg_version = {"version", "Output version information"}; - const arg_descriptor arg_data_dir = {"data-dir", "Specify data directory", ""}; - - const arg_descriptor arg_stop_after_height = { "stop-after-height", "If specified, the daemon will stop immediately after a block with the given height is added", 0 }; - - const arg_descriptor arg_config_file = { "config-file", "Specify configuration file", std::string(CURRENCY_NAME_SHORT ".conf") }; - const arg_descriptor arg_os_version = { "os-version", "" }; - - const arg_descriptor arg_log_dir = { "log-dir", "", "", true}; - const arg_descriptor arg_log_file = { "log-file", "", "" }; - const arg_descriptor arg_log_level = { "log-level", "", LOG_LEVEL_0, true }; - - const arg_descriptor arg_console = { "no-console", "Disable daemon console commands" }; - const arg_descriptor arg_show_details = { "currency-details", "Display currency details" }; - const arg_descriptor arg_show_rpc_autodoc = { "show_rpc_autodoc", "Display rpc auto-generated documentation template" }; - - const arg_descriptor arg_disable_upnp = { "disable-upnp", "Disable UPnP (enhances local network privacy)", false, true }; - - const arg_descriptor arg_disable_stop_if_time_out_of_sync = { "disable-stop-if-time-out-of-sync", "Do not stop the daemon if serious time synchronization problem is detected", false, true }; - const arg_descriptor arg_disable_stop_on_low_free_space = { "disable-stop-on-low-free-space", "Do not stop the daemon if free space at data dir is critically low", false, true }; - const arg_descriptor arg_enable_offers_service = { "enable-offers-service", "Enables marketplace feature", false, false}; - const arg_descriptor arg_db_engine = { "db-engine", "Specify database engine for storage. May be \"lmdb\"(default) or \"mdbx\"", ARG_DB_ENGINE_LMDB, false }; - - const arg_descriptor arg_no_predownload = { "no-predownload", "Do not pre-download blockchain database", }; - const arg_descriptor arg_force_predownload = { "force-predownload", "Pre-download blockchain database regardless of it's status", }; - const arg_descriptor arg_validate_predownload = { "validate-predownload", "Paranoid mode, re-validate each block from pre-downloaded database and rebuild own database", }; - const arg_descriptor arg_predownload_link = { "predownload-link", "Override url for blockchain database pre-downloading", "", true }; - -} diff --git a/src/common/command_line.h b/src/common/command_line.h deleted file mode 100644 index ee7985c..0000000 --- a/src/common/command_line.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -#include -#include -#include -#include "include_base_utils.h" - -namespace command_line -{ - template - struct arg_descriptor; - - template - struct arg_descriptor - { - typedef T value_type; - arg_descriptor(const char* _name, const char* _description): - name(_name), - description(_description), - not_use_default(true), - default_value(T()) - {} - arg_descriptor(const char* _name, const char* _description, const T& default_val) : - name(_name), - description(_description), - not_use_default(false), - default_value(default_val) - {} - arg_descriptor(const char* _name, const char* _description, const T& default_val, bool not_use_default) : - name(_name), - description(_description), - default_value(default_val), - not_use_default(not_use_default) - {} - - - const char* name; - const char* description; - T default_value; - bool not_use_default; - }; - - template - struct arg_descriptor, false> - { - typedef std::vector value_type; - - const char* name; - const char* description; - }; - - template - struct arg_descriptor - { - static_assert(!std::is_same::value, "Boolean switch can't be required"); - - typedef T value_type; - - const char* name; - const char* description; - }; - - template - boost::program_options::typed_value* make_semantic(const arg_descriptor& /*arg*/) - { - return boost::program_options::value()->required(); - } - - template - boost::program_options::typed_value* make_semantic(const arg_descriptor& arg) - { - auto semantic = boost::program_options::value(); - if (!arg.not_use_default) - semantic->default_value(arg.default_value); - return semantic; - } - - template - boost::program_options::typed_value* make_semantic(const arg_descriptor& arg, const T& def) - { - auto semantic = boost::program_options::value(); - if (!arg.not_use_default) - semantic->default_value(def); - return semantic; - } - - template - boost::program_options::typed_value, char>* make_semantic(const arg_descriptor, false>& /*arg*/) - { - auto semantic = boost::program_options::value< std::vector >(); - semantic->default_value(std::vector(), ""); - return semantic; - } - - template - void add_arg(boost::program_options::options_description& description, const arg_descriptor& arg, bool unique = true) - { - if (0 != description.find_nothrow(arg.name, false)) - { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); - return; - } - - description.add_options()(arg.name, make_semantic(arg), arg.description); - } - - template - void add_arg(boost::program_options::options_description& description, const arg_descriptor& arg, const T& def, bool unique = true) - { - if (0 != description.find_nothrow(arg.name, false)) - { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); - return; - } - - description.add_options()(arg.name, make_semantic(arg, def), arg.description); - } - - template<> - inline void add_arg(boost::program_options::options_description& description, const arg_descriptor& arg, bool unique) - { - if (0 != description.find_nothrow(arg.name, false)) - { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); - return; - } - - description.add_options()(arg.name, boost::program_options::bool_switch(), arg.description); - } - - template - boost::program_options::basic_parsed_options parse_command_line(int argc, const charT* const argv[], - const boost::program_options::options_description& desc, bool allow_unregistered = false) - { - auto parser = boost::program_options::basic_command_line_parser(argc, argv); - parser.options(desc); - if (allow_unregistered) - { - parser.allow_unregistered(); - } - return parser.run(); - } - - template - bool handle_error_helper(const boost::program_options::options_description& desc, std::string& err, F parser) - { - try - { - return parser(); - } - catch (std::exception& e) - { - err = e.what(); - std::cerr << "Failed to parse arguments: " << e.what() << std::endl; - std::cerr << desc << std::endl; - return false; - } - catch (...) - { - std::cerr << "Failed to parse arguments: unknown exception" << std::endl; - std::cerr << desc << std::endl; - return false; - } - } - - template - bool handle_error_helper(const boost::program_options::options_description& desc, F parser) - { - std::string stub_err; - return handle_error_helper(desc, stub_err, parser); - } - - template - bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) - { - auto value = vm[arg.name]; - return !value.empty(); - } - - - template - T get_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) - { - return vm[arg.name].template as(); - } - - template<> - inline bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) - { - return get_arg(vm, arg); - } - -#define ARG_DB_ENGINE_LMDB "lmdb" -#define ARG_DB_ENGINE_MDBX "mdbx" - - - extern const arg_descriptor arg_help; - extern const arg_descriptor arg_version; - extern const arg_descriptor arg_data_dir; - extern const arg_descriptor arg_stop_after_height; - extern const arg_descriptor arg_config_file; - extern const arg_descriptor arg_os_version; - extern const arg_descriptor arg_log_dir; - extern const arg_descriptor arg_log_file; - extern const arg_descriptor arg_log_level; - extern const arg_descriptor arg_console; - extern const arg_descriptor arg_show_details; - extern const arg_descriptor arg_show_rpc_autodoc; - extern const arg_descriptor arg_disable_upnp; - extern const arg_descriptor arg_disable_stop_if_time_out_of_sync; - extern const arg_descriptor arg_disable_stop_on_low_free_space; - extern const arg_descriptor arg_enable_offers_service; - extern const arg_descriptor arg_db_engine; - extern const arg_descriptor arg_no_predownload; - extern const arg_descriptor arg_force_predownload; - extern const arg_descriptor arg_validate_predownload; - extern const arg_descriptor arg_predownload_link; -} diff --git a/src/common/config_encrypt_helper.h b/src/common/config_encrypt_helper.h deleted file mode 100644 index c2208c7..0000000 --- a/src/common/config_encrypt_helper.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014-2020 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "wallet/view_iface.h" - - -namespace tools -{ - -#pragma pack(push, 1) - struct app_data_file_binary_header - { - uint64_t m_signature; - uint64_t m_cb_body; - }; -#pragma pack (pop) - - inline - std::string load_encrypted_file(const std::string& path, const std::string& key, std::string& body, uint64_t signature) - { - std::string app_data_buff; - bool r = epee::file_io_utils::load_file_to_string(path, app_data_buff); - if (!r) - { - return API_RETURN_CODE_NOT_FOUND; - } - - if (app_data_buff.size() < sizeof(app_data_file_binary_header)) - { - LOG_ERROR("app_data_buff.size()(" << app_data_buff.size() << ") < sizeof(app_data_file_binary_header) (" << sizeof(app_data_file_binary_header) << ") check failed while loading from " << path); - return API_RETURN_CODE_INVALID_FILE; - } - - crypto::chacha_crypt(app_data_buff, key); - - const app_data_file_binary_header* phdr = reinterpret_cast(app_data_buff.data()); - if (phdr->m_signature != signature) - { - return API_RETURN_CODE_WRONG_PASSWORD; - } - body = app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str(); - return API_RETURN_CODE_OK; - } - inline - std::string store_encrypted_file(const std::string& path, const std::string& key, const std::string& body, uint64_t signature) - { - std::string buff(sizeof(app_data_file_binary_header), 0); - app_data_file_binary_header* phdr = (app_data_file_binary_header*)buff.data(); - phdr->m_signature = signature; - phdr->m_cb_body = 0; // for future use - - buff.append(body); - crypto::chacha_crypt(buff, key); - - bool r = epee::file_io_utils::save_string_to_file(path, buff); - if (r) - return API_RETURN_CODE_OK; - else - return API_RETURN_CODE_FAIL; - } - -} \ No newline at end of file diff --git a/src/common/crypto_boost_serialization.h b/src/common/crypto_boost_serialization.h deleted file mode 100644 index 310c8e9..0000000 --- a/src/common/crypto_boost_serialization.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "crypto/crypto.h" - -namespace boost -{ - namespace serialization - { - //--------------------------------------------------- - template - inline void serialize(Archive &a, crypto::public_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::secret_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::key_derivation &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::key_image &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - - template - inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - template - inline void serialize(Archive &a, crypto::hash &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast(x); - } - } -} - -//} diff --git a/src/common/crypto_stream_operators.cpp b/src/common/crypto_stream_operators.cpp deleted file mode 100644 index cc87dd3..0000000 --- a/src/common/crypto_stream_operators.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto_stream_operators.h" - -bool parse_hash256(const std::string str_hash, crypto::hash& hash) -{ - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(crypto::hash)) - { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; - return false; - } - - buf.copy(reinterpret_cast(&hash), sizeof(crypto::hash)); - return true; -} diff --git a/src/common/crypto_stream_operators.h b/src/common/crypto_stream_operators.h deleted file mode 100644 index fa2531d..0000000 --- a/src/common/crypto_stream_operators.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include "include_base_utils.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "crypto/RIPEMD160_helper.h" - -bool parse_hash256(const std::string str_hash, crypto::hash& hash); - -template -std::ostream &print_t(std::ostream &o, const T &v) -{ - return o << "" << epee::string_tools::pod_to_hex(v) << ""; -} - - -template -std::ostream &print16(std::ostream &o, const T &v) -{ - return o << "" << epee::string_tools::pod_to_hex(v).substr(0, 5) << ".."; -} - -template -std::string print16(const T &v) -{ - return std::string("") + epee::string_tools::pod_to_hex(v).substr(0, 5) + ".."; -} - - -namespace crypto -{ - inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print_t(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash160 &v) { return print_t(o, v); } -} // namespace crypto diff --git a/src/common/db_abstract_accessor.h b/src/common/db_abstract_accessor.h deleted file mode 100644 index 71be14f..0000000 --- a/src/common/db_abstract_accessor.h +++ /dev/null @@ -1,1102 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include -#include "include_base_utils.h" - -#include "db_backend_base.h" -#include "misc_language.h" -#include "cache_helper.h" -#include "profile_tools.h" -#include "../serialization/serialization.h" -#include "readwrite_lock.h" -#include "math_helper.h" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "db" -// 'db' channel is disabled by default - -namespace tools -{ - namespace db - { - template - const char* key_to_ptr(const t_pod_key& k, size_t& s) - { - static_assert(std::is_pod::value, "t_pod_key must be a POD type."); - s = sizeof(k); - return reinterpret_cast(&k); - } - inline - const char* key_to_ptr(const std::string& k, size_t& s) - { - s = k.size(); - return k.data(); - } - template - void key_from_ptr(t_pod_key& k, const void* pkey, uint64_t ks) - { - static_assert(std::is_pod::value, "t_pod_key must be a POD type."); - CHECK_AND_ASSERT_THROW_MES(sizeof(t_pod_key) == ks, "size missmatch"); - CHECK_AND_ASSERT_THROW_MES(pkey, "wrog ptr(null)"); - k = *(t_pod_key*)pkey; - } - inline - void key_from_ptr(std::string& k, const void* pkey, uint64_t ks) - { - CHECK_AND_ASSERT_THROW_MES(pkey, "wrog ptr(null)"); - k.assign((const char*)pkey, static_cast(ks)); - } - - struct i_db_parent_to_container_callabck - { - virtual bool on_write_transaction_begin(){ return true; } - virtual bool on_write_transaction_commit(){ return true; } - virtual bool on_write_transaction_abort(){ return true; } - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class basic_db_accessor - { - std::shared_ptr m_backend; - epee::critical_section m_binded_containers_lock; - std::set m_binded_containers; - - epee::critical_section m_transactions_stack_lock; - std::map > m_transactions_stack; - std::atomic m_is_open; - epee::shared_recursive_mutex& m_rwlock; - public: - struct performance_data - { - epee::math_helper::average backend_set_pod_time; - epee::math_helper::average backend_set_t_time; - epee::math_helper::average set_serialize_t_time; - epee::math_helper::average backend_get_pod_time; - epee::math_helper::average backend_get_t_time; - epee::math_helper::average get_serialize_t_time; - }; - private: - mutable performance_data m_gperformance_data; - mutable std::unordered_map m_performance_data_map; - public: - basic_db_accessor(std::shared_ptr backend, epee::shared_recursive_mutex& rwlock) - : m_backend(backend), m_rwlock(rwlock), m_is_open(false) - { - } - - ~basic_db_accessor() - { - close(); - } - void reset_backend(std::shared_ptr backend) { m_backend = backend; } - performance_data& get_performance_data_for_handle(container_handle h) const { return m_performance_data_map[h]; } - performance_data& get_performance_data_global() const { return m_gperformance_data; } - - - bool bind_parent_container(i_db_parent_to_container_callabck* pcontainer) - { - CRITICAL_REGION_LOCAL(m_binded_containers_lock); - m_binded_containers.insert(pcontainer); - return true; - } - - bool unbind_parent_container(i_db_parent_to_container_callabck* pcontainer) - { - CRITICAL_REGION_LOCAL(m_binded_containers_lock); - auto it = m_binded_containers.find(pcontainer); - CHECK_AND_ASSERT_THROW_MES(it != m_binded_containers.end(), "Unable to unbind pointer"); - m_binded_containers.erase(it); - return true; - } - bool has_writer_tx_in_stack(const std::vector& ve) - { - for (auto v : ve) - { - if (!v) - return true; - } - return false; - } - bool begin_transaction(bool readonly = false) - { - bool r = m_backend->begin_transaction(readonly); - CRITICAL_REGION_LOCAL(m_transactions_stack_lock); - std::vector& this_thread_tx_stack = m_transactions_stack[std::this_thread::get_id()]; - - if (r) - { - bool need_to_brodcst_writer_tx = !has_writer_tx_in_stack(this_thread_tx_stack); - this_thread_tx_stack.push_back(readonly); - if (need_to_brodcst_writer_tx && !readonly) - { - LOG_PRINT_CYAN("[WRITE_TX_BEGIN]", LOG_LEVEL_2); - for (auto cnt_ptr : m_binded_containers) - { - cnt_ptr->on_write_transaction_begin(); - } - } - } - return r; - } - - bool begin_readonly_transaction()const - { - return const_cast(*this).begin_transaction(true); - } - - void commit_transaction()const - { - return const_cast(*this).commit_transaction(); - } - void commit_transaction() - { - bool r = false; - bool is_writer_tx = false; - { - CRITICAL_REGION_LOCAL(m_transactions_stack_lock); - std::vector& this_thread_tx_stack = m_transactions_stack[std::this_thread::get_id()]; - CHECK_AND_ASSERT_THROW_MES(this_thread_tx_stack.size(), "Internal error: this_thread_tx_stack.size = 0 at commit tx"); - is_writer_tx = !this_thread_tx_stack.back(); - } - - if (is_writer_tx) - m_rwlock.lock(); // wait all readers and writers to get exclusive access - - { - CRITICAL_REGION_LOCAL(m_transactions_stack_lock); - r = m_backend->commit_transaction(); //commit first and then switch cache isolation off (via on_write_transaction_commit() below) - - std::vector& this_thread_tx_stack = m_transactions_stack[std::this_thread::get_id()]; - CHECK_AND_ASSERT_THROW_MES(this_thread_tx_stack.size(), "Internal error: this_thread_tx_stack.size = 0 at commit tx"); - CHECK_AND_ASSERT_THROW_MES(!this_thread_tx_stack.back() == is_writer_tx, "Internal error: !this_thread_tx_stack.back() != is_writer_tx at commit tx"); - this_thread_tx_stack.pop_back(); - bool has_other_writers_on_stack = has_writer_tx_in_stack(this_thread_tx_stack); - if (is_writer_tx && !has_other_writers_on_stack) - { - LOG_PRINT_CYAN("[WRITE_TX_COMMIT]", LOG_LEVEL_2); - for (auto cnt_ptr : m_binded_containers) - { - cnt_ptr->on_write_transaction_commit(); // will cause cache isolation to be switched off - } - } - } - - if (is_writer_tx) - m_rwlock.unlock();//manual unlock - - CHECK_AND_ASSERT_THROW_MES(r, "failed to commit tx"); - } - void abort_transaction() - { - bool is_writer_tx = false; - { - CRITICAL_REGION_LOCAL(m_transactions_stack_lock); - std::vector& this_thread_tx_stack = m_transactions_stack[std::this_thread::get_id()]; - CHECK_AND_ASSERT_THROW_MES(this_thread_tx_stack.size(), "Internal error: this_thread_tx_stack.size = 0 at abort tx"); - CHECK_AND_ASSERT_THROW_MES(!this_thread_tx_stack.back(), "Internal error: abort on readonly tx"); - is_writer_tx = !this_thread_tx_stack.back(); - } - if (is_writer_tx) - m_rwlock.lock(); // wait all readers and writers to get exclusive access - - { - CRITICAL_REGION_LOCAL(m_transactions_stack_lock); - m_backend->abort_transaction(); // abort first and then switch cache isolation off (via on_write_transaction_abort() below) - - std::vector& this_thread_tx_stack = m_transactions_stack[std::this_thread::get_id()]; - CHECK_AND_ASSERT_THROW_MES(this_thread_tx_stack.size(), "Internal error: this_thread_tx_stack.size = 0 at abort tx"); - CHECK_AND_ASSERT_THROW_MES(!this_thread_tx_stack.back(), "Internal error: abort on readonly tx"); - this_thread_tx_stack.pop_back(); - bool has_other_writers_on_stack = has_writer_tx_in_stack(this_thread_tx_stack); - if (!has_other_writers_on_stack) - { - LOG_PRINT_CYAN("[WRITE_TX_ABORT]", LOG_LEVEL_2); - for (auto cnt_ptr : m_binded_containers) - { - cnt_ptr->on_write_transaction_abort(); // will cause cache isolation to be switched off - } - } - } - - if (is_writer_tx) - m_rwlock.unlock();//manual unlock - - } - - - std::shared_ptr get_backend() const - { - return m_backend; - } - - bool close() - { - m_is_open = false; - if (!m_backend) - return true; - return m_backend->close(); - } - - bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) - { - bool r = m_backend->open(path, cache_sz); - if(r) - m_is_open = true; - - return r; - } - - bool is_open() - { - return m_is_open; - } - - uint64_t size(container_handle h) const - { - return m_backend->size(h); - } - - template - bool erase(container_handle h, const t_pod_key& k) - { - //TRY_ENTRY(); - size_t sk = 0; - const char* pk = key_to_ptr(k, sk); - - return m_backend->erase(h, pk, sk); - //CATCH_ENTRY_L0("get_t_object_from_db", false); - } - - template - bool get_t_object(container_handle h, const t_pod_key& k, t_object& obj) const - { - performance_data& m_performance_data = m_gperformance_data; - //TRY_ENTRY(); - std::string res_buff; - size_t sk = 0; - const char* pk = key_to_ptr(k, sk); - - TIME_MEASURE_START_PD(backend_get_t_time); - if (!m_backend->get(h, pk, sk, res_buff)) - return false; - TIME_MEASURE_FINISH_PD(backend_get_t_time); - - - TIME_MEASURE_START_PD(get_serialize_t_time); - bool res = t_unserializable_object_from_blob(obj, res_buff); - TIME_MEASURE_FINISH_PD(get_serialize_t_time); - - return res; - //CATCH_ENTRY_L0("get_t_object_from_db", false); - } - - bool clear(container_handle h) - { - return m_backend->clear(h); - } - - template - bool set_t_object(container_handle h, const t_pod_key& k, t_object& obj) - { - performance_data& m_performance_data = m_performance_data_map[h]; - //TRY_ENTRY(); - std::string obj_buff; - TIME_MEASURE_START_PD(set_serialize_t_time); - ::t_serializable_object_to_blob(obj, obj_buff); - TIME_MEASURE_FINISH_PD(set_serialize_t_time); - - size_t sk = 0; - const char* pk = key_to_ptr(k, sk); - TIME_MEASURE_START_PD(backend_set_t_time); - bool r = m_backend->set(h, pk, sk, obj_buff.data(), obj_buff.size()); - TIME_MEASURE_FINISH_PD(backend_set_t_time); - return r; - //CATCH_ENTRY_L0("set_t_object_to_db", false); - } - - template - bool get_pod_object(container_handle h, const t_pod_key& k, t_pod_object& obj) const - { - static_assert(std::is_pod::value, "t_pod_object must be a POD type."); - performance_data& m_performance_data = m_gperformance_data; - - //TRY_ENTRY(); - std::string res_buff; - size_t sk = 0; - const char* pk = key_to_ptr(k, sk); - - TIME_MEASURE_START_PD(backend_get_pod_time); - if (!m_backend->get(h, pk, sk, res_buff)) - return false; - TIME_MEASURE_FINISH_PD(backend_get_pod_time); - - - CHECK_AND_ASSERT_MES(sizeof(t_pod_object) == res_buff.size(), false, "sizes missmath at get_pod_object_from_db(). returned size = " - << res_buff.size() << "expected: " << sizeof(t_pod_object)); - - obj = *(t_pod_object*)res_buff.data(); - return true; - //CATCH_ENTRY_L0("get_t_object_from_db", false); - } - - template - bool set_pod_object(container_handle h, const t_pod_key& k, const t_pod_object& obj) - { - performance_data& m_performance_data = m_performance_data_map[h]; - static_assert(std::is_pod::value, "t_pod_object must be a POD type."); - size_t sk = 0; - const char* pk = key_to_ptr(k, sk); - - TIME_MEASURE_START_PD(backend_set_pod_time); - bool r = m_backend->set(h, pk, sk, (const char*)&obj, sizeof(obj)); - TIME_MEASURE_FINISH_PD(backend_set_pod_time); - if (!r) - return false; - - return true; - //CATCH_ENTRY_L0("get_t_object_from_db", false); - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class key_value_pod_access_strategy - { - public: - template - static bool from_buff_to_obj(const void* pv, uint64_t vs, t_value& v) - { - CHECK_AND_ASSERT_THROW_MES(sizeof(t_value) == vs, "sizes missmath at get_pod_object_from_db(). returned size = " - << vs << "expected: " << sizeof(t_value)); - - v = *(t_value*)pv; - - return true; - } - - template - static void set(container_handle h, basic_db_accessor& bdb, const t_key& k, const t_value& v) - { - static_assert(std::is_pod::value, "t_value must be a POD type."); - bdb.set_pod_object(h, k, v); - } - template - static std::shared_ptr get(container_handle h, basic_db_accessor& bdb, const t_key& k) - { - static_assert(std::is_pod::value, "t_value must be a POD type."); - std::shared_ptr res(nullptr); - t_value v = AUTO_VAL_INIT(v); - if (bdb.get_pod_object(h, k, v)) - { - //TODO: remove one extra copy - res.reset(new t_value(v)); - } - return res; - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class key_value_t_access_strategy - { - public: - template - static bool from_buff_to_obj(const void* pv, uint64_t vs, t_value& v) - { - std::string src_blob((const char*)pv, static_cast(vs)); - return t_unserializable_object_from_blob(v, src_blob);//::t_serializable_object_to_blob(v, res_buff); - } - - - - template - static void set(container_handle h, basic_db_accessor& bdb, const t_key& k, const t_value& v) - { - bdb.set_t_object(h, k, v); - } - template - static std::shared_ptr get(container_handle h, basic_db_accessor& bdb, const t_key& k) - { - std::shared_ptr res(nullptr); - t_value v = AUTO_VAL_INIT(v); - if (bdb.get_t_object(h, k, v)) - { - //TODO: remove one extra copy - res.reset(new t_value(v)); - } - return res; - } - }; - - /****************************************************************************************/ - /* to make easier selecting of strategy by true/false instead of long type definition */ - /****************************************************************************************/ - template - class access_strategy_selector; - - template<> - class access_strategy_selector: public key_value_t_access_strategy - {}; - - template<> - class access_strategy_selector: public key_value_pod_access_strategy - {}; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct keys_accessor_cb : i_db_callback - { - t_cb m_cb; - keys_accessor_cb(t_cb cb) :m_cb(cb){} - bool on_enum_item(uint64_t i, const void* pkey, uint64_t ks, const void* pval, uint64_t vs) - { - t_key k = AUTO_VAL_INIT(k); - key_from_ptr(k, pkey, ks); - return m_cb(i, k); - } - }; - - template - struct items_accessor_cb : i_db_callback - { - t_cb m_cb; - items_accessor_cb(t_cb cb) :m_cb(cb){} - bool on_enum_item(uint64_t i, const void* pkey, uint64_t ks, const void* pval, uint64_t vs) - { - t_key k = AUTO_VAL_INIT(k); - t_value v = AUTO_VAL_INIT(v); - key_from_ptr(k, pkey, ks); - t_value_read_strategy::from_buff_to_obj(pval, vs, v); - return m_cb(i, k, v); - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class basic_key_value_accessor : public i_db_parent_to_container_callabck - { -#ifdef ENABLE_PROFILING - mutable epee::profile_tools::local_call_account m_get_profiler; - mutable epee::profile_tools::local_call_account m_set_profiler; - mutable epee::profile_tools::local_call_account m_explicit_get_profiler; - mutable epee::profile_tools::local_call_account m_explicit_set_profiler; - mutable epee::profile_tools::local_call_account m_commit_profiler; -#endif - mutable uint64_t size_cache; - mutable bool size_cache_valid; - protected: - container_handle m_h; - basic_db_accessor& bdb; - epee::misc_utils::isolation_lock m_isolation; - public: - typedef t_value t_value_type; - - basic_key_value_accessor(basic_db_accessor& db) : - bdb(db), - m_h(AUTO_VAL_INIT(m_h)), - size_cache(0), - size_cache_valid(false) - { - db.bind_parent_container(this); - } - - ~basic_key_value_accessor() - { - TRY_ENTRY(); - bdb.unbind_parent_container(this); - CATCH_ALL_DO_NOTHING(); - } - - virtual bool on_write_transaction_begin() - { - m_isolation.set_isolation_mode(); - return true; - } - virtual bool on_write_transaction_commit() - { - m_isolation.reset_isolation_mode(); - return true; - } - virtual bool on_write_transaction_abort() - { - m_isolation.reset_isolation_mode(); - return true; - } - - bool begin_transaction(bool read_only = false) - { - return bdb.begin_transaction(read_only); - } - void commit_transaction() - { - try - { - PROFILE_FUNC_ACC(m_commit_profiler); - bdb.commit_transaction(); - } - catch (...) - { - size_cache_valid = false; - throw; - } - } - void abort_transaction() - { - size_cache_valid = false; - bdb.abort_transaction(); - } - - bool init(const std::string& container_name) - { -#ifdef ENABLE_PROFILING - m_get_profiler.m_name = container_name +":get"; - m_set_profiler.m_name = container_name + ":set"; - m_explicit_get_profiler.m_name = container_name + ":explicit_get"; - m_explicit_set_profiler.m_name = container_name + ":explicit_set"; - m_commit_profiler.m_name = container_name + ":commit"; -#endif - return bdb.get_backend()->open_container(container_name, m_h); - } - - bool deinit() - { -#ifdef ENABLE_PROFILING - m_get_profiler.m_name = ""; - m_set_profiler.m_name = ""; - m_explicit_get_profiler.m_name = ""; - m_explicit_set_profiler.m_name = ""; - m_commit_profiler.m_name = ""; -#endif - bool r = true; - if (m_h) - r = bdb.get_backend()->close_container(m_h); - m_h = AUTO_VAL_INIT(m_h); - size_cache = 0; - size_cache_valid = false; - return r; - } - - template - void enumerate_keys(t_cb cb) const - { - keys_accessor_cb local_enum_handler(cb); - bdb.get_backend()->enumerate(m_h, &local_enum_handler); - } - - template - void enumerate_items(t_cb cb)const - { - items_accessor_cb > local_enum_handler(cb); - bdb.get_backend()->enumerate(m_h, &local_enum_handler); - } - - template - void explicit_set(const t_explicit_key& k, const t_explicit_value& v) - { - PROFILE_FUNC_ACC(m_explicit_set_profiler); - size_cache_valid = false; - t_strategy::set(m_h, bdb, k, v); - } - - template - std::shared_ptr explicit_get(const t_explicit_key& k) - { - PROFILE_FUNC_ACC(m_explicit_get_profiler); - return t_strategy::template get(m_h, bdb, k); - } - - void set(const t_key& k, const t_value& v) - { - PROFILE_FUNC_ACC(m_set_profiler); - size_cache_valid = false; - access_strategy_selector::set(m_h, bdb, k, v); - } - - std::shared_ptr get(const t_key& k) const - { - PROFILE_FUNC_ACC(m_get_profiler); - return access_strategy_selector::template get(m_h, bdb, k); - } - - //find() and end() aliases for make easier porting std stuff - std::shared_ptr find(const t_key& k) const - { - return get(k); - } - - std::shared_ptr end() const - { - return std::shared_ptr(nullptr); - } - - uint64_t size() const - { - return m_isolation.isolated_access([&](bool allowed_cache) - { - if (allowed_cache && size_cache_valid) - { - return size_cache; - } - else - { - uint64_t res = bdb.size(m_h); - if (allowed_cache) - { - size_cache = res; - size_cache_valid = true; - } - return res; - } - }); - } - uint64_t size_no_cache() const - { - return bdb.size(m_h); - } - - bool clear() - { - bool result = bdb.clear(m_h); - m_isolation.isolated_write_access([&](){ - size_cache_valid = false; - return true; - }); - return result; - } - - bool erase_validate(const t_key& k) - { - bool result = bdb.erase(m_h, k); - m_isolation.isolated_write_access([&](){ - size_cache_valid = false; - return true; - }); - return result; - } - - void erase(const t_key& k) - { - bdb.erase(m_h, k); - m_isolation.isolated_write_access([&](){ - size_cache_valid = false; - return true; - }); - } - - std::shared_ptr operator[] (const t_key& k) const - { - auto r = this->get(k); - CHECK_AND_ASSERT_THROW(r.get(), std::out_of_range("Out of range in basic_key_value_accessor")); - return r; - } - }; - - - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class cached_key_value_accessor : public basic_key_value_accessor - { - typedef basic_key_value_accessor base_class; - - - typedef epee::misc_utils::cache_with_write_isolation, 10000> cache_container_type; - //typedef epee::misc_utils::cache_dummy, 100000> cache_container_type; - mutable cache_container_type m_cache; - - - virtual bool on_write_transaction_abort() - { - clear_cache(); - return base_class::on_write_transaction_abort(); - } - - public: - struct performance_data - { - epee::math_helper::average hit_percent; - epee::math_helper::average read_cache_microsec; - epee::math_helper::average read_db_microsec; - epee::math_helper::average update_cache_microsec; - epee::math_helper::average write_to_cache_microsec; - epee::math_helper::average write_to_db_microsec; - }; - - cached_key_value_accessor(basic_db_accessor& db) : - basic_key_value_accessor(db), - m_cache(base_class::m_isolation) - { - - } - ~cached_key_value_accessor() - { - NESTED_TRY_ENTRY(); - - m_cache.clear(); //will clear cache isolated - - NESTED_CATCH_ENTRY(__func__); - } - - void clear_cache() const - { - m_cache.clear(); - } - - void set_cache_size(uint64_t max_cache_size) - { - m_cache.set_max_elements(max_cache_size); - } - - void set(const t_key& k, const t_value& v) - { - TIME_MEASURE_START_PD(write_to_db_microsec); - base_class::set(k, v); - TIME_MEASURE_FINISH_PD(write_to_db_microsec); - - TIME_MEASURE_START_PD(write_to_cache_microsec); - m_cache.set(k, std::shared_ptr(new t_value(v))); - TIME_MEASURE_FINISH_PD(write_to_cache_microsec); - } - - std::shared_ptr get(const t_key& k) const - { - std::shared_ptr res; - TIME_MEASURE_START_PD(read_cache_microsec); - bool r = m_cache.get(k, res); - TIME_MEASURE_FINISH_PD(read_cache_microsec); - if (r) - { - m_performance_data.hit_percent.push(100); - return res; - } - m_performance_data.hit_percent.push(0); - - TIME_MEASURE_START_PD(read_db_microsec); - res = base_class::get(k); - TIME_MEASURE_FINISH_PD(read_db_microsec); - if (res) - { - TIME_MEASURE_START_PD(update_cache_microsec); - m_cache.set(k, res); - TIME_MEASURE_FINISH_PD(update_cache_microsec); - } - return res; - } - - size_t clear() - { - m_cache.clear(); - return base_class::clear(); - } - - bool erase_validate(const t_key& k) - { - - auto res_ptr = base_class::erase_validate(k); - m_cache.erase(k); - return static_cast(res_ptr); - } - - std::shared_ptr operator[] (const t_key& k) const - { - return get(k); - } - - void erase(const t_key& k) - { - base_class::erase(k); - m_cache.erase(k); - } - - performance_data& get_performance_data() const - { - return m_performance_data; - } - typename basic_db_accessor::performance_data& get_performance_data_native() const - { - return base_class::bdb.get_performance_data_for_handle(base_class::m_h); - } - typename basic_db_accessor::performance_data& get_performance_data_global() const - { - return base_class::bdb.get_performance_data_global(); - } - - private: - mutable performance_data m_performance_data; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class solo_db_value - { - t_key m_key; - t_accessor& m_accessor; - public: - solo_db_value(const t_key& k, t_accessor& accessor) :m_accessor(accessor), m_key(k) - {} - - solo_db_value(const solo_db_value& v) :m_accessor(v.m_accessor), m_key(v.m_key) - {} - solo_db_value& operator=(const solo_db_value&) = delete; - - - t_value operator=(t_value v) - { - m_accessor.template explicit_set >(m_key, v); - return v; - } - - operator t_value() const - { - std::shared_ptr value_ptr = m_accessor.template explicit_get >(m_key); - if (value_ptr.get()) - return *value_ptr.get(); - - return AUTO_VAL_INIT(t_value()); - } - }; - - -#pragma pack(push, 1) - struct guid_key - { - uint64_t a; - uint64_t b; - }; -#pragma pack(pop) - - //we use this suffix to keep elements count of sub-container, guid_key collision supposed to be impossible (almost) - // {E005D3C8-C9E9-4C2E-B94C-A40EC25505AD} - static const guid_key const_counter_suffix = - { 0xe005d3c8c9e94c2e, 0xb94ca40ec25550ad}; - - -#pragma pack(push, 1) - template - struct composite_key - { - t_key_a container_id; - t_key_b sufix; - }; - -// template -// struct container_counter_key_holder : public composite_key -// {}; -#pragma pack(pop) - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class basic_key_to_array_accessor : public basic_key_value_accessor, t_value, is_t_access_strategy> - { - typedef basic_key_value_accessor, t_value, is_t_access_strategy> basic_accessor_type; - - solo_db_value, uint64_t, basic_accessor_type> - get_counter_accessor(const t_key& container_id) - { - static_assert(std::is_pod::value, "t_pod_key must be a POD type."); - composite_key cc = { container_id, const_counter_suffix}; - - return solo_db_value, uint64_t, basic_accessor_type >(cc, *this); - } - - const solo_db_value, uint64_t, basic_accessor_type > - get_counter_accessor(const t_key& container_id) const - { - static_assert(std::is_pod::value, "t_pod_key must be a POD type."); - composite_key cc = { container_id, const_counter_suffix }; - - return solo_db_value, uint64_t, basic_accessor_type >(cc, const_cast(static_cast(*this))); - } - - template - struct subitems_visitor : public i_db_callback - { - subitems_visitor(callback_t cb) - : m_callback(cb) - {} - - virtual bool on_enum_item(uint64_t i, const void* key_data, uint64_t key_size, const void* value_data, uint64_t value_size) override - { - if (key_size != sizeof(composite_key)) - return true; // skip solo values containing items size - - composite_key key = AUTO_VAL_INIT(key); - key_from_ptr(key, key_data, key_size); - - t_value value = AUTO_VAL_INIT(value); - access_strategy_selector::from_buff_to_obj(value_data, value_size, value); - - return m_callback(i, key.container_id, key.sufix, value); - } - - callback_t m_callback; - }; - - public: - basic_key_to_array_accessor(basic_db_accessor& db) : basic_key_value_accessor, t_value, is_t_access_strategy>(db) - {} - - uint64_t get_item_size(const t_key& k) const - { - return get_counter_accessor(k); - } - - std::shared_ptr get_subitem(const t_key& k, uint64_t i) const - { - if (i >= get_item_size(k)) - { - LOG_ERROR("Out of bound access: itmes_count = " << get_item_size(k) << ", i = " << i); - throw std::out_of_range("In basic_key_to_array_accessor"); - } - composite_key ck{ k, i }; - return this->get(ck); - } - - void push_back_item(const t_key& k, const t_value& v) - { - auto counter = get_counter_accessor(k); - uint64_t new_index = counter; - counter = new_index+1; - composite_key ck{ k, new_index }; - this->set(ck, v); - } - - void pop_back_item(const t_key& k) - { - auto counter = get_counter_accessor(k); - uint64_t sz = static_cast(counter); - - CHECK_AND_ASSERT_MES(sz != 0, void(), "pop_back_item called on empty subitem"); - - composite_key ck{ k, sz - 1 }; - this->erase(ck); - counter = --sz; - } - - // removes all items by key k - void erase_items(const t_key& k) - { - auto counter = get_counter_accessor(k); - uint64_t sz = static_cast(counter); - - while (sz != 0) - { - composite_key ck{ k, sz - 1 }; - this->erase(ck); - --sz; - } - - counter = 0; - } - - template - void enumerate_subitems(callback_t callback) const - { - subitems_visitor visitor(callback); - basic_accessor_type::bdb.get_backend()->enumerate(basic_accessor_type::m_h, &visitor); - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class array_accessor : public cached_key_value_accessor - { - public: - array_accessor(basic_db_accessor& db) : cached_key_value_accessor(db) - {} - void push_back(const t_value& v) - { - this->set(this->size(), v); - - } - void pop_back() - { - this->erase(this->size()-1); - } - std::shared_ptr back() const - { - auto res = this->get(this->size()-1); - CHECK_AND_ASSERT_THROW(res.get(), std::out_of_range(std::string("Out of range in array_accessor in call back(): size()=") - + std::to_string(this->size()) - + ", size_no_cache()=" + std::to_string(this->size_no_cache()) )); - return res; - } - - std::shared_ptr operator[] (const uint64_t& k) const - { - auto res = this->get(k); - CHECK_AND_ASSERT_THROW(res.get(), std::out_of_range(std::string("Out of range in array_accessor in call []: key = ") - + std::to_string(k) - + ", size_no_cache()=" + std::to_string(this->size_no_cache()))); - - return res; - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class reader_access - { - t_db& m_db; - bool got_transaction; - public: - reader_access(t_db& db) :m_db(db), got_transaction(false) - {} - - void lock() - { - //start read only transaction - if (m_db.is_open()) - { - m_db.begin_transaction(true); - got_transaction = true; - } - - } - void unlock() - { - if (got_transaction) - m_db.commit_transaction(); - - got_transaction = false; - } - - }; - - } -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL diff --git a/src/common/db_backend_base.h b/src/common/db_backend_base.h deleted file mode 100644 index 01c87e1..0000000 --- a/src/common/db_backend_base.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#ifndef ENV32BIT -#define CACHE_SIZE uint64_t(uint64_t(1UL * 128UL) * 1024UL * 1024UL * 1024UL) -#else -#define CACHE_SIZE (1 * 1024UL * 1024UL * 1024UL) -#endif - - -namespace tools -{ - namespace db - { - typedef size_t container_handle; - const uint64_t invalid_tx_id = 0; - struct i_db_callback - { - virtual bool on_enum_item(uint64_t i, const void* pkey, uint64_t ks, const void* pval, uint64_t vs) = 0; - }; - - struct stat_info - { - uint64_t tx_count; - uint64_t write_tx_count; - uint64_t map_size; - }; - - struct i_db_backend - { - virtual bool close()=0; - virtual bool begin_transaction(bool read_only = false) = 0; - virtual bool commit_transaction()=0; - virtual void abort_transaction()=0; - virtual bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) = 0; - virtual bool open_container(const std::string& name, container_handle& h)=0; - virtual bool close_container(container_handle& h) = 0; - virtual bool erase(container_handle h, const char* k, size_t s) = 0; - virtual uint64_t size(container_handle h) = 0; - virtual bool get(container_handle h, const char* k, size_t s, std::string& res_buff) = 0; - virtual bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) = 0; - virtual bool clear(container_handle h) = 0; - virtual bool enumerate(container_handle h, i_db_callback* pcb)=0; - virtual bool get_stat_info(stat_info& si) = 0; - virtual const char* name()=0; - virtual ~i_db_backend(){}; - }; - } -} \ No newline at end of file diff --git a/src/common/db_backend_leveldb.cpp b/src/common/db_backend_leveldb.cpp deleted file mode 100644 index c408c43..0000000 --- a/src/common/db_backend_leveldb.cpp +++ /dev/null @@ -1,109 +0,0 @@ - -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// #pragma once -// #include "db_backend_leveldb.h" -// -// namespace tools -// { -// namespace db -// { -// level_db_backend : public i_db_backend -// { -// std::string m_path; -// db_handle m_pdb; -// public: -// basic_db() :m_pdb(nullptr) -// {} -// ~basic_db(){ close(); } -// bool close() -// { -// if (m_pdb) -// delete m_pdb; -// m_pdb = nullptr; -// -// return true; -// } -// -// void begin_transaction() -// { -// //leveldb is not supporting transactions yet -// } -// -// void commit_transaction() -// { -// //leveldb is not supporting transactions yet -// } -// -// -// bool open(const std::string& path) -// { -// m_path = path; -// close(); -// leveldb::Options options; -// options.create_if_missing = true; -// leveldb::Status status = leveldb::DB::Open(options, path, &m_pdb); -// if (!status.ok()) -// { -// LOG_ERROR("Unable to open/create database " << path << ", error: " << status.ToString()); -// return err_handle; -// } -// return true; -// } -// -// bool erase(const char* k, size s) -// { -// TRY_ENTRY(); -// leveldb::WriteOptions wo; -// wo.sync = true; -// leveldb::Status s = m_pdb->Delete(wo, leveldb::Slice(k, s)); -// if (!s.ok()) -// return false; -// -// return true; -// CATCH_ENTRY_L0("get_t_object_from_db", false); -// } -// -// -// bool get(const char* k, size s, std::string& res_buff) -// { -// TRY_ENTRY(); -// leveldb::ReadOptions ro; -// leveldb::Status s = m_pdb->Get(ro, leveldb::Slice(k, s), &res_buff); -// if (!s.ok()) -// return false; -// -// CATCH_ENTRY_L0("get_t_object_from_db", false); -// } -// -// bool clear() -// { -// close(); -// boost::system::error_code ec; -// bool res = boost::filesystem::remove_all(m_path, ec); -// if (!res) -// { -// LOG_ERROR("Failed to remove db file " << m_path << ", why: " << ec); -// return false; -// } -// return open(m_path); -// } -// -// bool set(const char* k, size s, const char* v, size vs) -// { -// TRY_ENTRY(); -// leveldb::WriteOptions wo; -// wo.sync = true; -// leveldb::Status s = m_pdb->Put(wo, leveldb::Slice(k, s), leveldb::Slice(v, vs)); -// if (!s.ok()) -// return false; -// -// return true; -// CATCH_ENTRY_L0("set_t_object_to_db", false); -// } -// }; -// } -// } diff --git a/src/common/db_backend_leveldb.h b/src/common/db_backend_leveldb.h deleted file mode 100644 index 541f3d6..0000000 --- a/src/common/db_backend_leveldb.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "include_base_utils.h" - -// #include "db_backend_base.h" -// -// #include "currency_db_base.h" -// #include "leveldb/db.h" -// #include "common/boost_serialization_helper.h" -// #include "common/difficulty_boost_serialization.h" -// #include "currency_format_utils.h" -// -// -// namespace tools -// { -// namespace db -// { -// typedef leveldb::DB* db_handle; -// -// static const db_handle err_handle = nullptr; -// -// class level_db_backend : public i_db_backend -// { -// std::string m_path; -// db_handle m_pdb; -// public: -// level_db_backend() :m_pdb(nullptr) -// {} -// ~level_db_backend(){ close(); } -// bool close(); -// void begin_transaction(); -// void commit_transaction(); -// bool open(const std::string& path); -// bool erase(const char* k, size s); -// bool get(const char* k, size s, std::string& res_buff); -// bool clear(); -// bool set(const char* k, size s, const char* v, size vs); -// }; -// } -// } - - diff --git a/src/common/db_backend_lmdb.cpp b/src/common/db_backend_lmdb.cpp deleted file mode 100644 index 6dfb1ee..0000000 --- a/src/common/db_backend_lmdb.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "db_backend_lmdb.h" -#include "misc_language.h" -#include "string_coding.h" -#include "profile_tools.h" -#include "util.h" - -#define BUF_SIZE 1024 - -#define CHECK_AND_ASSERT_MESS_LMDB_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(rc == MDB_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess); -#define CHECK_AND_ASSERT_THROW_MESS_LMDB_DB(rc, mess) CHECK_AND_ASSERT_THROW_MES(rc == MDB_SUCCESS, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess); -#define ASSERT_MES_AND_THROW_LMDB(rc, mess) ASSERT_MES_AND_THROW("[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess); - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "lmdb" -// 'lmdb' channel is disabled by default - -namespace tools -{ - namespace db - { - lmdb_db_backend::lmdb_db_backend() : m_penv(AUTO_VAL_INIT(m_penv)) - { - - } - lmdb_db_backend::~lmdb_db_backend() - { - NESTED_TRY_ENTRY(); - - close(); - - NESTED_CATCH_ENTRY(__func__); - } - - bool lmdb_db_backend::open(const std::string& path_, uint64_t cache_sz) - { - int res = 0; - res = mdb_env_create(&m_penv); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_create"); - - res = mdb_env_set_maxdbs(m_penv, 15); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_maxdbs"); - - res = mdb_env_set_mapsize(m_penv, cache_sz); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_mapsize"); - - m_path = path_; - CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path); - - res = mdb_env_open(m_penv, m_path.c_str(), MDB_NORDAHEAD , 0644); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_open, m_path=" << m_path); - - return true; - } - - bool lmdb_db_backend::open_container(const std::string& name, container_handle& h) - { - MDB_dbi dbi = AUTO_VAL_INIT(dbi); - begin_transaction(); - int res = mdb_dbi_open(get_current_tx(), name.c_str(), MDB_CREATE, &dbi); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_dbi_open with container name: " << name); - commit_transaction(); - h = static_cast(dbi); - return true; - } - - bool lmdb_db_backend::close_container(container_handle& h) - { - static const container_handle null_handle = AUTO_VAL_INIT(null_handle); - CHECK_AND_ASSERT_MES(h != null_handle, false, "close_container is called for null container handle"); - MDB_dbi dbi = static_cast(h); - begin_transaction(); - mdb_dbi_close(m_penv, dbi); - commit_transaction(); - h = null_handle; - return true; - } - - bool lmdb_db_backend::close() - { - { - std::lock_guard lock(m_cs); - for (auto& tx_thread : m_txs) - { - for (auto txe : tx_thread.second) - { - int res = mdb_txn_commit(txe.ptx); - if (res != MDB_SUCCESS) - { - LOG_ERROR("[DB ERROR]: On close tranactions: " << mdb_strerror(res)); - } - } - } - - m_txs.clear(); - } - if (m_penv) - { - mdb_env_close(m_penv); - m_penv = nullptr; - } - return true; - } - - bool lmdb_db_backend::begin_transaction(bool read_only) - { - if (!read_only) - { - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED", LOG_LEVEL_3); - CRITICAL_SECTION_LOCK(m_write_exclusive_lock); - } - PROFILE_FUNC("lmdb_db_backend::begin_transaction"); - { - std::lock_guard lock(m_cs); - CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); - transactions_list& rtxlist = m_txs[std::this_thread::get_id()]; - MDB_txn* pparent_tx = nullptr; - MDB_txn* p_new_tx = nullptr; - bool parent_read_only = false; - if (rtxlist.size()) - { - pparent_tx = rtxlist.back().ptx; - parent_read_only = rtxlist.back().read_only; - } - - - if (pparent_tx && read_only) - { - ++rtxlist.back().count; - } - else - { - int res = 0; - unsigned int flags = 0; - if (read_only) - flags += MDB_RDONLY; - - //don't use parent tx in write transactions if parent tx was read-only (restriction in lmdb) - //see "Nested transactions: Max 1 child, write txns only, no writemap" - if (pparent_tx && parent_read_only) - pparent_tx = nullptr; - - CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); - res = mdb_txn_begin(m_penv, pparent_tx, flags, &p_new_tx); - if(res != MDB_SUCCESS) - { - //Important: if mdb_txn_begin is failed need to unlock previously locked mutex - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - //throw exception to avoid regular code execution - ASSERT_MES_AND_THROW_LMDB(res, "Unable to mdb_txn_begin"); - } - - rtxlist.push_back(tx_entry()); - rtxlist.back().count = read_only ? 1 : 0; - rtxlist.back().ptx = p_new_tx; - rtxlist.back().read_only = read_only; - } - } - - - LOG_PRINT_L4("[DB] Transaction started"); - return true; - } - - MDB_txn* lmdb_db_backend::get_current_tx() - { - std::lock_guard lock(m_cs); - auto& rtxlist = m_txs[std::this_thread::get_id()]; - CHECK_AND_ASSERT_MES(rtxlist.size(), nullptr, "Unable to find active tx for thread " << std::this_thread::get_id()); - return rtxlist.back().ptx; - } - - bool lmdb_db_backend::pop_tx_entry(tx_entry& txe) - { - std::lock_guard lock(m_cs); - auto it = m_txs.find(std::this_thread::get_id()); - CHECK_AND_ASSERT_MES(it != m_txs.end(), false, "[DB] Unable to find id cor current thread"); - CHECK_AND_ASSERT_MES(it->second.size(), false, "[DB] No active tx for current thread"); - - txe = it->second.back(); - - if (it->second.back().read_only && it->second.back().count == 0) - { - LOG_ERROR("Internal db tx state error: read_only and count readers == 0"); - } - - if ((it->second.back().read_only && it->second.back().count < 2) || (!it->second.back().read_only && it->second.back().count < 1)) - { - it->second.pop_back(); - if (!it->second.size()) - m_txs.erase(it); - } - else - { - --it->second.back().count; - } - return true; - } - - bool lmdb_db_backend::commit_transaction() - { - PROFILE_FUNC("lmdb_db_backend::commit_transaction"); - { - tx_entry txe = AUTO_VAL_INIT(txe); - bool r = pop_tx_entry(txe); - CHECK_AND_ASSERT_MES(r, false, "Unable to pop_tx_entry"); - - if (txe.count == 0 || (txe.read_only && txe.count == 1)) - { - int res = 0; - res = mdb_txn_commit(txe.ptx); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_txn_commit (error " << res << ")"); - if (!txe.read_only && !txe.count) - { - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED", LOG_LEVEL_3); - } - } - } - LOG_PRINT_L4("[DB] Transaction committed"); - return true; - } - - void lmdb_db_backend::abort_transaction() - { - { - tx_entry txe = AUTO_VAL_INIT(txe); - bool r = pop_tx_entry(txe); - CHECK_AND_ASSERT_MES(r, void(), "Unable to pop_tx_entry"); - if (txe.count == 0 || (txe.read_only && txe.count == 1)) - { - mdb_txn_abort(txe.ptx); - if (!txe.read_only && !txe.count) - { - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED(ABORTED)", LOG_LEVEL_3); - } - } - - - } - LOG_PRINT_L4("[DB] Transaction aborted"); - } - - bool lmdb_db_backend::erase(container_handle h, const char* k, size_t ks) - { - int res = 0; - MDB_val key = AUTO_VAL_INIT(key); - key.mv_data = (void*)k; - key.mv_size = ks; - - res = mdb_del(get_current_tx(), static_cast(h), &key, nullptr); - if (res == MDB_NOTFOUND) - return false; - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_del"); - return true; - } - - bool lmdb_db_backend::have_tx() - { - std::lock_guard lock(m_cs); - auto it = m_txs.find(std::this_thread::get_id()); - if (it == m_txs.end()) - return false; - return it->second.size() ? true : false; - } - - bool lmdb_db_backend::get(container_handle h, const char* k, size_t ks, std::string& res_buff) - { - PROFILE_FUNC("lmdb_db_backend::get"); - int res = 0; - MDB_val key = AUTO_VAL_INIT(key); - MDB_val data = AUTO_VAL_INIT(data); - key.mv_data = (void*)k; - key.mv_size = ks; - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - - res = mdb_get(get_current_tx(), static_cast(h), &key, &data); - - if (need_to_commit) - commit_transaction(); - - if (res == MDB_NOTFOUND) - return false; - - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_get, h: " << h << ", ks: " << ks); - res_buff.assign((const char*)data.mv_data, data.mv_size); - return true; - } - - bool lmdb_db_backend::clear(container_handle h) - { - int res = mdb_drop(get_current_tx(), static_cast(h), 0); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_drop"); - return true; - } - - uint64_t lmdb_db_backend::size(container_handle h) - { - PROFILE_FUNC("lmdb_db_backend::size"); - MDB_stat container_stat = AUTO_VAL_INIT(container_stat); - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - int res = mdb_stat(get_current_tx(), static_cast(h), &container_stat); - if (need_to_commit) - commit_transaction(); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_stat"); - return container_stat.ms_entries; - } - - bool lmdb_db_backend::set(container_handle h, const char* k, size_t ks, const char* v, size_t vs) - { - PROFILE_FUNC("lmdb_db_backend::set"); - int res = 0; - MDB_val key = AUTO_VAL_INIT(key); - MDB_val data[2] = {}; // mdb_put may access data[1] if some flags are set, this may trigger static code analizers, so here we allocate two elements to avoid it - key.mv_data = (void*)k; - key.mv_size = ks; - data[0].mv_data = (void*)v; - data[0].mv_size = vs; - - res = mdb_put(get_current_tx(), static_cast(h), &key, data, 0); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_put"); - return true; - } - bool lmdb_db_backend::enumerate(container_handle h, i_db_callback* pcb) - { - CHECK_AND_ASSERT_MES(pcb, false, "null capback ptr passed to enumerate"); - MDB_val key = AUTO_VAL_INIT(key); - MDB_val data = AUTO_VAL_INIT(data); - - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - MDB_cursor* cursor_ptr = nullptr; - int res = mdb_cursor_open(get_current_tx(), static_cast(h), &cursor_ptr); - CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_cursor_open"); - CHECK_AND_ASSERT_MES(cursor_ptr, false, "cursor_ptr is null after mdb_cursor_open"); - - uint64_t count = 0; - do - { - int res = mdb_cursor_get(cursor_ptr, &key, &data, MDB_NEXT); - if (res == MDB_NOTFOUND) - break; - if (!pcb->on_enum_item(count, key.mv_data, key.mv_size, data.mv_data, data.mv_size)) - break; - count++; - } while (cursor_ptr); - - mdb_cursor_close(cursor_ptr); - if (need_to_commit) - commit_transaction(); - return true; - } - - bool lmdb_db_backend::get_stat_info(tools::db::stat_info& si) - { - si = AUTO_VAL_INIT_T(tools::db::stat_info); - - MDB_envinfo ei = AUTO_VAL_INIT(ei); - mdb_env_info(m_penv, &ei); - si.map_size = ei.me_mapsize; - - std::lock_guard lock(m_cs); - for (auto& e : m_txs) - { - for (auto& pr : e.second) - { - ++si.tx_count; - if(!pr.read_only) - ++si.write_tx_count; - } - } - return true; - } - const char* lmdb_db_backend::name() - { - return "lmdb"; - } - } -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL diff --git a/src/common/db_backend_lmdb.h b/src/common/db_backend_lmdb.h deleted file mode 100644 index ef56c34..0000000 --- a/src/common/db_backend_lmdb.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include - -#include "include_base_utils.h" - -#include "db_backend_base.h" -#include "db/liblmdb/lmdb.h" - - -namespace tools -{ - namespace db - { - class lmdb_db_backend : public i_db_backend - { - - struct tx_entry - { - MDB_txn* ptx; - bool read_only; // needed for thread-top transaction, for figure out if we need to unlock exclusive access - size_t count; //count of read-only nested emulated transactions - }; - typedef std::list transactions_list; - - - std::string m_path; - MDB_env *m_penv; - - boost::recursive_mutex m_cs; - boost::recursive_mutex m_write_exclusive_lock; - std::map m_txs; // size_t -> count of nested read_only transactions - bool pop_tx_entry(tx_entry& txe); - public: - lmdb_db_backend(); - ~lmdb_db_backend(); - - //----------------- i_db_backend ----------------------------------------------------- - bool close() override; - bool begin_transaction(bool read_only = false) override; - bool commit_transaction() override; - void abort_transaction() override; - bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) override; - bool open_container(const std::string& name, container_handle& h) override; - bool close_container(container_handle& h) override; - bool erase(container_handle h, const char* k, size_t s) override; - bool get(container_handle h, const char* k, size_t s, std::string& res_buff) override; - bool clear(container_handle h) override; - uint64_t size(container_handle h) override; - bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) override; - bool enumerate(container_handle h, i_db_callback* pcb) override; - bool get_stat_info(tools::db::stat_info& si) override; - const char* name() override; - //------------------------------------------------------------------------------------- - bool have_tx(); - MDB_txn* get_current_tx(); - - }; - } -} diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp deleted file mode 100644 index 3307dec..0000000 --- a/src/common/db_backend_mdbx.cpp +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifdef ENABLED_ENGINE_MDBX -#include "db_backend_mdbx.h" -#include "misc_language.h" -#include "string_coding.h" -#include "profile_tools.h" -#include "util.h" - - -#define BUF_SIZE 1024 - -#define CHECK_AND_ASSERT_MESS_MDBX_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(res == MDBX_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); -#define CHECK_AND_ASSERT_THROW_MESS_MDBX_DB(rc, mess) CHECK_AND_ASSERT_THROW_MES(res == MDBX_SUCCESS, "[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); -#define ASSERT_MES_AND_THROW_MDBX(rc, mess) ASSERT_MES_AND_THROW("[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "mdbx" -// 'mdbx' channel is disabled by default - -namespace tools -{ - namespace db - { - mdbx_db_backend::mdbx_db_backend() : m_penv(AUTO_VAL_INIT(m_penv)) - { - - } - mdbx_db_backend::~mdbx_db_backend() - { - NESTED_TRY_ENTRY(); - - close(); - - NESTED_CATCH_ENTRY(__func__); - } - - bool mdbx_db_backend::open(const std::string& path_, uint64_t cache_sz) - { - int res = 0; - res = mdbx_env_create(&m_penv); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_create"); - - res = mdbx_env_set_maxdbs(m_penv, 15); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_set_maxdbs"); - - intptr_t size_lower = 0; - intptr_t size_now = -1; //don't change current database size - intptr_t size_upper = 0x10000000000; //don't set db file size limit - intptr_t growth_step = 0x40000000; //increment step 1GB - intptr_t shrink_threshold = -1; - intptr_t pagesize = 0x00001000; //4kb - res = mdbx_env_set_geometry(m_penv, size_lower, size_now, size_upper, growth_step, shrink_threshold, pagesize); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_set_mapsize"); - - m_path = path_; - CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path); - - res = mdbx_env_open(m_penv, m_path.c_str(), MDBX_NORDAHEAD , 0644); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_open, m_path=" << m_path); - - return true; - } - - bool mdbx_db_backend::open_container(const std::string& name, container_handle& h) - { - MDBX_dbi dbi = AUTO_VAL_INIT(dbi); - begin_transaction(); - int res = mdbx_dbi_open(get_current_tx(), name.c_str(), MDBX_CREATE, &dbi); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_dbi_open with container name: " << name); - commit_transaction(); - h = static_cast(dbi); - return true; - } - - bool mdbx_db_backend::close_container(container_handle& h) - { - static const container_handle null_handle = AUTO_VAL_INIT(null_handle); - CHECK_AND_ASSERT_MES(h != null_handle, false, "close_container is called for null container handle"); - - MDBX_dbi dbi = static_cast(h); - begin_transaction(); - mdbx_dbi_close(m_penv, dbi); - commit_transaction(); - h = null_handle; - return true; - } - - bool mdbx_db_backend::close() - { - { - std::lock_guard lock(m_cs); - for (auto& tx_thread : m_txs) - { - for (auto txe : tx_thread.second) - { - int res = mdbx_txn_commit(txe.ptx); - if (res != MDBX_SUCCESS) - { - LOG_ERROR("[DB ERROR]: On close tranactions: " << mdbx_strerror(res)); - } - } - } - - m_txs.clear(); - } - if (m_penv) - { - mdbx_env_close(m_penv); - m_penv = nullptr; - } - return true; - } - - bool mdbx_db_backend::begin_transaction(bool read_only) - { - if (!read_only) - { - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED", LOG_LEVEL_3); - CRITICAL_SECTION_LOCK(m_write_exclusive_lock); - } - PROFILE_FUNC("mdbx_db_backend::begin_transaction"); - { - std::lock_guard lock(m_cs); - CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); - transactions_list& rtxlist = m_txs[std::this_thread::get_id()]; - MDBX_txn* pparent_tx = nullptr; - MDBX_txn* p_new_tx = nullptr; - bool parent_read_only = false; - if (rtxlist.size()) - { - pparent_tx = rtxlist.back().ptx; - parent_read_only = rtxlist.back().read_only; - } - - - if (pparent_tx && read_only) - { - ++rtxlist.back().count; - } - else - { - int res = 0; - //MDBX_txn_flags_t flags = MDBX_txn_flags_t(); - unsigned int flags = 0; - if (read_only) - flags = MDBX_RDONLY;//flags = MDBX_TXN_RDONLY; - - //don't use parent tx in write transactions if parent tx was read-only (restriction in mdbx) - //see "Nested transactions: Max 1 child, write txns only, no writemap" - if (pparent_tx && parent_read_only) - pparent_tx = nullptr; - - CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); - res = mdbx_txn_begin(m_penv, pparent_tx, flags, &p_new_tx); - if(res != MDBX_SUCCESS) - { - //Important: if mdbx_txn_begin is failed need to unlock previously locked mutex - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - //throw exception to avoid regular code execution - ASSERT_MES_AND_THROW_MDBX(res, "Unable to mdbx_txn_begin"); - } - - rtxlist.push_back(tx_entry()); - rtxlist.back().count = read_only ? 1 : 0; - rtxlist.back().ptx = p_new_tx; - rtxlist.back().read_only = read_only; - } - } - - - LOG_PRINT_L4("[DB] Transaction started"); - return true; - } - - MDBX_txn* mdbx_db_backend::get_current_tx() - { - std::lock_guard lock(m_cs); - auto& rtxlist = m_txs[std::this_thread::get_id()]; - CHECK_AND_ASSERT_MES(rtxlist.size(), nullptr, "Unable to find active tx for thread " << std::this_thread::get_id()); - return rtxlist.back().ptx; - } - - bool mdbx_db_backend::pop_tx_entry(tx_entry& txe) - { - std::lock_guard lock(m_cs); - auto it = m_txs.find(std::this_thread::get_id()); - CHECK_AND_ASSERT_MES(it != m_txs.end(), false, "[DB] Unable to find id cor current thread"); - CHECK_AND_ASSERT_MES(it->second.size(), false, "[DB] No active tx for current thread"); - - txe = it->second.back(); - - if (it->second.back().read_only && it->second.back().count == 0) - { - LOG_ERROR("Internal db tx state error: read_only and count readers == 0"); - } - - if ((it->second.back().read_only && it->second.back().count < 2) || (!it->second.back().read_only && it->second.back().count < 1)) - { - it->second.pop_back(); - if (!it->second.size()) - m_txs.erase(it); - } - else - { - --it->second.back().count; - } - return true; - } - - bool mdbx_db_backend::commit_transaction() - { - PROFILE_FUNC("mdbx_db_backend::commit_transaction"); - { - tx_entry txe = AUTO_VAL_INIT(txe); - bool r = pop_tx_entry(txe); - CHECK_AND_ASSERT_MES(r, false, "Unable to pop_tx_entry"); - - if (txe.count == 0 || (txe.read_only && txe.count == 1)) - { - int res = 0; - res = mdbx_txn_commit(txe.ptx); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_txn_commit (error " << res << ")"); - if (!txe.read_only && !txe.count) - { - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED", LOG_LEVEL_3); - } - } - } - LOG_PRINT_L4("[DB] Transaction committed"); - return true; - } - - void mdbx_db_backend::abort_transaction() - { - { - tx_entry txe = AUTO_VAL_INIT(txe); - bool r = pop_tx_entry(txe); - CHECK_AND_ASSERT_MES(r, void(), "Unable to pop_tx_entry"); - if (txe.count == 0 || (txe.read_only && txe.count == 1)) - { - mdbx_txn_abort(txe.ptx); - if (!txe.read_only && !txe.count) - { - CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); - LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED(ABORTED)", LOG_LEVEL_3); - } - } - - - } - LOG_PRINT_L4("[DB] Transaction aborted"); - } - - bool mdbx_db_backend::erase(container_handle h, const char* k, size_t ks) - { - int res = 0; - MDBX_val key = AUTO_VAL_INIT(key); - key.iov_base = (void*)k; - key.iov_len = ks; - - res = mdbx_del(get_current_tx(), static_cast(h), &key, nullptr); - if (res == MDBX_NOTFOUND) - return false; - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_del"); - return true; - } - - bool mdbx_db_backend::have_tx() - { - std::lock_guard lock(m_cs); - auto it = m_txs.find(std::this_thread::get_id()); - if (it == m_txs.end()) - return false; - return it->second.size() ? true : false; - } - - bool mdbx_db_backend::get(container_handle h, const char* k, size_t ks, std::string& res_buff) - { - PROFILE_FUNC("mdbx_db_backend::get"); - int res = 0; - MDBX_val key = AUTO_VAL_INIT(key); - MDBX_val data = AUTO_VAL_INIT(data); - key.iov_base = (void*)k; - key.iov_len = ks; - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - - res = mdbx_get(get_current_tx(), static_cast(h), &key, &data); - - if (need_to_commit) - commit_transaction(); - - if (res == MDBX_NOTFOUND) - return false; - - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_get, h: " << h << ", ks: " << ks); - res_buff.assign((const char*)data.iov_base, data.iov_len); - return true; - } - - bool mdbx_db_backend::clear(container_handle h) - { - int res = mdbx_drop(get_current_tx(), static_cast(h), 0); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_drop"); - return true; - } - - uint64_t mdbx_db_backend::size(container_handle h) - { - PROFILE_FUNC("mdbx_db_backend::size"); - MDBX_stat container_stat = AUTO_VAL_INIT(container_stat); - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - int res = mdbx_dbi_stat(get_current_tx(), static_cast(h), &container_stat, sizeof(MDBX_stat)); - if (need_to_commit) - commit_transaction(); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_stat"); - return container_stat.ms_entries; - } - - bool mdbx_db_backend::set(container_handle h, const char* k, size_t ks, const char* v, size_t vs) - { - PROFILE_FUNC("mdbx_db_backend::set"); - int res = 0; - MDBX_val key = AUTO_VAL_INIT(key); - MDBX_val data[2] = {}; // mdbx_put may access data[1] if some flags are set, this may trigger static code analizers, so here we allocate two elements to avoid it - key.iov_base = (void*)k; - key.iov_len = ks; - data[0].iov_base = (void*)v; - data[0].iov_len = vs; - - //MDBX_put_flags_t flags = MDBX_put_flags_t(); - unsigned flags = 0; - res = mdbx_put(get_current_tx(), static_cast(h), &key, data, flags); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put"); - return true; - } - bool mdbx_db_backend::enumerate(container_handle h, i_db_callback* pcb) - { - CHECK_AND_ASSERT_MES(pcb, false, "null capback ptr passed to enumerate"); - MDBX_val key = AUTO_VAL_INIT(key); - MDBX_val data = AUTO_VAL_INIT(data); - - bool need_to_commit = false; - if (!have_tx()) - { - need_to_commit = true; - begin_transaction(true); - } - MDBX_cursor* cursor_ptr = nullptr; - int res = mdbx_cursor_open(get_current_tx(), static_cast(h), &cursor_ptr); - CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_cursor_open"); - CHECK_AND_ASSERT_MES(cursor_ptr, false, "cursor_ptr is null after mdbx_cursor_open"); - - uint64_t count = 0; - do - { - int res = mdbx_cursor_get(cursor_ptr, &key, &data, MDBX_NEXT); - if (res == MDBX_NOTFOUND) - break; - if (!pcb->on_enum_item(count, key.iov_base, key.iov_len, data.iov_base, data.iov_len)) - break; - count++; - } while (cursor_ptr); - - mdbx_cursor_close(cursor_ptr); - if (need_to_commit) - commit_transaction(); - return true; - } - - bool mdbx_db_backend::get_stat_info(tools::db::stat_info& si) - { - si = AUTO_VAL_INIT_T(tools::db::stat_info); - - MDBX_envinfo ei = AUTO_VAL_INIT(ei); - mdbx_env_info(m_penv, &ei, sizeof(MDBX_envinfo)); - si.map_size = ei.mi_mapsize; - - std::lock_guard lock(m_cs); - for (auto& e : m_txs) - { - for (auto& pr : e.second) - { - ++si.tx_count; - if(!pr.read_only) - ++si.write_tx_count; - } - } - return true; - } - const char* mdbx_db_backend::name() - { - return "mdbx"; - } - } -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL -#endif \ No newline at end of file diff --git a/src/common/db_backend_mdbx.h b/src/common/db_backend_mdbx.h deleted file mode 100644 index af5363f..0000000 --- a/src/common/db_backend_mdbx.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#ifdef ENABLED_ENGINE_MDBX -#include - -#include "include_base_utils.h" - -#include "db_backend_base.h" -#include "db/libmdbx/mdbx.h" - - -namespace tools -{ - namespace db - { - class mdbx_db_backend : public i_db_backend - { - - struct tx_entry - { - MDBX_txn* ptx; - bool read_only; // needed for thread-top transaction, for figure out if we need to unlock exclusive access - size_t count; //count of read-only nested emulated transactions - }; - typedef std::list transactions_list; - - - std::string m_path; - MDBX_env *m_penv; - - boost::recursive_mutex m_cs; - boost::recursive_mutex m_write_exclusive_lock; - std::map m_txs; // size_t -> count of nested read_only transactions - bool pop_tx_entry(tx_entry& txe); - public: - mdbx_db_backend(); - ~mdbx_db_backend(); - - //----------------- i_db_backend ----------------------------------------------------- - bool close() override; - bool begin_transaction(bool read_only = false) override; - bool commit_transaction() override; - void abort_transaction() override; - bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) override; - bool open_container(const std::string& name, container_handle& h) override; - bool close_container(container_handle& h) override; - bool erase(container_handle h, const char* k, size_t s) override; - bool get(container_handle h, const char* k, size_t s, std::string& res_buff) override; - bool clear(container_handle h) override; - uint64_t size(container_handle h) override; - bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) override; - bool enumerate(container_handle h, i_db_callback* pcb) override; - bool get_stat_info(tools::db::stat_info& si) override; - const char* name() override; - //------------------------------------------------------------------------------------- - bool have_tx(); - MDBX_txn* get_current_tx(); - - }; - - } -} -#endif \ No newline at end of file diff --git a/src/common/db_backend_selector.cpp b/src/common/db_backend_selector.cpp deleted file mode 100644 index 9c7917c..0000000 --- a/src/common/db_backend_selector.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2014-2020 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "db_backend_selector.h" -#include "currency_core/currency_config.h" -#include "command_line.h" -#include "db_backend_lmdb.h" -#include "db_backend_mdbx.h" - -#define LMDB_MAIN_FILE_NAME "data.mdb" -#define MDBX_MAIN_FILE_NAME "mdbx.dat" - -namespace tools -{ -namespace db -{ - - db_backend_selector::db_backend_selector() - : m_engine_type(db_none) - { - } - - void db_backend_selector::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, command_line::arg_db_engine); - } - - bool db_backend_selector::init(const boost::program_options::variables_map& vm) - { - try - { - m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); - - if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_LMDB) - { - m_engine_type = db_lmdb; - } - else if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_MDBX) - { -#ifdef ENABLED_ENGINE_MDBX - m_engine_type = db_mdbx; -#else - LOG_PRINT_L0(" DB ENGINE: " << ARG_DB_ENGINE_MDBX << " is not suported by this build(see DISABLE_MDBX cmake option), STOPPING"); -#endif - } - else - { - LOG_PRINT_RED_L0("UNKNOWN DB ENGINE: " << command_line::get_arg(vm, command_line::arg_db_engine) << ", STOPPING"); - } - } - catch (std::exception& e) - { - LOG_ERROR("internal error: db_backend_selector::init failed on command-line parsing, exception: " << e.what()); - return false; - } - - if (m_engine_type == db_none) - return false; - - return true; - } - - std::string db_backend_selector::get_db_folder_path() const - { - //CHECK_AND_ASSERT_THROW_MES(m_engine_type != db_none, "db_backend_selector was no inited"); - return m_config_folder + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX; - } - - std::string db_backend_selector::get_temp_db_folder_path() const - { - //CHECK_AND_ASSERT_THROW_MES(m_engine_type != db_none, "db_backend_selector was no inited"); - return get_temp_config_folder() + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX; - } - - std::string db_backend_selector::get_pool_db_folder_path() const - { - return m_config_folder + ("/" CURRENCY_POOLDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_POOLDATA_FOLDERNAME_SUFFIX; - } - - std::string db_backend_selector::get_db_main_file_name() const - { - switch (m_engine_type) - { - case db_lmdb: - return LMDB_MAIN_FILE_NAME; - case db_mdbx: - return MDBX_MAIN_FILE_NAME; - default: - return ""; - } - } - - std::string db_backend_selector::get_engine_name() const - { - switch (m_engine_type) - { - case db_lmdb: - return "lmdb"; - case db_mdbx: - return "mdbx"; - default: - return "unknown"; - } - } - - std::shared_ptr db_backend_selector::create_backend() - { - switch (m_engine_type) - { - case db_lmdb: - return std::shared_ptr(new tools::db::lmdb_db_backend); - - case db_mdbx: - return std::shared_ptr(new tools::db::mdbx_db_backend); - - default: - LOG_ERROR("db_backend_selector was no inited"); - return nullptr; - } - } - - std::string db_backend_selector::get_temp_config_folder() const - { - return m_config_folder + "_TEMP"; - } - - - - -} // namespace db -} // namespace tools diff --git a/src/common/db_backend_selector.h b/src/common/db_backend_selector.h deleted file mode 100644 index b9d811b..0000000 --- a/src/common/db_backend_selector.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014-2020 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "misc_language.h" -#include "db_backend_base.h" - -namespace tools -{ - namespace db - { - enum db_engine_type { db_none = 0, db_lmdb, db_mdbx }; - - class db_backend_selector - { - public: - db_backend_selector(); - - static void init_options(boost::program_options::options_description& desc); - bool init(const boost::program_options::variables_map& vm); - - std::string get_db_folder_path() const; - std::string get_db_main_file_name() const; - db_engine_type get_engine_type() const { return m_engine_type; } - std::string get_engine_name() const; - std::string get_config_folder() const { return m_config_folder; } - std::string get_temp_config_folder() const; - std::string get_temp_db_folder_path() const; - - std::string get_pool_db_folder_path() const; - - std::shared_ptr create_backend(); - - private: - db_engine_type m_engine_type; - std::string m_config_folder; - }; - - } // namespace db -} // namespace tools diff --git a/src/common/difficulty_boost_serialization.h b/src/common/difficulty_boost_serialization.h deleted file mode 100644 index 3630423..0000000 --- a/src/common/difficulty_boost_serialization.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include - -namespace boost -{ - namespace serialization - { - //--------------------------------------------------- - template - inline void serialize(archive_t &a, currency::wide_difficulty_type &x, const boost::serialization::version_type ver) - { - if(archive_t::is_loading::value) - { - //load high part - uint64_t v = 0; -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "loading" << ENDL; -#endif - a & v; - x = v; -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "hight part: " << std::hex << v << ENDL; -#endif - //load low part - x = x << 64; - a & v; -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "low part: " << std::hex << v << ENDL; -#endif - x += v; -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "loaded value: " << std::hex << x << ENDL; -#endif - }else - { -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "storing" << ENDL; -#endif - //store high part - currency::wide_difficulty_type x_ = x; -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "original: " << std::hex << x_ << ENDL; -#endif - x_ = x_ >> 64; - uint64_t v = x_.convert_to(); -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "hight part: " << std::hex << v << ENDL; -#endif - a & v; - //store low part - x_ = x; - x_ = x_ << 64; - x_ = x_ >> 64; - v = x_.convert_to(); -#ifdef DEBUG_DIFFICULTY_SERIALIZATION - std::cout << "low part: " << std::hex << v << ENDL; -#endif - a & v; - } - } - } -} diff --git a/src/common/encryption_filter.cpp b/src/common/encryption_filter.cpp deleted file mode 100644 index 8861fa8..0000000 --- a/src/common/encryption_filter.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#include "encryption_filter.h" -#include "crypto/chacha8_stream.h" \ No newline at end of file diff --git a/src/common/encryption_filter.h b/src/common/encryption_filter.h deleted file mode 100644 index 854dc7a..0000000 --- a/src/common/encryption_filter.h +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include // sink_tag -#include // boost::iostreams::write, boost::iostreams::read -#include "include_base_utils.h" -#include "crypto/chacha8.h" -#include "crypto/chacha8_stream.h" - - -namespace tools -{ - - /************************************************************************/ - /* */ - /************************************************************************/ - - class encrypt_chacha_processer_base - { - public: - typedef char char_type; - //typedef boost::iostreams::multichar_output_filter_tag category; - //typedef boost::iostreams::flushable_tag category; - static const uint32_t block_size = ECRYPT_BLOCKLENGTH; - - encrypt_chacha_processer_base(std::string const &pass, const crypto::chacha8_iv& iv) :m_iv(iv), m_ctx(AUTO_VAL_INIT(m_ctx)) - { - crypto::generate_chacha8_key(pass, m_key); - ECRYPT_keysetup(&m_ctx, &m_key.data[0], sizeof(m_key.data) * 8, sizeof(m_iv.data) * 8); - ECRYPT_ivsetup(&m_ctx, &m_iv.data[0]); - } - ~encrypt_chacha_processer_base() - { - - } - - template - std::streamsize process(char_type const * const buf, std::streamsize const n, cb_handler cb) const - { - if (n == 0) - return n; - if (n%ECRYPT_BLOCKLENGTH == 0 && m_buff.empty()) - { - std::vector buff(n); - ECRYPT_encrypt_blocks(&m_ctx, (u8*)buf, (u8*)&buff[0], (u32)(n / ECRYPT_BLOCKLENGTH)); - cb(&buff[0], n); - //m_underlying_stream.write(&buff[0], n); - return n; - } - else - { - m_buff.append(buf, n); - size_t encr_count = m_buff.size() - m_buff.size() % ECRYPT_BLOCKLENGTH; - if (!encr_count) - return n; - std::vector buff(encr_count); - ECRYPT_encrypt_blocks(&m_ctx, (u8*)m_buff.data(), (u8*)&buff[0], (u32)(m_buff.size() / ECRYPT_BLOCKLENGTH)); - //m_underlying_stream.write(&buff[0], encr_count); - cb(&buff[0], encr_count); - m_buff.erase(0, encr_count); - return encr_count; - } - - } - - template - bool flush(cb_handler cb) - { - if (m_buff.empty()) - return true; - - std::vector buff(m_buff.size()); - ECRYPT_encrypt_bytes(&m_ctx, (u8*)m_buff.data(), (u8*)&buff[0], (u32)m_buff.size()); - cb(&buff[0], m_buff.size()); - //m_underlying_stream.write(&buff[0], m_buff.size()); - return true; - } - - private: - const crypto::chacha8_iv& m_iv; - mutable ECRYPT_ctx m_ctx; - //std::ostream &m_underlying_stream; - crypto::chacha8_key m_key; - mutable std::string m_buff; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - - class encrypt_chacha_out_filter : public encrypt_chacha_processer_base - { - public: - typedef char char_type; - struct category : - public boost::iostreams::multichar_output_filter_tag, - public boost::iostreams::flushable_tag - { }; - - encrypt_chacha_out_filter(std::string const &pass, const crypto::chacha8_iv& iv) :encrypt_chacha_processer_base(pass, iv) - { - } - ~encrypt_chacha_out_filter() - { - } - - template - std::streamsize write(t_sink& snk, char_type const * const buf, std::streamsize const n) const - { - return encrypt_chacha_processer_base::process(buf, n, [&](char_type const * const buf_lambda, std::streamsize const n_lambda) { - boost::iostreams::write(snk, &buf_lambda[0], n_lambda); - }); - } - - template - bool flush(Sink& snk) - { - - encrypt_chacha_processer_base::flush([&](char_type const * const buf_lambda, std::streamsize const n_lambda) { - boost::iostreams::write(snk, &buf_lambda[0], n_lambda); - }); - return true; - } - - private: - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - - class encrypt_chacha_in_filter : public encrypt_chacha_processer_base - { - public: - typedef char char_type; - struct category : //public boost::iostreams::seekable_device_tag, - public boost::iostreams::multichar_input_filter_tag, - public boost::iostreams::flushable_tag - //public boost::iostreams::seekable_filter_tag - { }; - encrypt_chacha_in_filter(std::string const &pass, const crypto::chacha8_iv& iv) :encrypt_chacha_processer_base(pass, iv), m_was_eof(false) - { - } - ~encrypt_chacha_in_filter() - { - } - - template - std::streamsize read(Source& src, char* s, std::streamsize n) - { - if (m_buff.size() >= static_cast(n)) - { - return withdraw_to_read_buff(s, n); - } - if (m_was_eof && m_buff.empty()) - { - return -1; - } - - std::streamsize size_to_read_for_decrypt = (n - m_buff.size()); - size_to_read_for_decrypt += size_to_read_for_decrypt % encrypt_chacha_processer_base::block_size; - size_t offset_in_buff = m_buff.size(); - m_buff.resize(m_buff.size() + size_to_read_for_decrypt); - - std::streamsize result = boost::iostreams::read(src, (char*)&m_buff.data()[offset_in_buff], size_to_read_for_decrypt); - if (result == size_to_read_for_decrypt) - { - //regular read proocess, readed data enought to get decrypteds - encrypt_chacha_processer_base::process(&m_buff.data()[offset_in_buff], size_to_read_for_decrypt, [&](char_type const* const buf_lambda, std::streamsize const n_lambda) - { - CHECK_AND_ASSERT_THROW_MES(n_lambda == size_to_read_for_decrypt, "Error in decrypt: check n_lambda == size_to_read_for_decrypt failed"); - std::memcpy((char*)&m_buff.data()[offset_in_buff], buf_lambda, n_lambda); - }); - return withdraw_to_read_buff(s, n); - } - else - { - //been read some size_but it's basically might be eof - if (!m_was_eof) - { - size_t offset_before_flush = offset_in_buff; - if (result != -1) - { - //eof - encrypt_chacha_processer_base::process(&m_buff.data()[offset_in_buff], result, [&](char_type const* const buf_lambda, std::streamsize const n_lambda) { - std::memcpy((char*)&m_buff.data()[offset_in_buff], buf_lambda, n_lambda); - offset_before_flush = offset_in_buff + n_lambda; - }); - } - - encrypt_chacha_processer_base::flush([&](char_type const* const buf_lambda, std::streamsize const n_lambda) { - if (n_lambda + offset_before_flush > m_buff.size()) - { - m_buff.resize(n_lambda + offset_before_flush); - } - std::memcpy((char*)&m_buff.data()[offset_before_flush], buf_lambda, n_lambda); - m_buff.resize(offset_before_flush + n_lambda); - }); - - //just to make sure that it's over - std::string buff_stub(10, ' '); - std::streamsize r = boost::iostreams::read(src, (char*)&buff_stub.data()[0], 10); - CHECK_AND_ASSERT_THROW_MES(r == -1, "expected EOF"); - m_was_eof = true; - return withdraw_to_read_buff(s, n); - } - else - { - return -1; - } - } - } - - - template - bool flush(Sink& snk) - { - - return true; - } - - private: - - std::streamsize withdraw_to_read_buff(char* s, std::streamsize n) - { - - size_t copy_size = m_buff.size() > static_cast(n) ? static_cast(n) : m_buff.size(); - std::memcpy(s, m_buff.data(), copy_size); - m_buff.erase(0, copy_size); - return copy_size; - } - - std::string m_buff; - bool m_was_eof; - }; -} \ No newline at end of file diff --git a/src/common/error_codes.h b/src/common/error_codes.h deleted file mode 100644 index 7b77fec..0000000 --- a/src/common/error_codes.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#define API_RETURN_CODE_OK BASIC_RESPONSE_STATUS_OK -#define API_RETURN_CODE_FAIL BASIC_RESPONSE_STATUS_FAILED -#define API_RETURN_CODE_NOT_FOUND BASIC_RESPONSE_STATUS_NOT_FOUND -#define API_RETURN_CODE_ACCESS_DENIED "ACCESS_DENIED" -#define API_RETURN_CODE_INTERNAL_ERROR "INTERNAL_ERROR" -#define API_RETURN_CODE_NOT_ENOUGH_MONEY "NOT_ENOUGH_MONEY" -#define API_RETURN_CODE_NOT_ENOUGH_OUTPUTS_FOR_MIXING "NOT_ENOUGH_OUTPUTS_FOR_MIXING" -#define API_RETURN_CODE_INTERNAL_ERROR_QUE_FULL "INTERNAL_ERROR_QUE_FULL" -#define API_RETURN_CODE_BAD_ARG "BAD_ARG" -#define API_RETURN_CODE_BAD_ARG_EMPTY_DESTINATIONS "BAD_ARG_EMPTY_DESTINATIONS" -#define API_RETURN_CODE_BAD_ARG_WRONG_FEE "BAD_ARG_WRONG_FEE" -#define API_RETURN_CODE_BAD_ARG_INVALID_ADDRESS "BAD_ARG_INVALID_ADDRESS" -#define API_RETURN_CODE_BAD_ARG_WRONG_AMOUNT "BAD_ARG_WRONG_AMOUNT" -#define API_RETURN_CODE_BAD_ARG_WRONG_PAYMENT_ID "BAD_ARG_WRONG_PAYMENT_ID" -#define API_RETURN_CODE_WRONG_PASSWORD "WRONG_PASSWORD" -#define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID" -#define API_RETURN_CODE_WALLET_WATCH_ONLY_NOT_SUPPORTED "WALLET_WATCH_ONLY_NOT_SUPPORTED" -#define API_RETURN_CODE_WALLET_AUDITABLE_NOT_SUPPORTED "WALLET_AUDITABLE_NOT_SUPPORTED" -#define API_RETURN_CODE_FILE_NOT_FOUND "FILE_NOT_FOUND" -#define API_RETURN_CODE_ALREADY_EXISTS "ALREADY_EXISTS" -#define API_RETURN_CODE_CANCELED "CANCELED" -#define API_RETURN_CODE_FILE_RESTORED "FILE_RESTORED" -#define API_RETURN_CODE_TRUE "TRUE" -#define API_RETURN_CODE_FALSE "FALSE" -#define API_RETURN_CODE_CORE_BUSY "CORE_BUSY" -#define API_RETURN_CODE_OVERFLOW "OVERFLOW" -#define API_RETURN_CODE_BUSY "BUSY" -#define API_RETURN_CODE_INVALID_FILE "INVALID_FILE" -#define API_RETURN_CODE_WRONG_SEED "WRONG_SEED" -#define API_RETURN_CODE_GENESIS_MISMATCH "GENESIS_MISMATCH" -#define API_RETURN_CODE_DISCONNECTED "DISCONNECTED" -#define API_RETURN_CODE_UNINITIALIZED "UNINITIALIZED" -#define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG" -#define API_RETURN_CODE_TX_REJECTED "TX_REJECTED" -#define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED" -#define API_RETURN_CODE_WRAP "WRAP" \ No newline at end of file diff --git a/src/common/general_purpose_commands_defs.h b/src/common/general_purpose_commands_defs.h deleted file mode 100644 index f9da996..0000000 --- a/src/common/general_purpose_commands_defs.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "serialization/keyvalue_hexemizer.h" -#include "currency_core/currency_basic.h" -#include "storages/portable_storage_base.h" -#include "currency_core/basic_api_response_codes.h" -#include "common/error_codes.h" -namespace currency -{ - //----------------------------------------------- - - - struct tx_cost_struct - { - std::string usd_needed_for_erc20; - std::string zano_needed_for_erc20; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(usd_needed_for_erc20) - KV_SERIALIZE(zano_needed_for_erc20) - END_KV_SERIALIZE_MAP() - }; - - struct rpc_get_wrap_info_response - { - std::string unwraped_coins_left; - tx_cost_struct tx_cost; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(unwraped_coins_left) - KV_SERIALIZE(tx_cost) - END_KV_SERIALIZE_MAP() - }; - - -} - diff --git a/src/common/int-util.h b/src/common/int-util.h deleted file mode 100644 index ddf06df..0000000 --- a/src/common/int-util.h +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include - -#if defined(_MSC_VER) -#include -#include - -#if !defined(__ORDER_LITTLE_ENDIAN__) -#define __ORDER_LITTLE_ENDIAN__ 1011012001 -#endif - -#if !defined(__BYTE_ORDER__) -#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -#endif - -#if !defined(__ORDER_BIG_ENDIAN__) -#define __ORDER_BIG_ENDIAN__ 0 -#endif - -static inline uint32_t rol32(uint32_t x, int r) { - static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers"); - return _rotl(x, r); -} - -static inline uint64_t rol64(uint64_t x, int r) { - return _rotl64(x, r); -} - -#else - -static inline uint32_t rol32(uint32_t x, int r) { - return (x << (r & 31)) | (x >> (-r & 31)); -} - -static inline uint64_t rol64(uint64_t x, int r) { - return (x << (r & 63)) | (x >> (-r & 63)); -} - -#endif - -static inline uint64_t hi_dword(uint64_t val) { - return val >> 32; -} - -static inline uint64_t lo_dword(uint64_t val) { - return val & 0xFFFFFFFF; -} - -static inline uint64_t mul128_manually(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) { - // multiplier = ab = a * 2^32 + b - // multiplicand = cd = c * 2^32 + d - // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d - uint64_t a = hi_dword(multiplier); - uint64_t b = lo_dword(multiplier); - uint64_t c = hi_dword(multiplicand); - uint64_t d = lo_dword(multiplicand); - - uint64_t ac = a * c; - uint64_t ad = a * d; - uint64_t bc = b * c; - uint64_t bd = b * d; - - uint64_t adbc = ad + bc; - uint64_t adbc_carry = adbc < ad ? 1 : 0; - - // multiplier * multiplicand = product_hi * 2^64 + product_lo - uint64_t product_lo = bd + (adbc << 32); - uint64_t product_lo_carry = product_lo < bd ? 1 : 0; - *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; - assert(ac <= *product_hi); - - return product_lo; -} - -static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { - dividend |= ((uint64_t)*remainder) << 32; - *remainder = dividend % divisor; - return dividend / divisor; -} - -// Long division with 2^32 base -static inline uint32_t div128_32_manually(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { - uint64_t dividend_dwords[4]; - uint32_t remainder = 0; - - dividend_dwords[3] = hi_dword(dividend_hi); - dividend_dwords[2] = lo_dword(dividend_hi); - dividend_dwords[1] = hi_dword(dividend_lo); - dividend_dwords[0] = lo_dword(dividend_lo); - - *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32; - *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder); - *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32; - *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder); - - return remainder; -} - -static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) -{ -// #if defined(_MSC_VER) -// return _umul128(multiplier, multiplicand, product_hi); -// #elif defined(__GNUC__) -// __uint128_t product = ((__uint128_t)multiplier) * multiplicand; -// *product_hi = (uint64_t)(product >> 64); -// return ((uint64_t)product) & ~(UINT64_C(0)); -// #else - return mul128_manually(multiplier, multiplicand, product_hi); -//#endif*/ -} -//*/ - -static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) -{ -// #if defined(__GNUC__) -// __uint128_t dividend = (((__uint128_t)dividend_hi) << 64) | dividend_lo; -// __uint128_t quotient = dividend / divisor; -// __uint128_t reminder = dividend % divisor; -// *quotient_hi = (uint64_t)(quotient >> 64); -// *quotient_lo = ((uint64_t)quotient) & ~(UINT64_C(0)); -// return (uint32_t)reminder; -// #else - return div128_32_manually(dividend_hi, dividend_lo, divisor, quotient_hi, quotient_lo); -//#endif -} -//*/ -#define IDENT32(x) ((uint32_t) (x)) -#define IDENT64(x) ((uint64_t) (x)) - -#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \ - (((uint32_t) (x) & 0x0000ff00) << 8) | \ - (((uint32_t) (x) & 0x00ff0000) >> 8) | \ - (((uint32_t) (x) & 0xff000000) >> 24)) -#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \ - (((uint64_t) (x) & 0x000000000000ff00) << 40) | \ - (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \ - (((uint64_t) (x) & 0x00000000ff000000) << 8) | \ - (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \ - (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \ - (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \ - (((uint64_t) (x) & 0xff00000000000000) >> 56)) - -static inline uint32_t ident32(uint32_t x) { return x; } -static inline uint64_t ident64(uint64_t x) { return x; } - -static inline uint32_t swap32(uint32_t x) { - x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); - return (x << 16) | (x >> 16); -} -static inline uint64_t swap64(uint64_t x) { - x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); - x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); - return (x << 32) | (x >> 32); -} - -#if defined(__GNUC__) -#define UNUSED __attribute__((unused)) -#else -#define UNUSED -#endif -static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { } -#undef UNUSED - -static inline void mem_inplace_swap32(void *mem, size_t n) { - size_t i; - for (i = 0; i < n; i++) { - ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]); - } -} -static inline void mem_inplace_swap64(void *mem, size_t n) { - size_t i; - for (i = 0; i < n; i++) { - ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]); - } -} - -static inline void memcpy_ident32(void *dst, const void *src, size_t n) { - memcpy(dst, src, 4 * n); -} -static inline void memcpy_ident64(void *dst, const void *src, size_t n) { - memcpy(dst, src, 8 * n); -} - -static inline void memcpy_swap32(void *dst, const void *src, size_t n) { - size_t i; - for (i = 0; i < n; i++) { - ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]); - } -} -static inline void memcpy_swap64(void *dst, const void *src, size_t n) { - size_t i; - for (i = 0; i < n; i++) { - ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]); - } -} - -#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__ORDER_BIG_ENDIAN__) -static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); -#endif - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define SWAP32LE IDENT32 -#define SWAP32BE SWAP32 -#define swap32le ident32 -#define swap32be swap32 -#define mem_inplace_swap32le mem_inplace_ident -#define mem_inplace_swap32be mem_inplace_swap32 -#define memcpy_swap32le memcpy_ident32 -#define memcpy_swap32be memcpy_swap32 -#define SWAP64LE IDENT64 -#define SWAP64BE SWAP64 -#define swap64le ident64 -#define swap64be swap64 -#define mem_inplace_swap64le mem_inplace_ident -#define mem_inplace_swap64be mem_inplace_swap64 -#define memcpy_swap64le memcpy_ident64 -#define memcpy_swap64be memcpy_swap64 -#endif - -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define SWAP32BE IDENT32 -#define SWAP32LE SWAP32 -#define swap32be ident32 -#define swap32le swap32 -#define mem_inplace_swap32be mem_inplace_ident -#define mem_inplace_swap32le mem_inplace_swap32 -#define memcpy_swap32be memcpy_ident32 -#define memcpy_swap32le memcpy_swap32 -#define SWAP64BE IDENT64 -#define SWAP64LE SWAP64 -#define swap64be ident64 -#define swap64le swap64 -#define mem_inplace_swap64be mem_inplace_ident -#define mem_inplace_swap64le mem_inplace_swap64 -#define memcpy_swap64be memcpy_ident64 -#define memcpy_swap64le memcpy_swap64 -#endif diff --git a/src/common/make_hashable.h b/src/common/make_hashable.h deleted file mode 100644 index c22bfa4..0000000 --- a/src/common/make_hashable.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014-2020 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - -#define POD_MAKE_COMPARABLE(space, type) \ -namespace space { \ - inline bool operator==(const type &_v1, const type &_v2) { \ - return std::memcmp(&_v1, &_v2, sizeof(type)) == 0; \ - } \ - inline bool operator!=(const type &_v1, const type &_v2) { \ - return std::memcmp(&_v1, &_v2, sizeof(type)) != 0; \ - } \ -} - -#define POD_MAKE_HASHABLE(space, type) \ - POD_MAKE_COMPARABLE(space, type) \ -namespace space { \ - static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \ - inline std::size_t hash_value(const type &_v) { \ - return reinterpret_cast(_v); \ - } \ -} \ -namespace std { \ - template<> \ - struct hash { \ - std::size_t operator()(const space::type &_v) const { \ - return reinterpret_cast(_v); \ - } \ - }; \ -} - -namespace std -{ - - // this allows using std::pair<> as a key in unordered std containers - template - struct hash> - { - size_t operator()(const pair& p) const - { - auto hash1 = hash{}(p.first); - auto hash2 = hash{}(p.second); - return hash1 ^ hash2; - } - }; - -} // namespace std - diff --git a/src/common/median_db_cache.h b/src/common/median_db_cache.h deleted file mode 100644 index 2e2dea5..0000000 --- a/src/common/median_db_cache.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "misc_language.h" - -namespace tools -{ -#define LOC_INT_ERR(cond, msg) CHECK_AND_ASSERT_THROW_MES(cond, "internal error in median_db_cache: " << msg << ENDL << *this) - template - class median_db_cache : public epee::misc_utils::median_helper - { - typedef epee::misc_utils::median_helper super_t; - struct db_entry_type - { - key k; - associated_data d; - }; - - //m_tx_median_helper; - typedef tools::db::cached_key_value_accessor median_db_container; - median_db_container m_median_container; - uint64_t m_counter_hi; - uint64_t m_counter_lo; - bool m_is_loading_from_db; - - bool load_items_from_db() - { - std::map loaded_entries; - LOG_PRINT_L0("Loading median from db cache..."); - m_median_container.enumerate_items([&](uint64_t i, uint64_t index, const db_entry_type& entry) - { - //adjust counters - if (index > m_counter_hi) - m_counter_hi = index; - if (index < m_counter_lo) - m_counter_lo = index; - loaded_entries[index] = entry; - return true; - }); - LOG_PRINT_L0("Loaded " << loaded_entries.size() << " items, building median cache..."); - - m_is_loading_from_db = true; - for (auto i : loaded_entries) - { - this->push_item(i.second.k, i.second.d); - } - m_is_loading_from_db = false; - LOG_PRINT_L0("Median cache build OK"); - return true; - } - virtual void handle_add_front_item(const key& k, const associated_data& ad) - { - if (m_is_loading_from_db) - return; - db_entry_type det = AUTO_VAL_INIT(det); - det.k = k; - det.d = ad; - m_median_container.set(++m_counter_hi, det); - - //in case if it was totally empty at init(which is very doubtful) - if (m_counter_lo == std::numeric_limits::max()) - m_counter_lo = m_counter_hi; - - } - virtual void handle_remove_front_item(const key& k) - { - LOC_INT_ERR(!m_is_loading_from_db, "m_is_loading_from_db is true"); - LOC_INT_ERR(m_median_container.erase_validate(m_counter_hi), "erase_validate failed"); - --m_counter_hi; - //TODO: check coretests and make a decision on what to do with the following check - //LOC_INT_ERR(m_counter_lo <= m_counter_hi, "handle_remove_front_item: m_counter_lo(" << m_counter_lo << ") > m_counter_hi(" << m_counter_hi << ")"); - } - virtual void handle_purge_back_item() - { - LOC_INT_ERR(m_counter_lo < m_counter_hi, "handle_purge_back_item: m_counter_lo(" << m_counter_lo << ") >= m_counter_hi(" << m_counter_hi << ")"); - m_median_container.erase(m_counter_lo++); - } - - - - public: - median_db_cache(db::basic_db_accessor& db) : - m_median_container(db), - m_counter_hi(0), - m_counter_lo(std::numeric_limits::max()), - m_is_loading_from_db(false) - { - - } - bool init(const std::string& name) - { - bool r = m_median_container.init(name); - CHECK_AND_ASSERT_MES(r, false, "Failed to init m_median_container"); - return load_items_from_db(); - } - - ~median_db_cache() - { - } - - void clear() - { - super_t::clear(); - m_median_container.clear(); - m_counter_hi = 0; - m_counter_lo = std::numeric_limits::max(); - } - - template - friend std::ostream& operator<<(std::ostream& ss, const median_db_cache &mdbc); - }; // class median_db_cache -#undef LOC_INT_ERR - - template - inline std::ostream& operator<<(std::ostream& s, const median_db_cache &mdbc) - { - s << "median_db_cache<" << typeid(key_t).name() << ", " << typeid(associated_data_t).name() << "> instance 0x" << &mdbc << ENDL - << " m_counter_lo: " << mdbc.m_counter_lo << ENDL - << " m_counter_hi: " << mdbc.m_counter_hi << ENDL - << " m_is_loading_from_db: " << mdbc.m_is_loading_from_db << ENDL - << " m_median_container.size: " << mdbc.m_median_container.size() << ENDL - << " m_median_container.size_no_cache(): " << mdbc.m_median_container.size_no_cache() << ENDL - << "parent " << static_cast>(mdbc); - return s; - } - - -} \ No newline at end of file diff --git a/src/common/miniupnp_helper.h b/src/common/miniupnp_helper.h deleted file mode 100644 index be7c688..0000000 --- a/src/common/miniupnp_helper.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include "include_base_utils.h" -extern "C" { -#include "miniupnp/miniupnpc/miniupnpc.h" -#include "miniupnp/miniupnpc/upnpcommands.h" -#include "miniupnp/miniupnpc/upnperrors.h" -} - -#include "misc_language.h" -#include "currency_core/currency_config.h" -#include "version.h" - -namespace tools -{ - class miniupnp_helper - { - UPNPDev *m_devlist; - UPNPUrls m_urls; - IGDdatas m_data; - char m_lanaddr[64]; - int m_IGD; - boost::thread m_mapper_thread; - boost::thread m_initializer_thread; - uint32_t m_external_port; - uint32_t m_internal_port; - uint32_t m_period_ms; - public: - miniupnp_helper():m_devlist(nullptr), - m_urls(AUTO_VAL_INIT(m_urls)), - m_data(AUTO_VAL_INIT(m_data)), - m_IGD(0), - m_external_port(0), - m_internal_port(0), - m_period_ms(0) - { - m_lanaddr[0] = 0; - } - ~miniupnp_helper() - { - NESTED_TRY_ENTRY(); - - deinit(); - - NESTED_CATCH_ENTRY(__func__); - } - - bool start_regular_mapping(uint32_t internal_port, uint32_t external_port, uint32_t period_ms) - { - m_external_port = external_port; - m_internal_port = internal_port; - m_period_ms = period_ms; - if(!init()) - return false; - return true; - } - - bool stop_mapping() - { - if(m_mapper_thread.joinable()) - { - m_mapper_thread.interrupt(); - m_mapper_thread.join(); - } - - if(m_IGD == 1) - { - do_port_unmapping(); - } - return true; - } - - private: - - bool init() - { - m_initializer_thread = boost::thread([=]() - { - deinit(); - - int error = 0; - m_devlist = upnpDiscover(2000, nullptr, nullptr, 0, 0, 2, &error); - if (error) - { - LOG_PRINT_L0("Failed to call upnpDiscover"); - return false; - } - - m_IGD = UPNP_GetValidIGD(m_devlist, &m_urls, &m_data, m_lanaddr, sizeof(m_lanaddr)); - if (m_IGD != 1) - { - LOG_PRINT_L2("IGD not found"); - return false; - } - - m_mapper_thread = boost::thread([=]() {run_port_mapping_loop(m_internal_port, m_external_port, m_period_ms); }); - return true; - }); - return true; - } - - bool deinit() - { - if(m_initializer_thread.get_id() != boost::this_thread::get_id()) - { - if (m_initializer_thread.joinable()) - { - m_initializer_thread.interrupt(); - m_initializer_thread.join(); - } - } - - stop_mapping(); - - if(m_devlist) - { - freeUPNPDevlist(m_devlist); - m_devlist = nullptr; - } - - if(m_IGD > 0) - { - FreeUPNPUrls(&m_urls); - m_IGD = 0; - } - return true; - } - - bool run_port_mapping_loop(uint32_t internal_port, uint32_t external_port, uint32_t period_ms) - { - while(true) - { - do_port_mapping(external_port, internal_port); - boost::this_thread::sleep_for(boost::chrono::milliseconds( period_ms )); - } - return true; - } - - bool do_port_mapping(uint32_t external_port, uint32_t internal_port) - { - std::string internal_port_str = std::to_string(internal_port); - std::string external_port_str = std::to_string(external_port); - std::string str_desc = CURRENCY_NAME " v" PROJECT_VERSION_LONG; - - int r = UPNP_AddPortMapping(m_urls.controlURL, m_data.first.servicetype, - external_port_str.c_str(), internal_port_str.c_str(), m_lanaddr, str_desc.c_str(), "TCP", nullptr, "0"); - - if(r!=UPNPCOMMAND_SUCCESS) - { - LOG_PRINT_L1("AddPortMapping with external_port_str= " << external_port_str << - ", internal_port_str=" << internal_port_str << - ", failed with code=" << r << "(" << strupnperror(r) << ")"); - }else - { - LOG_PRINT_L0("[upnp] port mapped successful (ext: " << external_port_str << ", int:" << internal_port_str << ")"); - } - return true; - } - - void do_port_unmapping() - { - std::string external_port_str = std::to_string(m_external_port); - - int r = UPNP_DeletePortMapping(m_urls.controlURL, m_data.first.servicetype, external_port_str.c_str(), "TCP", nullptr); - if(r!=UPNPCOMMAND_SUCCESS) - { - LOG_PRINT_L1("DeletePortMapping with external_port_str= " << external_port_str << - ", failed with code=" << r << "(" << strupnperror(r) << ")"); - }else - { - LOG_PRINT_L0("[upnp] port unmapped successful (ext: " << external_port_str << ")"); - } - } - }; -} - diff --git a/src/common/mnemonic-encoding.cpp b/src/common/mnemonic-encoding.cpp deleted file mode 100644 index c2e3e30..0000000 --- a/src/common/mnemonic-encoding.cpp +++ /dev/null @@ -1,3395 +0,0 @@ -// Copyright (c) 2014, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* - * This file and its cpp file are for translating Electrum-style word lists - * into their equivalent byte representations for cross-compatibility with - * that method of "backing up" one's wallet keys. - */ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project - - -#include -#include -#include -#include -#include "mnemonic-encoding.h" -#include "include_base_utils.h" - -namespace tools -{ - namespace mnemonic_encoding - { - using namespace std; - - const map wordsMap = { - {"like", 0}, - {"just", 1}, - {"love", 2}, - {"know", 3}, - {"never", 4}, - {"want", 5}, - {"time", 6}, - {"out", 7}, - {"there", 8}, - {"make", 9}, - {"look", 10}, - {"eye", 11}, - {"down", 12}, - {"only", 13}, - {"think", 14}, - {"heart", 15}, - {"back", 16}, - {"then", 17}, - {"into", 18}, - {"about", 19}, - {"more", 20}, - {"away", 21}, - {"still", 22}, - {"them", 23}, - {"take", 24}, - {"thing", 25}, - {"even", 26}, - {"through", 27}, - {"long", 28}, - {"always", 29}, - {"world", 30}, - {"too", 31}, - {"friend", 32}, - {"tell", 33}, - {"try", 34}, - {"hand", 35}, - {"thought", 36}, - {"over", 37}, - {"here", 38}, - {"other", 39}, - {"need", 40}, - {"smile", 41}, - {"again", 42}, - {"much", 43}, - {"cry", 44}, - {"been", 45}, - {"night", 46}, - {"ever", 47}, - {"little", 48}, - {"said", 49}, - {"end", 50}, - {"some", 51}, - {"those", 52}, - {"around", 53}, - {"mind", 54}, - {"people", 55}, - {"girl", 56}, - {"leave", 57}, - {"dream", 58}, - {"left", 59}, - {"turn", 60}, - {"myself", 61}, - {"give", 62}, - {"nothing", 63}, - {"really", 64}, - {"off", 65}, - {"before", 66}, - {"something", 67}, - {"find", 68}, - {"walk", 69}, - {"wish", 70}, - {"good", 71}, - {"once", 72}, - {"place", 73}, - {"ask", 74}, - {"stop", 75}, - {"keep", 76}, - {"watch", 77}, - {"seem", 78}, - {"everything", 79}, - {"wait", 80}, - {"got", 81}, - {"yet", 82}, - {"made", 83}, - {"remember", 84}, - {"start", 85}, - {"alone", 86}, - {"run", 87}, - {"hope", 88}, - {"maybe", 89}, - {"believe", 90}, - {"body", 91}, - {"hate", 92}, - {"after", 93}, - {"close", 94}, - {"talk", 95}, - {"stand", 96}, - {"own", 97}, - {"each", 98}, - {"hurt", 99}, - {"help", 100}, - {"home", 101}, - {"god", 102}, - {"soul", 103}, - {"new", 104}, - {"many", 105}, - {"two", 106}, - {"inside", 107}, - {"should", 108}, - {"true", 109}, - {"first", 110}, - {"fear", 111}, - {"mean", 112}, - {"better", 113}, - {"play", 114}, - {"another", 115}, - {"gone", 116}, - {"change", 117}, - {"use", 118}, - {"wonder", 119}, - {"someone", 120}, - {"hair", 121}, - {"cold", 122}, - {"open", 123}, - {"best", 124}, - {"any", 125}, - {"behind", 126}, - {"happen", 127}, - {"water", 128}, - {"dark", 129}, - {"laugh", 130}, - {"stay", 131}, - {"forever", 132}, - {"name", 133}, - {"work", 134}, - {"show", 135}, - {"sky", 136}, - {"break", 137}, - {"came", 138}, - {"deep", 139}, - {"door", 140}, - {"put", 141}, - {"black", 142}, - {"together", 143}, - {"upon", 144}, - {"happy", 145}, - {"such", 146}, - {"great", 147}, - {"white", 148}, - {"matter", 149}, - {"fill", 150}, - {"past", 151}, - {"please", 152}, - {"burn", 153}, - {"cause", 154}, - {"enough", 155}, - {"touch", 156}, - {"moment", 157}, - {"soon", 158}, - {"voice", 159}, - {"scream", 160}, - {"anything", 161}, - {"stare", 162}, - {"sound", 163}, - {"red", 164}, - {"everyone", 165}, - {"hide", 166}, - {"kiss", 167}, - {"truth", 168}, - {"death", 169}, - {"beautiful", 170}, - {"mine", 171}, - {"blood", 172}, - {"broken", 173}, - {"very", 174}, - {"pass", 175}, - {"next", 176}, - {"forget", 177}, - {"tree", 178}, - {"wrong", 179}, - {"air", 180}, - {"mother", 181}, - {"understand", 182}, - {"lip", 183}, - {"hit", 184}, - {"wall", 185}, - {"memory", 186}, - {"sleep", 187}, - {"free", 188}, - {"high", 189}, - {"realize", 190}, - {"school", 191}, - {"might", 192}, - {"skin", 193}, - {"sweet", 194}, - {"perfect", 195}, - {"blue", 196}, - {"kill", 197}, - {"breath", 198}, - {"dance", 199}, - {"against", 200}, - {"fly", 201}, - {"between", 202}, - {"grow", 203}, - {"strong", 204}, - {"under", 205}, - {"listen", 206}, - {"bring", 207}, - {"sometimes", 208}, - {"speak", 209}, - {"pull", 210}, - {"person", 211}, - {"become", 212}, - {"family", 213}, - {"begin", 214}, - {"ground", 215}, - {"real", 216}, - {"small", 217}, - {"father", 218}, - {"sure", 219}, - {"feet", 220}, - {"rest", 221}, - {"young", 222}, - {"finally", 223}, - {"land", 224}, - {"across", 225}, - {"today", 226}, - {"different", 227}, - {"guy", 228}, - {"line", 229}, - {"fire", 230}, - {"reason", 231}, - {"reach", 232}, - {"second", 233}, - {"slowly", 234}, - {"write", 235}, - {"eat", 236}, - {"smell", 237}, - {"mouth", 238}, - {"step", 239}, - {"learn", 240}, - {"three", 241}, - {"floor", 242}, - {"promise", 243}, - {"breathe", 244}, - {"darkness", 245}, - {"push", 246}, - {"earth", 247}, - {"guess", 248}, - {"save", 249}, - {"song", 250}, - {"above", 251}, - {"along", 252}, - {"both", 253}, - {"color", 254}, - {"house", 255}, - {"almost", 256}, - {"sorry", 257}, - {"anymore", 258}, - {"brother", 259}, - {"okay", 260}, - {"dear", 261}, - {"game", 262}, - {"fade", 263}, - {"already", 264}, - {"apart", 265}, - {"warm", 266}, - {"beauty", 267}, - {"heard", 268}, - {"notice", 269}, - {"question", 270}, - {"shine", 271}, - {"began", 272}, - {"piece", 273}, - {"whole", 274}, - {"shadow", 275}, - {"secret", 276}, - {"street", 277}, - {"within", 278}, - {"finger", 279}, - {"point", 280}, - {"morning", 281}, - {"whisper", 282}, - {"child", 283}, - {"moon", 284}, - {"green", 285}, - {"story", 286}, - {"glass", 287}, - {"kid", 288}, - {"silence", 289}, - {"since", 290}, - {"soft", 291}, - {"yourself", 292}, - {"empty", 293}, - {"shall", 294}, - {"angel", 295}, - {"answer", 296}, - {"baby", 297}, - {"bright", 298}, - {"dad", 299}, - {"path", 300}, - {"worry", 301}, - {"hour", 302}, - {"drop", 303}, - {"follow", 304}, - {"power", 305}, - {"war", 306}, - {"half", 307}, - {"flow", 308}, - {"heaven", 309}, - {"act", 310}, - {"chance", 311}, - {"fact", 312}, - {"least", 313}, - {"tired", 314}, - {"children", 315}, - {"near", 316}, - {"quite", 317}, - {"afraid", 318}, - {"rise", 319}, - {"sea", 320}, - {"taste", 321}, - {"window", 322}, - {"cover", 323}, - {"nice", 324}, - {"trust", 325}, - {"lot", 326}, - {"sad", 327}, - {"cool", 328}, - {"force", 329}, - {"peace", 330}, - {"return", 331}, - {"blind", 332}, - {"easy", 333}, - {"ready", 334}, - {"roll", 335}, - {"rose", 336}, - {"drive", 337}, - {"held", 338}, - {"music", 339}, - {"beneath", 340}, - {"hang", 341}, - {"mom", 342}, - {"paint", 343}, - {"emotion", 344}, - {"quiet", 345}, - {"clear", 346}, - {"cloud", 347}, - {"few", 348}, - {"pretty", 349}, - {"bird", 350}, - {"outside", 351}, - {"paper", 352}, - {"picture", 353}, - {"front", 354}, - {"rock", 355}, - {"simple", 356}, - {"anyone", 357}, - {"meant", 358}, - {"reality", 359}, - {"road", 360}, - {"sense", 361}, - {"waste", 362}, - {"bit", 363}, - {"leaf", 364}, - {"thank", 365}, - {"happiness", 366}, - {"meet", 367}, - {"men", 368}, - {"smoke", 369}, - {"truly", 370}, - {"decide", 371}, - {"self", 372}, - {"age", 373}, - {"book", 374}, - {"form", 375}, - {"alive", 376}, - {"carry", 377}, - {"escape", 378}, - {"damn", 379}, - {"instead", 380}, - {"able", 381}, - {"ice", 382}, - {"minute", 383}, - {"throw", 384}, - {"catch", 385}, - {"leg", 386}, - {"ring", 387}, - {"course", 388}, - {"goodbye", 389}, - {"lead", 390}, - {"poem", 391}, - {"sick", 392}, - {"corner", 393}, - {"desire", 394}, - {"known", 395}, - {"problem", 396}, - {"remind", 397}, - {"shoulder", 398}, - {"suppose", 399}, - {"toward", 400}, - {"wave", 401}, - {"drink", 402}, - {"jump", 403}, - {"woman", 404}, - {"pretend", 405}, - {"sister", 406}, - {"week", 407}, - {"human", 408}, - {"joy", 409}, - {"crack", 410}, - {"grey", 411}, - {"pray", 412}, - {"surprise", 413}, - {"dry", 414}, - {"knee", 415}, - {"less", 416}, - {"search", 417}, - {"bleed", 418}, - {"caught", 419}, - {"clean", 420}, - {"embrace", 421}, - {"future", 422}, - {"king", 423}, - {"son", 424}, - {"sorrow", 425}, - {"chest", 426}, - {"hug", 427}, - {"remain", 428}, - {"sat", 429}, - {"worth", 430}, - {"blow", 431}, - {"daddy", 432}, - {"final", 433}, - {"parent", 434}, - {"tight", 435}, - {"also", 436}, - {"create", 437}, - {"lonely", 438}, - {"safe", 439}, - {"cross", 440}, - {"dress", 441}, - {"evil", 442}, - {"silent", 443}, - {"bone", 444}, - {"fate", 445}, - {"perhaps", 446}, - {"anger", 447}, - {"class", 448}, - {"scar", 449}, - {"snow", 450}, - {"tiny", 451}, - {"tonight", 452}, - {"continue", 453}, - {"control", 454}, - {"dog", 455}, - {"edge", 456}, - {"mirror", 457}, - {"month", 458}, - {"suddenly", 459}, - {"comfort", 460}, - {"given", 461}, - {"loud", 462}, - {"quickly", 463}, - {"gaze", 464}, - {"plan", 465}, - {"rush", 466}, - {"stone", 467}, - {"town", 468}, - {"battle", 469}, - {"ignore", 470}, - {"spirit", 471}, - {"stood", 472}, - {"stupid", 473}, - {"yours", 474}, - {"brown", 475}, - {"build", 476}, - {"dust", 477}, - {"hey", 478}, - {"kept", 479}, - {"pay", 480}, - {"phone", 481}, - {"twist", 482}, - {"although", 483}, - {"ball", 484}, - {"beyond", 485}, - {"hidden", 486}, - {"nose", 487}, - {"taken", 488}, - {"fail", 489}, - {"float", 490}, - {"pure", 491}, - {"somehow", 492}, - {"wash", 493}, - {"wrap", 494}, - {"angry", 495}, - {"cheek", 496}, - {"creature", 497}, - {"forgotten", 498}, - {"heat", 499}, - {"rip", 500}, - {"single", 501}, - {"space", 502}, - {"special", 503}, - {"weak", 504}, - {"whatever", 505}, - {"yell", 506}, - {"anyway", 507}, - {"blame", 508}, - {"job", 509}, - {"choose", 510}, - {"country", 511}, - {"curse", 512}, - {"drift", 513}, - {"echo", 514}, - {"figure", 515}, - {"grew", 516}, - {"laughter", 517}, - {"neck", 518}, - {"suffer", 519}, - {"worse", 520}, - {"yeah", 521}, - {"disappear", 522}, - {"foot", 523}, - {"forward", 524}, - {"knife", 525}, - {"mess", 526}, - {"somewhere", 527}, - {"stomach", 528}, - {"storm", 529}, - {"beg", 530}, - {"idea", 531}, - {"lift", 532}, - {"offer", 533}, - {"breeze", 534}, - {"field", 535}, - {"five", 536}, - {"often", 537}, - {"simply", 538}, - {"stuck", 539}, - {"win", 540}, - {"allow", 541}, - {"confuse", 542}, - {"enjoy", 543}, - {"except", 544}, - {"flower", 545}, - {"seek", 546}, - {"strength", 547}, - {"calm", 548}, - {"grin", 549}, - {"gun", 550}, - {"heavy", 551}, - {"hill", 552}, - {"large", 553}, - {"ocean", 554}, - {"shoe", 555}, - {"sigh", 556}, - {"straight", 557}, - {"summer", 558}, - {"tongue", 559}, - {"accept", 560}, - {"crazy", 561}, - {"everyday", 562}, - {"exist", 563}, - {"grass", 564}, - {"mistake", 565}, - {"sent", 566}, - {"shut", 567}, - {"surround", 568}, - {"table", 569}, - {"ache", 570}, - {"brain", 571}, - {"destroy", 572}, - {"heal", 573}, - {"nature", 574}, - {"shout", 575}, - {"sign", 576}, - {"stain", 577}, - {"choice", 578}, - {"doubt", 579}, - {"glance", 580}, - {"glow", 581}, - {"mountain", 582}, - {"queen", 583}, - {"stranger", 584}, - {"throat", 585}, - {"tomorrow", 586}, - {"city", 587}, - {"either", 588}, - {"fish", 589}, - {"flame", 590}, - {"rather", 591}, - {"shape", 592}, - {"spin", 593}, - {"spread", 594}, - {"ash", 595}, - {"distance", 596}, - {"finish", 597}, - {"image", 598}, - {"imagine", 599}, - {"important", 600}, - {"nobody", 601}, - {"shatter", 602}, - {"warmth", 603}, - {"became", 604}, - {"feed", 605}, - {"flesh", 606}, - {"funny", 607}, - {"lust", 608}, - {"shirt", 609}, - {"trouble", 610}, - {"yellow", 611}, - {"attention", 612}, - {"bare", 613}, - {"bite", 614}, - {"money", 615}, - {"protect", 616}, - {"amaze", 617}, - {"appear", 618}, - {"born", 619}, - {"choke", 620}, - {"completely", 621}, - {"daughter", 622}, - {"fresh", 623}, - {"friendship", 624}, - {"gentle", 625}, - {"probably", 626}, - {"six", 627}, - {"deserve", 628}, - {"expect", 629}, - {"grab", 630}, - {"middle", 631}, - {"nightmare", 632}, - {"river", 633}, - {"thousand", 634}, - {"weight", 635}, - {"worst", 636}, - {"wound", 637}, - {"barely", 638}, - {"bottle", 639}, - {"cream", 640}, - {"regret", 641}, - {"relationship", 642}, - {"stick", 643}, - {"test", 644}, - {"crush", 645}, - {"endless", 646}, - {"fault", 647}, - {"itself", 648}, - {"rule", 649}, - {"spill", 650}, - {"art", 651}, - {"circle", 652}, - {"join", 653}, - {"kick", 654}, - {"mask", 655}, - {"master", 656}, - {"passion", 657}, - {"quick", 658}, - {"raise", 659}, - {"smooth", 660}, - {"unless", 661}, - {"wander", 662}, - {"actually", 663}, - {"broke", 664}, - {"chair", 665}, - {"deal", 666}, - {"favorite", 667}, - {"gift", 668}, - {"note", 669}, - {"number", 670}, - {"sweat", 671}, - {"box", 672}, - {"chill", 673}, - {"clothes", 674}, - {"lady", 675}, - {"mark", 676}, - {"park", 677}, - {"poor", 678}, - {"sadness", 679}, - {"tie", 680}, - {"animal", 681}, - {"belong", 682}, - {"brush", 683}, - {"consume", 684}, - {"dawn", 685}, - {"forest", 686}, - {"innocent", 687}, - {"pen", 688}, - {"pride", 689}, - {"stream", 690}, - {"thick", 691}, - {"clay", 692}, - {"complete", 693}, - {"count", 694}, - {"draw", 695}, - {"faith", 696}, - {"press", 697}, - {"silver", 698}, - {"struggle", 699}, - {"surface", 700}, - {"taught", 701}, - {"teach", 702}, - {"wet", 703}, - {"bless", 704}, - {"chase", 705}, - {"climb", 706}, - {"enter", 707}, - {"letter", 708}, - {"melt", 709}, - {"metal", 710}, - {"movie", 711}, - {"stretch", 712}, - {"swing", 713}, - {"vision", 714}, - {"wife", 715}, - {"beside", 716}, - {"crash", 717}, - {"forgot", 718}, - {"guide", 719}, - {"haunt", 720}, - {"joke", 721}, - {"knock", 722}, - {"plant", 723}, - {"pour", 724}, - {"prove", 725}, - {"reveal", 726}, - {"steal", 727}, - {"stuff", 728}, - {"trip", 729}, - {"wood", 730}, - {"wrist", 731}, - {"bother", 732}, - {"bottom", 733}, - {"crawl", 734}, - {"crowd", 735}, - {"fix", 736}, - {"forgive", 737}, - {"frown", 738}, - {"grace", 739}, - {"loose", 740}, - {"lucky", 741}, - {"party", 742}, - {"release", 743}, - {"surely", 744}, - {"survive", 745}, - {"teacher", 746}, - {"gently", 747}, - {"grip", 748}, - {"speed", 749}, - {"suicide", 750}, - {"travel", 751}, - {"treat", 752}, - {"vein", 753}, - {"written", 754}, - {"cage", 755}, - {"chain", 756}, - {"conversation", 757}, - {"date", 758}, - {"enemy", 759}, - {"however", 760}, - {"interest", 761}, - {"million", 762}, - {"page", 763}, - {"pink", 764}, - {"proud", 765}, - {"sway", 766}, - {"themselves", 767}, - {"winter", 768}, - {"church", 769}, - {"cruel", 770}, - {"cup", 771}, - {"demon", 772}, - {"experience", 773}, - {"freedom", 774}, - {"pair", 775}, - {"pop", 776}, - {"purpose", 777}, - {"respect", 778}, - {"shoot", 779}, - {"softly", 780}, - {"state", 781}, - {"strange", 782}, - {"bar", 783}, - {"birth", 784}, - {"curl", 785}, - {"dirt", 786}, - {"excuse", 787}, - {"lord", 788}, - {"lovely", 789}, - {"monster", 790}, - {"order", 791}, - {"pack", 792}, - {"pants", 793}, - {"pool", 794}, - {"scene", 795}, - {"seven", 796}, - {"shame", 797}, - {"slide", 798}, - {"ugly", 799}, - {"among", 800}, - {"blade", 801}, - {"blonde", 802}, - {"closet", 803}, - {"creek", 804}, - {"deny", 805}, - {"drug", 806}, - {"eternity", 807}, - {"gain", 808}, - {"grade", 809}, - {"handle", 810}, - {"key", 811}, - {"linger", 812}, - {"pale", 813}, - {"prepare", 814}, - {"swallow", 815}, - {"swim", 816}, - {"tremble", 817}, - {"wheel", 818}, - {"won", 819}, - {"cast", 820}, - {"cigarette", 821}, - {"claim", 822}, - {"college", 823}, - {"direction", 824}, - {"dirty", 825}, - {"gather", 826}, - {"ghost", 827}, - {"hundred", 828}, - {"loss", 829}, - {"lung", 830}, - {"orange", 831}, - {"present", 832}, - {"swear", 833}, - {"swirl", 834}, - {"twice", 835}, - {"wild", 836}, - {"bitter", 837}, - {"blanket", 838}, - {"doctor", 839}, - {"everywhere", 840}, - {"flash", 841}, - {"grown", 842}, - {"knowledge", 843}, - {"numb", 844}, - {"pressure", 845}, - {"radio", 846}, - {"repeat", 847}, - {"ruin", 848}, - {"spend", 849}, - {"unknown", 850}, - {"buy", 851}, - {"clock", 852}, - {"devil", 853}, - {"early", 854}, - {"false", 855}, - {"fantasy", 856}, - {"pound", 857}, - {"precious", 858}, - {"refuse", 859}, - {"sheet", 860}, - {"teeth", 861}, - {"welcome", 862}, - {"add", 863}, - {"ahead", 864}, - {"block", 865}, - {"bury", 866}, - {"caress", 867}, - {"content", 868}, - {"depth", 869}, - {"despite", 870}, - {"distant", 871}, - {"marry", 872}, - {"purple", 873}, - {"threw", 874}, - {"whenever", 875}, - {"bomb", 876}, - {"dull", 877}, - {"easily", 878}, - {"grasp", 879}, - {"hospital", 880}, - {"innocence", 881}, - {"normal", 882}, - {"receive", 883}, - {"reply", 884}, - {"rhyme", 885}, - {"shade", 886}, - {"someday", 887}, - {"sword", 888}, - {"toe", 889}, - {"visit", 890}, - {"asleep", 891}, - {"bought", 892}, - {"center", 893}, - {"consider", 894}, - {"flat", 895}, - {"hero", 896}, - {"history", 897}, - {"ink", 898}, - {"insane", 899}, - {"muscle", 900}, - {"mystery", 901}, - {"pocket", 902}, - {"reflection", 903}, - {"shove", 904}, - {"silently", 905}, - {"smart", 906}, - {"soldier", 907}, - {"spot", 908}, - {"stress", 909}, - {"train", 910}, - {"type", 911}, - {"view", 912}, - {"whether", 913}, - {"bus", 914}, - {"energy", 915}, - {"explain", 916}, - {"holy", 917}, - {"hunger", 918}, - {"inch", 919}, - {"magic", 920}, - {"mix", 921}, - {"noise", 922}, - {"nowhere", 923}, - {"prayer", 924}, - {"presence", 925}, - {"shock", 926}, - {"snap", 927}, - {"spider", 928}, - {"study", 929}, - {"thunder", 930}, - {"trail", 931}, - {"admit", 932}, - {"agree", 933}, - {"bag", 934}, - {"bang", 935}, - {"bound", 936}, - {"butterfly", 937}, - {"cute", 938}, - {"exactly", 939}, - {"explode", 940}, - {"familiar", 941}, - {"fold", 942}, - {"further", 943}, - {"pierce", 944}, - {"reflect", 945}, - {"scent", 946}, - {"selfish", 947}, - {"sharp", 948}, - {"sink", 949}, - {"spring", 950}, - {"stumble", 951}, - {"universe", 952}, - {"weep", 953}, - {"women", 954}, - {"wonderful", 955}, - {"action", 956}, - {"ancient", 957}, - {"attempt", 958}, - {"avoid", 959}, - {"birthday", 960}, - {"branch", 961}, - {"chocolate", 962}, - {"core", 963}, - {"depress", 964}, - {"drunk", 965}, - {"especially", 966}, - {"focus", 967}, - {"fruit", 968}, - {"honest", 969}, - {"match", 970}, - {"palm", 971}, - {"perfectly", 972}, - {"pillow", 973}, - {"pity", 974}, - {"poison", 975}, - {"roar", 976}, - {"shift", 977}, - {"slightly", 978}, - {"thump", 979}, - {"truck", 980}, - {"tune", 981}, - {"twenty", 982}, - {"unable", 983}, - {"wipe", 984}, - {"wrote", 985}, - {"coat", 986}, - {"constant", 987}, - {"dinner", 988}, - {"drove", 989}, - {"egg", 990}, - {"eternal", 991}, - {"flight", 992}, - {"flood", 993}, - {"frame", 994}, - {"freak", 995}, - {"gasp", 996}, - {"glad", 997}, - {"hollow", 998}, - {"motion", 999}, - {"peer", 1000}, - {"plastic", 1001}, - {"root", 1002}, - {"screen", 1003}, - {"season", 1004}, - {"sting", 1005}, - {"strike", 1006}, - {"team", 1007}, - {"unlike", 1008}, - {"victim", 1009}, - {"volume", 1010}, - {"warn", 1011}, - {"weird", 1012}, - {"attack", 1013}, - {"await", 1014}, - {"awake", 1015}, - {"built", 1016}, - {"charm", 1017}, - {"crave", 1018}, - {"despair", 1019}, - {"fought", 1020}, - {"grant", 1021}, - {"grief", 1022}, - {"horse", 1023}, - {"limit", 1024}, - {"message", 1025}, - {"ripple", 1026}, - {"sanity", 1027}, - {"scatter", 1028}, - {"serve", 1029}, - {"split", 1030}, - {"string", 1031}, - {"trick", 1032}, - {"annoy", 1033}, - {"blur", 1034}, - {"boat", 1035}, - {"brave", 1036}, - {"clearly", 1037}, - {"cling", 1038}, - {"connect", 1039}, - {"fist", 1040}, - {"forth", 1041}, - {"imagination", 1042}, - {"iron", 1043}, - {"jock", 1044}, - {"judge", 1045}, - {"lesson", 1046}, - {"milk", 1047}, - {"misery", 1048}, - {"nail", 1049}, - {"naked", 1050}, - {"ourselves", 1051}, - {"poet", 1052}, - {"possible", 1053}, - {"princess", 1054}, - {"sail", 1055}, - {"size", 1056}, - {"snake", 1057}, - {"society", 1058}, - {"stroke", 1059}, - {"torture", 1060}, - {"toss", 1061}, - {"trace", 1062}, - {"wise", 1063}, - {"bloom", 1064}, - {"bullet", 1065}, - {"cell", 1066}, - {"check", 1067}, - {"cost", 1068}, - {"darling", 1069}, - {"during", 1070}, - {"footstep", 1071}, - {"fragile", 1072}, - {"hallway", 1073}, - {"hardly", 1074}, - {"horizon", 1075}, - {"invisible", 1076}, - {"journey", 1077}, - {"midnight", 1078}, - {"mud", 1079}, - {"nod", 1080}, - {"pause", 1081}, - {"relax", 1082}, - {"shiver", 1083}, - {"sudden", 1084}, - {"value", 1085}, - {"youth", 1086}, - {"abuse", 1087}, - {"admire", 1088}, - {"blink", 1089}, - {"breast", 1090}, - {"bruise", 1091}, - {"constantly", 1092}, - {"couple", 1093}, - {"creep", 1094}, - {"curve", 1095}, - {"difference", 1096}, - {"dumb", 1097}, - {"emptiness", 1098}, - {"gotta", 1099}, - {"honor", 1100}, - {"plain", 1101}, - {"planet", 1102}, - {"recall", 1103}, - {"rub", 1104}, - {"ship", 1105}, - {"slam", 1106}, - {"soar", 1107}, - {"somebody", 1108}, - {"tightly", 1109}, - {"weather", 1110}, - {"adore", 1111}, - {"approach", 1112}, - {"bond", 1113}, - {"bread", 1114}, - {"burst", 1115}, - {"candle", 1116}, - {"coffee", 1117}, - {"cousin", 1118}, - {"crime", 1119}, - {"desert", 1120}, - {"flutter", 1121}, - {"frozen", 1122}, - {"grand", 1123}, - {"heel", 1124}, - {"hello", 1125}, - {"language", 1126}, - {"level", 1127}, - {"movement", 1128}, - {"pleasure", 1129}, - {"powerful", 1130}, - {"random", 1131}, - {"rhythm", 1132}, - {"settle", 1133}, - {"silly", 1134}, - {"slap", 1135}, - {"sort", 1136}, - {"spoken", 1137}, - {"steel", 1138}, - {"threaten", 1139}, - {"tumble", 1140}, - {"upset", 1141}, - {"aside", 1142}, - {"awkward", 1143}, - {"bee", 1144}, - {"blank", 1145}, - {"board", 1146}, - {"button", 1147}, - {"card", 1148}, - {"carefully", 1149}, - {"complain", 1150}, - {"crap", 1151}, - {"deeply", 1152}, - {"discover", 1153}, - {"drag", 1154}, - {"dread", 1155}, - {"effort", 1156}, - {"entire", 1157}, - {"fairy", 1158}, - {"giant", 1159}, - {"gotten", 1160}, - {"greet", 1161}, - {"illusion", 1162}, - {"jeans", 1163}, - {"leap", 1164}, - {"liquid", 1165}, - {"march", 1166}, - {"mend", 1167}, - {"nervous", 1168}, - {"nine", 1169}, - {"replace", 1170}, - {"rope", 1171}, - {"spine", 1172}, - {"stole", 1173}, - {"terror", 1174}, - {"accident", 1175}, - {"apple", 1176}, - {"balance", 1177}, - {"boom", 1178}, - {"childhood", 1179}, - {"collect", 1180}, - {"demand", 1181}, - {"depression", 1182}, - {"eventually", 1183}, - {"faint", 1184}, - {"glare", 1185}, - {"goal", 1186}, - {"group", 1187}, - {"honey", 1188}, - {"kitchen", 1189}, - {"laid", 1190}, - {"limb", 1191}, - {"machine", 1192}, - {"mere", 1193}, - {"mold", 1194}, - {"murder", 1195}, - {"nerve", 1196}, - {"painful", 1197}, - {"poetry", 1198}, - {"prince", 1199}, - {"rabbit", 1200}, - {"shelter", 1201}, - {"shore", 1202}, - {"shower", 1203}, - {"soothe", 1204}, - {"stair", 1205}, - {"steady", 1206}, - {"sunlight", 1207}, - {"tangle", 1208}, - {"tease", 1209}, - {"treasure", 1210}, - {"uncle", 1211}, - {"begun", 1212}, - {"bliss", 1213}, - {"canvas", 1214}, - {"cheer", 1215}, - {"claw", 1216}, - {"clutch", 1217}, - {"commit", 1218}, - {"crimson", 1219}, - {"crystal", 1220}, - {"delight", 1221}, - {"doll", 1222}, - {"existence", 1223}, - {"express", 1224}, - {"fog", 1225}, - {"football", 1226}, - {"gay", 1227}, - {"goose", 1228}, - {"guard", 1229}, - {"hatred", 1230}, - {"illuminate", 1231}, - {"mass", 1232}, - {"math", 1233}, - {"mourn", 1234}, - {"rich", 1235}, - {"rough", 1236}, - {"skip", 1237}, - {"stir", 1238}, - {"student", 1239}, - {"style", 1240}, - {"support", 1241}, - {"thorn", 1242}, - {"tough", 1243}, - {"yard", 1244}, - {"yearn", 1245}, - {"yesterday", 1246}, - {"advice", 1247}, - {"appreciate", 1248}, - {"autumn", 1249}, - {"bank", 1250}, - {"beam", 1251}, - {"bowl", 1252}, - {"capture", 1253}, - {"carve", 1254}, - {"collapse", 1255}, - {"confusion", 1256}, - {"creation", 1257}, - {"dove", 1258}, - {"feather", 1259}, - {"girlfriend", 1260}, - {"glory", 1261}, - {"government", 1262}, - {"harsh", 1263}, - {"hop", 1264}, - {"inner", 1265}, - {"loser", 1266}, - {"moonlight", 1267}, - {"neighbor", 1268}, - {"neither", 1269}, - {"peach", 1270}, - {"pig", 1271}, - {"praise", 1272}, - {"screw", 1273}, - {"shield", 1274}, - {"shimmer", 1275}, - {"sneak", 1276}, - {"stab", 1277}, - {"subject", 1278}, - {"throughout", 1279}, - {"thrown", 1280}, - {"tower", 1281}, - {"twirl", 1282}, - {"wow", 1283}, - {"army", 1284}, - {"arrive", 1285}, - {"bathroom", 1286}, - {"bump", 1287}, - {"cease", 1288}, - {"cookie", 1289}, - {"couch", 1290}, - {"courage", 1291}, - {"dim", 1292}, - {"guilt", 1293}, - {"howl", 1294}, - {"hum", 1295}, - {"husband", 1296}, - {"insult", 1297}, - {"led", 1298}, - {"lunch", 1299}, - {"mock", 1300}, - {"mostly", 1301}, - {"natural", 1302}, - {"nearly", 1303}, - {"needle", 1304}, - {"nerd", 1305}, - {"peaceful", 1306}, - {"perfection", 1307}, - {"pile", 1308}, - {"price", 1309}, - {"remove", 1310}, - {"roam", 1311}, - {"sanctuary", 1312}, - {"serious", 1313}, - {"shiny", 1314}, - {"shook", 1315}, - {"sob", 1316}, - {"stolen", 1317}, - {"tap", 1318}, - {"vain", 1319}, - {"void", 1320}, - {"warrior", 1321}, - {"wrinkle", 1322}, - {"affection", 1323}, - {"apologize", 1324}, - {"blossom", 1325}, - {"bounce", 1326}, - {"bridge", 1327}, - {"cheap", 1328}, - {"crumble", 1329}, - {"decision", 1330}, - {"descend", 1331}, - {"desperately", 1332}, - {"dig", 1333}, - {"dot", 1334}, - {"flip", 1335}, - {"frighten", 1336}, - {"heartbeat", 1337}, - {"huge", 1338}, - {"lazy", 1339}, - {"lick", 1340}, - {"odd", 1341}, - {"opinion", 1342}, - {"process", 1343}, - {"puzzle", 1344}, - {"quietly", 1345}, - {"retreat", 1346}, - {"score", 1347}, - {"sentence", 1348}, - {"separate", 1349}, - {"situation", 1350}, - {"skill", 1351}, - {"soak", 1352}, - {"square", 1353}, - {"stray", 1354}, - {"taint", 1355}, - {"task", 1356}, - {"tide", 1357}, - {"underneath", 1358}, - {"veil", 1359}, - {"whistle", 1360}, - {"anywhere", 1361}, - {"bedroom", 1362}, - {"bid", 1363}, - {"bloody", 1364}, - {"burden", 1365}, - {"careful", 1366}, - {"compare", 1367}, - {"concern", 1368}, - {"curtain", 1369}, - {"decay", 1370}, - {"defeat", 1371}, - {"describe", 1372}, - {"double", 1373}, - {"dreamer", 1374}, - {"driver", 1375}, - {"dwell", 1376}, - {"evening", 1377}, - {"flare", 1378}, - {"flicker", 1379}, - {"grandma", 1380}, - {"guitar", 1381}, - {"harm", 1382}, - {"horrible", 1383}, - {"hungry", 1384}, - {"indeed", 1385}, - {"lace", 1386}, - {"melody", 1387}, - {"monkey", 1388}, - {"nation", 1389}, - {"object", 1390}, - {"obviously", 1391}, - {"rainbow", 1392}, - {"salt", 1393}, - {"scratch", 1394}, - {"shown", 1395}, - {"shy", 1396}, - {"stage", 1397}, - {"stun", 1398}, - {"third", 1399}, - {"tickle", 1400}, - {"useless", 1401}, - {"weakness", 1402}, - {"worship", 1403}, - {"worthless", 1404}, - {"afternoon", 1405}, - {"beard", 1406}, - {"boyfriend", 1407}, - {"bubble", 1408}, - {"busy", 1409}, - {"certain", 1410}, - {"chin", 1411}, - {"concrete", 1412}, - {"desk", 1413}, - {"diamond", 1414}, - {"doom", 1415}, - {"drawn", 1416}, - {"due", 1417}, - {"felicity", 1418}, - {"freeze", 1419}, - {"frost", 1420}, - {"garden", 1421}, - {"glide", 1422}, - {"harmony", 1423}, - {"hopefully", 1424}, - {"hunt", 1425}, - {"jealous", 1426}, - {"lightning", 1427}, - {"mama", 1428}, - {"mercy", 1429}, - {"peel", 1430}, - {"physical", 1431}, - {"position", 1432}, - {"pulse", 1433}, - {"punch", 1434}, - {"quit", 1435}, - {"rant", 1436}, - {"respond", 1437}, - {"salty", 1438}, - {"sane", 1439}, - {"satisfy", 1440}, - {"savior", 1441}, - {"sheep", 1442}, - {"slept", 1443}, - {"social", 1444}, - {"sport", 1445}, - {"tuck", 1446}, - {"utter", 1447}, - {"valley", 1448}, - {"wolf", 1449}, - {"aim", 1450}, - {"alas", 1451}, - {"alter", 1452}, - {"arrow", 1453}, - {"awaken", 1454}, - {"beaten", 1455}, - {"belief", 1456}, - {"brand", 1457}, - {"ceiling", 1458}, - {"cheese", 1459}, - {"clue", 1460}, - {"confidence", 1461}, - {"connection", 1462}, - {"daily", 1463}, - {"disguise", 1464}, - {"eager", 1465}, - {"erase", 1466}, - {"essence", 1467}, - {"everytime", 1468}, - {"expression", 1469}, - {"fan", 1470}, - {"flag", 1471}, - {"flirt", 1472}, - {"foul", 1473}, - {"fur", 1474}, - {"giggle", 1475}, - {"glorious", 1476}, - {"ignorance", 1477}, - {"law", 1478}, - {"lifeless", 1479}, - {"measure", 1480}, - {"mighty", 1481}, - {"muse", 1482}, - {"north", 1483}, - {"opposite", 1484}, - {"paradise", 1485}, - {"patience", 1486}, - {"patient", 1487}, - {"pencil", 1488}, - {"petal", 1489}, - {"plate", 1490}, - {"ponder", 1491}, - {"possibly", 1492}, - {"practice", 1493}, - {"slice", 1494}, - {"spell", 1495}, - {"stock", 1496}, - {"strife", 1497}, - {"strip", 1498}, - {"suffocate", 1499}, - {"suit", 1500}, - {"tender", 1501}, - {"tool", 1502}, - {"trade", 1503}, - {"velvet", 1504}, - {"verse", 1505}, - {"waist", 1506}, - {"witch", 1507}, - {"aunt", 1508}, - {"bench", 1509}, - {"bold", 1510}, - {"cap", 1511}, - {"certainly", 1512}, - {"click", 1513}, - {"companion", 1514}, - {"creator", 1515}, - {"dart", 1516}, - {"delicate", 1517}, - {"determine", 1518}, - {"dish", 1519}, - {"dragon", 1520}, - {"drama", 1521}, - {"drum", 1522}, - {"dude", 1523}, - {"everybody", 1524}, - {"feast", 1525}, - {"forehead", 1526}, - {"former", 1527}, - {"fright", 1528}, - {"fully", 1529}, - {"gas", 1530}, - {"hook", 1531}, - {"hurl", 1532}, - {"invite", 1533}, - {"juice", 1534}, - {"manage", 1535}, - {"moral", 1536}, - {"possess", 1537}, - {"raw", 1538}, - {"rebel", 1539}, - {"royal", 1540}, - {"scale", 1541}, - {"scary", 1542}, - {"several", 1543}, - {"slight", 1544}, - {"stubborn", 1545}, - {"swell", 1546}, - {"talent", 1547}, - {"tea", 1548}, - {"terrible", 1549}, - {"thread", 1550}, - {"torment", 1551}, - {"trickle", 1552}, - {"usually", 1553}, - {"vast", 1554}, - {"violence", 1555}, - {"weave", 1556}, - {"acid", 1557}, - {"agony", 1558}, - {"ashamed", 1559}, - {"awe", 1560}, - {"belly", 1561}, - {"blend", 1562}, - {"blush", 1563}, - {"character", 1564}, - {"cheat", 1565}, - {"common", 1566}, - {"company", 1567}, - {"coward", 1568}, - {"creak", 1569}, - {"danger", 1570}, - {"deadly", 1571}, - {"defense", 1572}, - {"define", 1573}, - {"depend", 1574}, - {"desperate", 1575}, - {"destination", 1576}, - {"dew", 1577}, - {"duck", 1578}, - {"dusty", 1579}, - {"embarrass", 1580}, - {"engine", 1581}, - {"example", 1582}, - {"explore", 1583}, - {"foe", 1584}, - {"freely", 1585}, - {"frustrate", 1586}, - {"generation", 1587}, - {"glove", 1588}, - {"guilty", 1589}, - {"health", 1590}, - {"hurry", 1591}, - {"idiot", 1592}, - {"impossible", 1593}, - {"inhale", 1594}, - {"jaw", 1595}, - {"kingdom", 1596}, - {"mention", 1597}, - {"mist", 1598}, - {"moan", 1599}, - {"mumble", 1600}, - {"mutter", 1601}, - {"observe", 1602}, - {"ode", 1603}, - {"pathetic", 1604}, - {"pattern", 1605}, - {"pie", 1606}, - {"prefer", 1607}, - {"puff", 1608}, - {"rape", 1609}, - {"rare", 1610}, - {"revenge", 1611}, - {"rude", 1612}, - {"scrape", 1613}, - {"spiral", 1614}, - {"squeeze", 1615}, - {"strain", 1616}, - {"sunset", 1617}, - {"suspend", 1618}, - {"sympathy", 1619}, - {"thigh", 1620}, - {"throne", 1621}, - {"total", 1622}, - {"unseen", 1623}, - {"weapon", 1624}, - {"weary", 1625} - }; - - const std::string wordsArray[] = { - "like", - "just", - "love", - "know", - "never", - "want", - "time", - "out", - "there", - "make", - "look", - "eye", - "down", - "only", - "think", - "heart", - "back", - "then", - "into", - "about", - "more", - "away", - "still", - "them", - "take", - "thing", - "even", - "through", - "long", - "always", - "world", - "too", - "friend", - "tell", - "try", - "hand", - "thought", - "over", - "here", - "other", - "need", - "smile", - "again", - "much", - "cry", - "been", - "night", - "ever", - "little", - "said", - "end", - "some", - "those", - "around", - "mind", - "people", - "girl", - "leave", - "dream", - "left", - "turn", - "myself", - "give", - "nothing", - "really", - "off", - "before", - "something", - "find", - "walk", - "wish", - "good", - "once", - "place", - "ask", - "stop", - "keep", - "watch", - "seem", - "everything", - "wait", - "got", - "yet", - "made", - "remember", - "start", - "alone", - "run", - "hope", - "maybe", - "believe", - "body", - "hate", - "after", - "close", - "talk", - "stand", - "own", - "each", - "hurt", - "help", - "home", - "god", - "soul", - "new", - "many", - "two", - "inside", - "should", - "true", - "first", - "fear", - "mean", - "better", - "play", - "another", - "gone", - "change", - "use", - "wonder", - "someone", - "hair", - "cold", - "open", - "best", - "any", - "behind", - "happen", - "water", - "dark", - "laugh", - "stay", - "forever", - "name", - "work", - "show", - "sky", - "break", - "came", - "deep", - "door", - "put", - "black", - "together", - "upon", - "happy", - "such", - "great", - "white", - "matter", - "fill", - "past", - "please", - "burn", - "cause", - "enough", - "touch", - "moment", - "soon", - "voice", - "scream", - "anything", - "stare", - "sound", - "red", - "everyone", - "hide", - "kiss", - "truth", - "death", - "beautiful", - "mine", - "blood", - "broken", - "very", - "pass", - "next", - "forget", - "tree", - "wrong", - "air", - "mother", - "understand", - "lip", - "hit", - "wall", - "memory", - "sleep", - "free", - "high", - "realize", - "school", - "might", - "skin", - "sweet", - "perfect", - "blue", - "kill", - "breath", - "dance", - "against", - "fly", - "between", - "grow", - "strong", - "under", - "listen", - "bring", - "sometimes", - "speak", - "pull", - "person", - "become", - "family", - "begin", - "ground", - "real", - "small", - "father", - "sure", - "feet", - "rest", - "young", - "finally", - "land", - "across", - "today", - "different", - "guy", - "line", - "fire", - "reason", - "reach", - "second", - "slowly", - "write", - "eat", - "smell", - "mouth", - "step", - "learn", - "three", - "floor", - "promise", - "breathe", - "darkness", - "push", - "earth", - "guess", - "save", - "song", - "above", - "along", - "both", - "color", - "house", - "almost", - "sorry", - "anymore", - "brother", - "okay", - "dear", - "game", - "fade", - "already", - "apart", - "warm", - "beauty", - "heard", - "notice", - "question", - "shine", - "began", - "piece", - "whole", - "shadow", - "secret", - "street", - "within", - "finger", - "point", - "morning", - "whisper", - "child", - "moon", - "green", - "story", - "glass", - "kid", - "silence", - "since", - "soft", - "yourself", - "empty", - "shall", - "angel", - "answer", - "baby", - "bright", - "dad", - "path", - "worry", - "hour", - "drop", - "follow", - "power", - "war", - "half", - "flow", - "heaven", - "act", - "chance", - "fact", - "least", - "tired", - "children", - "near", - "quite", - "afraid", - "rise", - "sea", - "taste", - "window", - "cover", - "nice", - "trust", - "lot", - "sad", - "cool", - "force", - "peace", - "return", - "blind", - "easy", - "ready", - "roll", - "rose", - "drive", - "held", - "music", - "beneath", - "hang", - "mom", - "paint", - "emotion", - "quiet", - "clear", - "cloud", - "few", - "pretty", - "bird", - "outside", - "paper", - "picture", - "front", - "rock", - "simple", - "anyone", - "meant", - "reality", - "road", - "sense", - "waste", - "bit", - "leaf", - "thank", - "happiness", - "meet", - "men", - "smoke", - "truly", - "decide", - "self", - "age", - "book", - "form", - "alive", - "carry", - "escape", - "damn", - "instead", - "able", - "ice", - "minute", - "throw", - "catch", - "leg", - "ring", - "course", - "goodbye", - "lead", - "poem", - "sick", - "corner", - "desire", - "known", - "problem", - "remind", - "shoulder", - "suppose", - "toward", - "wave", - "drink", - "jump", - "woman", - "pretend", - "sister", - "week", - "human", - "joy", - "crack", - "grey", - "pray", - "surprise", - "dry", - "knee", - "less", - "search", - "bleed", - "caught", - "clean", - "embrace", - "future", - "king", - "son", - "sorrow", - "chest", - "hug", - "remain", - "sat", - "worth", - "blow", - "daddy", - "final", - "parent", - "tight", - "also", - "create", - "lonely", - "safe", - "cross", - "dress", - "evil", - "silent", - "bone", - "fate", - "perhaps", - "anger", - "class", - "scar", - "snow", - "tiny", - "tonight", - "continue", - "control", - "dog", - "edge", - "mirror", - "month", - "suddenly", - "comfort", - "given", - "loud", - "quickly", - "gaze", - "plan", - "rush", - "stone", - "town", - "battle", - "ignore", - "spirit", - "stood", - "stupid", - "yours", - "brown", - "build", - "dust", - "hey", - "kept", - "pay", - "phone", - "twist", - "although", - "ball", - "beyond", - "hidden", - "nose", - "taken", - "fail", - "float", - "pure", - "somehow", - "wash", - "wrap", - "angry", - "cheek", - "creature", - "forgotten", - "heat", - "rip", - "single", - "space", - "special", - "weak", - "whatever", - "yell", - "anyway", - "blame", - "job", - "choose", - "country", - "curse", - "drift", - "echo", - "figure", - "grew", - "laughter", - "neck", - "suffer", - "worse", - "yeah", - "disappear", - "foot", - "forward", - "knife", - "mess", - "somewhere", - "stomach", - "storm", - "beg", - "idea", - "lift", - "offer", - "breeze", - "field", - "five", - "often", - "simply", - "stuck", - "win", - "allow", - "confuse", - "enjoy", - "except", - "flower", - "seek", - "strength", - "calm", - "grin", - "gun", - "heavy", - "hill", - "large", - "ocean", - "shoe", - "sigh", - "straight", - "summer", - "tongue", - "accept", - "crazy", - "everyday", - "exist", - "grass", - "mistake", - "sent", - "shut", - "surround", - "table", - "ache", - "brain", - "destroy", - "heal", - "nature", - "shout", - "sign", - "stain", - "choice", - "doubt", - "glance", - "glow", - "mountain", - "queen", - "stranger", - "throat", - "tomorrow", - "city", - "either", - "fish", - "flame", - "rather", - "shape", - "spin", - "spread", - "ash", - "distance", - "finish", - "image", - "imagine", - "important", - "nobody", - "shatter", - "warmth", - "became", - "feed", - "flesh", - "funny", - "lust", - "shirt", - "trouble", - "yellow", - "attention", - "bare", - "bite", - "money", - "protect", - "amaze", - "appear", - "born", - "choke", - "completely", - "daughter", - "fresh", - "friendship", - "gentle", - "probably", - "six", - "deserve", - "expect", - "grab", - "middle", - "nightmare", - "river", - "thousand", - "weight", - "worst", - "wound", - "barely", - "bottle", - "cream", - "regret", - "relationship", - "stick", - "test", - "crush", - "endless", - "fault", - "itself", - "rule", - "spill", - "art", - "circle", - "join", - "kick", - "mask", - "master", - "passion", - "quick", - "raise", - "smooth", - "unless", - "wander", - "actually", - "broke", - "chair", - "deal", - "favorite", - "gift", - "note", - "number", - "sweat", - "box", - "chill", - "clothes", - "lady", - "mark", - "park", - "poor", - "sadness", - "tie", - "animal", - "belong", - "brush", - "consume", - "dawn", - "forest", - "innocent", - "pen", - "pride", - "stream", - "thick", - "clay", - "complete", - "count", - "draw", - "faith", - "press", - "silver", - "struggle", - "surface", - "taught", - "teach", - "wet", - "bless", - "chase", - "climb", - "enter", - "letter", - "melt", - "metal", - "movie", - "stretch", - "swing", - "vision", - "wife", - "beside", - "crash", - "forgot", - "guide", - "haunt", - "joke", - "knock", - "plant", - "pour", - "prove", - "reveal", - "steal", - "stuff", - "trip", - "wood", - "wrist", - "bother", - "bottom", - "crawl", - "crowd", - "fix", - "forgive", - "frown", - "grace", - "loose", - "lucky", - "party", - "release", - "surely", - "survive", - "teacher", - "gently", - "grip", - "speed", - "suicide", - "travel", - "treat", - "vein", - "written", - "cage", - "chain", - "conversation", - "date", - "enemy", - "however", - "interest", - "million", - "page", - "pink", - "proud", - "sway", - "themselves", - "winter", - "church", - "cruel", - "cup", - "demon", - "experience", - "freedom", - "pair", - "pop", - "purpose", - "respect", - "shoot", - "softly", - "state", - "strange", - "bar", - "birth", - "curl", - "dirt", - "excuse", - "lord", - "lovely", - "monster", - "order", - "pack", - "pants", - "pool", - "scene", - "seven", - "shame", - "slide", - "ugly", - "among", - "blade", - "blonde", - "closet", - "creek", - "deny", - "drug", - "eternity", - "gain", - "grade", - "handle", - "key", - "linger", - "pale", - "prepare", - "swallow", - "swim", - "tremble", - "wheel", - "won", - "cast", - "cigarette", - "claim", - "college", - "direction", - "dirty", - "gather", - "ghost", - "hundred", - "loss", - "lung", - "orange", - "present", - "swear", - "swirl", - "twice", - "wild", - "bitter", - "blanket", - "doctor", - "everywhere", - "flash", - "grown", - "knowledge", - "numb", - "pressure", - "radio", - "repeat", - "ruin", - "spend", - "unknown", - "buy", - "clock", - "devil", - "early", - "false", - "fantasy", - "pound", - "precious", - "refuse", - "sheet", - "teeth", - "welcome", - "add", - "ahead", - "block", - "bury", - "caress", - "content", - "depth", - "despite", - "distant", - "marry", - "purple", - "threw", - "whenever", - "bomb", - "dull", - "easily", - "grasp", - "hospital", - "innocence", - "normal", - "receive", - "reply", - "rhyme", - "shade", - "someday", - "sword", - "toe", - "visit", - "asleep", - "bought", - "center", - "consider", - "flat", - "hero", - "history", - "ink", - "insane", - "muscle", - "mystery", - "pocket", - "reflection", - "shove", - "silently", - "smart", - "soldier", - "spot", - "stress", - "train", - "type", - "view", - "whether", - "bus", - "energy", - "explain", - "holy", - "hunger", - "inch", - "magic", - "mix", - "noise", - "nowhere", - "prayer", - "presence", - "shock", - "snap", - "spider", - "study", - "thunder", - "trail", - "admit", - "agree", - "bag", - "bang", - "bound", - "butterfly", - "cute", - "exactly", - "explode", - "familiar", - "fold", - "further", - "pierce", - "reflect", - "scent", - "selfish", - "sharp", - "sink", - "spring", - "stumble", - "universe", - "weep", - "women", - "wonderful", - "action", - "ancient", - "attempt", - "avoid", - "birthday", - "branch", - "chocolate", - "core", - "depress", - "drunk", - "especially", - "focus", - "fruit", - "honest", - "match", - "palm", - "perfectly", - "pillow", - "pity", - "poison", - "roar", - "shift", - "slightly", - "thump", - "truck", - "tune", - "twenty", - "unable", - "wipe", - "wrote", - "coat", - "constant", - "dinner", - "drove", - "egg", - "eternal", - "flight", - "flood", - "frame", - "freak", - "gasp", - "glad", - "hollow", - "motion", - "peer", - "plastic", - "root", - "screen", - "season", - "sting", - "strike", - "team", - "unlike", - "victim", - "volume", - "warn", - "weird", - "attack", - "await", - "awake", - "built", - "charm", - "crave", - "despair", - "fought", - "grant", - "grief", - "horse", - "limit", - "message", - "ripple", - "sanity", - "scatter", - "serve", - "split", - "string", - "trick", - "annoy", - "blur", - "boat", - "brave", - "clearly", - "cling", - "connect", - "fist", - "forth", - "imagination", - "iron", - "jock", - "judge", - "lesson", - "milk", - "misery", - "nail", - "naked", - "ourselves", - "poet", - "possible", - "princess", - "sail", - "size", - "snake", - "society", - "stroke", - "torture", - "toss", - "trace", - "wise", - "bloom", - "bullet", - "cell", - "check", - "cost", - "darling", - "during", - "footstep", - "fragile", - "hallway", - "hardly", - "horizon", - "invisible", - "journey", - "midnight", - "mud", - "nod", - "pause", - "relax", - "shiver", - "sudden", - "value", - "youth", - "abuse", - "admire", - "blink", - "breast", - "bruise", - "constantly", - "couple", - "creep", - "curve", - "difference", - "dumb", - "emptiness", - "gotta", - "honor", - "plain", - "planet", - "recall", - "rub", - "ship", - "slam", - "soar", - "somebody", - "tightly", - "weather", - "adore", - "approach", - "bond", - "bread", - "burst", - "candle", - "coffee", - "cousin", - "crime", - "desert", - "flutter", - "frozen", - "grand", - "heel", - "hello", - "language", - "level", - "movement", - "pleasure", - "powerful", - "random", - "rhythm", - "settle", - "silly", - "slap", - "sort", - "spoken", - "steel", - "threaten", - "tumble", - "upset", - "aside", - "awkward", - "bee", - "blank", - "board", - "button", - "card", - "carefully", - "complain", - "crap", - "deeply", - "discover", - "drag", - "dread", - "effort", - "entire", - "fairy", - "giant", - "gotten", - "greet", - "illusion", - "jeans", - "leap", - "liquid", - "march", - "mend", - "nervous", - "nine", - "replace", - "rope", - "spine", - "stole", - "terror", - "accident", - "apple", - "balance", - "boom", - "childhood", - "collect", - "demand", - "depression", - "eventually", - "faint", - "glare", - "goal", - "group", - "honey", - "kitchen", - "laid", - "limb", - "machine", - "mere", - "mold", - "murder", - "nerve", - "painful", - "poetry", - "prince", - "rabbit", - "shelter", - "shore", - "shower", - "soothe", - "stair", - "steady", - "sunlight", - "tangle", - "tease", - "treasure", - "uncle", - "begun", - "bliss", - "canvas", - "cheer", - "claw", - "clutch", - "commit", - "crimson", - "crystal", - "delight", - "doll", - "existence", - "express", - "fog", - "football", - "gay", - "goose", - "guard", - "hatred", - "illuminate", - "mass", - "math", - "mourn", - "rich", - "rough", - "skip", - "stir", - "student", - "style", - "support", - "thorn", - "tough", - "yard", - "yearn", - "yesterday", - "advice", - "appreciate", - "autumn", - "bank", - "beam", - "bowl", - "capture", - "carve", - "collapse", - "confusion", - "creation", - "dove", - "feather", - "girlfriend", - "glory", - "government", - "harsh", - "hop", - "inner", - "loser", - "moonlight", - "neighbor", - "neither", - "peach", - "pig", - "praise", - "screw", - "shield", - "shimmer", - "sneak", - "stab", - "subject", - "throughout", - "thrown", - "tower", - "twirl", - "wow", - "army", - "arrive", - "bathroom", - "bump", - "cease", - "cookie", - "couch", - "courage", - "dim", - "guilt", - "howl", - "hum", - "husband", - "insult", - "led", - "lunch", - "mock", - "mostly", - "natural", - "nearly", - "needle", - "nerd", - "peaceful", - "perfection", - "pile", - "price", - "remove", - "roam", - "sanctuary", - "serious", - "shiny", - "shook", - "sob", - "stolen", - "tap", - "vain", - "void", - "warrior", - "wrinkle", - "affection", - "apologize", - "blossom", - "bounce", - "bridge", - "cheap", - "crumble", - "decision", - "descend", - "desperately", - "dig", - "dot", - "flip", - "frighten", - "heartbeat", - "huge", - "lazy", - "lick", - "odd", - "opinion", - "process", - "puzzle", - "quietly", - "retreat", - "score", - "sentence", - "separate", - "situation", - "skill", - "soak", - "square", - "stray", - "taint", - "task", - "tide", - "underneath", - "veil", - "whistle", - "anywhere", - "bedroom", - "bid", - "bloody", - "burden", - "careful", - "compare", - "concern", - "curtain", - "decay", - "defeat", - "describe", - "double", - "dreamer", - "driver", - "dwell", - "evening", - "flare", - "flicker", - "grandma", - "guitar", - "harm", - "horrible", - "hungry", - "indeed", - "lace", - "melody", - "monkey", - "nation", - "object", - "obviously", - "rainbow", - "salt", - "scratch", - "shown", - "shy", - "stage", - "stun", - "third", - "tickle", - "useless", - "weakness", - "worship", - "worthless", - "afternoon", - "beard", - "boyfriend", - "bubble", - "busy", - "certain", - "chin", - "concrete", - "desk", - "diamond", - "doom", - "drawn", - "due", - "felicity", - "freeze", - "frost", - "garden", - "glide", - "harmony", - "hopefully", - "hunt", - "jealous", - "lightning", - "mama", - "mercy", - "peel", - "physical", - "position", - "pulse", - "punch", - "quit", - "rant", - "respond", - "salty", - "sane", - "satisfy", - "savior", - "sheep", - "slept", - "social", - "sport", - "tuck", - "utter", - "valley", - "wolf", - "aim", - "alas", - "alter", - "arrow", - "awaken", - "beaten", - "belief", - "brand", - "ceiling", - "cheese", - "clue", - "confidence", - "connection", - "daily", - "disguise", - "eager", - "erase", - "essence", - "everytime", - "expression", - "fan", - "flag", - "flirt", - "foul", - "fur", - "giggle", - "glorious", - "ignorance", - "law", - "lifeless", - "measure", - "mighty", - "muse", - "north", - "opposite", - "paradise", - "patience", - "patient", - "pencil", - "petal", - "plate", - "ponder", - "possibly", - "practice", - "slice", - "spell", - "stock", - "strife", - "strip", - "suffocate", - "suit", - "tender", - "tool", - "trade", - "velvet", - "verse", - "waist", - "witch", - "aunt", - "bench", - "bold", - "cap", - "certainly", - "click", - "companion", - "creator", - "dart", - "delicate", - "determine", - "dish", - "dragon", - "drama", - "drum", - "dude", - "everybody", - "feast", - "forehead", - "former", - "fright", - "fully", - "gas", - "hook", - "hurl", - "invite", - "juice", - "manage", - "moral", - "possess", - "raw", - "rebel", - "royal", - "scale", - "scary", - "several", - "slight", - "stubborn", - "swell", - "talent", - "tea", - "terrible", - "thread", - "torment", - "trickle", - "usually", - "vast", - "violence", - "weave", - "acid", - "agony", - "ashamed", - "awe", - "belly", - "blend", - "blush", - "character", - "cheat", - "common", - "company", - "coward", - "creak", - "danger", - "deadly", - "defense", - "define", - "depend", - "desperate", - "destination", - "dew", - "duck", - "dusty", - "embarrass", - "engine", - "example", - "explore", - "foe", - "freely", - "frustrate", - "generation", - "glove", - "guilty", - "health", - "hurry", - "idiot", - "impossible", - "inhale", - "jaw", - "kingdom", - "mention", - "mist", - "moan", - "mumble", - "mutter", - "observe", - "ode", - "pathetic", - "pattern", - "pie", - "prefer", - "puff", - "rape", - "rare", - "revenge", - "rude", - "scrape", - "spiral", - "squeeze", - "strain", - "sunset", - "suspend", - "sympathy", - "thigh", - "throne", - "total", - "unseen", - "weapon", - "weary" - }; - - - // convert text to binary data, 3 words -> 4 bytes - vector text2binary_throw(const string& text) - { - int n = NUMWORDS; - vector tokens; - string trimmed_copy(boost::trim_copy(text)); - boost::split(tokens, trimmed_copy, - boost::is_any_of(" ")); - if(tokens.size() % 3 != 0) - throw runtime_error("Invalid word count in mnemonic text"); - - vector res(tokens.size() / 3 * 4); // 3 tokens => 4 bytes - for (unsigned int i=0; i < tokens.size() / 3; i++) - { - if (wordsMap.count(tokens[i*3]) == 0 || - wordsMap.count(tokens[i*3 + 1]) == 0 || - wordsMap.count(tokens[i*3 + 2]) == 0) - throw runtime_error("Invalid word in mnemonic text"); - - uint32_t w1 = wordsMap.at(tokens[i*3]); - uint32_t w2 = wordsMap.at(tokens[i*3 + 1]); - uint32_t w3 = wordsMap.at(tokens[i*3 + 2]); - - uint32_t* val = reinterpret_cast(&res[i * 4]); - *val = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n); - } - return res; - } - - vector text2binary(const string& text) - { - try - { - return text2binary_throw(text); - } - catch (...) - { - return vector(); - } - } - // convert binary data to text, 4 bytes => 3 words - string binary2text(const vector& binary) - { - int n = NUMWORDS; // hardcoded because this is what electrum uses - - if (binary.size() % 4 != 0) - throw runtime_error("Invalid binary data size for mnemonic encoding"); - // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 - string res; - for (unsigned int i=0; i < binary.size() / 4; i++) - { - const uint32_t* val = - reinterpret_cast(&binary[i * 4]); - - uint32_t w1 = *val % n; - uint32_t w2 = ((*val / n) + w1) % n; - uint32_t w3 = (((*val / n) / n) + w2) % n; - - res += wordsArray[w1] + " "; - res += wordsArray[w2] + " "; - res += wordsArray[w3] + " "; - } - res.erase(--res.end()); // remove trailing space - return res; - } - std::string word_by_num(uint32_t n) - { - if (n >= NUMWORDS) - return ""; - return wordsArray[n]; - } - - bool valid_word(const std::string& w) - { - auto it = wordsMap.find(w); - return it != wordsMap.end(); - } - - uint64_t num_by_word(const std::string& w) - { - auto it = wordsMap.find(w); - CHECK_AND_ASSERT_THROW_MES(it!= wordsMap.end(), "unable to find word \"" << w << "\" in mnemonic dictionary"); - return it->second; - } - } -} diff --git a/src/common/mnemonic-encoding.h b/src/common/mnemonic-encoding.h deleted file mode 100644 index 4ce6b9b..0000000 --- a/src/common/mnemonic-encoding.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2014, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* - * This file and its cpp file are for translating Electrum-style word lists - * into their equivalent byte representations for cross-compatibility with - * that method of "backing up" one's wallet keys. - */ - - -#include -#include - -namespace tools -{ - namespace mnemonic_encoding - { - constexpr int NUMWORDS = 1626; - - std::vector text2binary(const std::string& text); - std::string binary2text(const std::vector& binary); - std::string word_by_num(uint32_t n); - uint64_t num_by_word(const std::string& w); - bool valid_word(const std::string& w); - } -} diff --git a/src/common/ntp.cpp b/src/common/ntp.cpp deleted file mode 100644 index fdbc2a5..0000000 --- a/src/common/ntp.cpp +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2019 Zano Project - -// Note: class udp_blocking_client is a slightly modified version of an example -// taken from https://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/timeouts/blocking_udp_client.cpp -// -// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ntp.h" - -using boost::asio::deadline_timer; -using boost::asio::ip::udp; - -//---------------------------------------------------------------------- - -// -// This class manages socket timeouts by applying the concept of a deadline. -// Each asynchronous operation is given a deadline by which it must complete. -// Deadlines are enforced by an "actor" that persists for the lifetime of the -// client object: -// -// +----------------+ -// | | -// | check_deadline |<---+ -// | | | -// +----------------+ | async_wait() -// | | -// +---------+ -// -// If the actor determines that the deadline has expired, any outstanding -// socket operations are cancelled. The socket operations themselves are -// implemented as transient actors: -// -// +---------------+ -// | | -// | receive | -// | | -// +---------------+ -// | -// async_- | +----------------+ -// receive() | | | -// +--->| handle_receive | -// | | -// +----------------+ -// -// The client object runs the io_service to block thread execution until the -// actor completes. -// -namespace -{ -class udp_blocking_client -{ -public: - udp_blocking_client(const udp::endpoint& listen_endpoint, udp::socket& socket, boost::asio::io_service& io_service) - : socket_(socket), - io_service_(io_service), - deadline_(io_service) - { - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - } - - std::size_t receive(const boost::asio::mutable_buffer& buffer, - boost::posix_time::time_duration timeout, boost::system::error_code& ec) - { - // Set a deadline for the asynchronous operation. - deadline_.expires_from_now(timeout); - - // Set up the variables that receive the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - ec = boost::asio::error::would_block; - std::size_t length = 0; - - // Start the asynchronous operation itself. The handle_receive function - // used as a callback will update the ec and length variables. - socket_.async_receive(boost::asio::buffer(buffer), - boost::bind(&udp_blocking_client::handle_receive, _1, _2, &ec, &length)); - - // Block until the asynchronous operation has completed. - do io_service_.run_one(); while (ec == boost::asio::error::would_block); - - return length; - } - -private: - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (deadline_.expires_at() <= deadline_timer::traits_type::now()) - { - // The deadline has passed. The outstanding asynchronous operation needs - // to be cancelled so that the blocked receive() function will return. - // - // Please note that cancel() has portability issues on some versions of - // Microsoft Windows, and it may be necessary to use close() instead. - // Consult the documentation for cancel() for further information. - socket_.cancel(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - deadline_.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - deadline_.async_wait(boost::bind(&udp_blocking_client::check_deadline, this)); - } - - static void handle_receive( - const boost::system::error_code& ec, std::size_t length, - boost::system::error_code* out_ec, std::size_t* out_length) - { - *out_ec = ec; - *out_length = length; - } - -private: - boost::asio::io_service& io_service_; - udp::socket& socket_; - deadline_timer deadline_; -}; - - -#pragma pack(push, 1) -struct ntp_packet -{ - - uint8_t li_vn_mode; // Eight bits. li, vn, and mode. - // li. Two bits. Leap indicator. - // vn. Three bits. Version number of the protocol. - // mode. Three bits. Client will pick mode 3 for client. - - uint8_t stratum; // Eight bits. Stratum level of the local clock. - uint8_t poll; // Eight bits. Maximum interval between successive messages. - uint8_t precision; // Eight bits. Precision of the local clock. - - uint32_t rootDelay; // 32 bits. Total round trip delay time. - uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. - uint32_t refId; // 32 bits. Reference clock identifier. - - uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. - uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. - - uint64_t orig_tm; // 64 bits. Originate time-stamp (set by client) - - uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. - uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. - - uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. - uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. - -}; // Total: 384 bits or 48 bytes. -#pragma pack(pop) - -static_assert(sizeof(ntp_packet) == 48, "ntp_packet has invalid size"); - -} // namespace - - -namespace tools -{ - int64_t get_ntp_time(const std::string& host_name, size_t timeout_sec) - { - try - { - boost::asio::io_service io_service; - boost::asio::ip::udp::resolver resolver(io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), host_name, "ntp"); - boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); - boost::asio::ip::udp::socket socket(io_service); - socket.open(boost::asio::ip::udp::v4()); - - ntp_packet packet_sent = AUTO_VAL_INIT(packet_sent); - packet_sent.li_vn_mode = 0x1b; - auto packet_sent_time = std::chrono::high_resolution_clock::now(); - socket.send_to(boost::asio::buffer(&packet_sent, sizeof packet_sent), receiver_endpoint); - - ntp_packet packet_received = AUTO_VAL_INIT(packet_received); - boost::asio::ip::udp::endpoint sender_endpoint; - - udp_blocking_client ubc(sender_endpoint, socket, io_service); - boost::system::error_code ec; - ubc.receive(boost::asio::buffer(&packet_received, sizeof packet_received), boost::posix_time::seconds(static_cast(timeout_sec)), ec); - if (ec) - { - LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): boost error: " << ec.message()); - return 0; - } - - auto packet_received_time = std::chrono::high_resolution_clock::now(); - int64_t roundtrip_mcs = std::chrono::duration_cast(packet_received_time - packet_sent_time).count(); - uint64_t roundtrip_s = roundtrip_mcs > 2000000 ? roundtrip_mcs / 2000000 : 0; - - time_t ntp_time = ntohl(packet_received.txTm_s); - if (ntp_time <= 2208988800U) - { - LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): wrong txTm_s: " << packet_received.txTm_s); - return 0; - } - // LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): RAW time received: " << ntp_time << ", refTm_s: " << ntohl(packet_received.refTm_s) << ", stratum: " << packet_received.stratum << ", round: " << roundtrip_mcs); - ntp_time -= 2208988800U; // Unix time starts from 01/01/1970 == 2208988800U - ntp_time += roundtrip_s; - return ntp_time; - } - catch (const std::exception& e) - { - LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): exception: " << e.what()); - return 0; - } - catch (...) - { - LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): unknown exception"); - return 0; - } - } - - - #define TIME_SYNC_NTP_SERVERS "time1.google.com", "time2.google.com", "time3.google.com", "time4.google.com" /* , "pool.ntp.org" -- we need to request a vender zone before using this pool */ - #define TIME_SYNC_NTP_TIMEOUT_SEC 5 - #define TIME_SYNC_NTP_ATTEMPTS_COUNT 3 // max number of attempts when getting time from NTP server - - int64_t get_ntp_time() - { - static const std::vector ntp_servers { TIME_SYNC_NTP_SERVERS }; - - for (size_t att = 0; att < TIME_SYNC_NTP_ATTEMPTS_COUNT; ++att) - { - const std::string& ntp_server = ntp_servers[att % ntp_servers.size()]; - LOG_PRINT_L3("NTP: trying to get time from " << ntp_server); - int64_t time = get_ntp_time(ntp_server, TIME_SYNC_NTP_TIMEOUT_SEC); - if (time > 0) - { - LOG_PRINT_L3("NTP: " << ntp_server << " responded with " << time << " (" << epee::misc_utils::get_time_str_v2(time) << ")"); - return time; - } - } - - LOG_PRINT_RED("NTP: unable to get time from NTP with " << TIME_SYNC_NTP_ATTEMPTS_COUNT << " trials", LOG_LEVEL_2); - return 0; // smth went wrong - } - - - -} // namespace tools diff --git a/src/common/ntp.h b/src/common/ntp.h deleted file mode 100644 index 4e453b3..0000000 --- a/src/common/ntp.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2019 Zano Project - -#pragma once -#include -#include - -namespace tools -{ - - // requests current time via NTP from 'host_hame' using 'timeout_sec' - // may return zero -- means error - int64_t get_ntp_time(const std::string& host_name, size_t timeout_sec = 5); - - // request time via predefined NTP servers - // may return zero -- mean error - int64_t get_ntp_time(); - -} // namespace tools diff --git a/src/common/pod-class.h b/src/common/pod-class.h deleted file mode 100644 index 84c8999..0000000 --- a/src/common/pod-class.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -// in C++ no difference 'class' vs 'struct' except the default members access. -// maybe be better to erase the 'POD_CLASS' macro completely? -#define POD_CLASS struct diff --git a/src/common/pod_array_file_container.h b/src/common/pod_array_file_container.h deleted file mode 100644 index 7c168d7..0000000 --- a/src/common/pod_array_file_container.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include - -namespace tools -{ - - template - class pod_array_file_container - { - public: - pod_array_file_container() - {} - - ~pod_array_file_container() - { - close(); - } - - bool open(const std::wstring& filename, bool create_if_not_exist, bool* p_corrupted = nullptr, std::string* p_reason = nullptr) - { - if (!create_if_not_exist && !boost::filesystem::exists(filename)) - { - if (p_reason) - *p_reason = "file doest not exist"; - return false; - } - - m_stream.open(filename, std::ios::binary | std::ios::app | std::ios::in); - if (m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit) - { - if (p_reason) - *p_reason = "file could not be opened"; - return false; - } - - if (p_corrupted) - *p_corrupted = false; - - size_t file_size = size_bytes(); - if (file_size % sizeof(pod_t) != 0) - { - // currupted - if (p_corrupted) - *p_corrupted = true; - - size_t corrected_size = file_size - file_size % sizeof(pod_t); - - // truncate to nearest item boundary - close(); - boost::filesystem::resize_file(filename, corrected_size); - m_stream.open(filename, std::ios::binary | std::ios::app | std::ios::in); - if ((m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit) || - size_bytes() != corrected_size) - { - if (p_reason) - *p_reason = "truncation failed"; - return false; - } - - if (p_reason) - *p_reason = std::string("file was corrupted, truncated: ") + epee::string_tools::num_to_string_fast(file_size) + " -> " + epee::string_tools::num_to_string_fast(corrected_size); - } - - return true; - } - - void close() - { - m_stream.close(); - } - - bool push_back(const pod_t& item) - { - if (!m_stream.is_open() || (m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit)) - return false; - - m_stream.seekp(0, std::ios_base::end); - m_stream.write(reinterpret_cast(&item), sizeof item); - - if (m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit) - return false; - - m_stream.flush(); - - return true; - } - - bool get_item(size_t index, pod_t& result) const - { - if (!m_stream.is_open() || (m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit)) - return false; - - size_t offset = index * sizeof result; - m_stream.seekg(offset); - if (m_stream.rdstate() != std::ios::goodbit) - return false; - - m_stream.read(reinterpret_cast(&result), sizeof result); - - return m_stream.gcount() == sizeof result; - } - - size_t size_bytes() const - { - if (!m_stream.is_open() || (m_stream.rdstate() != std::ios::goodbit && m_stream.rdstate() != std::ios::eofbit)) - return 0; - - m_stream.seekg(0, std::ios_base::end); - return m_stream.tellg(); - } - - size_t size() const - { - return size_bytes() / sizeof(pod_t); - } - - private: - mutable boost::filesystem::fstream m_stream; - }; - -} // namespace tools diff --git a/src/common/pre_download.h b/src/common/pre_download.h deleted file mode 100644 index 5feec36..0000000 --- a/src/common/pre_download.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2020 Zano Project -// Copyright (c) 2012-2018 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#pragma once - -#include -#include "net/http_client.h" -#include "db_backend_selector.h" -#include "crypto/crypto.h" -#include "currency_core/currency_core.h" - -namespace tools -{ - struct pre_download_entry - { - const char* url; - const char* hash; - uint64_t packed_size; - uint64_t unpacked_size; - }; - -#ifndef TESTNET - static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_1161000.pak", "26660ffcdaf80a43a586e64a1a6da042dcb9ff3b58e14ce1ec9a775b995dc146", 1330022593, 2684313600 }; - static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_1161000.pak", "9dd03f08dea396fe32e6483a8221b292be35fa41c29748f119f11c3275956cdc", 1787475468, 2600247296 }; -#else - static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 }; - static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 }; -#endif - - static constexpr uint64_t pre_download_min_size_difference = 512 * 1024 * 1024; // minimum difference in size between local DB and the downloadable one to start downloading - - template - bool process_predownload(const boost::program_options::variables_map& vm, callback_t cb_should_stop) - { - tools::db::db_backend_selector dbbs; - bool r = dbbs.init(vm); - CHECK_AND_ASSERT_MES(r, false, "db_backend_selector failed to initialize"); - - std::string config_folder = dbbs.get_config_folder(); - std::string working_folder = dbbs.get_db_folder_path(); - std::string db_main_file_path = working_folder + "/" + dbbs.get_db_main_file_name(); - - pre_download_entry pre_download = dbbs.get_engine_type() == db::db_lmdb ? c_pre_download_lmdb : c_pre_download_mdbx; - - // override pre-download link if necessary - std::string url = pre_download.url; - if (command_line::has_arg(vm, command_line::arg_predownload_link)) - url = command_line::get_arg(vm, command_line::arg_predownload_link); - - boost::system::error_code ec; - uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec); - bool flag_force_predownload = command_line::has_arg(vm, command_line::arg_force_predownload); - if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || flag_force_predownload) ) - { - LOG_PRINT_MAGENTA("Pre-downloading not needed (db file size = " << sz << ")", LOG_LEVEL_0); - return true; - } - - // okay, let's download - - - std::string downloading_file_path = db_main_file_path + ".download"; - - LOG_PRINT_MAGENTA("Trying to download blockchain database from " << url << " ...", LOG_LEVEL_0); - epee::net_utils::http::interruptible_http_client cl; - - crypto::stream_cn_hash hash_stream; - auto last_update = std::chrono::system_clock::now(); - - auto cb = [&hash_stream, &last_update, &cb_should_stop](const std::string& buff, uint64_t total_bytes, uint64_t received_bytes) - { - if (cb_should_stop(total_bytes, received_bytes)) - { - LOG_PRINT_MAGENTA(ENDL << "Interrupting download", LOG_LEVEL_0); - return false; - } - - hash_stream.update(buff.data(), buff.size()); - - auto dif = std::chrono::system_clock::now() - last_update; - if (dif >= std::chrono::milliseconds(300)) - { - boost::io::ios_flags_saver ifs(std::cout); - std::cout << "Received " << received_bytes / 1048576 << " of " << total_bytes / 1048576 << " MiB ( " << std::fixed << std::setprecision(1) << 100.0 * received_bytes / total_bytes << " %)\r"; - last_update = std::chrono::system_clock::now(); - } - - return true; - }; - - tools::create_directories_if_necessary(working_folder); - r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */); - if (!r) - { - LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0); - return !flag_force_predownload; // fatal error only if force-predownload - } - - crypto::hash data_hash = hash_stream.calculate_hash(); - if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash) - { - LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash); - return !flag_force_predownload; // fatal error only if force-predownload - } - - LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0); - - if (!command_line::has_arg(vm, command_line::arg_validate_predownload)) - { - boost::filesystem::remove(db_main_file_path, ec); - if (ec) - { - LOG_ERROR("Failed to remove " << db_main_file_path); - return false; - } - LOG_PRINT_L1("Removed " << db_main_file_path); - - boost::filesystem::rename(downloading_file_path, db_main_file_path, ec); - if (ec) - { - LOG_ERROR("Failed to rename " << downloading_file_path << " -> " << db_main_file_path); - return false; - } - LOG_PRINT_L1("Renamed " << downloading_file_path << " -> " << db_main_file_path); - - LOG_PRINT_GREEN("Blockchain successfully replaced with the new pre-downloaded data file", LOG_LEVEL_0); - return true; - } - - // - // paranoid mode - // move downloaded blockchain into a temporary folder - // - LOG_PRINT_MAGENTA(ENDL << "Downloaded blockchain database is about to be validated and added to the local database block-by-block" << ENDL, LOG_LEVEL_0); - std::string path_to_temp_datafolder = dbbs.get_temp_config_folder(); - std::string path_to_temp_blockchain = dbbs.get_temp_db_folder_path(); - std::string path_to_temp_blockchain_file = path_to_temp_blockchain + "/" + dbbs.get_db_main_file_name(); - - tools::create_directories_if_necessary(path_to_temp_blockchain); - boost::filesystem::rename(downloading_file_path, path_to_temp_blockchain_file, ec); - if (ec) - { - LOG_ERROR("Rename failed: " << downloading_file_path << " -> " << path_to_temp_blockchain_file); - return false; - } - - // remove old blockchain database from disk - boost::filesystem::remove_all(working_folder, ec); - if (ec) - { - LOG_ERROR("Failed to remove all from " << working_folder); - return false; - } - - std::string pool_db_path = dbbs.get_pool_db_folder_path(); - boost::filesystem::remove_all(pool_db_path, ec); - if (ec) - { - LOG_ERROR("Failed to remove all from " << pool_db_path); - return false; - } - - // source core - currency::core source_core(nullptr); - boost::program_options::variables_map source_core_vm; - source_core_vm.insert(std::make_pair("data-dir", boost::program_options::variable_value(path_to_temp_datafolder, false))); - source_core_vm.insert(std::make_pair("db-engine", boost::program_options::variable_value(dbbs.get_engine_name(), false))); - //source_core_vm.insert(std::make_pair("db-sync-mode", boost::program_options::variable_value(std::string("fast"), false))); - - r = source_core.init(source_core_vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to init source core"); - - // target core - currency::core target_core(nullptr); - boost::program_options::variables_map target_core_vm(vm); - target_core_vm.insert(std::make_pair("db-engine", boost::program_options::variable_value(dbbs.get_engine_name(), false))); - //vm_with_fast_sync.insert(std::make_pair("db-sync-mode", boost::program_options::variable_value(std::string("fast"), false))); - - r = target_core.init(target_core_vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to init target core"); - - CHECK_AND_ASSERT_MES(target_core.get_top_block_height() == 0, false, "Target blockchain initialized not empty"); - uint64_t total_blocks = source_core.get_current_blockchain_size(); - - LOG_PRINT_GREEN("Manually processing blocks from 1 to " << total_blocks << "...", LOG_LEVEL_0); - - for (uint64_t i = 1; i != total_blocks; i++) - { - std::list blocks; - std::list txs; - bool r = source_core.get_blocks(i, 1, blocks, txs); - CHECK_AND_ASSERT_MES(r && blocks.size()==1, false, "Failed to get block " << i << " from core"); - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - crypto::hash tx_hash = AUTO_VAL_INIT(tx_hash); - for (auto& tx : txs) - { - r = target_core.handle_incoming_tx(tx, tvc, true /* kept_by_block */); - CHECK_AND_ASSERT_MES(r && tvc.m_added_to_pool == true, false, "Failed to add a tx from block " << i << " from core"); - } - currency::block_verification_context bvc = AUTO_VAL_INIT(bvc); - r = target_core.handle_incoming_block(*blocks.begin(), bvc); - CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain == true, false, "Failed to add block " << i << " to core"); - if (!(i % 100)) - std::cout << "Block " << i << "(" << (i * 100) / total_blocks << "%) \r"; - - if (cb_should_stop(total_blocks, i)) - { - LOG_PRINT_MAGENTA(ENDL << "Interrupting updating db...", LOG_LEVEL_0); - return false; - } - } - - LOG_PRINT_GREEN("Processing finished, " << total_blocks << " successfully added.", LOG_LEVEL_0); - target_core.deinit(); - source_core.deinit(); - - boost::filesystem::remove_all(path_to_temp_datafolder, ec); - if (ec) - { - LOG_ERROR("Failed to remove all from " << path_to_temp_datafolder); - } - - return true; - } -} - diff --git a/src/common/unordered_containers_boost_serialization.h b/src/common/unordered_containers_boost_serialization.h deleted file mode 100644 index 644133f..0000000 --- a/src/common/unordered_containers_boost_serialization.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - -namespace boost -{ - namespace serialization - { - template - inline void save(Archive &a, const std::unordered_map &x, const boost::serialization::version_type ver) - { - size_t s = x.size(); - a << s; - BOOST_FOREACH(auto& v, x) - { - a << v.first; - a << v.second; - } - } - - template - inline void load(Archive &a, std::unordered_map &x, const boost::serialization::version_type ver) - { - x.clear(); - size_t s = 0; - a >> s; - for(size_t i = 0; i != s; i++) - { - h_key k; - hval v; - a >> k; - a >> v; - x.insert(std::pair(k, v)); - } - } - - - template - inline void save(Archive &a, const std::unordered_multimap &x, const boost::serialization::version_type ver) - { - size_t s = x.size(); - a << s; - BOOST_FOREACH(auto& v, x) - { - a << v.first; - a << v.second; - } - } - - template - inline void load(Archive &a, std::unordered_multimap &x, const boost::serialization::version_type ver) - { - x.clear(); - size_t s = 0; - a >> s; - for(size_t i = 0; i != s; i++) - { - h_key k; - hval v; - a >> k; - a >> v; - x.emplace(k, v); - } - } - - - template - inline void save(Archive &a, const std::unordered_set &x, const boost::serialization::version_type ver) - { - size_t s = x.size(); - a << s; - BOOST_FOREACH(auto& v, x) - { - a << v; - } - } - - template - inline void load(Archive &a, std::unordered_set &x, const boost::serialization::version_type ver) - { - x.clear(); - size_t s = 0; - a >> s; - for(size_t i = 0; i != s; i++) - { - hval v; - a >> v; - x.insert(v); - } - } - - - template - inline void serialize(Archive &a, std::unordered_map &x, const boost::serialization::version_type ver) - { - split_free(a, x, ver); - } - - template - inline void serialize(Archive &a, std::unordered_multimap &x, const boost::serialization::version_type ver) - { - split_free(a, x, ver); - } - - template - inline void serialize(Archive &a, std::unordered_set &x, const boost::serialization::version_type ver) - { - split_free(a, x, ver); - } - } -} diff --git a/src/common/util.cpp b/src/common/util.cpp deleted file mode 100644 index f5d4baa..0000000 --- a/src/common/util.cpp +++ /dev/null @@ -1,754 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "include_base_utils.h" -#include "zlib_helper.h" -using namespace epee; - -#include "util.h" -#include "currency_core/currency_config.h" -#include "version.h" - -#ifdef WIN32 -#include -#include -#include -#include -#pragma comment(lib, "netapi32.lib") -#else -#include -#endif - -#include - -#include "string_coding.h" - -namespace tools -{ - std::function signal_handler::m_handler; - std::function signal_handler::m_fatal_handler; - -#ifdef WIN32 - - bool GetWinMajorMinorVersion(DWORD& major, DWORD& minor) - { - bool bRetCode = false; - LPBYTE pinfoRawData = 0; - if (NERR_Success == NetWkstaGetInfo(NULL, 100, &pinfoRawData)) - { - WKSTA_INFO_100* pworkstationInfo = (WKSTA_INFO_100*)pinfoRawData; - major = pworkstationInfo->wki100_ver_major; - minor = pworkstationInfo->wki100_ver_minor; - ::NetApiBufferFree(pinfoRawData); - bRetCode = true; - } - return bRetCode; - } - - - std::string get_windows_version_display_string() - { - std::string winver; - OSVERSIONINFOEX osver; - SYSTEM_INFO sysInfo; - typedef void(__stdcall *GETSYSTEMINFO) (LPSYSTEM_INFO); - -#pragma warning (push) -#pragma warning (disable:4996) - memset(&osver, 0, sizeof(osver)); - osver.dwOSVersionInfoSize = sizeof(osver); - GetVersionEx((LPOSVERSIONINFO)&osver); -#pragma warning (pop) - DWORD major = 0; - DWORD minor = 0; - if (GetWinMajorMinorVersion(major, minor)) - { - osver.dwMajorVersion = major; - osver.dwMinorVersion = minor; - } - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) - { - OSVERSIONINFOEXW osvi; - ULONGLONG cm = 0; - cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_EQUAL); - ZeroMemory(&osvi, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(osvi); - osvi.dwMinorVersion = 3; - if (VerifyVersionInfoW(&osvi, VER_MINORVERSION, cm)) - { - osver.dwMinorVersion = 3; - } - } - - GETSYSTEMINFO getSysInfo = (GETSYSTEMINFO)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); - if (getSysInfo == NULL) getSysInfo = ::GetSystemInfo; - getSysInfo(&sysInfo); - - if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows 10 Server"; - else if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 10"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2012 R2"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 8.1"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2012"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 8"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2008 R2"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows 7"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType != VER_NT_WORKSTATION) winver = "Windows Server 2008"; - else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType == VER_NT_WORKSTATION) winver = "Windows Vista"; - else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION - && sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - winver = "Windows XP x64"; - else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2) winver = "Windows Server 2003"; - else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1) winver = "Windows XP"; - else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0) winver = "Windows 2000"; - else winver = "unknown"; - - if (osver.wServicePackMajor != 0) - { - std::string sp; - char buf[128] = { 0 }; - sp = " Service Pack "; - sprintf_s(buf, sizeof(buf), "%hd", osver.wServicePackMajor); - sp.append(buf); - winver += sp; - } - - if (osver.dwMajorVersion >= 6) - { - if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - winver += ", 64-bit"; - else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) - winver += ", 32-bit"; - } - - - winver += "(" - + std::to_string(osver.dwMajorVersion) + ":" - + std::to_string(osver.dwMinorVersion) + ":" - + std::to_string(osver.dwBuildNumber) + ":" - + std::to_string(osver.dwPlatformId) + ":" - + std::to_string(osver.wServicePackMajor) + ":" - + std::to_string(osver.wServicePackMinor) + ":" - + std::to_string(osver.wSuiteMask) + ":" - + std::to_string(osver.wProductType) + ")"; - - return winver; - } - - - - - - std::string get_windows_version_display_string_() - { - typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); - typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); -#define BUFSIZE 10000 - - char pszOS[BUFSIZE] = {0}; - OSVERSIONINFOEX osvi; - SYSTEM_INFO si; - PGNSI pGNSI; - PGPI pGPI; - BOOL bOsVersionInfoEx; - DWORD dwType; - - ZeroMemory(&si, sizeof(SYSTEM_INFO)); - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); - - if(!bOsVersionInfoEx) return pszOS; - - // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. - - pGNSI = (PGNSI) GetProcAddress( - GetModuleHandle(TEXT("kernel32.dll")), - "GetNativeSystemInfo"); - if(NULL != pGNSI) - pGNSI(&si); - else GetSystemInfo(&si); - - if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && - osvi.dwMajorVersion > 4 ) - { - StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft ")); - - // Test for the specific product. - - if ( osvi.dwMajorVersion == 6 ) - { - if( osvi.dwMinorVersion == 0 ) - { - if( osvi.wProductType == VER_NT_WORKSTATION ) - StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista ")); - else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " )); - } - - if ( osvi.dwMinorVersion == 1 ) - { - if( osvi.wProductType == VER_NT_WORKSTATION ) - StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 ")); - else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " )); - } - - pGPI = (PGPI) GetProcAddress( - GetModuleHandle(TEXT("kernel32.dll")), - "GetProductInfo"); - - pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); - - switch( dwType ) - { - case PRODUCT_ULTIMATE: - StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" )); - break; - case PRODUCT_PROFESSIONAL: - StringCchCat(pszOS, BUFSIZE, TEXT("Professional" )); - break; - case PRODUCT_HOME_PREMIUM: - StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" )); - break; - case PRODUCT_HOME_BASIC: - StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" )); - break; - case PRODUCT_ENTERPRISE: - StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" )); - break; - case PRODUCT_BUSINESS: - StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" )); - break; - case PRODUCT_STARTER: - StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" )); - break; - case PRODUCT_CLUSTER_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" )); - break; - case PRODUCT_DATACENTER_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" )); - break; - case PRODUCT_DATACENTER_SERVER_CORE: - StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" )); - break; - case PRODUCT_ENTERPRISE_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" )); - break; - case PRODUCT_ENTERPRISE_SERVER_CORE: - StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" )); - break; - case PRODUCT_ENTERPRISE_SERVER_IA64: - StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" )); - break; - case PRODUCT_SMALLBUSINESS_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" )); - break; - case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: - StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" )); - break; - case PRODUCT_STANDARD_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" )); - break; - case PRODUCT_STANDARD_SERVER_CORE: - StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" )); - break; - case PRODUCT_WEB_SERVER: - StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" )); - break; - } - } - - if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) - { - if( GetSystemMetrics(SM_SERVERR2) ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, ")); - else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003")); - else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server")); - else if( osvi.wProductType == VER_NT_WORKSTATION && - si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) - { - StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition")); - } - else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, ")); - - // Test for the server type. - if ( osvi.wProductType != VER_NT_WORKSTATION ) - { - if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 ) - { - if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" )); - else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" )); - } - - else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) - { - if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" )); - else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" )); - else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" )); - } - - else - { - if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" )); - else if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" )); - else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" )); - else if ( osvi.wSuiteMask & VER_SUITE_BLADE ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" )); - else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" )); - } - } - } - - if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) - { - StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP ")); - if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" )); - else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" )); - } - - if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) - { - StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 ")); - - if ( osvi.wProductType == VER_NT_WORKSTATION ) - { - StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" )); - } - else - { - if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" )); - else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) - StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" )); - else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" )); - } - } - - // Include service pack (if any) and build number. - - if( strlen(osvi.szCSDVersion) > 0 ) - { - StringCchCat(pszOS, BUFSIZE, TEXT(" ") ); - StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion); - } - - TCHAR buf[80]; - - StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber); - StringCchCat(pszOS, BUFSIZE, buf); - - if ( osvi.dwMajorVersion >= 6 ) - { - if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) - StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" )); - else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL ) - StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit")); - } - - return pszOS; - } - else - { - printf( "This sample does not support this version of Windows.\n"); - return pszOS; - } - } - - void signal_handler::GenerateCrashDump(EXCEPTION_POINTERS *pep /* = NULL*/) - { - SYSTEMTIME sysTime = { 0 }; - GetSystemTime(&sysTime); - // get the computer name - char compName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 }; - DWORD compNameLen = ARRAYSIZE(compName); - GetComputerNameA(compName, &compNameLen); - // build the filename: APPNAME_COMPUTERNAME_DATE_TIME.DMP - char path[MAX_PATH*10] = { 0 }; - std::string folder = epee::log_space::log_singletone::get_default_log_folder(); - sprintf_s(path, ARRAYSIZE(path),"%s\\crashdump_" PROJECT_VERSION_LONG "_%s_%04u-%02u-%02u_%02u-%02u-%02u.dmp", - folder.c_str(), compName, sysTime.wYear, sysTime.wMonth, sysTime.wDay, - sysTime.wHour, sysTime.wMinute, sysTime.wSecond); - - HANDLE hFile = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, - 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - // Create the minidump - MINIDUMP_EXCEPTION_INFORMATION mdei; - - mdei.ThreadId = GetCurrentThreadId(); - mdei.ExceptionPointers = pep; - mdei.ClientPointers = FALSE; - - MINIDUMP_CALLBACK_INFORMATION mci; - - mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback; - mci.CallbackParam = 0; - - MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory | - MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpWithFullMemoryInfo | - MiniDumpWithThreadInfo | - MiniDumpWithUnloadedModules); - - BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci); - - if (!rv) - { - LOG_ERROR("Minidump file create FAILED(error " << GetLastError() << ") on path: " << path); - } - else - { - LOG_PRINT_L0("Minidump file created on path: " << path); - } - // Close the file - CloseHandle(hFile); - } - else - { - LOG_ERROR("Minidump FAILED to create file (error " << GetLastError() << ") on path: " << path); - } - } - - - -#else // ifdef WIN32 -std::string get_nix_version_display_string() -{ - utsname un; - - if(uname(&un) < 0) - return std::string("*nix: failed to get os version"); - return std::string() + un.sysname + " " + un.version + " " + un.release; -} -#endif - - - - std::string get_os_version_string() - { -#ifdef WIN32 - return get_windows_version_display_string(); -#else - return get_nix_version_display_string(); -#endif - } - - - -#ifdef WIN32 - std::wstring get_special_folder_path_w(int nfolder, bool iscreate) - { - wchar_t psz_path[MAX_PATH] = L""; - - if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate)) - { - return psz_path; - } - - LOG_ERROR("SHGetSpecialFolderPathW(" << nfolder << ", " << iscreate << ") failed, could not obtain requested path."); - return L""; - } - - std::string get_special_folder_path_utf8(int nfolder, bool iscreate) - { - return epee::string_encoding::wstring_to_utf8(get_special_folder_path_w(nfolder, iscreate)); - } -#endif - - std::string get_default_data_dir() - { - //namespace fs = boost::filesystem; - // Windows < Vista: C:\Documents and Settings\Username\Application Data\CURRENCY_NAME_SHORT - // Windows >= Vista: C:\Users\Username\AppData\Roaming\CURRENCY_NAME_SHORT - // Mac: ~/Library/Application Support/CURRENCY_NAME_SHORT - // Unix: ~/.CURRENCY_NAME_SHORT - std::string config_folder; -#ifdef WIN32 - // Windows -#ifdef _M_X64 - config_folder = get_special_folder_path_utf8(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT; -#else - config_folder = get_special_folder_path_utf8(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT + "-x86"; -#endif -#else - std::string pathRet; - char* pszHome = getenv("HOME"); - if (pszHome == NULL || strlen(pszHome) == 0) - pathRet = "/"; - else - pathRet = pszHome; -#ifdef __APPLE__ - // Mac - pathRet += "/Library/Application Support"; - config_folder = (pathRet + "/" + CURRENCY_NAME_SHORT); -#else - // Unix - config_folder = (pathRet + "/." + CURRENCY_NAME_SHORT); -#endif -#endif - - return config_folder; - } - std::string get_host_computer_name() - { - char szname[1024] = ""; - gethostname(szname, sizeof(szname)); - szname[sizeof(szname)-1] = 0; //just to be sure - return szname; - } - - - std::string get_default_user_dir() - { - //namespace fs = boost::filesystem; - // Windows < Vista: C:\Documents and Settings\Username - // Windows >= Vista: C:\Users\Username\AppData\Roaming\CURRENCY_NAME_SHORT - // Mac: ~/Library/Application Support/CURRENCY_NAME_SHORT - // Unix: ~/.CURRENCY_NAME_SHORT - std::string wallets_dir; -#ifdef WIN32 - // Windows - wallets_dir = get_special_folder_path_utf8(CSIDL_PERSONAL, true) + "/" + CURRENCY_NAME_BASE; -#else - std::string pathRet; - char* pszHome = getenv("HOME"); - if (pszHome == NULL || strlen(pszHome) == 0) - pathRet = "/"; - else - pathRet = pszHome; - - wallets_dir = (pathRet + "/" + CURRENCY_NAME_BASE); - -#endif - return wallets_dir; - } - - std::string get_current_username() - { -#ifdef WIN32 - // Windows - const char* psz_username = getenv("USERNAME"); -#else - const char* psz_username = getenv("USER"); -#endif - if (psz_username == NULL || strlen(psz_username) == 0) - psz_username = "unknown_user"; - - return std::string(psz_username); - } - - - - bool create_directories_if_necessary(const std::string& path) - { - namespace fs = boost::filesystem; - boost::system::error_code ec; - fs::path fs_path = epee::string_encoding::utf8_to_wstring(path); - if (fs::is_directory(fs_path, ec)) - { - return true; - } - - bool res = fs::create_directories(fs_path, ec); - if (res) - { - LOG_PRINT_L2("Created directory: " << path); - } - else - { - LOG_PRINT_L2("Can't create directory: " << path << ", err: "<< ec.message()); - } - - return res; - } - - std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name) - { - int code; -#if defined(WIN32) - // Maximizing chances for success - DWORD attributes = ::GetFileAttributes(replaced_name.c_str()); - if (INVALID_FILE_ATTRIBUTES != attributes) - { - ::SetFileAttributes(replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY)); - } - - bool ok = 0 != ::MoveFileEx(replacement_name.c_str(), replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING); - code = ok ? 0 : static_cast(::GetLastError()); -#else - bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str()); - code = ok ? 0 : errno; -#endif - return std::error_code(code, std::system_category()); - } - -#define REQUEST_LOG_CHUNK_SIZE_MAX (10 * 1024 * 1024) - - bool get_log_chunk_gzipped(uint64_t offset, uint64_t size, std::string& output, std::string& error) - { - if (size > REQUEST_LOG_CHUNK_SIZE_MAX) - { - error = std::string("size is exceeding the limit = ") + epee::string_tools::num_to_string_fast(REQUEST_LOG_CHUNK_SIZE_MAX); - return false; - } - - std::string log_filename = epee::log_space::log_singletone::get_actual_log_file_path(); - if (std::ifstream log{ log_filename, std::ifstream::ate | std::ifstream::binary }) - { - uint64_t file_size = log.tellg(); - - if (offset >= file_size) - { - error = "offset is out of bounds"; - return false; - } - - if (offset + size > file_size) - { - error = "offset + size if out of bounds"; - return false; - } - - if (size != 0) - { - log.seekg(offset); - output.resize(size); - log.read(&output.front(), size); - uint64_t read_bytes = log.gcount(); - if (read_bytes != size) - { - error = std::string("read bytes: ") + epee::string_tools::num_to_string_fast(read_bytes); - return false; - } - - if (!epee::zlib_helper::pack(output)) - { - error = "zlib pack failed"; - return false; - } - } - - return true; - } - - error = std::string("can't open ") + log_filename; - return false; - } - - uint64_t get_log_file_size() - { - std::string log_filename = epee::log_space::log_singletone::get_actual_log_file_path(); - std::ifstream in(log_filename, std::ifstream::ate | std::ifstream::binary); - return static_cast(in.tellg()); - } - - bool check_remote_client_version(const std::string& client_ver) - { - std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id - v = v.substr(0, v.rfind('.')); // remove build number - - int v_major = 0, v_minor = 0, v_revision = 0; - - size_t dot_pos = v.find('.'); - if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) - return false; - - v = v.substr(dot_pos + 1); - dot_pos = v.find('.'); - if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) - return false; - - if (dot_pos != std::string::npos) - { - // revision - v = v.substr(dot_pos + 1); - if (!epee::string_tools::string_to_num_fast(v, v_revision)) - return false; - } - - // got v_major, v_minor, v_revision - - // allow 1.1.x and greater - - if (v_major < 1) - return false; - - if (v_major == 1 && v_minor < 1) - return false; - - return true; - } - - //this code was taken from https://stackoverflow.com/a/8594696/5566653 - //credits goes to @nijansen: https://stackoverflow.com/users/1056003/nijansen - bool copy_dir( boost::filesystem::path const & source, boost::filesystem::path const & destination) - { - namespace fs = boost::filesystem; - try - { - // Check whether the function call is valid - if (!fs::exists(source) ||!fs::is_directory(source)) - { - LOG_ERROR("Source directory " << source.string() << " does not exist or is not a directory."); - return false; - } - if (!fs::exists(destination)) - { - if (!fs::create_directory(destination)) - { - LOG_ERROR("Unable to create destination directory" << destination.string()); - return false; - } - } - // Create the destination directory - } - catch (fs::filesystem_error const & e) - { - LOG_ERROR("Exception: " << e.what()); - return false; - } - // Iterate through the source directory - for (fs::directory_iterator file(source); file != fs::directory_iterator(); ++file) - { - try - { - fs::path current(file->path()); - if (fs::is_directory(current)) - { - // Found directory: Recursion - if (!copy_dir(current, destination / current.filename())) - { - return false; - } - } - else - { - // Found file: Copy - fs::copy_file( current, destination / current.filename()); - } - } - catch (fs::filesystem_error const & e) - { - LOG_ERROR("Exception: " << e.what()); - } - } - return true; - } - -} // namespace tools diff --git a/src/common/util.h b/src/common/util.h deleted file mode 100644 index 0c5b0bb..0000000 --- a/src/common/util.h +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#define BOOST_FILESYSTEM_VERSION 3 -#define BOOST_NO_CXX11_SCOPED_ENUMS - -#include -#include -#include - -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "misc_language.h" -#include "p2p/p2p_protocol_defs.h" -#include "ntp.h" - -#if defined(WIN32) -#include -#endif - -#ifdef NDEBUG - #define BUILD_TYPE "Release" -#else - #define BUILD_TYPE "Debug" -#endif - -namespace tools -{ - std::string get_host_computer_name(); - std::string get_default_data_dir(); - std::string get_default_user_dir(); - std::string get_current_username(); - std::string get_os_version_string(); - bool copy_dir(boost::filesystem::path const & source, boost::filesystem::path const & destination); - bool check_remote_client_version(const std::string& client_ver); - - bool create_directories_if_necessary(const std::string& path); - std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name); - - inline crypto::hash get_proof_of_trust_hash(const nodetool::proof_of_trust& pot) - { - std::string s; - s.append(reinterpret_cast(&pot.peer_id), sizeof(pot.peer_id)); - s.append(reinterpret_cast(&pot.time), sizeof(pot.time)); - return crypto::cn_fast_hash(s.data(), s.size()); - } - - inline - crypto::public_key get_public_key_from_string(const std::string& str_key) - { - crypto::public_key k = AUTO_VAL_INIT(k); - epee::string_tools::hex_to_pod(str_key, k); - return k; - } - - bool get_log_chunk_gzipped(uint64_t offset, uint64_t size, std::string& output, std::string& error); - uint64_t get_log_file_size(); - - class signal_handler - { - public: - template - static bool install(T t) - { -#if defined(WIN32) - bool r = TRUE == ::SetConsoleCtrlHandler(&win_handler, TRUE); - if (r) - { - m_handler = t; - } - return r; -#else - signal(SIGINT, posix_handler); - signal(SIGTERM, posix_handler); - m_handler = t; - return true; -#endif - } - - template - static void install_fatal(T t) - { -#if defined(WIN32) - // NOTE: Unfortunately, there's no way to handle heap corruption signals/exceptions. More info: https://connect.microsoft.com/VisualStudio/feedback/details/664497/cant-catch-0xc0000374-exception-status-heap-corruption - ::SetUnhandledExceptionFilter(win_unhandled_exception_handler); -#else - signal(SIGABRT, posix_fatal_handler); - signal(SIGSEGV, posix_fatal_handler); - signal(SIGILL, posix_fatal_handler); -#endif - - m_fatal_handler = t; - } - - static void uninstall_fatal() - { -#if defined(WIN32) - ::SetUnhandledExceptionFilter(NULL); -#endif - signal(SIGABRT, SIG_DFL); - signal(SIGSEGV, SIG_DFL); - signal(SIGILL, SIG_DFL); - m_fatal_handler = &noop_fatal_handler; - } - - private: -#if defined(WIN32) - static BOOL WINAPI win_handler(DWORD type) - { - if (CTRL_C_EVENT == type || CTRL_BREAK_EVENT == type) - { - handle_signal(); - return TRUE; - } - else - { - LOG_PRINT_RED_L0("Got control signal " << type << ". Exiting without saving..."); - return FALSE; - } - return TRUE; - } - - /************************************************************************/ - // This code borrowed from http://www.debuginfo.com/articles/effminidumps2.html - /************************************************************************/ - - /////////////////////////////////////////////////////////////////////////////// - // This function determines whether we need data sections of the given module - // - - static bool IsDataSectionNeeded(const WCHAR* pModuleName) - { - // Check parameters - if (pModuleName == 0) - { - return false; - } - - // Extract the module name - - WCHAR szFileName[_MAX_FNAME] = L""; - - _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL); - // Compare the name with the list of known names and decide - // Note: For this to work, the executable name must be "mididump.exe" - if (wcsicmp(szFileName, L"mididump") == 0) - { - return true; - } - else if (wcsicmp(szFileName, L"ntdll") == 0) - { - return true; - } - // Complete - return false; - } - - /////////////////////////////////////////////////////////////////////////////// - // Custom minidump callback - // - - static BOOL CALLBACK MyMiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, - PMINIDUMP_CALLBACK_OUTPUT pOutput) - { - BOOL bRet = FALSE; - // Check parameters - if (pInput == 0) - return FALSE; - - if (pOutput == 0) - return FALSE; - - // Process the callbacks - switch (pInput->CallbackType) - { - case IncludeModuleCallback: - { - // Include the module into the dump - bRet = TRUE; - } - break; - - case IncludeThreadCallback: - { - // Include the thread into the dump - bRet = TRUE; - } - break; - - case ModuleCallback: - { - // Are data sections available for this module ? - - if (pOutput->ModuleWriteFlags & ModuleWriteDataSeg) - { - // Yes, they are, but do we need them? - - if (!IsDataSectionNeeded(pInput->Module.FullPath)) - { - wprintf(L"Excluding module data sections: %s \n", pInput->Module.FullPath); - - pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg); - } - } - - bRet = TRUE; - } - break; - - case ThreadCallback: - { - // Include all thread information into the minidump - bRet = TRUE; - } - break; - - case ThreadExCallback: - { - // Include this information - bRet = TRUE; - } - break; - - case MemoryCallback: - { - // We do not include any information here -> return FALSE - bRet = FALSE; - } - break; - - case CancelCallback: - break; - } - - return bRet; - - } - - static void GenerateCrashDump(EXCEPTION_POINTERS *pep = NULL); - - static LONG WINAPI win_unhandled_exception_handler(_In_ struct _EXCEPTION_POINTERS *ep) - { - GenerateCrashDump(ep); - handle_fatal_signal(ep->ExceptionRecord->ExceptionCode, ep->ExceptionRecord->ExceptionAddress); - return EXCEPTION_EXECUTE_HANDLER; - } - -#else - static void posix_handler(int /*type*/) - { - handle_signal(); - } -#endif - - static void posix_fatal_handler(int sig_number) - { - handle_fatal_signal(sig_number, 0); - } - - static void noop_fatal_handler(int, void*) {} - - static void handle_signal() - { - static epee::static_helpers::wrapper m_mutex; - std::unique_lock lock(m_mutex); - m_handler(); - } - - static void handle_fatal_signal(int sig_number, void* address) - { - static epee::static_helpers::wrapper m_mutex_fatal; - std::unique_lock lock(m_mutex_fatal); - m_fatal_handler(sig_number, address); - uninstall_fatal(); - } - - private: - static std::function m_handler; - static std::function m_fatal_handler; - }; - -} diff --git a/src/common/varint.h b/src/common/varint.h deleted file mode 100644 index 249fce2..0000000 --- a/src/common/varint.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include - -namespace tools { - - - //--------------------------------------------------------------- - template - size_t get_varint_packed_size(T v) - { - if(v <= 127) - return 1; - else if(v <= 16383) - return 2; - else if(v <= 2097151) - return 3; - else if(v <= 268435455) - return 4; - else if(v <= 34359738367) - return 5; - else if(v <= 4398046511103) - return 6; - else if(v <= 562949953421311) - return 7; - else - return 8; - } - template - typename std::enable_if::value && std::is_unsigned::value, void>::type - write_varint(OutputIt &&dest, T i) { - while (i >= 0x80) { - *dest++ = (static_cast(i) & 0x7f) | 0x80; - i >>= 7; - } - *dest++ = static_cast(i); - } - - template - std::string get_varint_data(const t_type& v) - { - std::stringstream ss; - write_varint(std::ostreambuf_iterator(ss), v); - return ss.str(); - } - - template - typename std::enable_if::value && std::is_unsigned::value && 0 <= bits && bits <= std::numeric_limits::digits, int>::type - read_varint(InputIt &&first, InputIt &&last, T &i) { - int read = 0; - i = 0; - for (int shift = 0;; shift += 7) { - if (first == last) { - return read; // End of input. - } - unsigned char byte = *first++; - ++read; - if (shift + 7 >= bits && byte >= 1 << (bits - shift)) { - return -1; // Overflow. - } - if (byte == 0 && shift != 0) { - return -2; // Non-canonical representation. - } - i |= static_cast(byte & 0x7f) << shift; - if ((byte & 0x80) == 0) { - break; - } - } - return read; - } - - template - int read_varint(InputIt &&first, InputIt &&last, T &i) { - return read_varint::digits, InputIt, T>(std::move(first), std::move(last), i); - } -} diff --git a/src/contrib/db/CMakeLists.txt b/src/contrib/db/CMakeLists.txt deleted file mode 100644 index 6f2213b..0000000 --- a/src/contrib/db/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - - -if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android") - message("excluded db support for IOS build") - return() -endif() - - - message("DB ENGINE: lmdb") - add_subdirectory(liblmdb) - if(MSVC) - target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) - else() - # Warnings as used by LMDB itself (LMDB_0.9.23) - target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) - endif() - if(NOT DISABLE_MDBX) - message("DB ENGINE: mdbx") - add_subdirectory(libmdbx) - endif() diff --git a/src/contrib/db/liblmdb/.gitignore b/src/contrib/db/liblmdb/.gitignore deleted file mode 100644 index d5102a8..0000000 --- a/src/contrib/db/liblmdb/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -mtest -mtest[23456] -testdb -mdb_copy -mdb_stat -mdb_dump -mdb_load -*.lo -*.[ao] -*.so -*.exe -*[~#] -*.bak -*.orig -*.rej -*.gcov -*.gcda -*.gcno -core -core.* -valgrind.* -man/ -html/ diff --git a/src/contrib/db/liblmdb/CHANGES b/src/contrib/db/liblmdb/CHANGES deleted file mode 100644 index aabb1ad..0000000 --- a/src/contrib/db/liblmdb/CHANGES +++ /dev/null @@ -1,192 +0,0 @@ -LMDB 0.9 Change Log - -LMDB 0.9.18 Release Engineering - Fix robust mutex detection on glibc 2.10-11 (ITS#8330) - Check for utf8_to_utf16 failures (ITS#7992) - Catch strdup failure in mdb_dbi_open - Build - Additional makefile var tweaks (ITS#8169) - Documentation - Add Getting Started page - - -LMDB 0.9.17 Release (2015/11/30) - Fix ITS#7377 catch calloc failure - Fix ITS#8237 regression from ITS#7589 - Fix ITS#8238 page_split for DUPFIXED pages - Fix ITS#8221 MDB_PAGE_FULL on delete/rebalance - Fix ITS#8258 rebalance/split assert - Fix ITS#8263 cursor_put cursor tracking - Fix ITS#8264 cursor_del cursor tracking - Fix ITS#8310 cursor_del cursor tracking - Fix ITS#8299 mdb_del cursor tracking - Fix ITS#8300 mdb_del cursor tracking - Fix ITS#8304 mdb_del cursor tracking - Fix ITS#7771 fakepage cursor tracking - Fix ITS#7789 ensure mapsize >= pages in use - Fix ITS#7971 mdb_txn_renew0() new reader slots - Fix ITS#7969 use __sync_synchronize on non-x86 - Fix ITS#8311 page_split from update_key - Fix ITS#8312 loose pages in nested txn - Fix ITS#8313 mdb_rebalance dummy cursor - Fix ITS#8315 dirty_room in nested txn - Fix ITS#8323 dirty_list in nested txn - Fix ITS#8316 page_merge cursor tracking - Fix ITS#8321 cursor tracking - Fix ITS#8319 mdb_load error messages - Fix ITS#8320 mdb_load plaintext input - Added mdb_txn_id() (ITS#7994) - Added robust mutex support - Miscellaneous cleanup/simplification - Build - Create install dirs if needed (ITS#8256) - Fix ThreadProc decl on Win32/MSVC (ITS#8270) - Added ssize_t typedef for MSVC (ITS#8067) - Use ANSI apis on Windows (ITS#8069) - Use O_SYNC if O_DSYNC,MDB_DSYNC are not defined (ITS#7209) - Allow passing AR to make (ITS#8168) - Allow passing mandir to make install (ITS#8169) - -LMDB 0.9.16 Release (2015/08/14) - Fix cursor EOF bug (ITS#8190) - Fix handling of subDB records (ITS#8181) - Fix mdb_midl_shrink() usage (ITS#8200) - -LMDB 0.9.15 Release (2015/06/19) - Fix txn init (ITS#7961,#7987) - Fix MDB_PREV_DUP (ITS#7955,#7671) - Fix compact of empty env (ITS#7956) - Fix mdb_copy file mode - Fix mdb_env_close() after failed mdb_env_open() - Fix mdb_rebalance collapsing root (ITS#8062) - Fix mdb_load with large values (ITS#8066) - Fix to retry writes on EINTR (ITS#8106) - Fix mdb_cursor_del on empty DB (ITS#8109) - Fix MDB_INTEGERDUP key compare (ITS#8117) - Fix error handling (ITS#7959,#8157,etc.) - Fix race conditions (ITS#7969,7970) - Added workaround for fdatasync bug in ext3fs - Build - Don't use -fPIC for static lib - Update .gitignore (ITS#7952,#7953) - Cleanup for "make test" (ITS#7841), "make clean", mtest*.c - Misc. Android/Windows cleanup - Documentation - Fix MDB_APPEND doc - Fix MDB_MAXKEYSIZE doc (ITS#8156) - Fix mdb_cursor_put,mdb_cursor_del EACCES description - Fix mdb_env_sync(MDB_RDONLY env) doc (ITS#8021) - Clarify MDB_WRITEMAP doc (ITS#8021) - Clarify mdb_env_open doc - Clarify mdb_dbi_open doc - -LMDB 0.9.14 Release (2014/09/20) - Fix to support 64K page size (ITS#7713) - Fix to persist decreased as well as increased mapsizes (ITS#7789) - Fix cursor bug when deleting last node of a DUPSORT key - Fix mdb_env_info to return FIXEDMAP address - Fix ambiguous error code from writing to closed DBI (ITS#7825) - Fix mdb_copy copying past end of file (ITS#7886) - Fix cursor bugs from page_merge/rebalance - Fix to dirty fewer pages in deletes (mdb_page_loose()) - Fix mdb_dbi_open creating subDBs (ITS#7917) - Fix mdb_cursor_get(_DUP) with single value (ITS#7913) - Fix Windows compat issues in mtests (ITS#7879) - Add compacting variant of mdb_copy - Add BigEndian integer key compare code - Add mdb_dump/mdb_load utilities - -LMDB 0.9.13 Release (2014/06/18) - Fix mdb_page_alloc unlimited overflow page search - Documentation - Re-fix MDB_CURRENT doc (ITS#7793) - Fix MDB_GET_MULTIPLE/MDB_NEXT_MULTIPLE doc - -LMDB 0.9.12 Release (2014/06/13) - Fix MDB_GET_BOTH regression (ITS#7875,#7681) - Fix MDB_MULTIPLE writing multiple keys (ITS#7834) - Fix mdb_rebalance (ITS#7829) - Fix mdb_page_split (ITS#7815) - Fix md_entries count (ITS#7861,#7828,#7793) - Fix MDB_CURRENT (ITS#7793) - Fix possible crash on Windows DLL detach - Misc code cleanup - Documentation - mdb_cursor_put: cursor moves on error (ITS#7771) - - -LMDB 0.9.11 Release (2014/01/15) - Add mdb_env_set_assert() (ITS#7775) - Fix: invalidate txn on page allocation errors (ITS#7377) - Fix xcursor tracking in mdb_cursor_del0() (ITS#7771) - Fix corruption from deletes (ITS#7756) - Fix Windows/MSVC build issues - Raise safe limit of max MDB_MAXKEYSIZE - Misc code cleanup - Documentation - Remove spurious note about non-overlapping flags (ITS#7665) - -LMDB 0.9.10 Release (2013/11/12) - Add MDB_NOMEMINIT option - Fix mdb_page_split() again (ITS#7589) - Fix MDB_NORDAHEAD definition (ITS#7734) - Fix mdb_cursor_del() positioning (ITS#7733) - Partial fix for larger page sizes (ITS#7713) - Fix Windows64/MSVC build issues - -LMDB 0.9.9 Release (2013/10/24) - Add mdb_env_get_fd() - Add MDB_NORDAHEAD option - Add MDB_NOLOCK option - Avoid wasting space in mdb_page_split() (ITS#7589) - Fix mdb_page_merge() cursor fixup (ITS#7722) - Fix mdb_cursor_del() on last delete (ITS#7718) - Fix adding WRITEMAP on existing env (ITS#7715) - Fix nested txns (ITS#7515) - Fix mdb_env_copy() O_DIRECT bug (ITS#7682) - Fix mdb_cursor_set(SET_RANGE) return code (ITS#7681) - Fix mdb_rebalance() cursor fixup (ITS#7701) - Misc code cleanup - Documentation - Note that by default, readers need write access - - -LMDB 0.9.8 Release (2013/09/09) - Allow mdb_env_set_mapsize() on an open environment - Fix mdb_dbi_flags() (ITS#7672) - Fix mdb_page_unspill() in nested txns - Fix mdb_cursor_get(CURRENT|NEXT) after a delete - Fix mdb_cursor_get(DUP) to always return key (ITS#7671) - Fix mdb_cursor_del() to always advance to next item (ITS#7670) - Fix mdb_cursor_set(SET_RANGE) for tree with single page (ITS#7681) - Fix mdb_env_copy() retry open if O_DIRECT fails (ITS#7682) - Tweak mdb_page_spill() to be less aggressive - Documentation - Update caveats since mdb_reader_check() added in 0.9.7 - -LMDB 0.9.7 Release (2013/08/17) - Don't leave stale lockfile on failed RDONLY open (ITS#7664) - Fix mdb_page_split() ref beyond cursor depth - Fix read txn data race (ITS#7635) - Fix mdb_rebalance (ITS#7536, #7538) - Fix mdb_drop() (ITS#7561) - Misc DEBUG macro fixes - Add MDB_NOTLS envflag - Add mdb_env_copyfd() - Add mdb_txn_env() (ITS#7660) - Add mdb_dbi_flags() (ITS#7661) - Add mdb_env_get_maxkeysize() - Add mdb_env_reader_list()/mdb_env_reader_check() - Add mdb_page_spill/unspill, remove hard txn size limit - Use shorter names for semaphores (ITS#7615) - Build - Fix install target (ITS#7656) - Documentation - Misc updates for cursors, DB handles, data lifetime - -LMDB 0.9.6 Release (2013/02/25) - Many fixes/enhancements - -LMDB 0.9.5 Release (2012/11/30) - Renamed from libmdb to liblmdb - Many fixes/enhancements diff --git a/src/contrib/db/liblmdb/CMakeLists.txt b/src/contrib/db/liblmdb/CMakeLists.txt deleted file mode 100644 index dc49182..0000000 --- a/src/contrib/db/liblmdb/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ - -set (lmdb_sources mdb.c midl.c) - -include_directories("${CMAKE_CURRENT_SOURCE_DIR}") - -if(NOT MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-missing-braces -Wno-aggregate-return -Wno-discarded-qualifiers -Wno-unused-but-set-variable -Wno-implicit-fallthrough -Wno-maybe-uninitialized ") -endif() -if(FREEBSD) - add_definitions(-DMDB_DSYNC=O_SYNC) -endif() - -add_library(lmdb ${lmdb_sources}) - -target_link_libraries(lmdb PRIVATE ${CMAKE_THREAD_LIBS_INIT}) - -if(WIN32) - target_link_libraries(lmdb ntdll) -endif() diff --git a/src/contrib/db/liblmdb/COPYRIGHT b/src/contrib/db/liblmdb/COPYRIGHT deleted file mode 100644 index 722d1a5..0000000 --- a/src/contrib/db/liblmdb/COPYRIGHT +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2011-2015 Howard Chu, Symas Corp. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted only as authorized by the OpenLDAP -Public License. - -A copy of this license is available in the file LICENSE in the -top-level directory of the distribution or, alternatively, at -. - -OpenLDAP is a registered trademark of the OpenLDAP Foundation. - -Individual files and/or contributed packages may be copyright by -other parties and/or subject to additional restrictions. - -This work also contains materials derived from public sources. - -Additional information about OpenLDAP can be obtained at -. diff --git a/src/contrib/db/liblmdb/Doxyfile b/src/contrib/db/liblmdb/Doxyfile deleted file mode 100644 index 5047c0b..0000000 --- a/src/contrib/db/liblmdb/Doxyfile +++ /dev/null @@ -1,1631 +0,0 @@ -# Doxyfile 1.7.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = LMDB - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -INLINE_GROUPED_CLASSES = YES -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = YES - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = lmdb.h midl.h mdb.c midl.c intro.doc - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = YES - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = DEBUG=2 __GNUC__=1 - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = tooltag=./man1 - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans.ttf - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/src/contrib/db/liblmdb/LICENSE b/src/contrib/db/liblmdb/LICENSE deleted file mode 100644 index 05ad757..0000000 --- a/src/contrib/db/liblmdb/LICENSE +++ /dev/null @@ -1,47 +0,0 @@ -The OpenLDAP Public License - Version 2.8, 17 August 2003 - -Redistribution and use of this software and associated documentation -("Software"), with or without modification, are permitted provided -that the following conditions are met: - -1. Redistributions in source form must retain copyright statements - and notices, - -2. Redistributions in binary form must reproduce applicable copyright - statements and notices, this list of conditions, and the following - disclaimer in the documentation and/or other materials provided - with the distribution, and - -3. Redistributions must contain a verbatim copy of this document. - -The OpenLDAP Foundation may revise this license from time to time. -Each revision is distinguished by a version number. You may use -this Software under terms of this license revision or under the -terms of any subsequent revision of the license. - -THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS -CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) -OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -The names of the authors and copyright holders must not be used in -advertising or otherwise to promote the sale, use or other dealing -in this Software without specific, written prior permission. Title -to copyright in this Software shall at all times remain with copyright -holders. - -OpenLDAP is a registered trademark of the OpenLDAP Foundation. - -Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, -California, USA. All Rights Reserved. Permission to copy and -distribute verbatim copies of this document is granted. diff --git a/src/contrib/db/liblmdb/Makefile b/src/contrib/db/liblmdb/Makefile deleted file mode 100644 index f3c93a2..0000000 --- a/src/contrib/db/liblmdb/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -# Makefile for liblmdb (Lightning memory-mapped database library). - -######################################################################## -# Configuration. The compiler options must enable threaded compilation. -# -# Preprocessor macros (for CPPFLAGS) of interest... -# Note that the defaults should already be correct for most -# platforms; you should not need to change any of these. -# Read their descriptions in mdb.c if you do: -# -# - MDB_USE_POSIX_MUTEX, MDB_USE_POSIX_SEM, MDB_USE_SYSV_SEM -# - MDB_DSYNC -# - MDB_FDATASYNC -# - MDB_FDATASYNC_WORKS -# - MDB_USE_PWRITEV -# - MDB_USE_ROBUST -# -# There may be other macros in mdb.c of interest. You should -# read mdb.c before changing any of them. -# -CC = gcc -AR = ar -W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized -THREADS = -pthread -OPT = -O2 -g -CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS) -LDLIBS = # -lntdll # Windows needs ntdll -SOLIBS = # -lntdll -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin -libdir = $(exec_prefix)/lib -includedir = $(prefix)/include -datarootdir = $(prefix)/share -mandir = $(datarootdir)/man - -######################################################################## - -IHDRS = lmdb.h -ILIBS = liblmdb.a liblmdb.so -IPROGS = mdb_stat mdb_copy mdb_dump mdb_load -IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1 -PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5 -all: $(ILIBS) $(PROGS) - -install: $(ILIBS) $(IPROGS) $(IHDRS) - mkdir -p $(DESTDIR)$(bindir) - mkdir -p $(DESTDIR)$(libdir) - mkdir -p $(DESTDIR)$(includedir) - mkdir -p $(DESTDIR)$(mandir)/man1 - for f in $(IPROGS); do cp $$f $(DESTDIR)$(bindir); done - for f in $(ILIBS); do cp $$f $(DESTDIR)$(libdir); done - for f in $(IHDRS); do cp $$f $(DESTDIR)$(includedir); done - for f in $(IDOCS); do cp $$f $(DESTDIR)$(mandir)/man1; done - -clean: - rm -rf $(PROGS) *.[ao] *.[ls]o *~ testdb - -test: all - rm -rf testdb && mkdir testdb - ./mtest && ./mdb_stat testdb - -liblmdb.a: mdb.o midl.o - $(AR) rs $@ mdb.o midl.o - -liblmdb.so: mdb.lo midl.lo -# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS) - $(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS) - -mdb_stat: mdb_stat.o liblmdb.a -mdb_copy: mdb_copy.o liblmdb.a -mdb_dump: mdb_dump.o liblmdb.a -mdb_load: mdb_load.o liblmdb.a -mtest: mtest.o liblmdb.a -mtest2: mtest2.o liblmdb.a -mtest3: mtest3.o liblmdb.a -mtest4: mtest4.o liblmdb.a -mtest5: mtest5.o liblmdb.a -mtest6: mtest6.o liblmdb.a - -mdb.o: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c - -midl.o: midl.c midl.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c midl.c - -mdb.lo: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c mdb.c -o $@ - -midl.lo: midl.c midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -c midl.c -o $@ - -%: %.o - $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@ - -%.o: %.c lmdb.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< - -COV_FLAGS=-fprofile-arcs -ftest-coverage -COV_OBJS=xmdb.o xmidl.o - -coverage: xmtest - for i in mtest*.c [0-9]*.c; do j=`basename \$$i .c`; $(MAKE) $$j.o; \ - gcc -o x$$j $$j.o $(COV_OBJS) -pthread $(COV_FLAGS); \ - rm -rf testdb; mkdir testdb; ./x$$j; done - gcov xmdb.c - gcov xmidl.c - -xmtest: mtest.o xmdb.o xmidl.o - gcc -o xmtest mtest.o xmdb.o xmidl.o -pthread $(COV_FLAGS) - -xmdb.o: mdb.c lmdb.h midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c mdb.c -o $@ - -xmidl.o: midl.c midl.h - $(CC) $(CFLAGS) -fPIC $(CPPFLAGS) -O0 $(COV_FLAGS) -c midl.c -o $@ diff --git a/src/contrib/db/liblmdb/intro.doc b/src/contrib/db/liblmdb/intro.doc deleted file mode 100644 index 870c7bb..0000000 --- a/src/contrib/db/liblmdb/intro.doc +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -/** @page starting Getting Started - -LMDB is compact, fast, powerful, and robust and implements a simplified -variant of the BerkeleyDB (BDB) API. (BDB is also very powerful, and verbosely -documented in its own right.) After reading this page, the main -\ref mdb documentation should make sense. Thanks to Bert Hubert -for creating the - -initial version of this writeup. - -Everything starts with an environment, created by #mdb_env_create(). -Once created, this environment must also be opened with #mdb_env_open(). - -#mdb_env_open() gets passed a name which is interpreted as a directory -path. Note that this directory must exist already, it is not created -for you. Within that directory, a lock file and a storage file will be -generated. If you don't want to use a directory, you can pass the -#MDB_NOSUBDIR option, in which case the path you provided is used -directly as the data file, and another file with a "-lock" suffix -added will be used for the lock file. - -Once the environment is open, a transaction can be created within it -using #mdb_txn_begin(). Transactions may be read-write or read-only, -and read-write transactions may be nested. A transaction must only -be used by one thread at a time. Transactions are always required, -even for read-only access. The transaction provides a consistent -view of the data. - -Once a transaction has been created, a database can be opened within it -using #mdb_dbi_open(). If only one database will ever be used in the -environment, a NULL can be passed as the database name. For named -databases, the #MDB_CREATE flag must be used to create the database -if it doesn't already exist. Also, #mdb_env_set_maxdbs() must be -called after #mdb_env_create() and before #mdb_env_open() to set the -maximum number of named databases you want to support. - -Note: a single transaction can open multiple databases. Generally -databases should only be opened once, by the first transaction in -the process. After the first transaction completes, the database -handles can freely be used by all subsequent transactions. - -Within a transaction, #mdb_get() and #mdb_put() can store single -key/value pairs if that is all you need to do (but see \ref Cursors -below if you want to do more). - -A key/value pair is expressed as two #MDB_val structures. This struct -has two fields, \c mv_size and \c mv_data. The data is a \c void pointer to -an array of \c mv_size bytes. - -Because LMDB is very efficient (and usually zero-copy), the data returned -in an #MDB_val structure may be memory-mapped straight from disk. In -other words look but do not touch (or free() for that matter). -Once a transaction is closed, the values can no longer be used, so -make a copy if you need to keep them after that. - -@section Cursors Cursors - -To do more powerful things, we must use a cursor. - -Within the transaction, a cursor can be created with #mdb_cursor_open(). -With this cursor we can store/retrieve/delete (multiple) values using -#mdb_cursor_get(), #mdb_cursor_put(), and #mdb_cursor_del(). - -#mdb_cursor_get() positions itself depending on the cursor operation -requested, and for some operations, on the supplied key. For example, -to list all key/value pairs in a database, use operation #MDB_FIRST for -the first call to #mdb_cursor_get(), and #MDB_NEXT on subsequent calls, -until the end is hit. - -To retrieve all keys starting from a specified key value, use #MDB_SET. -For more cursor operations, see the \ref mdb docs. - -When using #mdb_cursor_put(), either the function will position the -cursor for you based on the \b key, or you can use operation -#MDB_CURRENT to use the current position of the cursor. Note that -\b key must then match the current position's key. - -@subsection summary Summarizing the Opening - -So we have a cursor in a transaction which opened a database in an -environment which is opened from a filesystem after it was -separately created. - -Or, we create an environment, open it from a filesystem, create a -transaction within it, open a database within that transaction, -and create a cursor within all of the above. - -Got it? - -@section thrproc Threads and Processes - -LMDB uses POSIX locks on files, and these locks have issues if one -process opens a file multiple times. Because of this, do not -#mdb_env_open() a file multiple times from a single process. Instead, -share the LMDB environment that has opened the file across all threads. -Otherwise, if a single process opens the same environment multiple times, -closing it once will remove all the locks held on it, and the other -instances will be vulnerable to corruption from other processes. - -Also note that a transaction is tied to one thread by default using -Thread Local Storage. If you want to pass read-only transactions across -threads, you can use the #MDB_NOTLS option on the environment. - -@section txns Transactions, Rollbacks, etc. - -To actually get anything done, a transaction must be committed using -#mdb_txn_commit(). Alternatively, all of a transaction's operations -can be discarded using #mdb_txn_abort(). In a read-only transaction, -any cursors will \b not automatically be freed. In a read-write -transaction, all cursors will be freed and must not be used again. - -For read-only transactions, obviously there is nothing to commit to -storage. The transaction still must eventually be aborted to close -any database handle(s) opened in it, or committed to keep the -database handles around for reuse in new transactions. - -In addition, as long as a transaction is open, a consistent view of -the database is kept alive, which requires storage. A read-only -transaction that no longer requires this consistent view should -be terminated (committed or aborted) when the view is no longer -needed (but see below for an optimization). - -There can be multiple simultaneously active read-only transactions -but only one that can write. Once a single read-write transaction -is opened, all further attempts to begin one will block until the -first one is committed or aborted. This has no effect on read-only -transactions, however, and they may continue to be opened at any time. - -@section dupkeys Duplicate Keys - -#mdb_get() and #mdb_put() respectively have no and only some support -for multiple key/value pairs with identical keys. If there are multiple -values for a key, #mdb_get() will only return the first value. - -When multiple values for one key are required, pass the #MDB_DUPSORT -flag to #mdb_dbi_open(). In an #MDB_DUPSORT database, by default -#mdb_put() will not replace the value for a key if the key existed -already. Instead it will add the new value to the key. In addition, -#mdb_del() will pay attention to the value field too, allowing for -specific values of a key to be deleted. - -Finally, additional cursor operations become available for -traversing through and retrieving duplicate values. - -@section optim Some Optimization - -If you frequently begin and abort read-only transactions, as an -optimization, it is possible to only reset and renew a transaction. - -#mdb_txn_reset() releases any old copies of data kept around for -a read-only transaction. To reuse this reset transaction, call -#mdb_txn_renew() on it. Any cursors in this transaction must also -be renewed using #mdb_cursor_renew(). - -Note that #mdb_txn_reset() is similar to #mdb_txn_abort() and will -close any databases you opened within the transaction. - -To permanently free a transaction, reset or not, use #mdb_txn_abort(). - -@section cleanup Cleaning Up - -For read-only transactions, any cursors created within it must -be closed using #mdb_cursor_close(). - -It is very rarely necessary to close a database handle, and in -general they should just be left open. - -@section onward The Full API - -The full \ref mdb documentation lists further details, like how to: - - \li size a database (the default limits are intentionally small) - \li drop and clean a database - \li detect and report errors - \li optimize (bulk) loading speed - \li (temporarily) reduce robustness to gain even more speed - \li gather statistics about the database - \li define custom sort orders - -*/ diff --git a/src/contrib/db/liblmdb/lmdb.h b/src/contrib/db/liblmdb/lmdb.h deleted file mode 100644 index 0bca3eb..0000000 --- a/src/contrib/db/liblmdb/lmdb.h +++ /dev/null @@ -1,1618 +0,0 @@ -/** @file lmdb.h - * @brief Lightning memory-mapped database library - * - * @mainpage Lightning Memory-Mapped Database Manager (LMDB) - * - * @section intro_sec Introduction - * LMDB is a Btree-based database management library modeled loosely on the - * BerkeleyDB API, but much simplified. The entire database is exposed - * in a memory map, and all data fetches return data directly - * from the mapped memory, so no malloc's or memcpy's occur during - * data fetches. As such, the library is extremely simple because it - * requires no page caching layer of its own, and it is extremely high - * performance and memory-efficient. It is also fully transactional with - * full ACID semantics, and when the memory map is read-only, the - * database integrity cannot be corrupted by stray pointer writes from - * application code. - * - * The library is fully thread-aware and supports concurrent read/write - * access from multiple processes and threads. Data pages use a copy-on- - * write strategy so no active data pages are ever overwritten, which - * also provides resistance to corruption and eliminates the need of any - * special recovery procedures after a system crash. Writes are fully - * serialized; only one write transaction may be active at a time, which - * guarantees that writers can never deadlock. The database structure is - * multi-versioned so readers run with no locks; writers cannot block - * readers, and readers don't block writers. - * - * Unlike other well-known database mechanisms which use either write-ahead - * transaction logs or append-only data writes, LMDB requires no maintenance - * during operation. Both write-ahead loggers and append-only databases - * require periodic checkpointing and/or compaction of their log or database - * files otherwise they grow without bound. LMDB tracks free pages within - * the database and re-uses them for new write operations, so the database - * size does not grow without bound in normal use. - * - * The memory map can be used as a read-only or read-write map. It is - * read-only by default as this provides total immunity to corruption. - * Using read-write mode offers much higher write performance, but adds - * the possibility for stray application writes thru pointers to silently - * corrupt the database. Of course if your application code is known to - * be bug-free (...) then this is not an issue. - * - * If this is your first time using a transactional embedded key/value - * store, you may find the \ref starting page to be helpful. - * - * @section caveats_sec Caveats - * Troubleshooting the lock file, plus semaphores on BSD systems: - * - * - A broken lockfile can cause sync issues. - * Stale reader transactions left behind by an aborted program - * cause further writes to grow the database quickly, and - * stale locks can block further operation. - * - * Fix: Check for stale readers periodically, using the - * #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool. - * Stale writers will be cleared automatically on most systems: - * - Windows - automatic - * - BSD, systems using SysV semaphores - automatic - * - Linux, systems using POSIX mutexes with Robust option - automatic - * Otherwise just make all programs using the database close it; - * the lockfile is always reset on first open of the environment. - * - * - On BSD systems or others configured with MDB_USE_SYSV_SEM or - * MDB_USE_POSIX_SEM, - * startup can fail due to semaphores owned by another userid. - * - * Fix: Open and close the database as the user which owns the - * semaphores (likely last user) or as root, while no other - * process is using the database. - * - * Restrictions/caveats (in addition to those listed for some functions): - * - * - Only the database owner should normally use the database on - * BSD systems or when otherwise configured with MDB_USE_POSIX_SEM. - * Multiple users can cause startup to fail later, as noted above. - * - * - There is normally no pure read-only mode, since readers need write - * access to locks and lock file. Exceptions: On read-only filesystems - * or with the #MDB_NOLOCK flag described under #mdb_env_open(). - * - * - An LMDB configuration will often reserve considerable \b unused - * memory address space and maybe file size for future growth. - * This does not use actual memory or disk space, but users may need - * to understand the difference so they won't be scared off. - * - * - By default, in versions before 0.9.10, unused portions of the data - * file might receive garbage data from memory freed by other code. - * (This does not happen when using the #MDB_WRITEMAP flag.) As of - * 0.9.10 the default behavior is to initialize such memory before - * writing to the data file. Since there may be a slight performance - * cost due to this initialization, applications may disable it using - * the #MDB_NOMEMINIT flag. Applications handling sensitive data - * which must not be written should not use this flag. This flag is - * irrelevant when using #MDB_WRITEMAP. - * - * - A thread can only use one transaction at a time, plus any child - * transactions. Each transaction belongs to one thread. See below. - * The #MDB_NOTLS flag changes this for read-only transactions. - * - * - Use an MDB_env* in the process which opened it, without fork()ing. - * - * - Do not have open an LMDB database twice in the same process at - * the same time. Not even from a plain open() call - close()ing it - * breaks flock() advisory locking. - * - * - Avoid long-lived transactions. Read transactions prevent - * reuse of pages freed by newer write transactions, thus the - * database can grow quickly. Write transactions prevent - * other write transactions, since writes are serialized. - * - * - Avoid suspending a process with active transactions. These - * would then be "long-lived" as above. Also read transactions - * suspended when writers commit could sometimes see wrong data. - * - * ...when several processes can use a database concurrently: - * - * - Avoid aborting a process with an active transaction. - * The transaction becomes "long-lived" as above until a check - * for stale readers is performed or the lockfile is reset, - * since the process may not remove it from the lockfile. - * - * This does not apply to write transactions if the system clears - * stale writers, see above. - * - * - If you do that anyway, do a periodic check for stale readers. Or - * close the environment once in a while, so the lockfile can get reset. - * - * - Do not use LMDB databases on remote filesystems, even between - * processes on the same host. This breaks flock() on some OSes, - * possibly memory map sync, and certainly sync between programs - * on different hosts. - * - * - Opening a database can fail if another process is opening or - * closing it at exactly the same time. - * - * @author Howard Chu, Symas Corporation. - * - * @copyright Copyright 2011-2016 Howard Chu, Symas Corp. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - * - * @par Derived From: - * This code is derived from btree.c written by Martin Hedenfalk. - * - * Copyright (c) 2009, 2010 Martin Hedenfalk - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef _LMDB_H_ -#define _LMDB_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Unix permissions for creating files, or dummy definition for Windows */ -#ifdef _MSC_VER -typedef int mdb_mode_t; -#else -typedef mode_t mdb_mode_t; -#endif - -#ifdef MDB_VL32 -typedef uint64_t mdb_size_t; -#define mdb_env_create mdb_env_create_vl32 /**< Prevent mixing with non-VL32 builds */ -#else -typedef size_t mdb_size_t; -#endif - -/** An abstraction for a file handle. - * On POSIX systems file handles are small integers. On Windows - * they're opaque pointers. - */ -#ifdef _WIN32 -typedef void *mdb_filehandle_t; -#else -typedef int mdb_filehandle_t; -#endif - -/** @defgroup mdb LMDB API - * @{ - * @brief OpenLDAP Lightning Memory-Mapped Database Manager - */ -/** @defgroup Version Version Macros - * @{ - */ -/** Library major version */ -#define MDB_VERSION_MAJOR 0 -/** Library minor version */ -#define MDB_VERSION_MINOR 9 -/** Library patch version */ -#define MDB_VERSION_PATCH 70 - -/** Combine args a,b,c into a single integer for easy version comparisons */ -#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c)) - -/** The full library version as a single integer */ -#define MDB_VERSION_FULL \ - MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH) - -/** The release date of this library version */ -#define MDB_VERSION_DATE "December 19, 2015" - -/** A stringifier for the version info */ -#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")" - -/** A helper for the stringifier macro */ -#define MDB_VERFOO(a,b,c,d) MDB_VERSTR(a,b,c,d) - -/** The full library version as a C string */ -#define MDB_VERSION_STRING \ - MDB_VERFOO(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH,MDB_VERSION_DATE) -/** @} */ - -/** @brief Opaque structure for a database environment. - * - * A DB environment supports multiple databases, all residing in the same - * shared-memory map. - */ -typedef struct MDB_env MDB_env; - -/** @brief Opaque structure for a transaction handle. - * - * All database operations require a transaction handle. Transactions may be - * read-only or read-write. - */ -typedef struct MDB_txn MDB_txn; - -/** @brief A handle for an individual database in the DB environment. */ -typedef unsigned int MDB_dbi; - -/** @brief Opaque structure for navigating through a database */ -typedef struct MDB_cursor MDB_cursor; - -/** @brief Generic structure used for passing keys and data in and out - * of the database. - * - * Values returned from the database are valid only until a subsequent - * update operation, or the end of the transaction. Do not modify or - * free them, they commonly point into the database itself. - * - * Key sizes must be between 1 and #mdb_env_get_maxkeysize() inclusive. - * The same applies to data sizes in databases with the #MDB_DUPSORT flag. - * Other data items can in theory be from 0 to 0xffffffff bytes long. - */ -typedef struct MDB_val { - size_t mv_size; /**< size of the data item */ - void *mv_data; /**< address of the data item */ -} MDB_val; - -/** @brief A callback function used to compare two keys in a database */ -typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b); - -/** @brief A callback function used to relocate a position-dependent data item - * in a fixed-address database. - * - * The \b newptr gives the item's desired address in - * the memory map, and \b oldptr gives its previous address. The item's actual - * data resides at the address in \b item. This callback is expected to walk - * through the fields of the record in \b item and modify any - * values based at the \b oldptr address to be relative to the \b newptr address. - * @param[in,out] item The item that is to be relocated. - * @param[in] oldptr The previous address. - * @param[in] newptr The new address to relocate to. - * @param[in] relctx An application-provided context, set by #mdb_set_relctx(). - * @todo This feature is currently unimplemented. - */ -typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx); - -/** @defgroup mdb_env Environment Flags - * @{ - */ - /** mmap at a fixed address (experimental) */ -#define MDB_FIXEDMAP 0x01 - /** no environment directory */ -#define MDB_NOSUBDIR 0x4000 - /** don't fsync after commit */ -#define MDB_NOSYNC 0x10000 - /** read only */ -#define MDB_RDONLY 0x20000 - /** don't fsync metapage after commit */ -#define MDB_NOMETASYNC 0x40000 - /** use writable mmap */ -#define MDB_WRITEMAP 0x80000 - /** use asynchronous msync when #MDB_WRITEMAP is used */ -#define MDB_MAPASYNC 0x100000 - /** tie reader locktable slots to #MDB_txn objects instead of to threads */ -#define MDB_NOTLS 0x200000 - /** don't do any locking, caller must manage their own locks */ -#define MDB_NOLOCK 0x400000 - /** don't do readahead (no effect on Windows) */ -#define MDB_NORDAHEAD 0x800000 - /** don't initialize malloc'd memory before writing to datafile */ -#define MDB_NOMEMINIT 0x1000000 - /** use the previous snapshot rather than the latest one */ -#define MDB_PREVSNAPSHOT 0x2000000 -/** @} */ - -/** @defgroup mdb_dbi_open Database Flags - * @{ - */ - /** use reverse string keys */ -#define MDB_REVERSEKEY 0x02 - /** use sorted duplicates */ -#define MDB_DUPSORT 0x04 - /** numeric keys in native byte order: either unsigned int or size_t. - * The keys must all be of the same size. */ -#define MDB_INTEGERKEY 0x08 - /** with #MDB_DUPSORT, sorted dup items have fixed size */ -#define MDB_DUPFIXED 0x10 - /** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */ -#define MDB_INTEGERDUP 0x20 - /** with #MDB_DUPSORT, use reverse string dups */ -#define MDB_REVERSEDUP 0x40 - /** create DB if not already existing */ -#define MDB_CREATE 0x40000 -/** @} */ - -/** @defgroup mdb_put Write Flags - * @{ - */ -/** For put: Don't write if the key already exists. */ -#define MDB_NOOVERWRITE 0x10 -/** Only for #MDB_DUPSORT
- * For put: don't write if the key and data pair already exist.
- * For mdb_cursor_del: remove all duplicate data items. - */ -#define MDB_NODUPDATA 0x20 -/** For mdb_cursor_put: overwrite the current key/data pair */ -#define MDB_CURRENT 0x40 -/** For put: Just reserve space for data, don't copy it. Return a - * pointer to the reserved space. - */ -#define MDB_RESERVE 0x10000 -/** Data is being appended, don't split full pages. */ -#define MDB_APPEND 0x20000 -/** Duplicate data is being appended, don't split full pages. */ -#define MDB_APPENDDUP 0x40000 -/** Store multiple data items in one call. Only for #MDB_DUPFIXED. */ -#define MDB_MULTIPLE 0x80000 -/* @} */ - -/** @defgroup mdb_copy Copy Flags - * @{ - */ -/** Compacting copy: Omit free space from copy, and renumber all - * pages sequentially. - */ -#define MDB_CP_COMPACT 0x01 -/* @} */ - -/** @brief Cursor Get operations. - * - * This is the set of all operations for retrieving data - * using a cursor. - */ -typedef enum MDB_cursor_op { - MDB_FIRST, /**< Position at first key/data item */ - MDB_FIRST_DUP, /**< Position at first data item of current key. - Only for #MDB_DUPSORT */ - MDB_GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */ - MDB_GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */ - MDB_GET_CURRENT, /**< Return key/data at current cursor position */ - MDB_GET_MULTIPLE, /**< Return key and up to a page of duplicate data items - from current cursor position. Move cursor to prepare - for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ - MDB_LAST, /**< Position at last key/data item */ - MDB_LAST_DUP, /**< Position at last data item of current key. - Only for #MDB_DUPSORT */ - MDB_NEXT, /**< Position at next data item */ - MDB_NEXT_DUP, /**< Position at next data item of current key. - Only for #MDB_DUPSORT */ - MDB_NEXT_MULTIPLE, /**< Return key and up to a page of duplicate data items - from next cursor position. Move cursor to prepare - for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ - MDB_NEXT_NODUP, /**< Position at first data item of next key */ - MDB_PREV, /**< Position at previous data item */ - MDB_PREV_DUP, /**< Position at previous data item of current key. - Only for #MDB_DUPSORT */ - MDB_PREV_NODUP, /**< Position at last data item of previous key */ - MDB_SET, /**< Position at specified key */ - MDB_SET_KEY, /**< Position at specified key, return key + data */ - MDB_SET_RANGE, /**< Position at first key greater than or equal to specified key. */ - MDB_PREV_MULTIPLE /**< Position at previous page and return key and up to - a page of duplicate data items. Only for #MDB_DUPFIXED */ -} MDB_cursor_op; - -/** @defgroup errors Return Codes - * - * BerkeleyDB uses -30800 to -30999, we'll go under them - * @{ - */ - /** Successful result */ -#define MDB_SUCCESS 0 - /** key/data pair already exists */ -#define MDB_KEYEXIST (-30799) - /** key/data pair not found (EOF) */ -#define MDB_NOTFOUND (-30798) - /** Requested page not found - this usually indicates corruption */ -#define MDB_PAGE_NOTFOUND (-30797) - /** Located page was wrong type */ -#define MDB_CORRUPTED (-30796) - /** Update of meta page failed or environment had fatal error */ -#define MDB_PANIC (-30795) - /** Environment version mismatch */ -#define MDB_VERSION_MISMATCH (-30794) - /** File is not a valid LMDB file */ -#define MDB_INVALID (-30793) - /** Environment mapsize reached */ -#define MDB_MAP_FULL (-30792) - /** Environment maxdbs reached */ -#define MDB_DBS_FULL (-30791) - /** Environment maxreaders reached */ -#define MDB_READERS_FULL (-30790) - /** Too many TLS keys in use - Windows only */ -#define MDB_TLS_FULL (-30789) - /** Txn has too many dirty pages */ -#define MDB_TXN_FULL (-30788) - /** Cursor stack too deep - internal error */ -#define MDB_CURSOR_FULL (-30787) - /** Page has not enough space - internal error */ -#define MDB_PAGE_FULL (-30786) - /** Database contents grew beyond environment mapsize */ -#define MDB_MAP_RESIZED (-30785) - /** Operation and DB incompatible, or DB type changed. This can mean: - *
    - *
  • The operation expects an #MDB_DUPSORT / #MDB_DUPFIXED database. - *
  • Opening a named DB when the unnamed DB has #MDB_DUPSORT / #MDB_INTEGERKEY. - *
  • Accessing a data record as a database, or vice versa. - *
  • The database was dropped and recreated with different flags. - *
- */ -#define MDB_INCOMPATIBLE (-30784) - /** Invalid reuse of reader locktable slot */ -#define MDB_BAD_RSLOT (-30783) - /** Transaction must abort, has a child, or is invalid */ -#define MDB_BAD_TXN (-30782) - /** Unsupported size of key/DB name/data, or wrong DUPFIXED size */ -#define MDB_BAD_VALSIZE (-30781) - /** The specified DBI was changed unexpectedly */ -#define MDB_BAD_DBI (-30780) - /** The last defined error code */ -#define MDB_LAST_ERRCODE MDB_BAD_DBI -/** @} */ - -/** @brief Statistics for a database in the environment */ -typedef struct MDB_stat { - unsigned int ms_psize; /**< Size of a database page. - This is currently the same for all databases. */ - unsigned int ms_depth; /**< Depth (height) of the B-tree */ - mdb_size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */ - mdb_size_t ms_leaf_pages; /**< Number of leaf pages */ - mdb_size_t ms_overflow_pages; /**< Number of overflow pages */ - mdb_size_t ms_entries; /**< Number of data items */ -} MDB_stat; - -/** @brief Information about the environment */ -typedef struct MDB_envinfo { - void *me_mapaddr; /**< Address of map, if fixed */ - mdb_size_t me_mapsize; /**< Size of the data memory map */ - mdb_size_t me_last_pgno; /**< ID of the last used page */ - mdb_size_t me_last_txnid; /**< ID of the last committed transaction */ - unsigned int me_maxreaders; /**< max reader slots in the environment */ - unsigned int me_numreaders; /**< max reader slots used in the environment */ -} MDB_envinfo; - - /** @brief Return the LMDB library version information. - * - * @param[out] major if non-NULL, the library major version number is copied here - * @param[out] minor if non-NULL, the library minor version number is copied here - * @param[out] patch if non-NULL, the library patch version number is copied here - * @retval "version string" The library version as a string - */ -char *mdb_version(int *major, int *minor, int *patch); - - /** @brief Return a string describing a given error code. - * - * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3) - * function. If the error code is greater than or equal to 0, then the string - * returned by the system function strerror(3) is returned. If the error code - * is less than 0, an error string corresponding to the LMDB library error is - * returned. See @ref errors for a list of LMDB-specific error codes. - * @param[in] err The error code - * @retval "error message" The description of the error - */ -char *mdb_strerror(int err); - - /** @brief Create an LMDB environment handle. - * - * This function allocates memory for a #MDB_env structure. To release - * the allocated memory and discard the handle, call #mdb_env_close(). - * Before the handle may be used, it must be opened using #mdb_env_open(). - * Various other options may also need to be set before opening the handle, - * e.g. #mdb_env_set_mapsize(), #mdb_env_set_maxreaders(), #mdb_env_set_maxdbs(), - * depending on usage requirements. - * @param[out] env The address where the new handle will be stored - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_create(MDB_env **env); - - /** @brief Open an environment handle. - * - * If this function fails, #mdb_env_close() must be called to discard the #MDB_env handle. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] path The directory in which the database files reside. This - * directory must already exist and be writable. - * @param[in] flags Special options for this environment. This parameter - * must be set to 0 or by bitwise OR'ing together one or more of the - * values described here. - * Flags set by mdb_env_set_flags() are also used. - *
    - *
  • #MDB_FIXEDMAP - * use a fixed address for the mmap region. This flag must be specified - * when creating the environment, and is stored persistently in the environment. - * If successful, the memory map will always reside at the same virtual address - * and pointers used to reference data items in the database will be constant - * across multiple invocations. This option may not always work, depending on - * how the operating system has allocated memory to shared libraries and other uses. - * The feature is highly experimental. - *
  • #MDB_NOSUBDIR - * By default, LMDB creates its environment in a directory whose - * pathname is given in \b path, and creates its data and lock files - * under that directory. With this option, \b path is used as-is for - * the database main data file. The database lock file is the \b path - * with "-lock" appended. - *
  • #MDB_RDONLY - * Open the environment in read-only mode. No write operations will be - * allowed. LMDB will still modify the lock file - except on read-only - * filesystems, where LMDB does not use locks. - *
  • #MDB_WRITEMAP - * Use a writeable memory map unless MDB_RDONLY is set. This uses - * fewer mallocs but loses protection from application bugs - * like wild pointer writes and other bad updates into the database. - * This may be slightly faster for DBs that fit entirely in RAM, but - * is slower for DBs larger than RAM. - * Incompatible with nested transactions. - * Do not mix processes with and without MDB_WRITEMAP on the same - * environment. This can defeat durability (#mdb_env_sync etc). - *
  • #MDB_NOMETASYNC - * Flush system buffers to disk only once per transaction, omit the - * metadata flush. Defer that until the system flushes files to disk, - * or next non-MDB_RDONLY commit or #mdb_env_sync(). This optimization - * maintains database integrity, but a system crash may undo the last - * committed transaction. I.e. it preserves the ACI (atomicity, - * consistency, isolation) but not D (durability) database property. - * This flag may be changed at any time using #mdb_env_set_flags(). - *
  • #MDB_NOSYNC - * Don't flush system buffers to disk when committing a transaction. - * This optimization means a system crash can corrupt the database or - * lose the last transactions if buffers are not yet flushed to disk. - * The risk is governed by how often the system flushes dirty buffers - * to disk and how often #mdb_env_sync() is called. However, if the - * filesystem preserves write order and the #MDB_WRITEMAP flag is not - * used, transactions exhibit ACI (atomicity, consistency, isolation) - * properties and only lose D (durability). I.e. database integrity - * is maintained, but a system crash may undo the final transactions. - * Note that (#MDB_NOSYNC | #MDB_WRITEMAP) leaves the system with no - * hint for when to write transactions to disk, unless #mdb_env_sync() - * is called. (#MDB_MAPASYNC | #MDB_WRITEMAP) may be preferable. - * This flag may be changed at any time using #mdb_env_set_flags(). - *
  • #MDB_MAPASYNC - * When using #MDB_WRITEMAP, use asynchronous flushes to disk. - * As with #MDB_NOSYNC, a system crash can then corrupt the - * database or lose the last transactions. Calling #mdb_env_sync() - * ensures on-disk database integrity until next commit. - * This flag may be changed at any time using #mdb_env_set_flags(). - *
  • #MDB_NOTLS - * Don't use Thread-Local Storage. Tie reader locktable slots to - * #MDB_txn objects instead of to threads. I.e. #mdb_txn_reset() keeps - * the slot reseved for the #MDB_txn object. A thread may use parallel - * read-only transactions. A read-only transaction may span threads if - * the user synchronizes its use. Applications that multiplex many - * user threads over individual OS threads need this option. Such an - * application must also serialize the write transactions in an OS - * thread, since LMDB's write locking is unaware of the user threads. - *
  • #MDB_NOLOCK - * Don't do any locking. If concurrent access is anticipated, the - * caller must manage all concurrency itself. For proper operation - * the caller must enforce single-writer semantics, and must ensure - * that no readers are using old transactions while a writer is - * active. The simplest approach is to use an exclusive lock so that - * no readers may be active at all when a writer begins. - *
  • #MDB_NORDAHEAD - * Turn off readahead. Most operating systems perform readahead on - * read requests by default. This option turns it off if the OS - * supports it. Turning it off may help random read performance - * when the DB is larger than RAM and system RAM is full. - * The option is not implemented on Windows. - *
  • #MDB_NOMEMINIT - * Don't initialize malloc'd memory before writing to unused spaces - * in the data file. By default, memory for pages written to the data - * file is obtained using malloc. While these pages may be reused in - * subsequent transactions, freshly malloc'd pages will be initialized - * to zeroes before use. This avoids persisting leftover data from other - * code (that used the heap and subsequently freed the memory) into the - * data file. Note that many other system libraries may allocate - * and free memory from the heap for arbitrary uses. E.g., stdio may - * use the heap for file I/O buffers. This initialization step has a - * modest performance cost so some applications may want to disable - * it using this flag. This option can be a problem for applications - * which handle sensitive data like passwords, and it makes memory - * checkers like Valgrind noisy. This flag is not needed with #MDB_WRITEMAP, - * which writes directly to the mmap instead of using malloc for pages. The - * initialization is also skipped if #MDB_RESERVE is used; the - * caller is expected to overwrite all of the memory that was - * reserved in that case. - * This flag may be changed at any time using #mdb_env_set_flags(). - *
  • #MDB_PREVSNAPSHOT - * Open the environment with the previous snapshot rather than the latest - * one. This loses the latest transaction, but may help work around some - * types of corruption. If opened with write access, this must be the - * only process using the environment. This flag is automatically reset - * after a write transaction is successfully committed. - *
- * @param[in] mode The UNIX permissions to set on created files and semaphores. - * This parameter is ignored on Windows. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_VERSION_MISMATCH - the version of the LMDB library doesn't match the - * version that created the database environment. - *
  • #MDB_INVALID - the environment file headers are corrupted. - *
  • ENOENT - the directory specified by the path parameter doesn't exist. - *
  • EACCES - the user didn't have permission to access the environment files. - *
  • EAGAIN - the environment was locked by another process. - *
- */ -int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode); - - /** @brief Copy an LMDB environment to the specified path. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. - * @note This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under @ref caveats_sec. - * @param[in] env An environment handle returned by #mdb_env_create(). It - * must have already been opened successfully. - * @param[in] path The directory in which the copy will reside. This - * directory must already exist and be writable but must otherwise be - * empty. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_copy(MDB_env *env, const char *path); - - /** @brief Copy an LMDB environment to the specified file descriptor. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. - * @note This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under @ref caveats_sec. - * @param[in] env An environment handle returned by #mdb_env_create(). It - * must have already been opened successfully. - * @param[in] fd The filedescriptor to write the copy to. It must - * have already been opened for Write access. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd); - - /** @brief Copy an LMDB environment to the specified path, with options. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. - * @note This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under @ref caveats_sec. - * @param[in] env An environment handle returned by #mdb_env_create(). It - * must have already been opened successfully. - * @param[in] path The directory in which the copy will reside. This - * directory must already exist and be writable but must otherwise be - * empty. - * @param[in] flags Special options for this operation. This parameter - * must be set to 0 or by bitwise OR'ing together one or more of the - * values described here. - *
    - *
  • #MDB_CP_COMPACT - Perform compaction while copying: omit free - * pages and sequentially renumber all pages in output. This option - * consumes more CPU and runs more slowly than the default. - *
- * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags); - - /** @brief Copy an LMDB environment to the specified file descriptor, - * with options. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. See - * #mdb_env_copy2() for further details. - * @note This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under @ref caveats_sec. - * @param[in] env An environment handle returned by #mdb_env_create(). It - * must have already been opened successfully. - * @param[in] fd The filedescriptor to write the copy to. It must - * have already been opened for Write access. - * @param[in] flags Special options for this operation. - * See #mdb_env_copy2() for options. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned int flags); - - /** @brief Return statistics about the LMDB environment. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] stat The address of an #MDB_stat structure - * where the statistics will be copied - */ -int mdb_env_stat(MDB_env *env, MDB_stat *stat); - - /** @brief Return information about the LMDB environment. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] stat The address of an #MDB_envinfo structure - * where the information will be copied - */ -int mdb_env_info(MDB_env *env, MDB_envinfo *stat); - - /** @brief Flush the data buffers to disk. - * - * Data is always written to disk when #mdb_txn_commit() is called, - * but the operating system may keep it buffered. LMDB always flushes - * the OS buffers upon commit as well, unless the environment was - * opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC. This call is - * not valid if the environment was opened with #MDB_RDONLY. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] force If non-zero, force a synchronous flush. Otherwise - * if the environment has the #MDB_NOSYNC flag set the flushes - * will be omitted, and with #MDB_MAPASYNC they will be asynchronous. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EACCES - the environment is read-only. - *
  • EINVAL - an invalid parameter was specified. - *
  • EIO - an error occurred during synchronization. - *
- */ -int mdb_env_sync(MDB_env *env, int force); - - /** @brief Close the environment and release the memory map. - * - * Only a single thread may call this function. All transactions, databases, - * and cursors must already be closed before calling this function. Attempts to - * use any such handles after calling this function will cause a SIGSEGV. - * The environment handle will be freed and must not be used again after this call. - * @param[in] env An environment handle returned by #mdb_env_create() - */ -void mdb_env_close(MDB_env *env); - - /** @brief Set environment flags. - * - * This may be used to set some flags in addition to those from - * #mdb_env_open(), or to unset these flags. If several threads - * change the flags at the same time, the result is undefined. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] flags The flags to change, bitwise OR'ed together - * @param[in] onoff A non-zero value sets the flags, zero clears them. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_env_set_flags(MDB_env *env, unsigned int flags, int onoff); - - /** @brief Get environment flags. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] flags The address of an integer to store the flags - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_env_get_flags(MDB_env *env, unsigned int *flags); - - /** @brief Return the path that was used in #mdb_env_open(). - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] path Address of a string pointer to contain the path. This - * is the actual string in the environment, not a copy. It should not be - * altered in any way. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_env_get_path(MDB_env *env, const char **path); - - /** @brief Return the filedescriptor for the given environment. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] fd Address of a mdb_filehandle_t to contain the descriptor. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd); - - /** @brief Set the size of the memory map to use for this environment. - * - * The size should be a multiple of the OS page size. The default is - * 10485760 bytes. The size of the memory map is also the maximum size - * of the database. The value should be chosen as large as possible, - * to accommodate future growth of the database. - * This function should be called after #mdb_env_create() and before #mdb_env_open(). - * It may be called at later times if no transactions are active in - * this process. Note that the library does not check for this condition, - * the caller must ensure it explicitly. - * - * The new size takes effect immediately for the current process but - * will not be persisted to any others until a write transaction has been - * committed by the current process. Also, only mapsize increases are - * persisted into the environment. - * - * If the mapsize is increased by another process, and data has grown - * beyond the range of the current mapsize, #mdb_txn_begin() will - * return #MDB_MAP_RESIZED. This function may be called with a size - * of zero to adopt the new size. - * - * Any attempt to set a size smaller than the space already consumed - * by the environment will be silently changed to the current size of the used space. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] size The size in bytes - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified, or the environment has - * an active write transaction. - *
- */ -int mdb_env_set_mapsize(MDB_env *env, mdb_size_t size); - - /** @brief Set the maximum number of threads/reader slots for the environment. - * - * This defines the number of slots in the lock table that is used to track readers in the - * the environment. The default is 126. - * Starting a read-only transaction normally ties a lock table slot to the - * current thread until the environment closes or the thread exits. If - * MDB_NOTLS is in use, #mdb_txn_begin() instead ties the slot to the - * MDB_txn object until it or the #MDB_env object is destroyed. - * This function may only be called after #mdb_env_create() and before #mdb_env_open(). - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] readers The maximum number of reader lock table slots - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified, or the environment is already open. - *
- */ -int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers); - - /** @brief Get the maximum number of threads/reader slots for the environment. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] readers Address of an integer to store the number of readers - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers); - - /** @brief Set the maximum number of named databases for the environment. - * - * This function is only needed if multiple databases will be used in the - * environment. Simpler applications that use the environment as a single - * unnamed database can ignore this option. - * This function may only be called after #mdb_env_create() and before #mdb_env_open(). - * - * Currently a moderate number of slots are cheap but a huge number gets - * expensive: 7-120 words per transaction, and every #mdb_dbi_open() - * does a linear search of the opened slots. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] dbs The maximum number of databases - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified, or the environment is already open. - *
- */ -int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs); - - /** @brief Get the maximum size of keys and #MDB_DUPSORT data we can write. - * - * Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511. - * See @ref MDB_val. - * @param[in] env An environment handle returned by #mdb_env_create() - * @return The maximum size of a key we can write - */ -int mdb_env_get_maxkeysize(MDB_env *env); - - /** @brief Set application information associated with the #MDB_env. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] ctx An arbitrary pointer for whatever the application needs. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_set_userctx(MDB_env *env, void *ctx); - - /** @brief Get the application information associated with the #MDB_env. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @return The pointer set by #mdb_env_set_userctx(). - */ -void *mdb_env_get_userctx(MDB_env *env); - - /** @brief A callback function for most LMDB assert() failures, - * called before printing the message and aborting. - * - * @param[in] env An environment handle returned by #mdb_env_create(). - * @param[in] msg The assertion message, not including newline. - */ -typedef void MDB_assert_func(MDB_env *env, const char *msg); - - /** Set or reset the assert() callback of the environment. - * Disabled if liblmdb is buillt with NDEBUG. - * @note This hack should become obsolete as lmdb's error handling matures. - * @param[in] env An environment handle returned by #mdb_env_create(). - * @param[in] func An #MDB_assert_func function, or 0. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func); - - /** @brief Create a transaction for use with the environment. - * - * The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit(). - * @note A transaction and its cursors must only be used by a single - * thread, and a thread may only have a single transaction at a time. - * If #MDB_NOTLS is in use, this does not apply to read-only transactions. - * @note Cursors may not span transactions. - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] parent If this parameter is non-NULL, the new transaction - * will be a nested transaction, with the transaction indicated by \b parent - * as its parent. Transactions may be nested to any level. A parent - * transaction and its cursors may not issue any other operations than - * mdb_txn_commit and mdb_txn_abort while it has active child transactions. - * @param[in] flags Special options for this transaction. This parameter - * must be set to 0 or by bitwise OR'ing together one or more of the - * values described here. - *
    - *
  • #MDB_RDONLY - * This transaction will not perform any write operations. - *
  • #MDB_NOSYNC - * Don't flush system buffers to disk when committing this transaction. - *
  • #MDB_NOMETASYNC - * Flush system buffers but omit metadata flush when committing this transaction. - *
- * @param[out] txn Address where the new #MDB_txn handle will be stored - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_PANIC - a fatal error occurred earlier and the environment - * must be shut down. - *
  • #MDB_MAP_RESIZED - another process wrote data beyond this MDB_env's - * mapsize and this environment's map must be resized as well. - * See #mdb_env_set_mapsize(). - *
  • #MDB_READERS_FULL - a read-only transaction was requested and - * the reader lock table is full. See #mdb_env_set_maxreaders(). - *
  • ENOMEM - out of memory. - *
- */ -int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn); - - /** @brief Returns the transaction's #MDB_env - * - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - */ -MDB_env *mdb_txn_env(MDB_txn *txn); - - /** @brief Return the transaction's ID. - * - * This returns the identifier associated with this transaction. For a - * read-only transaction, this corresponds to the snapshot being read; - * concurrent readers will frequently have the same transaction ID. - * - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @return A transaction ID, valid if input is an active transaction. - */ -mdb_size_t mdb_txn_id(MDB_txn *txn); - - /** @brief Commit all the operations of a transaction into the database. - * - * The transaction handle is freed. It and its cursors must not be used - * again after this call, except with #mdb_cursor_renew(). - * @note Earlier documentation incorrectly said all cursors would be freed. - * Only write-transactions free cursors. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
  • ENOSPC - no more disk space. - *
  • EIO - a low-level I/O error occurred while writing. - *
  • ENOMEM - out of memory. - *
- */ -int mdb_txn_commit(MDB_txn *txn); - - /** @brief Abandon all the operations of the transaction instead of saving them. - * - * The transaction handle is freed. It and its cursors must not be used - * again after this call, except with #mdb_cursor_renew(). - * @note Earlier documentation incorrectly said all cursors would be freed. - * Only write-transactions free cursors. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - */ -void mdb_txn_abort(MDB_txn *txn); - - /** @brief Reset a read-only transaction. - * - * Abort the transaction like #mdb_txn_abort(), but keep the transaction - * handle. #mdb_txn_renew() may reuse the handle. This saves allocation - * overhead if the process will start a new read-only transaction soon, - * and also locking overhead if #MDB_NOTLS is in use. The reader table - * lock is released, but the table slot stays tied to its thread or - * #MDB_txn. Use mdb_txn_abort() to discard a reset handle, and to free - * its lock table slot if MDB_NOTLS is in use. - * Cursors opened within the transaction must not be used - * again after this call, except with #mdb_cursor_renew(). - * Reader locks generally don't interfere with writers, but they keep old - * versions of database pages allocated. Thus they prevent the old pages - * from being reused when writers commit new data, and so under heavy load - * the database size may grow much more rapidly than otherwise. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - */ -void mdb_txn_reset(MDB_txn *txn); - - /** @brief Renew a read-only transaction. - * - * This acquires a new reader lock for a transaction handle that had been - * released by #mdb_txn_reset(). It must be called before a reset transaction - * may be used again. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_PANIC - a fatal error occurred earlier and the environment - * must be shut down. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_txn_renew(MDB_txn *txn); - -/** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */ -#define mdb_open(txn,name,flags,dbi) mdb_dbi_open(txn,name,flags,dbi) -/** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */ -#define mdb_close(env,dbi) mdb_dbi_close(env,dbi) - - /** @brief Open a database in the environment. - * - * A database handle denotes the name and parameters of a database, - * independently of whether such a database exists. - * The database handle may be discarded by calling #mdb_dbi_close(). - * The old database handle is returned if the database was already open. - * The handle may only be closed once. - * - * The database handle will be private to the current transaction until - * the transaction is successfully committed. If the transaction is - * aborted the handle will be closed automatically. - * After a successful commit the handle will reside in the shared - * environment, and may be used by other transactions. - * - * This function must not be called from multiple concurrent - * transactions in the same process. A transaction that uses - * this function must finish (either commit or abort) before - * any other transaction in the process may use this function. - * - * To use named databases (with name != NULL), #mdb_env_set_maxdbs() - * must be called before opening the environment. Database names are - * keys in the unnamed database, and may be read but not written. - * - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] name The name of the database to open. If only a single - * database is needed in the environment, this value may be NULL. - * @param[in] flags Special options for this database. This parameter - * must be set to 0 or by bitwise OR'ing together one or more of the - * values described here. - *
    - *
  • #MDB_REVERSEKEY - * Keys are strings to be compared in reverse order, from the end - * of the strings to the beginning. By default, Keys are treated as strings and - * compared from beginning to end. - *
  • #MDB_DUPSORT - * Duplicate keys may be used in the database. (Or, from another perspective, - * keys may have multiple data items, stored in sorted order.) By default - * keys must be unique and may have only a single data item. - *
  • #MDB_INTEGERKEY - * Keys are binary integers in native byte order, either unsigned int - * or size_t, and will be sorted as such. - * The keys must all be of the same size. - *
  • #MDB_DUPFIXED - * This flag may only be used in combination with #MDB_DUPSORT. This option - * tells the library that the data items for this database are all the same - * size, which allows further optimizations in storage and retrieval. When - * all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE - * cursor operations may be used to retrieve multiple items at once. - *
  • #MDB_INTEGERDUP - * This option specifies that duplicate data items are binary integers, - * similar to #MDB_INTEGERKEY keys. - *
  • #MDB_REVERSEDUP - * This option specifies that duplicate data items should be compared as - * strings in reverse order. - *
  • #MDB_CREATE - * Create the named database if it doesn't exist. This option is not - * allowed in a read-only transaction or a read-only environment. - *
- * @param[out] dbi Address where the new #MDB_dbi handle will be stored - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_NOTFOUND - the specified database doesn't exist in the environment - * and #MDB_CREATE was not specified. - *
  • #MDB_DBS_FULL - too many databases have been opened. See #mdb_env_set_maxdbs(). - *
- */ -int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi); - - /** @brief Retrieve statistics for a database. - * - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[out] stat The address of an #MDB_stat structure - * where the statistics will be copied - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat); - - /** @brief Retrieve the DB flags for a database handle. - * - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[out] flags Address where the flags will be returned. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags); - - /** @brief Close a database handle. Normally unnecessary. Use with care: - * - * This call is not mutex protected. Handles should only be closed by - * a single thread, and only if no other threads are going to reference - * the database handle or one of its cursors any further. Do not close - * a handle if an existing transaction has modified its database. - * Doing so can cause misbehavior from database corruption to errors - * like MDB_BAD_VALSIZE (since the DB name is gone). - * - * Closing a database handle is not necessary, but lets #mdb_dbi_open() - * reuse the handle value. Usually it's better to set a bigger - * #mdb_env_set_maxdbs(), unless that value would be large. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - */ -void mdb_dbi_close(MDB_env *env, MDB_dbi dbi); - - /** @brief Empty or delete+close a database. - * - * See #mdb_dbi_close() for restrictions about closing the DB handle. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] del 0 to empty the DB, 1 to delete it from the - * environment and close the DB handle. - * @return A non-zero error value on failure and 0 on success. - */ -int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del); - - /** @brief Set a custom key comparison function for a database. - * - * The comparison function is called whenever it is necessary to compare a - * key specified by the application with a key currently stored in the database. - * If no comparison function is specified, and no special key flags were specified - * with #mdb_dbi_open(), the keys are compared lexically, with shorter keys collating - * before longer keys. - * @warning This function must be called before any data access functions are used, - * otherwise data corruption may occur. The same comparison function must be used by every - * program accessing the database, every time the database is used. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] cmp A #MDB_cmp_func function - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); - - /** @brief Set a custom data comparison function for a #MDB_DUPSORT database. - * - * This comparison function is called whenever it is necessary to compare a data - * item specified by the application with a data item currently stored in the database. - * This function only takes effect if the database was opened with the #MDB_DUPSORT - * flag. - * If no comparison function is specified, and no special key flags were specified - * with #mdb_dbi_open(), the data items are compared lexically, with shorter items collating - * before longer items. - * @warning This function must be called before any data access functions are used, - * otherwise data corruption may occur. The same comparison function must be used by every - * program accessing the database, every time the database is used. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] cmp A #MDB_cmp_func function - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp); - - /** @brief Set a relocation function for a #MDB_FIXEDMAP database. - * - * @todo The relocation function is called whenever it is necessary to move the data - * of an item to a different position in the database (e.g. through tree - * balancing operations, shifts as a result of adds or deletes, etc.). It is - * intended to allow address/position-dependent data items to be stored in - * a database in an environment opened with the #MDB_FIXEDMAP option. - * Currently the relocation feature is unimplemented and setting - * this function has no effect. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] rel A #MDB_rel_func function - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel); - - /** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function. - * - * See #mdb_set_relfunc and #MDB_rel_func for more details. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] ctx An arbitrary pointer for whatever the application needs. - * It will be passed to the callback function set by #mdb_set_relfunc - * as its \b relctx parameter whenever the callback is invoked. - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx); - - /** @brief Get items from a database. - * - * This function retrieves key/data pairs from the database. The address - * and length of the data associated with the specified \b key are returned - * in the structure to which \b data refers. - * If the database supports duplicate keys (#MDB_DUPSORT) then the - * first data item for the key will be returned. Retrieval of other - * items requires the use of #mdb_cursor_get(). - * - * @note The memory pointed to by the returned values is owned by the - * database. The caller need not dispose of the memory, and may not - * modify it in any way. For values returned in a read-only transaction - * any modification attempts will cause a SIGSEGV. - * @note Values returned from the database are valid only until a - * subsequent update operation, or the end of the transaction. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] key The key to search for in the database - * @param[out] data The data corresponding to the key - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_NOTFOUND - the key was not in the database. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data); - - /** @brief Store items into a database. - * - * This function stores key/data pairs in the database. The default behavior - * is to enter the new key/data pair, replacing any previously existing key - * if duplicates are disallowed, or adding a duplicate data item if - * duplicates are allowed (#MDB_DUPSORT). - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] key The key to store in the database - * @param[in,out] data The data to store - * @param[in] flags Special options for this operation. This parameter - * must be set to 0 or by bitwise OR'ing together one or more of the - * values described here. - *
    - *
  • #MDB_NODUPDATA - enter the new key/data pair only if it does not - * already appear in the database. This flag may only be specified - * if the database was opened with #MDB_DUPSORT. The function will - * return #MDB_KEYEXIST if the key/data pair already appears in the - * database. - *
  • #MDB_NOOVERWRITE - enter the new key/data pair only if the key - * does not already appear in the database. The function will return - * #MDB_KEYEXIST if the key already appears in the database, even if - * the database supports duplicates (#MDB_DUPSORT). The \b data - * parameter will be set to point to the existing item. - *
  • #MDB_RESERVE - reserve space for data of the given size, but - * don't copy the given data. Instead, return a pointer to the - * reserved space, which the caller can fill in later - before - * the next update operation or the transaction ends. This saves - * an extra memcpy if the data is being generated later. - * LMDB does nothing else with this memory, the caller is expected - * to modify all of the space requested. This flag must not be - * specified if the database was opened with #MDB_DUPSORT. - *
  • #MDB_APPEND - append the given key/data pair to the end of the - * database. This option allows fast bulk loading when keys are - * already known to be in the correct order. Loading unsorted keys - * with this flag will cause a #MDB_KEYEXIST error. - *
  • #MDB_APPENDDUP - as above, but for sorted dup data. - *
- * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize(). - *
  • #MDB_TXN_FULL - the transaction has too many dirty pages. - *
  • EACCES - an attempt was made to write in a read-only transaction. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, - unsigned int flags); - - /** @brief Delete items from a database. - * - * This function removes key/data pairs from the database. - * If the database does not support sorted duplicate data items - * (#MDB_DUPSORT) the data parameter is ignored. - * If the database supports sorted duplicates and the data parameter - * is NULL, all of the duplicate data items for the key will be - * deleted. Otherwise, if the data parameter is non-NULL - * only the matching data item will be deleted. - * This function will return #MDB_NOTFOUND if the specified key/data - * pair is not in the database. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] key The key to delete from the database - * @param[in] data The data to delete - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EACCES - an attempt was made to write in a read-only transaction. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data); - - /** @brief Create a cursor handle. - * - * A cursor is associated with a specific transaction and database. - * A cursor cannot be used when its database handle is closed. Nor - * when its transaction has ended, except with #mdb_cursor_renew(). - * It can be discarded with #mdb_cursor_close(). - * A cursor in a write-transaction can be closed before its transaction - * ends, and will otherwise be closed when its transaction ends. - * A cursor in a read-only transaction must be closed explicitly, before - * or after its transaction ends. It can be reused with - * #mdb_cursor_renew() before finally closing it. - * @note Earlier documentation said that cursors in every transaction - * were closed when the transaction committed or aborted. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[out] cursor Address where the new #MDB_cursor handle will be stored - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor); - - /** @brief Close a cursor handle. - * - * The cursor handle will be freed and must not be used again after this call. - * Its transaction must still be live if it is a write-transaction. - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - */ -void mdb_cursor_close(MDB_cursor *cursor); - - /** @brief Renew a cursor handle. - * - * A cursor is associated with a specific transaction and database. - * Cursors that are only used in read-only - * transactions may be re-used, to avoid unnecessary malloc/free overhead. - * The cursor may be associated with a new read-only transaction, and - * referencing the same database handle as it was created with. - * This may be done whether the previous transaction is live or dead. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_cursor_renew(MDB_txn *txn, MDB_cursor *cursor); - - /** @brief Return the cursor's transaction handle. - * - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - */ -MDB_txn *mdb_cursor_txn(MDB_cursor *cursor); - - /** @brief Return the cursor's database handle. - * - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - */ -MDB_dbi mdb_cursor_dbi(MDB_cursor *cursor); - - /** @brief Retrieve by cursor. - * - * This function retrieves key/data pairs from the database. The address and length - * of the key are returned in the object to which \b key refers (except for the - * case of the #MDB_SET option, in which the \b key object is unchanged), and - * the address and length of the data are returned in the object to which \b data - * refers. - * See #mdb_get() for restrictions on using the output values. - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - * @param[in,out] key The key for a retrieved item - * @param[in,out] data The data of a retrieved item - * @param[in] op A cursor operation #MDB_cursor_op - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_NOTFOUND - no matching key found. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, - MDB_cursor_op op); - - /** @brief Store by cursor. - * - * This function stores key/data pairs into the database. - * The cursor is positioned at the new item, or on failure usually near it. - * @note Earlier documentation incorrectly said errors would leave the - * state of the cursor unchanged. - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - * @param[in] key The key operated on. - * @param[in] data The data operated on. - * @param[in] flags Options for this operation. This parameter - * must be set to 0 or one of the values described here. - *
    - *
  • #MDB_CURRENT - replace the item at the current cursor position. - * The \b key parameter must still be provided, and must match it. - * If using sorted duplicates (#MDB_DUPSORT) the data item must still - * sort into the same place. This is intended to be used when the - * new data is the same size as the old. Otherwise it will simply - * perform a delete of the old record followed by an insert. - *
  • #MDB_NODUPDATA - enter the new key/data pair only if it does not - * already appear in the database. This flag may only be specified - * if the database was opened with #MDB_DUPSORT. The function will - * return #MDB_KEYEXIST if the key/data pair already appears in the - * database. - *
  • #MDB_NOOVERWRITE - enter the new key/data pair only if the key - * does not already appear in the database. The function will return - * #MDB_KEYEXIST if the key already appears in the database, even if - * the database supports duplicates (#MDB_DUPSORT). - *
  • #MDB_RESERVE - reserve space for data of the given size, but - * don't copy the given data. Instead, return a pointer to the - * reserved space, which the caller can fill in later - before - * the next update operation or the transaction ends. This saves - * an extra memcpy if the data is being generated later. This flag - * must not be specified if the database was opened with #MDB_DUPSORT. - *
  • #MDB_APPEND - append the given key/data pair to the end of the - * database. No key comparisons are performed. This option allows - * fast bulk loading when keys are already known to be in the - * correct order. Loading unsorted keys with this flag will cause - * a #MDB_KEYEXIST error. - *
  • #MDB_APPENDDUP - as above, but for sorted dup data. - *
  • #MDB_MULTIPLE - store multiple contiguous data elements in a - * single request. This flag may only be specified if the database - * was opened with #MDB_DUPFIXED. The \b data argument must be an - * array of two MDB_vals. The mv_size of the first MDB_val must be - * the size of a single data element. The mv_data of the first MDB_val - * must point to the beginning of the array of contiguous data elements. - * The mv_size of the second MDB_val must be the count of the number - * of data elements to store. On return this field will be set to - * the count of the number of elements actually written. The mv_data - * of the second MDB_val is unused. - *
- * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • #MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize(). - *
  • #MDB_TXN_FULL - the transaction has too many dirty pages. - *
  • EACCES - an attempt was made to write in a read-only transaction. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data, - unsigned int flags); - - /** @brief Delete current key/data pair - * - * This function deletes the key/data pair to which the cursor refers. - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - * @param[in] flags Options for this operation. This parameter - * must be set to 0 or one of the values described here. - *
    - *
  • #MDB_NODUPDATA - delete all of the data items for the current key. - * This flag may only be specified if the database was opened with #MDB_DUPSORT. - *
- * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EACCES - an attempt was made to write in a read-only transaction. - *
  • EINVAL - an invalid parameter was specified. - *
- */ -int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags); - - /** @brief Return count of duplicates for current key. - * - * This call is only valid on databases that support sorted duplicate - * data items #MDB_DUPSORT. - * @param[in] cursor A cursor handle returned by #mdb_cursor_open() - * @param[out] countp Address where the count will be stored - * @return A non-zero error value on failure and 0 on success. Some possible - * errors are: - *
    - *
  • EINVAL - cursor is not initialized, or an invalid parameter was specified. - *
- */ -int mdb_cursor_count(MDB_cursor *cursor, mdb_size_t *countp); - - /** @brief Compare two data items according to a particular database. - * - * This returns a comparison as if the two data items were keys in the - * specified database. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] a The first item to compare - * @param[in] b The second item to compare - * @return < 0 if a < b, 0 if a == b, > 0 if a > b - */ -int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b); - - /** @brief Compare two data items according to a particular database. - * - * This returns a comparison as if the two items were data items of - * the specified database. The database must have the #MDB_DUPSORT flag. - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - * @param[in] a The first item to compare - * @param[in] b The second item to compare - * @return < 0 if a < b, 0 if a == b, > 0 if a > b - */ -int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b); - - /** @brief A callback function used to print a message from the library. - * - * @param[in] msg The string to be printed. - * @param[in] ctx An arbitrary context pointer for the callback. - * @return < 0 on failure, >= 0 on success. - */ -typedef int (MDB_msg_func)(const char *msg, void *ctx); - - /** @brief Dump the entries in the reader lock table. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[in] func A #MDB_msg_func function - * @param[in] ctx Anything the message function needs - * @return < 0 on failure, >= 0 on success. - */ -int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx); - - /** @brief Check for stale entries in the reader lock table. - * - * @param[in] env An environment handle returned by #mdb_env_create() - * @param[out] dead Number of stale slots that were cleared - * @return 0 on success, non-zero on failure. - */ -int mdb_reader_check(MDB_env *env, int *dead); -/** @} */ - -#ifdef __cplusplus -} -#endif -/** @page tools LMDB Command Line Tools - The following describes the command line tools that are available for LMDB. - \li \ref mdb_copy_1 - \li \ref mdb_dump_1 - \li \ref mdb_load_1 - \li \ref mdb_stat_1 -*/ - -#endif /* _LMDB_H_ */ diff --git a/src/contrib/db/liblmdb/mdb.c b/src/contrib/db/liblmdb/mdb.c deleted file mode 100644 index 17762e8..0000000 --- a/src/contrib/db/liblmdb/mdb.c +++ /dev/null @@ -1,10945 +0,0 @@ -/** @file mdb.c - * @brief Lightning memory-mapped database library - * - * A Btree-based database management library modeled loosely on the - * BerkeleyDB API, but much simplified. - */ -/* - * Copyright 2011-2016 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - * - * This code is derived from btree.c written by Martin Hedenfalk. - * - * Copyright (c) 2009, 2010 Martin Hedenfalk - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif -#if defined(MDB_VL32) || defined(__WIN64__) -#define _FILE_OFFSET_BITS 64 -#endif -#ifdef _WIN32 -#include -#include -#include - -#ifndef _NTDEF_ -typedef _Return_type_success_(return >= 0) LONG NTSTATUS; -typedef NTSTATUS *PNTSTATUS; -#endif - -/** Visual studio big files support -*/ - -/* We use native NT APIs to setup the memory map, so that we can - * let the DB file grow incrementally instead of always preallocating - * the full size. These APIs are defined in and - * but those headers are meant for driver-level development and - * conflict with the regular user-level headers, so we explicitly - * declare them here. Using these APIs also means we must link to - * ntdll.dll, which is not linked by default in user code. - */ -NTSTATUS WINAPI -NtCreateSection(OUT PHANDLE sh, IN ACCESS_MASK acc, - IN void * oa OPTIONAL, - IN PLARGE_INTEGER ms OPTIONAL, - IN ULONG pp, IN ULONG aa, IN HANDLE fh OPTIONAL); - -typedef enum _SECTION_INHERIT { - ViewShare = 1, - ViewUnmap = 2 -} SECTION_INHERIT; - -NTSTATUS WINAPI -NtMapViewOfSection(IN PHANDLE sh, IN HANDLE ph, - IN OUT PVOID *addr, IN ULONG_PTR zbits, - IN SIZE_T cs, IN OUT PLARGE_INTEGER off OPTIONAL, - IN OUT PSIZE_T vs, IN SECTION_INHERIT ih, - IN ULONG at, IN ULONG pp); - -NTSTATUS WINAPI -NtClose(HANDLE h); - -/** getpid() returns int; MinGW defines pid_t but MinGW64 typedefs it - * as int64 which is wrong. MSVC doesn't define it at all, so just - * don't use it. - */ -#define MDB_PID_T int -#define MDB_THR_T DWORD -#include -#include -#ifdef __GNUC__ -# include -#else -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# define BYTE_ORDER LITTLE_ENDIAN -# ifndef SSIZE_MAX -# define SSIZE_MAX INT_MAX -# endif -#endif -#else -#include -#include -#define MDB_PID_T pid_t -#define MDB_THR_T pthread_t -#include -#include -#include -#ifdef HAVE_SYS_FILE_H -#include -#endif -#include -#endif - -#if defined(__mips) && defined(__linux) -/* MIPS has cache coherency issues, requires explicit cache control */ -#include -extern int cacheflush(char *addr, int nbytes, int cache); -#define CACHEFLUSH(addr, bytes, cache) cacheflush(addr, bytes, cache) -#else -#define CACHEFLUSH(addr, bytes, cache) -#endif - -#if defined(__linux) && !defined(MDB_FDATASYNC_WORKS) -/** fdatasync is broken on ext3/ext4fs on older kernels, see - * description in #mdb_env_open2 comments. You can safely - * define MDB_FDATASYNC_WORKS if this code will only be run - * on kernels 3.6 and newer. - */ -#define BROKEN_FDATASYNC -#endif - -#ifdef _WIN32 -typedef int64_t off64_t; -#elif __APPLE__ -typedef off_t off64_t; -#else - -#endif - - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#include -typedef SSIZE_T ssize_t; -#else -#include -#endif - -#if defined(__sun) || defined(__ANDROID__) -/* Most platforms have posix_memalign, older may only have memalign */ -#define HAVE_MEMALIGN 1 -#include -#endif - -#if !(defined(BYTE_ORDER) || defined(__BYTE_ORDER)) -#include -#include /* defines BYTE_ORDER on HPUX and Solaris */ -#endif - -#if defined(__APPLE__) || defined (BSD) -# if !(defined(MDB_USE_POSIX_MUTEX) || defined(MDB_USE_POSIX_SEM)) -# define MDB_USE_SYSV_SEM 1 -# endif -# define MDB_FDATASYNC fsync -#elif defined(__ANDROID__) -# define MDB_FDATASYNC fsync -#endif - -#ifndef _WIN32 -#include -#ifdef MDB_USE_POSIX_SEM -# define MDB_USE_HASH 1 -#include -#elif defined(MDB_USE_SYSV_SEM) -#include -#include -#ifdef _SEM_SEMUN_UNDEFINED -union semun { - int val; - struct semid_ds *buf; - unsigned short *array; -}; -#endif /* _SEM_SEMUN_UNDEFINED */ -#else -#define MDB_USE_POSIX_MUTEX 1 -#endif /* MDB_USE_POSIX_SEM */ -#endif /* !_WIN32 */ - -#if defined(_WIN32) + defined(MDB_USE_POSIX_SEM) + defined(MDB_USE_SYSV_SEM) \ - + defined(MDB_USE_POSIX_MUTEX) != 1 -# error "Ambiguous shared-lock implementation" -#endif - -#ifdef USE_VALGRIND -#include -#define VGMEMP_CREATE(h,r,z) VALGRIND_CREATE_MEMPOOL(h,r,z) -#define VGMEMP_ALLOC(h,a,s) VALGRIND_MEMPOOL_ALLOC(h,a,s) -#define VGMEMP_FREE(h,a) VALGRIND_MEMPOOL_FREE(h,a) -#define VGMEMP_DESTROY(h) VALGRIND_DESTROY_MEMPOOL(h) -#define VGMEMP_DEFINED(a,s) VALGRIND_MAKE_MEM_DEFINED(a,s) -#else -#define VGMEMP_CREATE(h,r,z) -#define VGMEMP_ALLOC(h,a,s) -#define VGMEMP_FREE(h,a) -#define VGMEMP_DESTROY(h) -#define VGMEMP_DEFINED(a,s) -#endif - -#ifndef BYTE_ORDER -# if (defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) -/* Solaris just defines one or the other */ -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# ifdef _LITTLE_ENDIAN -# define BYTE_ORDER LITTLE_ENDIAN -# else -# define BYTE_ORDER BIG_ENDIAN -# endif -# else -# define BYTE_ORDER __BYTE_ORDER -# endif -#endif - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN __LITTLE_ENDIAN -#endif -#ifndef BIG_ENDIAN -#define BIG_ENDIAN __BIG_ENDIAN -#endif - -#if defined(__i386) || defined(__x86_64) || defined(_M_IX86) -#define MISALIGNED_OK 1 -#endif - -#include "lmdb.h" -#include "midl.h" - -#if (BYTE_ORDER == LITTLE_ENDIAN) == (BYTE_ORDER == BIG_ENDIAN) -# error "Unknown or unsupported endianness (BYTE_ORDER)" -#elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF -# error "Two's complement, reasonably sized integer types, please" -#endif - -#ifdef __GNUC__ -/** Put infrequently used env functions in separate section */ -# ifdef __APPLE__ -# define ESECT __attribute__ ((section("__TEXT,text_env"))) -# else -# define ESECT __attribute__ ((section("text_env"))) -# endif -#else -#define ESECT -#endif - -#ifdef _WIN32 -#define CALL_CONV WINAPI -#else -#define CALL_CONV -#endif - -/** @defgroup internal LMDB Internals - * @{ - */ -/** @defgroup compat Compatibility Macros - * A bunch of macros to minimize the amount of platform-specific ifdefs - * needed throughout the rest of the code. When the features this library - * needs are similar enough to POSIX to be hidden in a one-or-two line - * replacement, this macro approach is used. - * @{ - */ - - /** Features under development */ -#ifndef MDB_DEVEL -#define MDB_DEVEL 0 -#endif - - /** Wrapper around __func__, which is a C99 feature */ -#if __STDC_VERSION__ >= 199901L -# define mdb_func_ __func__ -#elif __GNUC__ >= 2 || _MSC_VER >= 1300 -# define mdb_func_ __FUNCTION__ -#else -/* If a debug message says (), update the #if statements above */ -# define mdb_func_ "" -#endif - -/* Internal error codes, not exposed outside liblmdb */ -#define MDB_NO_ROOT (MDB_LAST_ERRCODE + 10) -#ifdef _WIN32 -#define MDB_OWNERDEAD ((int) WAIT_ABANDONED) -#elif defined MDB_USE_SYSV_SEM -#define MDB_OWNERDEAD (MDB_LAST_ERRCODE + 11) -#elif defined(MDB_USE_POSIX_MUTEX) && defined(EOWNERDEAD) -#define MDB_OWNERDEAD EOWNERDEAD /**< #LOCK_MUTEX0() result if dead owner */ -#endif - -#ifdef __GLIBC__ -#define GLIBC_VER ((__GLIBC__ << 16 )| __GLIBC_MINOR__) -#endif -/** Some platforms define the EOWNERDEAD error code - * even though they don't support Robust Mutexes. - * Compile with -DMDB_USE_ROBUST=0, or use some other - * mechanism like -DMDB_USE_SYSV_SEM instead of - * -DMDB_USE_POSIX_MUTEX. (SysV semaphores are - * also Robust, but some systems don't support them - * either.) - */ -#ifndef MDB_USE_ROBUST -/* Android currently lacks Robust Mutex support. So does glibc < 2.4. */ -# if defined(MDB_USE_POSIX_MUTEX) && (defined(__ANDROID__) || \ - (defined(__GLIBC__) && GLIBC_VER < 0x020004)) -# define MDB_USE_ROBUST 0 -# else -# define MDB_USE_ROBUST 1 -/* glibc < 2.12 only provided _np API */ -# if defined(__GLIBC__) && GLIBC_VER < 0x02000c -# define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP -# define pthread_mutexattr_setrobust(attr, flag) pthread_mutexattr_setrobust_np(attr, flag) -# define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex) -# endif -# endif -#endif /* MDB_USE_ROBUST */ - -#if defined(MDB_OWNERDEAD) && MDB_USE_ROBUST -#define MDB_ROBUST_SUPPORTED 1 -#endif - -#ifdef _WIN32 -#define MDB_USE_HASH 1 -#define MDB_PIDLOCK 0 -#define THREAD_RET DWORD -#define pthread_t HANDLE -#define pthread_mutex_t HANDLE -#define pthread_cond_t HANDLE -typedef HANDLE mdb_mutex_t, mdb_mutexref_t; -#define pthread_key_t DWORD -#define pthread_self() GetCurrentThreadId() -#define pthread_key_create(x,y) \ - ((*(x) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? ErrCode() : 0) -#define pthread_key_delete(x) TlsFree(x) -#define pthread_getspecific(x) TlsGetValue(x) -#define pthread_setspecific(x,y) (TlsSetValue(x,y) ? 0 : ErrCode()) -#define pthread_mutex_unlock(x) ReleaseMutex(*x) -#define pthread_mutex_lock(x) WaitForSingleObject(*x, INFINITE) -#define pthread_cond_signal(x) SetEvent(*x) -#define pthread_cond_wait(cond,mutex) do{SignalObjectAndWait(*mutex, *cond, INFINITE, FALSE); WaitForSingleObject(*mutex, INFINITE);}while(0) -#define THREAD_CREATE(thr,start,arg) thr=CreateThread(NULL,0,start,arg,0,NULL) -#define THREAD_FINISH(thr) WaitForSingleObject(thr, INFINITE) -#define LOCK_MUTEX0(mutex) WaitForSingleObject(mutex, INFINITE) -#define UNLOCK_MUTEX(mutex) ReleaseMutex(mutex) -#define mdb_mutex_consistent(mutex) 0 -#define getpid() GetCurrentProcessId() -#define MDB_FDATASYNC(fd) (!FlushFileBuffers(fd)) -#define MDB_MSYNC(addr,len,flags) (!FlushViewOfFile(addr,len)) -#define ErrCode() GetLastError() -#define GET_PAGESIZE(x) {SYSTEM_INFO si; GetSystemInfo(&si); (x) = si.dwPageSize;} -#define close(fd) (CloseHandle(fd) ? 0 : -1) -#define munmap(ptr,len) UnmapViewOfFile(ptr) -#ifdef PROCESS_QUERY_LIMITED_INFORMATION -#define MDB_PROCESS_QUERY_LIMITED_INFORMATION PROCESS_QUERY_LIMITED_INFORMATION -#else -#define MDB_PROCESS_QUERY_LIMITED_INFORMATION 0x1000 -#endif -#define Z "I" -#else -#define THREAD_RET void * -#define THREAD_CREATE(thr,start,arg) pthread_create(&thr,NULL,start,arg) -#define THREAD_FINISH(thr) pthread_join(thr,NULL) -#define Z "z" /**< printf format modifier for size_t */ - - /** For MDB_LOCK_FORMAT: True if readers take a pid lock in the lockfile */ -#define MDB_PIDLOCK 1 - -#ifdef MDB_USE_POSIX_SEM - -typedef sem_t *mdb_mutex_t, *mdb_mutexref_t; -#define LOCK_MUTEX0(mutex) mdb_sem_wait(mutex) -#define UNLOCK_MUTEX(mutex) sem_post(mutex) - -static int -mdb_sem_wait(sem_t *sem) -{ - int rc; - while ((rc = sem_wait(sem)) && (rc = errno) == EINTR) ; - return rc; -} - -#elif defined MDB_USE_SYSV_SEM - -typedef struct mdb_mutex { - int semid; - int semnum; - int *locked; -} mdb_mutex_t[1], *mdb_mutexref_t; - -#define LOCK_MUTEX0(mutex) mdb_sem_wait(mutex) -#define UNLOCK_MUTEX(mutex) do { \ - struct sembuf sb = { 0, 1, SEM_UNDO }; \ - sb.sem_num = (mutex)->semnum; \ - *(mutex)->locked = 0; \ - semop((mutex)->semid, &sb, 1); \ -} while(0) - -static int -mdb_sem_wait(mdb_mutexref_t sem) -{ - int rc, *locked = sem->locked; - struct sembuf sb = { 0, -1, SEM_UNDO }; - sb.sem_num = sem->semnum; - do { - if (!semop(sem->semid, &sb, 1)) { - rc = *locked ? MDB_OWNERDEAD : MDB_SUCCESS; - *locked = 1; - break; - } - } while ((rc = errno) == EINTR); - return rc; -} - -#define mdb_mutex_consistent(mutex) 0 - -#else /* MDB_USE_POSIX_MUTEX: */ - /** Shared mutex/semaphore as it is stored (mdb_mutex_t), and as - * local variables keep it (mdb_mutexref_t). - * - * An mdb_mutex_t can be assigned to an mdb_mutexref_t. They can - * be the same, or an array[size 1] and a pointer. - * @{ - */ -typedef pthread_mutex_t mdb_mutex_t[1], *mdb_mutexref_t; - /* @} */ - /** Lock the reader or writer mutex. - * Returns 0 or a code to give #mdb_mutex_failed(), as in #LOCK_MUTEX(). - */ -#define LOCK_MUTEX0(mutex) pthread_mutex_lock(mutex) - /** Unlock the reader or writer mutex. - */ -#define UNLOCK_MUTEX(mutex) pthread_mutex_unlock(mutex) - /** Mark mutex-protected data as repaired, after death of previous owner. - */ -#define mdb_mutex_consistent(mutex) pthread_mutex_consistent(mutex) -#endif /* MDB_USE_POSIX_SEM || MDB_USE_SYSV_SEM */ - - /** Get the error code for the last failed system function. - */ -#define ErrCode() errno - - /** An abstraction for a file handle. - * On POSIX systems file handles are small integers. On Windows - * they're opaque pointers. - */ -#define HANDLE int - - /** A value for an invalid file handle. - * Mainly used to initialize file variables and signify that they are - * unused. - */ -#define INVALID_HANDLE_VALUE (-1) - - /** Get the size of a memory page for the system. - * This is the basic size that the platform's memory manager uses, and is - * fundamental to the use of memory-mapped files. - */ -#define GET_PAGESIZE(x) ((x) = sysconf(_SC_PAGE_SIZE)) -#endif - -#ifdef MDB_VL32 -#ifdef _WIN32 -#define Y "I64" -#else -#define Y "ll" -#endif -#else -#define Y Z -#endif - -#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) -#define MNAME_LEN 32 -#elif defined(MDB_USE_SYSV_SEM) -#define MNAME_LEN (sizeof(int)) -#else -#define MNAME_LEN (sizeof(pthread_mutex_t)) -#endif - -#ifdef MDB_USE_SYSV_SEM -#define SYSV_SEM_FLAG 1 /**< SysV sems in lockfile format */ -#else -#define SYSV_SEM_FLAG 0 -#endif - -/** @} */ - -#ifdef MDB_ROBUST_SUPPORTED - /** Lock mutex, handle any error, set rc = result. - * Return 0 on success, nonzero (not rc) on error. - */ -#define LOCK_MUTEX(rc, env, mutex) \ - (((rc) = LOCK_MUTEX0(mutex)) && \ - ((rc) = mdb_mutex_failed(env, mutex, rc))) -static int mdb_mutex_failed(MDB_env *env, mdb_mutexref_t mutex, int rc); -#else -#define LOCK_MUTEX(rc, env, mutex) ((rc) = LOCK_MUTEX0(mutex)) -#define mdb_mutex_failed(env, mutex, rc) (rc) -#endif - -#ifndef _WIN32 -/** A flag for opening a file and requesting synchronous data writes. - * This is only used when writing a meta page. It's not strictly needed; - * we could just do a normal write and then immediately perform a flush. - * But if this flag is available it saves us an extra system call. - * - * @note If O_DSYNC is undefined but exists in /usr/include, - * preferably set some compiler flag to get the definition. - */ -#ifndef MDB_DSYNC -# ifdef O_DSYNC -# define MDB_DSYNC O_DSYNC -# else -# define MDB_DSYNC O_SYNC -# endif -#endif -#endif - -/** Function for flushing the data of a file. Define this to fsync - * if fdatasync() is not supported. - */ -#ifndef MDB_FDATASYNC -# define MDB_FDATASYNC fdatasync -#endif - -#ifndef MDB_MSYNC -# define MDB_MSYNC(addr,len,flags) msync(addr,len,flags) -#endif - -#ifndef MS_SYNC -#define MS_SYNC 1 -#endif - -#ifndef MS_ASYNC -#define MS_ASYNC 0 -#endif - - /** A page number in the database. - * Note that 64 bit page numbers are overkill, since pages themselves - * already represent 12-13 bits of addressable memory, and the OS will - * always limit applications to a maximum of 63 bits of address space. - * - * @note In the #MDB_node structure, we only store 48 bits of this value, - * which thus limits us to only 60 bits of addressable data. - */ -typedef MDB_ID pgno_t; - - /** A transaction ID. - * See struct MDB_txn.mt_txnid for details. - */ -typedef MDB_ID txnid_t; - -/** @defgroup debug Debug Macros - * @{ - */ -#ifndef MDB_DEBUG - /** Enable debug output. Needs variable argument macros (a C99 feature). - * Set this to 1 for copious tracing. Set to 2 to add dumps of all IDLs - * read from and written to the database (used for free space management). - */ -#define MDB_DEBUG 0 -#endif - -#if MDB_DEBUG -static int mdb_debug; -static txnid_t mdb_debug_start; - - /** Print a debug message with printf formatting. - * Requires double parenthesis around 2 or more args. - */ -# define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args)) -# define DPRINTF0(fmt, ...) \ - fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__) -#else -# define DPRINTF(args) ((void) 0) -#endif - /** Print a debug string. - * The string is printed literally, with no format processing. - */ -#define DPUTS(arg) DPRINTF(("%s", arg)) - /** Debuging output value of a cursor DBI: Negative in a sub-cursor. */ -#define DDBI(mc) \ - (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) -/** @} */ - - /** @brief The maximum size of a database page. - * - * It is 32k or 64k, since value-PAGEBASE must fit in - * #MDB_page.%mp_upper. - * - * LMDB will use database pages < OS pages if needed. - * That causes more I/O in write transactions: The OS must - * know (read) the whole page before writing a partial page. - * - * Note that we don't currently support Huge pages. On Linux, - * regular data files cannot use Huge pages, and in general - * Huge pages aren't actually pageable. We rely on the OS - * demand-pager to read our data and page it out when memory - * pressure from other processes is high. So until OSs have - * actual paging support for Huge pages, they're not viable. - */ -#define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000) - - /** The minimum number of keys required in a database page. - * Setting this to a larger value will place a smaller bound on the - * maximum size of a data item. Data items larger than this size will - * be pushed into overflow pages instead of being stored directly in - * the B-tree node. This value used to default to 4. With a page size - * of 4096 bytes that meant that any item larger than 1024 bytes would - * go into an overflow page. That also meant that on average 2-3KB of - * each overflow page was wasted space. The value cannot be lower than - * 2 because then there would no longer be a tree structure. With this - * value, items larger than 2KB will go into overflow pages, and on - * average only 1KB will be wasted. - */ -#define MDB_MINKEYS 2 - - /** A stamp that identifies a file as an LMDB file. - * There's nothing special about this value other than that it is easily - * recognizable, and it will reflect any byte order mismatches. - */ -#define MDB_MAGIC 0xBEEFC0DE - - /** The version number for a database's datafile format. */ -#define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1) - /** The version number for a database's lockfile format. */ -#define MDB_LOCK_VERSION ((MDB_DEVEL) ? 999 : 1) - - /** @brief The max size of a key we can write, or 0 for computed max. - * - * This macro should normally be left alone or set to 0. - * Note that a database with big keys or dupsort data cannot be - * reliably modified by a liblmdb which uses a smaller max. - * The default is 511 for backwards compat, or 0 when #MDB_DEVEL. - * - * Other values are allowed, for backwards compat. However: - * A value bigger than the computed max can break if you do not - * know what you are doing, and liblmdb <= 0.9.10 can break when - * modifying a DB with keys/dupsort data bigger than its max. - * - * Data items in an #MDB_DUPSORT database are also limited to - * this size, since they're actually keys of a sub-DB. Keys and - * #MDB_DUPSORT data items must fit on a node in a regular page. - */ -#ifndef MDB_MAXKEYSIZE -#define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511) -#endif - - /** The maximum size of a key we can write to the environment. */ -#if MDB_MAXKEYSIZE -#define ENV_MAXKEY(env) (MDB_MAXKEYSIZE) -#else -#define ENV_MAXKEY(env) ((env)->me_maxkey) -#endif - - /** @brief The maximum size of a data item. - * - * We only store a 32 bit value for node sizes. - */ -#define MAXDATASIZE 0xffffffffUL - -#if MDB_DEBUG - /** Key size which fits in a #DKBUF. - * @ingroup debug - */ -#define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511) - /** A key buffer. - * @ingroup debug - * This is used for printing a hex dump of a key's contents. - */ -#define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1] - /** Display a key in hex. - * @ingroup debug - * Invoke a function to display a key in hex. - */ -#define DKEY(x) mdb_dkey(x, kbuf) -#else -#define DKBUF -#define DKEY(x) 0 -#endif - - /** An invalid page number. - * Mainly used to denote an empty tree. - */ -#define P_INVALID (~(pgno_t)0) - - /** Test if the flags \b f are set in a flag word \b w. */ -#define F_ISSET(w, f) (((w) & (f)) == (f)) - - /** Round \b n up to an even number. */ -#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */ - - /** Used for offsets within a single page. - * Since memory pages are typically 4 or 8KB in size, 12-13 bits, - * this is plenty. - */ -typedef uint16_t indx_t; - - /** Default size of memory map. - * This is certainly too small for any actual applications. Apps should always set - * the size explicitly using #mdb_env_set_mapsize(). - */ -#define DEFAULT_MAPSIZE 1048576 - -/** @defgroup readers Reader Lock Table - * Readers don't acquire any locks for their data access. Instead, they - * simply record their transaction ID in the reader table. The reader - * mutex is needed just to find an empty slot in the reader table. The - * slot's address is saved in thread-specific data so that subsequent read - * transactions started by the same thread need no further locking to proceed. - * - * If #MDB_NOTLS is set, the slot address is not saved in thread-specific data. - * - * No reader table is used if the database is on a read-only filesystem, or - * if #MDB_NOLOCK is set. - * - * Since the database uses multi-version concurrency control, readers don't - * actually need any locking. This table is used to keep track of which - * readers are using data from which old transactions, so that we'll know - * when a particular old transaction is no longer in use. Old transactions - * that have discarded any data pages can then have those pages reclaimed - * for use by a later write transaction. - * - * The lock table is constructed such that reader slots are aligned with the - * processor's cache line size. Any slot is only ever used by one thread. - * This alignment guarantees that there will be no contention or cache - * thrashing as threads update their own slot info, and also eliminates - * any need for locking when accessing a slot. - * - * A writer thread will scan every slot in the table to determine the oldest - * outstanding reader transaction. Any freed pages older than this will be - * reclaimed by the writer. The writer doesn't use any locks when scanning - * this table. This means that there's no guarantee that the writer will - * see the most up-to-date reader info, but that's not required for correct - * operation - all we need is to know the upper bound on the oldest reader, - * we don't care at all about the newest reader. So the only consequence of - * reading stale information here is that old pages might hang around a - * while longer before being reclaimed. That's actually good anyway, because - * the longer we delay reclaiming old pages, the more likely it is that a - * string of contiguous pages can be found after coalescing old pages from - * many old transactions together. - * @{ - */ - /** Number of slots in the reader table. - * This value was chosen somewhat arbitrarily. 126 readers plus a - * couple mutexes fit exactly into 8KB on my development machine. - * Applications should set the table size using #mdb_env_set_maxreaders(). - */ -#define DEFAULT_READERS 126 - - /** The size of a CPU cache line in bytes. We want our lock structures - * aligned to this size to avoid false cache line sharing in the - * lock table. - * This value works for most CPUs. For Itanium this should be 128. - */ -#ifndef CACHELINE -#define CACHELINE 64 -#endif - - /** The information we store in a single slot of the reader table. - * In addition to a transaction ID, we also record the process and - * thread ID that owns a slot, so that we can detect stale information, - * e.g. threads or processes that went away without cleaning up. - * @note We currently don't check for stale records. We simply re-init - * the table when we know that we're the only process opening the - * lock file. - */ -typedef struct MDB_rxbody { - /** Current Transaction ID when this transaction began, or (txnid_t)-1. - * Multiple readers that start at the same time will probably have the - * same ID here. Again, it's not important to exclude them from - * anything; all we need to know is which version of the DB they - * started from so we can avoid overwriting any data used in that - * particular version. - */ - volatile txnid_t mrb_txnid; - /** The process ID of the process owning this reader txn. */ - volatile MDB_PID_T mrb_pid; - /** The thread ID of the thread owning this txn. */ - volatile MDB_THR_T mrb_tid; -} MDB_rxbody; - - /** The actual reader record, with cacheline padding. */ -typedef struct MDB_reader { - union { - MDB_rxbody mrx; - /** shorthand for mrb_txnid */ -#define mr_txnid mru.mrx.mrb_txnid -#define mr_pid mru.mrx.mrb_pid -#define mr_tid mru.mrx.mrb_tid - /** cache line alignment */ - char pad[(sizeof(MDB_rxbody)+CACHELINE-1) & ~(CACHELINE-1)]; - } mru; -} MDB_reader; - - /** The header for the reader table. - * The table resides in a memory-mapped file. (This is a different file - * than is used for the main database.) - * - * For POSIX the actual mutexes reside in the shared memory of this - * mapped file. On Windows, mutexes are named objects allocated by the - * kernel; we store the mutex names in this mapped file so that other - * processes can grab them. This same approach is also used on - * MacOSX/Darwin (using named semaphores) since MacOSX doesn't support - * process-shared POSIX mutexes. For these cases where a named object - * is used, the object name is derived from a 64 bit FNV hash of the - * environment pathname. As such, naming collisions are extremely - * unlikely. If a collision occurs, the results are unpredictable. - */ -typedef struct MDB_txbody { - /** Stamp identifying this as an LMDB file. It must be set - * to #MDB_MAGIC. */ - uint32_t mtb_magic; - /** Format of this lock file. Must be set to #MDB_LOCK_FORMAT. */ - uint32_t mtb_format; - /** The ID of the last transaction committed to the database. - * This is recorded here only for convenience; the value can always - * be determined by reading the main database meta pages. - */ - volatile txnid_t mtb_txnid; - /** The number of slots that have been used in the reader table. - * This always records the maximum count, it is not decremented - * when readers release their slots. - */ - volatile unsigned mtb_numreaders; -#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) - char mtb_rmname[MNAME_LEN]; -#elif defined(MDB_USE_SYSV_SEM) - int mtb_semid; - int mtb_rlocked; -#else - /** Mutex protecting access to this table. - * This is the reader table lock used with LOCK_MUTEX(). - */ - mdb_mutex_t mtb_rmutex; -#endif -} MDB_txbody; - - /** The actual reader table definition. */ -typedef struct MDB_txninfo { - union { - MDB_txbody mtb; -#define mti_magic mt1.mtb.mtb_magic -#define mti_format mt1.mtb.mtb_format -#define mti_rmutex mt1.mtb.mtb_rmutex -#define mti_rmname mt1.mtb.mtb_rmname -#define mti_txnid mt1.mtb.mtb_txnid -#define mti_numreaders mt1.mtb.mtb_numreaders -#ifdef MDB_USE_SYSV_SEM -#define mti_semid mt1.mtb.mtb_semid -#define mti_rlocked mt1.mtb.mtb_rlocked -#endif - char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)]; - } mt1; - union { -#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM) - char mt2_wmname[MNAME_LEN]; -#define mti_wmname mt2.mt2_wmname -#elif defined MDB_USE_SYSV_SEM - int mt2_wlocked; -#define mti_wlocked mt2.mt2_wlocked -#else - mdb_mutex_t mt2_wmutex; -#define mti_wmutex mt2.mt2_wmutex -#endif - char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)]; - } mt2; - MDB_reader mti_readers[1]; -} MDB_txninfo; - - /** Lockfile format signature: version, features and field layout */ -#define MDB_LOCK_FORMAT \ - ((uint32_t) \ - ((MDB_LOCK_VERSION) \ - /* Flags which describe functionality */ \ - + (SYSV_SEM_FLAG << 18) \ - + (((MDB_PIDLOCK) != 0) << 16))) -/** @} */ - -/** Common header for all page types. - * Overflow records occupy a number of contiguous pages with no - * headers on any page after the first. - */ -typedef struct MDB_page { -#define mp_pgno mp_p.p_pgno -#define mp_next mp_p.p_next - union { - pgno_t p_pgno; /**< page number */ - struct MDB_page *p_next; /**< for in-memory list of freed pages */ - } mp_p; - uint16_t mp_pad; -/** @defgroup mdb_page Page Flags - * @ingroup internal - * Flags for the page headers. - * @{ - */ -#define P_BRANCH 0x01 /**< branch page */ -#define P_LEAF 0x02 /**< leaf page */ -#define P_OVERFLOW 0x04 /**< overflow page */ -#define P_META 0x08 /**< meta page */ -#define P_DIRTY 0x10 /**< dirty page, also set for #P_SUBP pages */ -#define P_LEAF2 0x20 /**< for #MDB_DUPFIXED records */ -#define P_SUBP 0x40 /**< for #MDB_DUPSORT sub-pages */ -#define P_LOOSE 0x4000 /**< page was dirtied then freed, can be reused */ -#define P_KEEP 0x8000 /**< leave this page alone during spill */ -/** @} */ - uint16_t mp_flags; /**< @ref mdb_page */ -#define mp_lower mp_pb.pb.pb_lower -#define mp_upper mp_pb.pb.pb_upper -#define mp_pages mp_pb.pb_pages - union { - struct { - indx_t pb_lower; /**< lower bound of free space */ - indx_t pb_upper; /**< upper bound of free space */ - } pb; - uint32_t pb_pages; /**< number of overflow pages */ - } mp_pb; - indx_t mp_ptrs[1]; /**< dynamic size */ -} MDB_page; - - /** Size of the page header, excluding dynamic data at the end */ -#define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs)) - - /** Address of first usable data byte in a page, after the header */ -#define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ)) - - /** ITS#7713, change PAGEBASE to handle 65536 byte pages */ -#define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0) - - /** Number of nodes on a page */ -#define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1) - - /** The amount of space remaining in the page */ -#define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower) - - /** The percentage of space used in the page, in tenths of a percent. */ -#define PAGEFILL(env, p) (1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \ - ((env)->me_psize - PAGEHDRSZ)) - /** The minimum page fill factor, in tenths of a percent. - * Pages emptier than this are candidates for merging. - */ -#define FILL_THRESHOLD 250 - - /** Test if a page is a leaf page */ -#define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF) - /** Test if a page is a LEAF2 page */ -#define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2) - /** Test if a page is a branch page */ -#define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH) - /** Test if a page is an overflow page */ -#define IS_OVERFLOW(p) F_ISSET((p)->mp_flags, P_OVERFLOW) - /** Test if a page is a sub page */ -#define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP) - - /** The number of overflow pages needed to store the given size. */ -#define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1) - - /** Link in #MDB_txn.%mt_loose_pgs list */ -#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2)) - - /** Header for a single key/data pair within a page. - * Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2. - * We guarantee 2-byte alignment for 'MDB_node's. - */ -typedef struct MDB_node { - /** lo and hi are used for data size on leaf nodes and for - * child pgno on branch nodes. On 64 bit platforms, flags - * is also used for pgno. (Branch nodes have no flags). - * They are in host byte order in case that lets some - * accesses be optimized into a 32-bit word access. - */ -#if BYTE_ORDER == LITTLE_ENDIAN - unsigned short mn_lo, mn_hi; /**< part of data size or pgno */ -#else - unsigned short mn_hi, mn_lo; -#endif -/** @defgroup mdb_node Node Flags - * @ingroup internal - * Flags for node headers. - * @{ - */ -#define F_BIGDATA 0x01 /**< data put on overflow page */ -#define F_SUBDATA 0x02 /**< data is a sub-database */ -#define F_DUPDATA 0x04 /**< data has duplicates */ - -/** valid flags for #mdb_node_add() */ -#define NODE_ADD_FLAGS (F_DUPDATA|F_SUBDATA|MDB_RESERVE|MDB_APPEND) - -/** @} */ - unsigned short mn_flags; /**< @ref mdb_node */ - unsigned short mn_ksize; /**< key size */ - char mn_data[1]; /**< key and data are appended here */ -} MDB_node; - - /** Size of the node header, excluding dynamic data at the end */ -#define NODESIZE offsetof(MDB_node, mn_data) - - /** Bit position of top word in page number, for shifting mn_flags */ -#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0) - - /** Size of a node in a branch page with a given key. - * This is just the node header plus the key, there is no data. - */ -#define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->mv_size)) - - /** Size of a node in a leaf page with a given key and data. - * This is node header plus key plus data size. - */ -#define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size) - - /** Address of node \b i in page \b p */ -#define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEBASE)) - - /** Address of the key for the node */ -#define NODEKEY(node) (void *)((node)->mn_data) - - /** Address of the data for a node */ -#define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) - - /** Get the page number pointed to by a branch node */ -#define NODEPGNO(node) \ - ((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | \ - (PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0)) - /** Set the page number in a branch node */ -#define SETPGNO(node,pgno) do { \ - (node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; \ - if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0) - - /** Get the size of the data in a leaf node */ -#define NODEDSZ(node) ((node)->mn_lo | ((unsigned)(node)->mn_hi << 16)) - /** Set the size of the data for a leaf node */ -#define SETDSZ(node,size) do { \ - (node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0) - /** The size of a key in a node */ -#define NODEKSZ(node) ((node)->mn_ksize) - - /** Copy a page number from src to dst */ -#ifdef MISALIGNED_OK -#define COPY_PGNO(dst,src) dst = src -#else -#if SIZE_MAX > 4294967295UL -#define COPY_PGNO(dst,src) do { \ - unsigned short *s, *d; \ - s = (unsigned short *)&(src); \ - d = (unsigned short *)&(dst); \ - *d++ = *s++; \ - *d++ = *s++; \ - *d++ = *s++; \ - *d = *s; \ -} while (0) -#else -#define COPY_PGNO(dst,src) do { \ - unsigned short *s, *d; \ - s = (unsigned short *)&(src); \ - d = (unsigned short *)&(dst); \ - *d++ = *s++; \ - *d = *s; \ -} while (0) -#endif -#endif - /** The address of a key in a LEAF2 page. - * LEAF2 pages are used for #MDB_DUPFIXED sorted-duplicate sub-DBs. - * There are no node headers, keys are stored contiguously. - */ -#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i)*(ks))) - - /** Set the \b node's key into \b keyptr, if requested. */ -#define MDB_GET_KEY(node, keyptr) { if ((keyptr) != NULL) { \ - (keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } } - - /** Set the \b node's key into \b key. */ -#define MDB_GET_KEY2(node, key) { key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); } - - /** Information about a single database in the environment. */ -typedef struct MDB_db { - uint32_t md_pad; /**< also ksize for LEAF2 pages */ - uint16_t md_flags; /**< @ref mdb_dbi_open */ - uint16_t md_depth; /**< depth of this tree */ - pgno_t md_branch_pages; /**< number of internal pages */ - pgno_t md_leaf_pages; /**< number of leaf pages */ - pgno_t md_overflow_pages; /**< number of overflow pages */ - mdb_size_t md_entries; /**< number of data items */ - pgno_t md_root; /**< the root page of this tree */ -} MDB_db; - - /** mdb_dbi_open flags */ -#define MDB_VALID 0x8000 /**< DB handle is valid, for me_dbflags */ -#define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID)) -#define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\ - MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE) - - /** Handle for the DB used to track free pages. */ -#define FREE_DBI 0 - /** Handle for the default DB. */ -#define MAIN_DBI 1 - /** Number of DBs in metapage (free and main) - also hardcoded elsewhere */ -#define CORE_DBS 2 - - /** Number of meta pages - also hardcoded elsewhere */ -#define NUM_METAS 2 - - /** Meta page content. - * A meta page is the start point for accessing a database snapshot. - * Pages 0-1 are meta pages. Transaction N writes meta page #(N % 2). - */ -typedef struct MDB_meta { - /** Stamp identifying this as an LMDB file. It must be set - * to #MDB_MAGIC. */ - uint32_t mm_magic; - /** Version number of this file. Must be set to #MDB_DATA_VERSION. */ - uint32_t mm_version; -#ifdef MDB_VL32 - union { /* always zero since we don't support fixed mapping in MDB_VL32 */ - MDB_ID mmun_ull; - void *mmun_address; - } mm_un; -#define mm_address mm_un.mmun_address -#else - void *mm_address; /**< address for fixed mapping */ -#endif - pgno_t mm_mapsize; /**< size of mmap region */ - MDB_db mm_dbs[CORE_DBS]; /**< first is free space, 2nd is main db */ - /** The size of pages used in this DB */ -#define mm_psize mm_dbs[FREE_DBI].md_pad - /** Any persistent environment flags. @ref mdb_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags - pgno_t mm_last_pg; /**< last used page in file */ - volatile txnid_t mm_txnid; /**< txnid that committed this page */ -} MDB_meta; - - /** Buffer for a stack-allocated meta page. - * The members define size and alignment, and silence type - * aliasing warnings. They are not used directly; that could - * mean incorrectly using several union members in parallel. - */ -typedef union MDB_metabuf { - MDB_page mb_page; - struct { - char mm_pad[PAGEHDRSZ]; - MDB_meta mm_meta; - } mb_metabuf; -} MDB_metabuf; - - /** Auxiliary DB info. - * The information here is mostly static/read-only. There is - * only a single copy of this record in the environment. - */ -typedef struct MDB_dbx { - MDB_val md_name; /**< name of the database */ - MDB_cmp_func *md_cmp; /**< function for comparing keys */ - MDB_cmp_func *md_dcmp; /**< function for comparing data items */ - MDB_rel_func *md_rel; /**< user relocate function */ - void *md_relctx; /**< user-provided context for md_rel */ -} MDB_dbx; - - /** A database transaction. - * Every operation requires a transaction handle. - */ -struct MDB_txn { - MDB_txn *mt_parent; /**< parent of a nested txn */ - /** Nested txn under this txn, set together with flag #MDB_TXN_HAS_CHILD */ - MDB_txn *mt_child; - pgno_t mt_next_pgno; /**< next unallocated page */ -#ifdef MDB_VL32 - pgno_t mt_last_pgno; /**< last written page */ -#endif - /** The ID of this transaction. IDs are integers incrementing from 1. - * Only committed write transactions increment the ID. If a transaction - * aborts, the ID may be re-used by the next writer. - */ - txnid_t mt_txnid; - MDB_env *mt_env; /**< the DB environment */ - /** The list of pages that became unused during this transaction. - */ - MDB_IDL mt_free_pgs; - /** The list of loose pages that became unused and may be reused - * in this transaction, linked through #NEXT_LOOSE_PAGE(page). - */ - MDB_page *mt_loose_pgs; - /* #Number of loose pages (#mt_loose_pgs) */ - int mt_loose_count; - /** The sorted list of dirty pages we temporarily wrote to disk - * because the dirty list was full. page numbers in here are - * shifted left by 1, deleted slots have the LSB set. - */ - MDB_IDL mt_spill_pgs; - union { - /** For write txns: Modified pages. Sorted when not MDB_WRITEMAP. */ - MDB_ID2L dirty_list; - /** For read txns: This thread/txn's reader table slot, or NULL. */ - MDB_reader *reader; - } mt_u; - /** Array of records for each DB known in the environment. */ - MDB_dbx *mt_dbxs; - /** Array of MDB_db records for each known DB */ - MDB_db *mt_dbs; - /** Array of sequence numbers for each DB handle */ - unsigned int *mt_dbiseqs; -/** @defgroup mt_dbflag Transaction DB Flags - * @ingroup internal - * @{ - */ -#define DB_DIRTY 0x01 /**< DB was modified or is DUPSORT data */ -#define DB_STALE 0x02 /**< Named-DB record is older than txnID */ -#define DB_NEW 0x04 /**< Named-DB handle opened in this txn */ -#define DB_VALID 0x08 /**< DB handle is valid, see also #MDB_VALID */ -#define DB_USRVALID 0x10 /**< As #DB_VALID, but not set for #FREE_DBI */ -/** @} */ - /** In write txns, array of cursors for each DB */ - MDB_cursor **mt_cursors; - /** Array of flags for each DB */ - unsigned char *mt_dbflags; -#ifdef MDB_VL32 - /** List of read-only pages (actually chunks) */ - MDB_ID3L mt_rpages; - /** We map chunks of 16 pages. Even though Windows uses 4KB pages, all - * mappings must begin on 64KB boundaries. So we round off all pgnos to - * a chunk boundary. We do the same on Linux for symmetry, and also to - * reduce the frequency of mmap/munmap calls. - */ -#define MDB_RPAGE_CHUNK 16 -#define MDB_TRPAGE_SIZE 4096 /**< size of #mt_rpages array of chunks */ -#define MDB_TRPAGE_MAX (MDB_TRPAGE_SIZE-1) /**< maximum chunk index */ - unsigned int mt_rpcheck; /**< threshold for reclaiming unref'd chunks */ -#endif - /** Number of DB records in use, or 0 when the txn is finished. - * This number only ever increments until the txn finishes; we - * don't decrement it when individual DB handles are closed. - */ - MDB_dbi mt_numdbs; - -/** @defgroup mdb_txn Transaction Flags - * @ingroup internal - * @{ - */ - /** #mdb_txn_begin() flags */ -#define MDB_TXN_BEGIN_FLAGS (MDB_NOMETASYNC|MDB_NOSYNC|MDB_RDONLY) -#define MDB_TXN_NOMETASYNC MDB_NOMETASYNC /**< don't sync meta for this txn on commit */ -#define MDB_TXN_NOSYNC MDB_NOSYNC /**< don't sync this txn on commit */ -#define MDB_TXN_RDONLY MDB_RDONLY /**< read-only transaction */ - /* internal txn flags */ -#define MDB_TXN_WRITEMAP MDB_WRITEMAP /**< copy of #MDB_env flag in writers */ -#define MDB_TXN_FINISHED 0x01 /**< txn is finished or never began */ -#define MDB_TXN_ERROR 0x02 /**< txn is unusable after an error */ -#define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */ -#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */ -#define MDB_TXN_HAS_CHILD 0x10 /**< txn has an #MDB_txn.%mt_child */ - /** most operations on the txn are currently illegal */ -#define MDB_TXN_BLOCKED (MDB_TXN_FINISHED|MDB_TXN_ERROR|MDB_TXN_HAS_CHILD) -/** @} */ - unsigned int mt_flags; /**< @ref mdb_txn */ - /** #dirty_list room: Array size - \#dirty pages visible to this txn. - * Includes ancestor txns' dirty pages not hidden by other txns' - * dirty/spilled pages. Thus commit(nested txn) has room to merge - * dirty_list into mt_parent after freeing hidden mt_parent pages. - */ - unsigned int mt_dirty_room; -}; - -/** Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. - * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to - * raise this on a 64 bit machine. - */ -#define CURSOR_STACK 32 - -struct MDB_xcursor; - - /** Cursors are used for all DB operations. - * A cursor holds a path of (page pointer, key index) from the DB - * root to a position in the DB, plus other state. #MDB_DUPSORT - * cursors include an xcursor to the current data item. Write txns - * track their cursors and keep them up to date when data moves. - * Exception: An xcursor's pointer to a #P_SUBP page can be stale. - * (A node with #F_DUPDATA but no #F_SUBDATA contains a subpage). - */ -struct MDB_cursor { - /** Next cursor on this DB in this txn */ - MDB_cursor *mc_next; - /** Backup of the original cursor if this cursor is a shadow */ - MDB_cursor *mc_backup; - /** Context used for databases with #MDB_DUPSORT, otherwise NULL */ - struct MDB_xcursor *mc_xcursor; - /** The transaction that owns this cursor */ - MDB_txn *mc_txn; - /** The database handle this cursor operates on */ - MDB_dbi mc_dbi; - /** The database record for this cursor */ - MDB_db *mc_db; - /** The database auxiliary record for this cursor */ - MDB_dbx *mc_dbx; - /** The @ref mt_dbflag for this database */ - unsigned char *mc_dbflag; - unsigned short mc_snum; /**< number of pushed pages */ - unsigned short mc_top; /**< index of top page, normally mc_snum-1 */ -/** @defgroup mdb_cursor Cursor Flags - * @ingroup internal - * Cursor state flags. - * @{ - */ -#define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */ -#define C_EOF 0x02 /**< No more data */ -#define C_SUB 0x04 /**< Cursor is a sub-cursor */ -#define C_DEL 0x08 /**< last op was a cursor_del */ -#define C_UNTRACK 0x40 /**< Un-track cursor when closing */ -#define C_WRITEMAP MDB_TXN_WRITEMAP /**< Copy of txn flag */ -/** Read-only cursor into the txn's original snapshot in the map. - * Set for read-only txns, and in #mdb_page_alloc() for #FREE_DBI when - * #MDB_DEVEL & 2. Only implements code which is necessary for this. - */ -#define C_ORIG_RDONLY MDB_TXN_RDONLY -/** @} */ - unsigned int mc_flags; /**< @ref mdb_cursor */ - MDB_page *mc_pg[CURSOR_STACK]; /**< stack of pushed pages */ - indx_t mc_ki[CURSOR_STACK]; /**< stack of page indices */ -#ifdef MDB_VL32 - MDB_page *mc_ovpg; /**< a referenced overflow page */ -#endif -}; - - /** Context for sorted-dup records. - * We could have gone to a fully recursive design, with arbitrarily - * deep nesting of sub-databases. But for now we only handle these - * levels - main DB, optional sub-DB, sorted-duplicate DB. - */ -typedef struct MDB_xcursor { - /** A sub-cursor for traversing the Dup DB */ - MDB_cursor mx_cursor; - /** The database record for this Dup DB */ - MDB_db mx_db; - /** The auxiliary DB record for this Dup DB */ - MDB_dbx mx_dbx; - /** The @ref mt_dbflag for this Dup DB */ - unsigned char mx_dbflag; -} MDB_xcursor; - - /** State of FreeDB old pages, stored in the MDB_env */ -typedef struct MDB_pgstate { - pgno_t *mf_pghead; /**< Reclaimed freeDB pages, or NULL before use */ - txnid_t mf_pglast; /**< ID of last used record, or 0 if !mf_pghead */ -} MDB_pgstate; - - /** The database environment. */ -struct MDB_env { - HANDLE me_fd; /**< The main data file */ - HANDLE me_lfd; /**< The lock file */ - HANDLE me_mfd; /**< just for writing the meta pages */ -#if defined(MDB_VL32) && defined(_WIN32) - HANDLE me_fmh; /**< File Mapping handle */ -#endif - /** Failed to update the meta page. Probably an I/O error. */ -#define MDB_FATAL_ERROR 0x80000000U - /** Some fields are initialized. */ -#define MDB_ENV_ACTIVE 0x20000000U - /** me_txkey is set */ -#define MDB_ENV_TXKEY 0x10000000U - /** fdatasync is unreliable */ -#define MDB_FSYNCONLY 0x08000000U - uint32_t me_flags; /**< @ref mdb_env */ - unsigned int me_psize; /**< DB page size, inited from me_os_psize */ - unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */ - unsigned int me_maxreaders; /**< size of the reader table */ - /** Max #MDB_txninfo.%mti_numreaders of interest to #mdb_env_close() */ - volatile int me_close_readers; - MDB_dbi me_numdbs; /**< number of DBs opened */ - MDB_dbi me_maxdbs; /**< size of the DB table */ - MDB_PID_T me_pid; /**< process ID of this env */ - char *me_path; /**< path to the DB files */ - char *me_map; /**< the memory map of the data file */ - MDB_txninfo *me_txns; /**< the memory map of the lock file or NULL */ - MDB_meta *me_metas[NUM_METAS]; /**< pointers to the two meta pages */ - void *me_pbuf; /**< scratch area for DUPSORT put() */ - MDB_txn *me_txn; /**< current write transaction */ - MDB_txn *me_txn0; /**< prealloc'd write transaction */ - mdb_size_t me_mapsize; /**< size of the data memory map */ - off64_t me_size; /**< current file size */ - pgno_t me_maxpg; /**< me_mapsize / me_psize */ - MDB_dbx *me_dbxs; /**< array of static DB info */ - uint16_t *me_dbflags; /**< array of flags from MDB_db.md_flags */ - unsigned int *me_dbiseqs; /**< array of dbi sequence numbers */ - pthread_key_t me_txkey; /**< thread-key for readers */ - txnid_t me_pgoldest; /**< ID of oldest reader last time we looked */ - MDB_pgstate me_pgstate; /**< state of old pages from freeDB */ -# define me_pglast me_pgstate.mf_pglast -# define me_pghead me_pgstate.mf_pghead - MDB_page *me_dpages; /**< list of malloc'd blocks for re-use */ - /** IDL of pages that became unused in a write txn */ - MDB_IDL me_free_pgs; - /** ID2L of pages written during a write txn. Length MDB_IDL_UM_SIZE. */ - MDB_ID2L me_dirty_list; - /** Max number of freelist items that can fit in a single overflow page */ - int me_maxfree_1pg; - /** Max size of a node on a page */ - unsigned int me_nodemax; -#if !(MDB_MAXKEYSIZE) - unsigned int me_maxkey; /**< max size of a key */ -#endif - int me_live_reader; /**< have liveness lock in reader table */ -#ifdef _WIN32 - int me_pidquery; /**< Used in OpenProcess */ -#endif -#ifdef MDB_USE_POSIX_MUTEX /* Posix mutexes reside in shared mem */ -# define me_rmutex me_txns->mti_rmutex /**< Shared reader lock */ -# define me_wmutex me_txns->mti_wmutex /**< Shared writer lock */ -#else - mdb_mutex_t me_rmutex; - mdb_mutex_t me_wmutex; -#endif -#ifdef MDB_VL32 - MDB_ID3L me_rpages; /**< like #mt_rpages, but global to env */ - pthread_mutex_t me_rpmutex; /**< control access to #me_rpages */ -#define MDB_ERPAGE_SIZE 16384 -#define MDB_ERPAGE_MAX (MDB_ERPAGE_SIZE-1) - unsigned int me_rpcheck; -#endif - void *me_userctx; /**< User-settable context */ - MDB_assert_func *me_assert_func; /**< Callback for assertion failures */ -}; - - /** Nested transaction */ -typedef struct MDB_ntxn { - MDB_txn mnt_txn; /**< the transaction */ - MDB_pgstate mnt_pgstate; /**< parent transaction's saved freestate */ -} MDB_ntxn; - - /** max number of pages to commit in one writev() call */ -#define MDB_COMMIT_PAGES 64 -#if defined(IOV_MAX) && IOV_MAX < MDB_COMMIT_PAGES -#undef MDB_COMMIT_PAGES -#define MDB_COMMIT_PAGES IOV_MAX -#endif - - /** max bytes to write in one call */ -#define MAX_WRITE (0x40000000U >> (sizeof(ssize_t) == 4)) - - /** Check \b txn and \b dbi arguments to a function */ -#define TXN_DBI_EXIST(txn, dbi, validity) \ - ((txn) && (dbi)<(txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity))) - - /** Check for misused \b dbi handles */ -#define TXN_DBI_CHANGED(txn, dbi) \ - ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi]) - -static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp); -static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp); -static int mdb_page_touch(MDB_cursor *mc); - -#define MDB_END_NAMES {"committed", "empty-commit", "abort", "reset", \ - "reset-tmp", "fail-begin", "fail-beginchild"} -enum { - /* mdb_txn_end operation number, for logging */ - MDB_END_COMMITTED, MDB_END_EMPTY_COMMIT, MDB_END_ABORT, MDB_END_RESET, - MDB_END_RESET_TMP, MDB_END_FAIL_BEGIN, MDB_END_FAIL_BEGINCHILD -}; -#define MDB_END_OPMASK 0x0F /**< mask for #mdb_txn_end() operation number */ -#define MDB_END_UPDATE 0x10 /**< update env state (DBIs) */ -#define MDB_END_FREE 0x20 /**< free txn unless it is #MDB_env.%me_txn0 */ -#define MDB_END_SLOT MDB_NOTLS /**< release any reader slot if #MDB_NOTLS */ -static void mdb_txn_end(MDB_txn *txn, unsigned mode); - -static int mdb_page_get(MDB_cursor *mc, pgno_t pgno, MDB_page **mp, int *lvl); -static int mdb_page_search_root(MDB_cursor *mc, - MDB_val *key, int modify); -#define MDB_PS_MODIFY 1 -#define MDB_PS_ROOTONLY 2 -#define MDB_PS_FIRST 4 -#define MDB_PS_LAST 8 -static int mdb_page_search(MDB_cursor *mc, - MDB_val *key, int flags); -static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst); - -#define MDB_SPLIT_REPLACE MDB_APPENDDUP /**< newkey is not new */ -static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, - pgno_t newpgno, unsigned int nflags); - -static int mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta); -static MDB_meta *mdb_env_pick_meta(const MDB_env *env); -static int mdb_env_write_meta(MDB_txn *txn); -#ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */ -# define mdb_env_close0(env, excl) mdb_env_close1(env) -#endif -static void mdb_env_close0(MDB_env *env, int excl); - -static MDB_node *mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp); -static int mdb_node_add(MDB_cursor *mc, indx_t indx, - MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags); -static void mdb_node_del(MDB_cursor *mc, int ksize); -static void mdb_node_shrink(MDB_page *mp, indx_t indx); -static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft); -static int mdb_node_read(MDB_cursor *mc, MDB_node *leaf, MDB_val *data); -static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data); -static size_t mdb_branch_size(MDB_env *env, MDB_val *key); - -static int mdb_rebalance(MDB_cursor *mc); -static int mdb_update_key(MDB_cursor *mc, MDB_val *key); - -static void mdb_cursor_pop(MDB_cursor *mc); -static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp); - -static int mdb_cursor_del0(MDB_cursor *mc); -static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags); -static int mdb_cursor_sibling(MDB_cursor *mc, int move_right); -static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op); -static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op); -static int mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op, - int *exactp); -static int mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data); -static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data); - -static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx); -static void mdb_xcursor_init0(MDB_cursor *mc); -static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node); -static void mdb_xcursor_init2(MDB_cursor *mc, MDB_xcursor *src_mx, int force); - -static int mdb_drop0(MDB_cursor *mc, int subs); -static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi); -static int mdb_reader_check0(MDB_env *env, int rlocked, int *dead); - -/** @cond */ -static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long; -/** @endcond */ - -/** Compare two items pointing at size_t's of unknown alignment. */ -#ifdef MISALIGNED_OK -# define mdb_cmp_clong mdb_cmp_long -#else -# define mdb_cmp_clong mdb_cmp_cint -#endif - -#ifdef _WIN32 -static SECURITY_DESCRIPTOR mdb_null_sd; -static SECURITY_ATTRIBUTES mdb_all_sa; -static int mdb_sec_inited; - -static int utf8_to_utf16(const char *src, int srcsize, wchar_t **dst, int *dstsize); -#endif - -/** Return the library version info. */ -char * ESECT -mdb_version(int *major, int *minor, int *patch) -{ - if (major) *major = MDB_VERSION_MAJOR; - if (minor) *minor = MDB_VERSION_MINOR; - if (patch) *patch = MDB_VERSION_PATCH; - return MDB_VERSION_STRING; -} - -/** Table of descriptions for LMDB @ref errors */ -static char *const mdb_errstr[] = { - "MDB_KEYEXIST: Key/data pair already exists", - "MDB_NOTFOUND: No matching key/data pair found", - "MDB_PAGE_NOTFOUND: Requested page not found", - "MDB_CORRUPTED: Located page was wrong type", - "MDB_PANIC: Update of meta page failed or environment had fatal error", - "MDB_VERSION_MISMATCH: Database environment version mismatch", - "MDB_INVALID: File is not an LMDB file", - "MDB_MAP_FULL: Environment mapsize limit reached", - "MDB_DBS_FULL: Environment maxdbs limit reached", - "MDB_READERS_FULL: Environment maxreaders limit reached", - "MDB_TLS_FULL: Thread-local storage keys full - too many environments open", - "MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big", - "MDB_CURSOR_FULL: Internal error - cursor stack limit reached", - "MDB_PAGE_FULL: Internal error - page has no more space", - "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize", - "MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed", - "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot", - "MDB_BAD_TXN: Transaction must abort, has a child, or is invalid", - "MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size", - "MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly", -}; - -char * -mdb_strerror(int err) -{ -#ifdef _WIN32 - /** HACK: pad 4KB on stack over the buf. Return system msgs in buf. - * This works as long as no function between the call to mdb_strerror - * and the actual use of the message uses more than 4K of stack. - */ -#define MSGSIZE 1024 -#define PADSIZE 4096 - char buf[MSGSIZE+PADSIZE], *ptr = buf; -#endif - int i; - if (!err) - return ("Successful return: 0"); - - if (err >= MDB_KEYEXIST && err <= MDB_LAST_ERRCODE) { - i = err - MDB_KEYEXIST; - return mdb_errstr[i]; - } - -#ifdef _WIN32 - /* These are the C-runtime error codes we use. The comment indicates - * their numeric value, and the Win32 error they would correspond to - * if the error actually came from a Win32 API. A major mess, we should - * have used LMDB-specific error codes for everything. - */ - switch(err) { - case ENOENT: /* 2, FILE_NOT_FOUND */ - case EIO: /* 5, ACCESS_DENIED */ - case ENOMEM: /* 12, INVALID_ACCESS */ - case EACCES: /* 13, INVALID_DATA */ - case EBUSY: /* 16, CURRENT_DIRECTORY */ - case EINVAL: /* 22, BAD_COMMAND */ - case ENOSPC: /* 28, OUT_OF_PAPER */ - return strerror(err); - default: - ; - } - buf[0] = 0; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE); - return ptr; -#else - return strerror(err); -#endif -} - -/** assert(3) variant in cursor context */ -#define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr) -/** assert(3) variant in transaction context */ -#define mdb_tassert(txn, expr) mdb_assert0((txn)->mt_env, expr, #expr) -/** assert(3) variant in environment context */ -#define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr) - -#ifndef NDEBUG -# define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \ - mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__)) - -static void ESECT -mdb_assert_fail(MDB_env *env, const char *expr_txt, - const char *func, const char *file, int line) -{ - char buf[400]; - sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()", - file, line, expr_txt, func); - if (env->me_assert_func) - env->me_assert_func(env, buf); - fprintf(stderr, "%s\n", buf); - abort(); -} -#else -# define mdb_assert0(env, expr, expr_txt) ((void) 0) -#endif /* NDEBUG */ - -#if MDB_DEBUG -/** Return the page number of \b mp which may be sub-page, for debug output */ -static pgno_t -mdb_dbg_pgno(MDB_page *mp) -{ - pgno_t ret; - COPY_PGNO(ret, mp->mp_pgno); - return ret; -} - -/** Display a key in hexadecimal and return the address of the result. - * @param[in] key the key to display - * @param[in] buf the buffer to write into. Should always be #DKBUF. - * @return The key in hexadecimal form. - */ -char * -mdb_dkey(MDB_val *key, char *buf) -{ - char *ptr = buf; - unsigned char *c = key->mv_data; - unsigned int i; - - if (!key) - return ""; - - if (key->mv_size > DKBUF_MAXKEYSIZE) - return "MDB_MAXKEYSIZE"; - /* may want to make this a dynamic check: if the key is mostly - * printable characters, print it as-is instead of converting to hex. - */ -#if 1 - buf[0] = '\0'; - for (i=0; imv_size; i++) - ptr += sprintf(ptr, "%02x", *c++); -#else - sprintf(buf, "%.*s", key->mv_size, key->mv_data); -#endif - return buf; -} - -static const char * -mdb_leafnode_type(MDB_node *n) -{ - static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}}; - return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" : - tp[F_ISSET(n->mn_flags, F_DUPDATA)][F_ISSET(n->mn_flags, F_SUBDATA)]; -} - -/** Display all the keys in the page. */ -void -mdb_page_list(MDB_page *mp) -{ - pgno_t pgno = mdb_dbg_pgno(mp); - const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : ""; - MDB_node *node; - unsigned int i, nkeys, nsize, total = 0; - MDB_val key; - DKBUF; - - switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) { - case P_BRANCH: type = "Branch page"; break; - case P_LEAF: type = "Leaf page"; break; - case P_LEAF|P_SUBP: type = "Sub-page"; break; - case P_LEAF|P_LEAF2: type = "LEAF2 page"; break; - case P_LEAF|P_LEAF2|P_SUBP: type = "LEAF2 sub-page"; break; - case P_OVERFLOW: - fprintf(stderr, "Overflow page %"Y"u pages %u%s\n", - pgno, mp->mp_pages, state); - return; - case P_META: - fprintf(stderr, "Meta-page %"Y"u txnid %"Y"u\n", - pgno, ((MDB_meta *)METADATA(mp))->mm_txnid); - return; - default: - fprintf(stderr, "Bad page %"Y"u flags 0x%u\n", pgno, mp->mp_flags); - return; - } - - nkeys = NUMKEYS(mp); - fprintf(stderr, "%s %"Y"u numkeys %d%s\n", type, pgno, nkeys, state); - - for (i=0; imp_pad; - key.mv_data = LEAF2KEY(mp, i, nsize); - total += nsize; - fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key)); - continue; - } - node = NODEPTR(mp, i); - key.mv_size = node->mn_ksize; - key.mv_data = node->mn_data; - nsize = NODESIZE + key.mv_size; - if (IS_BRANCH(mp)) { - fprintf(stderr, "key %d: page %"Y"u, %s\n", i, NODEPGNO(node), - DKEY(&key)); - total += nsize; - } else { - if (F_ISSET(node->mn_flags, F_BIGDATA)) - nsize += sizeof(pgno_t); - else - nsize += NODEDSZ(node); - total += nsize; - nsize += sizeof(indx_t); - fprintf(stderr, "key %d: nsize %d, %s%s\n", - i, nsize, DKEY(&key), mdb_leafnode_type(node)); - } - total = EVEN(total); - } - fprintf(stderr, "Total: header %d + contents %d + unused %d\n", - IS_LEAF2(mp) ? PAGEHDRSZ : PAGEBASE + mp->mp_lower, total, SIZELEFT(mp)); -} - -void -mdb_cursor_chk(MDB_cursor *mc) -{ - unsigned int i; - MDB_node *node; - MDB_page *mp; - - if (!mc->mc_snum || !(mc->mc_flags & C_INITIALIZED)) return; - for (i=0; imc_top; i++) { - mp = mc->mc_pg[i]; - node = NODEPTR(mp, mc->mc_ki[i]); - if (NODEPGNO(node) != mc->mc_pg[i+1]->mp_pgno) - printf("oops!\n"); - } - if (mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i])) - printf("ack!\n"); - if (mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { - node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) && - mc->mc_xcursor->mx_cursor.mc_pg[0] != NODEDATA(node)) { - printf("blah!\n"); - } - } -} -#endif - -#if (MDB_DEBUG) > 2 -/** Count all the pages in each DB and in the freelist - * and make sure it matches the actual number of pages - * being used. - * All named DBs must be open for a correct count. - */ -static void mdb_audit(MDB_txn *txn) -{ - MDB_cursor mc; - MDB_val key, data; - MDB_ID freecount, count; - MDB_dbi i; - int rc; - - freecount = 0; - mdb_cursor_init(&mc, txn, FREE_DBI, NULL); - while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0) - freecount += *(MDB_ID *)data.mv_data; - mdb_tassert(txn, rc == MDB_NOTFOUND); - - count = 0; - for (i = 0; imt_numdbs; i++) { - MDB_xcursor mx; - if (!(txn->mt_dbflags[i] & DB_VALID)) - continue; - mdb_cursor_init(&mc, txn, i, &mx); - if (txn->mt_dbs[i].md_root == P_INVALID) - continue; - count += txn->mt_dbs[i].md_branch_pages + - txn->mt_dbs[i].md_leaf_pages + - txn->mt_dbs[i].md_overflow_pages; - if (txn->mt_dbs[i].md_flags & MDB_DUPSORT) { - rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST); - for (; rc == MDB_SUCCESS; rc = mdb_cursor_sibling(&mc, 1)) { - unsigned j; - MDB_page *mp; - mp = mc.mc_pg[mc.mc_top]; - for (j=0; jmn_flags & F_SUBDATA) { - MDB_db db; - memcpy(&db, NODEDATA(leaf), sizeof(db)); - count += db.md_branch_pages + db.md_leaf_pages + - db.md_overflow_pages; - } - } - } - mdb_tassert(txn, rc == MDB_NOTFOUND); - } - } - if (freecount + count + NUM_METAS != txn->mt_next_pgno) { - fprintf(stderr, "audit: %"Y"u freecount: %"Y"u count: %"Y"u total: %"Y"u next_pgno: %"Y"u\n", - txn->mt_txnid, freecount, count+NUM_METAS, - freecount+count+NUM_METAS, txn->mt_next_pgno); - } -} -#endif - -int -mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) -{ - return txn->mt_dbxs[dbi].md_cmp(a, b); -} - -int -mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b) -{ - MDB_cmp_func *dcmp = txn->mt_dbxs[dbi].md_dcmp; -#if UINT_MAX < SIZE_MAX || defined(MDB_VL32) - if (dcmp == mdb_cmp_int && a->mv_size == sizeof(mdb_size_t)) - dcmp = mdb_cmp_clong; -#endif - return dcmp(a, b); -} - -/** Allocate memory for a page. - * Re-use old malloc'd pages first for singletons, otherwise just malloc. - */ -static MDB_page * -mdb_page_malloc(MDB_txn *txn, unsigned num) -{ - MDB_env *env = txn->mt_env; - MDB_page *ret = env->me_dpages; - size_t psize = env->me_psize, sz = psize, off; - /* For ! #MDB_NOMEMINIT, psize counts how much to init. - * For a single page alloc, we init everything after the page header. - * For multi-page, we init the final page; if the caller needed that - * many pages they will be filling in at least up to the last page. - */ - if (num == 1) { - if (ret) { - VGMEMP_ALLOC(env, ret, sz); - VGMEMP_DEFINED(ret, sizeof(ret->mp_next)); - env->me_dpages = ret->mp_next; - return ret; - } - psize -= off = PAGEHDRSZ; - } else { - sz *= num; - off = sz - psize; - } - if ((ret = malloc(sz)) != NULL) { - VGMEMP_ALLOC(env, ret, sz); - if (!(env->me_flags & MDB_NOMEMINIT)) { - memset((char *)ret + off, 0, psize); - ret->mp_pad = 0; - } - } else { - txn->mt_flags |= MDB_TXN_ERROR; - } - return ret; -} -/** Free a single page. - * Saves single pages to a list, for future reuse. - * (This is not used for multi-page overflow pages.) - */ -static void -mdb_page_free(MDB_env *env, MDB_page *mp) -{ - mp->mp_next = env->me_dpages; - VGMEMP_FREE(env, mp); - env->me_dpages = mp; -} - -/** Free a dirty page */ -static void -mdb_dpage_free(MDB_env *env, MDB_page *dp) -{ - if (!IS_OVERFLOW(dp) || dp->mp_pages == 1) { - mdb_page_free(env, dp); - } else { - /* large pages just get freed directly */ - VGMEMP_FREE(env, dp); - free(dp); - } -} - -/** Return all dirty pages to dpage list */ -static void -mdb_dlist_free(MDB_txn *txn) -{ - MDB_env *env = txn->mt_env; - MDB_ID2L dl = txn->mt_u.dirty_list; - unsigned i, n = dl[0].mid; - - for (i = 1; i <= n; i++) { - mdb_dpage_free(env, dl[i].mptr); - } - dl[0].mid = 0; -} - -#ifdef MDB_VL32 -static void -mdb_page_unref(MDB_txn *txn, MDB_page *mp) -{ - pgno_t pgno; - MDB_ID3L tl = txn->mt_rpages; - unsigned x, rem; - if (mp->mp_flags & (P_SUBP|P_DIRTY)) - return; - rem = mp->mp_pgno & (MDB_RPAGE_CHUNK-1); - pgno = mp->mp_pgno ^ rem; - x = mdb_mid3l_search(tl, pgno); - if (x != tl[0].mid && tl[x+1].mid == mp->mp_pgno) - x++; - if (tl[x].mref) - tl[x].mref--; -} -#define MDB_PAGE_UNREF(txn, mp) mdb_page_unref(txn, mp) - -static void -mdb_cursor_unref(MDB_cursor *mc) -{ - int i; - if (mc->mc_txn->mt_rpages[0].mid) { - if (!mc->mc_snum || !mc->mc_pg[0] || IS_SUBP(mc->mc_pg[0])) - return; - for (i=0; imc_snum; i++) - mdb_page_unref(mc->mc_txn, mc->mc_pg[i]); - if (mc->mc_ovpg) { - mdb_page_unref(mc->mc_txn, mc->mc_ovpg); - mc->mc_ovpg = 0; - } - } - mc->mc_snum = mc->mc_top = 0; - mc->mc_pg[0] = NULL; - mc->mc_flags &= ~C_INITIALIZED; -} -#else -#define MDB_PAGE_UNREF(txn, mp) -#endif /* MDB_VL32 */ - -/** Loosen or free a single page. - * Saves single pages to a list for future reuse - * in this same txn. It has been pulled from the freeDB - * and already resides on the dirty list, but has been - * deleted. Use these pages first before pulling again - * from the freeDB. - * - * If the page wasn't dirtied in this txn, just add it - * to this txn's free list. - */ -static int -mdb_page_loose(MDB_cursor *mc, MDB_page *mp) -{ - int loose = 0; - pgno_t pgno = mp->mp_pgno; - MDB_txn *txn = mc->mc_txn; - - if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) { - if (txn->mt_parent) { - MDB_ID2 *dl = txn->mt_u.dirty_list; - /* If txn has a parent, make sure the page is in our - * dirty list. - */ - if (dl[0].mid) { - unsigned x = mdb_mid2l_search(dl, pgno); - if (x <= dl[0].mid && dl[x].mid == pgno) { - if (mp != dl[x].mptr) { /* bad cursor? */ - mc->mc_flags &= ~(C_INITIALIZED|C_EOF); - txn->mt_flags |= MDB_TXN_ERROR; - return MDB_CORRUPTED; - } - /* ok, it's ours */ - loose = 1; - } - } - } else { - /* no parent txn, so it's just ours */ - loose = 1; - } - } - if (loose) { - DPRINTF(("loosen db %d page %"Y"u", DDBI(mc), - mp->mp_pgno)); - NEXT_LOOSE_PAGE(mp) = txn->mt_loose_pgs; - txn->mt_loose_pgs = mp; - txn->mt_loose_count++; - mp->mp_flags |= P_LOOSE; - } else { - int rc = mdb_midl_append(&txn->mt_free_pgs, pgno); - if (rc) - return rc; - } - - return MDB_SUCCESS; -} - -/** Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn. - * @param[in] mc A cursor handle for the current operation. - * @param[in] pflags Flags of the pages to update: - * P_DIRTY to set P_KEEP, P_DIRTY|P_KEEP to clear it. - * @param[in] all No shortcuts. Needed except after a full #mdb_page_flush(). - * @return 0 on success, non-zero on failure. - */ -static int -mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all) -{ - enum { Mask = P_SUBP|P_DIRTY|P_LOOSE|P_KEEP }; - MDB_txn *txn = mc->mc_txn; - MDB_cursor *m3, *m0 = mc; - MDB_xcursor *mx; - MDB_page *dp, *mp; - MDB_node *leaf; - unsigned i, j; - int rc = MDB_SUCCESS, level; - - /* Mark pages seen by cursors */ - if (mc->mc_flags & C_UNTRACK) - mc = NULL; /* will find mc in mt_cursors */ - for (i = txn->mt_numdbs;; mc = txn->mt_cursors[--i]) { - for (; mc; mc=mc->mc_next) { - if (!(mc->mc_flags & C_INITIALIZED)) - continue; - for (m3 = mc;; m3 = &mx->mx_cursor) { - mp = NULL; - for (j=0; jmc_snum; j++) { - mp = m3->mc_pg[j]; - if ((mp->mp_flags & Mask) == pflags) - mp->mp_flags ^= P_KEEP; - } - mx = m3->mc_xcursor; - /* Proceed to mx if it is at a sub-database */ - if (! (mx && (mx->mx_cursor.mc_flags & C_INITIALIZED))) - break; - if (! (mp && (mp->mp_flags & P_LEAF))) - break; - leaf = NODEPTR(mp, m3->mc_ki[j-1]); - if (!(leaf->mn_flags & F_SUBDATA)) - break; - } - } - if (i == 0) - break; - } - - if (all) { - /* Mark dirty root pages */ - for (i=0; imt_numdbs; i++) { - if (txn->mt_dbflags[i] & DB_DIRTY) { - pgno_t pgno = txn->mt_dbs[i].md_root; - if (pgno == P_INVALID) - continue; - if ((rc = mdb_page_get(m0, pgno, &dp, &level)) != MDB_SUCCESS) - break; - if ((dp->mp_flags & Mask) == pflags && level <= 1) - dp->mp_flags ^= P_KEEP; - } - } - } - - return rc; -} - -static int mdb_page_flush(MDB_txn *txn, int keep); - -/** Spill pages from the dirty list back to disk. - * This is intended to prevent running into #MDB_TXN_FULL situations, - * but note that they may still occur in a few cases: - * 1) our estimate of the txn size could be too small. Currently this - * seems unlikely, except with a large number of #MDB_MULTIPLE items. - * 2) child txns may run out of space if their parents dirtied a - * lot of pages and never spilled them. TODO: we probably should do - * a preemptive spill during #mdb_txn_begin() of a child txn, if - * the parent's dirty_room is below a given threshold. - * - * Otherwise, if not using nested txns, it is expected that apps will - * not run into #MDB_TXN_FULL any more. The pages are flushed to disk - * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared. - * If the txn never references them again, they can be left alone. - * If the txn only reads them, they can be used without any fuss. - * If the txn writes them again, they can be dirtied immediately without - * going thru all of the work of #mdb_page_touch(). Such references are - * handled by #mdb_page_unspill(). - * - * Also note, we never spill DB root pages, nor pages of active cursors, - * because we'll need these back again soon anyway. And in nested txns, - * we can't spill a page in a child txn if it was already spilled in a - * parent txn. That would alter the parent txns' data even though - * the child hasn't committed yet, and we'd have no way to undo it if - * the child aborted. - * - * @param[in] m0 cursor A cursor handle identifying the transaction and - * database for which we are checking space. - * @param[in] key For a put operation, the key being stored. - * @param[in] data For a put operation, the data being stored. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data) -{ - MDB_txn *txn = m0->mc_txn; - MDB_page *dp; - MDB_ID2L dl = txn->mt_u.dirty_list; - unsigned int i, j, need; - int rc; - - if (m0->mc_flags & C_SUB) - return MDB_SUCCESS; - - /* Estimate how much space this op will take */ - i = m0->mc_db->md_depth; - /* Named DBs also dirty the main DB */ - if (m0->mc_dbi >= CORE_DBS) - i += txn->mt_dbs[MAIN_DBI].md_depth; - /* For puts, roughly factor in the key+data size */ - if (key) - i += (LEAFSIZE(key, data) + txn->mt_env->me_psize) / txn->mt_env->me_psize; - i += i; /* double it for good measure */ - need = i; - - if (txn->mt_dirty_room > i) - return MDB_SUCCESS; - - if (!txn->mt_spill_pgs) { - txn->mt_spill_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX); - if (!txn->mt_spill_pgs) - return ENOMEM; - } else { - /* purge deleted slots */ - MDB_IDL sl = txn->mt_spill_pgs; - unsigned int num = sl[0]; - j=0; - for (i=1; i<=num; i++) { - if (!(sl[i] & 1)) - sl[++j] = sl[i]; - } - sl[0] = j; - } - - /* Preserve pages which may soon be dirtied again */ - if ((rc = mdb_pages_xkeep(m0, P_DIRTY, 1)) != MDB_SUCCESS) - goto done; - - /* Less aggressive spill - we originally spilled the entire dirty list, - * with a few exceptions for cursor pages and DB root pages. But this - * turns out to be a lot of wasted effort because in a large txn many - * of those pages will need to be used again. So now we spill only 1/8th - * of the dirty pages. Testing revealed this to be a good tradeoff, - * better than 1/2, 1/4, or 1/10. - */ - if (need < MDB_IDL_UM_MAX / 8) - need = MDB_IDL_UM_MAX / 8; - - /* Save the page IDs of all the pages we're flushing */ - /* flush from the tail forward, this saves a lot of shifting later on. */ - for (i=dl[0].mid; i && need; i--) { - MDB_ID pn = dl[i].mid << 1; - dp = dl[i].mptr; - if (dp->mp_flags & (P_LOOSE|P_KEEP)) - continue; - /* Can't spill twice, make sure it's not already in a parent's - * spill list. - */ - if (txn->mt_parent) { - MDB_txn *tx2; - for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) { - if (tx2->mt_spill_pgs) { - j = mdb_midl_search(tx2->mt_spill_pgs, pn); - if (j <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[j] == pn) { - dp->mp_flags |= P_KEEP; - break; - } - } - } - if (tx2) - continue; - } - if ((rc = mdb_midl_append(&txn->mt_spill_pgs, pn))) - goto done; - need--; - } - mdb_midl_sort(txn->mt_spill_pgs); - - /* Flush the spilled part of dirty list */ - if ((rc = mdb_page_flush(txn, i)) != MDB_SUCCESS) - goto done; - - /* Reset any dirty pages we kept that page_flush didn't see */ - rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i); - -done: - txn->mt_flags |= rc ? MDB_TXN_ERROR : MDB_TXN_SPILLS; - return rc; -} - -/** Find oldest txnid still referenced. Expects txn->mt_txnid > 0. */ -static txnid_t -mdb_find_oldest(MDB_txn *txn) -{ - int i; - txnid_t mr, oldest = txn->mt_txnid - 1; - if (txn->mt_env->me_txns) { - MDB_reader *r = txn->mt_env->me_txns->mti_readers; - for (i = txn->mt_env->me_txns->mti_numreaders; --i >= 0; ) { - if (r[i].mr_pid) { - mr = r[i].mr_txnid; - if (oldest > mr) - oldest = mr; - } - } - } - return oldest; -} - -/** Add a page to the txn's dirty list */ -static void -mdb_page_dirty(MDB_txn *txn, MDB_page *mp) -{ - MDB_ID2 mid; - int rc, (*insert)(MDB_ID2L, MDB_ID2 *); - - if (txn->mt_flags & MDB_TXN_WRITEMAP) { - insert = mdb_mid2l_append; - } else { - insert = mdb_mid2l_insert; - } - mid.mid = mp->mp_pgno; - mid.mptr = mp; - rc = insert(txn->mt_u.dirty_list, &mid); - mdb_tassert(txn, rc == 0); - txn->mt_dirty_room--; -} - -/** Allocate page numbers and memory for writing. Maintain me_pglast, - * me_pghead and mt_next_pgno. - * - * If there are free pages available from older transactions, they - * are re-used first. Otherwise allocate a new page at mt_next_pgno. - * Do not modify the freedB, just merge freeDB records into me_pghead[] - * and move me_pglast to say which records were consumed. Only this - * function can create me_pghead and move me_pglast/mt_next_pgno. - * When #MDB_DEVEL & 2, it is not affected by #mdb_freelist_save(): it - * then uses the transaction's original snapshot of the freeDB. - * @param[in] mc cursor A cursor handle identifying the transaction and - * database for which we are allocating. - * @param[in] num the number of pages to allocate. - * @param[out] mp Address of the allocated page(s). Requests for multiple pages - * will always be satisfied by a single contiguous chunk of memory. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp) -{ -#ifdef MDB_PARANOID /* Seems like we can ignore this now */ - /* Get at most more freeDB records once me_pghead - * has enough pages. If not enough, use new pages from the map. - * If and mc is updating the freeDB, only get new - * records if me_pghead is empty. Then the freelist cannot play - * catch-up with itself by growing while trying to save it. - */ - enum { Paranoid = 1, Max_retries = 500 }; -#else - enum { Paranoid = 0, Max_retries = INT_MAX /*infinite*/ }; -#endif - int rc, retry = num * 60; - MDB_txn *txn = mc->mc_txn; - MDB_env *env = txn->mt_env; - pgno_t pgno, *mop = env->me_pghead; - unsigned i, j, mop_len = mop ? mop[0] : 0, n2 = num-1; - MDB_page *np; - txnid_t oldest = 0, last; - MDB_cursor_op op; - MDB_cursor m2; - int found_old = 0; - - /* If there are any loose pages, just use them */ - if (num == 1 && txn->mt_loose_pgs) { - np = txn->mt_loose_pgs; - txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np); - txn->mt_loose_count--; - DPRINTF(("db %d use loose page %"Y"u", DDBI(mc), - np->mp_pgno)); - *mp = np; - return MDB_SUCCESS; - } - - *mp = NULL; - - /* If our dirty list is already full, we can't do anything */ - if (txn->mt_dirty_room == 0) { - rc = MDB_TXN_FULL; - goto fail; - } - - for (op = MDB_FIRST;; op = MDB_NEXT) { - MDB_val key, data; - MDB_node *leaf; - pgno_t *idl; - - /* Seek a big enough contiguous page range. Prefer - * pages at the tail, just truncating the list. - */ - if (mop_len > n2) { - i = mop_len; - do { - pgno = mop[i]; - if (mop[i-n2] == pgno+n2) - goto search_done; - } while (--i > n2); - if (--retry < 0) - break; - } - - if (op == MDB_FIRST) { /* 1st iteration */ - /* Prepare to fetch more and coalesce */ - last = env->me_pglast; - oldest = env->me_pgoldest; - mdb_cursor_init(&m2, txn, FREE_DBI, NULL); -#if (MDB_DEVEL) & 2 /* "& 2" so MDB_DEVEL=1 won't hide bugs breaking freeDB */ - /* Use original snapshot. TODO: Should need less care in code - * which modifies the database. Maybe we can delete some code? - */ - m2.mc_flags |= C_ORIG_RDONLY; - m2.mc_db = &env->me_metas[(txn->mt_txnid-1) & 1]->mm_dbs[FREE_DBI]; - m2.mc_dbflag = (unsigned char *)""; /* probably unnecessary */ -#endif - if (last) { - op = MDB_SET_RANGE; - key.mv_data = &last; /* will look up last+1 */ - key.mv_size = sizeof(last); - } - if (Paranoid && mc->mc_dbi == FREE_DBI) - retry = -1; - } - if (Paranoid && retry < 0 && mop_len) - break; - - last++; - /* Do not fetch more if the record will be too recent */ - if (oldest <= last) { - if (!found_old) { - oldest = mdb_find_oldest(txn); - env->me_pgoldest = oldest; - found_old = 1; - } - if (oldest <= last) - break; - } - rc = mdb_cursor_get(&m2, &key, NULL, op); - if (rc) { - if (rc == MDB_NOTFOUND) - break; - goto fail; - } - last = *(txnid_t*)key.mv_data; - if (oldest <= last) { - if (!found_old) { - oldest = mdb_find_oldest(txn); - env->me_pgoldest = oldest; - found_old = 1; - } - if (oldest <= last) - break; - } - np = m2.mc_pg[m2.mc_top]; - leaf = NODEPTR(np, m2.mc_ki[m2.mc_top]); - if ((rc = mdb_node_read(&m2, leaf, &data)) != MDB_SUCCESS) - return rc; - - idl = (MDB_ID *) data.mv_data; - i = idl[0]; - if (!mop) { - if (!(env->me_pghead = mop = mdb_midl_alloc(i))) { - rc = ENOMEM; - goto fail; - } - } else { - if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0) - goto fail; - mop = env->me_pghead; - } - env->me_pglast = last; -#if (MDB_DEBUG) > 1 - DPRINTF(("IDL read txn %"Y"u root %"Y"u num %u", - last, txn->mt_dbs[FREE_DBI].md_root, i)); - for (j = i; j; j--) - DPRINTF(("IDL %"Y"u", idl[j])); -#endif - /* Merge in descending sorted order */ - mdb_midl_xmerge(mop, idl); - mop_len = mop[0]; - } - - /* Use new pages from the map when nothing suitable in the freeDB */ - i = 0; - pgno = txn->mt_next_pgno; - if (pgno + num >= env->me_maxpg) { - DPUTS("DB size maxed out"); - rc = MDB_MAP_FULL; - goto fail; - } -#if defined(_WIN32) && !defined(MDB_VL32) - if (!(env->me_flags & MDB_RDONLY)) { - void *p; - p = (MDB_page *)(env->me_map + env->me_psize * pgno); - p = VirtualAlloc(p, env->me_psize * num, MEM_COMMIT, - (env->me_flags & MDB_WRITEMAP) ? PAGE_READWRITE: - PAGE_READONLY); - if (!p) { - DPUTS("VirtualAlloc failed"); - rc = ErrCode(); - goto fail; - } - } -#endif - -search_done: - if (env->me_flags & MDB_WRITEMAP) { - np = (MDB_page *)(env->me_map + env->me_psize * pgno); - } else { - if (!(np = mdb_page_malloc(txn, num))) { - rc = ENOMEM; - goto fail; - } - } - if (i) { - mop[0] = mop_len -= num; - /* Move any stragglers down */ - for (j = i-num; j < mop_len; ) - mop[++j] = mop[++i]; - } else { - txn->mt_next_pgno = pgno + num; - } - np->mp_pgno = pgno; - mdb_page_dirty(txn, np); - *mp = np; - - return MDB_SUCCESS; - -fail: - txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -/** Copy the used portions of a non-overflow page. - * @param[in] dst page to copy into - * @param[in] src page to copy from - * @param[in] psize size of a page - */ -static void -mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize) -{ - enum { Align = sizeof(pgno_t) }; - indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper-lower; - - /* If page isn't full, just copy the used portion. Adjust - * alignment so memcpy may copy words instead of bytes. - */ - if ((unused &= -Align) && !IS_LEAF2(src)) { - upper = (upper + PAGEBASE) & -Align; - memcpy(dst, src, (lower + PAGEBASE + (Align-1)) & -Align); - memcpy((pgno_t *)((char *)dst+upper), (pgno_t *)((char *)src+upper), - psize - upper); - } else { - memcpy(dst, src, psize - unused); - } -} - -/** Pull a page off the txn's spill list, if present. - * If a page being referenced was spilled to disk in this txn, bring - * it back and make it dirty/writable again. - * @param[in] txn the transaction handle. - * @param[in] mp the page being referenced. It must not be dirty. - * @param[out] ret the writable page, if any. ret is unchanged if - * mp wasn't spilled. - */ -static int -mdb_page_unspill(MDB_txn *txn, MDB_page *mp, MDB_page **ret) -{ - MDB_env *env = txn->mt_env; - const MDB_txn *tx2; - unsigned x; - pgno_t pgno = mp->mp_pgno, pn = pgno << 1; - - for (tx2 = txn; tx2; tx2=tx2->mt_parent) { - if (!tx2->mt_spill_pgs) - continue; - x = mdb_midl_search(tx2->mt_spill_pgs, pn); - if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) { - MDB_page *np; - int num; - if (txn->mt_dirty_room == 0) - return MDB_TXN_FULL; - if (IS_OVERFLOW(mp)) - num = mp->mp_pages; - else - num = 1; - if (env->me_flags & MDB_WRITEMAP) { - np = mp; - } else { - np = mdb_page_malloc(txn, num); - if (!np) - return ENOMEM; - if (num > 1) - memcpy(np, mp, num * env->me_psize); - else - mdb_page_copy(np, mp, env->me_psize); - } - if (tx2 == txn) { - /* If in current txn, this page is no longer spilled. - * If it happens to be the last page, truncate the spill list. - * Otherwise mark it as deleted by setting the LSB. - */ - if (x == txn->mt_spill_pgs[0]) - txn->mt_spill_pgs[0]--; - else - txn->mt_spill_pgs[x] |= 1; - } /* otherwise, if belonging to a parent txn, the - * page remains spilled until child commits - */ - - mdb_page_dirty(txn, np); - np->mp_flags |= P_DIRTY; - *ret = np; - break; - } - } - return MDB_SUCCESS; -} - -/** Touch a page: make it dirty and re-insert into tree with updated pgno. - * @param[in] mc cursor pointing to the page to be touched - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_touch(MDB_cursor *mc) -{ - MDB_page *mp = mc->mc_pg[mc->mc_top], *np; - MDB_txn *txn = mc->mc_txn; - MDB_cursor *m2, *m3; - pgno_t pgno; - int rc; - - if (!F_ISSET(mp->mp_flags, P_DIRTY)) { - if (txn->mt_flags & MDB_TXN_SPILLS) { - np = NULL; - rc = mdb_page_unspill(txn, mp, &np); - if (rc) - goto fail; - if (np) - goto done; - } - if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) || - (rc = mdb_page_alloc(mc, 1, &np))) - goto fail; - pgno = np->mp_pgno; - DPRINTF(("touched db %d page %"Y"u -> %"Y"u", DDBI(mc), - mp->mp_pgno, pgno)); - mdb_cassert(mc, mp->mp_pgno != pgno); - mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno); - /* Update the parent page, if any, to point to the new page */ - if (mc->mc_top) { - MDB_page *parent = mc->mc_pg[mc->mc_top-1]; - MDB_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top-1]); - SETPGNO(node, pgno); - } else { - mc->mc_db->md_root = pgno; - } - } else if (txn->mt_parent && !IS_SUBP(mp)) { - MDB_ID2 mid, *dl = txn->mt_u.dirty_list; - pgno = mp->mp_pgno; - /* If txn has a parent, make sure the page is in our - * dirty list. - */ - if (dl[0].mid) { - unsigned x = mdb_mid2l_search(dl, pgno); - if (x <= dl[0].mid && dl[x].mid == pgno) { - if (mp != dl[x].mptr) { /* bad cursor? */ - mc->mc_flags &= ~(C_INITIALIZED|C_EOF); - txn->mt_flags |= MDB_TXN_ERROR; - return MDB_CORRUPTED; - } - return 0; - } - } - mdb_cassert(mc, dl[0].mid < MDB_IDL_UM_MAX); - /* No - copy it */ - np = mdb_page_malloc(txn, 1); - if (!np) - return ENOMEM; - mid.mid = pgno; - mid.mptr = np; - rc = mdb_mid2l_insert(dl, &mid); - mdb_cassert(mc, rc == 0); - } else { - return 0; - } - - mdb_page_copy(np, mp, txn->mt_env->me_psize); - np->mp_pgno = pgno; - np->mp_flags |= P_DIRTY; - -done: - /* Adjust cursors pointing to mp */ - mc->mc_pg[mc->mc_top] = np; - m2 = txn->mt_cursors[mc->mc_dbi]; - if (mc->mc_flags & C_SUB) { - for (; m2; m2=m2->mc_next) { - m3 = &m2->mc_xcursor->mx_cursor; - if (m3->mc_snum < mc->mc_snum) continue; - if (m3->mc_pg[mc->mc_top] == mp) - m3->mc_pg[mc->mc_top] = np; - } - } else { - for (; m2; m2=m2->mc_next) { - if (m2->mc_snum < mc->mc_snum) continue; - if (m2 == mc) continue; - if (m2->mc_pg[mc->mc_top] == mp) { - m2->mc_pg[mc->mc_top] = np; - if ((mc->mc_db->md_flags & MDB_DUPSORT) && - IS_LEAF(np) && - (m2->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) - { - MDB_node *leaf = NODEPTR(np, m2->mc_ki[mc->mc_top]); - if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); - } - } - } - } - MDB_PAGE_UNREF(mc->mc_txn, mp); - return 0; - -fail: - txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -int -mdb_env_sync0(MDB_env *env, int force, pgno_t numpgs) -{ - int rc = 0; - if (env->me_flags & MDB_RDONLY) - return EACCES; - if (force || !F_ISSET(env->me_flags, MDB_NOSYNC)) { - if (env->me_flags & MDB_WRITEMAP) { - int flags = ((env->me_flags & MDB_MAPASYNC) && !force) - ? MS_ASYNC : MS_SYNC; - if (MDB_MSYNC(env->me_map, env->me_psize * numpgs, flags)) - rc = ErrCode(); -#ifdef _WIN32 - else if (flags == MS_SYNC && MDB_FDATASYNC(env->me_fd)) - rc = ErrCode(); -#endif - } else { -#ifdef BROKEN_FDATASYNC - if (env->me_flags & MDB_FSYNCONLY) { - if (fsync(env->me_fd)) - rc = ErrCode(); - } else -#endif - if (MDB_FDATASYNC(env->me_fd)) - rc = ErrCode(); - } - } - return rc; -} - -int -mdb_env_sync(MDB_env *env, int force) -{ - MDB_meta *m = mdb_env_pick_meta(env); - return mdb_env_sync0(env, force, m->mm_last_pg+1); -} - -/** Back up parent txn's cursors, then grab the originals for tracking */ -static int -mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst) -{ - MDB_cursor *mc, *bk; - MDB_xcursor *mx; - size_t size; - int i; - - for (i = src->mt_numdbs; --i >= 0; ) { - if ((mc = src->mt_cursors[i]) != NULL) { - size = sizeof(MDB_cursor); - if (mc->mc_xcursor) - size += sizeof(MDB_xcursor); - for (; mc; mc = bk->mc_next) { - bk = malloc(size); - if (!bk) - return ENOMEM; - *bk = *mc; - mc->mc_backup = bk; - mc->mc_db = &dst->mt_dbs[i]; - /* Kill pointers into src to reduce abuse: The - * user may not use mc until dst ends. But we need a valid - * txn pointer here for cursor fixups to keep working. - */ - mc->mc_txn = dst; - mc->mc_dbflag = &dst->mt_dbflags[i]; - if ((mx = mc->mc_xcursor) != NULL) { - *(MDB_xcursor *)(bk+1) = *mx; - mx->mx_cursor.mc_txn = dst; - } - mc->mc_next = dst->mt_cursors[i]; - dst->mt_cursors[i] = mc; - } - } - } - return MDB_SUCCESS; -} - -/** Close this write txn's cursors, give parent txn's cursors back to parent. - * @param[in] txn the transaction handle. - * @param[in] merge true to keep changes to parent cursors, false to revert. - * @return 0 on success, non-zero on failure. - */ -static void -mdb_cursors_close(MDB_txn *txn, unsigned merge) -{ - MDB_cursor **cursors = txn->mt_cursors, *mc, *next, *bk; - MDB_xcursor *mx; - int i; - - for (i = txn->mt_numdbs; --i >= 0; ) { - for (mc = cursors[i]; mc; mc = next) { - next = mc->mc_next; - if ((bk = mc->mc_backup) != NULL) { - if (merge) { - /* Commit changes to parent txn */ - mc->mc_next = bk->mc_next; - mc->mc_backup = bk->mc_backup; - mc->mc_txn = bk->mc_txn; - mc->mc_db = bk->mc_db; - mc->mc_dbflag = bk->mc_dbflag; - if ((mx = mc->mc_xcursor) != NULL) - mx->mx_cursor.mc_txn = bk->mc_txn; - } else { - /* Abort nested txn */ - *mc = *bk; - if ((mx = mc->mc_xcursor) != NULL) - *mx = *(MDB_xcursor *)(bk+1); - } - mc = bk; - } - /* Only malloced cursors are permanently tracked. */ - free(mc); - } - cursors[i] = NULL; - } -} - -#if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */ -enum Pidlock_op { - Pidset, Pidcheck -}; -#else -enum Pidlock_op { - Pidset = F_SETLK, Pidcheck = F_GETLK -}; -#endif - -/** Set or check a pid lock. Set returns 0 on success. - * Check returns 0 if the process is certainly dead, nonzero if it may - * be alive (the lock exists or an error happened so we do not know). - * - * On Windows Pidset is a no-op, we merely check for the existence - * of the process with the given pid. On POSIX we use a single byte - * lock on the lockfile, set at an offset equal to the pid. - */ -static int -mdb_reader_pid(MDB_env *env, enum Pidlock_op op, MDB_PID_T pid) -{ -#if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */ - int ret = 0; - HANDLE h; - if (op == Pidcheck) { - h = OpenProcess(env->me_pidquery, FALSE, pid); - /* No documented "no such process" code, but other program use this: */ - if (!h) - return ErrCode() != ERROR_INVALID_PARAMETER; - /* A process exists until all handles to it close. Has it exited? */ - ret = WaitForSingleObject(h, 0) != 0; - CloseHandle(h); - } - return ret; -#else - for (;;) { - int rc; - struct flock lock_info; - memset(&lock_info, 0, sizeof(lock_info)); - lock_info.l_type = F_WRLCK; - lock_info.l_whence = SEEK_SET; - lock_info.l_start = pid; - lock_info.l_len = 1; - if ((rc = fcntl(env->me_lfd, op, &lock_info)) == 0) { - if (op == F_GETLK && lock_info.l_type != F_UNLCK) - rc = -1; - } else if ((rc = ErrCode()) == EINTR) { - continue; - } - return rc; - } -#endif -} - -/** Common code for #mdb_txn_begin() and #mdb_txn_renew(). - * @param[in] txn the transaction handle to initialize - * @return 0 on success, non-zero on failure. - */ -static int -mdb_txn_renew0(MDB_txn *txn) -{ - MDB_env *env = txn->mt_env; - MDB_txninfo *ti = env->me_txns; - MDB_meta *meta; - unsigned int i, nr, flags = txn->mt_flags; - uint16_t x; - int rc, new_notls = 0; - - if ((flags &= MDB_TXN_RDONLY) != 0) { - if (!ti) { - meta = mdb_env_pick_meta(env); - txn->mt_txnid = meta->mm_txnid; - txn->mt_u.reader = NULL; - } else { - MDB_reader *r = (env->me_flags & MDB_NOTLS) ? txn->mt_u.reader : - pthread_getspecific(env->me_txkey); - if (r) { - if (r->mr_pid != env->me_pid || r->mr_txnid != (txnid_t)-1) - return MDB_BAD_RSLOT; - } else { - MDB_PID_T pid = env->me_pid; - MDB_THR_T tid = pthread_self(); - mdb_mutexref_t rmutex = env->me_rmutex; - - if (!env->me_live_reader) { - rc = mdb_reader_pid(env, Pidset, pid); - if (rc) - return rc; - env->me_live_reader = 1; - } - - if (LOCK_MUTEX(rc, env, rmutex)) - return rc; - nr = ti->mti_numreaders; - for (i=0; imti_readers[i].mr_pid == 0) - break; - if (i == env->me_maxreaders) { - UNLOCK_MUTEX(rmutex); - return MDB_READERS_FULL; - } - r = &ti->mti_readers[i]; - /* Claim the reader slot, carefully since other code - * uses the reader table un-mutexed: First reset the - * slot, next publish it in mti_numreaders. After - * that, it is safe for mdb_env_close() to touch it. - * When it will be closed, we can finally claim it. - */ - r->mr_pid = 0; - r->mr_txnid = (txnid_t)-1; - r->mr_tid = tid; - if (i == nr) - ti->mti_numreaders = ++nr; - env->me_close_readers = nr; - r->mr_pid = pid; - UNLOCK_MUTEX(rmutex); - - new_notls = (env->me_flags & MDB_NOTLS); - if (!new_notls && (rc=pthread_setspecific(env->me_txkey, r))) { - r->mr_pid = 0; - return rc; - } - } - do /* LY: Retry on a race, ITS#7970. */ - r->mr_txnid = ti->mti_txnid; - while(r->mr_txnid != ti->mti_txnid); - txn->mt_txnid = r->mr_txnid; - txn->mt_u.reader = r; - meta = env->me_metas[txn->mt_txnid & 1]; - } - - } else { - /* Not yet touching txn == env->me_txn0, it may be active */ - if (ti) { - if (LOCK_MUTEX(rc, env, env->me_wmutex)) - return rc; - txn->mt_txnid = ti->mti_txnid; - meta = env->me_metas[txn->mt_txnid & 1]; - } else { - meta = mdb_env_pick_meta(env); - txn->mt_txnid = meta->mm_txnid; - } - txn->mt_txnid++; -#if MDB_DEBUG - if (txn->mt_txnid == mdb_debug_start) - mdb_debug = 1; -#endif - txn->mt_child = NULL; - txn->mt_loose_pgs = NULL; - txn->mt_loose_count = 0; - txn->mt_dirty_room = MDB_IDL_UM_MAX; - txn->mt_u.dirty_list = env->me_dirty_list; - txn->mt_u.dirty_list[0].mid = 0; - txn->mt_free_pgs = env->me_free_pgs; - txn->mt_free_pgs[0] = 0; - txn->mt_spill_pgs = NULL; - env->me_txn = txn; - memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned int)); - } - - /* Copy the DB info and flags */ - memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDB_db)); - - /* Moved to here to avoid a data race in read TXNs */ - txn->mt_next_pgno = meta->mm_last_pg+1; -#ifdef MDB_VL32 - txn->mt_last_pgno = txn->mt_next_pgno - 1; -#endif - - txn->mt_flags = flags; - - /* Setup db info */ - txn->mt_numdbs = env->me_numdbs; - for (i=CORE_DBS; imt_numdbs; i++) { - x = env->me_dbflags[i]; - txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS; - txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_USRVALID|DB_STALE : 0; - } - txn->mt_dbflags[MAIN_DBI] = DB_VALID|DB_USRVALID; - txn->mt_dbflags[FREE_DBI] = DB_VALID; - - if (env->me_flags & MDB_FATAL_ERROR) { - DPUTS("environment had fatal error, must shutdown!"); - rc = MDB_PANIC; - } else if (env->me_maxpg < txn->mt_next_pgno) { - rc = MDB_MAP_RESIZED; - } else { - return MDB_SUCCESS; - } - mdb_txn_end(txn, new_notls /*0 or MDB_END_SLOT*/ | MDB_END_FAIL_BEGIN); - return rc; -} - -int -mdb_txn_renew(MDB_txn *txn) -{ - int rc; - - if (!txn || !F_ISSET(txn->mt_flags, MDB_TXN_RDONLY|MDB_TXN_FINISHED)) - return EINVAL; - - rc = mdb_txn_renew0(txn); - if (rc == MDB_SUCCESS) { - DPRINTF(("renew txn %"Y"u%c %p on mdbenv %p, root page %"Y"u", - txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', - (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root)); - } - return rc; -} - -int -mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret) -{ - MDB_txn *txn; - MDB_ntxn *ntxn; - int rc, size, tsize; - - flags &= MDB_TXN_BEGIN_FLAGS; - flags |= env->me_flags & MDB_WRITEMAP; - - if (env->me_flags & MDB_RDONLY & ~flags) /* write txn in RDONLY env */ - return EACCES; - - if (parent) { - /* Nested transactions: Max 1 child, write txns only, no writemap */ - flags |= parent->mt_flags; - if (flags & (MDB_RDONLY|MDB_WRITEMAP|MDB_TXN_BLOCKED)) { - return (parent->mt_flags & MDB_TXN_RDONLY) ? EINVAL : MDB_BAD_TXN; - } - /* Child txns save MDB_pgstate and use own copy of cursors */ - size = env->me_maxdbs * (sizeof(MDB_db)+sizeof(MDB_cursor *)+1); - size += tsize = sizeof(MDB_ntxn); - } else if (flags & MDB_RDONLY) { - size = env->me_maxdbs * (sizeof(MDB_db)+1); - size += tsize = sizeof(MDB_txn); - } else { - /* Reuse preallocated write txn. However, do not touch it until - * mdb_txn_renew0() succeeds, since it currently may be active. - */ - txn = env->me_txn0; - goto renew; - } - if ((txn = calloc(1, size)) == NULL) { - DPRINTF(("calloc: %s", strerror(errno))); - return ENOMEM; - } -#ifdef MDB_VL32 - if (!parent) { - txn->mt_rpages = malloc(MDB_TRPAGE_SIZE * sizeof(MDB_ID3)); - if (!txn->mt_rpages) { - free(txn); - return ENOMEM; - } - txn->mt_rpages[0].mid = 0; - txn->mt_rpcheck = MDB_TRPAGE_SIZE/2; - } -#endif - txn->mt_dbxs = env->me_dbxs; /* static */ - txn->mt_dbs = (MDB_db *) ((char *)txn + tsize); - txn->mt_dbflags = (unsigned char *)txn + size - env->me_maxdbs; - txn->mt_flags = flags; - txn->mt_env = env; - - if (parent) { - unsigned int i; - txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs); - txn->mt_dbiseqs = parent->mt_dbiseqs; - txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE); - if (!txn->mt_u.dirty_list || - !(txn->mt_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX))) - { - free(txn->mt_u.dirty_list); - free(txn); - return ENOMEM; - } - txn->mt_txnid = parent->mt_txnid; - txn->mt_dirty_room = parent->mt_dirty_room; - txn->mt_u.dirty_list[0].mid = 0; - txn->mt_spill_pgs = NULL; - txn->mt_next_pgno = parent->mt_next_pgno; - parent->mt_flags |= MDB_TXN_HAS_CHILD; - parent->mt_child = txn; - txn->mt_parent = parent; - txn->mt_numdbs = parent->mt_numdbs; -#ifdef MDB_VL32 - txn->mt_rpages = parent->mt_rpages; -#endif - memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db)); - /* Copy parent's mt_dbflags, but clear DB_NEW */ - for (i=0; imt_numdbs; i++) - txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~DB_NEW; - rc = 0; - ntxn = (MDB_ntxn *)txn; - ntxn->mnt_pgstate = env->me_pgstate; /* save parent me_pghead & co */ - if (env->me_pghead) { - size = MDB_IDL_SIZEOF(env->me_pghead); - env->me_pghead = mdb_midl_alloc(env->me_pghead[0]); - if (env->me_pghead) - memcpy(env->me_pghead, ntxn->mnt_pgstate.mf_pghead, size); - else - rc = ENOMEM; - } - if (!rc) - rc = mdb_cursor_shadow(parent, txn); - if (rc) - mdb_txn_end(txn, MDB_END_FAIL_BEGINCHILD); - } else { /* MDB_RDONLY */ - txn->mt_dbiseqs = env->me_dbiseqs; -renew: - rc = mdb_txn_renew0(txn); - } - if (rc) { - if (txn != env->me_txn0) { -#ifdef MDB_VL32 - free(txn->mt_rpages); -#endif - free(txn); - } - } else { - txn->mt_flags |= flags; /* could not change txn=me_txn0 earlier */ - *ret = txn; - DPRINTF(("begin txn %"Y"u%c %p on mdbenv %p, root page %"Y"u", - txn->mt_txnid, (flags & MDB_RDONLY) ? 'r' : 'w', - (void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root)); - } - - return rc; -} - -MDB_env * -mdb_txn_env(MDB_txn *txn) -{ - if(!txn) return NULL; - return txn->mt_env; -} - -mdb_size_t -mdb_txn_id(MDB_txn *txn) -{ - if(!txn) return 0; - return txn->mt_txnid; -} - -/** Export or close DBI handles opened in this txn. */ -static void -mdb_dbis_update(MDB_txn *txn, int keep) -{ - int i; - MDB_dbi n = txn->mt_numdbs; - MDB_env *env = txn->mt_env; - unsigned char *tdbflags = txn->mt_dbflags; - - for (i = n; --i >= CORE_DBS;) { - if (tdbflags[i] & DB_NEW) { - if (keep) { - env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID; - } else { - char *ptr = env->me_dbxs[i].md_name.mv_data; - if (ptr) { - env->me_dbxs[i].md_name.mv_data = NULL; - env->me_dbxs[i].md_name.mv_size = 0; - env->me_dbflags[i] = 0; - env->me_dbiseqs[i]++; - free(ptr); - } - } - } - } - if (keep && env->me_numdbs < n) - env->me_numdbs = n; -} - -/** End a transaction, except successful commit of a nested transaction. - * May be called twice for readonly txns: First reset it, then abort. - * @param[in] txn the transaction handle to end - * @param[in] mode why and how to end the transaction - */ -static void -mdb_txn_end(MDB_txn *txn, unsigned mode) -{ - MDB_env *env = txn->mt_env; -#if MDB_DEBUG - static const char *const names[] = MDB_END_NAMES; -#endif - - /* Export or close DBI handles opened in this txn */ - mdb_dbis_update(txn, mode & MDB_END_UPDATE); - - DPRINTF(("%s txn %"Y"u%c %p on mdbenv %p, root page %"Y"u", - names[mode & MDB_END_OPMASK], - txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', - (void *) txn, (void *)env, txn->mt_dbs[MAIN_DBI].md_root)); - - if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) { - if (txn->mt_u.reader) { - txn->mt_u.reader->mr_txnid = (txnid_t)-1; - if (!(env->me_flags & MDB_NOTLS)) { - txn->mt_u.reader = NULL; /* txn does not own reader */ - } else if (mode & MDB_END_SLOT) { - txn->mt_u.reader->mr_pid = 0; - txn->mt_u.reader = NULL; - } /* else txn owns the slot until it does MDB_END_SLOT */ - } - txn->mt_numdbs = 0; /* prevent further DBI activity */ - txn->mt_flags |= MDB_TXN_FINISHED; - - } else if (!F_ISSET(txn->mt_flags, MDB_TXN_FINISHED)) { - pgno_t *pghead = env->me_pghead; - - if (!(mode & MDB_END_UPDATE)) /* !(already closed cursors) */ - mdb_cursors_close(txn, 0); - if (!(env->me_flags & MDB_WRITEMAP)) { - mdb_dlist_free(txn); - } - - txn->mt_numdbs = 0; - txn->mt_flags = MDB_TXN_FINISHED; - - if (!txn->mt_parent) { - mdb_midl_shrink(&txn->mt_free_pgs); - env->me_free_pgs = txn->mt_free_pgs; - /* me_pgstate: */ - env->me_pghead = NULL; - env->me_pglast = 0; - - env->me_txn = NULL; - mode = 0; /* txn == env->me_txn0, do not free() it */ - - /* The writer mutex was locked in mdb_txn_begin. */ - if (env->me_txns) - UNLOCK_MUTEX(env->me_wmutex); - } else { - txn->mt_parent->mt_child = NULL; - txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD; - env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate; - mdb_midl_free(txn->mt_free_pgs); - mdb_midl_free(txn->mt_spill_pgs); - free(txn->mt_u.dirty_list); - } - - mdb_midl_free(pghead); - } -#ifdef MDB_VL32 - if (!txn->mt_parent) { - MDB_ID3L el = env->me_rpages, tl = txn->mt_rpages; - unsigned i, x, n = tl[0].mid; - pthread_mutex_lock(&env->me_rpmutex); - for (i = 1; i <= n; i++) { - if (tl[i].mid & (MDB_RPAGE_CHUNK-1)) { - /* tmp overflow pages that we didn't share in env */ - munmap(tl[i].mptr, tl[i].mcnt * env->me_psize); - } else { - x = mdb_mid3l_search(el, tl[i].mid); - if (tl[i].mptr == el[x].mptr) { - el[x].mref--; - } else { - /* another tmp overflow page */ - munmap(tl[i].mptr, tl[i].mcnt * env->me_psize); - } - } - } - pthread_mutex_unlock(&env->me_rpmutex); - tl[0].mid = 0; - if (mode & MDB_END_FREE) - free(tl); - } -#endif - if (mode & MDB_END_FREE) - free(txn); -} - -void -mdb_txn_reset(MDB_txn *txn) -{ - if (txn == NULL) - return; - - /* This call is only valid for read-only txns */ - if (!(txn->mt_flags & MDB_TXN_RDONLY)) - return; - - mdb_txn_end(txn, MDB_END_RESET); -} - -void -mdb_txn_abort(MDB_txn *txn) -{ - if (txn == NULL) - return; - - if (txn->mt_child) - mdb_txn_abort(txn->mt_child); - - mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE); -} - -/** Save the freelist as of this transaction to the freeDB. - * This changes the freelist. Keep trying until it stabilizes. - * - * When (MDB_DEVEL) & 2, the changes do not affect #mdb_page_alloc(), - * it then uses the transaction's original snapshot of the freeDB. - */ -static int -mdb_freelist_save(MDB_txn *txn) -{ - /* env->me_pghead[] can grow and shrink during this call. - * env->me_pglast and txn->mt_free_pgs[] can only grow. - * Page numbers cannot disappear from txn->mt_free_pgs[]. - */ - MDB_cursor mc; - MDB_env *env = txn->mt_env; - int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1; - txnid_t pglast = 0, head_id = 0; - pgno_t freecnt = 0, *free_pgs, *mop; - ssize_t head_room = 0, total_room = 0, mop_len, clean_limit; - - mdb_cursor_init(&mc, txn, FREE_DBI, NULL); - - if (env->me_pghead) { - /* Make sure first page of freeDB is touched and on freelist */ - rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST|MDB_PS_MODIFY); - if (rc && rc != MDB_NOTFOUND) - return rc; - } - - if (!env->me_pghead && txn->mt_loose_pgs) { - /* Put loose page numbers in mt_free_pgs, since - * we may be unable to return them to me_pghead. - */ - MDB_page *mp = txn->mt_loose_pgs; - if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0) - return rc; - for (; mp; mp = NEXT_LOOSE_PAGE(mp)) - mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno); - txn->mt_loose_pgs = NULL; - txn->mt_loose_count = 0; - } - - /* MDB_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */ - clean_limit = (env->me_flags & (MDB_NOMEMINIT|MDB_WRITEMAP)) - ? SSIZE_MAX : maxfree_1pg; - - for (;;) { - /* Come back here after each Put() in case freelist changed */ - MDB_val key, data; - pgno_t *pgs; - ssize_t j; - - /* If using records from freeDB which we have not yet - * deleted, delete them and any we reserved for me_pghead. - */ - while (pglast < env->me_pglast) { - rc = mdb_cursor_first(&mc, &key, NULL); - if (rc) - return rc; - pglast = head_id = *(txnid_t *)key.mv_data; - total_room = head_room = 0; - mdb_tassert(txn, pglast <= env->me_pglast); - rc = mdb_cursor_del(&mc, 0); - if (rc) - return rc; - } - - /* Save the IDL of pages freed by this txn, to a single record */ - if (freecnt < txn->mt_free_pgs[0]) { - if (!freecnt) { - /* Make sure last page of freeDB is touched and on freelist */ - rc = mdb_page_search(&mc, NULL, MDB_PS_LAST|MDB_PS_MODIFY); - if (rc && rc != MDB_NOTFOUND) - return rc; - } - free_pgs = txn->mt_free_pgs; - /* Write to last page of freeDB */ - key.mv_size = sizeof(txn->mt_txnid); - key.mv_data = &txn->mt_txnid; - do { - freecnt = free_pgs[0]; - data.mv_size = MDB_IDL_SIZEOF(free_pgs); - rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); - if (rc) - return rc; - /* Retry if mt_free_pgs[] grew during the Put() */ - free_pgs = txn->mt_free_pgs; - } while (freecnt < free_pgs[0]); - mdb_midl_sort(free_pgs); - memcpy(data.mv_data, free_pgs, data.mv_size); -#if (MDB_DEBUG) > 1 - { - unsigned int i = free_pgs[0]; - DPRINTF(("IDL write txn %"Y"u root %"Y"u num %u", - txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i)); - for (; i; i--) - DPRINTF(("IDL %"Y"u", free_pgs[i])); - } -#endif - continue; - } - - mop = env->me_pghead; - mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count; - - /* Reserve records for me_pghead[]. Split it if multi-page, - * to avoid searching freeDB for a page range. Use keys in - * range [1,me_pglast]: Smaller than txnid of oldest reader. - */ - if (total_room >= mop_len) { - if (total_room == mop_len || --more < 0) - break; - } else if (head_room >= maxfree_1pg && head_id > 1) { - /* Keep current record (overflow page), add a new one */ - head_id--; - head_room = 0; - } - /* (Re)write {key = head_id, IDL length = head_room} */ - total_room -= head_room; - head_room = mop_len - total_room; - if (head_room > maxfree_1pg && head_id > 1) { - /* Overflow multi-page for part of me_pghead */ - head_room /= head_id; /* amortize page sizes */ - head_room += maxfree_1pg - head_room % (maxfree_1pg + 1); - } else if (head_room < 0) { - /* Rare case, not bothering to delete this record */ - head_room = 0; - } - key.mv_size = sizeof(head_id); - key.mv_data = &head_id; - data.mv_size = (head_room + 1) * sizeof(pgno_t); - rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE); - if (rc) - return rc; - /* IDL is initially empty, zero out at least the length */ - pgs = (pgno_t *)data.mv_data; - j = head_room > clean_limit ? head_room : 0; - do { - pgs[j] = 0; - } while (--j >= 0); - total_room += head_room; - } - - /* Return loose page numbers to me_pghead, though usually none are - * left at this point. The pages themselves remain in dirty_list. - */ - if (txn->mt_loose_pgs) { - MDB_page *mp = txn->mt_loose_pgs; - unsigned count = txn->mt_loose_count; - MDB_IDL loose; - /* Room for loose pages + temp IDL with same */ - if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0) - return rc; - mop = env->me_pghead; - loose = mop + MDB_IDL_ALLOCLEN(mop) - count; - for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp)) - loose[ ++count ] = mp->mp_pgno; - loose[0] = count; - mdb_midl_sort(loose); - mdb_midl_xmerge(mop, loose); - txn->mt_loose_pgs = NULL; - txn->mt_loose_count = 0; - mop_len = mop[0]; - } - - /* Fill in the reserved me_pghead records */ - rc = MDB_SUCCESS; - if (mop_len) { - MDB_val key, data; - - mop += mop_len; - rc = mdb_cursor_first(&mc, &key, &data); - for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) { - txnid_t id = *(txnid_t *)key.mv_data; - ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1; - MDB_ID save; - - mdb_tassert(txn, len >= 0 && id <= env->me_pglast); - key.mv_data = &id; - if (len > mop_len) { - len = mop_len; - data.mv_size = (len + 1) * sizeof(MDB_ID); - } - data.mv_data = mop -= len; - save = mop[0]; - mop[0] = len; - rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT); - mop[0] = save; - if (rc || !(mop_len -= len)) - break; - } - } - return rc; -} - -/** Flush (some) dirty pages to the map, after clearing their dirty flag. - * @param[in] txn the transaction that's being committed - * @param[in] keep number of initial pages in dirty_list to keep dirty. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_flush(MDB_txn *txn, int keep) -{ - MDB_env *env = txn->mt_env; - MDB_ID2L dl = txn->mt_u.dirty_list; - unsigned psize = env->me_psize, j; - int i, pagecount = dl[0].mid, rc; - size_t size = 0; - off64_t pos = 0; - pgno_t pgno = 0; - MDB_page *dp = NULL; -#ifdef _WIN32 - OVERLAPPED ov; -#else - struct iovec iov[MDB_COMMIT_PAGES]; - ssize_t wsize = 0, wres; - off64_t wpos = 0, next_pos = 1; /* impossible pos, so pos != next_pos */ - int n = 0; -#endif - - j = i = keep; - - if (env->me_flags & MDB_WRITEMAP) { - /* Clear dirty flags */ - while (++i <= pagecount) { - dp = dl[i].mptr; - /* Don't flush this page yet */ - if (dp->mp_flags & (P_LOOSE|P_KEEP)) { - dp->mp_flags &= ~P_KEEP; - dl[++j] = dl[i]; - continue; - } - dp->mp_flags &= ~P_DIRTY; - } - goto done; - } - - /* Write the pages */ - for (;;) { - if (++i <= pagecount) { - dp = dl[i].mptr; - /* Don't flush this page yet */ - if (dp->mp_flags & (P_LOOSE|P_KEEP)) { - dp->mp_flags &= ~P_KEEP; - dl[i].mid = 0; - continue; - } - pgno = dl[i].mid; - /* clear dirty flag */ - dp->mp_flags &= ~P_DIRTY; - pos = pgno * psize; - size = psize; - if (IS_OVERFLOW(dp)) size *= dp->mp_pages; - } -#ifdef _WIN32 - else break; - - /* Windows actually supports scatter/gather I/O, but only on - * unbuffered file handles. Since we're relying on the OS page - * cache for all our data, that's self-defeating. So we just - * write pages one at a time. We use the ov structure to set - * the write offset, to at least save the overhead of a Seek - * system call. - */ - DPRINTF(("committing page %"Z"u", pgno)); - memset(&ov, 0, sizeof(ov)); - ov.Offset = pos & 0xffffffff; - ov.OffsetHigh = pos >> 16 >> 16; - if (!WriteFile(env->me_fd, dp, size, NULL, &ov)) { - rc = ErrCode(); - DPRINTF(("WriteFile: %d", rc)); - return rc; - } -#else - /* Write up to MDB_COMMIT_PAGES dirty pages at a time. */ - if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) { - if (n) { -retry_write: - /* Write previous page(s) */ -#ifdef MDB_USE_PWRITEV - wres = pwritev(env->me_fd, iov, n, wpos); -#else - if (n == 1) { - wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos); - } else { -retry_seek: - if (lseek(env->me_fd, wpos, SEEK_SET) == -1) { - rc = ErrCode(); - if (rc == EINTR) - goto retry_seek; - DPRINTF(("lseek: %s", strerror(rc))); - return rc; - } - wres = writev(env->me_fd, iov, n); - } -#endif - if (wres != wsize) { - if (wres < 0) { - rc = ErrCode(); - if (rc == EINTR) - goto retry_write; - DPRINTF(("Write error: %s", strerror(rc))); - } else { - rc = EIO; /* TODO: Use which error code? */ - DPUTS("short write, filesystem full?"); - } - return rc; - } - n = 0; - } - if (i > pagecount) - break; - wpos = pos; - wsize = 0; - } - DPRINTF(("committing page %"Y"u", pgno)); - next_pos = pos + size; - iov[n].iov_len = size; - iov[n].iov_base = (char *)dp; - wsize += size; - n++; -#endif /* _WIN32 */ - } -#ifdef MDB_VL32 - if (pgno > txn->mt_last_pgno) - txn->mt_last_pgno = pgno; -#endif - - /* MIPS has cache coherency issues, this is a no-op everywhere else - * Note: for any size >= on-chip cache size, entire on-chip cache is - * flushed. - */ - CACHEFLUSH(env->me_map, txn->mt_next_pgno * env->me_psize, DCACHE); - - for (i = keep; ++i <= pagecount; ) { - dp = dl[i].mptr; - /* This is a page we skipped above */ - if (!dl[i].mid) { - dl[++j] = dl[i]; - dl[j].mid = dp->mp_pgno; - continue; - } - mdb_dpage_free(env, dp); - } - -done: - i--; - txn->mt_dirty_room += i - j; - dl[0].mid = j; - return MDB_SUCCESS; -} - -static int ESECT mdb_env_share_locks(MDB_env *env, int *excl); - -int -mdb_txn_commit(MDB_txn *txn) -{ - int rc; - unsigned int i, end_mode; - MDB_env *env; - - if (txn == NULL) - return EINVAL; - - /* mdb_txn_end() mode for a commit which writes nothing */ - end_mode = MDB_END_EMPTY_COMMIT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE; - - if (txn->mt_child) { - rc = mdb_txn_commit(txn->mt_child); - if (rc) - goto fail; - } - - env = txn->mt_env; - - if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) { - goto done; - } - - if (txn->mt_flags & (MDB_TXN_FINISHED|MDB_TXN_ERROR)) { - DPUTS("txn has failed/finished, can't commit"); - if (txn->mt_parent) - txn->mt_parent->mt_flags |= MDB_TXN_ERROR; - rc = MDB_BAD_TXN; - goto fail; - } - - if (txn->mt_parent) { - MDB_txn *parent = txn->mt_parent; - MDB_page **lp; - MDB_ID2L dst, src; - MDB_IDL pspill; - unsigned x, y, len, ps_len; - - /* Append our free list to parent's */ - rc = mdb_midl_append_list(&parent->mt_free_pgs, txn->mt_free_pgs); - if (rc) - goto fail; - mdb_midl_free(txn->mt_free_pgs); - /* Failures after this must either undo the changes - * to the parent or set MDB_TXN_ERROR in the parent. - */ - - parent->mt_next_pgno = txn->mt_next_pgno; - parent->mt_flags = txn->mt_flags; - - /* Merge our cursors into parent's and close them */ - mdb_cursors_close(txn, 1); - - /* Update parent's DB table. */ - memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDB_db)); - parent->mt_numdbs = txn->mt_numdbs; - parent->mt_dbflags[FREE_DBI] = txn->mt_dbflags[FREE_DBI]; - parent->mt_dbflags[MAIN_DBI] = txn->mt_dbflags[MAIN_DBI]; - for (i=CORE_DBS; imt_numdbs; i++) { - /* preserve parent's DB_NEW status */ - x = parent->mt_dbflags[i] & DB_NEW; - parent->mt_dbflags[i] = txn->mt_dbflags[i] | x; - } - - dst = parent->mt_u.dirty_list; - src = txn->mt_u.dirty_list; - /* Remove anything in our dirty list from parent's spill list */ - if ((pspill = parent->mt_spill_pgs) && (ps_len = pspill[0])) { - x = y = ps_len; - pspill[0] = (pgno_t)-1; - /* Mark our dirty pages as deleted in parent spill list */ - for (i=0, len=src[0].mid; ++i <= len; ) { - MDB_ID pn = src[i].mid << 1; - while (pn > pspill[x]) - x--; - if (pn == pspill[x]) { - pspill[x] = 1; - y = --x; - } - } - /* Squash deleted pagenums if we deleted any */ - for (x=y; ++x <= ps_len; ) - if (!(pspill[x] & 1)) - pspill[++y] = pspill[x]; - pspill[0] = y; - } - - /* Remove anything in our spill list from parent's dirty list */ - if (txn->mt_spill_pgs && txn->mt_spill_pgs[0]) { - for (i=1; i<=txn->mt_spill_pgs[0]; i++) { - MDB_ID pn = txn->mt_spill_pgs[i]; - if (pn & 1) - continue; /* deleted spillpg */ - pn >>= 1; - y = mdb_mid2l_search(dst, pn); - if (y <= dst[0].mid && dst[y].mid == pn) { - free(dst[y].mptr); - while (y < dst[0].mid) { - dst[y] = dst[y+1]; - y++; - } - dst[0].mid--; - } - } - } - - /* Find len = length of merging our dirty list with parent's */ - x = dst[0].mid; - dst[0].mid = 0; /* simplify loops */ - if (parent->mt_parent) { - len = x + src[0].mid; - y = mdb_mid2l_search(src, dst[x].mid + 1) - 1; - for (i = x; y && i; y--) { - pgno_t yp = src[y].mid; - while (yp < dst[i].mid) - i--; - if (yp == dst[i].mid) { - i--; - len--; - } - } - } else { /* Simplify the above for single-ancestor case */ - len = MDB_IDL_UM_MAX - txn->mt_dirty_room; - } - /* Merge our dirty list with parent's */ - y = src[0].mid; - for (i = len; y; dst[i--] = src[y--]) { - pgno_t yp = src[y].mid; - while (yp < dst[x].mid) - dst[i--] = dst[x--]; - if (yp == dst[x].mid) - free(dst[x--].mptr); - } - mdb_tassert(txn, i == x); - dst[0].mid = len; - free(txn->mt_u.dirty_list); - parent->mt_dirty_room = txn->mt_dirty_room; - if (txn->mt_spill_pgs) { - if (parent->mt_spill_pgs) { - /* TODO: Prevent failure here, so parent does not fail */ - rc = mdb_midl_append_list(&parent->mt_spill_pgs, txn->mt_spill_pgs); - if (rc) - parent->mt_flags |= MDB_TXN_ERROR; - mdb_midl_free(txn->mt_spill_pgs); - mdb_midl_sort(parent->mt_spill_pgs); - } else { - parent->mt_spill_pgs = txn->mt_spill_pgs; - } - } - - /* Append our loose page list to parent's */ - for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(*lp)) - ; - *lp = txn->mt_loose_pgs; - parent->mt_loose_count += txn->mt_loose_count; - - parent->mt_child = NULL; - mdb_midl_free(((MDB_ntxn *)txn)->mnt_pgstate.mf_pghead); - free(txn); - return rc; - } - - if (txn != env->me_txn) { - DPUTS("attempt to commit unknown transaction"); - rc = EINVAL; - goto fail; - } - - mdb_cursors_close(txn, 0); - - if (!txn->mt_u.dirty_list[0].mid && - !(txn->mt_flags & (MDB_TXN_DIRTY|MDB_TXN_SPILLS))) - goto done; - - DPRINTF(("committing txn %"Y"u %p on mdbenv %p, root page %"Y"u", - txn->mt_txnid, (void*)txn, (void*)env, txn->mt_dbs[MAIN_DBI].md_root)); - - /* Update DB root pointers */ - if (txn->mt_numdbs > CORE_DBS) { - MDB_cursor mc; - MDB_dbi i; - MDB_val data; - data.mv_size = sizeof(MDB_db); - - mdb_cursor_init(&mc, txn, MAIN_DBI, NULL); - for (i = CORE_DBS; i < txn->mt_numdbs; i++) { - if (txn->mt_dbflags[i] & DB_DIRTY) { - if (TXN_DBI_CHANGED(txn, i)) { - rc = MDB_BAD_DBI; - goto fail; - } - data.mv_data = &txn->mt_dbs[i]; - rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data, - F_SUBDATA); - if (rc) - goto fail; - } - } - } - - rc = mdb_freelist_save(txn); - if (rc) - goto fail; - - mdb_midl_free(env->me_pghead); - env->me_pghead = NULL; - mdb_midl_shrink(&txn->mt_free_pgs); - -#if (MDB_DEBUG) > 2 - mdb_audit(txn); -#endif - - if ((rc = mdb_page_flush(txn, 0))) - goto fail; - if (!F_ISSET(txn->mt_flags, MDB_TXN_NOSYNC) && - (rc = mdb_env_sync0(env, 0, txn->mt_next_pgno))) - goto fail; - if ((rc = mdb_env_write_meta(txn))) - goto fail; - end_mode = MDB_END_COMMITTED|MDB_END_UPDATE; - if (env->me_flags & MDB_PREVSNAPSHOT) { - if (!(env->me_flags & MDB_NOLOCK)) { - int excl; - rc = mdb_env_share_locks(env, &excl); - if (rc) - goto fail; - } - env->me_flags ^= MDB_PREVSNAPSHOT; - } - -done: - mdb_txn_end(txn, end_mode); - return MDB_SUCCESS; - -fail: - mdb_txn_abort(txn); - return rc; -} - -/** Read the environment parameters of a DB environment before - * mapping it into memory. - * @param[in] env the environment handle - * @param[in] prev whether to read the backup meta page - * @param[out] meta address of where to store the meta information - * @return 0 on success, non-zero on failure. - */ -static int ESECT -mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta) -{ - MDB_metabuf pbuf; - MDB_page *p; - MDB_meta *m; - int i, rc, off; - enum { Size = sizeof(pbuf) }; - - /* We don't know the page size yet, so use a minimum value. - * Read both meta pages so we can use the latest one. - */ - - for (i=off=0; imm_psize) { -#ifdef _WIN32 - DWORD len; - OVERLAPPED ov; - memset(&ov, 0, sizeof(ov)); - ov.Offset = off; - rc = ReadFile(env->me_fd, &pbuf, Size, &len, &ov) ? (int)len : -1; - if (rc == -1 && ErrCode() == ERROR_HANDLE_EOF) - rc = 0; -#else - rc = pread(env->me_fd, &pbuf, Size, off); -#endif - if (rc != Size) { - if (rc == 0 && off == 0) - return ENOENT; - rc = rc < 0 ? (int) ErrCode() : MDB_INVALID; - DPRINTF(("read: %s", mdb_strerror(rc))); - return rc; - } - - p = (MDB_page *)&pbuf; - - if (!F_ISSET(p->mp_flags, P_META)) { - DPRINTF(("page %"Y"u not a meta page", p->mp_pgno)); - return MDB_INVALID; - } - - m = METADATA(p); - if (m->mm_magic != MDB_MAGIC) { - DPUTS("meta has invalid magic"); - return MDB_INVALID; - } - - if (m->mm_version != MDB_DATA_VERSION) { - DPRINTF(("database is version %u, expected version %u", - m->mm_version, MDB_DATA_VERSION)); - return MDB_VERSION_MISMATCH; - } - - if (off == 0 || (prev ? m->mm_txnid < meta->mm_txnid : m->mm_txnid > meta->mm_txnid)) - *meta = *m; - } - return 0; -} - -/** Fill in most of the zeroed #MDB_meta for an empty database environment */ -static void ESECT -mdb_env_init_meta0(MDB_env *env, MDB_meta *meta) -{ - meta->mm_magic = MDB_MAGIC; - meta->mm_version = MDB_DATA_VERSION; - meta->mm_mapsize = env->me_mapsize; - meta->mm_psize = env->me_psize; - meta->mm_last_pg = NUM_METAS-1; - meta->mm_flags = env->me_flags & 0xffff; - meta->mm_flags |= MDB_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */ - meta->mm_dbs[FREE_DBI].md_root = P_INVALID; - meta->mm_dbs[MAIN_DBI].md_root = P_INVALID; -} - -/** Write the environment parameters of a freshly created DB environment. - * @param[in] env the environment handle - * @param[in] meta the #MDB_meta to write - * @return 0 on success, non-zero on failure. - */ -static int ESECT -mdb_env_init_meta(MDB_env *env, MDB_meta *meta) -{ - MDB_page *p, *q; - int rc; - unsigned int psize; -#ifdef _WIN32 - DWORD len; - OVERLAPPED ov; - memset(&ov, 0, sizeof(ov)); -#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ - ov.Offset = pos; \ - rc = WriteFile(fd, ptr, size, &len, &ov); } while(0) -#else - int len; -#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \ - len = pwrite(fd, ptr, size, pos); \ - if (len == -1 && ErrCode() == EINTR) continue; \ - rc = (len >= 0); break; } while(1) -#endif - - DPUTS("writing new meta page"); - - psize = env->me_psize; - - p = calloc(NUM_METAS, psize); - if (!p) - return ENOMEM; - p->mp_pgno = 0; - p->mp_flags = P_META; - *(MDB_meta *)METADATA(p) = *meta; - - q = (MDB_page *)((char *)p + psize); - q->mp_pgno = 1; - q->mp_flags = P_META; - *(MDB_meta *)METADATA(q) = *meta; - - DO_PWRITE(rc, env->me_fd, p, psize * NUM_METAS, len, 0); - if (!rc) - rc = ErrCode(); - else if ((unsigned) len == psize * NUM_METAS) - rc = MDB_SUCCESS; - else - rc = ENOSPC; - free(p); - return rc; -} - -/** Update the environment info to commit a transaction. - * @param[in] txn the transaction that's being committed - * @return 0 on success, non-zero on failure. - */ -static int -mdb_env_write_meta(MDB_txn *txn) -{ - MDB_env *env; - MDB_meta meta, metab, *mp; - unsigned flags; - mdb_size_t mapsize; - off64_t off; - int rc, len, toggle; - char *ptr; - HANDLE mfd; -#ifdef _WIN32 - OVERLAPPED ov; -#else - int r2; -#endif - - toggle = txn->mt_txnid & 1; - DPRINTF(("writing meta page %d for root page %"Y"u", - toggle, txn->mt_dbs[MAIN_DBI].md_root)); - - env = txn->mt_env; - flags = txn->mt_flags | env->me_flags; - mp = env->me_metas[toggle]; - mapsize = env->me_metas[toggle ^ 1]->mm_mapsize; - /* Persist any increases of mapsize config */ - if (mapsize < env->me_mapsize) - mapsize = env->me_mapsize; - - if (flags & MDB_WRITEMAP) { - mp->mm_mapsize = mapsize; - mp->mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI]; - mp->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; - mp->mm_last_pg = txn->mt_next_pgno - 1; -#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) && /* TODO: portability */ \ - !(defined(__i386__) || defined(__x86_64__)) - /* LY: issue a memory barrier, if not x86. ITS#7969 */ - __sync_synchronize(); -#endif - mp->mm_txnid = txn->mt_txnid; - if (!(flags & (MDB_NOMETASYNC|MDB_NOSYNC))) { - unsigned meta_size = env->me_psize; - rc = (env->me_flags & MDB_MAPASYNC) ? MS_ASYNC : MS_SYNC; - ptr = (char *)mp - PAGEHDRSZ; -#ifndef _WIN32 /* POSIX msync() requires ptr = start of OS page */ - r2 = (ptr - env->me_map) & (env->me_os_psize - 1); - ptr -= r2; - meta_size += r2; -#endif - if (MDB_MSYNC(ptr, meta_size, rc)) { - rc = ErrCode(); - goto fail; - } - } - goto done; - } - metab.mm_txnid = mp->mm_txnid; - metab.mm_last_pg = mp->mm_last_pg; - - meta.mm_mapsize = mapsize; - meta.mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI]; - meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; - meta.mm_last_pg = txn->mt_next_pgno - 1; - meta.mm_txnid = txn->mt_txnid; - - off = offsetof(MDB_meta, mm_mapsize); - ptr = (char *)&meta + off; - len = sizeof(MDB_meta) - off; - off += (char *)mp - env->me_map; - - /* Write to the SYNC fd */ - mfd = (flags & (MDB_NOSYNC|MDB_NOMETASYNC)) ? env->me_fd : env->me_mfd; -#ifdef _WIN32 - { - memset(&ov, 0, sizeof(ov)); - ov.Offset = off; - if (!WriteFile(mfd, ptr, len, (DWORD *)&rc, &ov)) - rc = -1; - } -#else -retry_write: - rc = pwrite(mfd, ptr, len, off); -#endif - if (rc != len) { - rc = rc < 0 ? ErrCode() : EIO; -#ifndef _WIN32 - if (rc == EINTR) - goto retry_write; -#endif - DPUTS("write failed, disk error?"); - /* On a failure, the pagecache still contains the new data. - * Write some old data back, to prevent it from being used. - * Use the non-SYNC fd; we know it will fail anyway. - */ - meta.mm_last_pg = metab.mm_last_pg; - meta.mm_txnid = metab.mm_txnid; -#ifdef _WIN32 - memset(&ov, 0, sizeof(ov)); - ov.Offset = off; - WriteFile(env->me_fd, ptr, len, NULL, &ov); -#else - r2 = pwrite(env->me_fd, ptr, len, off); - (void)r2; /* Silence warnings. We don't care about pwrite's return value */ -#endif -fail: - env->me_flags |= MDB_FATAL_ERROR; - return rc; - } - /* MIPS has cache coherency issues, this is a no-op everywhere else */ - CACHEFLUSH(env->me_map + off, len, DCACHE); -done: - /* Memory ordering issues are irrelevant; since the entire writer - * is wrapped by wmutex, all of these changes will become visible - * after the wmutex is unlocked. Since the DB is multi-version, - * readers will get consistent data regardless of how fresh or - * how stale their view of these values is. - */ - if (env->me_txns) - env->me_txns->mti_txnid = txn->mt_txnid; - - return MDB_SUCCESS; -} - -/** Check both meta pages to see which one is newer. - * @param[in] env the environment handle - * @return newest #MDB_meta. - */ -static MDB_meta * -mdb_env_pick_meta(const MDB_env *env) -{ - MDB_meta *const *metas = env->me_metas; - return metas[ (metas[0]->mm_txnid < metas[1]->mm_txnid) ^ - ((env->me_flags & MDB_PREVSNAPSHOT) != 0) ]; -} - -int ESECT -mdb_env_create(MDB_env **env) -{ - MDB_env *e; - - e = calloc(1, sizeof(MDB_env)); - if (!e) - return ENOMEM; - - e->me_maxreaders = DEFAULT_READERS; - e->me_maxdbs = e->me_numdbs = CORE_DBS; - e->me_fd = INVALID_HANDLE_VALUE; - e->me_lfd = INVALID_HANDLE_VALUE; - e->me_mfd = INVALID_HANDLE_VALUE; -#ifdef MDB_USE_POSIX_SEM - e->me_rmutex = SEM_FAILED; - e->me_wmutex = SEM_FAILED; -#elif defined MDB_USE_SYSV_SEM - e->me_rmutex->semid = -1; - e->me_wmutex->semid = -1; -#endif - e->me_pid = getpid(); - GET_PAGESIZE(e->me_os_psize); - VGMEMP_CREATE(e,0,0); - *env = e; - return MDB_SUCCESS; -} - -#ifdef _WIN32 -/** @brief Map a result from an NTAPI call to WIN32. */ -static DWORD -mdb_nt2win32(NTSTATUS st) -{ - OVERLAPPED o = {0}; - DWORD br; - o.Internal = st; - GetOverlappedResult(NULL, &o, &br, FALSE); - return GetLastError(); -} -#endif - -static int ESECT -mdb_env_map(MDB_env *env, void *addr) -{ - MDB_page *p; - unsigned int flags = env->me_flags; -#ifdef _WIN32 - int rc; - int access = SECTION_MAP_READ; - HANDLE mh; - void *map; - SIZE_T msize; - ULONG pageprot = PAGE_READONLY, secprot, alloctype; - - if (flags & MDB_WRITEMAP) { - access |= SECTION_MAP_WRITE; - pageprot = PAGE_READWRITE; - } - if (flags & MDB_RDONLY) { - secprot = PAGE_READONLY; - msize = 0; - alloctype = 0; - } else { - secprot = PAGE_READWRITE; - msize = env->me_mapsize; - alloctype = MEM_RESERVE; - } - - rc = NtCreateSection(&mh, access, NULL, NULL, secprot, SEC_RESERVE, env->me_fd); - if (rc) - return mdb_nt2win32(rc); - map = addr; -#ifdef MDB_VL32 - msize = NUM_METAS * env->me_psize; -#endif - rc = NtMapViewOfSection(mh, GetCurrentProcess(), &map, 0, 0, NULL, &msize, ViewUnmap, alloctype, pageprot); -#ifdef MDB_VL32 - env->me_fmh = mh; -#else - NtClose(mh); -#endif - if (rc) - return mdb_nt2win32(rc); - env->me_map = map; -#else -#ifdef MDB_VL32 - (void) flags; - env->me_map = mmap(addr, NUM_METAS * env->me_psize, PROT_READ, MAP_SHARED, - env->me_fd, 0); - if (env->me_map == MAP_FAILED) { - env->me_map = NULL; - return ErrCode(); - } -#else - int prot = PROT_READ; - if (flags & MDB_WRITEMAP) { - prot |= PROT_WRITE; - if (ftruncate(env->me_fd, env->me_mapsize) < 0) - return ErrCode(); - } - env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED, - env->me_fd, 0); - if (env->me_map == MAP_FAILED) { - env->me_map = NULL; - return ErrCode(); - } - - if (flags & MDB_NORDAHEAD) { - /* Turn off readahead. It's harmful when the DB is larger than RAM. */ -#ifdef MADV_RANDOM - madvise(env->me_map, env->me_mapsize, MADV_RANDOM); -#else -#ifdef POSIX_MADV_RANDOM - posix_madvise(env->me_map, env->me_mapsize, POSIX_MADV_RANDOM); -#endif /* POSIX_MADV_RANDOM */ -#endif /* MADV_RANDOM */ - } -#endif /* _WIN32 */ - - /* Can happen because the address argument to mmap() is just a - * hint. mmap() can pick another, e.g. if the range is in use. - * The MAP_FIXED flag would prevent that, but then mmap could - * instead unmap existing pages to make room for the new map. - */ - if (addr && env->me_map != addr) - return EBUSY; /* TODO: Make a new MDB_* error code? */ -#endif - - p = (MDB_page *)env->me_map; - env->me_metas[0] = METADATA(p); - env->me_metas[1] = (MDB_meta *)((char *)env->me_metas[0] + env->me_psize); - - return MDB_SUCCESS; -} - -int ESECT -mdb_env_set_mapsize(MDB_env *env, mdb_size_t size) -{ - /* If env is already open, caller is responsible for making - * sure there are no active txns. - */ - if (env->me_map) { - MDB_meta *meta; -#ifndef MDB_VL32 - void *old; - int rc; -#endif - if (env->me_txn) - return EINVAL; - meta = mdb_env_pick_meta(env); - if (!size) - size = meta->mm_mapsize; - { - /* Silently round up to minimum if the size is too small */ - mdb_size_t minsize = (meta->mm_last_pg + 1) * env->me_psize; - if (size < minsize) - size = minsize; - } -#ifndef MDB_VL32 - /* For MDB_VL32 this bit is a noop since we dynamically remap - * chunks of the DB anyway. - */ - munmap(env->me_map, env->me_mapsize); - env->me_mapsize = size; - old = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : NULL; - rc = mdb_env_map(env, old); - if (rc) - return rc; -#endif /* !MDB_VL32 */ - } - env->me_mapsize = size; - if (env->me_psize) - env->me_maxpg = env->me_mapsize / env->me_psize; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs) -{ - if (env->me_map) - return EINVAL; - env->me_maxdbs = dbs + CORE_DBS; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_set_maxreaders(MDB_env *env, unsigned int readers) -{ - if (env->me_map || readers < 1) - return EINVAL; - env->me_maxreaders = readers; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers) -{ - if (!env || !readers) - return EINVAL; - *readers = env->me_maxreaders; - return MDB_SUCCESS; -} - -static int ESECT -mdb_fsize(HANDLE fd, mdb_size_t *size) -{ -#ifdef _WIN32 - LARGE_INTEGER fsize; - - if (!GetFileSizeEx(fd, &fsize)) - return ErrCode(); - - *size = fsize.QuadPart; -#else - struct stat st; - - if (fstat(fd, &st)) - return ErrCode(); - - *size = st.st_size; -#endif - return MDB_SUCCESS; -} - -#ifdef BROKEN_FDATASYNC -#include -#include -#endif - -/** Further setup required for opening an LMDB environment - */ -static int ESECT -mdb_env_open2(MDB_env *env, int prev) -{ - unsigned int flags = env->me_flags; - int i, newenv = 0, rc; - MDB_meta meta; - -#ifdef _WIN32 - /* See if we should use QueryLimited */ - rc = GetVersion(); - if ((rc & 0xff) > 5) - env->me_pidquery = MDB_PROCESS_QUERY_LIMITED_INFORMATION; - else - env->me_pidquery = PROCESS_QUERY_INFORMATION; -#endif /* _WIN32 */ - -#ifdef BROKEN_FDATASYNC - /* ext3/ext4 fdatasync is broken on some older Linux kernels. - * https://lkml.org/lkml/2012/9/3/83 - * Kernels after 3.6-rc6 are known good. - * https://lkml.org/lkml/2012/9/10/556 - * See if the DB is on ext3/ext4, then check for new enough kernel - * Kernels 2.6.32.60, 2.6.34.15, 3.2.30, and 3.5.4 are also known - * to be patched. - */ - { - struct statfs st; - fstatfs(env->me_fd, &st); - while (st.f_type == 0xEF53) { - struct utsname uts; - int i; - uname(&uts); - if (uts.release[0] < '3') { - if (!strncmp(uts.release, "2.6.32.", 7)) { - i = atoi(uts.release+7); - if (i >= 60) - break; /* 2.6.32.60 and newer is OK */ - } else if (!strncmp(uts.release, "2.6.34.", 7)) { - i = atoi(uts.release+7); - if (i >= 15) - break; /* 2.6.34.15 and newer is OK */ - } - } else if (uts.release[0] == '3') { - i = atoi(uts.release+2); - if (i > 5) - break; /* 3.6 and newer is OK */ - if (i == 5) { - i = atoi(uts.release+4); - if (i >= 4) - break; /* 3.5.4 and newer is OK */ - } else if (i == 2) { - i = atoi(uts.release+4); - if (i >= 30) - break; /* 3.2.30 and newer is OK */ - } - } else { /* 4.x and newer is OK */ - break; - } - env->me_flags |= MDB_FSYNCONLY; - break; - } - } -#endif - - if ((i = mdb_env_read_header(env, prev, &meta)) != 0) { - if (i != ENOENT) - return i; - DPUTS("new mdbenv"); - newenv = 1; - env->me_psize = env->me_os_psize; - if (env->me_psize > MAX_PAGESIZE) - env->me_psize = MAX_PAGESIZE; - memset(&meta, 0, sizeof(meta)); - mdb_env_init_meta0(env, &meta); - meta.mm_mapsize = DEFAULT_MAPSIZE; - } else { - env->me_psize = meta.mm_psize; - } - - /* Was a mapsize configured? */ - if (!env->me_mapsize) { - env->me_mapsize = meta.mm_mapsize; - } - { - /* Make sure mapsize >= committed data size. Even when using - * mm_mapsize, which could be broken in old files (ITS#7789). - */ - mdb_size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize; - if (env->me_mapsize < minsize) - env->me_mapsize = minsize; - } - meta.mm_mapsize = env->me_mapsize; - - if (newenv && !(flags & MDB_FIXEDMAP)) { - /* mdb_env_map() may grow the datafile. Write the metapages - * first, so the file will be valid if initialization fails. - * Except with FIXEDMAP, since we do not yet know mm_address. - * We could fill in mm_address later, but then a different - * program might end up doing that - one with a memory layout - * and map address which does not suit the main program. - */ - rc = mdb_env_init_meta(env, &meta); - if (rc) - return rc; - newenv = 0; - } -#ifdef _WIN32 - /* For FIXEDMAP, make sure the file is non-empty before we attempt to map it */ - if (newenv) { - char dummy = 0; - DWORD len; - rc = WriteFile(env->me_fd, &dummy, 1, &len, NULL); - if (!rc) { - rc = ErrCode(); - return rc; - } - } -#endif - - rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL); - if (rc) - return rc; - - if (newenv) { - if (flags & MDB_FIXEDMAP) - meta.mm_address = env->me_map; - i = mdb_env_init_meta(env, &meta); - if (i != MDB_SUCCESS) { - return i; - } - } - - env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1; - env->me_nodemax = (((env->me_psize - PAGEHDRSZ) / MDB_MINKEYS) & -2) - - sizeof(indx_t); -#if !(MDB_MAXKEYSIZE) - env->me_maxkey = env->me_nodemax - (NODESIZE + sizeof(MDB_db)); -#endif - env->me_maxpg = env->me_mapsize / env->me_psize; - - if (env->me_txns) - env->me_txns->mti_txnid = meta.mm_txnid; - -#if MDB_DEBUG - { - MDB_meta *meta = mdb_env_pick_meta(env); - MDB_db *db = &meta->mm_dbs[MAIN_DBI]; - - DPRINTF(("opened database version %u, pagesize %u", - meta->mm_version, env->me_psize)); - DPRINTF(("using meta page %d", (int) (meta->mm_txnid & 1))); - DPRINTF(("depth: %u", db->md_depth)); - DPRINTF(("entries: %"Y"u", db->md_entries)); - DPRINTF(("branch pages: %"Y"u", db->md_branch_pages)); - DPRINTF(("leaf pages: %"Y"u", db->md_leaf_pages)); - DPRINTF(("overflow pages: %"Y"u", db->md_overflow_pages)); - DPRINTF(("root: %"Y"u", db->md_root)); - } -#endif - - return MDB_SUCCESS; -} - - -/** Release a reader thread's slot in the reader lock table. - * This function is called automatically when a thread exits. - * @param[in] ptr This points to the slot in the reader lock table. - */ -static void -mdb_env_reader_dest(void *ptr) -{ - MDB_reader *reader = ptr; - - reader->mr_pid = 0; -} - -#ifdef _WIN32 -/** Junk for arranging thread-specific callbacks on Windows. This is - * necessarily platform and compiler-specific. Windows supports up - * to 1088 keys. Let's assume nobody opens more than 64 environments - * in a single process, for now. They can override this if needed. - */ -#ifndef MAX_TLS_KEYS -#define MAX_TLS_KEYS 64 -#endif -static pthread_key_t mdb_tls_keys[MAX_TLS_KEYS]; -static int mdb_tls_nkeys; - -static void NTAPI mdb_tls_callback(PVOID module, DWORD reason, PVOID ptr) -{ - int i; - switch(reason) { - case DLL_PROCESS_ATTACH: break; - case DLL_THREAD_ATTACH: break; - case DLL_THREAD_DETACH: - for (i=0; ime_lfd, 0, 0, 1, 0, &ov)) { - rc = ErrCode(); - } else { - UnlockFile(env->me_lfd, 0, 0, 1, 0); - *excl = 0; - } - } -#else - { - struct flock lock_info; - /* The shared lock replaces the existing lock */ - memset((void *)&lock_info, 0, sizeof(lock_info)); - lock_info.l_type = F_RDLCK; - lock_info.l_whence = SEEK_SET; - lock_info.l_start = 0; - lock_info.l_len = 1; - while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) && - (rc = ErrCode()) == EINTR) ; - *excl = rc ? -1 : 0; /* error may mean we lost the lock */ - } -#endif - - return rc; -} - -/** Try to get exclusive lock, otherwise shared. - * Maintain *excl = -1: no/unknown lock, 0: shared, 1: exclusive. - */ -static int ESECT -mdb_env_excl_lock(MDB_env *env, int *excl) -{ - int rc = 0; -#ifdef _WIN32 - if (LockFile(env->me_lfd, 0, 0, 1, 0)) { - *excl = 1; - } else { - OVERLAPPED ov; - memset(&ov, 0, sizeof(ov)); - if (LockFileEx(env->me_lfd, 0, 0, 1, 0, &ov)) { - *excl = 0; - } else { - rc = ErrCode(); - } - } -#else - struct flock lock_info; - memset((void *)&lock_info, 0, sizeof(lock_info)); - lock_info.l_type = F_WRLCK; - lock_info.l_whence = SEEK_SET; - lock_info.l_start = 0; - lock_info.l_len = 1; - while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) && - (rc = ErrCode()) == EINTR) ; - if (!rc) { - *excl = 1; - } else -# ifndef MDB_USE_POSIX_MUTEX - if (*excl < 0) /* always true when MDB_USE_POSIX_MUTEX */ -# endif - { - lock_info.l_type = F_RDLCK; - while ((rc = fcntl(env->me_lfd, F_SETLKW, &lock_info)) && - (rc = ErrCode()) == EINTR) ; - if (rc == 0) - *excl = 0; - } -#endif - return rc; -} - -#ifdef MDB_USE_HASH -/* - * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code - * - * @(#) $Revision: 5.1 $ - * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $ - * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $ - * - * http://www.isthe.com/chongo/tech/comp/fnv/index.html - * - *** - * - * Please do not copyright this code. This code is in the public domain. - * - * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * By: - * chongo /\oo/\ - * http://www.isthe.com/chongo/ - * - * Share and Enjoy! :-) - */ - -typedef unsigned long long mdb_hash_t; -#define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL) - -/** perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer - * @param[in] val value to hash - * @param[in] hval initial value for hash - * @return 64 bit hash - * - * NOTE: To use the recommended 64 bit FNV-1a hash, use MDB_HASH_INIT as the - * hval arg on the first call. - */ -static mdb_hash_t -mdb_hash_val(MDB_val *val, mdb_hash_t hval) -{ - unsigned char *s = (unsigned char *)val->mv_data; /* unsigned string */ - unsigned char *end = s + val->mv_size; - /* - * FNV-1a hash each octet of the string - */ - while (s < end) { - /* xor the bottom with the current octet */ - hval ^= (mdb_hash_t)*s++; - - /* multiply by the 64 bit FNV magic prime mod 2^64 */ - hval += (hval << 1) + (hval << 4) + (hval << 5) + - (hval << 7) + (hval << 8) + (hval << 40); - } - /* return our new hash value */ - return hval; -} - -/** Hash the string and output the encoded hash. - * This uses modified RFC1924 Ascii85 encoding to accommodate systems with - * very short name limits. We don't care about the encoding being reversible, - * we just want to preserve as many bits of the input as possible in a - * small printable string. - * @param[in] str string to hash - * @param[out] encbuf an array of 11 chars to hold the hash - */ -static const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; - -static void ESECT -mdb_pack85(unsigned long l, char *out) -{ - int i; - - for (i=0; i<5; i++) { - *out++ = mdb_a85[l % 85]; - l /= 85; - } -} - -static void ESECT -mdb_hash_enc(MDB_val *val, char *encbuf) -{ - mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT); - - mdb_pack85(h, encbuf); - mdb_pack85(h>>32, encbuf+5); - encbuf[10] = '\0'; -} -#endif - -/** Open and/or initialize the lock region for the environment. - * @param[in] env The LMDB environment. - * @param[in] lpath The pathname of the file used for the lock region. - * @param[in] mode The Unix permissions for the file, if we create it. - * @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive - * @return 0 on success, non-zero on failure. - */ -static int ESECT -mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl) -{ -#ifdef _WIN32 -# define MDB_ERRCODE_ROFS ERROR_WRITE_PROTECT -#else -# define MDB_ERRCODE_ROFS EROFS -#ifdef O_CLOEXEC /* Linux: Open file and set FD_CLOEXEC atomically */ -# define MDB_CLOEXEC O_CLOEXEC -#else - int fdflags; -# define MDB_CLOEXEC 0 -#endif -#endif -#ifdef MDB_USE_SYSV_SEM - int semid; - union semun semu; -#endif - int rc; - off64_t size, rsize; - -#ifdef _WIN32 - wchar_t *wlpath; - rc = utf8_to_utf16(lpath, -1, &wlpath, NULL); - if (rc) - return rc; - env->me_lfd = CreateFileW(wlpath, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL); - free(wlpath); -#else - env->me_lfd = open(lpath, O_RDWR|O_CREAT|MDB_CLOEXEC, mode); -#endif - if (env->me_lfd == INVALID_HANDLE_VALUE) { - rc = ErrCode(); - if (rc == MDB_ERRCODE_ROFS && (env->me_flags & MDB_RDONLY)) { - return MDB_SUCCESS; - } - goto fail_errno; - } -#if ! ((MDB_CLOEXEC) || defined(_WIN32)) - /* Lose record locks when exec*() */ - if ((fdflags = fcntl(env->me_lfd, F_GETFD) | FD_CLOEXEC) >= 0) - fcntl(env->me_lfd, F_SETFD, fdflags); -#endif - - if (!(env->me_flags & MDB_NOTLS)) { - rc = pthread_key_create(&env->me_txkey, mdb_env_reader_dest); - if (rc) - goto fail; - env->me_flags |= MDB_ENV_TXKEY; -#ifdef _WIN32 - /* Windows TLS callbacks need help finding their TLS info. */ - if (mdb_tls_nkeys >= MAX_TLS_KEYS) { - rc = MDB_TLS_FULL; - goto fail; - } - mdb_tls_keys[mdb_tls_nkeys++] = env->me_txkey; -#endif - } - - /* Try to get exclusive lock. If we succeed, then - * nobody is using the lock region and we should initialize it. - */ - if ((rc = mdb_env_excl_lock(env, excl))) goto fail; - -#ifdef _WIN32 - size = GetFileSize(env->me_lfd, NULL); -#else - size = lseek(env->me_lfd, 0, SEEK_END); - if (size == -1) goto fail_errno; -#endif - rsize = (env->me_maxreaders-1) * sizeof(MDB_reader) + sizeof(MDB_txninfo); - if (size < rsize && *excl > 0) { -#ifdef _WIN32 - if (SetFilePointer(env->me_lfd, rsize, NULL, FILE_BEGIN) != (DWORD)rsize - || !SetEndOfFile(env->me_lfd)) - goto fail_errno; -#else - if (ftruncate(env->me_lfd, rsize) != 0) goto fail_errno; -#endif - } else { - rsize = size; - size = rsize - sizeof(MDB_txninfo); - env->me_maxreaders = size/sizeof(MDB_reader) + 1; - } - { -#ifdef _WIN32 - HANDLE mh; - mh = CreateFileMapping(env->me_lfd, NULL, PAGE_READWRITE, - 0, 0, NULL); - if (!mh) goto fail_errno; - env->me_txns = MapViewOfFileEx(mh, FILE_MAP_WRITE, 0, 0, rsize, NULL); - CloseHandle(mh); - if (!env->me_txns) goto fail_errno; -#else - void *m = mmap(NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED, - env->me_lfd, 0); - if (m == MAP_FAILED) goto fail_errno; - env->me_txns = m; -#endif - } - if (*excl > 0) { -#ifdef _WIN32 - BY_HANDLE_FILE_INFORMATION stbuf; - struct { - DWORD volume; - DWORD nhigh; - DWORD nlow; - } idbuf; - MDB_val val; - char encbuf[11]; - - if (!mdb_sec_inited) { - InitializeSecurityDescriptor(&mdb_null_sd, - SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&mdb_null_sd, TRUE, 0, FALSE); - mdb_all_sa.nLength = sizeof(SECURITY_ATTRIBUTES); - mdb_all_sa.bInheritHandle = FALSE; - mdb_all_sa.lpSecurityDescriptor = &mdb_null_sd; - mdb_sec_inited = 1; - } - if (!GetFileInformationByHandle(env->me_lfd, &stbuf)) goto fail_errno; - idbuf.volume = stbuf.dwVolumeSerialNumber; - idbuf.nhigh = stbuf.nFileIndexHigh; - idbuf.nlow = stbuf.nFileIndexLow; - val.mv_data = &idbuf; - val.mv_size = sizeof(idbuf); - mdb_hash_enc(&val, encbuf); - sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf); - sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf); - env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_rmname); - if (!env->me_rmutex) goto fail_errno; - env->me_wmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_wmname); - if (!env->me_wmutex) goto fail_errno; -#elif defined(MDB_USE_POSIX_SEM) - struct stat stbuf; - struct { - dev_t dev; - ino_t ino; - } idbuf; - MDB_val val; - char encbuf[11]; - -#if defined(__NetBSD__) -#define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */ -#endif - if (fstat(env->me_lfd, &stbuf)) goto fail_errno; - idbuf.dev = stbuf.st_dev; - idbuf.ino = stbuf.st_ino; - val.mv_data = &idbuf; - val.mv_size = sizeof(idbuf); - mdb_hash_enc(&val, encbuf); -#ifdef MDB_SHORT_SEMNAMES - encbuf[9] = '\0'; /* drop name from 15 chars to 14 chars */ -#endif - sprintf(env->me_txns->mti_rmname, "/MDBr%s", encbuf); - sprintf(env->me_txns->mti_wmname, "/MDBw%s", encbuf); - /* Clean up after a previous run, if needed: Try to - * remove both semaphores before doing anything else. - */ - sem_unlink(env->me_txns->mti_rmname); - sem_unlink(env->me_txns->mti_wmname); - env->me_rmutex = sem_open(env->me_txns->mti_rmname, - O_CREAT|O_EXCL, mode, 1); - if (env->me_rmutex == SEM_FAILED) goto fail_errno; - env->me_wmutex = sem_open(env->me_txns->mti_wmname, - O_CREAT|O_EXCL, mode, 1); - if (env->me_wmutex == SEM_FAILED) goto fail_errno; -#elif defined(MDB_USE_SYSV_SEM) - unsigned short vals[2] = {1, 1}; - key_t key = ftok(lpath, 'M'); - if (key == -1) - goto fail_errno; - semid = semget(key, 2, (mode & 0777) | IPC_CREAT); - if (semid < 0) - goto fail_errno; - semu.array = vals; - if (semctl(semid, 0, SETALL, semu) < 0) - goto fail_errno; - env->me_txns->mti_semid = semid; -#else /* MDB_USE_POSIX_MUTEX: */ - pthread_mutexattr_t mattr; - - if ((rc = pthread_mutexattr_init(&mattr)) - || (rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) -#ifdef MDB_ROBUST_SUPPORTED - || (rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST)) -#endif - || (rc = pthread_mutex_init(env->me_txns->mti_rmutex, &mattr)) - || (rc = pthread_mutex_init(env->me_txns->mti_wmutex, &mattr))) - goto fail; - pthread_mutexattr_destroy(&mattr); -#endif /* _WIN32 || ... */ - - env->me_txns->mti_magic = MDB_MAGIC; - env->me_txns->mti_format = MDB_LOCK_FORMAT; - env->me_txns->mti_txnid = 0; - env->me_txns->mti_numreaders = 0; - - } else { -#ifdef MDB_USE_SYSV_SEM - struct semid_ds buf; -#endif - if (env->me_txns->mti_magic != MDB_MAGIC) { - DPUTS("lock region has invalid magic"); - rc = MDB_INVALID; - goto fail; - } - if (env->me_txns->mti_format != MDB_LOCK_FORMAT) { - DPRINTF(("lock region has format+version 0x%x, expected 0x%x", - env->me_txns->mti_format, MDB_LOCK_FORMAT)); - rc = MDB_VERSION_MISMATCH; - goto fail; - } - rc = ErrCode(); - if (rc && rc != EACCES && rc != EAGAIN) { - goto fail; - } -#ifdef _WIN32 - env->me_rmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_rmname); - if (!env->me_rmutex) goto fail_errno; - env->me_wmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_wmname); - if (!env->me_wmutex) goto fail_errno; -#elif defined(MDB_USE_POSIX_SEM) - env->me_rmutex = sem_open(env->me_txns->mti_rmname, 0); - if (env->me_rmutex == SEM_FAILED) goto fail_errno; - env->me_wmutex = sem_open(env->me_txns->mti_wmname, 0); - if (env->me_wmutex == SEM_FAILED) goto fail_errno; -#elif defined(MDB_USE_SYSV_SEM) - semid = env->me_txns->mti_semid; - semu.buf = &buf; - /* check for read access */ - if (semctl(semid, 0, IPC_STAT, semu) < 0) - goto fail_errno; - /* check for write access */ - if (semctl(semid, 0, IPC_SET, semu) < 0) - goto fail_errno; -#endif - } -#ifdef MDB_USE_SYSV_SEM - env->me_rmutex->semid = semid; - env->me_wmutex->semid = semid; - env->me_rmutex->semnum = 0; - env->me_wmutex->semnum = 1; - env->me_rmutex->locked = &env->me_txns->mti_rlocked; - env->me_wmutex->locked = &env->me_txns->mti_wlocked; -#endif -#ifdef MDB_VL32 -#ifdef _WIN32 - env->me_rpmutex = CreateMutex(NULL, FALSE, NULL); -#else - pthread_mutex_init(&env->me_rpmutex, NULL); -#endif -#endif - - return MDB_SUCCESS; - -fail_errno: - rc = ErrCode(); -fail: - return rc; -} - - /** The name of the lock file in the DB environment */ -#define LOCKNAME "/lock.mdb" - /** The name of the data file in the DB environment */ -#define DATANAME "/data.mdb" - /** The suffix of the lock file when no subdir is used */ -#define LOCKSUFF "-lock" - /** Only a subset of the @ref mdb_env flags can be changed - * at runtime. Changing other flags requires closing the - * environment and re-opening it with the new flags. - */ -#define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT) -#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \ - MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD|MDB_PREVSNAPSHOT) - -#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS) -# error "Persistent DB flags & env flags overlap, but both go in mm_flags" -#endif - -int ESECT -mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode) -{ - int oflags, rc, len, excl = -1; - char *lpath, *dpath; -#ifdef _WIN32 - wchar_t *wpath; -#endif - - if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS))) - return EINVAL; - -#ifdef MDB_VL32 - if (flags & MDB_WRITEMAP) { - /* silently ignore WRITEMAP in 32 bit mode */ - flags ^= MDB_WRITEMAP; - } - if (flags & MDB_FIXEDMAP) { - /* cannot support FIXEDMAP */ - return EINVAL; - } -#endif - - len = strlen(path); - if (flags & MDB_NOSUBDIR) { - rc = len + sizeof(LOCKSUFF) + len + 1; - } else { - rc = len + sizeof(LOCKNAME) + len + sizeof(DATANAME); - } - lpath = malloc(rc); - if (!lpath) - return ENOMEM; - if (flags & MDB_NOSUBDIR) { - dpath = lpath + len + sizeof(LOCKSUFF); - sprintf(lpath, "%s" LOCKSUFF, path); - strcpy(dpath, path); - } else { - dpath = lpath + len + sizeof(LOCKNAME); - sprintf(lpath, "%s" LOCKNAME, path); - sprintf(dpath, "%s" DATANAME, path); - } - - rc = MDB_SUCCESS; - flags |= env->me_flags; - if (flags & MDB_RDONLY) { - /* silently ignore WRITEMAP when we're only getting read access */ - flags &= ~MDB_WRITEMAP; - } else { - if (!((env->me_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)) && - (env->me_dirty_list = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2))))) - rc = ENOMEM; - } -#ifdef MDB_VL32 - if (!rc) { - env->me_rpages = malloc(MDB_ERPAGE_SIZE * sizeof(MDB_ID3)); - if (!env->me_rpages) { - rc = ENOMEM; - goto leave; - } - env->me_rpages[0].mid = 0; - env->me_rpcheck = MDB_ERPAGE_SIZE/2; - } -#endif - env->me_flags = flags |= MDB_ENV_ACTIVE; - if (rc) - goto leave; - - env->me_path = strdup(path); - env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDB_dbx)); - env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t)); - env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(unsigned int)); - if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) { - rc = ENOMEM; - goto leave; - } - env->me_dbxs[FREE_DBI].md_cmp = mdb_cmp_long; /* aligned MDB_INTEGERKEY */ - - /* For RDONLY, get lockfile after we know datafile exists */ - if (!(flags & (MDB_RDONLY|MDB_NOLOCK))) { - rc = mdb_env_setup_locks(env, lpath, mode, &excl); - if (rc) - goto leave; - } - -#ifdef _WIN32 - if (F_ISSET(flags, MDB_RDONLY)) { - oflags = GENERIC_READ; - len = OPEN_EXISTING; - } else { - oflags = GENERIC_READ|GENERIC_WRITE; - len = OPEN_ALWAYS; - } - mode = FILE_ATTRIBUTE_NORMAL; - rc = utf8_to_utf16(dpath, -1, &wpath, NULL); - if (rc) - goto leave; - env->me_fd = CreateFileW(wpath, oflags, FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, len, mode, NULL); - free(wpath); -#else - if (F_ISSET(flags, MDB_RDONLY)) - oflags = O_RDONLY; - else - oflags = O_RDWR | O_CREAT; - - env->me_fd = open(dpath, oflags, mode); -#endif - if (env->me_fd == INVALID_HANDLE_VALUE) { - rc = ErrCode(); - goto leave; - } - - if ((flags & (MDB_RDONLY|MDB_NOLOCK)) == MDB_RDONLY) { - rc = mdb_env_setup_locks(env, lpath, mode, &excl); - if (rc) - goto leave; - if ((flags & MDB_PREVSNAPSHOT) && !excl) { - rc = EAGAIN; - goto leave; - } - } - - if ((rc = mdb_env_open2(env, flags & MDB_PREVSNAPSHOT)) == MDB_SUCCESS) { - if (flags & (MDB_RDONLY|MDB_WRITEMAP)) { - env->me_mfd = env->me_fd; - } else { - /* Synchronous fd for meta writes. Needed even with - * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset. - */ -#ifdef _WIN32 - len = OPEN_EXISTING; - rc = utf8_to_utf16(dpath, -1, &wpath, NULL); - if (rc) - goto leave; - env->me_mfd = CreateFileW(wpath, oflags, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, len, - mode | FILE_FLAG_WRITE_THROUGH, NULL); - free(wpath); -#else - oflags &= ~O_CREAT; - env->me_mfd = open(dpath, oflags | MDB_DSYNC, mode); -#endif - if (env->me_mfd == INVALID_HANDLE_VALUE) { - rc = ErrCode(); - goto leave; - } - } - DPRINTF(("opened dbenv %p", (void *) env)); - if (excl > 0 && !(flags & MDB_PREVSNAPSHOT)) { - rc = mdb_env_share_locks(env, &excl); - if (rc) - goto leave; - } - if (!(flags & MDB_RDONLY)) { - MDB_txn *txn; - int tsize = sizeof(MDB_txn), size = tsize + env->me_maxdbs * - (sizeof(MDB_db)+sizeof(MDB_cursor *)+sizeof(unsigned int)+1); - if ((env->me_pbuf = calloc(1, env->me_psize)) && - (txn = calloc(1, size))) - { - txn->mt_dbs = (MDB_db *)((char *)txn + tsize); - txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs); - txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs); - txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs); - txn->mt_env = env; -#ifdef MDB_VL32 - txn->mt_rpages = malloc(MDB_TRPAGE_SIZE * sizeof(MDB_ID3)); - if (!txn->mt_rpages) { - free(txn); - rc = ENOMEM; - goto leave; - } - txn->mt_rpages[0].mid = 0; - txn->mt_rpcheck = MDB_TRPAGE_SIZE/2; -#endif - txn->mt_dbxs = env->me_dbxs; - txn->mt_flags = MDB_TXN_FINISHED; - env->me_txn0 = txn; - } else { - rc = ENOMEM; - } - } - } - -leave: - if (rc) { - mdb_env_close0(env, excl); - } - free(lpath); - return rc; -} - -/** Destroy resources from mdb_env_open(), clear our readers & DBIs */ -static void ESECT -mdb_env_close0(MDB_env *env, int excl) -{ - int i; - - if (!(env->me_flags & MDB_ENV_ACTIVE)) - return; - - /* Doing this here since me_dbxs may not exist during mdb_env_close */ - if (env->me_dbxs) { - for (i = env->me_maxdbs; --i >= CORE_DBS; ) - free(env->me_dbxs[i].md_name.mv_data); - free(env->me_dbxs); - } - - free(env->me_pbuf); - free(env->me_dbiseqs); - free(env->me_dbflags); - free(env->me_path); - free(env->me_dirty_list); -#ifdef MDB_VL32 - if (env->me_txn0 && env->me_txn0->mt_rpages) - free(env->me_txn0->mt_rpages); - { unsigned int x; - for (x=1; x<=env->me_rpages[0].mid; x++) - munmap(env->me_rpages[x].mptr, env->me_rpages[x].mcnt * env->me_psize); - } - free(env->me_rpages); -#endif - free(env->me_txn0); - mdb_midl_free(env->me_free_pgs); - - if (env->me_flags & MDB_ENV_TXKEY) { - pthread_key_delete(env->me_txkey); -#ifdef _WIN32 - /* Delete our key from the global list */ - for (i=0; ime_txkey) { - mdb_tls_keys[i] = mdb_tls_keys[mdb_tls_nkeys-1]; - mdb_tls_nkeys--; - break; - } -#endif - } - - if (env->me_map) { -#ifdef MDB_VL32 - munmap(env->me_map, NUM_METAS*env->me_psize); -#else - munmap(env->me_map, env->me_mapsize); -#endif - } - if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE) - (void) close(env->me_mfd); - if (env->me_fd != INVALID_HANDLE_VALUE) - (void) close(env->me_fd); - if (env->me_txns) { - MDB_PID_T pid = env->me_pid; - /* Clearing readers is done in this function because - * me_txkey with its destructor must be disabled first. - * - * We skip the the reader mutex, so we touch only - * data owned by this process (me_close_readers and - * our readers), and clear each reader atomically. - */ - for (i = env->me_close_readers; --i >= 0; ) - if (env->me_txns->mti_readers[i].mr_pid == pid) - env->me_txns->mti_readers[i].mr_pid = 0; -#ifdef _WIN32 - if (env->me_rmutex) { - CloseHandle(env->me_rmutex); - if (env->me_wmutex) CloseHandle(env->me_wmutex); - } - /* Windows automatically destroys the mutexes when - * the last handle closes. - */ -#elif defined(MDB_USE_POSIX_SEM) - if (env->me_rmutex != SEM_FAILED) { - sem_close(env->me_rmutex); - if (env->me_wmutex != SEM_FAILED) - sem_close(env->me_wmutex); - /* If we have the filelock: If we are the - * only remaining user, clean up semaphores. - */ - if (excl == 0) - mdb_env_excl_lock(env, &excl); - if (excl > 0) { - sem_unlink(env->me_txns->mti_rmname); - sem_unlink(env->me_txns->mti_wmname); - } - } -#elif defined(MDB_USE_SYSV_SEM) - if (env->me_rmutex->semid != -1) { - /* If we have the filelock: If we are the - * only remaining user, clean up semaphores. - */ - if (excl == 0) - mdb_env_excl_lock(env, &excl); - if (excl > 0) - semctl(env->me_rmutex->semid, 0, IPC_RMID); - } -#endif - munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo)); - } - if (env->me_lfd != INVALID_HANDLE_VALUE) { -#ifdef _WIN32 - if (excl >= 0) { - /* Unlock the lockfile. Windows would have unlocked it - * after closing anyway, but not necessarily at once. - */ - UnlockFile(env->me_lfd, 0, 0, 1, 0); - } -#endif - (void) close(env->me_lfd); - } -#ifdef MDB_VL32 -#ifdef _WIN32 - if (env->me_fmh) CloseHandle(env->me_fmh); - if (env->me_rpmutex) CloseHandle(env->me_rpmutex); -#else - pthread_mutex_destroy(&env->me_rpmutex); -#endif -#endif - - env->me_flags &= ~(MDB_ENV_ACTIVE|MDB_ENV_TXKEY); -} - -void ESECT -mdb_env_close(MDB_env *env) -{ - MDB_page *dp; - - if (env == NULL) - return; - - VGMEMP_DESTROY(env); - while ((dp = env->me_dpages) != NULL) { - VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); - env->me_dpages = dp->mp_next; - free(dp); - } - - mdb_env_close0(env, 0); - free(env); -} - -/** Compare two items pointing at aligned mdb_size_t's */ -static int -mdb_cmp_long(const MDB_val *a, const MDB_val *b) -{ - return (*(mdb_size_t *)a->mv_data < *(mdb_size_t *)b->mv_data) ? -1 : - *(mdb_size_t *)a->mv_data > *(mdb_size_t *)b->mv_data; -} - -/** Compare two items pointing at aligned unsigned int's. - * - * This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp, - * but #mdb_cmp_clong() is called instead if the data type is mdb_size_t. - */ -static int -mdb_cmp_int(const MDB_val *a, const MDB_val *b) -{ - return (*(unsigned int *)a->mv_data < *(unsigned int *)b->mv_data) ? -1 : - *(unsigned int *)a->mv_data > *(unsigned int *)b->mv_data; -} - -/** Compare two items pointing at unsigned ints of unknown alignment. - * Nodes and keys are guaranteed to be 2-byte aligned. - */ -static int -mdb_cmp_cint(const MDB_val *a, const MDB_val *b) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - unsigned short *u, *c; - int x; - - u = (unsigned short *) ((char *) a->mv_data + a->mv_size); - c = (unsigned short *) ((char *) b->mv_data + a->mv_size); - do { - x = *--u - *--c; - } while(!x && u > (unsigned short *)a->mv_data); - return x; -#else - unsigned short *u, *c, *end; - int x; - - end = (unsigned short *) ((char *) a->mv_data + a->mv_size); - u = (unsigned short *)a->mv_data; - c = (unsigned short *)b->mv_data; - do { - x = *u++ - *c++; - } while(!x && u < end); - return x; -#endif -} - -/** Compare two items lexically */ -static int -mdb_cmp_memn(const MDB_val *a, const MDB_val *b) -{ - int diff; - ssize_t len_diff; - unsigned int len; - - len = a->mv_size; - len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size; - if (len_diff > 0) { - len = b->mv_size; - len_diff = 1; - } - - diff = memcmp(a->mv_data, b->mv_data, len); - return diff ? diff : len_diff<0 ? -1 : len_diff; -} - -/** Compare two items in reverse byte order */ -static int -mdb_cmp_memnr(const MDB_val *a, const MDB_val *b) -{ - const unsigned char *p1, *p2, *p1_lim; - ssize_t len_diff; - int diff; - - p1_lim = (const unsigned char *)a->mv_data; - p1 = (const unsigned char *)a->mv_data + a->mv_size; - p2 = (const unsigned char *)b->mv_data + b->mv_size; - - len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size; - if (len_diff > 0) { - p1_lim += len_diff; - len_diff = 1; - } - - while (p1 > p1_lim) { - diff = *--p1 - *--p2; - if (diff) - return diff; - } - return len_diff<0 ? -1 : len_diff; -} - -/** Search for key within a page, using binary search. - * Returns the smallest entry larger or equal to the key. - * If exactp is non-null, stores whether the found entry was an exact match - * in *exactp (1 or 0). - * Updates the cursor index with the index of the found entry. - * If no entry larger or equal to the key is found, returns NULL. - */ -static MDB_node * -mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp) -{ - unsigned int i = 0, nkeys; - int low, high; - int rc = 0; - MDB_page *mp = mc->mc_pg[mc->mc_top]; - MDB_node *node = NULL; - MDB_val nodekey; - MDB_cmp_func *cmp; - DKBUF; - - nkeys = NUMKEYS(mp); - - DPRINTF(("searching %u keys in %s %spage %"Y"u", - nkeys, IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", - mdb_dbg_pgno(mp))); - - low = IS_LEAF(mp) ? 0 : 1; - high = nkeys - 1; - cmp = mc->mc_dbx->md_cmp; - - /* Branch pages have no data, so if using integer keys, - * alignment is guaranteed. Use faster mdb_cmp_int. - */ - if (cmp == mdb_cmp_cint && IS_BRANCH(mp)) { - if (NODEPTR(mp, 1)->mn_ksize == sizeof(mdb_size_t)) - cmp = mdb_cmp_long; - else - cmp = mdb_cmp_int; - } - - if (IS_LEAF2(mp)) { - nodekey.mv_size = mc->mc_db->md_pad; - node = NODEPTR(mp, 0); /* fake */ - while (low <= high) { - i = (low + high) >> 1; - nodekey.mv_data = LEAF2KEY(mp, i, nodekey.mv_size); - rc = cmp(key, &nodekey); - DPRINTF(("found leaf index %u [%s], rc = %i", - i, DKEY(&nodekey), rc)); - if (rc == 0) - break; - if (rc > 0) - low = i + 1; - else - high = i - 1; - } - } else { - while (low <= high) { - i = (low + high) >> 1; - - node = NODEPTR(mp, i); - nodekey.mv_size = NODEKSZ(node); - nodekey.mv_data = NODEKEY(node); - - rc = cmp(key, &nodekey); -#if MDB_DEBUG - if (IS_LEAF(mp)) - DPRINTF(("found leaf index %u [%s], rc = %i", - i, DKEY(&nodekey), rc)); - else - DPRINTF(("found branch index %u [%s -> %"Y"u], rc = %i", - i, DKEY(&nodekey), NODEPGNO(node), rc)); -#endif - if (rc == 0) - break; - if (rc > 0) - low = i + 1; - else - high = i - 1; - } - } - - if (rc > 0) { /* Found entry is less than the key. */ - i++; /* Skip to get the smallest entry larger than key. */ - if (!IS_LEAF2(mp)) - node = NODEPTR(mp, i); - } - if (exactp) - *exactp = (rc == 0 && nkeys > 0); - /* store the key index */ - mc->mc_ki[mc->mc_top] = i; - if (i >= nkeys) - /* There is no entry larger or equal to the key. */ - return NULL; - - /* nodeptr is fake for LEAF2 */ - return node; -} - -#if 0 -static void -mdb_cursor_adjust(MDB_cursor *mc, func) -{ - MDB_cursor *m2; - - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { - if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) { - func(mc, m2); - } - } -} -#endif - -/** Pop a page off the top of the cursor's stack. */ -static void -mdb_cursor_pop(MDB_cursor *mc) -{ - if (mc->mc_snum) { - DPRINTF(("popping page %"Y"u off db %d cursor %p", - mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *) mc)); - - mc->mc_snum--; - if (mc->mc_snum) { - mc->mc_top--; - } else { - mc->mc_flags &= ~C_INITIALIZED; - } - } -} - -/** Push a page onto the top of the cursor's stack. */ -static int -mdb_cursor_push(MDB_cursor *mc, MDB_page *mp) -{ - DPRINTF(("pushing page %"Y"u on db %d cursor %p", mp->mp_pgno, - DDBI(mc), (void *) mc)); - - if (mc->mc_snum >= CURSOR_STACK) { - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return MDB_CURSOR_FULL; - } - - mc->mc_top = mc->mc_snum++; - mc->mc_pg[mc->mc_top] = mp; - mc->mc_ki[mc->mc_top] = 0; - - return MDB_SUCCESS; -} - -#ifdef MDB_VL32 -/** Map a read-only page. - * There are two levels of tracking in use, a per-txn list and a per-env list. - * ref'ing and unref'ing the per-txn list is faster since it requires no - * locking. Pages are cached in the per-env list for global reuse, and a lock - * is required. Pages are not immediately unmapped when their refcnt goes to - * zero; they hang around in case they will be reused again soon. - * - * When the per-txn list gets full, all pages with refcnt=0 are purged from the - * list and their refcnts in the per-env list are decremented. - * - * When the per-env list gets full, all pages with refcnt=0 are purged from the - * list and their pages are unmapped. - * - * @note "full" means the list has reached its respective rpcheck threshold. - * This threshold slowly raises if no pages could be purged on a given check, - * and returns to its original value when enough pages were purged. - * - * If purging doesn't free any slots, filling the per-txn list will return - * MDB_TXN_FULL, and filling the per-env list returns MDB_MAP_FULL. - * - * Reference tracking in a txn is imperfect, pages can linger with non-zero - * refcnt even without active references. It was deemed to be too invasive - * to add unrefs in every required location. However, all pages are unref'd - * at the end of the transaction. This guarantees that no stale references - * linger in the per-env list. - * - * Usually we map chunks of 16 pages at a time, but if an overflow page begins - * at the tail of the chunk we extend the chunk to include the entire overflow - * page. Unfortunately, pages can be turned into overflow pages after their - * chunk was already mapped. In that case we must remap the chunk if the - * overflow page is referenced. If the chunk's refcnt is 0 we can just remap - * it, otherwise we temporarily map a new chunk just for the overflow page. - * - * @note this chunk handling means we cannot guarantee that a data item - * returned from the DB will stay alive for the duration of the transaction: - * We unref pages as soon as a cursor moves away from the page - * A subsequent op may cause a purge, which may unmap any unref'd chunks - * The caller must copy the data if it must be used later in the same txn. - * - * Also - our reference counting revolves around cursors, but overflow pages - * aren't pointed to by a cursor's page stack. We have to remember them - * explicitly, in the added mc_ovpg field. A single cursor can only hold a - * reference to one overflow page at a time. - * - * @param[in] txn the transaction for this access. - * @param[in] pgno the page number for the page to retrieve. - * @param[out] ret address of a pointer where the page's address will be stored. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_rpage_get(MDB_txn *txn, pgno_t pg0, MDB_page **ret) -{ - MDB_env *env = txn->mt_env; - MDB_page *p; - MDB_ID3L tl = txn->mt_rpages; - MDB_ID3L el = env->me_rpages; - MDB_ID3 id3; - unsigned x, rem; - pgno_t pgno; - int rc, retries = 1; -#ifdef _WIN32 - LARGE_INTEGER off; - SIZE_T len; -#define SET_OFF(off,val) off.QuadPart = val -#define MAP(rc,env,addr,len,off) \ - addr = NULL; \ - rc = NtMapViewOfSection(env->me_fmh, GetCurrentProcess(), &addr, 0, \ - len, &off, &len, ViewUnmap, (env->me_flags & MDB_RDONLY) ? 0 : MEM_RESERVE, PAGE_READONLY); \ - if (rc) rc = mdb_nt2win32(rc) -#else - off64_t off; - size_t len; -#define SET_OFF(off,val) off = val -#define MAP(rc,env,addr,len,off) \ - addr = mmap(NULL, len, PROT_READ, MAP_SHARED, env->me_fd, off); \ - rc = (addr == MAP_FAILED) ? errno : 0 -#endif - - /* remember the offset of the actual page number, so we can - * return the correct pointer at the end. - */ - rem = pg0 & (MDB_RPAGE_CHUNK-1); - pgno = pg0 ^ rem; - - id3.mid = 0; - x = mdb_mid3l_search(tl, pgno); - if (x <= tl[0].mid && tl[x].mid == pgno) { - if (x != tl[0].mid && tl[x+1].mid == pg0) - x++; - /* check for overflow size */ - p = (MDB_page *)((char *)tl[x].mptr + rem * env->me_psize); - if (IS_OVERFLOW(p) && p->mp_pages + rem > tl[x].mcnt) { - id3.mcnt = p->mp_pages + rem; - len = id3.mcnt * env->me_psize; - SET_OFF(off, pgno * env->me_psize); - MAP(rc, env, id3.mptr, len, off); - if (rc) - return rc; - /* check for local-only page */ - if (rem) { - mdb_tassert(txn, tl[x].mid != pg0); - /* hope there's room to insert this locally. - * setting mid here tells later code to just insert - * this id3 instead of searching for a match. - */ - id3.mid = pg0; - goto notlocal; - } else { - /* ignore the mapping we got from env, use new one */ - tl[x].mptr = id3.mptr; - tl[x].mcnt = id3.mcnt; - /* if no active ref, see if we can replace in env */ - if (!tl[x].mref) { - unsigned i; - pthread_mutex_lock(&env->me_rpmutex); - i = mdb_mid3l_search(el, tl[x].mid); - if (el[i].mref == 1) { - /* just us, replace it */ - munmap(el[i].mptr, el[i].mcnt * env->me_psize); - el[i].mptr = tl[x].mptr; - el[i].mcnt = tl[x].mcnt; - } else { - /* there are others, remove ourself */ - el[i].mref--; - } - pthread_mutex_unlock(&env->me_rpmutex); - } - } - } - id3.mptr = tl[x].mptr; - id3.mcnt = tl[x].mcnt; - tl[x].mref++; - goto ok; - } - -notlocal: - if (tl[0].mid >= MDB_TRPAGE_MAX - txn->mt_rpcheck) { - unsigned i, y; - /* purge unref'd pages from our list and unref in env */ - pthread_mutex_lock(&env->me_rpmutex); -retry: - y = 0; - for (i=1; i<=tl[0].mid; i++) { - if (!tl[i].mref) { - if (!y) y = i; - /* tmp overflow pages don't go to env */ - if (tl[i].mid & (MDB_RPAGE_CHUNK-1)) { - munmap(tl[i].mptr, tl[i].mcnt * env->me_psize); - continue; - } - x = mdb_mid3l_search(el, tl[i].mid); - el[x].mref--; - } - } - pthread_mutex_unlock(&env->me_rpmutex); - if (!y) { - /* we didn't find any unref'd chunks. - * if we're out of room, fail. - */ - if (tl[0].mid >= MDB_TRPAGE_MAX) - return MDB_TXN_FULL; - /* otherwise, raise threshold for next time around - * and let this go. - */ - txn->mt_rpcheck /= 2; - } else { - /* we found some unused; consolidate the list */ - for (i=y+1; i<= tl[0].mid; i++) - if (tl[i].mref) - tl[y++] = tl[i]; - tl[0].mid = y-1; - /* decrease the check threshold toward its original value */ - if (!txn->mt_rpcheck) - txn->mt_rpcheck = 1; - while (txn->mt_rpcheck < tl[0].mid && txn->mt_rpcheck < MDB_TRPAGE_SIZE/2) - txn->mt_rpcheck *= 2; - } - } - if (tl[0].mid < MDB_TRPAGE_SIZE) { - id3.mref = 1; - if (id3.mid) - goto found; - /* don't map past last written page in read-only envs */ - if ((env->me_flags & MDB_RDONLY) && pgno + MDB_RPAGE_CHUNK-1 > txn->mt_last_pgno) - id3.mcnt = txn->mt_last_pgno + 1 - pgno; - else - id3.mcnt = MDB_RPAGE_CHUNK; - len = id3.mcnt * env->me_psize; - id3.mid = pgno; - - /* search for page in env */ - pthread_mutex_lock(&env->me_rpmutex); - x = mdb_mid3l_search(el, pgno); - if (x <= el[0].mid && el[x].mid == pgno) { - id3.mptr = el[x].mptr; - id3.mcnt = el[x].mcnt; - /* check for overflow size */ - p = (MDB_page *)((char *)id3.mptr + rem * env->me_psize); - if (IS_OVERFLOW(p) && p->mp_pages + rem > id3.mcnt) { - id3.mcnt = p->mp_pages + rem; - len = id3.mcnt * env->me_psize; - SET_OFF(off, pgno * env->me_psize); - MAP(rc, env, id3.mptr, len, off); - if (rc) - goto fail; - if (!el[x].mref) { - munmap(el[x].mptr, env->me_psize * el[x].mcnt); - el[x].mptr = id3.mptr; - el[x].mcnt = id3.mcnt; - } else { - id3.mid = pg0; - pthread_mutex_unlock(&env->me_rpmutex); - goto found; - } - } - el[x].mref++; - pthread_mutex_unlock(&env->me_rpmutex); - goto found; - } - if (el[0].mid >= MDB_ERPAGE_MAX - env->me_rpcheck) { - /* purge unref'd pages */ - unsigned i, y = 0; - for (i=1; i<=el[0].mid; i++) { - if (!el[i].mref) { - if (!y) y = i; - munmap(el[i].mptr, env->me_psize * el[i].mcnt); - } - } - if (!y) { - if (retries) { - /* see if we can unref some local pages */ - retries--; - id3.mid = 0; - goto retry; - } - if (el[0].mid >= MDB_ERPAGE_MAX) { - pthread_mutex_unlock(&env->me_rpmutex); - return MDB_MAP_FULL; - } - env->me_rpcheck /= 2; - } else { - for (i=y+1; i<= el[0].mid; i++) - if (el[i].mref) - el[y++] = el[i]; - el[0].mid = y-1; - if (!env->me_rpcheck) - env->me_rpcheck = 1; - while (env->me_rpcheck < el[0].mid && env->me_rpcheck < MDB_ERPAGE_SIZE/2) - env->me_rpcheck *= 2; - } - } - SET_OFF(off, pgno * env->me_psize); - MAP(rc, env, id3.mptr, len, off); - if (rc) { -fail: - pthread_mutex_unlock(&env->me_rpmutex); - return rc; - } - /* check for overflow size */ - p = (MDB_page *)((char *)id3.mptr + rem * env->me_psize); - if (IS_OVERFLOW(p) && p->mp_pages + rem > id3.mcnt) { - id3.mcnt = p->mp_pages + rem; - munmap(id3.mptr, len); - len = id3.mcnt * env->me_psize; - MAP(rc, env, id3.mptr, len, off); - if (rc) - goto fail; - } - mdb_mid3l_insert(el, &id3); - pthread_mutex_unlock(&env->me_rpmutex); -found: - mdb_mid3l_insert(tl, &id3); - } else { - return MDB_TXN_FULL; - } -ok: - p = (MDB_page *)((char *)id3.mptr + rem * env->me_psize); -#if MDB_DEBUG /* we don't need this check any more */ - if (IS_OVERFLOW(p)) { - mdb_tassert(txn, p->mp_pages + rem <= id3.mcnt); - } -#endif - *ret = p; - return MDB_SUCCESS; -} -#endif - -/** Find the address of the page corresponding to a given page number. - * @param[in] mc the cursor accessing the page. - * @param[in] pgno the page number for the page to retrieve. - * @param[out] ret address of a pointer where the page's address will be stored. - * @param[out] lvl dirty_list inheritance level of found page. 1=current txn, 0=mapped page. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_get(MDB_cursor *mc, pgno_t pgno, MDB_page **ret, int *lvl) -{ - MDB_txn *txn = mc->mc_txn; -#ifndef MDB_VL32 - MDB_env *env = txn->mt_env; -#endif - MDB_page *p = NULL; - int level; - - if (! (mc->mc_flags & (C_ORIG_RDONLY|C_WRITEMAP))) { - MDB_txn *tx2 = txn; - level = 1; - do { - MDB_ID2L dl = tx2->mt_u.dirty_list; - unsigned x; - /* Spilled pages were dirtied in this txn and flushed - * because the dirty list got full. Bring this page - * back in from the map (but don't unspill it here, - * leave that unless page_touch happens again). - */ - if (tx2->mt_spill_pgs) { - MDB_ID pn = pgno << 1; - x = mdb_midl_search(tx2->mt_spill_pgs, pn); - if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) { -#ifdef MDB_VL32 - int rc = mdb_rpage_get(txn, pgno, &p); - if (rc) - return rc; -#else - p = (MDB_page *)(env->me_map + env->me_psize * pgno); -#endif - goto done; - } - } - if (dl[0].mid) { - unsigned x = mdb_mid2l_search(dl, pgno); - if (x <= dl[0].mid && dl[x].mid == pgno) { - p = dl[x].mptr; - goto done; - } - } - level++; - } while ((tx2 = tx2->mt_parent) != NULL); - } - - if (pgno < txn->mt_next_pgno) { - level = 0; -#ifdef MDB_VL32 - { - int rc = mdb_rpage_get(txn, pgno, &p); - if (rc) - return rc; - } -#else - p = (MDB_page *)(env->me_map + env->me_psize * pgno); -#endif - } else { - DPRINTF(("page %"Y"u not found", pgno)); - txn->mt_flags |= MDB_TXN_ERROR; - return MDB_PAGE_NOTFOUND; - } - -done: - *ret = p; - if (lvl) - *lvl = level; - return MDB_SUCCESS; -} - -/** Finish #mdb_page_search() / #mdb_page_search_lowest(). - * The cursor is at the root page, set up the rest of it. - */ -static int -mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags) -{ - MDB_page *mp = mc->mc_pg[mc->mc_top]; - int rc; - DKBUF; - - while (IS_BRANCH(mp)) { - MDB_node *node; - indx_t i; - - DPRINTF(("branch page %"Y"u has %u keys", mp->mp_pgno, NUMKEYS(mp))); - /* Don't assert on branch pages in the FreeDB. We can get here - * while in the process of rebalancing a FreeDB branch page; we must - * let that proceed. ITS#8336 - */ - mdb_cassert(mc, !mc->mc_dbi || NUMKEYS(mp) > 1); - DPRINTF(("found index 0 to page %"Y"u", NODEPGNO(NODEPTR(mp, 0)))); - - if (flags & (MDB_PS_FIRST|MDB_PS_LAST)) { - i = 0; - if (flags & MDB_PS_LAST) - i = NUMKEYS(mp) - 1; - } else { - int exact; - node = mdb_node_search(mc, key, &exact); - if (node == NULL) - i = NUMKEYS(mp) - 1; - else { - i = mc->mc_ki[mc->mc_top]; - if (!exact) { - mdb_cassert(mc, i > 0); - i--; - } - } - DPRINTF(("following index %u for key [%s]", i, DKEY(key))); - } - - mdb_cassert(mc, i < NUMKEYS(mp)); - node = NODEPTR(mp, i); - - if ((rc = mdb_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0) - return rc; - - mc->mc_ki[mc->mc_top] = i; - if ((rc = mdb_cursor_push(mc, mp))) - return rc; - - if (flags & MDB_PS_MODIFY) { - if ((rc = mdb_page_touch(mc)) != 0) - return rc; - mp = mc->mc_pg[mc->mc_top]; - } - } - - if (!IS_LEAF(mp)) { - DPRINTF(("internal error, index points to a %02X page!?", - mp->mp_flags)); - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return MDB_CORRUPTED; - } - - DPRINTF(("found leaf page %"Y"u for key [%s]", mp->mp_pgno, - key ? DKEY(key) : "null")); - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - - return MDB_SUCCESS; -} - -/** Search for the lowest key under the current branch page. - * This just bypasses a NUMKEYS check in the current page - * before calling mdb_page_search_root(), because the callers - * are all in situations where the current page is known to - * be underfilled. - */ -static int -mdb_page_search_lowest(MDB_cursor *mc) -{ - MDB_page *mp = mc->mc_pg[mc->mc_top]; - MDB_node *node = NODEPTR(mp, 0); - int rc; - - if ((rc = mdb_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0) - return rc; - - mc->mc_ki[mc->mc_top] = 0; - if ((rc = mdb_cursor_push(mc, mp))) - return rc; - return mdb_page_search_root(mc, NULL, MDB_PS_FIRST); -} - -/** Search for the page a given key should be in. - * Push it and its parent pages on the cursor stack. - * @param[in,out] mc the cursor for this operation. - * @param[in] key the key to search for, or NULL for first/last page. - * @param[in] flags If MDB_PS_MODIFY is set, visited pages in the DB - * are touched (updated with new page numbers). - * If MDB_PS_FIRST or MDB_PS_LAST is set, find first or last leaf. - * This is used by #mdb_cursor_first() and #mdb_cursor_last(). - * If MDB_PS_ROOTONLY set, just fetch root node, no further lookups. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags) -{ - int rc; - pgno_t root; - - /* Make sure the txn is still viable, then find the root from - * the txn's db table and set it as the root of the cursor's stack. - */ - if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED) { - DPUTS("transaction may not be used now"); - return MDB_BAD_TXN; - } else { - /* Make sure we're using an up-to-date root */ - if (*mc->mc_dbflag & DB_STALE) { - MDB_cursor mc2; - if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) - return MDB_BAD_DBI; - mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL); - rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, 0); - if (rc) - return rc; - { - MDB_val data; - int exact = 0; - uint16_t flags; - MDB_node *leaf = mdb_node_search(&mc2, - &mc->mc_dbx->md_name, &exact); - if (!exact) - return MDB_NOTFOUND; - if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA) - return MDB_INCOMPATIBLE; /* not a named DB */ - rc = mdb_node_read(&mc2, leaf, &data); - if (rc) - return rc; - memcpy(&flags, ((char *) data.mv_data + offsetof(MDB_db, md_flags)), - sizeof(uint16_t)); - /* The txn may not know this DBI, or another process may - * have dropped and recreated the DB with other flags. - */ - if ((mc->mc_db->md_flags & PERSISTENT_FLAGS) != flags) - return MDB_INCOMPATIBLE; - memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db)); - } - *mc->mc_dbflag &= ~DB_STALE; - } - root = mc->mc_db->md_root; - - if (root == P_INVALID) { /* Tree is empty. */ - DPUTS("tree is empty"); - return MDB_NOTFOUND; - } - } - - mdb_cassert(mc, root > 1); - if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root) { -#ifdef MDB_VL32 - if (mc->mc_pg[0]) - MDB_PAGE_UNREF(mc->mc_txn, mc->mc_pg[0]); -#endif - if ((rc = mdb_page_get(mc, root, &mc->mc_pg[0], NULL)) != 0) - return rc; - } - -#ifdef MDB_VL32 - { - int i; - for (i=1; imc_snum; i++) - MDB_PAGE_UNREF(mc->mc_txn, mc->mc_pg[i]); - } -#endif - mc->mc_snum = 1; - mc->mc_top = 0; - - DPRINTF(("db %d root page %"Y"u has flags 0x%X", - DDBI(mc), root, mc->mc_pg[0]->mp_flags)); - - if (flags & MDB_PS_MODIFY) { - if ((rc = mdb_page_touch(mc))) - return rc; - } - - if (flags & MDB_PS_ROOTONLY) - return MDB_SUCCESS; - - return mdb_page_search_root(mc, key, flags); -} - -static int -mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp) -{ - MDB_txn *txn = mc->mc_txn; - pgno_t pg = mp->mp_pgno; - unsigned x = 0, ovpages = mp->mp_pages; - MDB_env *env = txn->mt_env; - MDB_IDL sl = txn->mt_spill_pgs; - MDB_ID pn = pg << 1; - int rc; - - DPRINTF(("free ov page %"Y"u (%d)", pg, ovpages)); - /* If the page is dirty or on the spill list we just acquired it, - * so we should give it back to our current free list, if any. - * Otherwise put it onto the list of pages we freed in this txn. - * - * Won't create me_pghead: me_pglast must be inited along with it. - * Unsupported in nested txns: They would need to hide the page - * range in ancestor txns' dirty and spilled lists. - */ - if (env->me_pghead && - !txn->mt_parent && - ((mp->mp_flags & P_DIRTY) || - (sl && (x = mdb_midl_search(sl, pn)) <= sl[0] && sl[x] == pn))) - { - unsigned i, j; - pgno_t *mop; - MDB_ID2 *dl, ix, iy; - rc = mdb_midl_need(&env->me_pghead, ovpages); - if (rc) - return rc; - if (!(mp->mp_flags & P_DIRTY)) { - /* This page is no longer spilled */ - if (x == sl[0]) - sl[0]--; - else - sl[x] |= 1; - goto release; - } - /* Remove from dirty list */ - dl = txn->mt_u.dirty_list; - x = dl[0].mid--; - for (ix = dl[x]; ix.mptr != mp; ix = iy) { - if (x > 1) { - x--; - iy = dl[x]; - dl[x] = ix; - } else { - mdb_cassert(mc, x > 1); - j = ++(dl[0].mid); - dl[j] = ix; /* Unsorted. OK when MDB_TXN_ERROR. */ - txn->mt_flags |= MDB_TXN_ERROR; - return MDB_CORRUPTED; - } - } - txn->mt_dirty_room++; - if (!(env->me_flags & MDB_WRITEMAP)) - mdb_dpage_free(env, mp); -release: - /* Insert in me_pghead */ - mop = env->me_pghead; - j = mop[0] + ovpages; - for (i = mop[0]; i && mop[i] < pg; i--) - mop[j--] = mop[i]; - while (j>i) - mop[j--] = pg++; - mop[0] += ovpages; - } else { - rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, ovpages); - if (rc) - return rc; - } -#ifdef MDB_VL32 - if (mc->mc_ovpg == mp) - mc->mc_ovpg = NULL; -#endif - mc->mc_db->md_overflow_pages -= ovpages; - return 0; -} - -/** Return the data associated with a given node. - * @param[in] mc The cursor for this operation. - * @param[in] leaf The node being read. - * @param[out] data Updated to point to the node's data. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_node_read(MDB_cursor *mc, MDB_node *leaf, MDB_val *data) -{ - MDB_page *omp; /* overflow page */ - pgno_t pgno; - int rc; - -#ifdef MDB_VL32 - if (mc->mc_ovpg) { - MDB_PAGE_UNREF(mc->mc_txn, mc->mc_ovpg); - mc->mc_ovpg = 0; - } -#endif - if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) { - data->mv_size = NODEDSZ(leaf); - data->mv_data = NODEDATA(leaf); - return MDB_SUCCESS; - } - - /* Read overflow data. - */ - data->mv_size = NODEDSZ(leaf); - memcpy(&pgno, NODEDATA(leaf), sizeof(pgno)); - if ((rc = mdb_page_get(mc, pgno, &omp, NULL)) != 0) { - DPRINTF(("read overflow page %"Y"u failed", pgno)); - return rc; - } - data->mv_data = METADATA(omp); -#ifdef MDB_VL32 - mc->mc_ovpg = omp; -#endif - - return MDB_SUCCESS; -} - -int -mdb_get(MDB_txn *txn, MDB_dbi dbi, - MDB_val *key, MDB_val *data) -{ - MDB_cursor mc; - MDB_xcursor mx; - int exact = 0, rc; - DKBUF; - - DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key))); - - if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - if (txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - mdb_cursor_init(&mc, txn, dbi, &mx); - rc = mdb_cursor_set(&mc, key, data, MDB_SET, &exact); -#ifdef MDB_VL32 - { - /* unref all the pages - caller must copy the data - * before doing anything else - */ - mdb_cursor_unref(&mc); - } -#endif - return rc; -} - -/** Find a sibling for a page. - * Replaces the page at the top of the cursor's stack with the - * specified sibling, if one exists. - * @param[in] mc The cursor for this operation. - * @param[in] move_right Non-zero if the right sibling is requested, - * otherwise the left sibling. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_cursor_sibling(MDB_cursor *mc, int move_right) -{ - int rc; - MDB_node *indx; - MDB_page *mp; -#ifdef MDB_VL32 - MDB_page *op; -#endif - - if (mc->mc_snum < 2) { - return MDB_NOTFOUND; /* root has no siblings */ - } - -#ifdef MDB_VL32 - op = mc->mc_pg[mc->mc_top]; -#endif - mdb_cursor_pop(mc); - DPRINTF(("parent page is page %"Y"u, index %u", - mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top])); - - if (move_right ? (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mc->mc_pg[mc->mc_top])) - : (mc->mc_ki[mc->mc_top] == 0)) { - DPRINTF(("no more keys left, moving to %s sibling", - move_right ? "right" : "left")); - if ((rc = mdb_cursor_sibling(mc, move_right)) != MDB_SUCCESS) { - /* undo cursor_pop before returning */ - mc->mc_top++; - mc->mc_snum++; - return rc; - } - } else { - if (move_right) - mc->mc_ki[mc->mc_top]++; - else - mc->mc_ki[mc->mc_top]--; - DPRINTF(("just moving to %s index key %u", - move_right ? "right" : "left", mc->mc_ki[mc->mc_top])); - } - mdb_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top])); - - MDB_PAGE_UNREF(mc->mc_txn, op); - - indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if ((rc = mdb_page_get(mc, NODEPGNO(indx), &mp, NULL)) != 0) { - /* mc will be inconsistent if caller does mc_snum++ as above */ - mc->mc_flags &= ~(C_INITIALIZED|C_EOF); - return rc; - } - - mdb_cursor_push(mc, mp); - if (!move_right) - mc->mc_ki[mc->mc_top] = NUMKEYS(mp)-1; - - return MDB_SUCCESS; -} - -/** Move the cursor to the next data item. */ -static int -mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) -{ - MDB_page *mp; - MDB_node *leaf; - int rc; - - if (mc->mc_flags & C_EOF) { - return MDB_NOTFOUND; - } - - mdb_cassert(mc, mc->mc_flags & C_INITIALIZED); - - mp = mc->mc_pg[mc->mc_top]; - - if (mc->mc_db->md_flags & MDB_DUPSORT) { - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - if (op == MDB_NEXT || op == MDB_NEXT_DUP) { - rc = mdb_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_NEXT); - if (op != MDB_NEXT || rc != MDB_NOTFOUND) { - if (rc == MDB_SUCCESS) - MDB_GET_KEY(leaf, key); - return rc; - } - } -#ifdef MDB_VL32 - else { - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - mdb_cursor_unref(&mc->mc_xcursor->mx_cursor); - } - } -#endif - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - if (op == MDB_NEXT_DUP) - return MDB_NOTFOUND; - } - } - - DPRINTF(("cursor_next: top page is %"Y"u in cursor %p", - mdb_dbg_pgno(mp), (void *) mc)); - if (mc->mc_flags & C_DEL) { - mc->mc_flags ^= C_DEL; - goto skip; - } - - if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) { - DPUTS("=====> move to next sibling page"); - if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) { - mc->mc_flags |= C_EOF; - return rc; - } - mp = mc->mc_pg[mc->mc_top]; - DPRINTF(("next page is %"Y"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top])); - } else - mc->mc_ki[mc->mc_top]++; - -skip: - DPRINTF(("==> cursor points to page %"Y"u with %u keys, key index %u", - mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top])); - - if (IS_LEAF2(mp)) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); - return MDB_SUCCESS; - } - - mdb_cassert(mc, IS_LEAF(mp)); - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - } - if (data) { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc != MDB_SUCCESS) - return rc; - } - } - - MDB_GET_KEY(leaf, key); - return MDB_SUCCESS; -} - -/** Move the cursor to the previous data item. */ -static int -mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op) -{ - MDB_page *mp; - MDB_node *leaf; - int rc; - - mdb_cassert(mc, mc->mc_flags & C_INITIALIZED); - - mp = mc->mc_pg[mc->mc_top]; - - if (mc->mc_db->md_flags & MDB_DUPSORT) { - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - if (op == MDB_PREV || op == MDB_PREV_DUP) { - rc = mdb_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_PREV); - if (op != MDB_PREV || rc != MDB_NOTFOUND) { - if (rc == MDB_SUCCESS) { - MDB_GET_KEY(leaf, key); - mc->mc_flags &= ~C_EOF; - } - return rc; - } - } -#ifdef MDB_VL32 - else { - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - mdb_cursor_unref(&mc->mc_xcursor->mx_cursor); - } - } -#endif - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - if (op == MDB_PREV_DUP) - return MDB_NOTFOUND; - } - } - - DPRINTF(("cursor_prev: top page is %"Y"u in cursor %p", - mdb_dbg_pgno(mp), (void *) mc)); - - mc->mc_flags &= ~(C_EOF|C_DEL); - - if (mc->mc_ki[mc->mc_top] == 0) { - DPUTS("=====> move to prev sibling page"); - if ((rc = mdb_cursor_sibling(mc, 0)) != MDB_SUCCESS) { - return rc; - } - mp = mc->mc_pg[mc->mc_top]; - mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1; - DPRINTF(("prev page is %"Y"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top])); - } else - mc->mc_ki[mc->mc_top]--; - - mc->mc_flags &= ~C_EOF; - - DPRINTF(("==> cursor points to page %"Y"u with %u keys, key index %u", - mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top])); - - if (IS_LEAF2(mp)) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); - return MDB_SUCCESS; - } - - mdb_cassert(mc, IS_LEAF(mp)); - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - } - if (data) { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc != MDB_SUCCESS) - return rc; - } - } - - MDB_GET_KEY(leaf, key); - return MDB_SUCCESS; -} - -/** Set the cursor on a specific data item. */ -static int -mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, - MDB_cursor_op op, int *exactp) -{ - int rc; - MDB_page *mp; - MDB_node *leaf = NULL; - DKBUF; - - if (key->mv_size == 0) - return MDB_BAD_VALSIZE; - - if (mc->mc_xcursor) { -#ifdef MDB_VL32 - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - mdb_cursor_unref(&mc->mc_xcursor->mx_cursor); - } -#endif - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - } - - /* See if we're already on the right page */ - if (mc->mc_flags & C_INITIALIZED) { - MDB_val nodekey; - - mp = mc->mc_pg[mc->mc_top]; - if (!NUMKEYS(mp)) { - mc->mc_ki[mc->mc_top] = 0; - return MDB_NOTFOUND; - } - if (mp->mp_flags & P_LEAF2) { - nodekey.mv_size = mc->mc_db->md_pad; - nodekey.mv_data = LEAF2KEY(mp, 0, nodekey.mv_size); - } else { - leaf = NODEPTR(mp, 0); - MDB_GET_KEY2(leaf, nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (rc == 0) { - /* Probably happens rarely, but first node on the page - * was the one we wanted. - */ - mc->mc_ki[mc->mc_top] = 0; - if (exactp) - *exactp = 1; - goto set1; - } - if (rc > 0) { - unsigned int i; - unsigned int nkeys = NUMKEYS(mp); - if (nkeys > 1) { - if (mp->mp_flags & P_LEAF2) { - nodekey.mv_data = LEAF2KEY(mp, - nkeys-1, nodekey.mv_size); - } else { - leaf = NODEPTR(mp, nkeys-1); - MDB_GET_KEY2(leaf, nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (rc == 0) { - /* last node was the one we wanted */ - mc->mc_ki[mc->mc_top] = nkeys-1; - if (exactp) - *exactp = 1; - goto set1; - } - if (rc < 0) { - if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { - /* This is definitely the right page, skip search_page */ - if (mp->mp_flags & P_LEAF2) { - nodekey.mv_data = LEAF2KEY(mp, - mc->mc_ki[mc->mc_top], nodekey.mv_size); - } else { - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - MDB_GET_KEY2(leaf, nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (rc == 0) { - /* current node was the one we wanted */ - if (exactp) - *exactp = 1; - goto set1; - } - } - rc = 0; - goto set2; - } - } - /* If any parents have right-sibs, search. - * Otherwise, there's nothing further. - */ - for (i=0; imc_top; i++) - if (mc->mc_ki[i] < - NUMKEYS(mc->mc_pg[i])-1) - break; - if (i == mc->mc_top) { - /* There are no other pages */ - mc->mc_ki[mc->mc_top] = nkeys; - return MDB_NOTFOUND; - } - } - if (!mc->mc_top) { - /* There are no other pages */ - mc->mc_ki[mc->mc_top] = 0; - if (op == MDB_SET_RANGE && !exactp) { - rc = 0; - goto set1; - } else - return MDB_NOTFOUND; - } - } else { - mc->mc_pg[0] = 0; - } - - rc = mdb_page_search(mc, key, 0); - if (rc != MDB_SUCCESS) - return rc; - - mp = mc->mc_pg[mc->mc_top]; - mdb_cassert(mc, IS_LEAF(mp)); - -set2: - leaf = mdb_node_search(mc, key, exactp); - if (exactp != NULL && !*exactp) { - /* MDB_SET specified and not an exact match. */ - return MDB_NOTFOUND; - } - - if (leaf == NULL) { - DPUTS("===> inexact leaf not found, goto sibling"); - if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) { - mc->mc_flags |= C_EOF; - return rc; /* no entries matched */ - } - mp = mc->mc_pg[mc->mc_top]; - mdb_cassert(mc, IS_LEAF(mp)); - leaf = NODEPTR(mp, 0); - } - -set1: - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - - if (IS_LEAF2(mp)) { - if (op == MDB_SET_RANGE || op == MDB_SET_KEY) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); - } - return MDB_SUCCESS; - } - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - } - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - if (op == MDB_SET || op == MDB_SET_KEY || op == MDB_SET_RANGE) { - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - } else { - int ex2, *ex2p; - if (op == MDB_GET_BOTH) { - ex2p = &ex2; - ex2 = 0; - } else { - ex2p = NULL; - } - rc = mdb_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_SET_RANGE, ex2p); - if (rc != MDB_SUCCESS) - return rc; - } - } else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) { - MDB_val olddata; - MDB_cmp_func *dcmp; - if ((rc = mdb_node_read(mc, leaf, &olddata)) != MDB_SUCCESS) - return rc; - dcmp = mc->mc_dbx->md_dcmp; -#if UINT_MAX < SIZE_MAX || defined(MDB_VL32) - if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(mdb_size_t)) - dcmp = mdb_cmp_clong; -#endif - rc = dcmp(data, &olddata); - if (rc) { - if (op == MDB_GET_BOTH || rc > 0) - return MDB_NOTFOUND; - rc = 0; - } - *data = olddata; - - } else { - if (mc->mc_xcursor) - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - } - } - - /* The key already matches in all other cases */ - if (op == MDB_SET_RANGE || op == MDB_SET_KEY) - MDB_GET_KEY(leaf, key); - DPRINTF(("==> cursor placed on key [%s]", DKEY(key))); - - return rc; -} - -/** Move the cursor to the first item in the database. */ -static int -mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data) -{ - int rc; - MDB_node *leaf; - - if (mc->mc_xcursor) { -#ifdef MDB_VL32 - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - mdb_cursor_unref(&mc->mc_xcursor->mx_cursor); - } -#endif - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - } - - if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { - rc = mdb_page_search(mc, NULL, MDB_PS_FIRST); - if (rc != MDB_SUCCESS) - return rc; - } - mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - - leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0); - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - - mc->mc_ki[mc->mc_top] = 0; - - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->mv_size); - return MDB_SUCCESS; - } - - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc) - return rc; - } else { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - } - } - MDB_GET_KEY(leaf, key); - return MDB_SUCCESS; -} - -/** Move the cursor to the last item in the database. */ -static int -mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data) -{ - int rc; - MDB_node *leaf; - - if (mc->mc_xcursor) { -#ifdef MDB_VL32 - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - mdb_cursor_unref(&mc->mc_xcursor->mx_cursor); - } -#endif - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF); - } - - if (!(mc->mc_flags & C_EOF)) { - - if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { - rc = mdb_page_search(mc, NULL, MDB_PS_LAST); - if (rc != MDB_SUCCESS) - return rc; - } - mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - - } - mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1; - mc->mc_flags |= C_INITIALIZED|C_EOF; - leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->mv_size); - return MDB_SUCCESS; - } - - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - mdb_xcursor_init1(mc, leaf); - rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (rc) - return rc; - } else { - if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS) - return rc; - } - } - - MDB_GET_KEY(leaf, key); - return MDB_SUCCESS; -} - -int -mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data, - MDB_cursor_op op) -{ - int rc; - int exact = 0; - int (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data); - - if (mc == NULL) - return EINVAL; - - if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - switch (op) { - case MDB_GET_CURRENT: - if (!(mc->mc_flags & C_INITIALIZED)) { - rc = EINVAL; - } else { - MDB_page *mp = mc->mc_pg[mc->mc_top]; - int nkeys = NUMKEYS(mp); - if (!nkeys || mc->mc_ki[mc->mc_top] >= nkeys) { - mc->mc_ki[mc->mc_top] = nkeys; - rc = MDB_NOTFOUND; - break; - } - rc = MDB_SUCCESS; - if (IS_LEAF2(mp)) { - key->mv_size = mc->mc_db->md_pad; - key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size); - } else { - MDB_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - MDB_GET_KEY(leaf, key); - if (data) { - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT); - } else { - rc = mdb_node_read(mc, leaf, data); - } - } - } - } - break; - case MDB_GET_BOTH: - case MDB_GET_BOTH_RANGE: - if (data == NULL) { - rc = EINVAL; - break; - } - if (mc->mc_xcursor == NULL) { - rc = MDB_INCOMPATIBLE; - break; - } - /* FALLTHRU */ - case MDB_SET: - case MDB_SET_KEY: - case MDB_SET_RANGE: - if (key == NULL) { - rc = EINVAL; - } else { - rc = mdb_cursor_set(mc, key, data, op, - op == MDB_SET_RANGE ? NULL : &exact); - } - break; - case MDB_GET_MULTIPLE: - if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) { - rc = EINVAL; - break; - } - if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { - rc = MDB_INCOMPATIBLE; - break; - } - rc = MDB_SUCCESS; - if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) || - (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF)) - break; - goto fetchm; - case MDB_NEXT_MULTIPLE: - if (data == NULL) { - rc = EINVAL; - break; - } - if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { - rc = MDB_INCOMPATIBLE; - break; - } - if (!(mc->mc_flags & C_INITIALIZED)) - rc = mdb_cursor_first(mc, key, data); - else - rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP); - if (rc == MDB_SUCCESS) { - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - MDB_cursor *mx; -fetchm: - mx = &mc->mc_xcursor->mx_cursor; - data->mv_size = NUMKEYS(mx->mc_pg[mx->mc_top]) * - mx->mc_db->md_pad; - data->mv_data = METADATA(mx->mc_pg[mx->mc_top]); - mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top])-1; - } else { - rc = MDB_NOTFOUND; - } - } - break; - case MDB_PREV_MULTIPLE: - if (data == NULL) { - rc = EINVAL; - break; - } - if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { - rc = MDB_INCOMPATIBLE; - break; - } - if (!(mc->mc_flags & C_INITIALIZED)) - rc = mdb_cursor_last(mc, key, data); - else - rc = MDB_SUCCESS; - if (rc == MDB_SUCCESS) { - MDB_cursor *mx = &mc->mc_xcursor->mx_cursor; - if (mx->mc_flags & C_INITIALIZED) { - rc = mdb_cursor_sibling(mx, 0); - if (rc == MDB_SUCCESS) - goto fetchm; - } else { - rc = MDB_NOTFOUND; - } - } - break; - case MDB_NEXT: - case MDB_NEXT_DUP: - case MDB_NEXT_NODUP: - if (!(mc->mc_flags & C_INITIALIZED)) - rc = mdb_cursor_first(mc, key, data); - else - rc = mdb_cursor_next(mc, key, data, op); - break; - case MDB_PREV: - case MDB_PREV_DUP: - case MDB_PREV_NODUP: - if (!(mc->mc_flags & C_INITIALIZED)) { - rc = mdb_cursor_last(mc, key, data); - if (rc) - break; - mc->mc_flags |= C_INITIALIZED; - mc->mc_ki[mc->mc_top]++; - } - rc = mdb_cursor_prev(mc, key, data, op); - break; - case MDB_FIRST: - rc = mdb_cursor_first(mc, key, data); - break; - case MDB_FIRST_DUP: - mfunc = mdb_cursor_first; - mmove: - if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) { - rc = EINVAL; - break; - } - if (mc->mc_xcursor == NULL) { - rc = MDB_INCOMPATIBLE; - break; - } - { - MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { - MDB_GET_KEY(leaf, key); - rc = mdb_node_read(mc, leaf, data); - break; - } - } - if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { - rc = EINVAL; - break; - } - rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL); - break; - case MDB_LAST: - rc = mdb_cursor_last(mc, key, data); - break; - case MDB_LAST_DUP: - mfunc = mdb_cursor_last; - goto mmove; - default: - DPRINTF(("unhandled/unimplemented cursor operation %u", op)); - rc = EINVAL; - break; - } - - if (mc->mc_flags & C_DEL) - mc->mc_flags ^= C_DEL; - - return rc; -} - -/** Touch all the pages in the cursor stack. Set mc_top. - * Makes sure all the pages are writable, before attempting a write operation. - * @param[in] mc The cursor to operate on. - */ -static int -mdb_cursor_touch(MDB_cursor *mc) -{ - int rc = MDB_SUCCESS; - - if (mc->mc_dbi >= CORE_DBS && !(*mc->mc_dbflag & DB_DIRTY)) { - MDB_cursor mc2; - MDB_xcursor mcx; - if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) - return MDB_BAD_DBI; - mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, &mcx); - rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY); - if (rc) - return rc; - *mc->mc_dbflag |= DB_DIRTY; - } - mc->mc_top = 0; - if (mc->mc_snum) { - do { - rc = mdb_page_touch(mc); - } while (!rc && ++(mc->mc_top) < mc->mc_snum); - mc->mc_top = mc->mc_snum-1; - } - return rc; -} - -/** Do not spill pages to disk if txn is getting full, may fail instead */ -#define MDB_NOSPILL 0x8000 - -int -mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data, - unsigned int flags) -{ - MDB_env *env; - MDB_node *leaf = NULL; - MDB_page *fp, *mp, *sub_root = NULL; - uint16_t fp_flags; - MDB_val xdata, *rdata, dkey, olddata; - MDB_db dummy; - int do_sub = 0, insert_key, insert_data; - unsigned int mcount = 0, dcount = 0, nospill; - size_t nsize; - int rc, rc2; - unsigned int nflags; - DKBUF; - - if (mc == NULL || key == NULL) - return EINVAL; - - env = mc->mc_txn->mt_env; - - /* Check this first so counter will always be zero on any - * early failures. - */ - if (flags & MDB_MULTIPLE) { - dcount = data[1].mv_size; - data[1].mv_size = 0; - if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFIXED)) - return MDB_INCOMPATIBLE; - } - - nospill = flags & MDB_NOSPILL; - flags &= ~MDB_NOSPILL; - - if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)) - return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; - - if (key->mv_size-1 >= ENV_MAXKEY(env)) - return MDB_BAD_VALSIZE; - -#if SIZE_MAX > MAXDATASIZE - if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE)) - return MDB_BAD_VALSIZE; -#else - if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env)) - return MDB_BAD_VALSIZE; -#endif - - DPRINTF(("==> put db %d key [%s], size %"Z"u, data size %"Z"u", - DDBI(mc), DKEY(key), key ? key->mv_size : 0, data->mv_size)); - - dkey.mv_size = 0; - - if (flags == MDB_CURRENT) { - if (!(mc->mc_flags & C_INITIALIZED)) - return EINVAL; - rc = MDB_SUCCESS; - } else if (mc->mc_db->md_root == P_INVALID) { - /* new database, cursor has nothing to point to */ - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_flags &= ~C_INITIALIZED; - rc = MDB_NO_ROOT; - } else { - int exact = 0; - MDB_val d2; - if (flags & MDB_APPEND) { - MDB_val k2; - rc = mdb_cursor_last(mc, &k2, &d2); - if (rc == 0) { - rc = mc->mc_dbx->md_cmp(key, &k2); - if (rc > 0) { - rc = MDB_NOTFOUND; - mc->mc_ki[mc->mc_top]++; - } else { - /* new key is <= last key */ - rc = MDB_KEYEXIST; - } - } - } else { - rc = mdb_cursor_set(mc, key, &d2, MDB_SET, &exact); - } - if ((flags & MDB_NOOVERWRITE) && rc == 0) { - DPRINTF(("duplicate key [%s]", DKEY(key))); - *data = d2; - return MDB_KEYEXIST; - } - if (rc && rc != MDB_NOTFOUND) - return rc; - } - - if (mc->mc_flags & C_DEL) - mc->mc_flags ^= C_DEL; - - /* Cursor is positioned, check for room in the dirty list */ - if (!nospill) { - if (flags & MDB_MULTIPLE) { - rdata = &xdata; - xdata.mv_size = data->mv_size * dcount; - } else { - rdata = data; - } - if ((rc2 = mdb_page_spill(mc, key, rdata))) - return rc2; - } - - if (rc == MDB_NO_ROOT) { - MDB_page *np; - /* new database, write a root leaf page */ - DPUTS("allocating new root leaf page"); - if ((rc2 = mdb_page_new(mc, P_LEAF, 1, &np))) { - return rc2; - } - mdb_cursor_push(mc, np); - mc->mc_db->md_root = np->mp_pgno; - mc->mc_db->md_depth++; - *mc->mc_dbflag |= DB_DIRTY; - if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED)) - == MDB_DUPFIXED) - np->mp_flags |= P_LEAF2; - mc->mc_flags |= C_INITIALIZED; - } else { - /* make sure all cursor pages are writable */ - rc2 = mdb_cursor_touch(mc); - if (rc2) - return rc2; - } - - insert_key = insert_data = rc; - if (insert_key) { - /* The key does not exist */ - DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top])); - if ((mc->mc_db->md_flags & MDB_DUPSORT) && - LEAFSIZE(key, data) > env->me_nodemax) - { - /* Too big for a node, insert in sub-DB. Set up an empty - * "old sub-page" for prep_subDB to expand to a full page. - */ - fp_flags = P_LEAF|P_DIRTY; - fp = env->me_pbuf; - fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */ - fp->mp_lower = fp->mp_upper = (PAGEHDRSZ-PAGEBASE); - olddata.mv_size = PAGEHDRSZ; - goto prep_subDB; - } - } else { - /* there's only a key anyway, so this is a no-op */ - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - char *ptr; - unsigned int ksize = mc->mc_db->md_pad; - if (key->mv_size != ksize) - return MDB_BAD_VALSIZE; - ptr = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize); - memcpy(ptr, key->mv_data, ksize); -fix_parent: - /* if overwriting slot 0 of leaf, need to - * update branch key if there is a parent page - */ - if (mc->mc_top && !mc->mc_ki[mc->mc_top]) { - unsigned short dtop = 1; - mc->mc_top--; - /* slot 0 is always an empty key, find real slot */ - while (mc->mc_top && !mc->mc_ki[mc->mc_top]) { - mc->mc_top--; - dtop++; - } - if (mc->mc_ki[mc->mc_top]) - rc2 = mdb_update_key(mc, key); - else - rc2 = MDB_SUCCESS; - mc->mc_top += dtop; - if (rc2) - return rc2; - } - return MDB_SUCCESS; - } - -more: - leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - olddata.mv_size = NODEDSZ(leaf); - olddata.mv_data = NODEDATA(leaf); - - /* DB has dups? */ - if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) { - /* Prepare (sub-)page/sub-DB to accept the new item, - * if needed. fp: old sub-page or a header faking - * it. mp: new (sub-)page. offset: growth in page - * size. xdata: node data with new page or DB. - */ - unsigned i, offset = 0; - mp = fp = xdata.mv_data = env->me_pbuf; - mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno; - - /* Was a single item before, must convert now */ - if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { - MDB_cmp_func *dcmp; - /* Just overwrite the current item */ - if (flags == MDB_CURRENT) - goto current; - dcmp = mc->mc_dbx->md_dcmp; -#if UINT_MAX < SIZE_MAX || defined(MDB_VL32) - if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(mdb_size_t)) - dcmp = mdb_cmp_clong; -#endif - /* does data match? */ - if (!dcmp(data, &olddata)) { - if (flags & (MDB_NODUPDATA|MDB_APPENDDUP)) - return MDB_KEYEXIST; - /* overwrite it */ - goto current; - } - - /* Back up original data item */ - dkey.mv_size = olddata.mv_size; - dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size); - - /* Make sub-page header for the dup items, with dummy body */ - fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP; - fp->mp_lower = (PAGEHDRSZ-PAGEBASE); - xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size; - if (mc->mc_db->md_flags & MDB_DUPFIXED) { - fp->mp_flags |= P_LEAF2; - fp->mp_pad = data->mv_size; - xdata.mv_size += 2 * data->mv_size; /* leave space for 2 more */ - } else { - xdata.mv_size += 2 * (sizeof(indx_t) + NODESIZE) + - (dkey.mv_size & 1) + (data->mv_size & 1); - } - fp->mp_upper = xdata.mv_size - PAGEBASE; - olddata.mv_size = xdata.mv_size; /* pretend olddata is fp */ - } else if (leaf->mn_flags & F_SUBDATA) { - /* Data is on sub-DB, just store it */ - flags |= F_DUPDATA|F_SUBDATA; - goto put_sub; - } else { - /* Data is on sub-page */ - fp = olddata.mv_data; - switch (flags) { - default: - if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) { - offset = EVEN(NODESIZE + sizeof(indx_t) + - data->mv_size); - break; - } - offset = fp->mp_pad; - if (SIZELEFT(fp) < offset) { - offset *= 4; /* space for 4 more */ - break; - } - /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */ - case MDB_CURRENT: - fp->mp_flags |= P_DIRTY; - COPY_PGNO(fp->mp_pgno, mp->mp_pgno); - mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; - flags |= F_DUPDATA; - goto put_sub; - } - xdata.mv_size = olddata.mv_size + offset; - } - - fp_flags = fp->mp_flags; - if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) { - /* Too big for a sub-page, convert to sub-DB */ - fp_flags &= ~P_SUBP; -prep_subDB: - if (mc->mc_db->md_flags & MDB_DUPFIXED) { - fp_flags |= P_LEAF2; - dummy.md_pad = fp->mp_pad; - dummy.md_flags = MDB_DUPFIXED; - if (mc->mc_db->md_flags & MDB_INTEGERDUP) - dummy.md_flags |= MDB_INTEGERKEY; - } else { - dummy.md_pad = 0; - dummy.md_flags = 0; - } - dummy.md_depth = 1; - dummy.md_branch_pages = 0; - dummy.md_leaf_pages = 1; - dummy.md_overflow_pages = 0; - dummy.md_entries = NUMKEYS(fp); - xdata.mv_size = sizeof(MDB_db); - xdata.mv_data = &dummy; - if ((rc = mdb_page_alloc(mc, 1, &mp))) - return rc; - offset = env->me_psize - olddata.mv_size; - flags |= F_DUPDATA|F_SUBDATA; - dummy.md_root = mp->mp_pgno; - sub_root = mp; - } - if (mp != fp) { - mp->mp_flags = fp_flags | P_DIRTY; - mp->mp_pad = fp->mp_pad; - mp->mp_lower = fp->mp_lower; - mp->mp_upper = fp->mp_upper + offset; - if (fp_flags & P_LEAF2) { - memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad); - } else { - memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGEBASE, - olddata.mv_size - fp->mp_upper - PAGEBASE); - for (i=0; imp_ptrs[i] = fp->mp_ptrs[i] + offset; - } - } - - rdata = &xdata; - flags |= F_DUPDATA; - do_sub = 1; - if (!insert_key) - mdb_node_del(mc, 0); - goto new_sub; - } -current: - /* LMDB passes F_SUBDATA in 'flags' to write a DB record */ - if ((leaf->mn_flags ^ flags) & F_SUBDATA) - return MDB_INCOMPATIBLE; - /* overflow page overwrites need special handling */ - if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { - MDB_page *omp; - pgno_t pg; - int level, ovpages, dpages = OVPAGES(data->mv_size, env->me_psize); - - memcpy(&pg, olddata.mv_data, sizeof(pg)); - if ((rc2 = mdb_page_get(mc, pg, &omp, &level)) != 0) - return rc2; - ovpages = omp->mp_pages; - - /* Is the ov page large enough? */ - if (ovpages >= dpages) { - if (!(omp->mp_flags & P_DIRTY) && - (level || (env->me_flags & MDB_WRITEMAP))) - { - rc = mdb_page_unspill(mc->mc_txn, omp, &omp); - if (rc) - return rc; - level = 0; /* dirty in this txn or clean */ - } - /* Is it dirty? */ - if (omp->mp_flags & P_DIRTY) { - /* yes, overwrite it. Note in this case we don't - * bother to try shrinking the page if the new data - * is smaller than the overflow threshold. - */ - if (level > 1) { - /* It is writable only in a parent txn */ - size_t sz = (size_t) env->me_psize * ovpages, off; - MDB_page *np = mdb_page_malloc(mc->mc_txn, ovpages); - MDB_ID2 id2; - if (!np) - return ENOMEM; - id2.mid = pg; - id2.mptr = np; - /* Note - this page is already counted in parent's dirty_room */ - rc2 = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2); - mdb_cassert(mc, rc2 == 0); - if (!(flags & MDB_RESERVE)) { - /* Copy end of page, adjusting alignment so - * compiler may copy words instead of bytes. - */ - off = (PAGEHDRSZ + data->mv_size) & -sizeof(size_t); - memcpy((size_t *)((char *)np + off), - (size_t *)((char *)omp + off), sz - off); - sz = PAGEHDRSZ; - } - memcpy(np, omp, sz); /* Copy beginning of page */ - omp = np; - } - SETDSZ(leaf, data->mv_size); - if (F_ISSET(flags, MDB_RESERVE)) - data->mv_data = METADATA(omp); - else - memcpy(METADATA(omp), data->mv_data, data->mv_size); - return MDB_SUCCESS; - } - } - if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS) - return rc2; - } else if (data->mv_size == olddata.mv_size) { - /* same size, just replace it. Note that we could - * also reuse this node if the new data is smaller, - * but instead we opt to shrink the node in that case. - */ - if (F_ISSET(flags, MDB_RESERVE)) - data->mv_data = olddata.mv_data; - else if (!(mc->mc_flags & C_SUB)) - memcpy(olddata.mv_data, data->mv_data, data->mv_size); - else { - memcpy(NODEKEY(leaf), key->mv_data, key->mv_size); - goto fix_parent; - } - return MDB_SUCCESS; - } - mdb_node_del(mc, 0); - } - - rdata = data; - -new_sub: - nflags = flags & NODE_ADD_FLAGS; - nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); - if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) { - if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA ) - nflags &= ~MDB_APPEND; /* sub-page may need room to grow */ - if (!insert_key) - nflags |= MDB_SPLIT_REPLACE; - rc = mdb_page_split(mc, key, rdata, P_INVALID, nflags); - } else { - /* There is room already in this leaf page. */ - rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags); - if (rc == 0) { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2, *m3; - MDB_dbi dbi = mc->mc_dbi; - unsigned i = mc->mc_top; - MDB_page *mp = mc->mc_pg[i]; - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (mc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp) continue; - if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) { - m3->mc_ki[i]++; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { - MDB_node *n2 = NODEPTR(mp, m3->mc_ki[i]); - if ((n2->mn_flags & (F_SUBDATA|F_DUPDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2); - } - } - } - } - - if (rc == MDB_SUCCESS) { - /* Now store the actual data in the child DB. Note that we're - * storing the user data in the keys field, so there are strict - * size limits on dupdata. The actual data fields of the child - * DB are all zero size. - */ - if (do_sub) { - int xflags, new_dupdata; - mdb_size_t ecount; -put_sub: - xdata.mv_size = 0; - xdata.mv_data = ""; - leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (flags & MDB_CURRENT) { - xflags = MDB_CURRENT|MDB_NOSPILL; - } else { - mdb_xcursor_init1(mc, leaf); - xflags = (flags & MDB_NODUPDATA) ? - MDB_NOOVERWRITE|MDB_NOSPILL : MDB_NOSPILL; - } - if (sub_root) - mc->mc_xcursor->mx_cursor.mc_pg[0] = sub_root; - new_dupdata = (int)dkey.mv_size; - /* converted, write the original data first */ - if (dkey.mv_size) { - rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); - if (rc) - goto bad_sub; - /* we've done our job */ - dkey.mv_size = 0; - } - if (!(leaf->mn_flags & F_SUBDATA) || sub_root) { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2; - MDB_xcursor *mx = mc->mc_xcursor; - unsigned i = mc->mc_top; - MDB_page *mp = mc->mc_pg[i]; - int nkeys = NUMKEYS(mp); - - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { - if (m2 == mc || m2->mc_snum < mc->mc_snum) continue; - if (!(m2->mc_flags & C_INITIALIZED)) continue; - if (m2->mc_pg[i] == mp) { - if (m2->mc_ki[i] == mc->mc_ki[i]) { - mdb_xcursor_init2(m2, mx, new_dupdata); - } else if (!insert_key && m2->mc_ki[i] < nkeys) { - MDB_node *n2 = NODEPTR(mp, m2->mc_ki[i]); - if ((n2->mn_flags & (F_SUBDATA|F_DUPDATA)) == F_DUPDATA) - m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2); - } - } - } - } - ecount = mc->mc_xcursor->mx_db.md_entries; - if (flags & MDB_APPENDDUP) - xflags |= MDB_APPEND; - rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); - if (flags & F_SUBDATA) { - void *db = NODEDATA(leaf); - memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db)); - } - insert_data = mc->mc_xcursor->mx_db.md_entries - ecount; - } - /* Increment count unless we just replaced an existing item. */ - if (insert_data) - mc->mc_db->md_entries++; - if (insert_key) { - /* Invalidate txn if we created an empty sub-DB */ - if (rc) - goto bad_sub; - /* If we succeeded and the key didn't exist before, - * make sure the cursor is marked valid. - */ - mc->mc_flags |= C_INITIALIZED; - } - if (flags & MDB_MULTIPLE) { - if (!rc) { - mcount++; - /* let caller know how many succeeded, if any */ - data[1].mv_size = mcount; - if (mcount < dcount) { - data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; - insert_key = insert_data = 0; - goto more; - } - } - } - return rc; -bad_sub: - if (rc == MDB_KEYEXIST) /* should not happen, we deleted that item */ - rc = MDB_CORRUPTED; - } - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -int -mdb_cursor_del(MDB_cursor *mc, unsigned int flags) -{ - MDB_node *leaf; - MDB_page *mp; - int rc; - - if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)) - return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; - - if (!(mc->mc_flags & C_INITIALIZED)) - return EINVAL; - - if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) - return MDB_NOTFOUND; - - if (!(flags & MDB_NOSPILL) && (rc = mdb_page_spill(mc, NULL, NULL))) - return rc; - - rc = mdb_cursor_touch(mc); - if (rc) - return rc; - - mp = mc->mc_pg[mc->mc_top]; - if (IS_LEAF2(mp)) - goto del_key; - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - - if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { - if (flags & MDB_NODUPDATA) { - /* mdb_cursor_del0() will subtract the final entry */ - mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1; - mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; - } else { - if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { - mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); - } - rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL); - if (rc) - return rc; - /* If sub-DB still has entries, we're done */ - if (mc->mc_xcursor->mx_db.md_entries) { - if (leaf->mn_flags & F_SUBDATA) { - /* update subDB info */ - void *db = NODEDATA(leaf); - memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db)); - } else { - MDB_cursor *m2; - /* shrink fake page */ - mdb_node_shrink(mp, mc->mc_ki[mc->mc_top]); - leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); - mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); - /* fix other sub-DB cursors pointed at fake pages on this page */ - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) { - if (m2 == mc || m2->mc_snum < mc->mc_snum) continue; - if (!(m2->mc_flags & C_INITIALIZED)) continue; - if (m2->mc_pg[mc->mc_top] == mp) { - if (m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top]) { - m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); - } else { - MDB_node *n2 = NODEPTR(mp, m2->mc_ki[mc->mc_top]); - if (!(n2->mn_flags & F_SUBDATA)) - m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2); - } - } - } - } - mc->mc_db->md_entries--; - return rc; - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; - } - /* otherwise fall thru and delete the sub-DB */ - } - - if (leaf->mn_flags & F_SUBDATA) { - /* add all the child DB's pages to the free list */ - rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0); - if (rc) - goto fail; - } - } - /* LMDB passes F_SUBDATA in 'flags' to delete a DB record */ - else if ((leaf->mn_flags ^ flags) & F_SUBDATA) { - rc = MDB_INCOMPATIBLE; - goto fail; - } - - /* add overflow pages to free list */ - if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { - MDB_page *omp; - pgno_t pg; - - memcpy(&pg, NODEDATA(leaf), sizeof(pg)); - if ((rc = mdb_page_get(mc, pg, &omp, NULL)) || - (rc = mdb_ovpage_free(mc, omp))) - goto fail; - } - -del_key: - return mdb_cursor_del0(mc); - -fail: - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -/** Allocate and initialize new pages for a database. - * @param[in] mc a cursor on the database being added to. - * @param[in] flags flags defining what type of page is being allocated. - * @param[in] num the number of pages to allocate. This is usually 1, - * unless allocating overflow pages for a large record. - * @param[out] mp Address of a page, or NULL on failure. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp) -{ - MDB_page *np; - int rc; - - if ((rc = mdb_page_alloc(mc, num, &np))) - return rc; - DPRINTF(("allocated new mpage %"Y"u, page size %u", - np->mp_pgno, mc->mc_txn->mt_env->me_psize)); - np->mp_flags = flags | P_DIRTY; - np->mp_lower = (PAGEHDRSZ-PAGEBASE); - np->mp_upper = mc->mc_txn->mt_env->me_psize - PAGEBASE; - - if (IS_BRANCH(np)) - mc->mc_db->md_branch_pages++; - else if (IS_LEAF(np)) - mc->mc_db->md_leaf_pages++; - else if (IS_OVERFLOW(np)) { - mc->mc_db->md_overflow_pages += num; - np->mp_pages = num; - } - *mp = np; - - return 0; -} - -/** Calculate the size of a leaf node. - * The size depends on the environment's page size; if a data item - * is too large it will be put onto an overflow page and the node - * size will only include the key and not the data. Sizes are always - * rounded up to an even number of bytes, to guarantee 2-byte alignment - * of the #MDB_node headers. - * @param[in] env The environment handle. - * @param[in] key The key for the node. - * @param[in] data The data for the node. - * @return The number of bytes needed to store the node. - */ -static size_t -mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data) -{ - size_t sz; - - sz = LEAFSIZE(key, data); - if (sz > env->me_nodemax) { - /* put on overflow page */ - sz -= data->mv_size - sizeof(pgno_t); - } - - return EVEN(sz + sizeof(indx_t)); -} - -/** Calculate the size of a branch node. - * The size should depend on the environment's page size but since - * we currently don't support spilling large keys onto overflow - * pages, it's simply the size of the #MDB_node header plus the - * size of the key. Sizes are always rounded up to an even number - * of bytes, to guarantee 2-byte alignment of the #MDB_node headers. - * @param[in] env The environment handle. - * @param[in] key The key for the node. - * @return The number of bytes needed to store the node. - */ -static size_t -mdb_branch_size(MDB_env *env, MDB_val *key) -{ - size_t sz; - - sz = INDXSIZE(key); - if (sz > env->me_nodemax) { - /* put on overflow page */ - /* not implemented */ - /* sz -= key->size - sizeof(pgno_t); */ - } - - return sz + sizeof(indx_t); -} - -/** Add a node to the page pointed to by the cursor. - * @param[in] mc The cursor for this operation. - * @param[in] indx The index on the page where the new node should be added. - * @param[in] key The key for the new node. - * @param[in] data The data for the new node, if any. - * @param[in] pgno The page number, if adding a branch node. - * @param[in] flags Flags for the node. - * @return 0 on success, non-zero on failure. Possible errors are: - *
    - *
  • ENOMEM - failed to allocate overflow pages for the node. - *
  • MDB_PAGE_FULL - there is insufficient room in the page. This error - * should never happen since all callers already calculate the - * page's free space before calling this function. - *
- */ -static int -mdb_node_add(MDB_cursor *mc, indx_t indx, - MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags) -{ - unsigned int i; - size_t node_size = NODESIZE; - ssize_t room; - indx_t ofs; - MDB_node *node; - MDB_page *mp = mc->mc_pg[mc->mc_top]; - MDB_page *ofp = NULL; /* overflow page */ - void *ndata; - DKBUF; - - mdb_cassert(mc, mp->mp_upper >= mp->mp_lower); - - DPRINTF(("add to %s %spage %"Y"u index %i, data size %"Z"u key size %"Z"u [%s]", - IS_LEAF(mp) ? "leaf" : "branch", - IS_SUBP(mp) ? "sub-" : "", - mdb_dbg_pgno(mp), indx, data ? data->mv_size : 0, - key ? key->mv_size : 0, key ? DKEY(key) : "null")); - - if (IS_LEAF2(mp)) { - /* Move higher keys up one slot. */ - int ksize = mc->mc_db->md_pad, dif; - char *ptr = LEAF2KEY(mp, indx, ksize); - dif = NUMKEYS(mp) - indx; - if (dif > 0) - memmove(ptr+ksize, ptr, dif*ksize); - /* insert new key */ - memcpy(ptr, key->mv_data, ksize); - - /* Just using these for counting */ - mp->mp_lower += sizeof(indx_t); - mp->mp_upper -= ksize - sizeof(indx_t); - return MDB_SUCCESS; - } - - room = (ssize_t)SIZELEFT(mp) - (ssize_t)sizeof(indx_t); - if (key != NULL) - node_size += key->mv_size; - if (IS_LEAF(mp)) { - mdb_cassert(mc, key && data); - if (F_ISSET(flags, F_BIGDATA)) { - /* Data already on overflow page. */ - node_size += sizeof(pgno_t); - } else if (node_size + data->mv_size > mc->mc_txn->mt_env->me_nodemax) { - int ovpages = OVPAGES(data->mv_size, mc->mc_txn->mt_env->me_psize); - int rc; - /* Put data on overflow page. */ - DPRINTF(("data size is %"Z"u, node would be %"Z"u, put data on overflow page", - data->mv_size, node_size+data->mv_size)); - node_size = EVEN(node_size + sizeof(pgno_t)); - if ((ssize_t)node_size > room) - goto full; - if ((rc = mdb_page_new(mc, P_OVERFLOW, ovpages, &ofp))) - return rc; - DPRINTF(("allocated overflow page %"Y"u", ofp->mp_pgno)); - flags |= F_BIGDATA; - goto update; - } else { - node_size += data->mv_size; - } - } - node_size = EVEN(node_size); - if ((ssize_t)node_size > room) - goto full; - -update: - /* Move higher pointers up one slot. */ - for (i = NUMKEYS(mp); i > indx; i--) - mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; - - /* Adjust free space offsets. */ - ofs = mp->mp_upper - node_size; - mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t)); - mp->mp_ptrs[indx] = ofs; - mp->mp_upper = ofs; - mp->mp_lower += sizeof(indx_t); - - /* Write the node data. */ - node = NODEPTR(mp, indx); - node->mn_ksize = (key == NULL) ? 0 : key->mv_size; - node->mn_flags = flags; - if (IS_LEAF(mp)) - SETDSZ(node,data->mv_size); - else - SETPGNO(node,pgno); - - if (key) - memcpy(NODEKEY(node), key->mv_data, key->mv_size); - - if (IS_LEAF(mp)) { - ndata = NODEDATA(node); - if (ofp == NULL) { - if (F_ISSET(flags, F_BIGDATA)) - memcpy(ndata, data->mv_data, sizeof(pgno_t)); - else if (F_ISSET(flags, MDB_RESERVE)) - data->mv_data = ndata; - else - memcpy(ndata, data->mv_data, data->mv_size); - } else { - memcpy(ndata, &ofp->mp_pgno, sizeof(pgno_t)); - ndata = METADATA(ofp); - if (F_ISSET(flags, MDB_RESERVE)) - data->mv_data = ndata; - else - memcpy(ndata, data->mv_data, data->mv_size); - } - } - - return MDB_SUCCESS; - -full: - DPRINTF(("not enough room in page %"Y"u, got %u ptrs", - mdb_dbg_pgno(mp), NUMKEYS(mp))); - DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room)); - DPRINTF(("node size = %"Z"u", node_size)); - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return MDB_PAGE_FULL; -} - -/** Delete the specified node from a page. - * @param[in] mc Cursor pointing to the node to delete. - * @param[in] ksize The size of a node. Only used if the page is - * part of a #MDB_DUPFIXED database. - */ -static void -mdb_node_del(MDB_cursor *mc, int ksize) -{ - MDB_page *mp = mc->mc_pg[mc->mc_top]; - indx_t indx = mc->mc_ki[mc->mc_top]; - unsigned int sz; - indx_t i, j, numkeys, ptr; - MDB_node *node; - char *base; - - DPRINTF(("delete node %u on %s page %"Y"u", indx, - IS_LEAF(mp) ? "leaf" : "branch", mdb_dbg_pgno(mp))); - numkeys = NUMKEYS(mp); - mdb_cassert(mc, indx < numkeys); - - if (IS_LEAF2(mp)) { - int x = numkeys - 1 - indx; - base = LEAF2KEY(mp, indx, ksize); - if (x) - memmove(base, base + ksize, x * ksize); - mp->mp_lower -= sizeof(indx_t); - mp->mp_upper += ksize - sizeof(indx_t); - return; - } - - node = NODEPTR(mp, indx); - sz = NODESIZE + node->mn_ksize; - if (IS_LEAF(mp)) { - if (F_ISSET(node->mn_flags, F_BIGDATA)) - sz += sizeof(pgno_t); - else - sz += NODEDSZ(node); - } - sz = EVEN(sz); - - ptr = mp->mp_ptrs[indx]; - for (i = j = 0; i < numkeys; i++) { - if (i != indx) { - mp->mp_ptrs[j] = mp->mp_ptrs[i]; - if (mp->mp_ptrs[i] < ptr) - mp->mp_ptrs[j] += sz; - j++; - } - } - - base = (char *)mp + mp->mp_upper + PAGEBASE; - memmove(base + sz, base, ptr - mp->mp_upper); - - mp->mp_lower -= sizeof(indx_t); - mp->mp_upper += sz; -} - -/** Compact the main page after deleting a node on a subpage. - * @param[in] mp The main page to operate on. - * @param[in] indx The index of the subpage on the main page. - */ -static void -mdb_node_shrink(MDB_page *mp, indx_t indx) -{ - MDB_node *node; - MDB_page *sp, *xp; - char *base; - indx_t delta, nsize, len, ptr; - int i; - - node = NODEPTR(mp, indx); - sp = (MDB_page *)NODEDATA(node); - delta = SIZELEFT(sp); - nsize = NODEDSZ(node) - delta; - - /* Prepare to shift upward, set len = length(subpage part to shift) */ - if (IS_LEAF2(sp)) { - len = nsize; - if (nsize & 1) - return; /* do not make the node uneven-sized */ - } else { - xp = (MDB_page *)((char *)sp + delta); /* destination subpage */ - for (i = NUMKEYS(sp); --i >= 0; ) - xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta; - len = PAGEHDRSZ; - } - sp->mp_upper = sp->mp_lower; - COPY_PGNO(sp->mp_pgno, mp->mp_pgno); - SETDSZ(node, nsize); - - /* Shift upward */ - base = (char *)mp + mp->mp_upper + PAGEBASE; - memmove(base + delta, base, (char *)sp + len - base); - - ptr = mp->mp_ptrs[indx]; - for (i = NUMKEYS(mp); --i >= 0; ) { - if (mp->mp_ptrs[i] <= ptr) - mp->mp_ptrs[i] += delta; - } - mp->mp_upper += delta; -} - -/** Initial setup of a sorted-dups cursor. - * Sorted duplicates are implemented as a sub-database for the given key. - * The duplicate data items are actually keys of the sub-database. - * Operations on the duplicate data items are performed using a sub-cursor - * initialized when the sub-database is first accessed. This function does - * the preliminary setup of the sub-cursor, filling in the fields that - * depend only on the parent DB. - * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized. - */ -static void -mdb_xcursor_init0(MDB_cursor *mc) -{ - MDB_xcursor *mx = mc->mc_xcursor; - - mx->mx_cursor.mc_xcursor = NULL; - mx->mx_cursor.mc_txn = mc->mc_txn; - mx->mx_cursor.mc_db = &mx->mx_db; - mx->mx_cursor.mc_dbx = &mx->mx_dbx; - mx->mx_cursor.mc_dbi = mc->mc_dbi; - mx->mx_cursor.mc_dbflag = &mx->mx_dbflag; - mx->mx_cursor.mc_snum = 0; - mx->mx_cursor.mc_top = 0; -#ifdef MDB_VL32 - mx->mx_cursor.mc_ovpg = 0; -#endif - mx->mx_cursor.mc_flags = C_SUB | (mc->mc_flags & (C_ORIG_RDONLY|C_WRITEMAP)); - mx->mx_dbx.md_name.mv_size = 0; - mx->mx_dbx.md_name.mv_data = NULL; - mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp; - mx->mx_dbx.md_dcmp = NULL; - mx->mx_dbx.md_rel = mc->mc_dbx->md_rel; -} - -/** Final setup of a sorted-dups cursor. - * Sets up the fields that depend on the data from the main cursor. - * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized. - * @param[in] node The data containing the #MDB_db record for the - * sorted-dup database. - */ -static void -mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node) -{ - MDB_xcursor *mx = mc->mc_xcursor; - - mx->mx_cursor.mc_flags &= C_SUB|C_ORIG_RDONLY|C_WRITEMAP; - if (node->mn_flags & F_SUBDATA) { - memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDB_db)); - mx->mx_cursor.mc_pg[0] = 0; - mx->mx_cursor.mc_snum = 0; - mx->mx_cursor.mc_top = 0; - } else { - MDB_page *fp = NODEDATA(node); - mx->mx_db.md_pad = 0; - mx->mx_db.md_flags = 0; - mx->mx_db.md_depth = 1; - mx->mx_db.md_branch_pages = 0; - mx->mx_db.md_leaf_pages = 1; - mx->mx_db.md_overflow_pages = 0; - mx->mx_db.md_entries = NUMKEYS(fp); - COPY_PGNO(mx->mx_db.md_root, fp->mp_pgno); - mx->mx_cursor.mc_snum = 1; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags |= C_INITIALIZED; - mx->mx_cursor.mc_pg[0] = fp; - mx->mx_cursor.mc_ki[0] = 0; - if (mc->mc_db->md_flags & MDB_DUPFIXED) { - mx->mx_db.md_flags = MDB_DUPFIXED; - mx->mx_db.md_pad = fp->mp_pad; - if (mc->mc_db->md_flags & MDB_INTEGERDUP) - mx->mx_db.md_flags |= MDB_INTEGERKEY; - } - } - DPRINTF(("Sub-db -%u root page %"Y"u", mx->mx_cursor.mc_dbi, - mx->mx_db.md_root)); - mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */ -#if UINT_MAX < SIZE_MAX || defined(MDB_VL32) - if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_pad == sizeof(mdb_size_t)) - mx->mx_dbx.md_cmp = mdb_cmp_clong; -#endif -} - - -/** Fixup a sorted-dups cursor due to underlying update. - * Sets up some fields that depend on the data from the main cursor. - * Almost the same as init1, but skips initialization steps if the - * xcursor had already been used. - * @param[in] mc The main cursor whose sorted-dups cursor is to be fixed up. - * @param[in] src_mx The xcursor of an up-to-date cursor. - * @param[in] new_dupdata True if converting from a non-#F_DUPDATA item. - */ -static void -mdb_xcursor_init2(MDB_cursor *mc, MDB_xcursor *src_mx, int new_dupdata) -{ - MDB_xcursor *mx = mc->mc_xcursor; - - if (new_dupdata) { - mx->mx_cursor.mc_snum = 1; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags |= C_INITIALIZED; - mx->mx_cursor.mc_ki[0] = 0; - mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */ -#if UINT_MAX < SIZE_MAX - mx->mx_dbx.md_cmp = src_mx->mx_dbx.md_cmp; -#endif - } else if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) { - return; - } - mx->mx_db = src_mx->mx_db; - mx->mx_cursor.mc_pg[0] = src_mx->mx_cursor.mc_pg[0]; - DPRINTF(("Sub-db -%u root page %"Y"u", mx->mx_cursor.mc_dbi, - mx->mx_db.md_root)); -} - -/** Initialize a cursor for a given transaction and database. */ -static void -mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx) -{ - mc->mc_next = NULL; - mc->mc_backup = NULL; - mc->mc_dbi = dbi; - mc->mc_txn = txn; - mc->mc_db = &txn->mt_dbs[dbi]; - mc->mc_dbx = &txn->mt_dbxs[dbi]; - mc->mc_dbflag = &txn->mt_dbflags[dbi]; - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_pg[0] = 0; - mc->mc_ki[0] = 0; -#ifdef MDB_VL32 - mc->mc_ovpg = 0; -#endif - mc->mc_flags = txn->mt_flags & (C_ORIG_RDONLY|C_WRITEMAP); - if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) { - mdb_tassert(txn, mx != NULL); - mc->mc_xcursor = mx; - mdb_xcursor_init0(mc); - } else { - mc->mc_xcursor = NULL; - } - if (*mc->mc_dbflag & DB_STALE) { - mdb_page_search(mc, NULL, MDB_PS_ROOTONLY); - } -} - -int -mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret) -{ - MDB_cursor *mc; - size_t size = sizeof(MDB_cursor); - - if (!ret || !TXN_DBI_EXIST(txn, dbi, DB_VALID)) - return EINVAL; - - if (txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - if (dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) - return EINVAL; - - if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) - size += sizeof(MDB_xcursor); - - if ((mc = malloc(size)) != NULL) { - mdb_cursor_init(mc, txn, dbi, (MDB_xcursor *)(mc + 1)); - if (txn->mt_cursors) { - mc->mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = mc; - mc->mc_flags |= C_UNTRACK; - } - } else { - return ENOMEM; - } - - *ret = mc; - - return MDB_SUCCESS; -} - -int -mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc) -{ - if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID)) - return EINVAL; - - if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors) - return EINVAL; - - if (txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - mdb_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor); - return MDB_SUCCESS; -} - -/* Return the count of duplicate data items for the current key */ -int -mdb_cursor_count(MDB_cursor *mc, mdb_size_t *countp) -{ - MDB_node *leaf; - - if (mc == NULL || countp == NULL) - return EINVAL; - - if (mc->mc_xcursor == NULL) - return MDB_INCOMPATIBLE; - - if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - if (!(mc->mc_flags & C_INITIALIZED)) - return EINVAL; - - if (!mc->mc_snum || (mc->mc_flags & C_EOF)) - return MDB_NOTFOUND; - - leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { - *countp = 1; - } else { - if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) - return EINVAL; - - *countp = mc->mc_xcursor->mx_db.md_entries; - } - return MDB_SUCCESS; -} - -void -mdb_cursor_close(MDB_cursor *mc) -{ -#ifdef MDB_VL32 - if (mc) { - mdb_cursor_unref(mc); - } -#endif - if (mc && !mc->mc_backup) { - /* remove from txn, if tracked */ - if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { - MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; - while (*prev && *prev != mc) prev = &(*prev)->mc_next; - if (*prev == mc) - *prev = mc->mc_next; - } - free(mc); - } -} - -MDB_txn * -mdb_cursor_txn(MDB_cursor *mc) -{ - if (!mc) return NULL; - return mc->mc_txn; -} - -MDB_dbi -mdb_cursor_dbi(MDB_cursor *mc) -{ - return mc->mc_dbi; -} - -/** Replace the key for a branch node with a new key. - * @param[in] mc Cursor pointing to the node to operate on. - * @param[in] key The new key to use. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_update_key(MDB_cursor *mc, MDB_val *key) -{ - MDB_page *mp; - MDB_node *node; - char *base; - size_t len; - int delta, ksize, oksize; - indx_t ptr, i, numkeys, indx; - DKBUF; - - indx = mc->mc_ki[mc->mc_top]; - mp = mc->mc_pg[mc->mc_top]; - node = NODEPTR(mp, indx); - ptr = mp->mp_ptrs[indx]; -#if MDB_DEBUG - { - MDB_val k2; - char kbuf2[DKBUF_MAXKEYSIZE*2+1]; - k2.mv_data = NODEKEY(node); - k2.mv_size = node->mn_ksize; - DPRINTF(("update key %u (ofs %u) [%s] to [%s] on page %"Y"u", - indx, ptr, - mdb_dkey(&k2, kbuf2), - DKEY(key), - mp->mp_pgno)); - } -#endif - - /* Sizes must be 2-byte aligned. */ - ksize = EVEN(key->mv_size); - oksize = EVEN(node->mn_ksize); - delta = ksize - oksize; - - /* Shift node contents if EVEN(key length) changed. */ - if (delta) { - if (delta > 0 && SIZELEFT(mp) < delta) { - pgno_t pgno; - /* not enough space left, do a delete and split */ - DPRINTF(("Not enough room, delta = %d, splitting...", delta)); - pgno = NODEPGNO(node); - mdb_node_del(mc, 0); - return mdb_page_split(mc, key, NULL, pgno, MDB_SPLIT_REPLACE); - } - - numkeys = NUMKEYS(mp); - for (i = 0; i < numkeys; i++) { - if (mp->mp_ptrs[i] <= ptr) - mp->mp_ptrs[i] -= delta; - } - - base = (char *)mp + mp->mp_upper + PAGEBASE; - len = ptr - mp->mp_upper + NODESIZE; - memmove(base - delta, base, len); - mp->mp_upper -= delta; - - node = NODEPTR(mp, indx); - } - - /* But even if no shift was needed, update ksize */ - if (node->mn_ksize != key->mv_size) - node->mn_ksize = key->mv_size; - - if (key->mv_size) - memcpy(NODEKEY(node), key->mv_data, key->mv_size); - - return MDB_SUCCESS; -} - -static void -mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst); - -/** Perform \b act while tracking temporary cursor \b mn */ -#define WITH_CURSOR_TRACKING(mn, act) do { \ - MDB_cursor dummy, *tracked, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ - if ((mn).mc_flags & C_SUB) { \ - dummy.mc_flags = C_INITIALIZED; \ - dummy.mc_xcursor = (MDB_xcursor *)&(mn); \ - tracked = &dummy; \ - } else { \ - tracked = &(mn); \ - } \ - tracked->mc_next = *tp; \ - *tp = tracked; \ - { act; } \ - *tp = tracked->mc_next; \ -} while (0) - -/** Move a node from csrc to cdst. - */ -static int -mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft) -{ - MDB_node *srcnode; - MDB_val key, data; - pgno_t srcpg; - MDB_cursor mn; - int rc; - unsigned short flags; - - DKBUF; - - /* Mark src and dst as dirty. */ - if ((rc = mdb_page_touch(csrc)) || - (rc = mdb_page_touch(cdst))) - return rc; - - if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { - key.mv_size = csrc->mc_db->md_pad; - key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size); - data.mv_size = 0; - data.mv_data = NULL; - srcpg = 0; - flags = 0; - } else { - srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]); - mdb_cassert(csrc, !((size_t)srcnode & 1)); - srcpg = NODEPGNO(srcnode); - flags = srcnode->mn_flags; - if (csrc->mc_ki[csrc->mc_top] == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) { - unsigned int snum = csrc->mc_snum; - MDB_node *s2; - /* must find the lowest key below src */ - rc = mdb_page_search_lowest(csrc); - if (rc) - return rc; - if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { - key.mv_size = csrc->mc_db->md_pad; - key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size); - } else { - s2 = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); - key.mv_size = NODEKSZ(s2); - key.mv_data = NODEKEY(s2); - } - csrc->mc_snum = snum--; - csrc->mc_top = snum; - } else { - key.mv_size = NODEKSZ(srcnode); - key.mv_data = NODEKEY(srcnode); - } - data.mv_size = NODEDSZ(srcnode); - data.mv_data = NODEDATA(srcnode); - } - mn.mc_xcursor = NULL; - if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) { - unsigned int snum = cdst->mc_snum; - MDB_node *s2; - MDB_val bkey; - /* must find the lowest key below dst */ - mdb_cursor_copy(cdst, &mn); - rc = mdb_page_search_lowest(&mn); - if (rc) - return rc; - if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { - bkey.mv_size = mn.mc_db->md_pad; - bkey.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, bkey.mv_size); - } else { - s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0); - bkey.mv_size = NODEKSZ(s2); - bkey.mv_data = NODEKEY(s2); - } - mn.mc_snum = snum--; - mn.mc_top = snum; - mn.mc_ki[snum] = 0; - rc = mdb_update_key(&mn, &bkey); - if (rc) - return rc; - } - - DPRINTF(("moving %s node %u [%s] on page %"Y"u to node %u on page %"Y"u", - IS_LEAF(csrc->mc_pg[csrc->mc_top]) ? "leaf" : "branch", - csrc->mc_ki[csrc->mc_top], - DKEY(&key), - csrc->mc_pg[csrc->mc_top]->mp_pgno, - cdst->mc_ki[cdst->mc_top], cdst->mc_pg[cdst->mc_top]->mp_pgno)); - - /* Add the node to the destination page. - */ - rc = mdb_node_add(cdst, cdst->mc_ki[cdst->mc_top], &key, &data, srcpg, flags); - if (rc != MDB_SUCCESS) - return rc; - - /* Delete the node from the source page. - */ - mdb_node_del(csrc, key.mv_size); - - { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2, *m3; - MDB_dbi dbi = csrc->mc_dbi; - MDB_page *mpd, *mps; - - mps = csrc->mc_pg[csrc->mc_top]; - /* If we're adding on the left, bump others up */ - if (fromleft) { - mpd = cdst->mc_pg[csrc->mc_top]; - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (csrc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) - continue; - if (m3 != cdst && - m3->mc_pg[csrc->mc_top] == mpd && - m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) { - m3->mc_ki[csrc->mc_top]++; - } - if (m3 !=csrc && - m3->mc_pg[csrc->mc_top] == mps && - m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) { - m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top]; - m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; - m3->mc_ki[csrc->mc_top-1]++; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) && - IS_LEAF(mps)) { - MDB_node *node = NODEPTR(m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } - } - } else - /* Adding on the right, bump others down */ - { - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (csrc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (m3 == csrc) continue; - if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) - continue; - if (m3->mc_pg[csrc->mc_top] == mps) { - if (!m3->mc_ki[csrc->mc_top]) { - m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top]; - m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; - m3->mc_ki[csrc->mc_top-1]--; - } else { - m3->mc_ki[csrc->mc_top]--; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) && - IS_LEAF(mps)) { - MDB_node *node = NODEPTR(m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } - } - } - } - } - - /* Update the parent separators. - */ - if (csrc->mc_ki[csrc->mc_top] == 0) { - if (csrc->mc_ki[csrc->mc_top-1] != 0) { - if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { - key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size); - } else { - srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); - key.mv_size = NODEKSZ(srcnode); - key.mv_data = NODEKEY(srcnode); - } - DPRINTF(("update separator for source page %"Y"u to [%s]", - csrc->mc_pg[csrc->mc_top]->mp_pgno, DKEY(&key))); - mdb_cursor_copy(csrc, &mn); - mn.mc_snum--; - mn.mc_top--; - /* We want mdb_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, - rc = mdb_update_key(&mn, &key)); - if (rc) - return rc; - } - if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) { - MDB_val nullkey; - indx_t ix = csrc->mc_ki[csrc->mc_top]; - nullkey.mv_size = 0; - csrc->mc_ki[csrc->mc_top] = 0; - rc = mdb_update_key(csrc, &nullkey); - csrc->mc_ki[csrc->mc_top] = ix; - mdb_cassert(csrc, rc == MDB_SUCCESS); - } - } - - if (cdst->mc_ki[cdst->mc_top] == 0) { - if (cdst->mc_ki[cdst->mc_top-1] != 0) { - if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) { - key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size); - } else { - srcnode = NODEPTR(cdst->mc_pg[cdst->mc_top], 0); - key.mv_size = NODEKSZ(srcnode); - key.mv_data = NODEKEY(srcnode); - } - DPRINTF(("update separator for destination page %"Y"u to [%s]", - cdst->mc_pg[cdst->mc_top]->mp_pgno, DKEY(&key))); - mdb_cursor_copy(cdst, &mn); - mn.mc_snum--; - mn.mc_top--; - /* We want mdb_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, - rc = mdb_update_key(&mn, &key)); - if (rc) - return rc; - } - if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) { - MDB_val nullkey; - indx_t ix = cdst->mc_ki[cdst->mc_top]; - nullkey.mv_size = 0; - cdst->mc_ki[cdst->mc_top] = 0; - rc = mdb_update_key(cdst, &nullkey); - cdst->mc_ki[cdst->mc_top] = ix; - mdb_cassert(cdst, rc == MDB_SUCCESS); - } - } - - return MDB_SUCCESS; -} - -/** Merge one page into another. - * The nodes from the page pointed to by \b csrc will - * be copied to the page pointed to by \b cdst and then - * the \b csrc page will be freed. - * @param[in] csrc Cursor pointing to the source page. - * @param[in] cdst Cursor pointing to the destination page. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst) -{ - MDB_page *psrc, *pdst; - MDB_node *srcnode; - MDB_val key, data; - unsigned nkeys; - int rc; - indx_t i, j; - - psrc = csrc->mc_pg[csrc->mc_top]; - pdst = cdst->mc_pg[cdst->mc_top]; - - DPRINTF(("merging page %"Y"u into %"Y"u", psrc->mp_pgno, pdst->mp_pgno)); - - mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */ - mdb_cassert(csrc, cdst->mc_snum > 1); - - /* Mark dst as dirty. */ - if ((rc = mdb_page_touch(cdst))) - return rc; - - /* get dst page again now that we've touched it. */ - pdst = cdst->mc_pg[cdst->mc_top]; - - /* Move all nodes from src to dst. - */ - j = nkeys = NUMKEYS(pdst); - if (IS_LEAF2(psrc)) { - key.mv_size = csrc->mc_db->md_pad; - key.mv_data = METADATA(psrc); - for (i = 0; i < NUMKEYS(psrc); i++, j++) { - rc = mdb_node_add(cdst, j, &key, NULL, 0, 0); - if (rc != MDB_SUCCESS) - return rc; - key.mv_data = (char *)key.mv_data + key.mv_size; - } - } else { - for (i = 0; i < NUMKEYS(psrc); i++, j++) { - srcnode = NODEPTR(psrc, i); - if (i == 0 && IS_BRANCH(psrc)) { - MDB_cursor mn; - MDB_node *s2; - mdb_cursor_copy(csrc, &mn); - mn.mc_xcursor = NULL; - /* must find the lowest key below src */ - rc = mdb_page_search_lowest(&mn); - if (rc) - return rc; - if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { - key.mv_size = mn.mc_db->md_pad; - key.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.mv_size); - } else { - s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0); - key.mv_size = NODEKSZ(s2); - key.mv_data = NODEKEY(s2); - } - } else { - key.mv_size = srcnode->mn_ksize; - key.mv_data = NODEKEY(srcnode); - } - - data.mv_size = NODEDSZ(srcnode); - data.mv_data = NODEDATA(srcnode); - rc = mdb_node_add(cdst, j, &key, &data, NODEPGNO(srcnode), srcnode->mn_flags); - if (rc != MDB_SUCCESS) - return rc; - } - } - - DPRINTF(("dst page %"Y"u now has %u keys (%.1f%% filled)", - pdst->mp_pgno, NUMKEYS(pdst), - (float)PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10)); - - /* Unlink the src page from parent and add to free list. - */ - csrc->mc_top--; - mdb_node_del(csrc, 0); - if (csrc->mc_ki[csrc->mc_top] == 0) { - key.mv_size = 0; - rc = mdb_update_key(csrc, &key); - if (rc) { - csrc->mc_top++; - return rc; - } - } - csrc->mc_top++; - - psrc = csrc->mc_pg[csrc->mc_top]; - /* If not operating on FreeDB, allow this page to be reused - * in this txn. Otherwise just add to free list. - */ - rc = mdb_page_loose(csrc, psrc); - if (rc) - return rc; - if (IS_LEAF(psrc)) - csrc->mc_db->md_leaf_pages--; - else - csrc->mc_db->md_branch_pages--; - { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2, *m3; - MDB_dbi dbi = csrc->mc_dbi; - unsigned int top = csrc->mc_top; - - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (csrc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (m3 == csrc) continue; - if (m3->mc_snum < csrc->mc_snum) continue; - if (m3->mc_pg[top] == psrc) { - m3->mc_pg[top] = pdst; - m3->mc_ki[top] += nkeys; - m3->mc_ki[top-1] = cdst->mc_ki[top-1]; - } else if (m3->mc_pg[top-1] == csrc->mc_pg[top-1] && - m3->mc_ki[top-1] > csrc->mc_ki[top-1]) { - m3->mc_ki[top-1]--; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) && - IS_LEAF(psrc)) { - MDB_node *node = NODEPTR(m3->mc_pg[top], m3->mc_ki[top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } - } - } - { - unsigned int snum = cdst->mc_snum; - uint16_t depth = cdst->mc_db->md_depth; - mdb_cursor_pop(cdst); - rc = mdb_rebalance(cdst); - /* Did the tree height change? */ - if (depth != cdst->mc_db->md_depth) - snum += cdst->mc_db->md_depth - depth; - cdst->mc_snum = snum; - cdst->mc_top = snum-1; - } - return rc; -} - -/** Copy the contents of a cursor. - * @param[in] csrc The cursor to copy from. - * @param[out] cdst The cursor to copy to. - */ -static void -mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst) -{ - unsigned int i; - - cdst->mc_txn = csrc->mc_txn; - cdst->mc_dbi = csrc->mc_dbi; - cdst->mc_db = csrc->mc_db; - cdst->mc_dbx = csrc->mc_dbx; - cdst->mc_snum = csrc->mc_snum; - cdst->mc_top = csrc->mc_top; - cdst->mc_flags = csrc->mc_flags; -#ifdef MDB_VL32 - cdst->mc_ovpg = csrc->mc_ovpg; -#endif - - for (i=0; imc_snum; i++) { - cdst->mc_pg[i] = csrc->mc_pg[i]; - cdst->mc_ki[i] = csrc->mc_ki[i]; - } -} - -/** Rebalance the tree after a delete operation. - * @param[in] mc Cursor pointing to the page where rebalancing - * should begin. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_rebalance(MDB_cursor *mc) -{ - MDB_node *node; - int rc, fromleft; - unsigned int ptop, minkeys, thresh; - MDB_cursor mn; - indx_t oldki; - - if (IS_BRANCH(mc->mc_pg[mc->mc_top])) { - minkeys = 2; - thresh = 1; - } else { - minkeys = 1; - thresh = FILL_THRESHOLD; - } - DPRINTF(("rebalancing %s page %"Y"u (has %u keys, %.1f%% full)", - IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch", - mdb_dbg_pgno(mc->mc_pg[mc->mc_top]), NUMKEYS(mc->mc_pg[mc->mc_top]), - (float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10)); - - if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= thresh && - NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) { - DPRINTF(("no need to rebalance page %"Y"u, above fill threshold", - mdb_dbg_pgno(mc->mc_pg[mc->mc_top]))); - return MDB_SUCCESS; - } - - if (mc->mc_snum < 2) { - MDB_page *mp = mc->mc_pg[0]; - if (IS_SUBP(mp)) { - DPUTS("Can't rebalance a subpage, ignoring"); - return MDB_SUCCESS; - } - if (NUMKEYS(mp) == 0) { - DPUTS("tree is completely empty"); - mc->mc_db->md_root = P_INVALID; - mc->mc_db->md_depth = 0; - mc->mc_db->md_leaf_pages = 0; - rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno); - if (rc) - return rc; - /* Adjust cursors pointing to mp */ - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_flags &= ~C_INITIALIZED; - { - MDB_cursor *m2, *m3; - MDB_dbi dbi = mc->mc_dbi; - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (mc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum)) - continue; - if (m3->mc_pg[0] == mp) { - m3->mc_snum = 0; - m3->mc_top = 0; - m3->mc_flags &= ~C_INITIALIZED; - } - } - } - } else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) { - int i; - DPUTS("collapsing root page!"); - rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno); - if (rc) - return rc; - mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0)); - rc = mdb_page_get(mc, mc->mc_db->md_root, &mc->mc_pg[0], NULL); - if (rc) - return rc; - mc->mc_db->md_depth--; - mc->mc_db->md_branch_pages--; - mc->mc_ki[0] = mc->mc_ki[1]; - for (i = 1; imc_db->md_depth; i++) { - mc->mc_pg[i] = mc->mc_pg[i+1]; - mc->mc_ki[i] = mc->mc_ki[i+1]; - } - { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2, *m3; - MDB_dbi dbi = mc->mc_dbi; - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (mc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (m3 == mc) continue; - if (!(m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_pg[0] == mp) { - for (i=0; imc_db->md_depth; i++) { - m3->mc_pg[i] = m3->mc_pg[i+1]; - m3->mc_ki[i] = m3->mc_ki[i+1]; - } - m3->mc_snum--; - m3->mc_top--; - } - } - } - } else - DPUTS("root page doesn't need rebalancing"); - return MDB_SUCCESS; - } - - /* The parent (branch page) must have at least 2 pointers, - * otherwise the tree is invalid. - */ - ptop = mc->mc_top-1; - mdb_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1); - - /* Leaf page fill factor is below the threshold. - * Try to move keys from left or right neighbor, or - * merge with a neighbor page. - */ - - /* Find neighbors. - */ - mdb_cursor_copy(mc, &mn); - mn.mc_xcursor = NULL; - - oldki = mc->mc_ki[mc->mc_top]; - if (mc->mc_ki[ptop] == 0) { - /* We're the leftmost leaf in our parent. - */ - DPUTS("reading right neighbor"); - mn.mc_ki[ptop]++; - node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]); - rc = mdb_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL); - if (rc) - return rc; - mn.mc_ki[mn.mc_top] = 0; - mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]); - fromleft = 0; - } else { - /* There is at least one neighbor to the left. - */ - DPUTS("reading left neighbor"); - mn.mc_ki[ptop]--; - node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]); - rc = mdb_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL); - if (rc) - return rc; - mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1; - mc->mc_ki[mc->mc_top] = 0; - fromleft = 1; - } - - DPRINTF(("found neighbor page %"Y"u (%u keys, %.1f%% full)", - mn.mc_pg[mn.mc_top]->mp_pgno, NUMKEYS(mn.mc_pg[mn.mc_top]), - (float)PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) / 10)); - - /* If the neighbor page is above threshold and has enough keys, - * move one key from it. Otherwise we should try to merge them. - * (A branch page must never have less than 2 keys.) - */ - if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= thresh && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) { - rc = mdb_node_move(&mn, mc, fromleft); - if (fromleft) { - /* if we inserted on left, bump position up */ - oldki++; - } - } else { - if (!fromleft) { - rc = mdb_page_merge(&mn, mc); - } else { - oldki += NUMKEYS(mn.mc_pg[mn.mc_top]); - mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1; - /* We want mdb_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, - rc = mdb_page_merge(mc, &mn)); - mdb_cursor_copy(&mn, mc); - } - mc->mc_flags &= ~C_EOF; - } - mc->mc_ki[mc->mc_top] = oldki; - return rc; -} - -/** Complete a delete operation started by #mdb_cursor_del(). */ -static int -mdb_cursor_del0(MDB_cursor *mc) -{ - int rc; - MDB_page *mp; - indx_t ki; - unsigned int nkeys; - MDB_cursor *m2, *m3; - MDB_dbi dbi = mc->mc_dbi; - - ki = mc->mc_ki[mc->mc_top]; - mp = mc->mc_pg[mc->mc_top]; - mdb_node_del(mc, mc->mc_db->md_pad); - mc->mc_db->md_entries--; - { - /* Adjust other cursors pointing to mp */ - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (m3 == mc || m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) { - if (m3->mc_ki[mc->mc_top] == ki) { - m3->mc_flags |= C_DEL; - if (mc->mc_db->md_flags & MDB_DUPSORT) - m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; - } else if (m3->mc_ki[mc->mc_top] > ki) { - m3->mc_ki[mc->mc_top]--; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) { - MDB_node *node = NODEPTR(m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } - } - } - } - rc = mdb_rebalance(mc); - - if (rc == MDB_SUCCESS) { - /* DB is totally empty now, just bail out. - * Other cursors adjustments were already done - * by mdb_rebalance and aren't needed here. - */ - if (!mc->mc_snum) - return rc; - - mp = mc->mc_pg[mc->mc_top]; - nkeys = NUMKEYS(mp); - - /* Adjust other cursors pointing to mp */ - for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) { - /* if m3 points past last node in page, find next sibling */ - if (m3->mc_ki[mc->mc_top] >= nkeys) { - rc = mdb_cursor_sibling(m3, 1); - if (rc == MDB_NOTFOUND) { - m3->mc_flags |= C_EOF; - rc = MDB_SUCCESS; - } - } - } - } - mc->mc_flags |= C_DEL; - } - - if (rc) - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -int -mdb_del(MDB_txn *txn, MDB_dbi dbi, - MDB_val *key, MDB_val *data) -{ - if (!key || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)) - return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; - - if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) { - /* must ignore any data */ - data = NULL; - } - - return mdb_del0(txn, dbi, key, data, 0); -} - -static int -mdb_del0(MDB_txn *txn, MDB_dbi dbi, - MDB_val *key, MDB_val *data, unsigned flags) -{ - MDB_cursor mc; - MDB_xcursor mx; - MDB_cursor_op op; - MDB_val rdata, *xdata; - int rc, exact = 0; - DKBUF; - - DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key))); - - mdb_cursor_init(&mc, txn, dbi, &mx); - - if (data) { - op = MDB_GET_BOTH; - rdata = *data; - xdata = &rdata; - } else { - op = MDB_SET; - xdata = NULL; - flags |= MDB_NODUPDATA; - } - rc = mdb_cursor_set(&mc, key, xdata, op, &exact); - if (rc == 0) { - /* let mdb_page_split know about this cursor if needed: - * delete will trigger a rebalance; if it needs to move - * a node from one page to another, it will have to - * update the parent's separator key(s). If the new sepkey - * is larger than the current one, the parent page may - * run out of space, triggering a split. We need this - * cursor to be consistent until the end of the rebalance. - */ - mc.mc_flags |= C_UNTRACK; - mc.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &mc; - rc = mdb_cursor_del(&mc, flags); - txn->mt_cursors[dbi] = mc.mc_next; - } - return rc; -} - -/** Split a page and insert a new node. - * @param[in,out] mc Cursor pointing to the page and desired insertion index. - * The cursor will be updated to point to the actual page and index where - * the node got inserted after the split. - * @param[in] newkey The key for the newly inserted node. - * @param[in] newdata The data for the newly inserted node. - * @param[in] newpgno The page number, if the new node is a branch node. - * @param[in] nflags The #NODE_ADD_FLAGS for the new node. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno, - unsigned int nflags) -{ - unsigned int flags; - int rc = MDB_SUCCESS, new_root = 0, did_split = 0; - indx_t newindx; - pgno_t pgno = 0; - int i, j, split_indx, nkeys, pmax; - MDB_env *env = mc->mc_txn->mt_env; - MDB_node *node; - MDB_val sepkey, rkey, xdata, *rdata = &xdata; - MDB_page *copy = NULL; - MDB_page *mp, *rp, *pp; - int ptop; - MDB_cursor mn; - DKBUF; - - mp = mc->mc_pg[mc->mc_top]; - newindx = mc->mc_ki[mc->mc_top]; - nkeys = NUMKEYS(mp); - - DPRINTF(("-----> splitting %s page %"Y"u and adding [%s] at index %i/%i", - IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno, - DKEY(newkey), mc->mc_ki[mc->mc_top], nkeys)); - - /* Create a right sibling. */ - if ((rc = mdb_page_new(mc, mp->mp_flags, 1, &rp))) - return rc; - rp->mp_pad = mp->mp_pad; - DPRINTF(("new right sibling: page %"Y"u", rp->mp_pgno)); - - /* Usually when splitting the root page, the cursor - * height is 1. But when called from mdb_update_key, - * the cursor height may be greater because it walks - * up the stack while finding the branch slot to update. - */ - if (mc->mc_top < 1) { - if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp))) - goto done; - /* shift current top to make room for new parent */ - for (i=mc->mc_snum; i>0; i--) { - mc->mc_pg[i] = mc->mc_pg[i-1]; - mc->mc_ki[i] = mc->mc_ki[i-1]; - } - mc->mc_pg[0] = pp; - mc->mc_ki[0] = 0; - mc->mc_db->md_root = pp->mp_pgno; - DPRINTF(("root split! new root = %"Y"u", pp->mp_pgno)); - new_root = mc->mc_db->md_depth++; - - /* Add left (implicit) pointer. */ - if ((rc = mdb_node_add(mc, 0, NULL, NULL, mp->mp_pgno, 0)) != MDB_SUCCESS) { - /* undo the pre-push */ - mc->mc_pg[0] = mc->mc_pg[1]; - mc->mc_ki[0] = mc->mc_ki[1]; - mc->mc_db->md_root = mp->mp_pgno; - mc->mc_db->md_depth--; - goto done; - } - mc->mc_snum++; - mc->mc_top++; - ptop = 0; - } else { - ptop = mc->mc_top-1; - DPRINTF(("parent branch page is %"Y"u", mc->mc_pg[ptop]->mp_pgno)); - } - - mdb_cursor_copy(mc, &mn); - mn.mc_xcursor = NULL; - mn.mc_pg[mn.mc_top] = rp; - mn.mc_ki[ptop] = mc->mc_ki[ptop]+1; - - if (nflags & MDB_APPEND) { - mn.mc_ki[mn.mc_top] = 0; - sepkey = *newkey; - split_indx = newindx; - nkeys = 0; - } else { - - split_indx = (nkeys+1) / 2; - - if (IS_LEAF2(rp)) { - char *split, *ins; - int x; - unsigned int lsize, rsize, ksize; - /* Move half of the keys to the right sibling */ - x = mc->mc_ki[mc->mc_top] - split_indx; - ksize = mc->mc_db->md_pad; - split = LEAF2KEY(mp, split_indx, ksize); - rsize = (nkeys - split_indx) * ksize; - lsize = (nkeys - split_indx) * sizeof(indx_t); - mp->mp_lower -= lsize; - rp->mp_lower += lsize; - mp->mp_upper += rsize - lsize; - rp->mp_upper -= rsize - lsize; - sepkey.mv_size = ksize; - if (newindx == split_indx) { - sepkey.mv_data = newkey->mv_data; - } else { - sepkey.mv_data = split; - } - if (x<0) { - ins = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], ksize); - memcpy(rp->mp_ptrs, split, rsize); - sepkey.mv_data = rp->mp_ptrs; - memmove(ins+ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize); - memcpy(ins, newkey->mv_data, ksize); - mp->mp_lower += sizeof(indx_t); - mp->mp_upper -= ksize - sizeof(indx_t); - } else { - if (x) - memcpy(rp->mp_ptrs, split, x * ksize); - ins = LEAF2KEY(rp, x, ksize); - memcpy(ins, newkey->mv_data, ksize); - memcpy(ins+ksize, split + x * ksize, rsize - x * ksize); - rp->mp_lower += sizeof(indx_t); - rp->mp_upper -= ksize - sizeof(indx_t); - mc->mc_ki[mc->mc_top] = x; - } - } else { - int psize, nsize, k; - /* Maximum free space in an empty page */ - pmax = env->me_psize - PAGEHDRSZ; - if (IS_LEAF(mp)) - nsize = mdb_leaf_size(env, newkey, newdata); - else - nsize = mdb_branch_size(env, newkey); - nsize = EVEN(nsize); - - /* grab a page to hold a temporary copy */ - copy = mdb_page_malloc(mc->mc_txn, 1); - if (copy == NULL) { - rc = ENOMEM; - goto done; - } - copy->mp_pgno = mp->mp_pgno; - copy->mp_flags = mp->mp_flags; - copy->mp_lower = (PAGEHDRSZ-PAGEBASE); - copy->mp_upper = env->me_psize - PAGEBASE; - - /* prepare to insert */ - for (i=0, j=0; imp_ptrs[j++] = 0; - } - copy->mp_ptrs[j++] = mp->mp_ptrs[i]; - } - - /* When items are relatively large the split point needs - * to be checked, because being off-by-one will make the - * difference between success or failure in mdb_node_add. - * - * It's also relevant if a page happens to be laid out - * such that one half of its nodes are all "small" and - * the other half of its nodes are "large." If the new - * item is also "large" and falls on the half with - * "large" nodes, it also may not fit. - * - * As a final tweak, if the new item goes on the last - * spot on the page (and thus, onto the new page), bias - * the split so the new page is emptier than the old page. - * This yields better packing during sequential inserts. - */ - if (nkeys < 20 || nsize > pmax/16 || newindx >= nkeys) { - /* Find split point */ - psize = 0; - if (newindx <= split_indx || newindx >= nkeys) { - i = 0; j = 1; - k = newindx >= nkeys ? nkeys : split_indx+1+IS_LEAF(mp); - } else { - i = nkeys; j = -1; - k = split_indx-1; - } - for (; i!=k; i+=j) { - if (i == newindx) { - psize += nsize; - node = NULL; - } else { - node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE); - psize += NODESIZE + NODEKSZ(node) + sizeof(indx_t); - if (IS_LEAF(mp)) { - if (F_ISSET(node->mn_flags, F_BIGDATA)) - psize += sizeof(pgno_t); - else - psize += NODEDSZ(node); - } - psize = EVEN(psize); - } - if (psize > pmax || i == k-j) { - split_indx = i + (j<0); - break; - } - } - } - if (split_indx == newindx) { - sepkey.mv_size = newkey->mv_size; - sepkey.mv_data = newkey->mv_data; - } else { - node = (MDB_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEBASE); - sepkey.mv_size = node->mn_ksize; - sepkey.mv_data = NODEKEY(node); - } - } - } - - DPRINTF(("separator is %d [%s]", split_indx, DKEY(&sepkey))); - - /* Copy separator key to the parent. - */ - if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) { - int snum = mc->mc_snum; - mn.mc_snum--; - mn.mc_top--; - did_split = 1; - /* We want other splits to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, - rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0)); - if (rc) - goto done; - - /* root split? */ - if (mc->mc_snum > snum) { - ptop++; - } - /* Right page might now have changed parent. - * Check if left page also changed parent. - */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { - for (i=0; imc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - mc->mc_pg[ptop] = mn.mc_pg[ptop]; - if (mn.mc_ki[ptop]) { - mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1; - } else { - /* find right page's left sibling */ - mc->mc_ki[ptop] = mn.mc_ki[ptop]; - mdb_cursor_sibling(mc, 0); - } - } - } else { - mn.mc_top--; - rc = mdb_node_add(&mn, mn.mc_ki[ptop], &sepkey, NULL, rp->mp_pgno, 0); - mn.mc_top++; - } - if (rc != MDB_SUCCESS) { - goto done; - } - if (nflags & MDB_APPEND) { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[mc->mc_top] = 0; - rc = mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags); - if (rc) - goto done; - for (i=0; imc_top; i++) - mc->mc_ki[i] = mn.mc_ki[i]; - } else if (!IS_LEAF2(mp)) { - /* Move nodes */ - mc->mc_pg[mc->mc_top] = rp; - i = split_indx; - j = 0; - do { - if (i == newindx) { - rkey.mv_data = newkey->mv_data; - rkey.mv_size = newkey->mv_size; - if (IS_LEAF(mp)) { - rdata = newdata; - } else - pgno = newpgno; - flags = nflags; - /* Update index for the new key. */ - mc->mc_ki[mc->mc_top] = j; - } else { - node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE); - rkey.mv_data = NODEKEY(node); - rkey.mv_size = node->mn_ksize; - if (IS_LEAF(mp)) { - xdata.mv_data = NODEDATA(node); - xdata.mv_size = NODEDSZ(node); - rdata = &xdata; - } else - pgno = NODEPGNO(node); - flags = node->mn_flags; - } - - if (!IS_LEAF(mp) && j == 0) { - /* First branch index doesn't need key data. */ - rkey.mv_size = 0; - } - - rc = mdb_node_add(mc, j, &rkey, rdata, pgno, flags); - if (rc) - goto done; - if (i == nkeys) { - i = 0; - j = 0; - mc->mc_pg[mc->mc_top] = copy; - } else { - i++; - j++; - } - } while (i != split_indx); - - nkeys = NUMKEYS(copy); - for (i=0; imp_ptrs[i] = copy->mp_ptrs[i]; - mp->mp_lower = copy->mp_lower; - mp->mp_upper = copy->mp_upper; - memcpy(NODEPTR(mp, nkeys-1), NODEPTR(copy, nkeys-1), - env->me_psize - copy->mp_upper - PAGEBASE); - - /* reset back to original page */ - if (newindx < split_indx) { - mc->mc_pg[mc->mc_top] = mp; - } else { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[ptop]++; - /* Make sure mc_ki is still valid. - */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { - for (i=0; i<=ptop; i++) { - mc->mc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - } - } - if (nflags & MDB_RESERVE) { - node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (!(node->mn_flags & F_BIGDATA)) - newdata->mv_data = NODEDATA(node); - } - } else { - if (newindx >= split_indx) { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[ptop]++; - /* Make sure mc_ki is still valid. - */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { - for (i=0; i<=ptop; i++) { - mc->mc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - } - } - } - - { - /* Adjust other cursors pointing to mp */ - MDB_cursor *m2, *m3; - MDB_dbi dbi = mc->mc_dbi; - nkeys = NUMKEYS(mp); - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) { - if (mc->mc_flags & C_SUB) - m3 = &m2->mc_xcursor->mx_cursor; - else - m3 = m2; - if (m3 == mc) - continue; - if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (new_root) { - int k; - /* sub cursors may be on different DB */ - if (m3->mc_pg[0] != mp) - continue; - /* root split */ - for (k=new_root; k>=0; k--) { - m3->mc_ki[k+1] = m3->mc_ki[k]; - m3->mc_pg[k+1] = m3->mc_pg[k]; - } - if (m3->mc_ki[0] >= nkeys) { - m3->mc_ki[0] = 1; - } else { - m3->mc_ki[0] = 0; - } - m3->mc_pg[0] = mc->mc_pg[0]; - m3->mc_snum++; - m3->mc_top++; - } - if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) { - if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDB_SPLIT_REPLACE)) - m3->mc_ki[mc->mc_top]++; - if (m3->mc_ki[mc->mc_top] >= nkeys) { - m3->mc_pg[mc->mc_top] = rp; - m3->mc_ki[mc->mc_top] -= nkeys; - for (i=0; imc_top; i++) { - m3->mc_ki[i] = mn.mc_ki[i]; - m3->mc_pg[i] = mn.mc_pg[i]; - } - } - } else if (!did_split && m3->mc_top >= ptop && m3->mc_pg[ptop] == mc->mc_pg[ptop] && - m3->mc_ki[ptop] >= mc->mc_ki[ptop]) { - m3->mc_ki[ptop]++; - } - if (m3->mc_xcursor && (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) && - IS_LEAF(mp)) { - MDB_node *node = NODEPTR(m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) - m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); - } - } - } - DPRINTF(("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp))); - -done: - if (copy) /* tmp page */ - mdb_page_free(env, copy); - if (rc) - mc->mc_txn->mt_flags |= MDB_TXN_ERROR; - return rc; -} - -int -mdb_put(MDB_txn *txn, MDB_dbi dbi, - MDB_val *key, MDB_val *data, unsigned int flags) -{ - MDB_cursor mc; - MDB_xcursor mx; - int rc; - - if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP)) - return EINVAL; - - if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)) - return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN; - - mdb_cursor_init(&mc, txn, dbi, &mx); - mc.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &mc; - rc = mdb_cursor_put(&mc, key, data, flags); - txn->mt_cursors[dbi] = mc.mc_next; - return rc; -} - -#ifndef MDB_WBUF -#define MDB_WBUF (1024*1024) -#endif - - /** State needed for a compacting copy. */ -typedef struct mdb_copy { - pthread_mutex_t mc_mutex; - pthread_cond_t mc_cond; - char *mc_wbuf[2]; - char *mc_over[2]; - MDB_env *mc_env; - MDB_txn *mc_txn; - int mc_wlen[2]; - int mc_olen[2]; - pgno_t mc_next_pgno; - HANDLE mc_fd; - int mc_status; - volatile int mc_new; - int mc_toggle; - -} mdb_copy; - - /** Dedicated writer thread for compacting copy. */ -static THREAD_RET ESECT CALL_CONV -mdb_env_copythr(void *arg) -{ - mdb_copy *my = arg; - char *ptr; - int toggle = 0, wsize, rc; -#ifdef _WIN32 - DWORD len; -#define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) -#else - int len; -#define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) -#endif - - pthread_mutex_lock(&my->mc_mutex); - my->mc_new = 0; - pthread_cond_signal(&my->mc_cond); - for(;;) { - while (!my->mc_new) - pthread_cond_wait(&my->mc_cond, &my->mc_mutex); - if (my->mc_new < 0) { - my->mc_new = 0; - break; - } - my->mc_new = 0; - wsize = my->mc_wlen[toggle]; - ptr = my->mc_wbuf[toggle]; -again: - while (wsize > 0) { - DO_WRITE(rc, my->mc_fd, ptr, wsize, len); - if (!rc) { - rc = ErrCode(); - break; - } else if (len > 0) { - rc = MDB_SUCCESS; - ptr += len; - wsize -= len; - continue; - } else { - rc = EIO; - break; - } - } - if (rc) { - my->mc_status = rc; - break; - } - /* If there's an overflow page tail, write it too */ - if (my->mc_olen[toggle]) { - wsize = my->mc_olen[toggle]; - ptr = my->mc_over[toggle]; - my->mc_olen[toggle] = 0; - goto again; - } - my->mc_wlen[toggle] = 0; - toggle ^= 1; - pthread_cond_signal(&my->mc_cond); - } - pthread_cond_signal(&my->mc_cond); - pthread_mutex_unlock(&my->mc_mutex); - return (THREAD_RET)0; -#undef DO_WRITE -} - - /** Tell the writer thread there's a buffer ready to write */ -static int ESECT -mdb_env_cthr_toggle(mdb_copy *my, int st) -{ - int toggle = my->mc_toggle ^ 1; - pthread_mutex_lock(&my->mc_mutex); - if (my->mc_status) { - pthread_mutex_unlock(&my->mc_mutex); - return my->mc_status; - } - while (my->mc_new == 1) - pthread_cond_wait(&my->mc_cond, &my->mc_mutex); - my->mc_new = st; - my->mc_toggle = toggle; - pthread_cond_signal(&my->mc_cond); - pthread_mutex_unlock(&my->mc_mutex); - return 0; -} - - /** Depth-first tree traversal for compacting copy. */ -static int ESECT -mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags) -{ - MDB_cursor mc; - MDB_node *ni; - MDB_page *mo, *mp, *leaf; - char *buf, *ptr; - int rc, toggle; - unsigned int i; - - /* Empty DB, nothing to do */ - if (*pg == P_INVALID) - return MDB_SUCCESS; - - mc.mc_snum = 1; - mc.mc_top = 0; - mc.mc_txn = my->mc_txn; - - rc = mdb_page_get(&mc, *pg, &mc.mc_pg[0], NULL); - if (rc) - return rc; - rc = mdb_page_search_root(&mc, NULL, MDB_PS_FIRST); - if (rc) - return rc; - - /* Make cursor pages writable */ - buf = ptr = malloc(my->mc_env->me_psize * mc.mc_snum); - if (buf == NULL) - return ENOMEM; - - for (i=0; imc_env->me_psize); - mc.mc_pg[i] = (MDB_page *)ptr; - ptr += my->mc_env->me_psize; - } - - /* This is writable space for a leaf page. Usually not needed. */ - leaf = (MDB_page *)ptr; - - toggle = my->mc_toggle; - while (mc.mc_snum > 0) { - unsigned n; - mp = mc.mc_pg[mc.mc_top]; - n = NUMKEYS(mp); - - if (IS_LEAF(mp)) { - if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) { - for (i=0; imn_flags & F_BIGDATA) { - MDB_page *omp; - pgno_t pg; - - /* Need writable leaf */ - if (mp != leaf) { - mc.mc_pg[mc.mc_top] = leaf; - mdb_page_copy(leaf, mp, my->mc_env->me_psize); - mp = leaf; - ni = NODEPTR(mp, i); - } - - memcpy(&pg, NODEDATA(ni), sizeof(pg)); - rc = mdb_page_get(&mc, pg, &omp, NULL); - if (rc) - goto done; - if (my->mc_wlen[toggle] >= MDB_WBUF) { - rc = mdb_env_cthr_toggle(my, 1); - if (rc) - goto done; - toggle = my->mc_toggle; - } - mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); - memcpy(mo, omp, my->mc_env->me_psize); - mo->mp_pgno = my->mc_next_pgno; - my->mc_next_pgno += omp->mp_pages; - my->mc_wlen[toggle] += my->mc_env->me_psize; - if (omp->mp_pages > 1) { - my->mc_olen[toggle] = my->mc_env->me_psize * (omp->mp_pages - 1); - my->mc_over[toggle] = (char *)omp + my->mc_env->me_psize; - rc = mdb_env_cthr_toggle(my, 1); - if (rc) - goto done; - toggle = my->mc_toggle; - } - memcpy(NODEDATA(ni), &mo->mp_pgno, sizeof(pgno_t)); - } else if (ni->mn_flags & F_SUBDATA) { - MDB_db db; - - /* Need writable leaf */ - if (mp != leaf) { - mc.mc_pg[mc.mc_top] = leaf; - mdb_page_copy(leaf, mp, my->mc_env->me_psize); - mp = leaf; - ni = NODEPTR(mp, i); - } - - memcpy(&db, NODEDATA(ni), sizeof(db)); - my->mc_toggle = toggle; - rc = mdb_env_cwalk(my, &db.md_root, ni->mn_flags & F_DUPDATA); - if (rc) - goto done; - toggle = my->mc_toggle; - memcpy(NODEDATA(ni), &db, sizeof(db)); - } - } - } - } else { - mc.mc_ki[mc.mc_top]++; - if (mc.mc_ki[mc.mc_top] < n) { - pgno_t pg; -again: - ni = NODEPTR(mp, mc.mc_ki[mc.mc_top]); - pg = NODEPGNO(ni); - rc = mdb_page_get(&mc, pg, &mp, NULL); - if (rc) - goto done; - mc.mc_top++; - mc.mc_snum++; - mc.mc_ki[mc.mc_top] = 0; - if (IS_BRANCH(mp)) { - /* Whenever we advance to a sibling branch page, - * we must proceed all the way down to its first leaf. - */ - mdb_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize); - goto again; - } else - mc.mc_pg[mc.mc_top] = mp; - continue; - } - } - if (my->mc_wlen[toggle] >= MDB_WBUF) { - rc = mdb_env_cthr_toggle(my, 1); - if (rc) - goto done; - toggle = my->mc_toggle; - } - mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); - mdb_page_copy(mo, mp, my->mc_env->me_psize); - mo->mp_pgno = my->mc_next_pgno++; - my->mc_wlen[toggle] += my->mc_env->me_psize; - if (mc.mc_top) { - /* Update parent if there is one */ - ni = NODEPTR(mc.mc_pg[mc.mc_top-1], mc.mc_ki[mc.mc_top-1]); - SETPGNO(ni, mo->mp_pgno); - mdb_cursor_pop(&mc); - } else { - /* Otherwise we're done */ - *pg = mo->mp_pgno; - break; - } - } -done: - free(buf); - return rc; -} - - /** Copy environment with compaction. */ -static int ESECT -mdb_env_copyfd1(MDB_env *env, HANDLE fd) -{ - MDB_meta *mm; - MDB_page *mp; - mdb_copy my; - MDB_txn *txn = NULL; - pthread_t thr; - int rc; - -#ifdef _WIN32 - my.mc_mutex = CreateMutex(NULL, FALSE, NULL); - my.mc_cond = CreateEvent(NULL, FALSE, FALSE, NULL); - my.mc_wbuf[0] = _aligned_malloc(MDB_WBUF*2, env->me_os_psize); - if (my.mc_wbuf[0] == NULL) - return errno; -#else - pthread_mutex_init(&my.mc_mutex, NULL); - pthread_cond_init(&my.mc_cond, NULL); -#ifdef HAVE_MEMALIGN - my.mc_wbuf[0] = memalign(env->me_os_psize, MDB_WBUF*2); - if (my.mc_wbuf[0] == NULL) - return errno; -#else - rc = posix_memalign((void **)&my.mc_wbuf[0], env->me_os_psize, MDB_WBUF*2); - if (rc) - return rc; -#endif -#endif - memset(my.mc_wbuf[0], 0, MDB_WBUF*2); - my.mc_wbuf[1] = my.mc_wbuf[0] + MDB_WBUF; - my.mc_wlen[0] = 0; - my.mc_wlen[1] = 0; - my.mc_olen[0] = 0; - my.mc_olen[1] = 0; - my.mc_next_pgno = NUM_METAS; - my.mc_status = 0; - my.mc_new = 1; - my.mc_toggle = 0; - my.mc_env = env; - my.mc_fd = fd; - THREAD_CREATE(thr, mdb_env_copythr, &my); - - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - if (rc) - return rc; - - mp = (MDB_page *)my.mc_wbuf[0]; - memset(mp, 0, NUM_METAS * env->me_psize); - mp->mp_pgno = 0; - mp->mp_flags = P_META; - mm = (MDB_meta *)METADATA(mp); - mdb_env_init_meta0(env, mm); - mm->mm_address = env->me_metas[0]->mm_address; - - mp = (MDB_page *)(my.mc_wbuf[0] + env->me_psize); - mp->mp_pgno = 1; - mp->mp_flags = P_META; - *(MDB_meta *)METADATA(mp) = *mm; - mm = (MDB_meta *)METADATA(mp); - - /* Count the number of free pages, subtract from lastpg to find - * number of active pages - */ - { - MDB_ID freecount = 0; - MDB_cursor mc; - MDB_val key, data; - mdb_cursor_init(&mc, txn, FREE_DBI, NULL); - while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0) - freecount += *(MDB_ID *)data.mv_data; - freecount += txn->mt_dbs[FREE_DBI].md_branch_pages + - txn->mt_dbs[FREE_DBI].md_leaf_pages + - txn->mt_dbs[FREE_DBI].md_overflow_pages; - - /* Set metapage 1 */ - mm->mm_last_pg = txn->mt_next_pgno - freecount - 1; - mm->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; - if (mm->mm_last_pg > NUM_METAS-1) { - mm->mm_dbs[MAIN_DBI].md_root = mm->mm_last_pg; - mm->mm_txnid = 1; - } else { - mm->mm_dbs[MAIN_DBI].md_root = P_INVALID; - } - } - my.mc_wlen[0] = env->me_psize * NUM_METAS; - my.mc_txn = txn; - pthread_mutex_lock(&my.mc_mutex); - while(my.mc_new) - pthread_cond_wait(&my.mc_cond, &my.mc_mutex); - pthread_mutex_unlock(&my.mc_mutex); - rc = mdb_env_cwalk(&my, &txn->mt_dbs[MAIN_DBI].md_root, 0); - if (rc == MDB_SUCCESS && my.mc_wlen[my.mc_toggle]) - rc = mdb_env_cthr_toggle(&my, 1); - mdb_env_cthr_toggle(&my, -1); - pthread_mutex_lock(&my.mc_mutex); - while(my.mc_new) - pthread_cond_wait(&my.mc_cond, &my.mc_mutex); - pthread_mutex_unlock(&my.mc_mutex); - THREAD_FINISH(thr); - - mdb_txn_abort(txn); -#ifdef _WIN32 - CloseHandle(my.mc_cond); - CloseHandle(my.mc_mutex); - _aligned_free(my.mc_wbuf[0]); -#else - pthread_cond_destroy(&my.mc_cond); - pthread_mutex_destroy(&my.mc_mutex); - free(my.mc_wbuf[0]); -#endif - return rc; -} - - /** Copy environment as-is. */ -static int ESECT -mdb_env_copyfd0(MDB_env *env, HANDLE fd) -{ - MDB_txn *txn = NULL; - mdb_mutexref_t wmutex = NULL; - int rc; - mdb_size_t wsize, w3; - char *ptr; -#ifdef _WIN32 - DWORD len, w2; -#define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL) -#else - ssize_t len; - size_t w2; -#define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0) -#endif - - /* Do the lock/unlock of the reader mutex before starting the - * write txn. Otherwise other read txns could block writers. - */ - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - if (rc) - return rc; - - if (env->me_txns) { - /* We must start the actual read txn after blocking writers */ - mdb_txn_end(txn, MDB_END_RESET_TMP); - - /* Temporarily block writers until we snapshot the meta pages */ - wmutex = env->me_wmutex; - if (LOCK_MUTEX(rc, env, wmutex)) - goto leave; - - rc = mdb_txn_renew0(txn); - if (rc) { - UNLOCK_MUTEX(wmutex); - goto leave; - } - } - - wsize = env->me_psize * NUM_METAS; - ptr = env->me_map; - w2 = wsize; - while (w2 > 0) { - DO_WRITE(rc, fd, ptr, w2, len); - if (!rc) { - rc = ErrCode(); - break; - } else if (len > 0) { - rc = MDB_SUCCESS; - ptr += len; - w2 -= len; - continue; - } else { - /* Non-blocking or async handles are not supported */ - rc = EIO; - break; - } - } - if (wmutex) - UNLOCK_MUTEX(wmutex); - - if (rc) - goto leave; - - w3 = txn->mt_next_pgno * env->me_psize; - { - mdb_size_t fsize = 0; - if ((rc = mdb_fsize(env->me_fd, &fsize))) - goto leave; - if (w3 > fsize) - w3 = fsize; - } - wsize = w3 - wsize; - while (wsize > 0) { - if (wsize > MAX_WRITE) - w2 = MAX_WRITE; - else - w2 = wsize; - DO_WRITE(rc, fd, ptr, w2, len); - if (!rc) { - rc = ErrCode(); - break; - } else if (len > 0) { - rc = MDB_SUCCESS; - ptr += len; - wsize -= len; - continue; - } else { - rc = EIO; - break; - } - } - -leave: - mdb_txn_abort(txn); - return rc; -} - -int ESECT -mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned int flags) -{ - if (flags & MDB_CP_COMPACT) - return mdb_env_copyfd1(env, fd); - else - return mdb_env_copyfd0(env, fd); -} - -int ESECT -mdb_env_copyfd(MDB_env *env, HANDLE fd) -{ - return mdb_env_copyfd2(env, fd, 0); -} - -int ESECT -mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags) -{ - int rc, len; - char *lpath; - HANDLE newfd = INVALID_HANDLE_VALUE; -#ifdef _WIN32 - wchar_t *wpath; -#endif - - if (env->me_flags & MDB_NOSUBDIR) { - lpath = (char *)path; - } else { - len = strlen(path); - len += sizeof(DATANAME); - lpath = malloc(len); - if (!lpath) - return ENOMEM; - sprintf(lpath, "%s" DATANAME, path); - } - - /* The destination path must exist, but the destination file must not. - * We don't want the OS to cache the writes, since the source data is - * already in the OS cache. - */ -#ifdef _WIN32 - rc = utf8_to_utf16(lpath, -1, &wpath, NULL); - if (rc) - goto leave; - newfd = CreateFileW(wpath, GENERIC_WRITE, 0, NULL, CREATE_NEW, - FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL); - free(wpath); -#else - newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL, 0666); -#endif - if (newfd == INVALID_HANDLE_VALUE) { - rc = ErrCode(); - goto leave; - } - - if (env->me_psize >= env->me_os_psize) { -#ifdef O_DIRECT - /* Set O_DIRECT if the file system supports it */ - if ((rc = fcntl(newfd, F_GETFL)) != -1) - (void) fcntl(newfd, F_SETFL, rc | O_DIRECT); -#endif -#ifdef F_NOCACHE /* __APPLE__ */ - rc = fcntl(newfd, F_NOCACHE, 1); - if (rc) { - rc = ErrCode(); - goto leave; - } -#endif - } - - rc = mdb_env_copyfd2(env, newfd, flags); - -leave: - if (!(env->me_flags & MDB_NOSUBDIR)) - free(lpath); - if (newfd != INVALID_HANDLE_VALUE) - if (close(newfd) < 0 && rc == MDB_SUCCESS) - rc = ErrCode(); - - return rc; -} - -int ESECT -mdb_env_copy(MDB_env *env, const char *path) -{ - return mdb_env_copy2(env, path, 0); -} - -int ESECT -mdb_env_set_flags(MDB_env *env, unsigned int flag, int onoff) -{ - if (flag & ~CHANGEABLE) - return EINVAL; - if (onoff) - env->me_flags |= flag; - else - env->me_flags &= ~flag; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_get_flags(MDB_env *env, unsigned int *arg) -{ - if (!env || !arg) - return EINVAL; - - *arg = env->me_flags & (CHANGEABLE|CHANGELESS); - return MDB_SUCCESS; -} - -int ESECT -mdb_env_set_userctx(MDB_env *env, void *ctx) -{ - if (!env) - return EINVAL; - env->me_userctx = ctx; - return MDB_SUCCESS; -} - -void * ESECT -mdb_env_get_userctx(MDB_env *env) -{ - return env ? env->me_userctx : NULL; -} - -int ESECT -mdb_env_set_assert(MDB_env *env, MDB_assert_func *func) -{ - if (!env) - return EINVAL; -#ifndef NDEBUG - env->me_assert_func = func; -#endif - return MDB_SUCCESS; -} - -int ESECT -mdb_env_get_path(MDB_env *env, const char **arg) -{ - if (!env || !arg) - return EINVAL; - - *arg = env->me_path; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg) -{ - if (!env || !arg) - return EINVAL; - - *arg = env->me_fd; - return MDB_SUCCESS; -} - -/** Common code for #mdb_stat() and #mdb_env_stat(). - * @param[in] env the environment to operate in. - * @param[in] db the #MDB_db record containing the stats to return. - * @param[out] arg the address of an #MDB_stat structure to receive the stats. - * @return 0, this function always succeeds. - */ -static int ESECT -mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg) -{ - arg->ms_psize = env->me_psize; - arg->ms_depth = db->md_depth; - arg->ms_branch_pages = db->md_branch_pages; - arg->ms_leaf_pages = db->md_leaf_pages; - arg->ms_overflow_pages = db->md_overflow_pages; - arg->ms_entries = db->md_entries; - - return MDB_SUCCESS; -} - -int ESECT -mdb_env_stat(MDB_env *env, MDB_stat *arg) -{ - MDB_meta *meta; - - if (env == NULL || arg == NULL) - return EINVAL; - - meta = mdb_env_pick_meta(env); - - return mdb_stat0(env, &meta->mm_dbs[MAIN_DBI], arg); -} - -int ESECT -mdb_env_info(MDB_env *env, MDB_envinfo *arg) -{ - MDB_meta *meta; - - if (env == NULL || arg == NULL) - return EINVAL; - - meta = mdb_env_pick_meta(env); - arg->me_mapaddr = meta->mm_address; - arg->me_last_pgno = meta->mm_last_pg; - arg->me_last_txnid = meta->mm_txnid; - - arg->me_mapsize = env->me_mapsize; - arg->me_maxreaders = env->me_maxreaders; - arg->me_numreaders = env->me_txns ? env->me_txns->mti_numreaders : 0; - return MDB_SUCCESS; -} - -/** Set the default comparison functions for a database. - * Called immediately after a database is opened to set the defaults. - * The user can then override them with #mdb_set_compare() or - * #mdb_set_dupsort(). - * @param[in] txn A transaction handle returned by #mdb_txn_begin() - * @param[in] dbi A database handle returned by #mdb_dbi_open() - */ -static void -mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi) -{ - uint16_t f = txn->mt_dbs[dbi].md_flags; - - txn->mt_dbxs[dbi].md_cmp = - (f & MDB_REVERSEKEY) ? mdb_cmp_memnr : - (f & MDB_INTEGERKEY) ? mdb_cmp_cint : mdb_cmp_memn; - - txn->mt_dbxs[dbi].md_dcmp = - !(f & MDB_DUPSORT) ? 0 : - ((f & MDB_INTEGERDUP) - ? ((f & MDB_DUPFIXED) ? mdb_cmp_int : mdb_cmp_cint) - : ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn)); -} - -int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi) -{ - MDB_val key, data; - MDB_dbi i; - MDB_cursor mc; - MDB_db dummy; - int rc, dbflag, exact; - unsigned int unused = 0, seq; - char *namedup; - size_t len; - - if (flags & ~VALID_FLAGS) - return EINVAL; - if (txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - /* main DB? */ - if (!name) { - *dbi = MAIN_DBI; - if (flags & PERSISTENT_FLAGS) { - uint16_t f2 = flags & PERSISTENT_FLAGS; - /* make sure flag changes get committed */ - if ((txn->mt_dbs[MAIN_DBI].md_flags | f2) != txn->mt_dbs[MAIN_DBI].md_flags) { - txn->mt_dbs[MAIN_DBI].md_flags |= f2; - txn->mt_flags |= MDB_TXN_DIRTY; - } - } - mdb_default_cmp(txn, MAIN_DBI); - return MDB_SUCCESS; - } - - if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) { - mdb_default_cmp(txn, MAIN_DBI); - } - - /* Is the DB already open? */ - len = strlen(name); - for (i=CORE_DBS; imt_numdbs; i++) { - if (!txn->mt_dbxs[i].md_name.mv_size) { - /* Remember this free slot */ - if (!unused) unused = i; - continue; - } - if (len == txn->mt_dbxs[i].md_name.mv_size && - !strncmp(name, txn->mt_dbxs[i].md_name.mv_data, len)) { - *dbi = i; - return MDB_SUCCESS; - } - } - - /* If no free slot and max hit, fail */ - if (!unused && txn->mt_numdbs >= txn->mt_env->me_maxdbs) - return MDB_DBS_FULL; - - /* Cannot mix named databases with some mainDB flags */ - if (txn->mt_dbs[MAIN_DBI].md_flags & (MDB_DUPSORT|MDB_INTEGERKEY)) - return (flags & MDB_CREATE) ? MDB_INCOMPATIBLE : MDB_NOTFOUND; - - /* Find the DB info */ - dbflag = DB_NEW|DB_VALID|DB_USRVALID; - exact = 0; - key.mv_size = len; - key.mv_data = (void *)name; - mdb_cursor_init(&mc, txn, MAIN_DBI, NULL); - rc = mdb_cursor_set(&mc, &key, &data, MDB_SET, &exact); - if (rc == MDB_SUCCESS) { - /* make sure this is actually a DB */ - MDB_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]); - if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA) - return MDB_INCOMPATIBLE; - } else if (! (rc == MDB_NOTFOUND && (flags & MDB_CREATE))) { - return rc; - } - - /* Done here so we cannot fail after creating a new DB */ - if ((namedup = strdup(name)) == NULL) - return ENOMEM; - - if (rc) { - /* MDB_NOTFOUND and MDB_CREATE: Create new DB */ - data.mv_size = sizeof(MDB_db); - data.mv_data = &dummy; - memset(&dummy, 0, sizeof(dummy)); - dummy.md_root = P_INVALID; - dummy.md_flags = flags & PERSISTENT_FLAGS; - rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA); - dbflag |= DB_DIRTY; - } - - if (rc) { - free(namedup); - } else { - /* Got info, register DBI in this txn */ - unsigned int slot = unused ? unused : txn->mt_numdbs; - txn->mt_dbxs[slot].md_name.mv_data = namedup; - txn->mt_dbxs[slot].md_name.mv_size = len; - txn->mt_dbxs[slot].md_rel = NULL; - txn->mt_dbflags[slot] = dbflag; - /* txn-> and env-> are the same in read txns, use - * tmp variable to avoid undefined assignment - */ - seq = ++txn->mt_env->me_dbiseqs[slot]; - txn->mt_dbiseqs[slot] = seq; - - memcpy(&txn->mt_dbs[slot], data.mv_data, sizeof(MDB_db)); - *dbi = slot; - mdb_default_cmp(txn, slot); - if (!unused) { - txn->mt_numdbs++; - } - } - - return rc; -} - -int ESECT -mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg) -{ - if (!arg || !TXN_DBI_EXIST(txn, dbi, DB_VALID)) - return EINVAL; - - if (txn->mt_flags & MDB_TXN_BLOCKED) - return MDB_BAD_TXN; - - if (txn->mt_dbflags[dbi] & DB_STALE) { - MDB_cursor mc; - MDB_xcursor mx; - /* Stale, must read the DB's root. cursor_init does it for us. */ - mdb_cursor_init(&mc, txn, dbi, &mx); - } - return mdb_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg); -} - -void mdb_dbi_close(MDB_env *env, MDB_dbi dbi) -{ - char *ptr; - if (dbi < CORE_DBS || dbi >= env->me_maxdbs) - return; - ptr = env->me_dbxs[dbi].md_name.mv_data; - /* If there was no name, this was already closed */ - if (ptr) { - env->me_dbxs[dbi].md_name.mv_data = NULL; - env->me_dbxs[dbi].md_name.mv_size = 0; - env->me_dbflags[dbi] = 0; - env->me_dbiseqs[dbi]++; - free(ptr); - } -} - -int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags) -{ - /* We could return the flags for the FREE_DBI too but what's the point? */ - if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS; - return MDB_SUCCESS; -} - -/** Add all the DB's pages to the free list. - * @param[in] mc Cursor on the DB to free. - * @param[in] subs non-Zero to check for sub-DBs in this DB. - * @return 0 on success, non-zero on failure. - */ -static int -mdb_drop0(MDB_cursor *mc, int subs) -{ - int rc; - - rc = mdb_page_search(mc, NULL, MDB_PS_FIRST); - if (rc == MDB_SUCCESS) { - MDB_txn *txn = mc->mc_txn; - MDB_node *ni; - MDB_cursor mx; - unsigned int i; - - /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves. - * This also avoids any P_LEAF2 pages, which have no nodes. - * Also if the DB doesn't have sub-DBs and has no overflow - * pages, omit scanning leaves. - */ - if ((mc->mc_flags & C_SUB) || - (!subs && !mc->mc_db->md_overflow_pages)) - mdb_cursor_pop(mc); - - mdb_cursor_copy(mc, &mx); -#ifdef MDB_VL32 - /* bump refcount for mx's pages */ - for (i=0; imc_snum; i++) - mdb_page_get(&mx, mc->mc_pg[i]->mp_pgno, &mx.mc_pg[i], NULL); -#endif - while (mc->mc_snum > 0) { - MDB_page *mp = mc->mc_pg[mc->mc_top]; - unsigned n = NUMKEYS(mp); - if (IS_LEAF(mp)) { - for (i=0; imn_flags & F_BIGDATA) { - MDB_page *omp; - pgno_t pg; - memcpy(&pg, NODEDATA(ni), sizeof(pg)); - rc = mdb_page_get(mc, pg, &omp, NULL); - if (rc != 0) - goto done; - mdb_cassert(mc, IS_OVERFLOW(omp)); - rc = mdb_midl_append_range(&txn->mt_free_pgs, - pg, omp->mp_pages); - if (rc) - goto done; - mc->mc_db->md_overflow_pages -= omp->mp_pages; - if (!mc->mc_db->md_overflow_pages && !subs) - break; - } else if (subs && (ni->mn_flags & F_SUBDATA)) { - mdb_xcursor_init1(mc, ni); - rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0); - if (rc) - goto done; - } - } - if (!subs && !mc->mc_db->md_overflow_pages) - goto pop; - } else { - if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0) - goto done; - for (i=0; imt_free_pgs, pg); - } - } - if (!mc->mc_top) - break; - mc->mc_ki[mc->mc_top] = i; - rc = mdb_cursor_sibling(mc, 1); - if (rc) { - if (rc != MDB_NOTFOUND) - goto done; - /* no more siblings, go back to beginning - * of previous level. - */ -pop: - mdb_cursor_pop(mc); - mc->mc_ki[0] = 0; - for (i=1; imc_snum; i++) { - mc->mc_ki[i] = 0; - mc->mc_pg[i] = mx.mc_pg[i]; - } - } - } - /* free it */ - rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root); -done: - if (rc) - txn->mt_flags |= MDB_TXN_ERROR; -#ifdef MDB_VL32 - /* drop refcount for mx's pages */ - mdb_cursor_unref(&mx); -#endif - } else if (rc == MDB_NOTFOUND) { - rc = MDB_SUCCESS; - } - mc->mc_flags &= ~C_INITIALIZED; - return rc; -} - -int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del) -{ - MDB_cursor *mc, *m2; - int rc; - - if ((unsigned)del > 1 || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) - return EACCES; - - if (TXN_DBI_CHANGED(txn, dbi)) - return MDB_BAD_DBI; - - rc = mdb_cursor_open(txn, dbi, &mc); - if (rc) - return rc; - - rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT); - /* Invalidate the dropped DB's cursors */ - for (m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) - m2->mc_flags &= ~(C_INITIALIZED|C_EOF); - if (rc) - goto leave; - - /* Can't delete the main DB */ - if (del && dbi >= CORE_DBS) { - rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA); - if (!rc) { - txn->mt_dbflags[dbi] = DB_STALE; - mdb_dbi_close(txn->mt_env, dbi); - } else { - txn->mt_flags |= MDB_TXN_ERROR; - } - } else { - /* reset the DB record, mark it dirty */ - txn->mt_dbflags[dbi] |= DB_DIRTY; - txn->mt_dbs[dbi].md_depth = 0; - txn->mt_dbs[dbi].md_branch_pages = 0; - txn->mt_dbs[dbi].md_leaf_pages = 0; - txn->mt_dbs[dbi].md_overflow_pages = 0; - txn->mt_dbs[dbi].md_entries = 0; - txn->mt_dbs[dbi].md_root = P_INVALID; - - txn->mt_flags |= MDB_TXN_DIRTY; - } -leave: - mdb_cursor_close(mc); - return rc; -} - -int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) -{ - if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - txn->mt_dbxs[dbi].md_cmp = cmp; - return MDB_SUCCESS; -} - -int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp) -{ - if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - txn->mt_dbxs[dbi].md_dcmp = cmp; - return MDB_SUCCESS; -} - -int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel) -{ - if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - txn->mt_dbxs[dbi].md_rel = rel; - return MDB_SUCCESS; -} - -int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx) -{ - if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)) - return EINVAL; - - txn->mt_dbxs[dbi].md_relctx = ctx; - return MDB_SUCCESS; -} - -int ESECT -mdb_env_get_maxkeysize(MDB_env *env) -{ - return ENV_MAXKEY(env); -} - -int ESECT -mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx) -{ - unsigned int i, rdrs; - MDB_reader *mr; - char buf[64]; - int rc = 0, first = 1; - - if (!env || !func) - return -1; - if (!env->me_txns) { - return func("(no reader locks)\n", ctx); - } - rdrs = env->me_txns->mti_numreaders; - mr = env->me_txns->mti_readers; - for (i=0; i> 1; - cursor = base + pivot + 1; - val = pid - ids[cursor]; - - if( val < 0 ) { - n = pivot; - - } else if ( val > 0 ) { - base = cursor; - n -= pivot + 1; - - } else { - /* found, so it's a duplicate */ - return -1; - } - } - - if( val > 0 ) { - ++cursor; - } - ids[0]++; - for (n = ids[0]; n > cursor; n--) - ids[n] = ids[n-1]; - ids[n] = pid; - return 0; -} - -int ESECT -mdb_reader_check(MDB_env *env, int *dead) -{ - if (!env) - return EINVAL; - if (dead) - *dead = 0; - return env->me_txns ? mdb_reader_check0(env, 0, dead) : MDB_SUCCESS; -} - -/** As #mdb_reader_check(). rlocked = . */ -static int ESECT -mdb_reader_check0(MDB_env *env, int rlocked, int *dead) -{ - mdb_mutexref_t rmutex = rlocked ? NULL : env->me_rmutex; - unsigned int i, j, rdrs; - MDB_reader *mr; - MDB_PID_T *pids, pid; - int rc = MDB_SUCCESS, count = 0; - - rdrs = env->me_txns->mti_numreaders; - pids = malloc((rdrs+1) * sizeof(MDB_PID_T)); - if (!pids) - return ENOMEM; - pids[0] = 0; - mr = env->me_txns->mti_readers; - for (i=0; ime_pid) { - if (mdb_pid_insert(pids, pid) == 0) { - if (!mdb_reader_pid(env, Pidcheck, pid)) { - /* Stale reader found */ - j = i; - if (rmutex) { - if ((rc = LOCK_MUTEX0(rmutex)) != 0) { - if ((rc = mdb_mutex_failed(env, rmutex, rc))) - break; - rdrs = 0; /* the above checked all readers */ - } else { - /* Recheck, a new process may have reused pid */ - if (mdb_reader_pid(env, Pidcheck, pid)) - j = rdrs; - } - } - for (; jme_rmutex); - if (!rlocked) { - /* Keep mti_txnid updated, otherwise next writer can - * overwrite data which latest meta page refers to. - */ - meta = mdb_env_pick_meta(env); - env->me_txns->mti_txnid = meta->mm_txnid; - /* env is hosed if the dead thread was ours */ - if (env->me_txn) { - env->me_flags |= MDB_FATAL_ERROR; - env->me_txn = NULL; - rc = MDB_PANIC; - } - } - DPRINTF(("%cmutex owner died, %s", (rlocked ? 'r' : 'w'), - (rc ? "this process' env is hosed" : "recovering"))); - rc2 = mdb_reader_check0(env, rlocked, NULL); - if (rc2 == 0) - rc2 = mdb_mutex_consistent(mutex); - if (rc || (rc = rc2)) { - DPRINTF(("LOCK_MUTEX recovery failed, %s", mdb_strerror(rc))); - UNLOCK_MUTEX(mutex); - } - } else { -#ifdef _WIN32 - rc = ErrCode(); -#endif - DPRINTF(("LOCK_MUTEX failed, %s", mdb_strerror(rc))); - } - - return rc; -} -#endif /* MDB_ROBUST_SUPPORTED */ -/** @} */ - -#if defined(_WIN32) -static int utf8_to_utf16(const char *src, int srcsize, wchar_t **dst, int *dstsize) -{ - int need; - wchar_t *result; - need = MultiByteToWideChar(CP_UTF8, 0, src, srcsize, NULL, 0); - if (need == 0xFFFD) - return EILSEQ; - if (need == 0) - return EINVAL; - result = malloc(sizeof(wchar_t) * need); - if (!result) - return ENOMEM; - MultiByteToWideChar(CP_UTF8, 0, src, srcsize, result, need); - if (dstsize) - *dstsize = need; - *dst = result; - return 0; -} -#endif /* defined(_WIN32) */ diff --git a/src/contrib/db/liblmdb/mdb_copy.1 b/src/contrib/db/liblmdb/mdb_copy.1 deleted file mode 100644 index 401e47a..0000000 --- a/src/contrib/db/liblmdb/mdb_copy.1 +++ /dev/null @@ -1,60 +0,0 @@ -.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14" -.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.SH NAME -mdb_copy \- LMDB environment copy tool -.SH SYNOPSIS -.B mdb_copy -[\c -.BR \-V ] -[\c -.BR \-c ] -[\c -.BR \-n ] -[\c -.BR \-v ] -.B srcpath -[\c -.BR dstpath ] -.SH DESCRIPTION -The -.B mdb_copy -utility copies an LMDB environment. The environment can -be copied regardless of whether it is currently in use. -No lockfile is created, since it gets recreated at need. - -If -.I dstpath -is specified it must be the path of an empty directory -for storing the backup. Otherwise, the backup will be -written to stdout. - -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-c -Compact while copying. Only current data pages will be copied; freed -or unused pages will be omitted from the copy. This option will -slow down the backup process as it is more CPU-intensive. -.TP -.BR \-n -Open LDMB environment(s) which do not use subdirectories. -.TP -.BR \-v -Use the previous environment state instead of the latest state. -This may be useful if the latest state has been corrupted. - -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. -.SH CAVEATS -This utility can trigger significant file size growth if run -in parallel with write transactions, because pages which they -free during copying cannot be reused until the copy is done. -.SH "SEE ALSO" -.BR mdb_stat (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/liblmdb/mdb_copy.c b/src/contrib/db/liblmdb/mdb_copy.c deleted file mode 100644 index 95a6e71..0000000 --- a/src/contrib/db/liblmdb/mdb_copy.c +++ /dev/null @@ -1,84 +0,0 @@ -/* mdb_copy.c - memory-mapped database backup tool */ -/* - * Copyright 2012-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#ifdef _WIN32 -#include -#define MDB_STDOUT GetStdHandle(STD_OUTPUT_HANDLE) -#else -#define MDB_STDOUT 1 -#endif -#include -#include -#include -#include "lmdb.h" - -static void -sighandle(int sig) -{ -} - -int main(int argc,char * argv[]) -{ - int rc; - MDB_env *env; - const char *progname = argv[0], *act; - unsigned flags = MDB_RDONLY; - unsigned cpflags = 0; - - for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) { - if (argv[1][1] == 'n' && argv[1][2] == '\0') - flags |= MDB_NOSUBDIR; - else if (argv[1][1] == 'v' && argv[1][2] == '\0') - flags |= MDB_PREVSNAPSHOT; - else if (argv[1][1] == 'c' && argv[1][2] == '\0') - cpflags |= MDB_CP_COMPACT; - else if (argv[1][1] == 'V' && argv[1][2] == '\0') { - printf("%s\n", MDB_VERSION_STRING); - exit(0); - } else - argc = 0; - } - - if (argc<2 || argc>3) { - fprintf(stderr, "usage: %s [-V] [-c] [-n] [-v] srcpath [dstpath]\n", progname); - exit(EXIT_FAILURE); - } - -#ifdef SIGPIPE - signal(SIGPIPE, sighandle); -#endif -#ifdef SIGHUP - signal(SIGHUP, sighandle); -#endif - signal(SIGINT, sighandle); - signal(SIGTERM, sighandle); - - act = "opening environment"; - rc = mdb_env_create(&env); - if (rc == MDB_SUCCESS) { - rc = mdb_env_open(env, argv[1], flags, 0600); - } - if (rc == MDB_SUCCESS) { - act = "copying"; - if (argc == 2) - rc = mdb_env_copyfd2(env, MDB_STDOUT, cpflags); - else - rc = mdb_env_copy2(env, argv[2], cpflags); - } - if (rc) - fprintf(stderr, "%s: %s failed, error %d (%s)\n", - progname, act, rc, mdb_strerror(rc)); - mdb_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/liblmdb/mdb_dump.1 b/src/contrib/db/liblmdb/mdb_dump.1 deleted file mode 100644 index a25fb92..0000000 --- a/src/contrib/db/liblmdb/mdb_dump.1 +++ /dev/null @@ -1,81 +0,0 @@ -.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14" -.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.SH NAME -mdb_dump \- LMDB environment export tool -.SH SYNOPSIS -.B mdb_dump -[\c -.BR \-V ] -[\c -.BI \-f \ file\fR] -[\c -.BR \-l ] -[\c -.BR \-n ] -[\c -.BR \-v ] -[\c -.BR \-p ] -[\c -.BR \-a \ | -.BI \-s \ subdb\fR] -.BR \ envpath -.SH DESCRIPTION -The -.B mdb_dump -utility reads a database and writes its contents to the -standard output using a portable flat-text format -understood by the -.BR mdb_load (1) -utility. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-f \ file -Write to the specified file instead of to the standard output. -.TP -.BR \-l -List the databases stored in the environment. Just the -names will be listed, no data will be output. -.TP -.BR \-n -Dump an LMDB database which does not use subdirectories. -.TP -.BR \-v -Use the previous environment state instead of the latest state. -This may be useful if the latest state has been corrupted. -.TP -.BR \-p -If characters in either the key or data items are printing characters (as -defined by isprint(3)), output them directly. This option permits users to -use standard text editors and tools to modify the contents of databases. - -Note: different systems may have different notions about what characters -are considered printing characters, and databases dumped in this manner may -be less portable to external systems. -.TP -.BR \-a -Dump all of the subdatabases in the environment. -.TP -.BR \-s \ subdb -Dump a specific subdatabase. If no database is specified, only the main database is dumped. -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. - -Dumping and reloading databases that use user-defined comparison functions -will result in new databases that use the default comparison functions. -\fBIn this case it is quite likely that the reloaded database will be -damaged beyond repair permitting neither record storage nor retrieval.\fP - -The only available workaround is to modify the source for the -.BR mdb_load (1) -utility to load the database using the correct comparison functions. -.SH "SEE ALSO" -.BR mdb_load (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/liblmdb/mdb_dump.c b/src/contrib/db/liblmdb/mdb_dump.c deleted file mode 100644 index 7a42bc0..0000000 --- a/src/contrib/db/liblmdb/mdb_dump.c +++ /dev/null @@ -1,330 +0,0 @@ -/* mdb_dump.c - memory-mapped database dump tool */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#include -#include -#include -#include -#include -#include -#include -#include "lmdb.h" - -#ifdef _WIN32 -#define Z "I" -#else -#define Z "z" -#endif -#ifdef MDB_VL32 -#ifdef _WIN32 -#define Y "I64" -#else -#define Y "ll" -#endif -#else -#define Y Z -#endif - -#define PRINT 1 -static int mode; - -typedef struct flagbit { - int bit; - char *name; -} flagbit; - -flagbit dbflags[] = { - { MDB_REVERSEKEY, "reversekey" }, - { MDB_DUPSORT, "dupsort" }, - { MDB_INTEGERKEY, "integerkey" }, - { MDB_DUPFIXED, "dupfixed" }, - { MDB_INTEGERDUP, "integerdup" }, - { MDB_REVERSEDUP, "reversedup" }, - { 0, NULL } -}; - -static volatile sig_atomic_t gotsig; - -static void dumpsig( int sig ) -{ - gotsig=1; -} - -static const char hexc[] = "0123456789abcdef"; - -static void hex(unsigned char c) -{ - putchar(hexc[c >> 4]); - putchar(hexc[c & 0xf]); -} - -static void text(MDB_val *v) -{ - unsigned char *c, *end; - - putchar(' '); - c = v->mv_data; - end = c + v->mv_size; - while (c < end) { - if (isprint(*c)) { - putchar(*c); - } else { - putchar('\\'); - hex(*c); - } - c++; - } - putchar('\n'); -} - -static void byte(MDB_val *v) -{ - unsigned char *c, *end; - - putchar(' '); - c = v->mv_data; - end = c + v->mv_size; - while (c < end) { - hex(*c++); - } - putchar('\n'); -} - -/* Dump in BDB-compatible format */ -static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name) -{ - MDB_cursor *mc; - MDB_stat ms; - MDB_val key, data; - MDB_envinfo info; - unsigned int flags; - int rc, i; - - rc = mdb_dbi_flags(txn, dbi, &flags); - if (rc) return rc; - - rc = mdb_stat(txn, dbi, &ms); - if (rc) return rc; - - rc = mdb_env_info(mdb_txn_env(txn), &info); - if (rc) return rc; - - printf("VERSION=3\n"); - printf("format=%s\n", mode & PRINT ? "print" : "bytevalue"); - if (name) - printf("database=%s\n", name); - printf("type=btree\n"); - printf("mapsize=%" Y "u\n", info.me_mapsize); - if (info.me_mapaddr) - printf("mapaddr=%p\n", info.me_mapaddr); - printf("maxreaders=%u\n", info.me_maxreaders); - - if (flags & MDB_DUPSORT) - printf("duplicates=1\n"); - - for (i=0; dbflags[i].bit; i++) - if (flags & dbflags[i].bit) - printf("%s=1\n", dbflags[i].name); - - printf("db_pagesize=%d\n", ms.ms_psize); - printf("HEADER=END\n"); - - rc = mdb_cursor_open(txn, dbi, &mc); - if (rc) return rc; - - while ((rc = mdb_cursor_get(mc, &key, &data, MDB_NEXT) == MDB_SUCCESS)) { - if (gotsig) { - rc = EINTR; - break; - } - if (mode & PRINT) { - text(&key); - text(&data); - } else { - byte(&key); - byte(&data); - } - } - printf("DATA=END\n"); - if (rc == MDB_NOTFOUND) - rc = MDB_SUCCESS; - - return rc; -} - -static void usage(char *prog) -{ - fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-a|-s subdb] dbpath\n", prog); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) -{ - int i, rc; - MDB_env *env; - MDB_txn *txn; - MDB_dbi dbi; - char *prog = argv[0]; - char *envname; - char *subname = NULL; - int alldbs = 0, envflags = 0, list = 0; - - if (argc < 2) { - usage(prog); - } - - /* -a: dump main DB and all subDBs - * -s: dump only the named subDB - * -n: use NOSUBDIR flag on env_open - * -p: use printable characters - * -f: write to file instead of stdout - * -v: use previous snapshot - * -V: print version and exit - * (default) dump only the main DB - */ - while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) { - switch(i) { - case 'V': - printf("%s\n", MDB_VERSION_STRING); - exit(0); - break; - case 'l': - list = 1; - /*FALLTHROUGH*/; - case 'a': - if (subname) - usage(prog); - alldbs++; - break; - case 'f': - if (freopen(optarg, "w", stdout) == NULL) { - fprintf(stderr, "%s: %s: reopen: %s\n", - prog, optarg, strerror(errno)); - exit(EXIT_FAILURE); - } - break; - case 'n': - envflags |= MDB_NOSUBDIR; - break; - case 'v': - envflags |= MDB_PREVSNAPSHOT; - break; - case 'p': - mode |= PRINT; - break; - case 's': - if (alldbs) - usage(prog); - subname = optarg; - break; - default: - usage(prog); - } - } - - if (optind != argc - 1) - usage(prog); - -#ifdef SIGPIPE - signal(SIGPIPE, dumpsig); -#endif -#ifdef SIGHUP - signal(SIGHUP, dumpsig); -#endif - signal(SIGINT, dumpsig); - signal(SIGTERM, dumpsig); - - envname = argv[optind]; - rc = mdb_env_create(&env); - if (rc) { - fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); - return EXIT_FAILURE; - } - - if (alldbs || subname) { - mdb_env_set_maxdbs(env, 2); - } - - rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); - if (rc) { - fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - if (rc) { - fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - rc = mdb_open(txn, subname, 0, &dbi); - if (rc) { - fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - - if (alldbs) { - MDB_cursor *cursor; - MDB_val key; - int count = 0; - - rc = mdb_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { - char *str; - MDB_dbi db2; - if (memchr(key.mv_data, '\0', key.mv_size)) - continue; - count++; - str = malloc(key.mv_size+1); - memcpy(str, key.mv_data, key.mv_size); - str[key.mv_size] = '\0'; - rc = mdb_open(txn, str, 0, &db2); - if (rc == MDB_SUCCESS) { - if (list) { - printf("%s\n", str); - list++; - } else { - rc = dumpit(txn, db2, str); - if (rc) - break; - } - mdb_close(env, db2); - } - free(str); - if (rc) continue; - } - mdb_cursor_close(cursor); - if (!count) { - fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, envname); - rc = MDB_NOTFOUND; - } else if (rc == MDB_NOTFOUND) { - rc = MDB_SUCCESS; - } - } else { - rc = dumpit(txn, dbi, subname); - } - if (rc && rc != MDB_NOTFOUND) - fprintf(stderr, "%s: %s: %s\n", prog, envname, mdb_strerror(rc)); - - mdb_close(env, dbi); -txn_abort: - mdb_txn_abort(txn); -env_close: - mdb_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/liblmdb/mdb_load.1 b/src/contrib/db/liblmdb/mdb_load.1 deleted file mode 100644 index ede3702..0000000 --- a/src/contrib/db/liblmdb/mdb_load.1 +++ /dev/null @@ -1,84 +0,0 @@ -.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14" -.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.SH NAME -mdb_load \- LMDB environment import tool -.SH SYNOPSIS -.B mdb_load -[\c -.BR \-V ] -[\c -.BI \-f \ file\fR] -[\c -.BR \-n ] -[\c -.BI \-s \ subdb\fR] -[\c -.BR \-N ] -[\c -.BR \-T ] -.BR \ envpath -.SH DESCRIPTION -The -.B mdb_load -utility reads from the standard input and loads it into the -LMDB environment -.BR envpath . - -The input to -.B mdb_load -must be in the output format specified by the -.BR mdb_dump (1) -utility or as specified by the -.B -T -option below. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-a -Append all records in the order they appear in the input. The input is assumed to already be -in correctly sorted order and no sorting or checking for redundant values will be performed. -This option must be used to reload data that was produced by running -.B mdb_dump -on a database that uses custom compare functions. -.TP -.BR \-f \ file -Read from the specified file instead of from the standard input. -.TP -.BR \-n -Load an LMDB database which does not use subdirectories. -.TP -.BR \-s \ subdb -Load a specific subdatabase. If no database is specified, data is loaded into the main database. -.TP -.BR \-N -Don't overwrite existing records when loading into an already existing database; just skip them. -.TP -.BR \-T -Load data from simple text files. The input must be paired lines of text, where the first -line of the pair is the key item, and the second line of the pair is its corresponding -data item. - -A simple escape mechanism, where newline and backslash (\\) characters are special, is -applied to the text input. Newline characters are interpreted as record separators. -Backslash characters in the text will be interpreted in one of two ways: If the backslash -character precedes another backslash character, the pair will be interpreted as a literal -backslash. If the backslash character precedes any other character, the two characters -following the backslash will be interpreted as a hexadecimal specification of a single -character; for example, \\0a is a newline character in the ASCII character set. - -For this reason, any backslash or newline characters that naturally occur in the text -input must be escaped to avoid misinterpretation by -.BR mdb_load . - -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. - -.SH "SEE ALSO" -.BR mdb_dump (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/liblmdb/mdb_load.c b/src/contrib/db/liblmdb/mdb_load.c deleted file mode 100644 index 797c2f9..0000000 --- a/src/contrib/db/liblmdb/mdb_load.c +++ /dev/null @@ -1,499 +0,0 @@ -/* mdb_load.c - memory-mapped database load tool */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#include -#include -#include -#include -#include -#include -#include "lmdb.h" - -#define PRINT 1 -#define NOHDR 2 -static int mode; - -static char *subname = NULL; - -static size_t lineno; -static int version; - -static int flags; - -static char *prog; - -static int Eof; - -static MDB_envinfo info; - -static MDB_val kbuf, dbuf; -static MDB_val k0buf; - -#ifdef _WIN32 -#define Z "I" -#else -#define Z "z" -#endif -#ifdef MDB_VL32 -#ifdef _WIN32 -#define Y "I64" -#else -#define Y "ll" -#endif -#else -#define Y Z -#endif - -#define STRLENOF(s) (sizeof(s)-1) - -typedef struct flagbit { - int bit; - char *name; - int len; -} flagbit; - -#define S(s) s, STRLENOF(s) - -flagbit dbflags[] = { - { MDB_REVERSEKEY, S("reversekey") }, - { MDB_DUPSORT, S("dupsort") }, - { MDB_INTEGERKEY, S("integerkey") }, - { MDB_DUPFIXED, S("dupfixed") }, - { MDB_INTEGERDUP, S("integerdup") }, - { MDB_REVERSEDUP, S("reversedup") }, - { 0, NULL, 0 } -}; - -static void readhdr(void) -{ - char *ptr; - - while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) { - lineno++; - if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) { - version=atoi((char *)dbuf.mv_data+STRLENOF("VERSION=")); - if (version > 3) { - fprintf(stderr, "%s: line %" Z "d: unsupported VERSION %d\n", - prog, lineno, version); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.mv_data, "HEADER=END", STRLENOF("HEADER=END"))) { - break; - } else if (!strncmp(dbuf.mv_data, "format=", STRLENOF("format="))) { - if (!strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "print", STRLENOF("print"))) - mode |= PRINT; - else if (strncmp((char *)dbuf.mv_data+STRLENOF("FORMAT="), "bytevalue", STRLENOF("bytevalue"))) { - fprintf(stderr, "%s: line %" Z "d: unsupported FORMAT %s\n", - prog, lineno, (char *)dbuf.mv_data+STRLENOF("FORMAT=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.mv_data, "database=", STRLENOF("database="))) { - ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); - if (ptr) *ptr = '\0'; - if (subname) free(subname); - subname = strdup((char *)dbuf.mv_data+STRLENOF("database=")); - } else if (!strncmp(dbuf.mv_data, "type=", STRLENOF("type="))) { - if (strncmp((char *)dbuf.mv_data+STRLENOF("type="), "btree", STRLENOF("btree"))) { - fprintf(stderr, "%s: line %" Z "d: unsupported type %s\n", - prog, lineno, (char *)dbuf.mv_data+STRLENOF("type=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.mv_data, "mapaddr=", STRLENOF("mapaddr="))) { - int i; - ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); - if (ptr) *ptr = '\0'; - i = sscanf((char *)dbuf.mv_data+STRLENOF("mapaddr="), "%p", &info.me_mapaddr); - if (i != 1) { - fprintf(stderr, "%s: line %" Z "d: invalid mapaddr %s\n", - prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapaddr=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.mv_data, "mapsize=", STRLENOF("mapsize="))) { - int i; - ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); - if (ptr) *ptr = '\0'; - i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%" Y "u", &info.me_mapsize); - if (i != 1) { - fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n", - prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.mv_data, "maxreaders=", STRLENOF("maxreaders="))) { - int i; - ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size); - if (ptr) *ptr = '\0'; - i = sscanf((char *)dbuf.mv_data+STRLENOF("maxreaders="), "%u", &info.me_maxreaders); - if (i != 1) { - fprintf(stderr, "%s: line %" Z "d: invalid maxreaders %s\n", - prog, lineno, (char *)dbuf.mv_data+STRLENOF("maxreaders=")); - exit(EXIT_FAILURE); - } - } else { - int i; - for (i=0; dbflags[i].bit; i++) { - if (!strncmp(dbuf.mv_data, dbflags[i].name, dbflags[i].len) && - ((char *)dbuf.mv_data)[dbflags[i].len] == '=') { - flags |= dbflags[i].bit; - break; - } - } - if (!dbflags[i].bit) { - ptr = memchr(dbuf.mv_data, '=', dbuf.mv_size); - if (!ptr) { - fprintf(stderr, "%s: line %" Z "d: unexpected format\n", - prog, lineno); - exit(EXIT_FAILURE); - } else { - *ptr = '\0'; - fprintf(stderr, "%s: line %" Z "d: unrecognized keyword ignored: %s\n", - prog, lineno, (char *)dbuf.mv_data); - } - } - } - } -} - -static void badend(void) -{ - fprintf(stderr, "%s: line %" Z "d: unexpected end of input\n", - prog, lineno); -} - -static int unhex(unsigned char *c2) -{ - int x, c; - x = *c2++ & 0x4f; - if (x & 0x40) - x -= 55; - c = x << 4; - x = *c2 & 0x4f; - if (x & 0x40) - x -= 55; - c |= x; - return c; -} - -static int readline(MDB_val *out, MDB_val *buf) -{ - unsigned char *c1, *c2, *end; - size_t len, l2; - int c; - - if (!(mode & NOHDR)) { - c = fgetc(stdin); - if (c == EOF) { - Eof = 1; - return EOF; - } - if (c != ' ') { - lineno++; - if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) { -badend: - Eof = 1; - badend(); - return EOF; - } - if (c == 'D' && !strncmp(buf->mv_data, "ATA=END", STRLENOF("ATA=END"))) - return EOF; - goto badend; - } - } - if (fgets(buf->mv_data, buf->mv_size, stdin) == NULL) { - Eof = 1; - return EOF; - } - lineno++; - - c1 = buf->mv_data; - len = strlen((char *)c1); - l2 = len; - - /* Is buffer too short? */ - while (c1[len-1] != '\n') { - buf->mv_data = realloc(buf->mv_data, buf->mv_size*2); - if (!buf->mv_data) { - Eof = 1; - fprintf(stderr, "%s: line %" Z "d: out of memory, line too long\n", - prog, lineno); - return EOF; - } - c1 = buf->mv_data; - c1 += l2; - if (fgets((char *)c1, buf->mv_size+1, stdin) == NULL) { - Eof = 1; - badend(); - return EOF; - } - buf->mv_size *= 2; - len = strlen((char *)c1); - l2 += len; - } - c1 = c2 = buf->mv_data; - len = l2; - c1[--len] = '\0'; - end = c1 + len; - - if (mode & PRINT) { - while (c2 < end) { - if (*c2 == '\\') { - if (c2[1] == '\\') { - c1++; c2 += 2; - } else { - if (c2+3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) { - Eof = 1; - badend(); - return EOF; - } - *c1++ = unhex(++c2); - c2 += 2; - } - } else { - c1++; c2++; - } - } - } else { - /* odd length not allowed */ - if (len & 1) { - Eof = 1; - badend(); - return EOF; - } - while (c2 < end) { - if (!isxdigit(*c2) || !isxdigit(c2[1])) { - Eof = 1; - badend(); - return EOF; - } - *c1++ = unhex(c2); - c2 += 2; - } - } - c2 = out->mv_data = buf->mv_data; - out->mv_size = c1 - c2; - - return 0; -} - -static void usage(void) -{ - fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog); - exit(EXIT_FAILURE); -} - -static int greater(const MDB_val *a, const MDB_val *b) -{ - return 1; -} - -int main(int argc, char *argv[]) -{ - int i, rc; - MDB_env *env; - MDB_txn *txn; - MDB_cursor *mc; - MDB_dbi dbi; - char *envname; - int envflags = 0, putflags = 0; - int dohdr = 0, append = 0; - MDB_val prevk; - - prog = argv[0]; - - if (argc < 2) { - usage(); - } - - /* -a: append records in input order - * -f: load file instead of stdin - * -n: use NOSUBDIR flag on env_open - * -s: load into named subDB - * -N: use NOOVERWRITE on puts - * -T: read plaintext - * -V: print version and exit - */ - while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) { - switch(i) { - case 'V': - printf("%s\n", MDB_VERSION_STRING); - exit(0); - break; - case 'a': - append = 1; - break; - case 'f': - if (freopen(optarg, "r", stdin) == NULL) { - fprintf(stderr, "%s: %s: reopen: %s\n", - prog, optarg, strerror(errno)); - exit(EXIT_FAILURE); - } - break; - case 'n': - envflags |= MDB_NOSUBDIR; - break; - case 's': - subname = strdup(optarg); - break; - case 'N': - putflags = MDB_NOOVERWRITE|MDB_NODUPDATA; - break; - case 'T': - mode |= NOHDR | PRINT; - break; - default: - usage(); - } - } - - if (optind != argc - 1) - usage(); - - dbuf.mv_size = 4096; - dbuf.mv_data = malloc(dbuf.mv_size); - - if (!(mode & NOHDR)) - readhdr(); - - envname = argv[optind]; - rc = mdb_env_create(&env); - if (rc) { - fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); - return EXIT_FAILURE; - } - - mdb_env_set_maxdbs(env, 2); - - if (info.me_maxreaders) - mdb_env_set_maxreaders(env, info.me_maxreaders); - - if (info.me_mapsize) - mdb_env_set_mapsize(env, info.me_mapsize); - - if (info.me_mapaddr) - envflags |= MDB_FIXEDMAP; - - rc = mdb_env_open(env, envname, envflags, 0664); - if (rc) { - fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2; - kbuf.mv_data = malloc(kbuf.mv_size * 2); - k0buf.mv_size = kbuf.mv_size; - k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size; - prevk.mv_size = 0; - prevk.mv_data = k0buf.mv_data; - - while(!Eof) { - MDB_val key, data; - int batch = 0; - flags = 0; - int appflag; - - if (!dohdr) { - dohdr = 1; - } else if (!(mode & NOHDR)) - readhdr(); - - rc = mdb_txn_begin(env, NULL, 0, &txn); - if (rc) { - fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi); - if (rc) { - fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - if (append) { - mdb_set_compare(txn, dbi, greater); - if (flags & MDB_DUPSORT) - mdb_set_dupsort(txn, dbi, greater); - } - - rc = mdb_cursor_open(txn, dbi, &mc); - if (rc) { - fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - - while(1) { - rc = readline(&key, &kbuf); - if (rc) /* rc == EOF */ - break; - - rc = readline(&data, &dbuf); - if (rc) { - fprintf(stderr, "%s: line %" Z "d: failed to read key value\n", prog, lineno); - goto txn_abort; - } - - if (append) { - appflag = MDB_APPEND; - if (flags & MDB_DUPSORT) { - if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size)) - appflag = MDB_APPENDDUP; - else { - memcpy(prevk.mv_data, key.mv_data, key.mv_size); - prevk.mv_size = key.mv_size; - } - } - } else { - appflag = 0; - } - rc = mdb_cursor_put(mc, &key, &data, putflags|appflag); - if (rc == MDB_KEYEXIST && putflags) - continue; - if (rc) { - fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - batch++; - if (batch == 100) { - rc = mdb_txn_commit(txn); - if (rc) { - fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", - prog, lineno, mdb_strerror(rc)); - goto env_close; - } - rc = mdb_txn_begin(env, NULL, 0, &txn); - if (rc) { - fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - rc = mdb_cursor_open(txn, dbi, &mc); - if (rc) { - fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - batch = 0; - } - } - rc = mdb_txn_commit(txn); - txn = NULL; - if (rc) { - fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", - prog, lineno, mdb_strerror(rc)); - goto env_close; - } - mdb_dbi_close(env, dbi); - } - -txn_abort: - mdb_txn_abort(txn); -env_close: - mdb_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/liblmdb/mdb_stat.1 b/src/contrib/db/liblmdb/mdb_stat.1 deleted file mode 100644 index bf49bd3..0000000 --- a/src/contrib/db/liblmdb/mdb_stat.1 +++ /dev/null @@ -1,70 +0,0 @@ -.TH MDB_STAT 1 "2014/06/20" "LMDB 0.9.14" -.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.SH NAME -mdb_stat \- LMDB environment status tool -.SH SYNOPSIS -.B mdb_stat -[\c -.BR \-V ] -[\c -.BR \-e ] -[\c -.BR \-f [ f [ f ]]] -[\c -.BR \-n ] -[\c -.BR \-v ] -[\c -.BR \-r [ r ]] -[\c -.BR \-a \ | -.BI \-s \ subdb\fR] -.BR \ envpath -.SH DESCRIPTION -The -.B mdb_stat -utility displays the status of an LMDB environment. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-e -Display information about the database environment. -.TP -.BR \-f -Display information about the environment freelist. -If \fB\-ff\fP is given, summarize each freelist entry. -If \fB\-fff\fP is given, display the full list of page IDs in the freelist. -.TP -.BR \-n -Display the status of an LMDB database which does not use subdirectories. -.TP -.BR \-v -Use the previous environment state instead of the latest state. -This may be useful if the latest state has been corrupted. -.TP -.BR \-r -Display information about the environment reader table. -Shows the process ID, thread ID, and transaction ID for each active -reader slot. The process ID and transaction ID are in decimal, the -thread ID is in hexadecimal. The transaction ID is displayed as "-" -if the reader does not currently have a read transaction open. -If \fB\-rr\fP is given, check for stale entries in the reader -table and clear them. The reader table will be printed again -after the check is performed. -.TP -.BR \-a -Display the status of all of the subdatabases in the environment. -.TP -.BR \-s \ subdb -Display the status of a specific subdatabase. -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. -.SH "SEE ALSO" -.BR mdb_copy (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/liblmdb/mdb_stat.c b/src/contrib/db/liblmdb/mdb_stat.c deleted file mode 100644 index 30ec81f..0000000 --- a/src/contrib/db/liblmdb/mdb_stat.c +++ /dev/null @@ -1,276 +0,0 @@ -/* mdb_stat.c - memory-mapped database status tool */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#include -#include -#include -#include -#include "lmdb.h" - -#ifdef _WIN32 -#define Z "I" -#else -#define Z "z" -#endif -#ifdef MDB_VL32 -#ifdef _WIN32 -#define Y "I64" -#else -#define Y "ll" -#endif -#else -#define Y Z -#endif - -static void prstat(MDB_stat *ms) -{ -#if 0 - printf(" Page size: %u\n", ms->ms_psize); -#endif - printf(" Tree depth: %u\n", ms->ms_depth); - printf(" Branch pages: %"Y"u\n", ms->ms_branch_pages); - printf(" Leaf pages: %"Y"u\n", ms->ms_leaf_pages); - printf(" Overflow pages: %"Y"u\n", ms->ms_overflow_pages); - printf(" Entries: %"Y"u\n", ms->ms_entries); -} - -static void usage(char *prog) -{ - fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) -{ - int i, rc; - MDB_env *env; - MDB_txn *txn; - MDB_dbi dbi; - MDB_stat mst; - MDB_envinfo mei; - char *prog = argv[0]; - char *envname; - char *subname = NULL; - int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; - - if (argc < 2) { - usage(prog); - } - - /* -a: print stat of main DB and all subDBs - * -s: print stat of only the named subDB - * -e: print env info - * -f: print freelist info - * -r: print reader info - * -n: use NOSUBDIR flag on env_open - * -v: use previous snapshot - * -V: print version and exit - * (default) print stat of only the main DB - */ - while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) { - switch(i) { - case 'V': - printf("%s\n", MDB_VERSION_STRING); - exit(0); - break; - case 'a': - if (subname) - usage(prog); - alldbs++; - break; - case 'e': - envinfo++; - break; - case 'f': - freinfo++; - break; - case 'n': - envflags |= MDB_NOSUBDIR; - break; - case 'v': - envflags |= MDB_PREVSNAPSHOT; - break; - case 'r': - rdrinfo++; - break; - case 's': - if (alldbs) - usage(prog); - subname = optarg; - break; - default: - usage(prog); - } - } - - if (optind != argc - 1) - usage(prog); - - envname = argv[optind]; - rc = mdb_env_create(&env); - if (rc) { - fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); - return EXIT_FAILURE; - } - - if (alldbs || subname) { - mdb_env_set_maxdbs(env, 4); - } - - rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); - if (rc) { - fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - if (envinfo) { - (void)mdb_env_stat(env, &mst); - (void)mdb_env_info(env, &mei); - printf("Environment Info\n"); - printf(" Map address: %p\n", mei.me_mapaddr); - printf(" Map size: %"Y"u\n", mei.me_mapsize); - printf(" Page size: %u\n", mst.ms_psize); - printf(" Max pages: %"Y"u\n", mei.me_mapsize / mst.ms_psize); - printf(" Number of pages used: %"Y"u\n", mei.me_last_pgno+1); - printf(" Last transaction ID: %"Y"u\n", mei.me_last_txnid); - printf(" Max readers: %u\n", mei.me_maxreaders); - printf(" Number of readers used: %u\n", mei.me_numreaders); - } - - if (rdrinfo) { - printf("Reader Table Status\n"); - rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); - if (rdrinfo > 1) { - int dead; - mdb_reader_check(env, &dead); - printf(" %d stale readers cleared.\n", dead); - rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); - } - if (!(subname || alldbs || freinfo)) - goto env_close; - } - - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - if (rc) { - fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); - goto env_close; - } - - if (freinfo) { - MDB_cursor *cursor; - MDB_val key, data; - size_t pages = 0, *iptr; - - printf("Freelist Status\n"); - dbi = 0; - rc = mdb_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - rc = mdb_stat(txn, dbi, &mst); - if (rc) { - fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - prstat(&mst); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - iptr = data.mv_data; - pages += *iptr; - if (freinfo > 1) { - char *bad = ""; - size_t pg, prev; - ssize_t i, j, span = 0; - j = *iptr++; - for (i = j, prev = 1; --i >= 0; ) { - pg = iptr[i]; - if (pg <= prev) - bad = " [bad sequence]"; - prev = pg; - pg += span; - for (; i >= span && iptr[i-span] == pg; span++, pg++) ; - } - printf(" Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n", - *(size_t *)key.mv_data, j, span, bad); - if (freinfo > 2) { - for (--j; j >= 0; ) { - pg = iptr[j]; - for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ; - printf(span>1 ? " %9"Z"u[%"Z"d]\n" : " %9"Z"u\n", - pg, span); - } - } - } - } - mdb_cursor_close(cursor); - printf(" Free pages: %"Z"u\n", pages); - } - - rc = mdb_open(txn, subname, 0, &dbi); - if (rc) { - fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - - rc = mdb_stat(txn, dbi, &mst); - if (rc) { - fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - printf("Status of %s\n", subname ? subname : "Main DB"); - prstat(&mst); - - if (alldbs) { - MDB_cursor *cursor; - MDB_val key; - - rc = mdb_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { - char *str; - MDB_dbi db2; - if (memchr(key.mv_data, '\0', key.mv_size)) - continue; - str = malloc(key.mv_size+1); - memcpy(str, key.mv_data, key.mv_size); - str[key.mv_size] = '\0'; - rc = mdb_open(txn, str, 0, &db2); - if (rc == MDB_SUCCESS) - printf("Status of %s\n", str); - free(str); - if (rc) continue; - rc = mdb_stat(txn, db2, &mst); - if (rc) { - fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); - goto txn_abort; - } - prstat(&mst); - mdb_close(env, db2); - } - mdb_cursor_close(cursor); - } - - if (rc == MDB_NOTFOUND) - rc = MDB_SUCCESS; - - mdb_close(env, dbi); -txn_abort: - mdb_txn_abort(txn); -env_close: - mdb_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/liblmdb/midl.c b/src/contrib/db/liblmdb/midl.c deleted file mode 100644 index 152a1ec..0000000 --- a/src/contrib/db/liblmdb/midl.c +++ /dev/null @@ -1,420 +0,0 @@ -/** @file midl.c - * @brief ldap bdb back-end ID List functions */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * Copyright 2000-2015 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include -#include -#include -#include -#include -#include "midl.h" - -/** @defgroup internal LMDB Internals - * @{ - */ -/** @defgroup idls ID List Management - * @{ - */ -#define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) ) - -unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id ) -{ - /* - * binary search of id in ids - * if found, returns position of id - * if not found, returns first position greater than id - */ - unsigned base = 0; - unsigned cursor = 1; - int val = 0; - unsigned n = ids[0]; - - while( 0 < n ) { - unsigned pivot = n >> 1; - cursor = base + pivot + 1; - val = CMP( ids[cursor], id ); - - if( val < 0 ) { - n = pivot; - - } else if ( val > 0 ) { - base = cursor; - n -= pivot + 1; - - } else { - return cursor; - } - } - - if( val > 0 ) { - ++cursor; - } - return cursor; -} - -#if 0 /* superseded by append/sort */ -int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) -{ - unsigned x, i; - - x = mdb_midl_search( ids, id ); - assert( x > 0 ); - - if( x < 1 ) { - /* internal error */ - return -2; - } - - if ( x <= ids[0] && ids[x] == id ) { - /* duplicate */ - assert(0); - return -1; - } - - if ( ++ids[0] >= MDB_IDL_DB_MAX ) { - /* no room */ - --ids[0]; - return -2; - - } else { - /* insert id */ - for (i=ids[0]; i>x; i--) - ids[i] = ids[i-1]; - ids[x] = id; - } - - return 0; -} -#endif - -MDB_IDL mdb_midl_alloc(int num) -{ - MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID)); - if (ids) { - *ids++ = num; - *ids = 0; - } - return ids; -} - -void mdb_midl_free(MDB_IDL ids) -{ - if (ids) - free(ids-1); -} - -void mdb_midl_shrink( MDB_IDL *idp ) -{ - MDB_IDL ids = *idp; - if (*(--ids) > MDB_IDL_UM_MAX && - (ids = realloc(ids, (MDB_IDL_UM_MAX+2) * sizeof(MDB_ID)))) - { - *ids++ = MDB_IDL_UM_MAX; - *idp = ids; - } -} - -static int mdb_midl_grow( MDB_IDL *idp, int num ) -{ - MDB_IDL idn = *idp-1; - /* grow it */ - idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID)); - if (!idn) - return ENOMEM; - *idn++ += num; - *idp = idn; - return 0; -} - -int mdb_midl_need( MDB_IDL *idp, unsigned num ) -{ - MDB_IDL ids = *idp; - num += ids[0]; - if (num > ids[-1]) { - num = (num + num/4 + (256 + 2)) & -256; - if (!(ids = realloc(ids-1, num * sizeof(MDB_ID)))) - return ENOMEM; - *ids++ = num - 2; - *idp = ids; - } - return 0; -} - -int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) -{ - MDB_IDL ids = *idp; - /* Too big? */ - if (ids[0] >= ids[-1]) { - if (mdb_midl_grow(idp, MDB_IDL_UM_MAX)) - return ENOMEM; - ids = *idp; - } - ids[0]++; - ids[ids[0]] = id; - return 0; -} - -int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) -{ - MDB_IDL ids = *idp; - /* Too big? */ - if (ids[0] + app[0] >= ids[-1]) { - if (mdb_midl_grow(idp, app[0])) - return ENOMEM; - ids = *idp; - } - memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID)); - ids[0] += app[0]; - return 0; -} - -int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n ) -{ - MDB_ID *ids = *idp, len = ids[0]; - /* Too big? */ - if (len + n > ids[-1]) { - if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX)) - return ENOMEM; - ids = *idp; - } - ids[0] = len + n; - ids += len; - while (n) - ids[n--] = id++; - return 0; -} - -void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge ) -{ - MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k; - idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */ - old_id = idl[j]; - while (i) { - merge_id = merge[i--]; - for (; old_id < merge_id; old_id = idl[--j]) - idl[k--] = old_id; - idl[k--] = merge_id; - } - idl[0] = total; -} - -/* Quicksort + Insertion sort for small arrays */ - -#define SMALL 8 -#define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; } - -void -mdb_midl_sort( MDB_IDL ids ) -{ - /* Max possible depth of int-indexed tree * 2 items/level */ - int istack[sizeof(int)*CHAR_BIT * 2]; - int i,j,k,l,ir,jstack; - MDB_ID a, itmp; - - ir = (int)ids[0]; - l = 1; - jstack = 0; - for(;;) { - if (ir - l < SMALL) { /* Insertion sort */ - for (j=l+1;j<=ir;j++) { - a = ids[j]; - for (i=j-1;i>=1;i--) { - if (ids[i] >= a) break; - ids[i+1] = ids[i]; - } - ids[i+1] = a; - } - if (jstack == 0) break; - ir = istack[jstack--]; - l = istack[jstack--]; - } else { - k = (l + ir) >> 1; /* Choose median of left, center, right */ - MIDL_SWAP(ids[k], ids[l+1]); - if (ids[l] < ids[ir]) { - MIDL_SWAP(ids[l], ids[ir]); - } - if (ids[l+1] < ids[ir]) { - MIDL_SWAP(ids[l+1], ids[ir]); - } - if (ids[l] < ids[l+1]) { - MIDL_SWAP(ids[l], ids[l+1]); - } - i = l+1; - j = ir; - a = ids[l+1]; - for(;;) { - do i++; while(ids[i] > a); - do j--; while(ids[j] < a); - if (j < i) break; - MIDL_SWAP(ids[i],ids[j]); - } - ids[l+1] = ids[j]; - ids[j] = a; - jstack += 2; - if (ir-i+1 >= j-l) { - istack[jstack] = ir; - istack[jstack-1] = i; - ir = j-1; - } else { - istack[jstack] = j-1; - istack[jstack-1] = l; - l = i; - } - } - } -} - -unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id ) -{ - /* - * binary search of id in ids - * if found, returns position of id - * if not found, returns first position greater than id - */ - unsigned base = 0; - unsigned cursor = 1; - int val = 0; - unsigned n = (unsigned)ids[0].mid; - - while( 0 < n ) { - unsigned pivot = n >> 1; - cursor = base + pivot + 1; - val = CMP( id, ids[cursor].mid ); - - if( val < 0 ) { - n = pivot; - - } else if ( val > 0 ) { - base = cursor; - n -= pivot + 1; - - } else { - return cursor; - } - } - - if( val > 0 ) { - ++cursor; - } - return cursor; -} - -int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id ) -{ - unsigned x, i; - - x = mdb_mid2l_search( ids, id->mid ); - - if( x < 1 ) { - /* internal error */ - return -2; - } - - if ( x <= ids[0].mid && ids[x].mid == id->mid ) { - /* duplicate */ - return -1; - } - - if ( ids[0].mid >= MDB_IDL_UM_MAX ) { - /* too big */ - return -2; - - } else { - /* insert id */ - ids[0].mid++; - for (i=(unsigned)ids[0].mid; i>x; i--) - ids[i] = ids[i-1]; - ids[x] = *id; - } - - return 0; -} - -int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id ) -{ - /* Too big? */ - if (ids[0].mid >= MDB_IDL_UM_MAX) { - return -2; - } - ids[0].mid++; - ids[ids[0].mid] = *id; - return 0; -} - -#ifdef MDB_VL32 -unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id ) -{ - /* - * binary search of id in ids - * if found, returns position of id - * if not found, returns first position greater than id - */ - unsigned base = 0; - unsigned cursor = 1; - int val = 0; - unsigned n = (unsigned)ids[0].mid; - - while( 0 < n ) { - unsigned pivot = n >> 1; - cursor = base + pivot + 1; - val = CMP( id, ids[cursor].mid ); - - if( val < 0 ) { - n = pivot; - - } else if ( val > 0 ) { - base = cursor; - n -= pivot + 1; - - } else { - return cursor; - } - } - - if( val > 0 ) { - ++cursor; - } - return cursor; -} - -int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id ) -{ - unsigned x, i; - - x = mdb_mid3l_search( ids, id->mid ); - - if( x < 1 ) { - /* internal error */ - return -2; - } - - if ( x <= ids[0].mid && ids[x].mid == id->mid ) { - /* duplicate */ - return -1; - } - - /* insert id */ - ids[0].mid++; - for (i=(unsigned)ids[0].mid; i>x; i--) - ids[i] = ids[i-1]; - ids[x] = *id; - - return 0; -} -#endif /* MDB_VL32 */ - -/** @} */ -/** @} */ diff --git a/src/contrib/db/liblmdb/midl.h b/src/contrib/db/liblmdb/midl.h deleted file mode 100644 index 1555ecb..0000000 --- a/src/contrib/db/liblmdb/midl.h +++ /dev/null @@ -1,204 +0,0 @@ -/** @file midl.h - * @brief LMDB ID List header file. - * - * This file was originally part of back-bdb but has been - * modified for use in libmdb. Most of the macros defined - * in this file are unused, just left over from the original. - * - * This file is only used internally in libmdb and its definitions - * are not exposed publicly. - */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * Copyright 2000-2015 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#ifndef _MDB_MIDL_H_ -#define _MDB_MIDL_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** @defgroup internal LMDB Internals - * @{ - */ - -/** @defgroup idls ID List Management - * @{ - */ - /** A generic unsigned ID number. These were entryIDs in back-bdb. - * Preferably it should have the same size as a pointer. - */ -#ifdef MDB_VL32 -typedef uint64_t MDB_ID; -#else -typedef size_t MDB_ID; -#endif - - /** An IDL is an ID List, a sorted array of IDs. The first - * element of the array is a counter for how many actual - * IDs are in the list. In the original back-bdb code, IDLs are - * sorted in ascending order. For libmdb IDLs are sorted in - * descending order. - */ -typedef MDB_ID *MDB_IDL; - -/* IDL sizes - likely should be even bigger - * limiting factors: sizeof(ID), thread stack size - */ -#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */ -#define MDB_IDL_DB_SIZE (1<. - */ -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor, *cur2; - MDB_cursor_op op; - int count; - int *values; - char sval[32] = ""; - - srand(time(NULL)); - - count = (rand()%384) + 64; - values = (int *)malloc(count*sizeof(int)); - - for(i = 0;i in each iteration, since MDB_NOOVERWRITE may modify it */ - data.mv_size = sizeof(sval); - data.mv_data = sval; - if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) { - j++; - data.mv_size = sizeof(sval); - data.mv_data = sval; - } - } - if (j) printf("%d duplicates skipped\n", j); - E(mdb_txn_commit(txn)); - E(mdb_env_stat(env, &mst)); - - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %p %.*s, data: %p %.*s\n", - key.mv_data, (int) key.mv_size, (char *) key.mv_data, - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - j=0; - key.mv_data = sval; - for (i= count - 1; i > -1; i-= (rand()%5)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(sval, "%03x ", values[i]); - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor last\n"); - E(mdb_cursor_get(cursor, &key, &data, MDB_LAST)); - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor last/prev\n"); - E(mdb_cursor_get(cursor, &key, &data, MDB_LAST)); - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - E(mdb_cursor_get(cursor, &key, &data, MDB_PREV)); - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - printf("Deleting with cursor\n"); - E(mdb_txn_begin(env, NULL, 0, &txn)); - E(mdb_cursor_open(txn, dbi, &cur2)); - for (i=0; i<50; i++) { - if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, MDB_NEXT))) - break; - printf("key: %p %.*s, data: %p %.*s\n", - key.mv_data, (int) key.mv_size, (char *) key.mv_data, - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - E(mdb_del(txn, dbi, &key, NULL)); - } - - printf("Restarting cursor in txn\n"); - for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) { - if (RES(MDB_NOTFOUND, mdb_cursor_get(cur2, &key, &data, op))) - break; - printf("key: %p %.*s, data: %p %.*s\n", - key.mv_data, (int) key.mv_size, (char *) key.mv_data, - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - } - mdb_cursor_close(cur2); - E(mdb_txn_commit(txn)); - - printf("Restarting cursor outside txn\n"); - E(mdb_txn_begin(env, NULL, 0, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - for (op=MDB_FIRST, i=0; i<=32; op=MDB_NEXT, i++) { - if (RES(MDB_NOTFOUND, mdb_cursor_get(cursor, &key, &data, op))) - break; - printf("key: %p %.*s, data: %p %.*s\n", - key.mv_data, (int) key.mv_size, (char *) key.mv_data, - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - } - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); - mdb_env_close(env); - - return 0; -} diff --git a/src/contrib/db/liblmdb/mtest2.c b/src/contrib/db/liblmdb/mtest2.c deleted file mode 100644 index eacbe59..0000000 --- a/src/contrib/db/liblmdb/mtest2.c +++ /dev/null @@ -1,124 +0,0 @@ -/* mtest2.c - memory-mapped database tester/toy */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -/* Just like mtest.c, but using a subDB instead of the main DB */ - -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor; - int count; - int *values; - char sval[32] = ""; - - srand(time(NULL)); - - count = (rand()%384) + 64; - values = (int *)malloc(count*sizeof(int)); - - for(i = 0;i -1; i-= (rand()%5)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(sval, "%03x ", values[i]); - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); - mdb_env_close(env); - return 0; -} diff --git a/src/contrib/db/liblmdb/mtest3.c b/src/contrib/db/liblmdb/mtest3.c deleted file mode 100644 index 9db79e6..0000000 --- a/src/contrib/db/liblmdb/mtest3.c +++ /dev/null @@ -1,133 +0,0 @@ -/* mtest3.c - memory-mapped database tester/toy */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -/* Tests for sorted duplicate DBs */ -#include -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor; - int count; - int *values; - char sval[32]; - char kval[sizeof(int)]; - - srand(time(NULL)); - - memset(sval, 0, sizeof(sval)); - - count = (rand()%384) + 64; - values = (int *)malloc(count*sizeof(int)); - - for(i = 0;i -1; i-= (rand()%5)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(kval, "%03x", values[i & ~0x0f]); - sprintf(sval, "%03x %d foo bar", values[i], values[i]); - key.mv_size = sizeof(int); - key.mv_data = kval; - data.mv_size = sizeof(sval); - data.mv_data = sval; - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); - mdb_env_close(env); - return 0; -} diff --git a/src/contrib/db/liblmdb/mtest4.c b/src/contrib/db/liblmdb/mtest4.c deleted file mode 100644 index 6df890e..0000000 --- a/src/contrib/db/liblmdb/mtest4.c +++ /dev/null @@ -1,168 +0,0 @@ -/* mtest4.c - memory-mapped database tester/toy */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -/* Tests for sorted duplicate DBs with fixed-size keys */ -#include -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor; - int count; - int *values; - char sval[8]; - char kval[sizeof(int)]; - - memset(sval, 0, sizeof(sval)); - - count = 510; - values = (int *)malloc(count*sizeof(int)); - - for(i = 0;i -1; i-= (rand()%3)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(sval, "%07x", values[i]); - key.mv_size = sizeof(int); - key.mv_data = kval; - data.mv_size = sizeof(sval); - data.mv_data = sval; - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); - mdb_env_close(env); - return 0; -} diff --git a/src/contrib/db/liblmdb/mtest5.c b/src/contrib/db/liblmdb/mtest5.c deleted file mode 100644 index 14e3c0d..0000000 --- a/src/contrib/db/liblmdb/mtest5.c +++ /dev/null @@ -1,135 +0,0 @@ -/* mtest5.c - memory-mapped database tester/toy */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -/* Tests for sorted duplicate DBs using cursor_put */ -#include -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor; - int count; - int *values; - char sval[32]; - char kval[sizeof(int)]; - - srand(time(NULL)); - - memset(sval, 0, sizeof(sval)); - - count = (rand()%384) + 64; - values = (int *)malloc(count*sizeof(int)); - - for(i = 0;i -1; i-= (rand()%5)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(kval, "%03x", values[i & ~0x0f]); - sprintf(sval, "%03x %d foo bar", values[i], values[i]); - key.mv_size = sizeof(int); - key.mv_data = kval; - data.mv_size = sizeof(sval); - data.mv_data = sval; - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); - mdb_env_close(env); - return 0; -} diff --git a/src/contrib/db/liblmdb/mtest6.c b/src/contrib/db/liblmdb/mtest6.c deleted file mode 100644 index ae3c7f2..0000000 --- a/src/contrib/db/liblmdb/mtest6.c +++ /dev/null @@ -1,141 +0,0 @@ -/* mtest6.c - memory-mapped database tester/toy */ -/* - * Copyright 2011-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -/* Tests for DB splits and merges */ -#include -#include -#include -#include -#include "lmdb.h" - -#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr) -#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0)) -#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \ - "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort())) - -char dkbuf[1024]; - -int main(int argc,char * argv[]) -{ - int i = 0, j = 0, rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data, sdata; - MDB_txn *txn; - MDB_stat mst; - MDB_cursor *cursor; - int count; - int *values; - long kval; - char *sval; - - srand(time(NULL)); - - E(mdb_env_create(&env)); - E(mdb_env_set_mapsize(env, 10485760)); - E(mdb_env_set_maxdbs(env, 4)); - E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664)); - - E(mdb_txn_begin(env, NULL, 0, &txn)); - E(mdb_dbi_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi)); - E(mdb_cursor_open(txn, dbi, &cursor)); - E(mdb_stat(txn, dbi, &mst)); - - sval = calloc(1, mst.ms_psize / 4); - key.mv_size = sizeof(long); - key.mv_data = &kval; - sdata.mv_size = mst.ms_psize / 4 - 30; - sdata.mv_data = sval; - - printf("Adding 12 values, should yield 3 splits\n"); - for (i=0;i<12;i++) { - kval = i*5; - sprintf(sval, "%08x", kval); - data = sdata; - (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); - } - printf("Adding 12 more values, should yield 3 splits\n"); - for (i=0;i<12;i++) { - kval = i*5+4; - sprintf(sval, "%08x", kval); - data = sdata; - (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); - } - printf("Adding 12 more values, should yield 3 splits\n"); - for (i=0;i<12;i++) { - kval = i*5+1; - sprintf(sval, "%08x", kval); - data = sdata; - (void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE)); - } - E(mdb_cursor_get(cursor, &key, &data, MDB_FIRST)); - - do { - printf("key: %p %s, data: %p %.*s\n", - key.mv_data, mdb_dkey(&key, dkbuf), - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - } while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0); - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_commit(txn); - -#if 0 - j=0; - - for (i= count - 1; i > -1; i-= (rand()%5)) { - j++; - txn=NULL; - E(mdb_txn_begin(env, NULL, 0, &txn)); - sprintf(kval, "%03x", values[i & ~0x0f]); - sprintf(sval, "%03x %d foo bar", values[i], values[i]); - key.mv_size = sizeof(int); - key.mv_data = kval; - data.mv_size = sizeof(sval); - data.mv_data = sval; - if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { - j--; - mdb_txn_abort(txn); - } else { - E(mdb_txn_commit(txn)); - } - } - free(values); - printf("Deleted %d values\n", j); - - E(mdb_env_stat(env, &mst)); - E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); - E(mdb_cursor_open(txn, dbi, &cursor)); - printf("Cursor next\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - printf("Cursor prev\n"); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { - printf("key: %.*s, data: %.*s\n", - (int) key.mv_size, (char *) key.mv_data, - (int) data.mv_size, (char *) data.mv_data); - } - CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); - mdb_cursor_close(cursor); - mdb_txn_abort(txn); - - mdb_dbi_close(env, dbi); -#endif - mdb_env_close(env); - - return 0; -} diff --git a/src/contrib/db/liblmdb/sample-bdb.txt b/src/contrib/db/liblmdb/sample-bdb.txt deleted file mode 100644 index 563807a..0000000 --- a/src/contrib/db/liblmdb/sample-bdb.txt +++ /dev/null @@ -1,73 +0,0 @@ -/* sample-bdb.txt - BerkeleyDB toy/sample - * - * Do a line-by-line comparison of this and sample-mdb.txt - */ -/* - * Copyright 2012-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#include -#include -#include - -int main(int argc,char * argv[]) -{ - int rc; - DB_ENV *env; - DB *dbi; - DBT key, data; - DB_TXN *txn; - DBC *cursor; - char sval[32], kval[32]; - - /* Note: Most error checking omitted for simplicity */ - -#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD) - rc = db_env_create(&env, 0); - rc = env->open(env, "./testdb", FLAGS, 0664); - rc = db_create(&dbi, env, 0); - rc = env->txn_begin(env, NULL, &txn, 0); - rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664); - - memset(&key, 0, sizeof(DBT)); - memset(&data, 0, sizeof(DBT)); - key.size = sizeof(int); - key.data = sval; - data.size = sizeof(sval); - data.data = sval; - - sprintf(sval, "%03x %d foo bar", 32, 3141592); - rc = dbi->put(dbi, txn, &key, &data, 0); - rc = txn->commit(txn, 0); - if (rc) { - fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc)); - goto leave; - } - rc = env->txn_begin(env, NULL, &txn, 0); - rc = dbi->cursor(dbi, txn, &cursor, 0); - key.flags = DB_DBT_USERMEM; - key.data = kval; - key.ulen = sizeof(kval); - data.flags = DB_DBT_USERMEM; - data.data = sval; - data.ulen = sizeof(sval); - while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) { - printf("key: %p %.*s, data: %p %.*s\n", - key.data, (int) key.size, (char *) key.data, - data.data, (int) data.size, (char *) data.data); - } - rc = cursor->c_close(cursor); - rc = txn->abort(txn); -leave: - rc = dbi->close(dbi, 0); - rc = env->close(env, 0); - return rc; -} diff --git a/src/contrib/db/liblmdb/sample-mdb.txt b/src/contrib/db/liblmdb/sample-mdb.txt deleted file mode 100644 index 10a2568..0000000 --- a/src/contrib/db/liblmdb/sample-mdb.txt +++ /dev/null @@ -1,62 +0,0 @@ -/* sample-mdb.txt - MDB toy/sample - * - * Do a line-by-line comparison of this and sample-bdb.txt - */ -/* - * Copyright 2012-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ -#include -#include "lmdb.h" - -int main(int argc,char * argv[]) -{ - int rc; - MDB_env *env; - MDB_dbi dbi; - MDB_val key, data; - MDB_txn *txn; - MDB_cursor *cursor; - char sval[32]; - - /* Note: Most error checking omitted for simplicity */ - - rc = mdb_env_create(&env); - rc = mdb_env_open(env, "./testdb", 0, 0664); - rc = mdb_txn_begin(env, NULL, 0, &txn); - rc = mdb_dbi_open(txn, NULL, 0, &dbi); - - key.mv_size = sizeof(int); - key.mv_data = sval; - data.mv_size = sizeof(sval); - data.mv_data = sval; - - sprintf(sval, "%03x %d foo bar", 32, 3141592); - rc = mdb_put(txn, dbi, &key, &data, 0); - rc = mdb_txn_commit(txn); - if (rc) { - fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc)); - goto leave; - } - rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); - rc = mdb_cursor_open(txn, dbi, &cursor); - while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { - printf("key: %p %.*s, data: %p %.*s\n", - key.mv_data, (int) key.mv_size, (char *) key.mv_data, - data.mv_data, (int) data.mv_size, (char *) data.mv_data); - } - mdb_cursor_close(cursor); - mdb_txn_abort(txn); -leave: - mdb_dbi_close(env, dbi); - mdb_env_close(env); - return 0; -} diff --git a/src/contrib/db/liblmdb/tooltag b/src/contrib/db/liblmdb/tooltag deleted file mode 100644 index 229bf16..0000000 --- a/src/contrib/db/liblmdb/tooltag +++ /dev/null @@ -1,22 +0,0 @@ - - - mdb_copy_1 - mdb_copy - environment copy tool - mdb_copy.1 - - - mdb_dump_1 - mdb_dump - environment export tool - mdb_dump.1 - - - mdb_load_1 - mdb_load - environment import tool - mdb_load.1 - - - mdb_stat_1 - mdb_stat - environment status tool - mdb_stat.1 - - diff --git a/src/contrib/db/libmdbx/.circleci/config.yml b/src/contrib/db/libmdbx/.circleci/config.yml deleted file mode 100644 index 91e11a4..0000000 --- a/src/contrib/db/libmdbx/.circleci/config.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 2 -jobs: - build: - docker: - - image: circleci/buildpack-deps:artful - environment: - - TESTDB: /tmp/test.db - - TESTLOG: /tmp/test.log - steps: - - checkout - - run: make all - - run: ulimit -c unlimited && make check - - run: - command: | - mkdir -p /tmp/artifacts - mv -t /tmp/artifacts $TESTLOG $TESTDB core.* - when: on_fail - - store_artifacts: - path: /tmp/artifacts - destination: test-artifacts diff --git a/src/contrib/db/libmdbx/.clang-format b/src/contrib/db/libmdbx/.clang-format deleted file mode 100644 index 6c59ef3..0000000 --- a/src/contrib/db/libmdbx/.clang-format +++ /dev/null @@ -1,3 +0,0 @@ -BasedOnStyle: LLVM -Standard: Cpp11 -ReflowComments: true diff --git a/src/contrib/db/libmdbx/.gitignore b/src/contrib/db/libmdbx/.gitignore deleted file mode 100644 index 0496b62..0000000 --- a/src/contrib/db/libmdbx/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ -*.[ao] -*.bak -*.exe -*.gcda -*.gcno -*.gcov -*.lo -*.orig -*.rej -*.so -*[~#] -.idea -.le.ini -.vs/ -cmake-build-* -@* -core -mdbx_example -libmdbx.creator.user -mdbx_chk -mdbx_copy -mdbx_dump -mdbx_load -mdbx_stat -mdbx_test -test.log -test/tmp.db -test/tmp.db-lck -tmp.db -tmp.db-lck -valgrind.* -src/elements/version.c -src/elements/config.h -dist/ -*.tar* diff --git a/src/contrib/db/libmdbx/.travis.yml b/src/contrib/db/libmdbx/.travis.yml deleted file mode 100644 index 7b468ad..0000000 --- a/src/contrib/db/libmdbx/.travis.yml +++ /dev/null @@ -1,61 +0,0 @@ -language: c cpp - -matrix: - include: - - os: linux - dist: precise - env: CC=cc CXX=c++ - - os: linux - dist: trusty - compiler: clang - env: CC=clang CXX=clang++ - - os: linux - dist: xenial - compiler: gcc - env: CC=gcc CXX=g++ - - os: linux - dist: bionic - compiler: clang - env: CC=clang CXX=clang++ - - os: osx - osx_image: xcode11 - env: CC=cc CXX=c++ - - os: osx - osx_image: xcode9.4 - env: CC=cc CXX=c++ - -script: > - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then - git fetch --unshallow --tags --prune && - git submodule foreach --recursive git fetch --unshallow --tags --prune && - (if which clang-format-6.0 > /dev/null && make reformat && [[ -n $(git diff) ]]; - then - echo "You must run 'make reformat' before submitting a pull request"; - echo ""; - git diff; - exit -1; - fi) && - make --keep-going all && MALLOC_CHECK_=7 MALLOC_PERTURB_=42 make --keep-going check - else - [ ! -s cov-int/scm_log.txt ] || cat cov-int/scm_log.txt; - fi && sleep 3 - -env: - global: - - secure: "M+W+heGGyRQJoBq2W0uqWVrpL4KBXmL0MFL7FSs7f9vmAaDyEgziUXeZRj3GOKzW4kTef3LpIeiu9SmvqSMoQivGGiomZShqPVl045o/OUgRCAT7Al1RLzEZ0efSHpIPf0PZ6byEf6GR2ML76OfuL6JxTVdnz8iVyO2sgLE1HbX1VeB+wgd/jfMeOBhCCXskfK6MLyZihfMYsiYZYSaV98ZDhDLSlzuuRIgzb0bMi8aL6AErs0WLW0NelRBeHkKPYfAUc85pdQHscgrJw6Rh/zT6+8BQ/q5f4IgWhiu4xoRg3Ngl7SNoedRQh93ADM3UG2iGl6HDFpVORaXcFWKAtuYY+kHQ0HB84BRYpQmeBuXNpltsfxQ3d1Q3u0RlE45zRvmr2+X1mFnkcNUAWISLPbsOUlriDQM8irGwRpho77/uYnRC00bJsHW//s6+uPf9zrAw1nI4f0y3PAWukGF/xs6HAI3FZPsuSSnx18Tj3Opgbc9Spop+V3hkhdiJoPGpNKTkFX4ZRXfkPgoRVJmtp4PpbpH0Ps/mCriKjMEfGGi0HcVCi0pEGLXiecdqJ5KPg5+22zNycEujQBJcNTKd9shN+R3glrbmhAxTEzGdGwxXXJ2ybwJ2PWJLMYZ7g98nLyX+uQPaA3BlsbYJHNeS5283/9pJsd9DzfHKsN2nFSc=" - -before_install: - - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- - - ${CC} --version - - ${CXX} --version - -addons: - coverity_scan: - project: - name: "ReOpen/libmdbx" - version: 0.1 - description: "Build submitted via Travis CI" - notification_email: leo@yuriev.ru - build_command_prepend: "git fetch --unshallow --tags --prune && make dist" - build_command: "make MDBX_OPTIONS=-DMDBX_DEBUG=2 -C dist all" - branch_pattern: coverity_scan diff --git a/src/contrib/db/libmdbx/AUTHORS b/src/contrib/db/libmdbx/AUTHORS deleted file mode 100644 index 10910e5..0000000 --- a/src/contrib/db/libmdbx/AUTHORS +++ /dev/null @@ -1,32 +0,0 @@ -Contributors -============ - -Alexey Naumov -Chris Mikkelson -Claude Brisson -David Barbour -David Wilson -dreamsxin -Hallvard Furuseth , -Heiko Becker -Howard Chu , -Ignacio Casal Quinteiro -James Rouzier -Jean-Christophe DUBOIS -John Hewson -Klaus Malorny -Kurt Zeilenga -Leonid Yuriev , -Lorenz Bauer -Luke Yeager -Martin Hedenfalk -Ondrej Kuznik -Orivej Desh -Oskari Timperi -Pavel Medvedev -Philipp Storz -Quanah Gibson-Mount -Salvador Ortiz -Sebastien Launay -Vladimir Romanov -Zano Foundation diff --git a/src/contrib/db/libmdbx/CMakeLists.dist-minimal b/src/contrib/db/libmdbx/CMakeLists.dist-minimal deleted file mode 100644 index 1f138af..0000000 --- a/src/contrib/db/libmdbx/CMakeLists.dist-minimal +++ /dev/null @@ -1,192 +0,0 @@ -## -## This is the minimal template for CMakeList.txt which could be used -## to build libmdbx from the "amalgamated form" of libmdbx's source code. -## -## The amalgamated form is intended to embedding libmdbx in other projects -## in cases when using as git-submodule is not acceptable or inconveniently. -## -## The amalgamated form could be generated from full git repository -## on Linux just by `make dist`. -## - -## -## Copyright 2019 Leonid Yuriev -## and other libmdbx authors: please see AUTHORS file. -## All rights reserved. -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted only as authorized by the OpenLDAP -## Public License. -## -## A copy of this license is available in the file LICENSE in the -## top-level directory of the distribution or, alternatively, at -## . -## - -## -## libmdbx = { Revised and extended descendant of Symas LMDB. } -## Please see README.md at https://github.com/leo-yuriev/libmdbx -## -## Libmdbx is superior to LMDB in terms of features and reliability, -## not inferior in performance. libmdbx works on Linux, FreeBSD, MacOS X -## and other systems compliant with POSIX.1-2008, but also support Windows -## as a complementary platform. -## -## The next version is under active non-public development and will be -## released as MithrilDB and libmithrildb for libraries & packages. -## Admittedly mythical Mithril is resembling silver but being stronger and -## lighter than steel. Therefore MithrilDB is rightly relevant name. -## -## MithrilDB will be radically different from libmdbx by the new database -## format and API based on C++17, as well as the Apache 2.0 License. -## The goal of this revolution is to provide a clearer and robust API, -## add more features and new valuable properties of database. -## -## The Future will (be) Positive. Ð’ÑÑ‘ будет хорошо. -## - -cmake_minimum_required(VERSION 3.8.2) -cmake_policy(PUSH) -cmake_policy(VERSION 3.8.2) -if(NOT CMAKE_VERSION VERSION_LESS 3.9) - cmake_policy(SET CMP0069 NEW) -endif() -if(NOT CMAKE_VERSION VERSION_LESS 3.12) - cmake_policy(SET CMP0075 NEW) -endif() -if(NOT CMAKE_VERSION VERSION_LESS 3.13) - cmake_policy(SET CMP0077 NEW) -endif() - -if(DEFINED PROJECT_NAME) - set(SUBPROJECT ON) - set(NOT_SUBPROJECT OFF) -else() - set(SUBPROJECT OFF) - set(NOT_SUBPROJECT ON) - project(libmdbx C CXX) -endif() - -find_package(Threads REQUIRED) - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() - -list(FIND CMAKE_C_COMPILE_FEATURES c_std_11 HAS_C11) -if(NOT HAS_C11 LESS 0) - set(MDBX_C_STANDARD 11) -else() - set(MDBX_C_STANDARD 99) -endif() -message(STATUS "Use C${MDBX_C_STANDARD} for libmdbx") - -# not supported by this (minimal) script -add_definitions(-DMDBX_AVOID_CRT=0) - -# provide build timestamp -string(TIMESTAMP MDBX_BUILD_TIMESTAMP UTC) -add_definitions(-DMDBX_BUILD_TIMESTAMP="${MDBX_BUILD_TIMESTAMP}") - -# provide compiler info -execute_process(COMMAND sh -c "${CMAKE_C_COMPILER} --version | head -1" - OUTPUT_VARIABLE MDBX_BUILD_COMPILER - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET - RESULT_VARIABLE rc) -if(rc OR NOT MDBX_BUILD_COMPILER) - string(STRIP "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}" MDBX_BUILD_COMPILER) -endif() -add_definitions(-DMDBX_BUILD_COMPILER="${MDBX_BUILD_COMPILER}") - -# provide cpu/arch-system pair -if(CMAKE_C_COMPILER_TARGET) - set(MDBX_BUILD_TARGET "${CMAKE_C_COMPILER_TARGET}") -elseif(CMAKE_C_PLATFORM_ID AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) - string(STRIP "${CMAKE_C_PLATFORM_ID}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_LIBRARY_ARCHITECTURE) - string(STRIP "${CMAKE_LIBRARY_ARCHITECTURE}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) - string(STRIP "${CMAKE_GENERATOR_PLATFORM}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_SYSTEM_ARCH) - string(STRIP "${CMAKE_SYSTEM_ARCH}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -else() - string(STRIP "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -endif() -add_definitions(-DMDBX_BUILD_TARGET="${MDBX_BUILD_TARGET}") - -# provide build target-config -if(CMAKE_CONFIGURATION_TYPES) - add_definitions(-DMDBX_BUILD_CONFIG="$") -else() - add_definitions(-DMDBX_BUILD_CONFIG="${CMAKE_BUILD_TYPE}") -endif() - -# provide build cflags -set(MDBX_BUILD_FLAGS "") -list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_FLAGS}) -list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_DEFINES}) -if(CMAKE_CONFIGURATION_TYPES) - add_definitions(-DMDBX_BUILD_FLAGS_CONFIG="$<$:${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_DEFINES_DEBUG}>$<$:${CMAKE_C_FLAGS_RELEASE} ${CMAKE_C_DEFINES_RELEASE}>$<$:${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CMAKE_C_DEFINES_RELWITHDEBINFO}>$<$:${CMAKE_C_FLAGS_MINSIZEREL} ${CMAKE_C_DEFINES_MINSIZEREL}>") -else() - string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPERCASE) - list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPERCASE}}) - list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_DEFINES_${CMAKE_BUILD_TYPE_UPPERCASE}}) -endif() -list(REMOVE_DUPLICATES MDBX_BUILD_FLAGS) -string(REPLACE ";" " " MDBX_BUILD_FLAGS "${MDBX_BUILD_FLAGS}") -add_definitions(-DMDBX_BUILD_FLAGS="${MDBX_BUILD_FLAGS}") - -# shared library -if(NOT DEFINED MDBX_BUILD_SHARED_LIBRARY) - if(DEFINED BUILD_SHARED_LIBS) - option(MDBX_BUILD_SHARED_LIBRARY "Build libmdbx as shared library (DLL)" ${BUILD_SHARED_LIBS}) - else() - option(MDBX_BUILD_SHARED_LIBRARY "Build libmdbx as shared library (DLL)" ON) - endif() -endif() -if(MDBX_BUILD_SHARED_LIBRARY) - add_library(mdbx SHARED mdbx.c mdbx.h) - set_target_properties(mdbx PROPERTIES - C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON - PUBLIC_HEADER mdbx.h) - target_compile_definitions(mdbx PRIVATE LIBMDBX_EXPORTS INTERFACE LIBMDBX_IMPORTS) - if(DEFINED INTERPROCEDURAL_OPTIMIZATION) - set_target_properties(mdbx PROPERTIES - INTERPROCEDURAL_OPTIMIZATION $) - endif() - target_link_libraries(mdbx PRIVATE ${CMAKE_THREAD_LIBS_INIT}) - if(WIN32) - target_link_libraries(mdbx PRIVATE ntdll.lib) - endif() -endif() - -# static library used for tools, to avoid rpath/dll-path troubles -add_library(mdbx-static STATIC EXCLUDE_FROM_ALL mdbx.c mdbx.h) -set_target_properties(mdbx-static PROPERTIES - C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON - PUBLIC_HEADER mdbx.h) -target_link_libraries(mdbx-static INTERFACE ${CMAKE_THREAD_LIBS_INIT}) -if(DEFINED INTERPROCEDURAL_OPTIMIZATION) - set_target_properties(mdbx-static PROPERTIES - INTERPROCEDURAL_OPTIMIZATION $) -endif() -if(WIN32) - target_link_libraries(mdbx-static INTERFACE ntdll.lib) -endif() - -# mdbx-tools -foreach(TOOL mdbx_chk mdbx_copy mdbx_stat mdbx_dump mdbx_load) - add_executable(${TOOL} ${TOOL}.c) - set_target_properties(${TOOL} PROPERTIES - C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON) - if(DEFINED INTERPROCEDURAL_OPTIMIZATION) - set_target_properties(${TOOL} PROPERTIES - INTERPROCEDURAL_OPTIMIZATION $) - endif() - target_link_libraries(${TOOL} mdbx-static) -endforeach() - -cmake_policy(POP) diff --git a/src/contrib/db/libmdbx/CMakeLists.txt b/src/contrib/db/libmdbx/CMakeLists.txt deleted file mode 100644 index 75e9b3b..0000000 --- a/src/contrib/db/libmdbx/CMakeLists.txt +++ /dev/null @@ -1,342 +0,0 @@ -## -## Copyright 2019 Leonid Yuriev -## and other libmdbx authors: please see AUTHORS file. -## All rights reserved. -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted only as authorized by the OpenLDAP -## Public License. -## -## A copy of this license is available in the file LICENSE in the -## top-level directory of the distribution or, alternatively, at -## . -## - -## -## libmdbx = { Revised and extended descendant of Symas LMDB. } -## Please see README.md at https://github.com/leo-yuriev/libmdbx -## -## Libmdbx is superior to LMDB in terms of features and reliability, -## not inferior in performance. libmdbx works on Linux, FreeBSD, MacOS X -## and other systems compliant with POSIX.1-2008, but also support Windows -## as a complementary platform. -## -## The next version is under active non-public development and will be -## released as MithrilDB and libmithrildb for libraries & packages. -## Admittedly mythical Mithril is resembling silver but being stronger and -## lighter than steel. Therefore MithrilDB is rightly relevant name. -## -## MithrilDB will be radically different from libmdbx by the new database -## format and API based on C++17, as well as the Apache 2.0 License. -## The goal of this revolution is to provide a clearer and robust API, -## add more features and new valuable properties of database. -## -## The Future will (be) Positive. Ð’ÑÑ‘ будет хорошо. -## - -cmake_minimum_required(VERSION 3.8.2) -cmake_policy(PUSH) -cmake_policy(VERSION 3.8.2) -if(NOT CMAKE_VERSION VERSION_LESS 3.13) - cmake_policy(SET CMP0077 NEW) -endif() -if(NOT CMAKE_VERSION VERSION_LESS 3.12) - cmake_policy(SET CMP0075 NEW) -endif() -if(NOT CMAKE_VERSION VERSION_LESS 3.9) - cmake_policy(SET CMP0069 NEW) - include(CheckIPOSupported) - check_ipo_supported(RESULT CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE) -else() - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE FALSE) -endif() - -if(DEFINED PROJECT_NAME) - set(SUBPROJECT ON) - set(NOT_SUBPROJECT OFF) - if(NOT DEFINED BUILD_TESTING) - set(BUILD_TESTING OFF) - endif() -else() - set(SUBPROJECT OFF) - set(NOT_SUBPROJECT ON) - project(libmdbx C CXX) - if(NOT DEFINED BUILD_TESTING) - set(BUILD_TESTING ON) - endif() -endif() - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() - -macro(add_mdbx_option NAME DESCRIPTION DEFAULT) - list(APPEND MDBX_BUILD_OPTIONS ${NAME}) - if(NOT ${DEFAULT} STREQUAL "AUTO") - option(${NAME} "${DESCRIPTION}" ${DEFAULT}) - endif() -endmacro() - -# only for compatibility testing -# set(CMAKE_CXX_STANDARD 14) - -if(NOT "$ENV{TEAMCITY_PROCESS_FLOW_ID}" STREQUAL "") - set(CI TEAMCITY) - message(STATUS "TeamCity CI") -elseif(NOT "$ENV{TRAVIS}" STREQUAL "") - set(CI TRAVIS) - message(STATUS "Travis CI") -elseif(NOT "$ENV{CIRCLECI}" STREQUAL "") - set(CI CIRCLE) - message(STATUS "Circle CI") -elseif(NOT "$ENV{APPVEYOR}" STREQUAL "") - set(CI APPVEYOR) - message(STATUS "AppVeyor CI") -elseif(NOT "$ENV{CI}" STREQUAL "") - set(CI "$ENV{CI}") - message(STATUS "Other CI (${CI})") -else() - message(STATUS "Assume No any CI environment") - unset(CI) -endif() - -# output all mdbx-related targets in single directory -if(NOT DEFINED MDBX_OUTPUT_DIR) - set(MDBX_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) -endif() -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) -set(CMAKE_PDB_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MDBX_OUTPUT_DIR}) - -include(CheckLibraryExists) -include(CheckIncludeFiles) -include(CheckCCompilerFlag) -include(CheckSymbolExists) -include(CheckCSourceRuns) -include(CheckCXXSourceRuns) -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) -include(TestBigEndian) -include(CheckFunctionExists) -include(FindPackageMessage) -include(CheckStructHasMember) -include(CMakeDependentOption) -include(GNUInstallDirs) - -if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION LESS 1900) - message(SEND_ERROR "MSVC compiler ${MSVC_VERSION} is too old for building MDBX." - " At least 'Microsoft Visual Studio 2015' is required.") -endif() - -# Set default build type to Release. This is to ease a User's life. -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() -string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPERCASE) - -include(cmake/utils.cmake) -include(cmake/compiler.cmake) -include(cmake/profile.cmake) - -find_program(ECHO echo) -find_program(CAT cat) -find_program(GIT git) -find_program(LD ld) - -# CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) -# CHECK_INCLUDE_FILES(sys/uio.h HAVE_SYS_UIO_H) -# CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H) - -CHECK_FUNCTION_EXISTS(pow NOT_NEED_LIBM) -if(NOT_NEED_LIBM) - set(LIB_MATH "") -else() - set(CMAKE_REQUIRED_LIBRARIES m) - CHECK_FUNCTION_EXISTS(pow HAVE_LIBM) - if(HAVE_LIBM) - set(LIB_MATH m) - else() - message(FATAL_ERROR "No libm found for math support") - endif() -endif() - -find_package(Threads REQUIRED) - -if(SUBPROJECT) - if(NOT DEFINED BUILD_SHARED_LIBS) - option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)" OFF) - endif() - if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) - option(CMAKE_POSITION_INDEPENDENT_CODE "Generate position independed (PIC)" ON) - endif() -else() - option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)" ON) - option(CMAKE_POSITION_INDEPENDENT_CODE "Generate position independed (PIC)" ON) - if (CC_HAS_ARCH_NATIVE) - option(BUILD_FOR_NATIVE_CPU "Generate code for the compiling machine CPU" OFF) - endif() - - if(CMAKE_CONFIGURATION_TYPES OR NOT CMAKE_BUILD_TYPE_UPPERCASE STREQUAL "DEBUG") - set(INTERPROCEDURAL_OPTIMIZATION_DEFAULT ON) - else() - set(INTERPROCEDURAL_OPTIMIZATION_DEFAULT OFF) - endif() - - if(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE - OR GCC_LTO_AVAILABLE OR MSVC_LTO_AVAILABLE OR CLANG_LTO_AVAILABLE) - option(INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural/LTO optimization" ${INTERPROCEDURAL_OPTIMIZATION_DEFAULT}) - endif() - - if(INTERPROCEDURAL_OPTIMIZATION) - if(GCC_LTO_AVAILABLE) - set(LTO_ENABLED TRUE) - set(CMAKE_AR ${CMAKE_GCC_AR} CACHE PATH "Path to ar program with LTO-plugin" FORCE) - set(CMAKE_NM ${CMAKE_GCC_NM} CACHE PATH "Path to nm program with LTO-plugin" FORCE) - set(CMAKE_RANLIB ${CMAKE_GCC_RANLIB} CACHE PATH "Path to ranlib program with LTO-plugin" FORCE) - message(STATUS "MDBX indulge Link-Time Optimization by GCC") - elseif(CLANG_LTO_AVAILABLE) - set(LTO_ENABLED TRUE) - set(CMAKE_AR ${CMAKE_CLANG_AR} CACHE PATH "Path to ar program with LTO-plugin" FORCE) - set(CMAKE_NM ${CMAKE_CLANG_NM} CACHE PATH "Path to nm program with LTO-plugin" FORCE) - set(CMAKE_RANLIB ${CMAKE_CLANG_RANLIB} CACHE PATH "Path to ranlib program with LTO-plugin" FORCE) - message(STATUS "MDBX indulge Link-Time Optimization by CLANG") - elseif(MSVC_LTO_AVAILABLE) - set(LTO_ENABLED TRUE) - message(STATUS "MDBX indulge Link-Time Optimization by MSVC") - elseif(CMAKE_INTERPROCEDURAL_OPTIMIZATION_AVAILABLE) - message(STATUS "MDBX indulge Interprocedural Optimization by CMake") - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) - set(LTO_ENABLED TRUE) - else() - message(WARNING "Unable to engage interprocedural/LTO optimization.") - endif() - else() - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) - set(LTO_ENABLED FALSE) - endif() - - find_program(VALGRIND valgrind) - if(VALGRIND) - # LY: cmake is ugly and nasty. - # - therefore memcheck-options should be defined before including ctest; - # - otherwise ctest may ignore it. - set(MEMORYCHECK_SUPPRESSIONS_FILE - "${PROJECT_SOURCE_DIR}/test/valgrind_suppress.txt" - CACHE FILEPATH "Suppressions file for Valgrind" FORCE) - set(MEMORYCHECK_COMMAND_OPTIONS - "--trace-children=yes --leak-check=full --track-origins=yes --error-exitcode=42 --error-markers=@ --errors-for-leak-kinds=definite --fair-sched=yes --suppressions=${MEMORYCHECK_SUPPRESSIONS_FILE}" - CACHE STRING "Valgrind options" FORCE) - set(VALGRIND_COMMAND_OPTIONS "${MEMORYCHECK_COMMAND_OPTIONS}" CACHE STRING "Valgrind options" FORCE) - endif() - - # - # Enable 'make tags' target. - find_program(CTAGS ctags) - if(CTAGS) - add_custom_target(tags COMMAND ${CTAGS} -R -f tags - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - add_custom_target(ctags DEPENDS tags) - endif(CTAGS) - - # - # Enable 'make reformat' target. - find_program(CLANG_FORMAT - NAMES clang-format-6.0 clang-format-5.0 clang-format-4.0 - clang-format-3.9 clang-format-3.8 clang-format-3.7 clang-format) - if(CLANG_FORMAT AND UNIX) - add_custom_target(reformat - VERBATIM - COMMAND - git ls-files | - grep -E \\.\(c|cxx|cc|cpp|h|hxx|hpp\)\(\\.in\)?\$ | - xargs ${CLANG_FORMAT} -i --style=file - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - endif() - - if(NOT "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") - add_custom_target(distclean) - add_custom_command(TARGET distclean - COMMAND ${CMAKE_COMMAND} -E remove_directory "${PROJECT_BINARY_DIR}" - COMMENT "Removing the build directory and its content") - elseif(IS_DIRECTORY .git AND GIT) - add_custom_target(distclean) - add_custom_command(TARGET distclean - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMAND ${GIT} submodule foreach --recursive git clean -f -X -d - COMMAND ${GIT} clean -f -X -d - COMMENT "Removing all build files from the source directory") - endif() - - setup_compile_flags() -endif(SUBPROJECT) - -list(FIND CMAKE_C_COMPILE_FEATURES c_std_11 HAS_C11) -if(NOT HAS_C11 LESS 0) - set(MDBX_C_STANDARD 11) -else() - set(MDBX_C_STANDARD 99) -endif() -message(STATUS "Use C${MDBX_C_STANDARD} for libmdbx") - -############################################################################## -############################################################################## -# -# #### ##### ##### # #### # # #### -# # # # # # # # # ## # # -# # # # # # # # # # # # #### -# # # ##### # # # # # # # # -# # # # # # # # # ## # # -# #### # # # #### # # #### -# - -set(MDBX_BUILD_OPTIONS ENABLE_ASAN MDBX_USE_VALGRIND ENABLE_GPROF ENABLE_GCOV) -add_mdbx_option(MDBX_BUILD_SHARED_LIBRARY "Build libmdbx as shared library (DLL)" ${BUILD_SHARED_LIBS}) -add_mdbx_option(MDBX_ALLOY_BUILD "Build MDBX library as single object file" ON) -add_mdbx_option(MDBX_TXN_CHECKOWNER "Checking transaction matches the calling thread inside libmdbx's API" ON) -add_mdbx_option(MDBX_TXN_CHECKPID "Paranoid checking PID inside libmdbx's API" AUTO) -mark_as_advanced(MDBX_TXN_CHECKPID) -if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - add_mdbx_option(MDBX_DISABLE_GNU_SOURCE "Don't use nonstandard GNU/Linux extension functions" OFF) - mark_as_advanced(MDBX_DISABLE_GNU_SOURCE) -endif() -if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - add_mdbx_option(MDBX_OSX_SPEED_INSTEADOF_DURABILITY "Disable use fcntl(F_FULLFSYNC) in favor of speed" OFF) - mark_as_advanced(MDBX_OSX_SPEED_INSTEADOF_DURABILITY) -endif() -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - add_mdbx_option(MDBX_AVOID_CRT "Avoid dependence from MSVC CRT" ${NOT_SUBPROJECT}) - if(NOT MDBX_BUILD_SHARED_LIBRARY) - add_mdbx_option(MDBX_CONFIG_MANUAL_TLS_CALLBACK - "Provide mdbx_dll_handler() for manual initialization" OFF) - mark_as_advanced(MDBX_CONFIG_MANUAL_TLS_CALLBACK) - endif() -else() - add_mdbx_option(MDBX_USE_ROBUST "Use POSIX.1-2008 robust mutexes" AUTO) - mark_as_advanced(MDBX_USE_ROBUST) - add_mdbx_option(MDBX_USE_OFDLOCKS "Use Open file description locks (aka OFD locks, non-POSIX)" AUTO) - mark_as_advanced(MDBX_USE_OFDLOCKS) -endif() -option(MDBX_ENABLE_TESTS "Build MDBX tests." ${BUILD_TESTING}) - -################################################################################ -################################################################################ - -add_subdirectory(src) -if(MDBX_ENABLE_TESTS) - add_subdirectory(test) -endif() - -set(PACKAGE "libmdbx") -set(CPACK_PACKAGE_VERSION_MAJOR ${MDBX_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${MDBX_VERSION_MINOR}) -set(CPACK_PACKAGE_VERSION_PATCH ${MDBX_VERSION_RELEASE}) -set(CPACK_PACKAGE_VERSION_COMMIT ${MDBX_VERSION_REVISION}) -set(PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}.${CPACK_PACKAGE_VERSION_COMMIT}") -message(STATUS "libmdbx package version is ${PACKAGE_VERSION}") - -cmake_policy(POP) diff --git a/src/contrib/db/libmdbx/COPYRIGHT b/src/contrib/db/libmdbx/COPYRIGHT deleted file mode 100644 index 46e0961..0000000 --- a/src/contrib/db/libmdbx/COPYRIGHT +++ /dev/null @@ -1,22 +0,0 @@ -Copyright 2015-2019 Leonid Yuriev . -Copyright 2011-2015 Howard Chu, Symas Corp. -Copyright 2015,2016 Peter-Service R&D LLC. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted only as authorized by the OpenLDAP -Public License. - -A copy of this license is available in the file LICENSE in the -top-level directory of the distribution or, alternatively, at -. - -OpenLDAP is a registered trademark of the OpenLDAP Foundation. - -Individual files and/or contributed packages may be copyright by -other parties and/or subject to additional restrictions. - -This work also contains materials derived from public sources. - -Additional information about OpenLDAP can be obtained at -. diff --git a/src/contrib/db/libmdbx/GNUmakefile b/src/contrib/db/libmdbx/GNUmakefile deleted file mode 100644 index f6d0edf..0000000 --- a/src/contrib/db/libmdbx/GNUmakefile +++ /dev/null @@ -1,362 +0,0 @@ -# This makefile is for GNU Make, and nowadays provided -# just for compatibility and preservation of traditions. -# Please use CMake in case of any difficulties or problems. -# -# Preprocessor macros (for MDBX_OPTIONS) of interest... -# Note that the defaults should already be correct for most platforms; -# you should not need to change any of these. Read their descriptions -# in README and source code if you do. There may be other macros of interest. -SHELL := /bin/bash - -# install sandbox -SANDBOX ?= - -# install prefixes (inside sandbox) -prefix ?= /usr/local -mandir ?= $(prefix)/man - -# lib/bin suffix for multiarch/biarch, e.g. '.x86_64' -suffix ?= - -CC ?= gcc -LD ?= ld -MDBX_OPTIONS ?= -DNDEBUG=1 -CFLAGS ?= -Os -g3 -Wall -Werror -Wextra -Wpedantic -ffunction-sections -fPIC -fvisibility=hidden -std=gnu11 -pthread -Wno-tautological-compare - -# LY: '--no-as-needed,-lrt' for ability to built with modern glibc, but then run with the old -LDFLAGS ?= $(shell $(LD) --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1')$(shell $(LD) --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip') -EXE_LDFLAGS ?= -pthread - -################################################################################ - -UNAME := $(shell uname -s 2>/dev/null || echo Unknown) -define uname2sosuffix - case "$(UNAME)" in - Darwin*|Mach*) echo dylib;; - CYGWIN*|MINGW*|MSYS*|Windows*) echo dll;; - *) echo so;; - esac -endef -SO_SUFFIX := $(shell $(uname2sosuffix)) - -HEADERS := mdbx.h -LIBRARIES := libmdbx.a libmdbx.$(SO_SUFFIX) -TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk -MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1 mdbx_chk.1 - -.PHONY: mdbx all install clean test dist check - -all: $(LIBRARIES) $(TOOLS) - -mdbx: libmdbx.a libmdbx.$(SO_SUFFIX) - -tools: $(TOOLS) - -strip: all - strip libmdbx.$(SO_SUFFIX) $(TOOLS) - -clean: - rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* \ - *.gcov *.log *.err src/*.o test/*.o mdbx_example dist \ - config.h src/elements/config.h src/elements/version.c *.tar* - -libmdbx.a: mdbx-static.o - $(AR) rs $@ $? - -libmdbx.$(SO_SUFFIX): mdbx-dylib.o - $(CC) $(CFLAGS) $^ -pthread -shared $(LDFLAGS) -o $@ - -#> dist-cutoff-begin -ifeq ($(wildcard mdbx.c),mdbx.c) -#< dist-cutoff-end - -################################################################################ -# Amalgamated source code, i.e. distributed after `make dists` -MAN_SRCDIR := man1/ - -config.h: mdbx.c $(lastword $(MAKEFILE_LIST)) - (echo '#define MDBX_BUILD_TIMESTAMP "$(shell date +%Y-%m-%dT%H:%M:%S%z)"' \ - && echo '#define MDBX_BUILD_FLAGS "$(CFLAGS) $(LDFLAGS)"' \ - && echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"' \ - && echo '#define MDBX_BUILD_TARGET "$(shell set -o pipefail; LC_ALL=C $(CC) -v 2>&1 | grep -i '^Target:' | cut -d ' ' -f 2- || echo 'Please use GCC or CLANG compatible compiler')"' \ - ) > $@ - -mdbx-dylib.o: config.h mdbx.c $(lastword $(MAKEFILE_LIST)) - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' -DLIBMDBX_EXPORTS=1 -c mdbx.c -o $@ - -mdbx-static.o: config.h mdbx.c $(lastword $(MAKEFILE_LIST)) - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' -ULIBMDBX_EXPORTS -c mdbx.c -o $@ - -mdbx_%: mdbx_%.c libmdbx.a - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' $^ $(EXE_LDFLAGS) -o $@ - -#> dist-cutoff-begin -else -################################################################################ -# Plain (non-amalgamated) sources with test - -define uname2osal - case "$(UNAME)" in - CYGWIN*|MINGW*|MSYS*|Windows*) echo windows;; - *) echo unix;; - esac -endef - -define uname2titer - case "$(UNAME)" in - Darwin*|Mach*) echo 2;; - *) echo 12;; - esac -endef - -DIST_EXTRA := LICENSE README.md CMakeLists.txt GNUmakefile $(addprefix man1/, $(MANPAGES)) -DIST_SRC := mdbx.h mdbx.c $(addsuffix .c, $(TOOLS)) - -TEST_DB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.db -TEST_LOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.log -TEST_OSAL := $(shell $(uname2osal)) -TEST_ITER := $(shell $(uname2titer)) -TEST_SRC := test/osal-$(TEST_OSAL).cc $(filter-out $(wildcard test/osal-*.cc), $(wildcard test/*.cc)) -TEST_INC := $(wildcard test/*.h) -TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC)) -CXX ?= g++ -CXXSTD ?= $(shell $(CXX) -std=c++27 -c test/test.cc -o /dev/null 2>/dev/null && echo -std=c++17 || echo -std=c++11) -CXXFLAGS := $(CXXSTD) $(filter-out -std=gnu11,$(CFLAGS)) - -MAN_SRCDIR := src/man1/ -ALLOY_DEPS := $(wildcard src/elements/*) -MDBX_VERSION_GIT = ${shell set -o pipefail; git describe --tags | sed -n 's|^v*\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\)\(.*\)|\1|p' || echo 'Please fetch tags and/or install latest git version'} -MDBX_GIT_TIMESTAMP = $(shell git show --no-patch --format=%cI HEAD || echo 'Please install latest get version') -MDBX_GIT_DESCRIBE = $(shell git describe --tags --long --dirty=-dirty || echo 'Please fetch tags and/or install latest git version') -MDBX_VERSION_SUFFIX = $(shell set -o pipefail; echo -n '$(MDBX_GIT_DESCRIBE)' | tr -c -s '[a-zA-Z0-9]' _) -MDBX_BUILD_SOURCERY = $(shell set -o pipefail; $(MAKE) -s src/elements/version.c && (openssl dgst -r -sha256 src/elements/version.c || sha256sum src/elements/version.c || shasum -a 256 src/elements/version.c) 2>/dev/null | cut -d ' ' -f 1 || echo 'Please install openssl or sha256sum or shasum')_$(MDBX_VERSION_SUFFIX) - -test check: all mdbx_example mdbx_test - rm -f $(TEST_DB) $(TEST_LOG) && (set -o pipefail; \ - (./mdbx_test --progress --console=no --repeat=$(TEST_ITER) --pathname=$(TEST_DB) --dont-cleanup-after basic && \ - ./mdbx_test --mode=-writemap,-lifo --progress --console=no --repeat=1 --pathname=$(TEST_DB) --dont-cleanup-after basic) \ - | tee -a $(TEST_LOG) | tail -n 42) \ - && ./mdbx_chk -vvn $(TEST_DB) && ./mdbx_chk -vvn $(TEST_DB)-copy - -mdbx_example: mdbx.h example/example-mdbx.c libmdbx.$(SO_SUFFIX) - $(CC) $(CFLAGS) -I. example/example-mdbx.c ./libmdbx.$(SO_SUFFIX) -o $@ - -check-singleprocess: all mdbx_test - rm -f $(TEST_DB) $(TEST_LOG) && (set -o pipefail; \ - (./mdbx_test --progress --console=no --repeat=42 --pathname=$(TEST_DB) --dont-cleanup-after --hill && \ - ./mdbx_test --progress --console=no --repeat=2 --pathname=$(TEST_DB) --dont-cleanup-before --dont-cleanup-after --copy && \ - ./mdbx_test --mode=-writemap,-lifo --progress --console=no --repeat=42 --pathname=$(TEST_DB) --dont-cleanup-after --nested) \ - | tee -a $(TEST_LOG) | tail -n 42) \ - && ./mdbx_chk -vvn $(TEST_DB) && ./mdbx_chk -vvn $(TEST_DB)-copy - -check-fault: all mdbx_test - rm -f $(TEST_DB) $(TEST_LOG) && (set -o pipefail; ./mdbx_test --progress --console=no --pathname=$(TEST_DB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TEST_LOG) | tail -n 42) \ - ; ./mdbx_chk -vvnw $(TEST_DB) && ([ ! -e $(TEST_DB)-copy ] || ./mdbx_chk -vvn $(TEST_DB)-copy) - -VALGRIND=valgrind --trace-children=yes --log-file=valgrind-%p.log --leak-check=full --track-origins=yes --error-exitcode=42 --suppressions=test/valgrind_suppress.txt -memcheck check-valgrind: all mdbx_test - @echo "$(MDBX_OPTIONS)" | grep -q MDBX_USE_VALGRIND || echo "WARNING: Please build libmdbx with -DMDBX_USE_VALGRIND to avoid false-positives from Valgrind !!!" >&2 - rm -f valgrind-*.log $(TEST_DB) $(TEST_LOG) && (set -o pipefail; \ - ($(VALGRIND) ./mdbx_test --mode=-writemap,-lifo --progress --console=no --repeat=4 --pathname=$(TEST_DB) --dont-cleanup-after basic && \ - $(VALGRIND) ./mdbx_test --progress --console=no --pathname=$(TEST_DB) --dont-cleanup-before --dont-cleanup-after --copy && \ - $(VALGRIND) ./mdbx_test --progress --console=no --repeat=2 --pathname=$(TEST_DB) --dont-cleanup-after basic) \ - | tee -a $(TEST_LOG) | tail -n 42) \ - && $(VALGRIND) ./mdbx_chk -vvn $(TEST_DB) && ./mdbx_chk -vvn $(TEST_DB)-copy - -define test-rule -$(patsubst %.cc,%.o,$(1)): $(1) $(TEST_INC) mdbx.h $(lastword $(MAKEFILE_LIST)) - $(CXX) $(CXXFLAGS) $(MDBX_OPTIONS) -c $(1) -o $$@ - -endef -$(foreach file,$(TEST_SRC),$(eval $(call test-rule,$(file)))) - -mdbx_%: src/tools/mdbx_%.c libmdbx.a - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' $^ $(EXE_LDFLAGS) -o $@ - -mdbx_test: $(TEST_OBJ) libmdbx.$(SO_SUFFIX) - $(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@ - -git_DIR := $(shell if [ -d .git ]; then echo .git; elif [ -s .git -a -f .git ]; then grep '^gitdir: ' .git | cut -d ':' -f 2; else echo "Please use libmdbx as a git-submodule or the amalgamated source code" >&2 && echo git_directory; fi) - -src/elements/version.c: src/elements/version.c.in $(lastword $(MAKEFILE_LIST)) $(git_DIR)/HEAD $(git_DIR)/index $(git_DIR)/refs/tags - sed \ - -e "s|@MDBX_GIT_TIMESTAMP@|$(MDBX_GIT_TIMESTAMP)|" \ - -e "s|@MDBX_GIT_TREE@|$(shell git show --no-patch --format=%T HEAD || echo 'Please install latest get version')|" \ - -e "s|@MDBX_GIT_COMMIT@|$(shell git show --no-patch --format=%H HEAD || echo 'Please install latest get version')|" \ - -e "s|@MDBX_GIT_DESCRIBE@|$(MDBX_GIT_DESCRIBE)|" \ - -e "s|\$${MDBX_VERSION_MAJOR}|$(shell echo '$(MDBX_VERSION_GIT)' | cut -d . -f 1)|" \ - -e "s|\$${MDBX_VERSION_MINOR}|$(shell echo '$(MDBX_VERSION_GIT)' | cut -d . -f 2)|" \ - -e "s|\$${MDBX_VERSION_RELEASE}|$(shell echo '$(MDBX_VERSION_GIT)' | cut -d . -f 3)|" \ - -e "s|\$${MDBX_VERSION_REVISION}|$(shell git rev-list --count --no-merges HEAD || echo 'Please fetch tags and/or install latest git version')|" \ - src/elements/version.c.in > $@ - -src/elements/config.h: src/elements/version.c $(lastword $(MAKEFILE_LIST)) - (echo '#define MDBX_BUILD_TIMESTAMP "$(shell date +%Y-%m-%dT%H:%M:%S%z)"' \ - && echo '#define MDBX_BUILD_FLAGS "$(CFLAGS) $(LDFLAGS)"' \ - && echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"' \ - && echo '#define MDBX_BUILD_TARGET "$(shell set -o pipefail; LC_ALL=C $(CC) -v 2>&1 | grep -i '^Target:' | cut -d ' ' -f 2- || echo 'Please use GCC or CLANG compatible compiler')"' \ - && echo '#define MDBX_BUILD_SOURCERY $(MDBX_BUILD_SOURCERY)' \ - ) > $@ - -mdbx-dylib.o: src/elements/config.h src/elements/version.c src/alloy.c $(ALLOY_DEPS) $(lastword $(MAKEFILE_LIST)) - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' -DLIBMDBX_EXPORTS=1 -c src/alloy.c -o $@ - -mdbx-static.o: src/elements/config.h src/elements/version.c src/alloy.c $(ALLOY_DEPS) $(lastword $(MAKEFILE_LIST)) - $(CC) $(CFLAGS) $(MDBX_OPTIONS) '-DMDBX_CONFIG_H="config.h"' -ULIBMDBX_EXPORTS -c src/alloy.c -o $@ - -.PHONY: dist -dist: libmdbx-sources-$(MDBX_VERSION_SUFFIX).tar.gz $(lastword $(MAKEFILE_LIST)) - -libmdbx-sources-$(MDBX_VERSION_SUFFIX).tar.gz: $(addprefix dist/, $(DIST_SRC) $(DIST_EXTRA)) $(addprefix dist/man1/,$(MANPAGES)) - tar -c -a -f $@ --owner=0 --group=0 -C dist $(DIST_SRC) $(DIST_EXTRA) \ - && rm dist/@tmp-shared_internals.inc - -dist/mdbx.h: mdbx.h src/elements/version.c $(lastword $(MAKEFILE_LIST)) - mkdir -p dist && cp $< $@ - -dist/GNUmakefile: GNUmakefile - mkdir -p dist && sed -e '/^#> dist-cutoff-begin/,/^#< dist-cutoff-end/d' $< > $@ - -dist/@tmp-shared_internals.inc: src/elements/version.c $(ALLOY_DEPS) $(lastword $(MAKEFILE_LIST)) - mkdir -p dist && sed \ - -e 's|#pragma once|#define MDBX_ALLOY 1\n#define MDBX_BUILD_SOURCERY $(MDBX_BUILD_SOURCERY)|' \ - -e 's|#include "../../mdbx.h"|@INCLUDE "mdbx.h"|' \ - -e '/#include "defs.h"/r src/elements/defs.h' \ - -e '/#include "osal.h"/r src/elements/osal.h' \ - src/elements/internals.h > $@ - -dist/mdbx.c: dist/@tmp-shared_internals.inc $(lastword $(MAKEFILE_LIST)) - mkdir -p dist && (cat dist/@tmp-shared_internals.inc \ - && cat src/elements/core.c src/elements/osal.c src/elements/version.c \ - && echo '#if defined(_WIN32) || defined(_WIN64)' \ - && cat src/elements/lck-windows.c && echo '#else /* LCK-implementation */' \ - && cat src/elements/lck-posix.c && echo '#endif /* LCK-implementation */' \ - ) | grep -v -e '#include "' -e '#pragma once' | sed 's|@INCLUDE|#include|' > $@ - -define dist-tool-rule -dist/$(1).c: src/tools/$(1).c src/tools/wingetopt.h src/tools/wingetopt.c \ - dist/@tmp-shared_internals.inc $(lastword $(MAKEFILE_LIST)) - mkdir -p dist && sed \ - -e '/#include "..\/elements\/internals.h"/r dist/@tmp-shared_internals.inc' \ - -e '/#include "wingetopt.h"/r src/tools/wingetopt.c' \ - src/tools/$(1).c \ - | grep -v -e '#include "' -e '#pragma once' -e '#define MDBX_ALLOY' \ - | sed 's|@INCLUDE|#include|' > $$@ - -endef -$(foreach file,$(TOOLS),$(eval $(call dist-tool-rule,$(file)))) - -dist/man1/mdbx_%.1: src/man1/mdbx_%.1 - mkdir -p dist/man1/ && cp $< $@ -dist/LICENSE: LICENSE - mkdir -p dist/man1/ && cp $< $@ -dist/README.md: README.md - mkdir -p dist/man1/ && cp $< $@ -dist/CMakeLists.txt: CMakeLists.dist-minimal - mkdir -p dist/man1/ && cp $< $@ -endif - -################################################################################ -# Cross-compilation simple test - -CROSS_LIST = mips-linux-gnu-gcc \ - powerpc64-linux-gnu-gcc powerpc-linux-gnu-gcc \ - arm-linux-gnueabihf-gcc aarch64-linux-gnu-gcc \ - sh4-linux-gnu-gcc mips64-linux-gnuabi64-gcc - -# hppa-linux-gnu-gcc - don't supported by current qemu release -# s390x-linux-gnu-gcc - qemu troubles (hang/abort) -# sparc64-linux-gnu-gcc - qemu troubles (fcntl for F_SETLK/F_GETLK) -# alpha-linux-gnu-gcc - qemu (or gcc) troubles (coredump) - -CROSS_LIST_NOQEMU = hppa-linux-gnu-gcc s390x-linux-gnu-gcc \ - sparc64-linux-gnu-gcc alpha-linux-gnu-gcc - -cross-gcc: - @echo "CORRESPONDING CROSS-COMPILERs ARE REQUIRED." - @echo "FOR INSTANCE: apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" - @for CC in $(CROSS_LIST_NOQEMU) $(CROSS_LIST); do \ - echo "===================== $$CC"; \ - $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) all || exit $$?; \ - done - -# Unfortunately qemu don't provide robust support for futexes. -# Therefore it is impossible to run full multi-process tests. -cross-qemu: - @echo "CORRESPONDING CROSS-COMPILERs AND QEMUs ARE REQUIRED." - @echo "FOR INSTANCE: " - @echo " 1) apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" - @echo " 2) apt install binfmt-support qemu-user-static qemu-user qemu-system-arm qemu-system-mips qemu-system-misc qemu-system-ppc qemu-system-sparc" - @for CC in $(CROSS_LIST); do \ - echo "===================== $$CC + qemu"; \ - $(MAKE) clean && \ - CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static MDBX_OPTIONS="-DMDBX_SAFE4QEMU $(MDBX_OPTIONS)" \ - $(MAKE) check-singleprocess || exit $$?; \ - done - -#< dist-cutoff-end -install: $(LIBRARIES) $(TOOLS) $(HEADERS) - mkdir -p $(SANDBOX)$(prefix)/bin$(suffix) \ - && cp -t $(SANDBOX)$(prefix)/bin$(suffix) $(TOOLS) && \ - mkdir -p $(SANDBOX)$(prefix)/lib$(suffix) \ - && cp -t $(SANDBOX)$(prefix)/lib$(suffix) $(LIBRARIES) && \ - mkdir -p $(SANDBOX)$(prefix)/include \ - && cp -t $(SANDBOX)$(prefix)/include $(HEADERS) && \ - mkdir -p $(SANDBOX)$(mandir)/man1 \ - && cp -t $(SANDBOX)$(mandir)/man1 $(addprefix $(MAN_SRCDIR), $(MANPAGES)) - -################################################################################ -# Benchmarking by ioarena - -IOARENA ?= $(shell \ - (test -x ../ioarena/@BUILD/src/ioarena && echo ../ioarena/@BUILD/src/ioarena) || \ - (test -x ../../@BUILD/src/ioarena && echo ../../@BUILD/src/ioarena) || \ - (test -x ../../src/ioarena && echo ../../src/ioarena) || which ioarena) -NN ?= 25000000 - -ifneq ($(wildcard $(IOARENA)),) - -.PHONY: bench clean-bench re-bench - -clean-bench: - rm -rf bench-*.txt _ioarena/* - -re-bench: clean-bench bench - -define bench-rule -bench-$(1)_$(2).txt: $(3) $(IOARENA) $(lastword $(MAKEFILE_LIST)) - LD_LIBRARY_PATH="./:$$$${LD_LIBRARY_PATH}" \ - $(IOARENA) -D $(1) -B crud -m nosync -n $(2) \ - | tee $$@ | grep throughput && \ - LD_LIBRARY_PATH="./:$$$${LD_LIBRARY_PATH}" \ - $(IOARENA) -D $(1) -B get,iterate -m sync -r 4 -n $(2) \ - | tee -a $$@ | grep throughput \ - || mv -f $$@ $$@.error - -endef - -$(eval $(call bench-rule,mdbx,$(NN),libmdbx.$(SO_SUFFIX))) - -$(eval $(call bench-rule,sophia,$(NN))) -$(eval $(call bench-rule,leveldb,$(NN))) -$(eval $(call bench-rule,rocksdb,$(NN))) -$(eval $(call bench-rule,wiredtiger,$(NN))) -$(eval $(call bench-rule,forestdb,$(NN))) -$(eval $(call bench-rule,lmdb,$(NN))) -$(eval $(call bench-rule,nessdb,$(NN))) -$(eval $(call bench-rule,sqlite3,$(NN))) -$(eval $(call bench-rule,ejdb,$(NN))) -$(eval $(call bench-rule,vedisdb,$(NN))) -$(eval $(call bench-rule,dummy,$(NN))) - -$(eval $(call bench-rule,debug,10)) - -bench: bench-mdbx_$(NN).txt - -.PHONY: bench-debug - -bench-debug: bench-debug_10.txt - -bench-quartet: bench-mdbx_$(NN).txt bench-lmdb_$(NN).txt bench-rocksdb_$(NN).txt bench-wiredtiger_$(NN).txt - -endif diff --git a/src/contrib/db/libmdbx/LICENSE b/src/contrib/db/libmdbx/LICENSE deleted file mode 100644 index 05ad757..0000000 --- a/src/contrib/db/libmdbx/LICENSE +++ /dev/null @@ -1,47 +0,0 @@ -The OpenLDAP Public License - Version 2.8, 17 August 2003 - -Redistribution and use of this software and associated documentation -("Software"), with or without modification, are permitted provided -that the following conditions are met: - -1. Redistributions in source form must retain copyright statements - and notices, - -2. Redistributions in binary form must reproduce applicable copyright - statements and notices, this list of conditions, and the following - disclaimer in the documentation and/or other materials provided - with the distribution, and - -3. Redistributions must contain a verbatim copy of this document. - -The OpenLDAP Foundation may revise this license from time to time. -Each revision is distinguished by a version number. You may use -this Software under terms of this license revision or under the -terms of any subsequent revision of the license. - -THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS -CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) -OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -The names of the authors and copyright holders must not be used in -advertising or otherwise to promote the sale, use or other dealing -in this Software without specific, written prior permission. Title -to copyright in this Software shall at all times remain with copyright -holders. - -OpenLDAP is a registered trademark of the OpenLDAP Foundation. - -Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, -California, USA. All Rights Reserved. Permission to copy and -distribute verbatim copies of this document is granted. diff --git a/src/contrib/db/libmdbx/README.md b/src/contrib/db/libmdbx/README.md deleted file mode 100644 index 1e82f3f..0000000 --- a/src/contrib/db/libmdbx/README.md +++ /dev/null @@ -1,591 +0,0 @@ -### The [repository now only mirrored on the Github](https://abf.io/erthink/libmdbx) due to illegal discriminatory restrictions for Russian Crimea and for sovereign crimeans. - ------ - -libmdbx -====================================== - -_libmdbx_ is an extremely fast, compact, powerful, embedded -transactional [key-value -store](https://en.wikipedia.org/wiki/Key-value_database) -database, with permissive [OpenLDAP Public License](LICENSE). -_libmdbx_ has a specific set of properties and capabilities, -focused on creating unique lightweight solutions with -extraordinary performance. - -The next version is under active non-public development and will be -released as **_MithrilDB_** and `libmithrildb` for libraries & packages. -Admittedly mythical [Mithril](https://en.wikipedia.org/wiki/Mithril) is -resembling silver but being stronger and lighter than steel. Therefore -_MithrilDB_ is rightly relevant name. -> _MithrilDB_ will be radically different from _libmdbx_ by the new -> database format and API based on C++17, as well as the [Apache 2.0 -> License](https://www.apache.org/licenses/LICENSE-2.0). The goal of this -> revolution is to provide a clearer and robust API, add more features and -> new valuable properties of database. - -*The Future will (be) [Positive](https://www.ptsecurity.com). Ð’ÑÑ‘ будет хорошо.* - -[![Build Status](https://travis-ci.org/leo-yuriev/libmdbx.svg?branch=master)](https://travis-ci.org/leo-yuriev/libmdbx) -[![Build status](https://ci.appveyor.com/api/projects/status/ue94mlopn50dqiqg/branch/master?svg=true)](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master) -[![Coverity Scan Status](https://scan.coverity.com/projects/12915/badge.svg)](https://scan.coverity.com/projects/reopen-libmdbx) - -## Table of Contents -- [Overview](#overview) - - [Comparison with other databases](#comparison-with-other-databases) - - [History & Acknowledgments](#history) -- [Description](#description) - - [Key features](#key-features) - - [Improvements over LMDB](#improvements-over-lmdb) - - [Gotchas](#gotchas) -- [Usage](#usage) - - [Building](#building) - - [Bindings](#bindings) -- [Performance comparison](#performance-comparison) - - [Integral performance](#integral-performance) - - [Read scalability](#read-scalability) - - [Sync-write mode](#sync-write-mode) - - [Lazy-write mode](#lazy-write-mode) - - [Async-write mode](#async-write-mode) - - [Cost comparison](#cost-comparison) - ------ - -## Overview - -_libmdbx_ is revised and extended descendant of amazing [Lightning -Memory-Mapped -Database](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database). -_libmdbx_ inherits all features and characteristics from -[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database), -but resolves some issues and adds several features. - - - _libmdbx_ guarantee data integrity after crash unless this was explicitly -neglected in favour of write performance. - - - _libmdbx_ allows multiple processes to read and update several key-value -tables concurrently, while being -[ACID](https://en.wikipedia.org/wiki/ACID)-compliant, with minimal -overhead and Olog(N) operation cost. - - - _libmdbx_ enforce -[serializability](https://en.wikipedia.org/wiki/Serializability) for -writers by single -[mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) and affords -[wait-free](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom) -for parallel readers without atomic/interlocked operations, while -writing and reading transactions do not block each other. - - - _libmdbx_ uses [B+Trees](https://en.wikipedia.org/wiki/B%2B_tree) and -[Memory-Mapping](https://en.wikipedia.org/wiki/Memory-mapped_file), -doesn't use [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) -which might be a caveat for some workloads. - - - _libmdbx_ implements a simplified variant of the [Berkeley -DB](https://en.wikipedia.org/wiki/Berkeley_DB) and/or -[dbm](https://en.wikipedia.org/wiki/DBM_(computing)) API. - - - _libmdbx_ supports Linux, Windows, MacOS, FreeBSD and other systems -compliant with POSIX.1-2008. - -### Comparison with other databases -For now please refer to [chapter of "BoltDB comparison with other -databases"](https://github.com/coreos/bbolt#comparison-with-other-databases) -which is also (mostly) applicable to _libmdbx_. - -### History -At first the development was carried out within the -[ReOpenLDAP](https://github.com/leo-yuriev/ReOpenLDAP) project. About a -year later _libmdbx_ was separated into standalone project, which was -[presented at Highload++ 2015 -conference](http://www.highload.ru/2015/abstracts/1831.html). - -Since 2017 _libmdbx_ is used in [Fast Positive Tables](https://github.com/leo-yuriev/libfpta), -and development is funded by [Positive Technologies](https://www.ptsecurity.com). - -### Acknowledgments -Howard Chu is the author of LMDB, from which -originated the MDBX in 2015. - -Martin Hedenfalk is the author of `btree.c` code, which -was used for begin development of LMDB. - ------ - -Description -=========== - -## Key features - -1. Key-value pairs are stored in ordered map(s), keys are always sorted, -range lookups are supported. - -2. Data is [memory-mapped](https://en.wikipedia.org/wiki/Memory-mapped_file) -into each worker DB process, and could be accessed zero-copy from transactions. - -3. Transactions are -[ACID](https://en.wikipedia.org/wiki/ACID)-compliant, through to -[MVCC](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) -and [CoW](https://en.wikipedia.org/wiki/Copy-on-write). Writes are -strongly serialized and aren't blocked by reads, transactions can't -conflict with each other. Reads are guaranteed to get only commited data -([relaxing serializability](https://en.wikipedia.org/wiki/Serializability#Relaxing_serializability)). - -4. Read transactions are -[non-blocking](https://en.wikipedia.org/wiki/Non-blocking_algorithm), -don't use [atomic operations](https://en.wikipedia.org/wiki/Linearizability#High-level_atomic_operations). -Readers don't block each other and aren't blocked by writers. Read -performance scales linearly with CPU core count. - > Nonetheless, "connect to DB" (starting the first read transaction in a thread) and - > "disconnect from DB" (closing DB or thread termination) requires a lock - > acquisition to register/unregister at the "readers table". - -5. Keys with multiple values are stored efficiently without key -duplication, sorted by value, including integers (valuable for -secondary indexes). - -6. Efficient operation on short fixed length keys, -including 32/64-bit integer types. - -7. [WAF](https://en.wikipedia.org/wiki/Write_amplification) (Write -Amplification Factor) и RAF (Read Amplification Factor) are Olog(N). - -8. No [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) and -transaction journal. In case of a crash no recovery needed. No need for -regular maintenance. Backups can be made on the fly on working DB -without freezing writers. - -9. No additional memory management, all done by basic OS services. - - -## Improvements over LMDB - -_libmdbx_ is superior to _legendary [LMDB](https://symas.com/lmdb/)_ in -terms of features and reliability, not inferior in performance. In -comparison to LMDB, _libmdbx_ make things "just work" perfectly and -out-of-the-box, not silently and catastrophically break down. The list -below is pruned down to the improvements most notable and obvious from -the user's point of view. - -1. Automatic on-the-fly database size control by preset parameters, both -reduction and increment. - > _libmdbx_ manage the database size according to parameters specified - > by `mdbx_env_set_geometry()` function, - > ones include the growth step and the truncation threshold. - -2. Automatic continuous zero-overhead database compactification. - > _libmdbx_ logically move as possible a freed pages - > at end of allocation area into unallocated space, - > and then release such space if a lot of. - -3. LIFO policy for recycling a Garbage Collection items. On systems with a disk -write-back cache, this can significantly increase write performance, up to -several times in a best case scenario. - > LIFO means that for reuse pages will be taken which became unused the lastest. - > Therefore the loop of database pages circulation becomes as short as possible. - > In other words, the number of pages, that are overwritten in memory - > and on disk during a series of write transactions, will be as small as possible. - > Thus creates ideal conditions for the efficient operation of the disk write-back cache. - -4. Fast estimation of range query result volume, i.e. how many items can -be found between a `KEY1` and a `KEY2`. This is prerequisite for build -and/or optimize query execution plans. - > _libmdbx_ performs a rough estimate based only on b-tree pages that - > are common for the both stacks of cursors that were set to corresponing - > keys. - -5. `mdbx_chk` tool for database integrity check. - -6. Guarantee of database integrity even in asynchronous unordered write-to-disk mode. - > _libmdbx_ propose additional trade-off by implementing append-like manner for updates - > in `NOSYNC` and `MAPASYNC` modes, that avoid database corruption after a system crash - > contrary to LMDB. Nevertheless, the `MDBX_UTTERLY_NOSYNC` mode available to match LMDB behaviour, - > and for a special use-cases. - -7. Automated steady flush to disk upon volume of changes and/or by -timeout via cheap polling. - -8. Sequence generation and three cheap persistent 64-bit markers with ACID. - -9. Support for keys and values of zero length, including multi-values -(aka sorted duplicates). - -10. The handler of lack-of-space condition with a callback, -that allow you to control and resolve such situations. - -11. Support for opening a database in the exclusive mode, including on a network share. - -12. Extended transaction info, including dirty and leftover space info -for a write transaction, reading lag and hold over space for read -transactions. - -13. Extended whole-database info (aka environment) and reader enumeration. - -14. Extended update or delete, _at once_ with getting previous value -and addressing the particular item from multi-value with the same key. - -15. Support for explicitly updating the existing record, not insertion a new one. - -16. All cursors are uniformly, can be reused and should be closed explicitly, -regardless ones were opened within write or read transaction. - -17. Correct update of current record with `MDBX_CURRENT` flag when size -of key or data was changed, including sorted duplicated. - -18. Opening database handles is spared from race conditions and -pre-opening is not needed. - -19. Ability to determine whether the particular data is on a dirty page -or not, that allows to avoid copy-out before updates. - -20. Ability to determine whether the cursor is pointed to a key-value -pair, to the first, to the last, or not set to anything. - -21. Returning `MDBX_EMULTIVAL` error in case of ambiguous update or delete. - -22. On **MacOS** the `fcntl(F_FULLFSYNC)` syscall is used _by -default_ to synchronize data with the disk, as this is [the only way to -guarantee data -durability](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fsync.2.html) -in case of power failure. Unfortunately, in scenarios with high write -intensity, the use of `F_FULLFSYNC` significant degrades performance -compared to LMDB, where the `fsync()` syscall is used. Therefore, -_libmdbx_ allows you to override this behavior by defining the -`MDBX_OSX_SPEED_INSTEADOF_DURABILITY=1` option while build the library. - -23. On **Windows** the `LockFileEx()` syscall is used for locking, since -it allows place the database on network drives, and provides protection -against incompetent user actions (aka -[poka-yoke](https://en.wikipedia.org/wiki/Poka-yoke)). Therefore -_libmdbx_ may be a little lag in performance tests from LMDB where a -named mutexes are used. - - -## Gotchas - -1. There cannot be more than one writer at a time. - > On the other hand, this allows serialize an updates and eliminate any - > possibility of conflicts, deadlocks or logical errors. - -2. No [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) means -relatively big [WAF](https://en.wikipedia.org/wiki/Write_amplification) -(Write Amplification Factor). Because of this syncing data to disk might -be quite resource intensive and be main performance bottleneck during -intensive write workload. - > As compromise _libmdbx_ allows several modes of lazy and/or periodic - > syncing, including `MAPASYNC` mode, which modificate data in memory and - > asynchronously syncs data to disk, moment to sync is picked by OS. - > - > Although this should be used with care, synchronous transactions in a DB - > with transaction journal will require 2 IOPS minimum (probably 3-4 in - > practice) because of filesystem overhead, overhead depends on - > filesystem, not on record count or record size. In _libmdbx_ IOPS count - > will grow logarithmically depending on record count in DB (height of B+ - > tree) and will require at least 2 IOPS per transaction too. - -3. [CoW](https://en.wikipedia.org/wiki/Copy-on-write) for -[MVCC](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) -is done on memory page level with -[B+trees](https://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE). -Therefore altering data requires to copy about Olog(N) memory pages, -which uses [memory bandwidth](https://en.wikipedia.org/wiki/Memory_bandwidth) and is main -performance bottleneck in `MDBX_MAPASYNC` mode. - > This is unavoidable, but isn't that bad. Syncing data to disk requires - > much more similar operations which will be done by OS, therefore this is - > noticeable only if data sync to persistent storage is fully disabled. - > _libmdbx_ allows to safely save data to persistent storage with minimal - > performance overhead. If there is no need to save data to persistent - > storage then it's much more preferable to use `std::map`. - -4. Massive altering of data during a parallel long read operation will -increase the process work set, may exhaust entire free database space and -result in subsequent write performance degradation. - > _libmdbx_ mostly solve this issue by lack-of-space callback and `MDBX_LIFORECLAIM` mode. - > See [`mdbx.h`](mdbx.h) with API description for details. - > The "next" version of libmdbx (MithrilDB) will completely solve this. - -5. There are no built-in checksums or digests to verify database integrity. - > The "next" version of _libmdbx_ (MithrilDB) will solve this issue employing [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree). - --------------------------------------------------------------------------------- - -Usage -===== - -## Source code embedding - -_libmdbx_ provides two official ways for integration in source code form: - -1. Using the amalgamated source code. - > The amalgamated source code includes all files requires to build and - > use _libmdbx_, but not for testing _libmdbx_ itself. - -2. Adding the complete original source code as a `git submodule`. - > This allows you to build as _libmdbx_ and testing tool. - > On the other hand, this way requires you to pull git tags, and use C++11 compiler for test tool. - -**_Please, avoid using any other techniques._** Otherwise, at least -don't ask for support and don't name such chimeras `libmdbx`. - -The amalgamated source code could be created from original clone of git -repository on Linux by executing `make dist`. As a result, the desired -set of files will be formed in the `dist` subdirectory. - -## Building - -Both amalgamated and original source code provides build through the use -[CMake](https://cmake.org/) or [GNU -Make](https://www.gnu.org/software/make/) with -[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)). All build ways -are completely traditional and have minimal prerequirements like -`build-essential`, i.e. the non-obsolete C/C++ compiler and a -[SDK](https://en.wikipedia.org/wiki/Software_development_kit) for the -target platform. Obviously you need building tools itself, i.e. `git`, -`cmake` or GNU `make` with `bash`. - -So just use CMake or GNU Make in your habitual manner and feel free to -fill an issue or make pull request in the case something will be -unexpected or broken down. - -#### DSO/DLL unloading and destructors of Thread-Local-Storage objects -When building _libmdbx_ as a shared library or use static _libmdbx_ as a -part of another dynamic library, it is advisable to make sure that your -system ensures the correctness of the call destructors of -Thread-Local-Storage objects when unloading dynamic libraries. - -If this is not the case, then unloading a dynamic-link library with -_libmdbx_ code inside, can result in either a resource leak or a crash -due to calling destructors from an already unloaded DSO/DLL object. The -problem can only manifest in a multithreaded application, which makes -the unloading of shared dynamic libraries with _libmdbx_ code inside, -after using _libmdbx_. It is known that TLS-destructors are properly -maintained in the following cases: - -- On all modern versions of Windows (Windows 7 and later). - -- On systems with the -[`__cxa_thread_atexit_impl()`](https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables) -function in the standard C library, including systems with GNU libc -version 2.18 and later. - -- On systems with libpthread/ntpl from GNU libc with bug fixes -[#21031](https://sourceware.org/bugzilla/show_bug.cgi?id=21031) and -[#21032](https://sourceware.org/bugzilla/show_bug.cgi?id=21032), or -where there are no similar bugs in the pthreads implementation. - -### Linux and other platforms with GNU Make -To build the library it is enough to execute `make all` in the directory -of source code, and `make check` for execute the basic tests. - -If the `make` installed on the system is not GNU Make, there will be a -lot of errors from make when trying to build. In this case, perhaps you -should use `gmake` instead of `make`, or even `gnu-make`, etc. - -### FreeBSD and related platforms -As a rule, in such systems, the default is to use Berkeley Make. And GNU -Make is called by the gmake command or may be missing. In addition, -[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) may be absent. - -You need to install the required components: GNU Make, bash, C and C++ -compilers compatible with GCC or CLANG. After that, to build the -library, it is enough execute `gmake all` (or `make all`) in the -directory with source code, and `gmake check` (or `make check`) to run -the basic tests. - -### Windows -For build _libmdbx_ on Windows the _original_ CMake and [Microsoft Visual -Studio](https://en.wikipedia.org/wiki/Microsoft_Visual_Studio) are -recommended. - -Building by MinGW, MSYS or Cygwin is potentially possible. However, -these scripts are not tested and will probably require you to modify the -CMakeLists.txt or Makefile respectively. - -It should be noted that in _libmdbx_ was efforts to resolve -runtime dependencies from CRT and other libraries Visual Studio. -For this is enough define the `MDBX_AVOID_CRT` during build. - -An example of running a basic test script can be found in the -[CI-script](appveyor.yml) for [AppVeyor](https://www.appveyor.com/). To -run the [long stochastic test scenario](test/long_stochastic.sh), -[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) is required, and -the such testing is recommended with place the test data on the -[RAM-disk](https://en.wikipedia.org/wiki/RAM_drive). - -### MacOS -Current [native build tools](https://en.wikipedia.org/wiki/Xcode) for -MacOS include GNU Make, CLANG and an outdated version of bash. -Therefore, to build the library, it is enough to run `make all` in the -directory with source code, and run `make check` to execute the base -tests. If something goes wrong, it is recommended to install -[Homebrew](https://brew.sh/) and try again. - -To run the [long stochastic test scenario](test/long_stochastic.sh), you -will need to install the current (not outdated) version of -[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)). To do this, we -recommend that you install [Homebrew](https://brew.sh/) and then execute -`brew install bash`. - -## Bindings - - | Runtime | GitHub | Author | - | -------- | ------ | ------ | - | Java | [mdbxjni](https://github.com/castortech/mdbxjni) | [Castor Technologies](https://castortech.com/) | - | .NET | [mdbx.NET](https://github.com/wangjia184/mdbx.NET) | [Jerry Wang](https://github.com/wangjia184) | - - --------------------------------------------------------------------------------- - -Performance comparison -====================== - -All benchmarks were done by [IOArena](https://github.com/pmwkaa/ioarena) -and multiple [scripts](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015) -runs on Lenovo Carbon-2 laptop, i7-4600U 2.1 GHz, 8 Gb RAM, -SSD SAMSUNG MZNTD512HAGL-000L1 (DXT23L0Q) 512 Gb. - -## Integral performance - -Here showed sum of performance metrics in 3 benchmarks: - - - Read/Search on 4 CPU cores machine; - - - Transactions with [CRUD](https://en.wikipedia.org/wiki/CRUD) - operations in sync-write mode (fdatasync is called after each - transaction); - - - Transactions with [CRUD](https://en.wikipedia.org/wiki/CRUD) - operations in lazy-write mode (moment to sync data to persistent storage - is decided by OS). - -*Reasons why asynchronous mode isn't benchmarked here:* - - 1. It doesn't make sense as it has to be done with DB engines, oriented - for keeping data in memory e.g. [Tarantool](https://tarantool.io/), - [Redis](https://redis.io/)), etc. - - 2. Performance gap is too high to compare in any meaningful way. - -![Comparison #1: Integral Performance](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-1.png) - --------------------------------------------------------------------------------- - -## Read Scalability - -Summary performance with concurrent read/search queries in 1-2-4-8 -threads on 4 CPU cores machine. - -![Comparison #2: Read Scalability](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-2.png) - --------------------------------------------------------------------------------- - -## Sync-write mode - - - Linear scale on left and dark rectangles mean arithmetic mean - transactions per second; - - - Logarithmic scale on right is in seconds and yellow intervals mean - execution time of transactions. Each interval shows minimal and maximum - execution time, cross marks standard deviation. - -**10,000 transactions in sync-write mode**. In case of a crash all data -is consistent and state is right after last successful transaction. -[fdatasync](https://linux.die.net/man/2/fdatasync) syscall is used after -each write transaction in this mode. - -In the benchmark each transaction contains combined CRUD operations (2 -inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database -and after full run the database contains 10,000 small key-value records. - -![Comparison #3: Sync-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-3.png) - --------------------------------------------------------------------------------- - -## Lazy-write mode - - - Linear scale on left and dark rectangles mean arithmetic mean of - thousands transactions per second; - - - Logarithmic scale on right in seconds and yellow intervals mean - execution time of transactions. Each interval shows minimal and maximum - execution time, cross marks standard deviation. - -**100,000 transactions in lazy-write mode**. In case of a crash all data -is consistent and state is right after one of last transactions, but -transactions after it will be lost. Other DB engines use -[WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) or transaction -journal for that, which in turn depends on order of operations in -journaled filesystem. _libmdbx_ doesn't use WAL and hands I/O operations -to filesystem and OS kernel (mmap). - -In the benchmark each transaction contains combined CRUD operations (2 -inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database -and after full run the database contains 100,000 small key-value -records. - - -![Comparison #4: Lazy-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-4.png) - --------------------------------------------------------------------------------- - -## Async-write mode - - - Linear scale on left and dark rectangles mean arithmetic mean of - thousands transactions per second; - - - Logarithmic scale on right in seconds and yellow intervals mean - execution time of transactions. Each interval shows minimal and maximum - execution time, cross marks standard deviation. - -**1,000,000 transactions in async-write mode**. In case of a crash all -data will be consistent and state will be right after one of last -transactions, but lost transaction count is much higher than in -lazy-write mode. All DB engines in this mode do as little writes as -possible on persistent storage. _libmdbx_ uses -[msync(MS_ASYNC)](https://linux.die.net/man/2/msync) in this mode. - -In the benchmark each transaction contains combined CRUD operations (2 -inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database -and after full run the database contains 10,000 small key-value records. - -![Comparison #5: Async-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-5.png) - --------------------------------------------------------------------------------- - -## Cost comparison - -Summary of used resources during lazy-write mode benchmarks: - - - Read and write IOPS; - - - Sum of user CPU time and sys CPU time; - - - Used space on persistent storage after the test and closed DB, but not - waiting for the end of all internal housekeeping operations (LSM - compactification, etc). - -_ForestDB_ is excluded because benchmark showed it's resource -consumption for each resource (CPU, IOPS) much higher than other engines -which prevents to meaningfully compare it with them. - -All benchmark data is gathered by -[getrusage()](http://man7.org/linux/man-pages/man2/getrusage.2.html) -syscall and by scanning data directory. - -![Comparison #6: Cost comparison](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-6.png) - --------------------------------------------------------------------------------- - -``` -$ objdump -f -h -j .text libmdbx.so - -libmdbx.so: file format elf64-x86-64 -architecture: i386:x86-64, flags 0x00000150: -HAS_SYMS, DYNAMIC, D_PAGED -start address 0x0000000000003710 - -Sections: -Idx Name Size VMA LMA File off Algn - 11 .text 00015eff 0000000000003710 0000000000003710 00003710 2**4 - CONTENTS, ALLOC, LOAD, READONLY, CODE -``` diff --git a/src/contrib/db/libmdbx/appveyor.yml b/src/contrib/db/libmdbx/appveyor.yml deleted file mode 100644 index be7ee76..0000000 --- a/src/contrib/db/libmdbx/appveyor.yml +++ /dev/null @@ -1,99 +0,0 @@ -version: 0.3.2.{build} - -environment: - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMAKE_GENERATOR: Visual Studio 16 2019 - TOOLSET: 142 - MDBX_BUILD_SHARED_LIBRARY: OFF - MDBX_AVOID_CRT: OFF - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMAKE_GENERATOR: Visual Studio 16 2019 - TOOLSET: 142 - MDBX_BUILD_SHARED_LIBRARY: ON - MDBX_AVOID_CRT: ON - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMAKE_GENERATOR: Visual Studio 16 2019 - TOOLSET: 142 - MDBX_BUILD_SHARED_LIBRARY: OFF - MDBX_AVOID_CRT: ON - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - CMAKE_GENERATOR: Visual Studio 16 2019 - TOOLSET: 142 - MDBX_BUILD_SHARED_LIBRARY: ON - MDBX_AVOID_CRT: OFF - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - CMAKE_GENERATOR: Visual Studio 15 2017 - TOOLSET: 141 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - CMAKE_GENERATOR: Visual Studio 14 2015 - TOOLSET: 140 - -branches: - except: - - coverity_scan - -configuration: -- Debug -- Release - -platform: -- Win32 -- x64 - -before_build: -- git clean -x -f -d -- git submodule sync -- git fetch --tags --prune -- git submodule update --init --recursive -- git submodule foreach --recursive git fetch --tags --prune -- cmake --version - -build_script: -- ps: | - Write-Output "*******************************************************************************" - Write-Output "Configuration: $env:CONFIGURATION" - Write-Output "Platform: $env:PLATFORM" - Write-Output "Toolchain: $env:CMAKE_GENERATOR v$env:TOOLSET" - Write-Output "Options: MDBX_AVOID_CRT=$env:MDBX_AVOID_CRT MDBX_BUILD_SHARED_LIBRARY=$env:MDBX_BUILD_SHARED_LIBRARY" - Write-Output "*******************************************************************************" - - md _build -Force | Out-Null - cd _build - - $generator = $env:CMAKE_GENERATOR - if ($env:TOOLSET -lt 142) { - if ($env:PLATFORM -eq "x64") { - $generator = "$generator Win64" - } - & cmake -G "$generator" -D CMAKE_CONFIGURATION_TYPES="Debug;Release" -D MDBX_AVOID_CRT:BOOL=$env:MDBX_AVOID_CRT -D MDBX_BUILD_SHARED_LIBRARY:BOOL=$env:MDBX_BUILD_SHARED_LIBRARY .. - } else { - & cmake -G "$generator" -A $env:PLATFORM -D CMAKE_CONFIGURATION_TYPES="Debug;Release" -DMDBX_AVOID_CRT:BOOL=$env:MDBX_AVOID_CRT -D MDBX_BUILD_SHARED_LIBRARY:BOOL=$env:MDBX_BUILD_SHARED_LIBRARY .. - } - if ($LastExitCode -ne 0) { - throw "Exec: $ErrorMessage" - } - Write-Output "*******************************************************************************" - - & cmake --build . --config $env:CONFIGURATION - if ($LastExitCode -ne 0) { - throw "Exec: $ErrorMessage" - } - Write-Output "*******************************************************************************" - -test_script: -- ps: | - if (($env:PLATFORM -ne "ARM") -and ($env:PLATFORM -ne "ARM64")) { - & ./$env:CONFIGURATION/mdbx_test.exe --progress --console=no --pathname=test.db --dont-cleanup-after basic > test.log - Get-Content test.log | Select-Object -last 42 - if ($LastExitCode -ne 0) { - throw "Exec: $ErrorMessage" - } else { - & ./$env:CONFIGURATION/mdbx_chk.exe -nvv test.db | Tee-Object -file chk.log | Select-Object -last 42 - } - } - -on_failure: -- ps: Push-AppveyorArtifact \projects\libmdbx\_build\test.log -- ps: Push-AppveyorArtifact \projects\libmdbx\_build\test.db -- ps: Push-AppveyorArtifact \projects\libmdbx\_build\chk.log diff --git a/src/contrib/db/libmdbx/cmake/compiler.cmake b/src/contrib/db/libmdbx/cmake/compiler.cmake deleted file mode 100644 index 03b0805..0000000 --- a/src/contrib/db/libmdbx/cmake/compiler.cmake +++ /dev/null @@ -1,666 +0,0 @@ -## Copyright (c) 2012-2019 Leonid Yuriev . -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## - -cmake_minimum_required(VERSION 3.8.2) -cmake_policy(PUSH) -cmake_policy(VERSION 3.8.2) - -if (CMAKE_VERSION MATCHES ".*MSVC.*") - message(FATAL_ERROR "CMake from MSVC kit is unfit! " - "Please use the original CMake from https://cmake.org/download/") -endif() - -if (NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED)) - message(FATAL_ERROR "This module required C or C++ to be enabled") -endif() - -include(CMakeDependentOption) - -if(CMAKE_CXX_COMPILER_LOADED) - include(CheckCXXSourceRuns) - include(CheckCXXSourceCompiles) - include(CheckCXXCompilerFlag) -endif() -if(CMAKE_C_COMPILER_LOADED) - include(CheckCSourceRuns) - include(CheckCSourceCompiles) - include(CheckCCompilerFlag) -endif() - -# Check if the same compile family is used for both C and CXX -if(CMAKE_C_COMPILER_LOADED AND CMAKE_CXX_COMPILER_LOADED AND - NOT (CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)) - message(WARNING "CMAKE_C_COMPILER_ID (${CMAKE_C_COMPILER_ID}) is different " - "from CMAKE_CXX_COMPILER_ID (${CMAKE_CXX_COMPILER_ID}). " - "The final binary may be unusable.") -endif() - -if(CMAKE_CXX_COMPILER_LOADED) - set(CMAKE_PRIMARY_LANG "CXX") -else() - set(CMAKE_PRIMARY_LANG "C") -endif() - -macro(check_compiler_flag flag variable) - if(CMAKE_CXX_COMPILER_LOADED) - check_cxx_compiler_flag(${flag} ${variable}) - else() - check_c_compiler_flag(${flag} ${variable}) - endif() -endmacro(check_compiler_flag) - -# We support building with Clang and gcc. First check -# what we're using for build. -if(CMAKE_C_COMPILER_LOADED AND CMAKE_C_COMPILER_ID STREQUAL "Clang") - set(CMAKE_COMPILER_IS_CLANG ON) - set(CMAKE_COMPILER_IS_GNUCC OFF) -endif() -if(CMAKE_CXX_COMPILER_LOADED AND CMAKE_CXx_COMPILER_ID STREQUAL "Clang") - set(CMAKE_COMPILER_IS_CLANG ON) - set(CMAKE_COMPILER_IS_GNUCXX OFF) -endif() - -# Hard coding the compiler version is ugly from cmake POV, but -# at least gives user a friendly error message. The most critical -# demand for C++ compiler is support of C++11 lambdas, added -# only in version 4.5 https://gcc.gnu.org/projects/cxx0x.html -if(CMAKE_COMPILER_IS_GNUCC) - if(CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) - message(FATAL_ERROR " - Your GCC version is ${CMAKE_C_COMPILER_VERSION}, please update") - endif() -endif() -if(CMAKE_COMPILER_IS_GNUCXX) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.5) - message(FATAL_ERROR " - Your G++ version is ${CMAKE_CXX_COMPILER_VERSION}, please update") - endif() -endif() - -if(CMAKE_C_COMPILER_LOADED) - # Check for Elbrus lcc - execute_process(COMMAND ${CMAKE_C_COMPILER} --version - OUTPUT_VARIABLE tmp_lcc_probe_version - RESULT_VARIABLE tmp_lcc_probe_result ERROR_QUIET) - if(tmp_lcc_probe_result EQUAL 0) - string(FIND "${tmp_lcc_probe_version}" "lcc:" tmp_lcc_marker) - string(FIND "${tmp_lcc_probe_version}" ":e2k-" tmp_e2k_marker) - if(tmp_lcc_marker GREATER -1 AND tmp_e2k_marker GREATER tmp_lcc_marker) - execute_process(COMMAND ${CMAKE_C_COMPILER} -print-version - OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION - RESULT_VARIABLE tmp_lcc_probe_result) - set(CMAKE_COMPILER_IS_ELBRUSC ON) - set(CMAKE_C_COMPILER_ID "Elbrus") - else() - set(CMAKE_COMPILER_IS_ELBRUSC OFF) - endif() - unset(tmp_lcc_marker) - unset(tmp_e2k_marker) - endif() - unset(tmp_lcc_probe_version) - unset(tmp_lcc_probe_result) -endif() - -if(CMAKE_CXX_COMPILER_LOADED) - # Check for Elbrus l++ - execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version - OUTPUT_VARIABLE tmp_lxx_probe_version - RESULT_VARIABLE tmp_lxx_probe_result ERROR_QUIET) - if(tmp_lxx_probe_result EQUAL 0) - string(FIND "${tmp_lxx_probe_version}" "lcc:" tmp_lcc_marker) - string(FIND "${tmp_lxx_probe_version}" ":e2k-" tmp_e2k_marker) - if(tmp_lcc_marker GREATER -1 AND tmp_e2k_marker GREATER tmp_lcc_marker) - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-version - OUTPUT_VARIABLE CMAKE_CXX_COMPILER_VERSION - RESULT_VARIABLE tmp_lxx_probe_result) - set(CMAKE_COMPILER_IS_ELBRUSCXX ON) - set(CMAKE_CXX_COMPILER_ID "Elbrus") - else() - set(CMAKE_COMPILER_IS_ELBRUSCXX OFF) - endif() - unset(tmp_lcc_marker) - unset(tmp_e2k_marker) - endif() - unset(tmp_lxx_probe_version) - unset(tmp_lxx_probe_result) -endif() - -if(CMAKE_CL_64) - set(MSVC64 1) -endif() -if(WIN32 AND CMAKE_COMPILER_IS_GNU${CMAKE_PRIMARY_LANG}) - execute_process(COMMAND ${CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER} -dumpmachine - OUTPUT_VARIABLE __GCC_TARGET_MACHINE - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(__GCC_TARGET_MACHINE MATCHES "amd64|x86_64|AMD64") - set(MINGW64 1) - endif() - unset(__GCC_TARGET_MACHINE) -endif() - -if(CMAKE_COMPILER_IS_ELBRUSC OR CMAKE_SYSTEM_PROCESSOR MATCHES "e2k.*|E2K.*|elbrus.*|ELBRUS.*") - set(E2K TRUE) - set(CMAKE_SYSTEM_ARCH "Elbrus") -elseif((MSVC64 OR MINGW64) AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(X86_64 TRUE) - set(CMAKE_SYSTEM_ARCH "x86_64") -elseif(MINGW OR (MSVC AND NOT CMAKE_CROSSCOMPILING)) - set(X86_32 TRUE) - set(CMAKE_SYSTEM_ARCH "x86") -elseif(CMAKE_COMPILER_IS_ELBRUSC OR CMAKE_SYSTEM_PROCESSOR MATCHES "e2k.*|E2K.*|elbrus.*|ELBRUS.*") - set(E2K TRUE) - set(CMAKE_SYSTEM_ARCH "Elbrus") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(X86_64 TRUE) - set(CMAKE_SYSTEM_ARCH "x86_64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*") - set(X86_32 TRUE) - set(CMAKE_SYSTEM_ARCH "x86") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|ARM64.*)" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(AARCH64 TRUE) - set(CMAKE_SYSTEM_ARCH "ARM64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)") - set(ARM32 TRUE) - set(CMAKE_SYSTEM_ARCH "ARM") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le.*" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PPC64LE TRUE) - set(CMAKE_SYSTEM_ARCH "PPC64LE") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64.*" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PPC64 TRUE) - set(CMAKE_SYSTEM_ARCH "PPC64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc).*") - set(PPC32 TRUE) - set(CMAKE_SYSTEM_ARCH "PPC") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips|MIPS)64.*" AND CMAKE_SIZEOF_VOID_P EQUAL 8) - set(MIPS64 TRUE) - set(CMAKE_SYSTEM_ARCH "MIPS64") -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(mips|MIPS).*") - set(MIPS32 TRUE) - set(CMAKE_SYSTEM_ARCH "MIPS") -endif() - -if(MSVC) - check_compiler_flag("/WX" CC_HAS_WERROR) -else() - # - # GCC started to warn for unused result starting from 4.2, and - # this is when it introduced -Wno-unused-result - # GCC can also be built on top of llvm runtime (on mac). - check_compiler_flag("-Wno-unknown-pragmas" CC_HAS_WNO_UNKNOWN_PRAGMAS) - check_compiler_flag("-Wextra" CC_HAS_WEXTRA) - check_compiler_flag("-Werror" CC_HAS_WERROR) - check_compiler_flag("-fexceptions" CC_HAS_FEXCEPTIONS) - check_cxx_compiler_flag("-fcxx-exceptions" CC_HAS_FCXX_EXCEPTIONS) - check_compiler_flag("-funwind-tables" CC_HAS_FUNWIND_TABLES) - check_compiler_flag("-fno-omit-frame-pointer" CC_HAS_FNO_OMIT_FRAME_POINTER) - check_compiler_flag("-fno-common" CC_HAS_FNO_COMMON) - check_compiler_flag("-ggdb" CC_HAS_GGDB) - check_compiler_flag("-fvisibility=hidden" CC_HAS_VISIBILITY) - check_compiler_flag("-march=native" CC_HAS_ARCH_NATIVE) - check_compiler_flag("-Og" CC_HAS_DEBUG_FRENDLY_OPTIMIZATION) - check_compiler_flag("-Wall" CC_HAS_WALL) - check_compiler_flag("-Ominimal" CC_HAS_OMINIMAL) - check_compiler_flag("-ffunction-sections -fdata-sections" CC_HAS_SECTIONS) - check_compiler_flag("-ffast-math" CC_HAS_FASTMATH) - - # Check for an omp support - set(CMAKE_REQUIRED_FLAGS "-fopenmp -Werror") - check_cxx_source_compiles("int main(void) { - #pragma omp parallel - return 0; - }" HAVE_OPENMP) - set(CMAKE_REQUIRED_FLAGS "") -endif() - -# Check for LTO support by GCC -if(CMAKE_COMPILER_IS_GNU${CMAKE_PRIMARY_LANG}) - unset(gcc_collect) - unset(gcc_lto_wrapper) - - if(NOT CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 4.7) - execute_process(COMMAND ${CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER} -v - OUTPUT_VARIABLE gcc_info_v ERROR_VARIABLE gcc_info_v) - - string(REGEX MATCH "^(.+\nCOLLECT_GCC=)([^ \n]+)(\n.+)$" gcc_collect_valid ${gcc_info_v}) - if(gcc_collect_valid) - string(REGEX REPLACE "^(.+\nCOLLECT_GCC=)([^ \n]+)(\n.+)$" "\\2" gcc_collect ${gcc_info_v}) - endif() - - string(REGEX MATCH "^(.+\nCOLLECT_LTO_WRAPPER=)([^ \n]+/lto-wrapper)(\n.+)$" gcc_lto_wrapper_valid ${gcc_info_v}) - if(gcc_lto_wrapper_valid) - string(REGEX REPLACE "^(.+\nCOLLECT_LTO_WRAPPER=)([^ \n]+/lto-wrapper)(\n.+)$" "\\2" gcc_lto_wrapper ${gcc_info_v}) - endif() - - set(gcc_suffix "") - if(gcc_collect_valid AND gcc_collect) - string(REGEX MATCH "^(.*cc)(-.+)$" gcc_suffix_valid ${gcc_collect}) - if(gcc_suffix_valid) - string(REGEX MATCH "^(.*cc)(-.+)$" "\\2" gcc_suffix ${gcc_collect}) - endif() - endif() - - get_filename_component(gcc_dir ${CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER} DIRECTORY) - if(NOT CMAKE_GCC_AR) - find_program(CMAKE_GCC_AR NAMES gcc${gcc_suffix}-ar gcc-ar${gcc_suffix} PATHS ${gcc_dir} NO_DEFAULT_PATH) - endif() - if(NOT CMAKE_GCC_NM) - find_program(CMAKE_GCC_NM NAMES gcc${gcc_suffix}-nm gcc-nm${gcc_suffix} PATHS ${gcc_dir} NO_DEFAULT_PATH) - endif() - if(NOT CMAKE_GCC_RANLIB) - find_program(CMAKE_GCC_RANLIB NAMES gcc${gcc_suffix}-ranlib gcc-ranlib${gcc_suffix} PATHS ${gcc_dir} NO_DEFAULT_PATH) - endif() - - unset(gcc_dir) - unset(gcc_suffix_valid) - unset(gcc_suffix) - unset(gcc_lto_wrapper_valid) - unset(gcc_collect_valid) - unset(gcc_collect) - unset(gcc_info_v) - endif() - - if(CMAKE_GCC_AR AND CMAKE_GCC_NM AND CMAKE_GCC_RANLIB AND gcc_lto_wrapper) - message(STATUS "Found GCC's LTO toolset: ${gcc_lto_wrapper}, ${CMAKE_GCC_AR}, ${CMAKE_GCC_RANLIB}") - set(GCC_LTO_CFLAGS "-flto -fno-fat-lto-objects -fuse-linker-plugin") - set(GCC_LTO_AVAILABLE TRUE) - message(STATUS "Link-Time Optimization by GCC is available") - else() - set(GCC_LTO_AVAILABLE FALSE) - message(STATUS "Link-Time Optimization by GCC is NOT available") - endif() - unset(gcc_lto_wrapper) -endif() - -# check for LTO by MSVC -if(MSVC) - if(NOT MSVC_VERSION LESS 1600) - set(MSVC_LTO_AVAILABLE TRUE) - message(STATUS "Link-Time Optimization by MSVC is available") - else() - set(MSVC_LTO_AVAILABLE FALSE) - message(STATUS "Link-Time Optimization by MSVC is NOT available") - endif() -endif() - -# Check for LTO support by CLANG -if(CMAKE_COMPILER_IS_CLANG) - if(NOT CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 3.5) - execute_process(COMMAND ${CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER} -print-search-dirs - OUTPUT_VARIABLE clang_search_dirs) - - unset(clang_bindir) - unset(clang_libdir) - string(REGEX MATCH "^(.*programs: =)([^:]*:)*([^:]+/llvm[-.0-9]+/bin[^:]*)(:[^:]*)*(\n.+)$" clang_bindir_valid ${clang_search_dirs}) - if(clang_bindir_valid) - string(REGEX REPLACE "^(.*programs: =)([^:]*:)*([^:]+/llvm[-.0-9]+/bin[^:]*)(:[^:]*)*(\n.+)$" "\\3" clang_bindir ${clang_search_dirs}) - get_filename_component(clang_libdir "${clang_bindir}/../lib" REALPATH) - if(clang_libdir) - message(STATUS "Found CLANG/LLVM directories: ${clang_bindir}, ${clang_libdir}") - endif() - endif() - - if(NOT (clang_bindir AND clang_libdir)) - message(STATUS "Could NOT find CLANG/LLVM directories (bin and/or lib).") - endif() - - if(NOT CMAKE_CLANG_LD AND clang_bindir) - find_program(CMAKE_CLANG_LD NAMES llvm-link link llvm-ld ld PATHS ${clang_bindir} NO_DEFAULT_PATH) - endif() - if(NOT CMAKE_CLANG_AR AND clang_bindir) - find_program(CMAKE_CLANG_AR NAMES llvm-ar ar PATHS ${clang_bindir} NO_DEFAULT_PATH) - endif() - if(NOT CMAKE_CLANG_NM AND clang_bindir) - find_program(CMAKE_CLANG_NM NAMES llvm-nm nm PATHS ${clang_bindir} NO_DEFAULT_PATH) - endif() - if(NOT CMAKE_CLANG_RANLIB AND clang_bindir) - find_program(CMAKE_CLANG_RANLIB NAMES llvm-ranlib ranlib PATHS ${clang_bindir} NO_DEFAULT_PATH) - endif() - - set(clang_lto_plugin_name "LLVMgold${CMAKE_SHARED_LIBRARY_SUFFIX}") - if(NOT CMAKE_LD_GOLD AND clang_bindir) - find_program(CMAKE_LD_GOLD NAMES ld.gold PATHS) - endif() - if(NOT CLANG_LTO_PLUGIN AND clang_libdir) - find_file(CLANG_LTO_PLUGIN ${clang_lto_plugin_name} PATH ${clang_libdir} NO_DEFAULT_PATH) - endif() - if(CLANG_LTO_PLUGIN) - message(STATUS "Found CLANG/LLVM's plugin for LTO: ${CLANG_LTO_PLUGIN}") - else() - message(STATUS "Could NOT find CLANG/LLVM's plugin (${clang_lto_plugin_name}) for LTO.") - endif() - - if(CMAKE_CLANG_LD AND CMAKE_CLANG_AR AND CMAKE_CLANG_NM AND CMAKE_CLANG_RANLIB) - message(STATUS "Found CLANG/LLVM's binutils for LTO: ${CMAKE_CLANG_AR}, ${CMAKE_CLANG_RANLIB}") - else() - message(STATUS "Could NOT find CLANG/LLVM's binutils (ar, ranlib, nm) for LTO.") - endif() - - unset(clang_lto_plugin_name) - unset(clang_libdir) - unset(clang_bindir_valid) - unset(clang_bindir) - unset(clang_search_dirs) - endif() - - if((CLANG_LTO_PLUGIN AND CMAKE_LD_GOLD) AND - (CMAKE_CLANG_LD AND CMAKE_CLANG_AR AND CMAKE_CLANG_NM AND CMAKE_CLANG_RANLIB)) - set(CLANG_LTO_AVAILABLE TRUE) - message(STATUS "Link-Time Optimization by CLANG/LLVM is available") - elseif(CMAKE_TOOLCHAIN_FILE AND NOT CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 7.0) - set(CLANG_LTO_AVAILABLE TRUE) - if (NOT CMAKE_CLANG_AR) - set(CMAKE_CLANG_AR ${CMAKE_AR}) - endif() - if (NOT CMAKE_CLANG_NM) - set(CMAKE_CLANG_NM ${CMAKE_NM}) - endif() - if (NOT CMAKE_CLANG_RANLIB) - set(CMAKE_CLANG_RANLIB ${CMAKE_RANLIB }) - endif() - message(STATUS "Assume Link-Time Optimization by CLANG/LLVM is available via ${CMAKE_TOOLCHAIN_FILE}") - else() - set(CLANG_LTO_AVAILABLE FALSE) - message(STATUS "Link-Time Optimization by CLANG/LLVM is NOT available") - endif() -endif() - -# Perform build type specific configuration. -option(ENABLE_BACKTRACE "Enable output of fiber backtrace information in 'show - fiber' administrative command. Only works on x86 architectures, if compiled - with gcc. If GNU binutils and binutils-dev libraries are installed, backtrace - is output with resolved function (symbol) names. Otherwise only frame - addresses are printed." OFF) - -set(HAVE_BFD False) -if(ENABLE_BACKTRACE) - if(NOT (X86_32 OR X86_64) OR NOT CMAKE_COMPILER_IS_GNU${CMAKE_PRIMARY_LANG}) - # We only know this option to work with gcc - message(FATAL_ERROR "ENABLE_BACKTRACE option is set but the system - is not x86 based (${CMAKE_SYSTEM_PROCESSOR}) or the compiler - is not GNU GCC (${CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER}).") - endif() - # Use GNU bfd if present. - find_library(BFD_LIBRARY NAMES libbfd.a) - if(BFD_LIBRARY) - check_library_exists(${BFD_LIBRARY} bfd_init "" HAVE_BFD_LIB) - endif() - find_library(IBERTY_LIBRARY NAMES libiberty.a) - if(IBERTY_LIBRARY) - check_library_exists(${IBERTY_LIBRARY} cplus_demangle "" HAVE_IBERTY_LIB) - endif() - set(CMAKE_REQUIRED_DEFINITIONS -DPACKAGE=${PACKAGE} -DPACKAGE_VERSION=${PACKAGE_VERSION}) - check_include_files(bfd.h HAVE_BFD_H) - set(CMAKE_REQUIRED_DEFINITIONS) - find_package(ZLIB) - if(HAVE_BFD_LIB AND HAVE_BFD_H AND HAVE_IBERTY_LIB AND ZLIB_FOUND) - set(HAVE_BFD ON) - set(BFD_LIBRARIES ${BFD_LIBRARY} ${IBERTY_LIBRARY} ${ZLIB_LIBRARIES}) - find_package_message(BFD_LIBRARIES "Found libbfd and dependencies" - ${BFD_LIBRARIES}) - if(TARGET_OS_FREEBSD AND NOT TARGET_OS_DEBIAN_FREEBSD) - set(BFD_LIBRARIES ${BFD_LIBRARIES} iconv) - endif() - endif() -endif() - -macro(setup_compile_flags) - # LY: save initial C/CXX flags - if(NOT INITIAL_CMAKE_FLAGS_SAVED) - if(MSVC) - string(REGEX REPLACE "^(.*)(/EHsc)( *)(.*)$" "\\1/EHs\\3\\4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - endif() - set(INITIAL_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_C_FLAGS ${CMAKE_C_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_STATIC_LINKER_FLAGS ${CMAKE_STATIC_LINKER_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS} CACHE STRING "Initial CMake's flags" FORCE) - set(INITIAL_CMAKE_FLAGS_SAVED TRUE CACHE INTERNAL "State of initial CMake's flags" FORCE) - endif() - - # LY: reset C/CXX flags - set(CXX_FLAGS ${INITIAL_CMAKE_CXX_FLAGS}) - set(C_FLAGS ${INITIAL_CMAKE_C_FLAGS}) - set(EXE_LINKER_FLAGS ${INITIAL_CMAKE_EXE_LINKER_FLAGS}) - set(SHARED_LINKER_FLAGS ${INITIAL_CMAKE_SHARED_LINKER_FLAGS}) - set(STATIC_LINKER_FLAGS ${INITIAL_CMAKE_STATIC_LINKER_FLAGS}) - set(MODULE_LINKER_FLAGS ${INITIAL_CMAKE_MODULE_LINKER_FLAGS}) - - if(CC_HAS_FEXCEPTIONS) - add_compile_flags("C;CXX" "-fexceptions") - endif() - if(CC_HAS_FCXX_EXCEPTIONS) - add_compile_flags("CXX" "-fcxx-exceptions -frtti") - endif() - - # In C a global variable without a storage specifier (static/extern) and - # without an initialiser is called a ’tentative definition’. The - # language permits multiple tentative definitions in the single - # translation unit; i.e. int foo; int foo; is perfectly ok. GNU - # toolchain goes even further, allowing multiple tentative definitions - # in *different* translation units. Internally, variables introduced via - # tentative definitions are implemented as ‘common’ symbols. Linker - # permits multiple definitions if they are common symbols, and it picks - # one arbitrarily for inclusion in the binary being linked. - # - # -fno-common forces GNU toolchain to behave in a more - # standard-conformant way in respect to tentative definitions and it - # prevents common symbols generation. Since we are a cross-platform - # project it really makes sense. There are toolchains that don’t - # implement GNU style handling of the tentative definitions and there - # are platforms lacking proper support for common symbols (osx). - if(CC_HAS_FNO_COMMON) - add_compile_flags("C;CXX" "-fno-common") - endif() - - if(CC_HAS_GGDB) - add_compile_flags("C;CXX" "-ggdb") - endif() - - if(CC_HAS_WNO_UNKNOWN_PRAGMAS AND NOT HAVE_OPENMP) - add_compile_flags("C;CXX" -Wno-unknown-pragmas) - endif() - - if(CC_HAS_SECTIONS) - add_compile_flags("C;CXX" -ffunction-sections -fdata-sections) - elseif(MSVC) - add_compile_flags("C;CXX" /Gy) - endif() - - # We must set -fno-omit-frame-pointer here, since we rely - # on frame pointer when getting a backtrace, and it must - # be used consistently across all object files. - # The same reasoning applies to -fno-stack-protector switch. - if(ENABLE_BACKTRACE) - if(CC_HAS_FNO_OMIT_FRAME_POINTER) - add_compile_flags("C;CXX" "-fno-omit-frame-pointer") - endif() - endif() - - if(MSVC) - if (MSVC_VERSION LESS 1900) - message(FATAL_ERROR "At least \"Microsoft C/C++ Compiler\" version 19.0.24234.1 (Visual Studio 2015 Update 3) is required.") - endif() - add_compile_flags("CXX" "/Zc:__cplusplus") - add_compile_flags("C;CXX" "/W4") - add_compile_flags("C;CXX" "/utf-8") - else() - if(CC_HAS_WALL) - add_compile_flags("C;CXX" "-Wall") - endif() - if(CC_HAS_WEXTRA) - add_compile_flags("C;CXX" "-Wextra") - endif() - endif() - - if(CMAKE_COMPILER_IS_GNU${CMAKE_PRIMARY_LANG} - AND CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 5) - # G++ bug. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488 - add_compile_flags("CXX" "-Wno-invalid-offsetof") - endif() - - add_definitions("-D__STDC_FORMAT_MACROS=1") - add_definitions("-D__STDC_LIMIT_MACROS=1") - add_definitions("-D__STDC_CONSTANT_MACROS=1") - add_definitions("-D_HAS_EXCEPTIONS=1") - - # Only add -Werror if it's a debug build, done by developers. - # Release builds should not cause extra trouble. - if(CC_HAS_WERROR AND (CI OR CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE STREQUAL "Debug")) - if(MSVC) - add_compile_flags("C;CXX" "/WX") - elseif(CMAKE_COMPILER_IS_CLANG) - if (NOT CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 6) - add_compile_flags("C;CXX" "-Werror") - endif() - elseif(CMAKE_COMPILER_IS_GNUCC) - if (NOT CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 6) - add_compile_flags("C;CXX" "-Werror") - endif() - else() - add_compile_flags("C;CXX" "-Werror") - endif() - endif() - - if(HAVE_OPENMP) - add_compile_flags("C;CXX" "-fopenmp") - endif() - - if (ENABLE_ASAN) - add_compile_flags("C;CXX" -fsanitize=address) - endif() - - if(ENABLE_GCOV) - if(NOT HAVE_GCOV) - message(FATAL_ERROR - "ENABLE_GCOV option requested but gcov library is not found") - endif() - - add_compile_flags("C;CXX" "-fprofile-arcs" "-ftest-coverage") - set(EXE_LINKER_FLAGS "${EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") - set(SHARED_LINKER_FLAGS "${SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") - set(MODULE_LINKER_FLAGS "${MODULE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") - # add_library(gcov SHARED IMPORTED) - endif() - - if(ENABLE_GPROF) - add_compile_flags("C;CXX" "-pg") - endif() - - if(CMAKE_COMPILER_IS_GNUCC AND LTO_ENABLED) - add_compile_flags("C;CXX" ${GCC_LTO_CFLAGS}) - set(EXE_LINKER_FLAGS "${EXE_LINKER_FLAGS} ${GCC_LTO_CFLAGS} -fverbose-asm -fwhole-program") - set(SHARED_LINKER_FLAGS "${SHARED_LINKER_FLAGS} ${GCC_LTO_CFLAGS} -fverbose-asm") - set(MODULE_LINKER_FLAGS "${MODULE_LINKER_FLAGS} ${GCC_LTO_CFLAGS} -fverbose-asm") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5) - # Pass the same optimization flags to the linker - set(compile_flags "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPERCASE}}") - set(EXE_LINKER_FLAGS "${EXE_LINKER_FLAGS} ${compile_flags}") - set(SHARED_LINKER_FLAGS "${SHARED_LINKER_FLAGS} ${compile_flags}") - set(MODULE_LINKER_FLAGS "${MODULE_LINKER_FLAGS} ${compile_flags}") - unset(compile_flags) - else() - add_compile_flags("CXX" "-flto-odr-type-merging") - endif() - endif() - - if(MSVC AND LTO_ENABLED) - add_compile_flags("C;CXX" "/GL") - foreach(linkmode IN ITEMS EXE SHARED STATIC MODULE) - set(${linkmode}_LINKER_FLAGS "${${linkmode}_LINKER_FLAGS} /LTCG") - string(REGEX REPLACE "^(.*)(/INCREMENTAL:NO *)(.*)$" "\\1\\3" ${linkmode}_LINKER_FLAGS "${${linkmode}_LINKER_FLAGS}") - string(REGEX REPLACE "^(.*)(/INCREMENTAL:YES *)(.*)$" "\\1\\3" ${linkmode}_LINKER_FLAGS "${${linkmode}_LINKER_FLAGS}") - string(REGEX REPLACE "^(.*)(/INCREMENTAL *)(.*)$" "\\1\\3" ${linkmode}_LINKER_FLAGS "${${linkmode}_LINKER_FLAGS}") - string(STRIP "${${linkmode}_LINKER_FLAGS}" ${linkmode}_LINKER_FLAGS) - foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES ITEMS Release MinSizeRel RelWithDebInfo Debug) - string(TOUPPER "${config}" config_uppercase) - if(DEFINED "CMAKE_${linkmode}_LINKER_FLAGS_${config_uppercase}") - string(REGEX REPLACE "^(.*)(/INCREMENTAL:NO *)(.*)$" "\\1\\3" altered_flags "${CMAKE_${linkmode}_LINKER_FLAGS_${config_uppercase}}") - string(REGEX REPLACE "^(.*)(/INCREMENTAL:YES *)(.*)$" "\\1\\3" altered_flags "${altered_flags}") - string(REGEX REPLACE "^(.*)(/INCREMENTAL *)(.*)$" "\\1\\3" altered_flags "${altered_flags}") - string(STRIP "${altered_flags}" altered_flags) - if(NOT "${altered_flags}" STREQUAL "${CMAKE_${linkmode}_LINKER_FLAGS_${config_uppercase}}") - set(CMAKE_${linkmode}_LINKER_FLAGS_${config_uppercase} "${altered_flags}" CACHE STRING "Altered: '/INCREMENTAL' removed for LTO" FORCE) - endif() - endif() - endforeach(config) - endforeach(linkmode) - unset(linkmode) - - foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES ITEMS Release MinSizeRel RelWithDebInfo) - foreach(lang IN ITEMS C CXX) - string(TOUPPER "${config}" config_uppercase) - if(DEFINED "CMAKE_${lang}_FLAGS_${config_uppercase}") - string(REPLACE "/O2" "/Ox" altered_flags "${CMAKE_${lang}_FLAGS_${config_uppercase}}") - if(NOT "${altered_flags}" STREQUAL "${CMAKE_${lang}_FLAGS_${config_uppercase}}") - set(CMAKE_${lang}_FLAGS_${config_uppercase} "${altered_flags}" CACHE STRING "Altered: '/O2' replaced by '/Ox' for LTO" FORCE) - endif() - endif() - unset(config_uppercase) - endforeach(lang) - endforeach(config) - unset(altered_flags) - unset(lang) - unset(config) - endif() - - if(CMAKE_COMPILER_IS_CLANG AND OSX_ARCHITECTURES) - set(EXE_LINKER_FLAGS "${EXE_LINKER_FLAGS} -Wl,-keep_dwarf_unwind") - set(SHARED_LINKER_FLAGS "${SHARED_LINKER_FLAGS} -Wl,-keep_dwarf_unwind") - set(MODULE_LINKER_FLAGS "${MODULE_LINKER_FLAGS} -Wl,-keep_dwarf_unwind") - endif() - - if(CMAKE_COMPILER_IS_CLANG AND LTO_ENABLED) - if(CMAKE_${CMAKE_PRIMARY_LANG}_COMPILER_VERSION VERSION_LESS 3.9) - set(CLANG_LTO_FLAG "-flto") - else() - set(CLANG_LTO_FLAG "-flto=thin") - endif() - add_compile_flags("C;CXX" ${CLANG_LTO_FLAG}) - set(EXE_LINKER_FLAGS "${EXE_LINKER_FLAGS} ${CLANG_LTO_FLAG} -fverbose-asm -fwhole-program") - set(SHARED_LINKER_FLAGS "${SHARED_LINKER_FLAGS} ${CLANG_LTO_FLAG} -fverbose-asm") - set(MODULE_LINKER_FLAGS "${MODULE_LINKER_FLAGS} ${CLANG_LTO_FLAG} -fverbose-asm") - endif() - - # LY: push C/CXX flags into the cache - set(CMAKE_CXX_FLAGS ${CXX_FLAGS} CACHE STRING "Flags used by the C++ compiler during all build types" FORCE) - set(CMAKE_C_FLAGS ${C_FLAGS} CACHE STRING "Flags used by the C compiler during all build types" FORCE) - set(CMAKE_EXE_LINKER_FLAGS ${EXE_LINKER_FLAGS} CACHE STRING "Flags used by the linker" FORCE) - set(CMAKE_SHARED_LINKER_FLAGS ${SHARED_LINKER_FLAGS} CACHE STRING "Flags used by the linker during the creation of dll's" FORCE) - set(CMAKE_STATIC_LINKER_FLAGS ${STATIC_LINKER_FLAGS} CACHE STRING "Flags used by the linker during the creation of static libraries" FORCE) - set(CMAKE_MODULE_LINKER_FLAGS ${MODULE_LINKER_FLAGS} CACHE STRING "Flags used by the linker during the creation of modules" FORCE) - unset(CXX_FLAGS) - unset(C_FLAGS) - unset(EXE_LINKER_FLAGS) - unset(SHARED_LINKER_FLAGS) - unset(STATIC_LINKER_FLAGS) - unset(MODULE_LINKER_FLAGS) -endmacro(setup_compile_flags) - -# determine library for for std::filesystem -set(LIBCXX_FILESYSTEM "") -if(CMAKE_COMPILER_IS_GNUCXX) - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) - set(LIBCXX_FILESYSTEM "stdc++fs") - endif() -elseif (CMAKE_COMPILER_IS_CLANG) - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) - set(LIBCXX_FILESYSTEM "c++experimental") - else() - set(LIBCXX_FILESYSTEM "stdc++fs") - endif() -endif() - -cmake_policy(POP) diff --git a/src/contrib/db/libmdbx/cmake/profile.cmake b/src/contrib/db/libmdbx/cmake/profile.cmake deleted file mode 100644 index 6507e8d..0000000 --- a/src/contrib/db/libmdbx/cmake/profile.cmake +++ /dev/null @@ -1,45 +0,0 @@ -## Copyright (c) 2012-2019 Leonid Yuriev . -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## - -cmake_minimum_required(VERSION 3.8.2) -cmake_policy(PUSH) -cmake_policy(VERSION 3.8.2) - -include(CheckLibraryExists) -check_library_exists(gcov __gcov_flush "" HAVE_GCOV) - -option(ENABLE_GCOV - "Enable integration with gcov, a code coverage program" OFF) - -option(ENABLE_GPROF - "Enable integration with gprof, a performance analyzing tool" OFF) - -if(CMAKE_CXX_COMPILER_LOADED) - include(CheckIncludeFileCXX) - check_include_file_cxx(valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) -else() - include(CheckIncludeFile) - check_include_file(valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) -endif() - -option(MDBX_USE_VALGRIND "Enable integration with valgrind, a memory analyzing tool" OFF) -if(MDBX_USE_VALGRIND AND NOT HAVE_VALGRIND_MEMCHECK_H) - message(FATAL_ERROR "MDBX_USE_VALGRIND option is set but valgrind/memcheck.h is not found") -endif() - -option(ENABLE_ASAN - "Enable AddressSanitizer, a fast memory error detector based on compiler instrumentation" OFF) - -cmake_policy(POP) diff --git a/src/contrib/db/libmdbx/cmake/utils.cmake b/src/contrib/db/libmdbx/cmake/utils.cmake deleted file mode 100644 index c31f53c..0000000 --- a/src/contrib/db/libmdbx/cmake/utils.cmake +++ /dev/null @@ -1,183 +0,0 @@ -## Copyright (c) 2012-2019 Leonid Yuriev . -## -## Licensed under the Apache License, Version 2.0 (the "License"); -## you may not use this file except in compliance with the License. -## You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## - -cmake_minimum_required(VERSION 3.8.2) -cmake_policy(PUSH) -cmake_policy(VERSION 3.8.2) - -macro(add_compile_flags langs) - foreach(_lang ${langs}) - string(REPLACE ";" " " _flags "${ARGN}") - if(CMAKE_CXX_COMPILER_LOADED AND _lang STREQUAL "CXX") - set("${_lang}_FLAGS" "${${_lang}_FLAGS} ${_flags}") - endif() - if(CMAKE_C_COMPILER_LOADED AND _lang STREQUAL "C") - set("${_lang}_FLAGS" "${${_lang}_FLAGS} ${_flags}") - endif() - endforeach() - unset(_lang) - unset(_flags) -endmacro(add_compile_flags) - -macro(set_source_files_compile_flags) - foreach(file ${ARGN}) - get_filename_component(_file_ext ${file} EXT) - set(_lang "") - if("${_file_ext}" STREQUAL ".m") - set(_lang OBJC) - # CMake believes that Objective C is a flavor of C++, not C, - # and uses g++ compiler for .m files. - # LANGUAGE property forces CMake to use CC for ${file} - set_source_files_properties(${file} PROPERTIES LANGUAGE C) - elseif("${_file_ext}" STREQUAL ".mm") - set(_lang OBJCXX) - endif() - - if(_lang) - get_source_file_property(_flags ${file} COMPILE_FLAGS) - if("${_flags}" STREQUAL "NOTFOUND") - set(_flags "${CMAKE_${_lang}_FLAGS}") - else() - set(_flags "${_flags} ${CMAKE_${_lang}_FLAGS}") - endif() - # message(STATUS "Set (${file} ${_flags}") - set_source_files_properties(${file} PROPERTIES COMPILE_FLAGS - "${_flags}") - endif() - endforeach() - unset(_file_ext) - unset(_lang) -endmacro(set_source_files_compile_flags) - -macro(fetch_version name version_file) - set(${name}_VERSION "") - set(${name}_GIT_DESCRIBE "") - set(${name}_GIT_TIMESTAMP "") - set(${name}_GIT_TREE "") - set(${name}_GIT_COMMIT "") - set(${name}_GIT_REVISION 0) - set(${name}_GIT_VERSION "") - if(GIT) - execute_process(COMMAND ${GIT} describe --tags --long --dirty=-dirty - OUTPUT_VARIABLE ${name}_GIT_DESCRIBE - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_DESCRIBE" STREQUAL "") - message(FATAL_ERROR "Please fetch tags and/or install latest version of git ('describe --tags --long --dirty' failed)") - endif() - - execute_process(COMMAND ${GIT} show --no-patch --format=%cI HEAD - OUTPUT_VARIABLE ${name}_GIT_TIMESTAMP - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TIMESTAMP" STREQUAL "%cI") - execute_process(COMMAND ${GIT} show --no-patch --format=%ci HEAD - OUTPUT_VARIABLE ${name}_GIT_TIMESTAMP - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TIMESTAMP" STREQUAL "%ci") - message(FATAL_ERROR "Please install latest version of git ('show --no-patch --format=%cI HEAD' failed)") - endif() - endif() - - execute_process(COMMAND ${GIT} show --no-patch --format=%T HEAD - OUTPUT_VARIABLE ${name}_GIT_TREE - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_TREE" STREQUAL "") - message(FATAL_ERROR "Please install latest version of git ('show --no-patch --format=%T HEAD' failed)") - endif() - - execute_process(COMMAND ${GIT} show --no-patch --format=%H HEAD - OUTPUT_VARIABLE ${name}_GIT_COMMIT - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_COMMIT" STREQUAL "") - message(FATAL_ERROR "Please install latest version of git ('show --no-patch --format=%H HEAD' failed)") - endif() - - execute_process(COMMAND ${GIT} rev-list --count --no-merges HEAD - OUTPUT_VARIABLE ${name}_GIT_REVISION - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE rc) - if(rc OR "${name}_GIT_REVISION" STREQUAL "") - message(FATAL_ERROR "Please install latest version of git ('rev-list --count --no-merges HEAD' failed)") - endif() - - string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" git_version_valid "${${name}_GIT_DESCRIBE}") - if(git_version_valid) - string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;\\4" ${name}_GIT_VERSION ${${name}_GIT_DESCRIBE}) - else() - string(REGEX MATCH "^(v)?([0-9]+)\\.([0-9]+)(.*)?" git_version_valid "${${name}_GIT_DESCRIBE}") - if(git_version_valid) - string(REGEX REPLACE "^(v)?([0-9]+)\\.([0-9]+)(.*)?" "\\2;\\3;0" ${name}_GIT_VERSION ${${name}_GIT_DESCRIBE}) - else() - message(AUTHOR_WARNING "Bad ${name} version \"${${name}_GIT_DESCRIBE}\"; falling back to 0.0.0 (have you made an initial release?)") - set(${name}_GIT_VERSION "0;0;0") - endif() - endif() - endif() - - if(NOT ${name}_GIT_VERSION OR NOT ${name}_GIT_TIMESTAMP OR NOT ${name}_GIT_REVISION) - message(WARNING "Unable to retrive ${name} version from git.") - set(${name}_GIT_VERSION "0;0;0;0") - set(${name}_GIT_TIMESTAMP "") - set(${name}_GIT_REVISION 0) - - # Try to get version from VERSION file - if(EXISTS "${version_file}") - file(STRINGS "${version_file}" ${name}_VERSION) - endif() - - if(NOT ${name}_VERSION) - message(WARNING "Unable to retrive ${name} version from \"${version_file}\" file.") - set(${name}_VERSION_LIST ${${name}_GIT_VERSION}) - string(REPLACE ";" "." ${name}_VERSION "${${name}_GIT_VERSION}") - else() - string(REPLACE "." ";" ${name}_VERSION_LIST ${${name}_VERSION}) - endif() - - else() - list(APPEND ${name}_GIT_VERSION ${${name}_GIT_REVISION}) - set(${name}_VERSION_LIST ${${name}_GIT_VERSION}) - string(REPLACE ";" "." ${name}_VERSION "${${name}_GIT_VERSION}") - endif() - - list(GET ${name}_VERSION_LIST 0 "${name}_VERSION_MAJOR") - list(GET ${name}_VERSION_LIST 1 "${name}_VERSION_MINOR") - list(GET ${name}_VERSION_LIST 2 "${name}_VERSION_RELEASE") - list(GET ${name}_VERSION_LIST 3 "${name}_VERSION_REVISION") - - set(${name}_VERSION_MAJOR ${${name}_VERSION_MAJOR} PARENT_SCOPE) - set(${name}_VERSION_MINOR ${${name}_VERSION_MINOR} PARENT_SCOPE) - set(${name}_VERSION_RELEASE ${${name}_VERSION_RELEASE} PARENT_SCOPE) - set(${name}_VERSION_REVISION ${${name}_VERSION_REVISION} PARENT_SCOPE) - set(${name}_VERSION ${${name}_VERSION} PARENT_SCOPE) - - set(${name}_GIT_DESCRIBE ${${name}_GIT_DESCRIBE} PARENT_SCOPE) - set(${name}_GIT_TIMESTAMP ${${name}_GIT_TIMESTAMP} PARENT_SCOPE) - set(${name}_GIT_TREE ${${name}_GIT_TREE} PARENT_SCOPE) - set(${name}_GIT_COMMIT ${${name}_GIT_COMMIT} PARENT_SCOPE) - set(${name}_GIT_REVISION ${${name}_GIT_REVISION} PARENT_SCOPE) - set(${name}_GIT_VERSION ${${name}_GIT_VERSION} PARENT_SCOPE) -endmacro(fetch_version) - -cmake_policy(POP) diff --git a/src/contrib/db/libmdbx/example/CMakeLists.txt b/src/contrib/db/libmdbx/example/CMakeLists.txt deleted file mode 100644 index d3e56e8..0000000 --- a/src/contrib/db/libmdbx/example/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(TARGET mdbx_example) -project(${TARGET}) - -add_executable(${TARGET} example-mdbx.c) - -target_link_libraries(${TARGET} mdbx) diff --git a/src/contrib/db/libmdbx/example/README.md b/src/contrib/db/libmdbx/example/README.md deleted file mode 100644 index b819cf4..0000000 --- a/src/contrib/db/libmdbx/example/README.md +++ /dev/null @@ -1 +0,0 @@ -See [example-mdbx.c](example-mdbx.c) as an example of using _libmdbx_, and do a line-by-line comparison of it with the [sample-bdb.txt](sample-bdb.txt) file. diff --git a/src/contrib/db/libmdbx/example/example-mdbx.c b/src/contrib/db/libmdbx/example/example-mdbx.c deleted file mode 100644 index 1d25ef6..0000000 --- a/src/contrib/db/libmdbx/example/example-mdbx.c +++ /dev/null @@ -1,112 +0,0 @@ -/* MDBX usage examle - * - * Do a line-by-line comparison of this and sample-bdb.txt - */ - -/* - * Copyright 2015-2019 Leonid Yuriev . - * Copyright 2017 Ilya Shipitsin . - * Copyright 2012-2015 Howard Chu, Symas Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "mdbx.h" -#include -#include - -int main(int argc, char *argv[]) { - (void)argc; - (void)argv; - - int rc; - MDBX_env *env = NULL; - MDBX_dbi dbi = 0; - MDBX_val key, data; - MDBX_txn *txn = NULL; - MDBX_cursor *cursor = NULL; - char sval[32]; - - rc = mdbx_env_create(&env); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_env_create: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - rc = mdbx_env_open(env, "./example-db", - MDBX_NOSUBDIR | MDBX_COALESCE | MDBX_LIFORECLAIM, 0664); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_env_open: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - rc = mdbx_txn_begin(env, NULL, 0, &txn); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_txn_begin: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - rc = mdbx_dbi_open(txn, NULL, 0, &dbi); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_dbi_open: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - key.iov_len = sizeof(int); - key.iov_base = sval; - data.iov_len = sizeof(sval); - data.iov_base = sval; - - sprintf(sval, "%03x %d foo bar", 32, 3141592); - rc = mdbx_put(txn, dbi, &key, &data, 0); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_put: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - rc = mdbx_txn_commit(txn); - if (rc) { - fprintf(stderr, "mdbx_txn_commit: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - txn = NULL; - - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_txn_begin: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - rc = mdbx_cursor_open(txn, dbi, &cursor); - if (rc != MDBX_SUCCESS) { - fprintf(stderr, "mdbx_cursor_open: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - int found = 0; - while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == 0) { - printf("key: %p %.*s, data: %p %.*s\n", key.iov_base, (int)key.iov_len, - (char *)key.iov_base, data.iov_base, (int)data.iov_len, - (char *)data.iov_base); - found += 1; - } - if (rc != MDBX_NOTFOUND || found == 0) { - fprintf(stderr, "mdbx_cursor_get: (%d) %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } else { - rc = MDBX_SUCCESS; - } -bailout: - if (cursor) - mdbx_cursor_close(cursor); - if (txn) - mdbx_txn_abort(txn); - if (dbi) - mdbx_dbi_close(env, dbi); - if (env) - mdbx_env_close(env); - return (rc != MDBX_SUCCESS) ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/example/sample-bdb.txt b/src/contrib/db/libmdbx/example/sample-bdb.txt deleted file mode 100644 index 5c89540..0000000 --- a/src/contrib/db/libmdbx/example/sample-bdb.txt +++ /dev/null @@ -1,77 +0,0 @@ -/* BerkeleyDB toy/sample - * - * Do a line-by-line comparison of this and example-mdbx.c - */ - -/* - * Copyright 2015-2019 Leonid Yuriev . - * Copyright 2012-2015 Howard Chu, Symas Corp. - * Copyright 2015,2016 Peter-Service R&D LLC. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include -#include -#include - -int main(int argc,char * argv[]) -{ - int rc; - DB_ENV *env; - DB *dbi; - DBT key, data; - DB_TXN *txn; - DBC *cursor; - char sval[32], kval[32]; - - /* Note: Most error checking omitted for simplicity */ - -#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD) - rc = db_env_create(&env, 0); - rc = env->open(env, "./testdb", FLAGS, 0664); - rc = db_create(&dbi, env, 0); - rc = env->txn_begin(env, NULL, &txn, 0); - rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664); - - memset(&key, 0, sizeof(DBT)); - memset(&data, 0, sizeof(DBT)); - key.size = sizeof(int); - key.data = sval; - data.size = sizeof(sval); - data.data = sval; - - sprintf(sval, "%03x %d foo bar", 32, 3141592); - rc = dbi->put(dbi, txn, &key, &data, 0); - rc = txn->commit(txn, 0); - if (rc) { - fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc)); - goto leave; - } - rc = env->txn_begin(env, NULL, &txn, 0); - rc = dbi->cursor(dbi, txn, &cursor, 0); - key.flags = DB_DBT_USERMEM; - key.data = kval; - key.ulen = sizeof(kval); - data.flags = DB_DBT_USERMEM; - data.data = sval; - data.ulen = sizeof(sval); - while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) { - printf("key: %p %.*s, data: %p %.*s\n", - key.data, (int) key.size, (char *) key.data, - data.data, (int) data.size, (char *) data.data); - } - rc = cursor->c_close(cursor); - rc = txn->abort(txn); -leave: - rc = dbi->close(dbi, 0); - rc = env->close(env, 0); - return rc; -} diff --git a/src/contrib/db/libmdbx/mdbx.h b/src/contrib/db/libmdbx/mdbx.h deleted file mode 100644 index a52335b..0000000 --- a/src/contrib/db/libmdbx/mdbx.h +++ /dev/null @@ -1,3497 +0,0 @@ -/**** BRIEFLY ****************************************************************** - * - * libmdbx is superior to LMDB (https://bit.ly/26ts7tL) in terms of features - * and reliability, not inferior in performance. In comparison to LMDB, libmdbx - * makes many things just work perfectly, not silently and catastrophically - * break down. libmdbx supports Linux, Windows, MacOS, FreeBSD and other - * systems compliant with POSIX.1-2008. - * - * Look below for API description, for other information (build, embedding and - * amalgamation, improvements over LMDB, benchmarking, etc) please refer to - * README.md at https://abf.io/erthink/libmdbx. - * - * --- - * - * The next version is under active non-public development and will be released - * as MithrilDB and libmithrildb for libraries & packages. Admittedly mythical - * Mithril is resembling silver but being stronger and lighter than steel. - * Therefore MithrilDB is rightly relevant name. - * - * MithrilDB will be radically different from libmdbx by the new database format - * and API based on C++17, as well as the Apache 2.0 License. The goal of this - * revolution is to provide a clearer and robust API, add more features and new - * valuable properties of database. - * - * The Future will (be) Positive. Ð’ÑÑ‘ будет хорошо. - * - * - **** INTRODUCTION ************************************************************* - * - * // For the most part, this section is a copy of the corresponding text - * // from LMDB description, but with some edits reflecting the improvements - * // and enhancements were made in MDBX. - * - * MDBX is a Btree-based database management library modeled loosely on the - * BerkeleyDB API, but much simplified. The entire database (aka "environment") - * is exposed in a memory map, and all data fetches return data directly from - * the mapped memory, so no malloc's or memcpy's occur during data fetches. - * As such, the library is extremely simple because it requires no page caching - * layer of its own, and it is extremely high performance and memory-efficient. - * It is also fully transactional with full ACID semantics, and when the memory - * map is read-only, the database integrity cannot be corrupted by stray pointer - * writes from application code. - * - * The library is fully thread-aware and supports concurrent read/write access - * from multiple processes and threads. Data pages use a copy-on-write strategy - * so no active data pages are ever overwritten, which also provides resistance - * to corruption and eliminates the need of any special recovery procedures - * after a system crash. Writes are fully serialized; only one write transaction - * may be active at a time, which guarantees that writers can never deadlock. - * The database structure is multi-versioned so readers run with no locks; - * writers cannot block readers, and readers don't block writers. - * - * Unlike other well-known database mechanisms which use either write-ahead - * transaction logs or append-only data writes, MDBX requires no maintenance - * during operation. Both write-ahead loggers and append-only databases require - * periodic checkpointing and/or compaction of their log or database files - * otherwise they grow without bound. MDBX tracks free pages within the database - * and re-uses them for new write operations, so the database size does not grow - * without bound in normal use. It is worth noting that the "next" version - * libmdbx (MithrilDB) will solve this problem. - * - * The memory map can be used as a read-only or read-write map. It is read-only - * by default as this provides total immunity to corruption. Using read-write - * mode offers much higher write performance, but adds the possibility for stray - * application writes thru pointers to silently corrupt the database. - * Of course if your application code is known to be bug-free (...) then this is - * not an issue. - * - * If this is your first time using a transactional embedded key-value store, - * you may find the "GETTING STARTED" section below to be helpful. - * - * - **** GETTING STARTED ********************************************************** - * - * // This section is based on Bert Hubert's intro "LMDB Semantics", with - * // edits reflecting the improvements and enhancements were made in MDBX. - * // See https://bit.ly/2maejGY for Bert Hubert's original. - * - * Everything starts with an environment, created by mdbx_env_create(). - * Once created, this environment must also be opened with mdbx_env_open(), - * and after use be closed by mdbx_env_close(). At that a non-zero value of the - * last argument "mode" supposes MDBX will create database and directory if ones - * does not exist. In this case the non-zero "mode" argument specifies the file - * mode bits be applied when a new files are created by open() function. - * - * Within that directory, a lock file (aka LCK-file) and a storage file (aka - * DXB-file) will be generated. If you don't want to use a directory, you can - * pass the MDBX_NOSUBDIR option, in which case the path you provided is used - * directly as the DXB-file, and another file with a "-lck" suffix added - * will be used for the LCK-file. - * - * Once the environment is open, a transaction can be created within it using - * mdbx_txn_begin(). Transactions may be read-write or read-only, and read-write - * transactions may be nested. A transaction must only be used by one thread at - * a time. Transactions are always required, even for read-only access. The - * transaction provides a consistent view of the data. - * - * Once a transaction has been created, a database (i.e. key-value space inside - * the environment) can be opened within it using mdbx_dbi_open(). If only one - * database will ever be used in the environment, a NULL can be passed as the - * database name. For named databases, the MDBX_CREATE flag must be used to - * create the database if it doesn't already exist. Also, mdbx_env_set_maxdbs() - * must be called after mdbx_env_create() and before mdbx_env_open() to set the - * maximum number of named databases you want to support. - * - * NOTE: a single transaction can open multiple databases. Generally databases - * should only be opened once, by the first transaction in the process. - * - * Within a transaction, mdbx_get() and mdbx_put() can store single key-value - * pairs if that is all you need to do (but see CURSORS below if you want to do - * more). - * - * A key-value pair is expressed as two MDBX_val structures. This struct that is - * exactly similar to POSIX's struct iovec and has two fields, iov_len and - * iov_base. The data is a void pointer to an array of iov_len bytes. - * (!) The notable difference between MDBX and LMDB is that MDBX support zero - * length keys. - * - * Because MDBX is very efficient (and usually zero-copy), the data returned in - * an MDBX_val structure may be memory-mapped straight from disk. In other words - * look but do not touch (or free() for that matter). Once a transaction is - * closed, the values can no longer be used, so make a copy if you need to keep - * them after that. - * - * - * CURSORS -- To do more powerful things, we must use a cursor. - * - * Within the transaction, a cursor can be created with mdbx_cursor_open(). - * With this cursor we can store/retrieve/delete (multiple) values using - * mdbx_cursor_get(), mdbx_cursor_put(), and mdbx_cursor_del(). - * - * mdbx_cursor_get() positions itself depending on the cursor operation - * requested, and for some operations, on the supplied key. For example, to list - * all key-value pairs in a database, use operation MDBX_FIRST for the first - * call to mdbx_cursor_get(), and MDBX_NEXT on subsequent calls, until the end - * is hit. - * - * To retrieve all keys starting from a specified key value, use MDBX_SET. For - * more cursor operations, see the API description below. - * - * When using mdbx_cursor_put(), either the function will position the cursor - * for you based on the key, or you can use operation MDBX_CURRENT to use the - * current position of the cursor. NOTE that key must then match the current - * position's key. - * - * - * SUMMARIZING THE OPENING - * - * So we have a cursor in a transaction which opened a database in an - * environment which is opened from a filesystem after it was separately - * created. - * - * Or, we create an environment, open it from a filesystem, create a transaction - * within it, open a database within that transaction, and create a cursor - * within all of the above. - * - * Got it? - * - * - * THREADS AND PROCESSES - * - * Do not have open an database twice in the same process at the same time, MDBX - * will track and prevent this. Instead, share the MDBX environment that has - * opened the file across all threads. The reason for this is: - * - When the "Open file description" locks (aka OFD-locks) are not available, - * MDBX uses POSIX locks on files, and these locks have issues if one process - * opens a file multiple times. - * - If a single process opens the same environment multiple times, closing it - * once will remove all the locks held on it, and the other instances will be - * vulnerable to corruption from other processes. - * + For compatibility with LMDB which allows multi-opening, MDBX can be - * configured at runtime by mdbx_setup_debug(MDBX_DBG_LEGACY_MULTIOPEN, ...) - * prior to calling other MDBX funcitons. In this way MDBX will track - * databases opening, detect multi-opening cases and then recover POSIX file - * locks as necessary. However, lock recovery can cause unexpected pauses, - * such as when another process opened the database in exclusive mode before - * the lock was restored - we have to wait until such a process releases the - * database, and so on. - * - * Do not use opened MDBX environment(s) after fork() in a child process(es), - * MDBX will check and prevent this at critical points. Instead, ensure there is - * no open MDBX-instance(s) during fork(), or atleast close it immediately after - * fork() in the child process and reopen if required - for instance by using - * pthread_atfork(). The reason for this is: - * - For competitive consistent reading, MDBX assigns a slot in the shared - * table for each process that interacts with the database. This slot is - * populated with process attributes, including the PID. - * - After fork(), in order to remain connected to a database, the child - * process must have its own such "slot", which can't be assigned in any - * simple and robust way another than the regular. - * - A write transaction from a parent process cannot continue in a child - * process for obvious reasons. - * - Moreover, in a multithreaded process at the fork() moment any number of - * threads could run in critical and/or intermediate sections of MDBX code - * with interaction and/or racing conditions with threads from other - * process(es). For instance: shrinking a database or copying it to a pipe, - * opening or closing environment, begining or finishing a transaction, - * and so on. - * = Therefore, any solution other than simply close database (and reopen if - * necessary) in a child process would be both extreme complicated and so - * fragile. - * - * Also note that a transaction is tied to one thread by default using Thread - * Local Storage. If you want to pass read-only transactions across threads, - * you can use the MDBX_NOTLS option on the environment. Nevertheless, a write - * transaction entirely should only be used in one thread from start to finish. - * MDBX checks this in a reasonable manner and return the MDBX_THREAD_MISMATCH - * error in rules violation. - * - * - * TRANSACTIONS, ROLLBACKS, etc. - * - * To actually get anything done, a transaction must be committed using - * mdbx_txn_commit(). Alternatively, all of a transaction's operations - * can be discarded using mdbx_txn_abort(). - * - * (!) An important difference between MDBX and LMDB is that MDBX required that - * any opened cursors can be reused and must be freed explicitly, regardless - * ones was opened in a read-only or write transaction. The REASON for this is - * eliminates ambiguity which helps to avoid errors such as: use-after-free, - * double-free, i.e. memory corruption and segfaults. - * - * For read-only transactions, obviously there is nothing to commit to storage. - * (!) An another notable difference between MDBX and LMDB is that MDBX make - * handles opened for existing databases immediately available for other - * transactions, regardless this transaction will be aborted or reset. The - * REASON for this is to avoiding the requirement for multiple opening a same - * handles in concurrent read transactions, and tracking of such open but hidden - * handles until the completion of read transactions which opened them. - * - * In addition, as long as a transaction is open, a consistent view of the - * database is kept alive, which requires storage. A read-only transaction that - * no longer requires this consistent view should be terminated (committed or - * aborted) when the view is no longer needed (but see below for an - * optimization). - * - * There can be multiple simultaneously active read-only transactions but only - * one that can write. Once a single read-write transaction is opened, all - * further attempts to begin one will block until the first one is committed or - * aborted. This has no effect on read-only transactions, however, and they may - * continue to be opened at any time. - * - * - * DUPLICATE KEYS - * - * mdbx_get() and mdbx_put() respectively have no and only some support or - * multiple key-value pairs with identical keys. If there are multiple values - * for a key, mdbx_get() will only return the first value. - * - * When multiple values for one key are required, pass the MDBX_DUPSORT flag to - * mdbx_dbi_open(). In an MDBX_DUPSORT database, by default mdbx_put() will not - * replace the value for a key if the key existed already. Instead it will add - * the new value to the key. In addition, mdbx_del() will pay attention to the - * value field too, allowing for specific values of a key to be deleted. - * - * Finally, additional cursor operations become available for traversing through - * and retrieving duplicate values. - * - * - * SOME OPTIMIZATION - * - * If you frequently begin and abort read-only transactions, as an optimization, - * it is possible to only reset and renew a transaction. - * - * mdbx_txn_reset() releases any old copies of data kept around for a read-only - * transaction. To reuse this reset transaction, call mdbx_txn_renew() on it. - * Any cursors in this transaction can also be renewed using mdbx_cursor_renew() - * or freed by mdbx_cursor_close(). - * - * To permanently free a transaction, reset or not, use mdbx_txn_abort(). - * - * - * CLEANING UP - * - * Any created cursors must be closed using mdbx_cursor_close(). It is advisable - * to repeat: - * (!) An important difference between MDBX and LMDB is that MDBX required that - * any opened cursors can be reused and must be freed explicitly, regardless - * ones was opened in a read-only or write transaction. The REASON for this is - * eliminates ambiguity which helps to avoid errors such as: use-after-free, - * double-free, i.e. memory corruption and segfaults. - * - * It is very rarely necessary to close a database handle, and in general they - * should just be left open. When you close a handle, it immediately becomes - * unavailable for all transactions in the environment. Therefore, you should - * avoid closing the handle while at least one transaction is using it. - * - * - * THE FULL API - * - * The full MDBX documentation lists further details below, - * like how to: - * - * - configure database size and automatic size management - * - drop and clean a database - * - detect and report errors - * - optimize (bulk) loading speed - * - (temporarily) reduce robustness to gain even more speed - * - gather statistics about the database - * - define custom sort orders - * - estimate size of range query result - * - double perfomance by LIFO reclaiming on storages with write-back - * - use sequences and canary markers - * - use lack-of-space callback (aka OOM-KICK) - * - use exclusive mode - * - * - **** RESTRICTIONS & CAVEATS *************************************************** - * in addition to those listed for some functions. - * - * - Troubleshooting the LCK-file. - * 1. A broken LCK-file can cause sync issues, including appearance of - * wrong/inconsistent data for readers. When database opened in the - * cooperative read-write mode the LCK-file requires to be mapped to - * memory in read-write access. In this case it is always possible for - * stray/malfunctioned application could writes thru pointers to - * silently corrupt the LCK-file. - * - * Unfortunately, there is no any portable way to prevent such - * corruption, since the LCK-file is updated concurrently by - * multiple processes in a lock-free manner and any locking is - * unwise due to a large overhead. - * - * The "next" version of libmdbx (MithrilDB) will solve this issue. - * - * Workaround: Just make all programs using the database close it; - * the LCK-file is always reset on first open. - * - * 2. Stale reader transactions left behind by an aborted program cause - * further writes to grow the database quickly, and stale locks can - * block further operation. - * MDBX checks for stale readers while opening environment and before - * growth the database. But in some cases, this may not be enough. - * - * Workaround: Check for stale readers periodically, using the - * mdbx_reader_check() function or the mdbx_stat tool. - * - * 3. Stale writers will be cleared automatically by MDBX on supprted - * platforms. But this is platform-specific, especially of - * implementation of shared POSIX-mutexes and support for robust - * mutexes. For instance there are no known issues on Linux, OSX, - * Windows and FreeBSD. - * - * Workaround: Otherwise just make all programs using the database - * close it; the LCK-file is always reset on first open - * of the environment. - * - * - Do not use MDBX databases on remote filesystems, even between processes - * on the same host. This breaks file locks on some platforms, possibly - * memory map sync, and certainly sync between programs on different hosts. - * - * On the other hand, MDBX support the exclusive database operation over - * a network, and cooperative read-only access to the database placed on - * a read-only network shares. - * - * - Do not use opened MDBX_env instance(s) in a child processes after fork(). - * It would be insane to call fork() and any MDBX-functions simultaneously - * from multiple threads. The best way is to prevent the presence of open - * MDBX-instances during fork(). - * - * The MDBX_TXN_CHECKPID build-time option, which is ON by default on - * non-Windows platforms (i.e. where fork() is available), enables PID - * checking at a few critical points. But this does not give any guarantees, - * but only allows you to detect such errors a little sooner. Depending on - * the platform, you should expect an application crash and/or database - * corruption in such cases. - * - * On the other hand, MDBX allow calling mdbx_close_env() in such cases to - * release resources, but no more and in general this is a wrong way. - * - * - There is no pure read-only mode in a normal explicitly way, since - * readers need write access to LCK-file to be ones visible for writer. - * MDBX always tries to open/create LCK-file for read-write, but switches - * to without-LCK mode on appropriate errors (EROFS, EACCESS, EPERM) - * if the read-only mode was requested by the MDBX_RDONLY flag which is - * described below. - * - * The "next" version of libmdbx (MithrilDB) will solve this issue. - * - * - A thread can only use one transaction at a time, plus any nested - * read-write transactions in the non-writemap mode. Each transaction - * belongs to one thread. The MDBX_NOTLS flag changes this for read-only - * transactions. See below. - * - * - Do not have open an MDBX database twice in the same process at the same - * time. By default MDBX prevent this in most cases by tracking databases - * opening and return MDBX_BUSY if anyone LCK-file is already open. - * - * The reason for this is that when the "Open file description" locks (aka - * OFD-locks) are not available, MDBX uses POSIX locks on files, and these - * locks have issues if one process opens a file multiple times. If a single - * process opens the same environment multiple times, closing it once will - * remove all the locks held on it, and the other instances will be - * vulnerable to corruption from other processes. - * - * For compatibility with LMDB which allows multi-opening, MDBX can be - * configured at runtime by mdbx_setup_debug(MDBX_DBG_LEGACY_MULTIOPEN, ...) - * prior to calling other MDBX funcitons. In this way MDBX will track - * databases opening, detect multi-opening cases and then recover POSIX file - * locks as necessary. However, lock recovery can cause unexpected pauses, - * such as when another process opened the database in exclusive mode before - * the lock was restored - we have to wait until such a process releases the - * database, and so on. - * - * - Avoid long-lived transactions, especially in the scenarios with a high - * rate of write transactions. Read transactions prevent reuse of pages - * freed by newer write transactions, thus the database can grow quickly. - * Write transactions prevent other write transactions, since writes are - * serialized. - * - * Understanding the problem of long-lived read transactions requires some - * explanation, but can be difficult for quick perception. So is is - * reasonable to simplify this as follows: - * 1. Garbage collection problem exists in all databases one way or - * another, e.g. VACUUM in PostgreSQL. But in _libmdbx_ it's even more - * discernible because of high transaction rate and intentional - * internals simplification in favor of performance. - * - * 2. MDBX employs Multiversion concurrency control on the Copy-on-Write - * basis, that allows multiple readers runs in parallel with a write - * transaction without blocking. An each write transaction needs free - * pages to put the changed data, that pages will be placed in the new - * b-tree snapshot at commit. MDBX efficiently recycling pages from - * previous created unused snapshots, BUT this is impossible if anyone - * a read transaction use such snapshot. - * - * 3. Thus massive altering of data during a parallel long read operation - * will increase the process's work set and may exhaust entire free - * database space. - * - * A good example of long readers is a hot backup to the slow destination - * or debugging of a client application while retaining an active read - * transaction. LMDB this results in MAP_FULL error and subsequent write - * performance degradation. - * - * MDBX mostly solve "long-lived" readers issue by the lack-of-space callback - * which allow to aborts long readers, and by the MDBX_LIFORECLAIM mode which - * addresses subsequent performance degradation. - * The "next" version of libmdbx (MithrilDB) will completely solve this. - * - * - Avoid suspending a process with active transactions. These would then be - * "long-lived" as above. - * - * The "next" version of libmdbx (MithrilDB) will solve this issue. - * - * - Avoid aborting a process with an active read-only transaction in scenaries - * with high rate of write transactions. The transaction becomes "long-lived" - * as above until a check for stale readers is performed or the LCK-file is - * reset, since the process may not remove it from the lockfile. This does - * not apply to write transactions if the system clears stale writers, see - * above. - * - * - An MDBX database configuration will often reserve considerable unused - * memory address space and maybe file size for future growth. This does - * not use actual memory or disk space, but users may need to understand - * the difference so they won't be scared off. - * - * - The Write Amplification Factor. - * TBD. - * - **** LICENSE AND COPYRUSTING ************************************************** - * - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - * - * --- - * - * This code is derived from "LMDB engine" written by - * Howard Chu (Symas Corporation), which itself derived from btree.c - * written by Martin Hedenfalk. - * - * --- - * - * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - * - * --- - * - * Portions Copyright (c) 2009, 2010 Martin Hedenfalk - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - **** ACKNOWLEDGEMENTS ********************************************************* - * - * Howard Chu (Symas Corporation) - the author of LMDB, - * from which originated the MDBX in 2015. - * - * Martin Hedenfalk - the author of `btree.c` code, - * which was used for begin development of LMDB. - * - ******************************************************************************/ - -#pragma once -#ifndef LIBMDBX_H -#define LIBMDBX_H - -#ifdef _MSC_VER -#pragma warning(push, 1) -#pragma warning(disable : 4548) /* expression before comma has no effect; \ - expected expression with side - effect */ -#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ - * semantics are not enabled. Specify /EHsc */ -#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ - * mode specified; termination on exception is \ - * not guaranteed. Specify /EHsc */ -#endif /* _MSC_VER (warnings) */ - -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) - -#include -#include -#ifndef __mode_t_defined -typedef unsigned short mode_t; -#endif -typedef HANDLE mdbx_filehandle_t; -typedef DWORD mdbx_pid_t; -typedef DWORD mdbx_tid_t; -#define MDBX_ENODATA ERROR_HANDLE_EOF -#define MDBX_EINVAL ERROR_INVALID_PARAMETER -#define MDBX_EACCESS ERROR_ACCESS_DENIED -#define MDBX_ENOMEM ERROR_OUTOFMEMORY -#define MDBX_EROFS ERROR_FILE_READ_ONLY -#define MDBX_ENOSYS ERROR_NOT_SUPPORTED -#define MDBX_EIO ERROR_WRITE_FAULT -#define MDBX_EPERM ERROR_INVALID_FUNCTION -#define MDBX_EINTR ERROR_CANCELLED -#define MDBX_ENOFILE ERROR_FILE_NOT_FOUND - -#else - -#include /* for error codes */ -#include /* for pthread_t */ -#include /* for pid_t */ -#include /* for truct iovec */ -#define HAVE_STRUCT_IOVEC 1 -typedef int mdbx_filehandle_t; -typedef pid_t mdbx_pid_t; -typedef pthread_t mdbx_tid_t; -#ifdef ENODATA -#define MDBX_ENODATA ENODATA -#else -#define MDBX_ENODATA -1 -#endif -#define MDBX_EINVAL EINVAL -#define MDBX_EACCESS EACCES -#define MDBX_ENOMEM ENOMEM -#define MDBX_EROFS EROFS -#define MDBX_ENOSYS ENOSYS -#define MDBX_EIO EIO -#define MDBX_EPERM EPERM -#define MDBX_EINTR EINTR -#define MDBX_ENOFILE ENOENT - -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -/*----------------------------------------------------------------------------*/ - -#ifndef __has_attribute -#define __has_attribute(x) (0) -#endif - -#ifndef __dll_export -#if defined(_WIN32) || defined(__CYGWIN__) -#if defined(__GNUC__) || __has_attribute(dllexport) -#define __dll_export __attribute__((dllexport)) -#elif defined(_MSC_VER) -#define __dll_export __declspec(dllexport) -#else -#define __dll_export -#endif -#elif defined(__GNUC__) || __has_attribute(__visibility__) -#define __dll_export __attribute__((__visibility__("default"))) -#else -#define __dll_export -#endif -#endif /* __dll_export */ - -#ifndef __dll_import -#if defined(_WIN32) || defined(__CYGWIN__) -#if defined(__GNUC__) || __has_attribute(dllimport) -#define __dll_import __attribute__((dllimport)) -#elif defined(_MSC_VER) -#define __dll_import __declspec(dllimport) -#else -#define __dll_import -#endif -#else -#define __dll_import -#endif -#endif /* __dll_import */ - -/*----------------------------------------------------------------------------*/ - -#define MDBX_VERSION_MAJOR 0 -#define MDBX_VERSION_MINOR 3 - -#ifndef LIBMDBX_API -#if defined(LIBMDBX_EXPORTS) -#define LIBMDBX_API __dll_export -#elif defined(LIBMDBX_IMPORTS) -#define LIBMDBX_API __dll_import -#else -#define LIBMDBX_API -#endif -#endif /* LIBMDBX_API */ - -#ifdef __cplusplus -extern "C" { -#endif - -/**** MDBX version information ************************************************/ - -#if defined(LIBMDBX_IMPORTS) -#define LIBMDBX_VERINFO_API __dll_import -#else -#define LIBMDBX_VERINFO_API __dll_export -#endif /* LIBMDBX_VERINFO_API */ - -typedef struct mdbx_version_info { - uint8_t major; - uint8_t minor; - uint16_t release; - uint32_t revision; - struct /* source info from git */ { - const char *datetime /* committer date, strict ISO-8601 format */; - const char *tree /* commit hash (hexadecimal digits) */; - const char *commit /* tree hash, i.e. digest of the source code */; - const char *describe /* git-describe string */; - } git; - const char *sourcery /* sourcery anchor for pinning */; -} mdbx_version_info; -extern LIBMDBX_VERINFO_API const mdbx_version_info mdbx_version; - -/* MDBX build information. - * WARNING: Some strings could be NULL in case no corresponding information was - * provided at build time (i.e. flags). */ -typedef struct mdbx_build_info { - const char *datetime /* build timestamp (ISO-8601 or __DATE__ __TIME__) */; - const char *target /* cpu/arch-system-config triplet */; - const char *options /* mdbx-related options */; - const char *compiler /* compiler */; - const char *flags /* CFLAGS */; -} mdbx_build_info; -extern LIBMDBX_VERINFO_API const mdbx_build_info mdbx_build; - -#if defined(_WIN32) || defined(_WIN64) -#if !MDBX_BUILD_SHARED_LIBRARY - -/* MDBX internally uses global and thread local storage destructors to - * automatically (de)initialization, releasing reader lock table slots - * and so on. - * - * If MDBX builded as a DLL this is done out-of-the-box by DllEntry() function, - * which called automatically by Windows core with passing corresponding reason - * argument. - * - * Otherwise, if MDBX was builded not as a DLL, some black magic - * may be required depending of Windows version: - * - Modern Windows versions, including Windows Vista and later, provides - * support for "TLS Directory" (e.g .CRT$XL[A-Z] sections in executable - * or dll file). In this case, MDBX capable of doing all automatically, - * and you do not need to call mdbx_dll_handler(). - * - Obsolete versions of Windows, prior to Windows Vista, REQUIRES calling - * mdbx_dll_handler() manually from corresponding DllMain() or WinMain() - * of your DLL or application. - * - This behavior is under control of the MODX_CONFIG_MANUAL_TLS_CALLBACK - * option, which is determined by default according to the target version - * of Windows at build time. - * But you may override MODX_CONFIG_MANUAL_TLS_CALLBACK in special cases. - * - * Therefore, building MDBX as a DLL is recommended for all version of Windows. - * So, if you doubt, just build MDBX as the separate DLL and don't worry. */ - -#ifndef MDBX_CONFIG_MANUAL_TLS_CALLBACK -#if defined(_WIN32_WINNT_VISTA) && WINVER >= _WIN32_WINNT_VISTA -/* As described above mdbx_dll_handler() is NOT needed forWindows Vista - * and later. */ -#define MDBX_CONFIG_MANUAL_TLS_CALLBACK 0 -#else -/* As described above mdbx_dll_handler() IS REQUIRED for Windows versions - * prior to Windows Vista. */ -#define MDBX_CONFIG_MANUAL_TLS_CALLBACK 1 -#endif -#endif /* MDBX_CONFIG_MANUAL_TLS_CALLBACK */ - -#if MDBX_CONFIG_MANUAL_TLS_CALLBACK -void LIBMDBX_API NTAPI mdbx_dll_handler(PVOID module, DWORD reason, - PVOID reserved); -#endif /* MDBX_CONFIG_MANUAL_TLS_CALLBACK */ -#endif /* !MDBX_BUILD_SHARED_LIBRARY */ -#endif /* Windows */ - -/**** OPACITY STRUCTURES ******************************************************/ - -/* Opaque structure for a database environment. - * - * An environment supports multiple key-value databases (aka key-value spaces - * or tables), all residing in the same shared-memory map. */ -typedef struct MDBX_env MDBX_env; - -/* Opaque structure for a transaction handle. - * - * All database operations require a transaction handle. Transactions may be - * read-only or read-write. */ -typedef struct MDBX_txn MDBX_txn; - -/* A handle for an individual database (key-value spaces) in the environment. - * Zero handle is used internally (hidden Garbage Collection DB). - * So, any valid DBI-handle great than 0 and less than or equal MDBX_MAX_DBI. */ -typedef uint32_t MDBX_dbi; -#define MDBX_MAX_DBI UINT32_C(32765) - -/* Opaque structure for navigating through a database */ -typedef struct MDBX_cursor MDBX_cursor; - -/* Generic structure used for passing keys and data in and out of the database. - * - * Values returned from the database are valid only until a subsequent - * update operation, or the end of the transaction. Do not modify or - * free them, they commonly point into the database itself. - * - * Key sizes must be between 0 and mdbx_env_get_maxkeysize() inclusive. - * The same applies to data sizes in databases with the MDBX_DUPSORT flag. - * Other data items can in theory be from 0 to 0x7fffffff bytes long. - * - * (!) The notable difference between MDBX and LMDB is that MDBX support zero - * length keys. */ -#ifndef HAVE_STRUCT_IOVEC -struct iovec { - void *iov_base /* pointer to some data */; - size_t iov_len /* the length of data in bytes */; -}; -#define HAVE_STRUCT_IOVEC -#endif /* HAVE_STRUCT_IOVEC */ - -typedef struct iovec MDBX_val; - -/* The maximum size of a data item. - * MDBX only store a 32 bit value for node sizes. */ -#define MDBX_MAXDATASIZE INT32_MAX - -/**** DEBUG & LOGGING ********************************************************** - * Logging and runtime debug flags. - * - * NOTE: Most of debug feature enabled only when libmdbx builded with - * MDBX_DEBUG options. - */ - -/* Log level (requires build libmdbx with MDBX_DEBUG) */ -#define MDBX_LOG_FATAL 0 /* critical conditions, i.e. assertion failures */ -#define MDBX_LOG_ERROR 1 /* error conditions */ -#define MDBX_LOG_WARN 2 /* warning conditions */ -#define MDBX_LOG_NOTICE 3 /* normal but significant condition */ -#define MDBX_LOG_VERBOSE 4 /* verbose informational */ -#define MDBX_LOG_DEBUG 5 /* debug-level messages */ -#define MDBX_LOG_TRACE 6 /* trace debug-level messages */ -#define MDBX_LOG_EXTRA 7 /* extra debug-level messages (dump pgno lists) */ - -/* Runtime debug flags. - * - * MDBX_DBG_DUMP and MDBX_DBG_LEGACY_MULTIOPEN always have an effect, - * but MDBX_DBG_ASSERT, MDBX_DBG_AUDIT and MDBX_DBG_JITTER only if libmdbx - * builded with MDBX_DEBUG. */ - -#define MDBX_DBG_ASSERT 1 /* Enable assertion checks */ -#define MDBX_DBG_AUDIT 2 /* Enable pages usage audit at commit transactions */ -#define MDBX_DBG_JITTER 4 /* Enable small random delays in critical points */ -#define MDBX_DBG_DUMP 8 /* Include or not database(s) in coredump files */ -#define MDBX_DBG_LEGACY_MULTIOPEN 16 /* Enable multi-opening environment(s) */ - -/* A debug-logger callback function, - * called before printing the message and aborting. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] msg The assertion message, not including newline. */ -typedef void MDBX_debug_func(int loglevel, const char *function, int line, - const char *msg, va_list args); - -/* FIXME: Complete description */ -LIBMDBX_API int mdbx_setup_debug(int loglevel, int flags, - MDBX_debug_func *logger); - -/* A callback function for most MDBX assert() failures, - * called before printing the message and aborting. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] msg The assertion message, not including newline. */ -typedef void MDBX_assert_func(const MDBX_env *env, const char *msg, - const char *function, unsigned line); - -/* Set or reset the assert() callback of the environment. - * - * Does nothing if libmdbx was built with MDBX_DEBUG=0 or with NDEBUG, - * and will return MDBX_ENOSYS in such case. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] func An MDBX_assert_func function, or 0. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func); - -/* FIXME: Complete description */ -LIBMDBX_API const char *mdbx_dump_val(const MDBX_val *key, char *const buf, - const size_t bufsize); - -/**** THE FILES **************************************************************** - * At the file system level, the environment corresponds to a pair of files. */ - -/* The name of the lock file in the environment */ -#define MDBX_LOCKNAME "/mdbx.lck" -/* The name of the data file in the environment */ -#define MDBX_DATANAME "/mdbx.dat" - -/* The suffix of the lock file when MDBX_NOSUBDIR is used */ -#define MDBX_LOCK_SUFFIX "-lck" - -/**** ENVIRONMENT FLAGS *******************************************************/ - -/* MDBX_NOSUBDIR = no environment directory. - * - * By default, MDBX creates its environment in a directory whose pathname is - * given in path, and creates its data and lock files under that directory. - * With this option, path is used as-is for the database main data file. - * The database lock file is the path with "-lck" appended. - * - * - with MDBX_NOSUBDIR = in a filesystem we have the pair of MDBX-files which - * names derived from given pathname by appending predefined suffixes. - * - * - without MDBX_NOSUBDIR = in a filesystem we have the MDBX-directory with - * given pathname, within that a pair of MDBX-files with predefined names. - * - * This flag affects only at environment opening and can't be changed after. */ -#define MDBX_NOSUBDIR 0x4000u - -/* MDBX_RDONLY = read only mode. - * - * Open the environment in read-only mode. No write operations will be allowed. - * MDBX will still modify the lock file - except on read-only filesystems, - * where MDBX does not use locks. - * - * - with MDBX_RDONLY = open environment in read-only mode. - * MDBX supports pure read-only mode (i.e. without opening LCK-file) only - * when environment directory and/or both files are not writable (and the - * LCK-file may be missing). In such case allowing file(s) to be placed - * on a network read-only share. - * - * - without MDBX_RDONLY = open environment in read-write mode. - * - * This flag affects only at environment opening but can't be changed after. */ -#define MDBX_RDONLY 0x20000u - -/* MDBX_EXCLUSIVE = open environment in exclusive/monopolistic mode. - * - * MDBX_EXCLUSIVE flag can be used as a replacement for MDB_NOLOCK, which don't - * supported by MDBX. In this way, you can get the minimal overhead, but with - * the correct multi-process and mutli-thread locking. - * - * - with MDBX_EXCLUSIVE = open environment in exclusive/monopolistic mode - * or return MDBX_BUSY if environment already used by other process. - * The main feature of the exclusive mode is the ability to open the - * environment placed on a network share. - * - * - without MDBX_EXCLUSIVE = open environment in cooperative mode, - * i.e. for multi-process access/interaction/cooperation. - * The main requirements of the cooperative mode are: - * 1. data files MUST be placed in the LOCAL file system, - * but NOT on a network share. - * 2. environment MUST be opened only by LOCAL processes, - * but NOT over a network. - * 3. OS kernel (i.e. file system and memory mapping implementation) and - * all processes that open the given environment MUST be running - * in the physically single RAM with cache-coherency. The only - * exception for cache-consistency requirement is Linux on MIPS - * architecture, but this case has not been tested for a long time). - - * This flag affects only at environment opening but can't be changed after. */ -#define MDBX_EXCLUSIVE 0x400000u - -/* MDBX_WRITEMAP = map data into memory with write permission. - * - * Use a writeable memory map unless MDBX_RDONLY is set. This uses fewer mallocs - * and requires much less work for tracking database pages, but loses protection - * from application bugs like wild pointer writes and other bad updates into the - * database. This may be slightly faster for DBs that fit entirely in RAM, but - * is slower for DBs larger than RAM. Also adds the possibility for stray - * application writes thru pointers to silently corrupt the database. - * Incompatible with nested transactions. - * - * NOTE: The MDBX_WRITEMAP mode is incompatible with nested transactions, since - * this is unreasonable. I.e. nested transactions requires mallocation of - * database pages and more work for tracking ones, which neuters a - * performance boost caused by the MDBX_WRITEMAP mode. - * - * NOTE: MDBX don't allow to mix processes with and without MDBX_WRITEMAP on - * the same environment. In such case MDBX_INCOMPATIBLE will be generated. - * - * - with MDBX_WRITEMAP = all data will be mapped into memory in the read-write - * mode. This offers a significant performance benefit, since the data will - * be modified directly in mapped memory and then flushed to disk by - * single system call, without any memory management nor copying. - * (!) On the other hand, MDBX_WRITEMAP adds the possibility for stray - * application writes thru pointers to silently corrupt the database. - * Moreover, MDBX_WRITEMAP disallows nested write transactions. - * - * - without MDBX_WRITEMAP = data will be mapped into memory in the read-only - * mode. This requires stocking all modified database pages in memory and - * then writing them to disk through file operations. - * - * This flag affects only at environment opening but can't be changed after. */ -#define MDBX_WRITEMAP 0x80000u - -/* MDBX_NOTLS = tie reader locktable slots to read-only transactions instead - * of to threads. - * - * Don't use Thread-Local Storage, instead tie reader locktable slots to - * MDBX_txn objects instead of to threads. So, mdbx_txn_reset() keeps the slot - * reserved for the MDBX_txn object. A thread may use parallel read-only - * transactions. And a read-only transaction may span threads if you - * synchronizes its use. - * - * Applications that multiplex many user threads over individual OS threads need - * this option. Such an application must also serialize the write transactions - * in an OS thread, since MDBX's write locking is unaware of the user threads. - * - * NOTE: Regardless to MDBX_NOTLS flag a write transaction entirely should - * always be used in one thread from start to finish. MDBX checks this in a - * reasonable manner and return the MDBX_THREAD_MISMATCH error in rules - * violation. - * - * This flag affects only at environment opening but can't be changed after. */ -#define MDBX_NOTLS 0x200000u - -/* MDBX_NORDAHEAD = don't do readahead. - * - * Turn off readahead. Most operating systems perform readahead on read requests - * by default. This option turns it off if the OS supports it. Turning it off - * may help random read performance when the DB is larger than RAM and system - * RAM is full. - * - * NOTE: The mdbx_is_readahead_reasonable() function allows to quickly find out - * whether to use readahead or not based on the size of the data and the - * amount of available memory. - * - * This flag affects only at environment opening and can't be changed after. */ -#define MDBX_NORDAHEAD 0x800000u - -/* MDBX_NOMEMINIT = don't initialize malloc'd memory before writing to datafile. - * - * Don't initialize malloc'd memory before writing to unused spaces in the data - * file. By default, memory for pages written to the data file is obtained using - * malloc. While these pages may be reused in subsequent transactions, freshly - * malloc'd pages will be initialized to zeroes before use. This avoids - * persisting leftover data from other code (that used the heap and subsequently - * freed the memory) into the data file. - * - * Note that many other system libraries may allocate and free memory from the - * heap for arbitrary uses. E.g., stdio may use the heap for file I/O buffers. - * This initialization step has a modest performance cost so some applications - * may want to disable it using this flag. This option can be a problem for - * applications which handle sensitive data like passwords, and it makes memory - * checkers like Valgrind noisy. This flag is not needed with MDBX_WRITEMAP, - * which writes directly to the mmap instead of using malloc for pages. The - * initialization is also skipped if MDBX_RESERVE is used; the caller is - * expected to overwrite all of the memory that was reserved in that case. - * - * This flag may be changed at any time using mdbx_env_set_flags(). */ -#define MDBX_NOMEMINIT 0x1000000u - -/* MDBX_COALESCE = aims to coalesce a Garbage Collection items. - * - * With MDBX_COALESCE flag MDBX will aims to coalesce items while recycling - * a Garbage Collection. Technically, when possible short lists of pages will - * be combined into longer ones, but to fit on one database page. As a result, - * there will be fewer items in Garbage Collection and a page lists are longer, - * which slightly increases the likelihood of returning pages to Unallocated - * space and reducing the database file. - * - * This flag may be changed at any time using mdbx_env_set_flags(). */ -#define MDBX_COALESCE 0x2000000u - -/* MDBX_LIFORECLAIM = LIFO policy for recycling a Garbage Collection items. - * - * MDBX_LIFORECLAIM flag turns on LIFO policy for recycling a Garbage - * Collection items, instead of FIFO by default. On systems with a disk - * write-back cache, this can significantly increase write performance, up to - * several times in a best case scenario. - * - * LIFO recycling policy means that for reuse pages will be taken which became - * unused the lastest (i.e. just now or most recently). Therefore the loop of - * database pages circulation becomes as short as possible. In other words, the - * number of pages, that are overwritten in memory and on disk during a series - * of write transactions, will be as small as possible. Thus creates ideal - * conditions for the efficient operation of the disk write-back cache. - * - * MDBX_LIFORECLAIM is compatible with all no-sync flags (i.e. MDBX_NOMETASYNC, - * MDBX_NOSYNC, MDBX_UTTERLY_NOSYNC, MDBX_MAPASYNC), but gives no noticeable - * impact in combination with MDB_NOSYNC and MDX_MAPASYNC. Because MDBX will - * not reused paged from the last "steady" MVCC-snapshot and later, i.e. the - * loop length of database pages circulation will be mostly defined by frequency - * of calling mdbx_env_sync() rather than LIFO and FIFO difference. - * - * This flag may be changed at any time using mdbx_env_set_flags(). */ -#define MDBX_LIFORECLAIM 0x4000000u - -/* Debuging option, fill/perturb released pages. */ -#define MDBX_PAGEPERTURB 0x8000000u - -/**** SYNC MODES *************************************************************** - * (!!!) Using any combination of MDBX_NOSYNC, MDBX_NOMETASYNC, MDBX_MAPASYNC - * and especially MDBX_UTTERLY_NOSYNC is always a deal to reduce durability - * for gain write performance. You must know exactly what you are doing and - * what risks you are taking! - * - * NOTE for LMDB users: MDBX_NOSYNC is NOT similar to LMDB_NOSYNC, but - * MDBX_UTTERLY_NOSYNC is exactly match LMDB_NOSYNC. - * See details below. - * - * THE SCENE: - * - The DAT-file contains several MVCC-snapshots of B-tree at same time, - * each of those B-tree has its own root page. - * - Each of meta pages at the beginning of the DAT file contains a pointer - * to the root page of B-tree which is the result of the particular - * transaction, and a number of this transaction. - * - For data durability, MDBX must first write all MVCC-snapshot data pages - * and ensure that are written to the disk, then update a meta page with - * the new transaction number and a pointer to the corresponding new root - * page, and flush any buffers yet again. - * - Thus during commit a I/O buffers should be flushed to the disk twice; - * i.e. fdatasync(), FlushFileBuffers() or similar syscall should be called - * twice for each commit. This is very expensive for performance, but - * guaranteed durability even on unexpected system failure or power outage. - * Of course, provided that the operating system and the underlying hardware - * (e.g. disk) work correctly. - * - * TRADE-OFF: By skipping some stages described above, you can significantly - * benefit in speed, while partially or completely losing in the guarantee of - * data durability and/or consistency in the event of system or power failure. - * Moreover, if for any reason disk write order is not preserved, then at moment - * of a system crash, a meta-page with a pointer to the new B-tree may be - * written to disk, while the itself B-tree not yet. In that case, the database - * will be corrupted! - * - * - * MDBX_NOMETASYNC = don't sync the meta-page after commit. - * - * Flush system buffers to disk only once per transaction, omit the - * metadata flush. Defer that until the system flushes files to disk, - * or next non-MDBX_RDONLY commit or mdbx_env_sync(). Depending on the - * platform and hardware, with MDBX_NOMETASYNC you may get a doubling of - * write performance. - * - * This trade-off maintains database integrity, but a system crash may - * undo the last committed transaction. I.e. it preserves the ACI - * (atomicity, consistency, isolation) but not D (durability) database - * property. - * - * MDBX_NOMETASYNC flag may be changed at any time using - * mdbx_env_set_flags() or by passing to mdbx_txn_begin() for particular - * write transaction. - * - * - * MDBX_UTTERLY_NOSYNC = don't sync anything and wipe previous steady commits. - * - * Don't flush system buffers to disk when committing a transaction. This - * optimization means a system crash can corrupt the database, if buffers - * are not yet flushed to disk. Depending on the platform and hardware, - * with MDBX_UTTERLY_NOSYNC you may get a multiple increase of write - * performance, even 100 times or more. - * - * If the filesystem preserves write order (which is rare and never - * provided unless explicitly noted) and the MDBX_WRITEMAP and - * MDBX_LIFORECLAIM flags are not used, then a system crash can't corrupt - * the database, but you can lose the last transactions, if at least one - * buffer is not yet flushed to disk. The risk is governed by how often the - * system flushes dirty buffers to disk and how often mdbx_env_sync() is - * called. So, transactions exhibit ACI (atomicity, consistency, isolation) - * properties and only lose D (durability). I.e. database integrity is - * maintained, but a system crash may undo the final transactions. - * - * Otherwise, if the filesystem not preserves write order (which is - * typically) or MDBX_WRITEMAP or MDBX_LIFORECLAIM flags are used, you - * should expect the corrupted database after a system crash. - * - * So, most important thing about MDBX_UTTERLY_NOSYNC: - * - a system crash immediately after commit the write transaction - * high likely lead to database corruption. - * - successful completion of mdbx_env_sync(force = true) after one or - * more commited transactions guarantees consystency and durability. - * - BUT by committing two or more transactions you back database into a - * weak state, in which a system crash may lead to database corruption! - * In case single transaction after mdbx_env_sync, you may lose - * transaction itself, but not a whole database. - * - * Nevertheless, MDBX_UTTERLY_NOSYNC provides ACID in case of a application - * crash, and therefore may be very useful in scenarios where data - * durability is not required over a system failure (e.g for short-lived - * data), or if you can ignore such risk. - * - * MDBX_UTTERLY_NOSYNC flag may be changed at any time using - * mdbx_env_set_flags(), but don't has effect if passed to mdbx_txn_begin() - * for particular write transaction. - * - * - * MDBX_NOSYNC = don't sync anything but keep previous steady commits. - * - * Like MDBX_UTTERLY_NOSYNC the MDBX_NOSYNC flag similarly disable flush - * system buffers to disk when committing a transaction. But there is a - * huge difference in how are recycled the MVCC snapshots corresponding - * to previous "steady" transactions (see below). - * - * Depending on the platform and hardware, with MDBX_NOSYNC you may get - * a multiple increase of write performance, even 10 times or more. - * NOTE that (MDBX_NOSYNC | MDBX_WRITEMAP) leaves the system with no hint - * for when to write transactions to disk. Therefore the (MDBX_MAPASYNC | - * MDBX_WRITEMAP) may be preferable, but without MDBX_NOSYNC because - * the (MDBX_MAPASYNC | MDBX_NOSYNC) actually gives MDBX_UTTERLY_NOSYNC. - * - * In contrast to MDBX_UTTERLY_NOSYNC mode, with MDBX_NOSYNC flag MDBX will - * keeps untouched pages within B-tree of the last transaction "steady" - * which was synced to disk completely. This has big implications for both - * data durability and (unfortunately) performance: - * - a system crash can't corrupt the database, but you will lose the - * last transactions; because MDBX will rollback to last steady commit - * since it kept explicitly. - * - the last steady transaction makes an effect similar to "long-lived" - * read transaction (see above in the "RESTRICTIONS & CAVEATS" section) - * since prevents reuse of pages freed by newer write transactions, - * thus the any data changes will be placed in newly allocated pages. - * - to avoid rapid database growth, the system will sync data and issue - * a steady commit-point to resume reuse pages, each time there is - * insufficient space and before increasing the size of the file on - * disk. - * - * In other words, with MDBX_NOSYNC flag MDBX insures you from the whole - * database corruption, at the cost increasing database size and/or number - * of disk IOPS. So, MDBX_NOSYNC flag could be used with mdbx_env_synv() - * as alternatively for batch committing or nested transaction (in some - * cases). As well, auto-sync feature exposed by mdbx_env_set_syncbytes() - * and mdbx_env_set_syncperiod() functions could be very usefull with - * MDBX_NOSYNC flag. - * - * The number and volume of of disk IOPS with MDBX_NOSYNC flag will - * exactly the as without any no-sync flags. However, you should expect - * a larger process's work set (https://bit.ly/2kA2tFX) and significantly - * worse a locality of reference (https://bit.ly/2mbYq2J), due to the - * more intensive allocation of previously unused pages and increase the - * size of the database. - * - * MDBX_NOSYNC flag may be changed at any time using - * mdbx_env_set_flags() or by passing to mdbx_txn_begin() for particular - * write transaction. - * - * - * MDBX_MAPASYNC = use asynchronous msync when MDBX_WRITEMAP is used. - * - * MDBX_MAPASYNC meaningful and give effect only in conjunction - * with MDBX_WRITEMAP or MDBX_NOSYNC: - * - with MDBX_NOSYNC actually gives MDBX_UTTERLY_NOSYNC, which - * wipe previous steady commits for reuse pages as described above. - * - with MDBX_WRITEMAP but without MDBX_NOSYNC instructs MDBX to use - * asynchronous mmap-flushes to disk as described below. - * - with both MDBX_WRITEMAP and MDBX_NOSYNC you get the both effects. - * - * Asynchronous mmap-flushes means that actually all writes will scheduled - * and performed by operation system on it own manner, i.e. unordered. - * MDBX itself just notify operating system that it would be nice to write - * data to disk, but no more. - * - * With MDBX_MAPASYNC flag, but without MDBX_UTTERLY_NOSYNC (i.e. without - * OR'ing with MDBX_NOSYNC) MDBX will keeps untouched pages within B-tree - * of the last transaction "steady" which was synced to disk completely. - * So, this makes exactly the same "long-lived" impact and the same - * consequences as described above for MDBX_NOSYNC flag. - * - * Depending on the platform and hardware, with combination of - * MDBX_WRITEMAP and MDBX_MAPASYNC you may get a multiple increase of write - * performance, even 25 times or more. MDBX_MAPASYNC flag may be changed at - * any time using mdbx_env_set_flags() or by passing to mdbx_txn_begin() - * for particular write transaction. - */ - -/* Don't sync meta-page after commit, - * see description in the "SYNC MODES" section above. */ -#define MDBX_NOMETASYNC 0x40000u - -/* Don't sync anything but keep previous steady commits, - * see description in the "SYNC MODES" section above. - * - * (!) don't combine this flag with MDBX_MAPASYNC - * since you will got MDBX_UTTERLY_NOSYNC in that way (see below) */ -#define MDBX_NOSYNC 0x10000u - -/* Use asynchronous msync when MDBX_WRITEMAP is used, - * see description in the "SYNC MODES" section above. - * - * (!) don't combine this flag with MDBX_NOSYNC - * since you will got MDBX_UTTERLY_NOSYNC in that way (see below) */ -#define MDBX_MAPASYNC 0x100000u - -/* Don't sync anything and wipe previous steady commits, - * see description in the "SYNC MODES" section above. */ -#define MDBX_UTTERLY_NOSYNC (MDBX_NOSYNC | MDBX_MAPASYNC) - -/**** DATABASE FLAGS **********************************************************/ -/* Use reverse string keys */ -#define MDBX_REVERSEKEY 0x02u -/* Use sorted duplicates */ -#define MDBX_DUPSORT 0x04u -/* Numeric keys in native byte order, either uint32_t or uint64_t. - * The keys must all be of the same size. */ -#define MDBX_INTEGERKEY 0x08u -/* With MDBX_DUPSORT, sorted dup items have fixed size */ -#define MDBX_DUPFIXED 0x10u -/* With MDBX_DUPSORT, dups are MDBX_INTEGERKEY-style integers */ -#define MDBX_INTEGERDUP 0x20u -/* With MDBX_DUPSORT, use reverse string dups */ -#define MDBX_REVERSEDUP 0x40u -/* Create DB if not already existing */ -#define MDBX_CREATE 0x40000u - -/**** DATA UPDATE FLAGS *******************************************************/ -/* For put: Don't write if the key already exists. */ -#define MDBX_NOOVERWRITE 0x10u -/* Only for MDBX_DUPSORT - * For put: don't write if the key and data pair already exist. - * For mdbx_cursor_del: remove all duplicate data items. */ -#define MDBX_NODUPDATA 0x20u -/* For mdbx_cursor_put: overwrite the current key/data pair - * MDBX allows this flag for mdbx_put() for explicit overwrite/update without - * insertion. */ -#define MDBX_CURRENT 0x40u -/* For put: Just reserve space for data, don't copy it. Return a - * pointer to the reserved space. */ -#define MDBX_RESERVE 0x10000u -/* Data is being appended, don't split full pages. */ -#define MDBX_APPEND 0x20000u -/* Duplicate data is being appended, don't split full pages. */ -#define MDBX_APPENDDUP 0x40000u -/* Store multiple data items in one call. Only for MDBX_DUPFIXED. */ -#define MDBX_MULTIPLE 0x80000u - -/**** TRANSACTION FLAGS *******************************************************/ -/* Do not block when starting a write transaction */ -#define MDBX_TRYTXN 0x10000000u - -/**** ENVIRONMENT COPY FLAGS **************************************************/ -/* Compacting: Omit free space from copy, and renumber all pages sequentially */ -#define MDBX_CP_COMPACT 1u - -/**** CURSOR OPERATIONS ******************************************************** - * - * This is the set of all operations for retrieving data - * using a cursor. */ -typedef enum MDBX_cursor_op { - MDBX_FIRST, /* Position at first key/data item */ - MDBX_FIRST_DUP, /* MDBX_DUPSORT-only: Position at first data item - * of current key. */ - MDBX_GET_BOTH, /* MDBX_DUPSORT-only: Position at key/data pair. */ - MDBX_GET_BOTH_RANGE, /* MDBX_DUPSORT-only: position at key, nearest data. */ - MDBX_GET_CURRENT, /* Return key/data at current cursor position */ - MDBX_GET_MULTIPLE, /* MDBX_DUPFIXED-only: Return up to a page of duplicate - * data items from current cursor position. - * Move cursor to prepare for MDBX_NEXT_MULTIPLE. */ - MDBX_LAST, /* Position at last key/data item */ - MDBX_LAST_DUP, /* MDBX_DUPSORT-only: Position at last data item - * of current key. */ - MDBX_NEXT, /* Position at next data item */ - MDBX_NEXT_DUP, /* MDBX_DUPSORT-only: Position at next data item - * of current key. */ - MDBX_NEXT_MULTIPLE, /* MDBX_DUPFIXED-only: Return up to a page of - * duplicate data items from next cursor position. - * Move cursor to prepare for MDBX_NEXT_MULTIPLE. */ - MDBX_NEXT_NODUP, /* Position at first data item of next key */ - MDBX_PREV, /* Position at previous data item */ - MDBX_PREV_DUP, /* MDBX_DUPSORT-only: Position at previous data item - * of current key. */ - MDBX_PREV_NODUP, /* Position at last data item of previous key */ - MDBX_SET, /* Position at specified key */ - MDBX_SET_KEY, /* Position at specified key, return both key and data */ - MDBX_SET_RANGE, /* Position at first key greater than or equal to - * specified key. */ - MDBX_PREV_MULTIPLE /* MDBX_DUPFIXED-only: Position at previous page and - * return up to a page of duplicate data items. */ -} MDBX_cursor_op; - -/**** ERRORS & RETURN CODES **************************************************** - * BerkeleyDB uses -30800 to -30999, we'll go under them */ - -/* Successful result */ -#define MDBX_SUCCESS 0 -#define MDBX_RESULT_FALSE MDBX_SUCCESS -/* Successful result with special meaning or a flag */ -#define MDBX_RESULT_TRUE (-1) - -/* key/data pair already exists */ -#define MDBX_KEYEXIST (-30799) -/* key/data pair not found (EOF) */ -#define MDBX_NOTFOUND (-30798) -/* Requested page not found - this usually indicates corruption */ -#define MDBX_PAGE_NOTFOUND (-30797) -/* Database is corrupted (page was wrong type and so on) */ -#define MDBX_CORRUPTED (-30796) -/* Environment had fatal error (i.e. update of meta page failed and so on) */ -#define MDBX_PANIC (-30795) -/* DB file version mismatch with libmdbx */ -#define MDBX_VERSION_MISMATCH (-30794) -/* File is not a valid MDBX file */ -#define MDBX_INVALID (-30793) -/* Environment mapsize reached */ -#define MDBX_MAP_FULL (-30792) -/* Environment maxdbs reached */ -#define MDBX_DBS_FULL (-30791) -/* Environment maxreaders reached */ -#define MDBX_READERS_FULL (-30790) -/* Txn has too many dirty pages */ -#define MDBX_TXN_FULL (-30788) -/* Cursor stack too deep - internal error */ -#define MDBX_CURSOR_FULL (-30787) -/* Page has not enough space - internal error */ -#define MDBX_PAGE_FULL (-30786) -/* Database contents grew beyond environment mapsize */ -#define MDBX_MAP_RESIZED (-30785) -/* Operation and DB incompatible, or DB type changed. This can mean: - * - The operation expects an MDBX_DUPSORT / MDBX_DUPFIXED database. - * - Opening a named DB when the unnamed DB has MDBX_DUPSORT/MDBX_INTEGERKEY. - * - Accessing a data record as a database, or vice versa. - * - The database was dropped and recreated with different flags. */ -#define MDBX_INCOMPATIBLE (-30784) -/* Invalid reuse of reader locktable slot */ -#define MDBX_BAD_RSLOT (-30783) -/* Transaction must abort, has a child, or is invalid */ -#define MDBX_BAD_TXN (-30782) -/* Unsupported size of key/DB name/data, or wrong DUPFIXED size */ -#define MDBX_BAD_VALSIZE (-30781) -/* The specified DBI was changed unexpectedly */ -#define MDBX_BAD_DBI (-30780) -/* Unexpected problem - txn should abort */ -#define MDBX_PROBLEM (-30779) -/* Another write transaction is running or environment is already used while - * opening with MDBX_EXCLUSIVE flag */ -#define MDBX_BUSY (-30778) -/* The last defined error code */ -#define MDBX_LAST_ERRCODE MDBX_BUSY - -/* The mdbx_put() or mdbx_replace() was called for key, - * that has more that one associated value. */ -#define MDBX_EMULTIVAL (-30421) - -/* Bad signature of a runtime object(s), this can mean: - * - memory corruption or double-free; - * - ABI version mismatch (rare case); */ -#define MDBX_EBADSIGN (-30420) - -/* Database should be recovered, but this could NOT be done automatically - * right now (e.g. in readonly mode and so forth). */ -#define MDBX_WANNA_RECOVERY (-30419) - -/* The given key value is mismatched to the current cursor position, - * when mdbx_cursor_put() called with MDBX_CURRENT option. */ -#define MDBX_EKEYMISMATCH (-30418) - -/* Database is too large for current system, - * e.g. could NOT be mapped into RAM. */ -#define MDBX_TOO_LARGE (-30417) - -/* A thread has attempted to use a not owned object, - * e.g. a transaction that started by another thread. */ -#define MDBX_THREAD_MISMATCH (-30416) - -/**** FUNCTIONS & RELATED STRUCTURES ******************************************/ - -/* Return a string describing a given error code. - * - * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3) - * function. If the error code is greater than or equal to 0, then the string - * returned by the system function strerror(3) is returned. If the error code - * is less than 0, an error string corresponding to the MDBX library error is - * returned. See errors for a list of MDBX-specific error codes. - * - * mdbx_strerror() - is NOT thread-safe because may share common internal - * buffer for system maessages. The returned string must - * NOT be modified by the application, but MAY be modified - * by a subsequent call to mdbx_strerror(), strerror() and - * other related functions. - * - * mdbx_strerror_r() - is thread-safe since uses user-supplied buffer where - * appropriate. The returned string must NOT be modified - * by the application, since it may be pointer to internal - * constatn string. However, there is no restriction if the - * returned string points to the supplied buffer. - * - * [in] err The error code. - * - * Returns "error message" The description of the error. */ -LIBMDBX_API const char *mdbx_strerror(int errnum); -LIBMDBX_API const char *mdbx_strerror_r(int errnum, char *buf, size_t buflen); - -#if defined(_WIN32) || defined(_WIN64) -/* Bit of Windows' madness. The similar functions but returns Windows - * error-messages in the OEM-encoding for console utilities. */ -LIBMDBX_API const char *mdbx_strerror_ANSI2OEM(int errnum); -LIBMDBX_API const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, - size_t buflen); -#endif /* Bit of Windows' madness */ - -/* Create an MDBX environment instance. - * - * This function allocates memory for a MDBX_env structure. To release - * the allocated memory and discard the handle, call mdbx_env_close(). - * Before the handle may be used, it must be opened using mdbx_env_open(). - * - * Various other options may also need to be set before opening the handle, - * e.g. mdbx_env_set_geometry(), mdbx_env_set_maxreaders(), - * mdbx_env_set_maxdbs(), depending on usage requirements. - * - * [out] env The address where the new handle will be stored. - * - * Returns a non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_create(MDBX_env **penv); - -/* Open an environment instance. - * - * Indifferently this function will fails or not, the mdbx_env_close() must be - * called later to discard the MDBX_env handle and release associated resources. - * - * [in] env An environment handle returned by mdbx_env_create() - * [in] pathname The directory in which the database files reside. - * This directory must already exist and be writable. - * [in] flags Special options for this environment. This parameter - * must be set to 0 or by bitwise OR'ing together one - * or more of the values described above in the - * "ENVIRONMENT FLAGS" and "SYNC MODES" sections. - * - * Flags set by mdbx_env_set_flags() are also used: - * - MDBX_NOSUBDIR, MDBX_RDONLY, MDBX_EXCLUSIVE, MDBX_WRITEMAP, MDBX_NOTLS, - * MDBX_NORDAHEAD, MDBX_NOMEMINIT, MDBX_COALESCE, MDBX_LIFORECLAIM. - * See "ENVIRONMENT FLAGS" section above. - * - * - MDBX_NOMETASYNC, MDBX_NOSYNC, MDBX_UTTERLY_NOSYNC, MDBX_MAPASYNC. - * See "SYNC MODES" section above. - * - * NOTE: MDB_NOLOCK flag don't supported by MDBX, - * try use MDBX_EXCLUSIVE as a replacement. - * - * NOTE: MDBX don't allow to mix processes with different MDBX_WRITEMAP, - * MDBX_NOSYNC, MDBX_NOMETASYNC, MDBX_MAPASYNC flags onthe same - * environment. In such case MDBX_INCOMPATIBLE will be returned. - * - * If the database is already exist and parameters specified early by - * mdbx_env_set_geometry() are incompatible (i.e. for instance, different page - * size) then mdbx_env_open() will return MDBX_INCOMPATIBLE error. - * - * [in] mode The UNIX permissions to set on created files. Zero value means - * to open existing, but do not create. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_VERSION_MISMATCH = the version of the MDBX library doesn't match the - * version that created the database environment. - * - MDBX_INVALID = the environment file headers are corrupted. - * - MDBX_ENOENT = the directory specified by the path parameter - * doesn't exist. - * - MDBX_EACCES = the user didn't have permission to access - * the environment files. - * - MDBX_EAGAIN = the environment was locked by another process. - * - MDBX_BUSY = MDBX_EXCLUSIVE flag was specified and the - * environment is in use by another process, - * or the current process tries to open environment - * more than once. - * - MDBX_INCOMPATIBLE = Environment is already opened by another process, - * but with different set of MDBX_WRITEMAP, - * MDBX_NOSYNC, MDBX_NOMETASYNC, MDBX_MAPASYNC - * flags. - * Or if the database is already exist and - * parameters specified early by - * mdbx_env_set_geometry() are incompatible (i.e. - * for instance, different page size). - * - MDBX_WANNA_RECOVERY = MDBX_RDONLY flag was specified but read-write - * access is required to rollback inconsistent state - * after a system crash. - * - MDBX_TOO_LARGE = Database is too large for this process, i.e. - * 32-bit process tries to open >4Gb database. */ -LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *pathname, - unsigned flags, mode_t mode); - -/* Copy an MDBX environment to the specified path, with options. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. - * NOTE: This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under "Caveats" section. - * - * [in] env An environment handle returned by mdbx_env_create(). It must - * have already been opened successfully. - * [in] dest The directory in which the copy will reside. This directory - * must already exist and be writable but must otherwise be empty. - * [in] flags Special options for this operation. This parameter must be set - * to 0 or by bitwise OR'ing together one or more of the values - * described here: - * - * - MDBX_CP_COMPACT - * Perform compaction while copying: omit free pages and sequentially - * renumber all pages in output. This option consumes little bit more - * CPU for processing, but may running quickly than the default, on - * account skipping free pages. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_copy(MDBX_env *env, const char *dest, unsigned flags); - -/* Copy an MDBX environment to the specified file descriptor, - * with options. - * - * This function may be used to make a backup of an existing environment. - * No lockfile is created, since it gets recreated at need. See - * mdbx_env_copy() for further details. - * - * NOTE: This call can trigger significant file size growth if run in - * parallel with write transactions, because it employs a read-only - * transaction. See long-lived transactions under "Caveats" section. - * - * NOTE: Fails if the environment has suffered a page leak and the destination - * file descriptor is associated with a pipe, socket, or FIFO. - * - * [in] env An environment handle returned by mdbx_env_create(). It must - * have already been opened successfully. - * [in] fd The filedescriptor to write the copy to. It must have already - * been opened for Write access. - * [in] flags Special options for this operation. See mdbx_env_copy() for - * options. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd, - unsigned flags); - -/* Statistics for a database in the environment */ -typedef struct MDBX_stat { - uint32_t ms_psize; /* Size of a database page. - * This is the same for all databases. */ - uint32_t ms_depth; /* Depth (height) of the B-tree */ - uint64_t ms_branch_pages; /* Number of internal (non-leaf) pages */ - uint64_t ms_leaf_pages; /* Number of leaf pages */ - uint64_t ms_overflow_pages; /* Number of overflow pages */ - uint64_t ms_entries; /* Number of data items */ - uint64_t ms_mod_txnid; /* Transaction ID of commited last modification */ -} MDBX_stat; - -/* Return statistics about the MDBX environment. - * - * At least one of env or txn argument must be non-null. If txn is passed - * non-null then stat will be filled accordingly to the given transaction. - * Otherwise, if txn is null, then stat will be populated by a snapshot from the - * last committed write transaction, and at next time, other information can be - * returned. - * - * Legacy mdbx_env_stat() correspond to calling mdbx_env_stat_ex() with the null - * txn argument. - * - * [in] env An environment handle returned by mdbx_env_create() - * [in] txn A transaction handle returned by mdbx_txn_begin() - * [out] stat The address of an MDBX_stat structure where the statistics - * will be copied - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_stat_ex(const MDBX_env *env, const MDBX_txn *txn, - MDBX_stat *stat, size_t bytes); -LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes); - -/* Information about the environment */ -typedef struct MDBX_envinfo { - struct { - uint64_t lower; /* lower limit for datafile size */ - uint64_t upper; /* upper limit for datafile size */ - uint64_t current; /* current datafile size */ - uint64_t shrink; /* shrink threshold for datafile */ - uint64_t grow; /* growth step for datafile */ - } mi_geo; - uint64_t mi_mapsize; /* Size of the data memory map */ - uint64_t mi_last_pgno; /* ID of the last used page */ - uint64_t mi_recent_txnid; /* ID of the last committed transaction */ - uint64_t mi_latter_reader_txnid; /* ID of the last reader transaction */ - uint64_t mi_self_latter_reader_txnid; /* ID of the last reader transaction of - caller process */ - uint64_t mi_meta0_txnid, mi_meta0_sign; - uint64_t mi_meta1_txnid, mi_meta1_sign; - uint64_t mi_meta2_txnid, mi_meta2_sign; - uint32_t mi_maxreaders; /* max reader slots in the environment */ - uint32_t mi_numreaders; /* max reader slots used in the environment */ - uint32_t mi_dxb_pagesize; /* database pagesize */ - uint32_t mi_sys_pagesize; /* system pagesize */ - - uint64_t - mi_bootid[2]; /* A mostly unique ID that is regenerated on each boot. - As such it can be used to identify the local - machine's current boot. MDBX uses such when open - the database to determine whether rollback required - to the last steady sync point or not. I.e. if current - bootid is differ from the value within a database then - the system was rebooted and all changes since last steady - sync must be reverted for data integrity. Zeros mean that - no relevant information is available from the system. */ - uint64_t mi_unsync_volume; /* bytes not explicitly synchronized to disk */ - uint64_t mi_autosync_threshold; /* current auto-sync threshold, see - mdbx_env_set_syncbytes(). */ - uint32_t mi_since_sync_seconds16dot16; /* time since the last steady sync in - 1/65536 of second */ - uint32_t mi_autosync_period_seconds16dot16 /* current auto-sync period in - 1/65536 of second, see - mdbx_env_set_syncperiod(). */ - ; - uint32_t mi_since_reader_check_seconds16dot16; /* time since the last readers - check in 1/65536 of second, - see mdbx_reader_check(). */ - uint32_t mi_mode; /* current environment mode, the same as - mdbx_env_get_flags() returns. */ -} MDBX_envinfo; - -/* Return information about the MDBX environment. - * - * At least one of env or txn argument must be non-null. If txn is passed - * non-null then stat will be filled accordingly to the given transaction. - * Otherwise, if txn is null, then stat will be populated by a snapshot from the - * last committed write transaction, and at next time, other information can be - * returned. - * - * Legacy mdbx_env_info() correspond to calling mdbx_env_info_ex() with the null - * txn argument. - - * [in] env An environment handle returned by mdbx_env_create() - * [in] txn A transaction handle returned by mdbx_txn_begin() - * [out] stat The address of an MDBX_envinfo structure - * where the information will be copied - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, - MDBX_envinfo *info, size_t bytes); -LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info, size_t bytes); - -/* Flush the environment data buffers to disk. - * - * Unless the environment was opened with no-sync flags (MDBX_NOMETASYNC, - * MDBX_NOSYNC, MDBX_UTTERLY_NOSYNC and MDBX_MAPASYNC), then data is always - * written an flushed to disk when mdbx_txn_commit() is called. Otherwise - * mdbx_env_sync() may be called to manually write and flush unsynced data to - * disk. - * - * Besides, mdbx_env_sync_ex() with argument force=false may be used to - * provide polling mode for lazy/asynchronous sync in conjunction with - * mdbx_env_set_syncbytes() and/or mdbx_env_set_syncperiod(). - * - * The mdbx_env_sync() is shortcut to calling mdbx_env_sync_ex() with - * try force=true and nonblock=false arguments. - * - * The mdbx_env_sync_poll() is shortcut to calling mdbx_env_sync_ex() with - * the force=false and nonblock=true arguments. - * - * NOTE: This call is not valid if the environment was opened with MDBX_RDONLY. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] force If non-zero, force a flush. Otherwise, if force is zero, then - * will run in polling mode, i.e. it will check the thresholds - * that were set mdbx_env_set_syncbytes() and/or - * mdbx_env_set_syncperiod() and perform flush If at least one - * of the thresholds is reached. - * [in] nonblock Don't wait if write transaction is running by other thread. - * - * Returns A non-zero error value on failure and MDBX_RESULT_TRUE or 0 on - * success. The MDBX_RESULT_TRUE means no data pending for flush to disk, - * and 0 otherwise. Some possible errors are: - * - MDBX_EACCES = the environment is read-only. - * - MDBX_BUSY = the environment is used by other thread and nonblock=true. - * - MDBX_EINVAL = an invalid parameter was specified. - * - MDBX_EIO = an error occurred during synchronization. */ -LIBMDBX_API int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock); -LIBMDBX_API int mdbx_env_sync(MDBX_env *env); -LIBMDBX_API int mdbx_env_sync_poll(MDBX_env *env); - -/* Sets threshold to force flush the data buffers to disk, even of MDBX_NOSYNC, - * MDBX_NOMETASYNC and MDBX_MAPASYNC flags in the environment. The threshold - * value affects all processes which operates with given environment until the - * last process close environment or a new value will be settled. - * - * Data is always written to disk when mdbx_txn_commit() is called, but the - * operating system may keep it buffered. MDBX always flushes the OS buffers - * upon commit as well, unless the environment was opened with MDBX_NOSYNC, - * MDBX_MAPASYNC or in part MDBX_NOMETASYNC. - * - * The default is 0, than mean no any threshold checked, and no additional - * flush will be made. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] threshold The size in bytes of summary changes when a synchronous - * flush would be made. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold); - -/* Sets relative period since the last unsteay commit to force flush the data - * buffers to disk, even of MDBX_NOSYNC, MDBX_NOMETASYNC and MDBX_MAPASYNC flags - * in the environment. The relative period value affects all processes which - * operates with given environment until the last process close environment or a - * new value will be settled. - * - * Data is always written to disk when mdbx_txn_commit() is called, but the - * operating system may keep it buffered. MDBX always flushes the OS buffers - * upon commit as well, unless the environment was opened with MDBX_NOSYNC, - * MDBX_MAPASYNC or in part MDBX_NOMETASYNC. - * - * Settled period don't checked asynchronously, but only by the - * mdbx_txn_commit() and mdbx_env_sync() functions. Therefore, in cases where - * transactions are committed infrequently and/or irregularly, polling by - * mdbx_env_sync() may be a reasonable solution to timeout enforcement. - * - * The default is 0, than mean no any timeout checked, and no additional - * flush will be made. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] seconds_16dot16 The period in 1/65536 of second when a synchronous - * flush would be made since the last unsteay commit. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_syncperiod(MDBX_env *env, - unsigned seconds_16dot16); - -/* Close the environment and release the memory map. - * - * Only a single thread may call this function. All transactions, databases, - * and cursors must already be closed before calling this function. Attempts - * to use any such handles after calling this function will cause a SIGSEGV. - * The environment handle will be freed and must not be used again after this - * call. - * - * Legacy mdbx_env_close() correspond to calling mdbx_env_close_ex() with the - * argument dont_sync=false. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] dont_sync A dont'sync flag, if non-zero the last checkpoint (meta-page - * update) will be kept "as is" and may be still "weak" in the - * NOSYNC/MAPASYNC modes. Such "weak" checkpoint will be - * ignored on opening next time, and transactions since the - * last non-weak checkpoint (meta-page update) will rolledback - * for consistency guarantee. - * - * Returns A non-zero error value on failure and 0 on success. - * Some possible errors are: - * - MDBX_BUSY = The write transaction is running by other thread, in such - * case MDBX_env instance has NOT be destroyed not released! - * NOTE: if any OTHER error code was returned then given - * MDBX_env instance has been destroyed and released. - * - MDBX_PANIC = If mdbx_env_close_ex() was called in the child process - * after fork(). In this case MDBX_PANIC is a expecte, - * i.e. MDBX_env instance was freed in proper manner. - * - MDBX_EIO = an error occurred during synchronization. */ -LIBMDBX_API int mdbx_env_close_ex(MDBX_env *env, int dont_sync); -LIBMDBX_API int mdbx_env_close(MDBX_env *env); - -/* Set environment flags. - * - * This may be used to set some flags in addition to those from - * mdbx_env_open(), or to unset these flags. - * - * NOTE: In contrast to LMDB, the MDBX serialize threads via mutex while - * changing the flags. Therefore this function will be blocked while a write - * transaction running by other thread, or MDBX_BUSY will be returned if - * function called within a write transaction. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] flags The flags to change, bitwise OR'ed together. - * [in] onoff A non-zero value sets the flags, zero clears them. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff); - -/* Get environment flags. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [out] flags The address of an integer to store the flags. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_flags(MDBX_env *env, unsigned *flags); - -/* Return the path that was used in mdbx_env_open(). - * - * [in] env An environment handle returned by mdbx_env_create() - * [out] dest Address of a string pointer to contain the path. - * This is the actual string in the environment, not a copy. - * It should not be altered in any way. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_path(MDBX_env *env, const char **dest); - -/* Return the file descriptor for the given environment. - * - * NOTE: All MDBX file descriptors have FD_CLOEXEC and - * could't be used after exec() and or fork(). - * - * [in] env An environment handle returned by mdbx_env_create(). - * [out] fd Address of a int to contain the descriptor. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd); - -/* Set all size-related parameters of environment, including page size and the - * min/max size of the memory map. - * - * In contrast to LMDB, the MDBX provide automatic size management of an - * database according the given parameters, including shrinking and resizing - * on the fly. From user point of view all of these just working. Nevertheless, - * it is reasonable to know some details in order to make optimal decisions when - * choosing parameters. - * - * Both mdbx_env_info_ex() and legacy mdbx_env_info() are inapplicable to - * read-only opened environment. - * - * Both mdbx_env_info_ex() and legacy mdbx_env_info() could be called either - * before or after mdbx_env_open(), either within the write transaction running - * by current thread or not: - * - * - In case mdbx_env_info_ex() or legacy mdbx_env_info() was called BEFORE - * mdbx_env_open(), i.e. for closed environment, then the specified - * parameters will be used for new database creation, or will be appliend - * during openeing if database exists and no other process using it. - * - * If the database is already exist, opened with MDBX_EXCLUSIVE or not used - * by any other process, and parameters specified by mdbx_env_set_geometry() - * are incompatible (i.e. for instance, different page size) then - * mdbx_env_open() will return MDBX_INCOMPATIBLE error. - * - * In another way, if database will opened read-only or will used by other - * process during calling mdbx_env_open() that specified parameters will - * silently discarded (open the database with MDBX_EXCLUSIVE flag to avoid - * this). - * - * - In case mdbx_env_info_ex() or legacy mdbx_env_info() was called after - * mdbx_env_open() WITHIN the write transaction running by current thread, - * then specified parameters will be appliad as a part of write transaction, - * i.e. will not be visible to any others processes until the current write - * transaction has been committed by the current process. However, if - * transaction will be aborted, then the database file will be reverted to - * the previous size not immediately, but when a next transaction will be - * committed or when the database will be opened next time. - * - * - In case mdbx_env_info_ex() or legacy mdbx_env_info() was called after - * mdbx_env_open() but OUTSIDE a write transaction, then MDBX will execute - * internal pseudo-transaction to apply new parameters (but only if anything - * has been changed), and changes be visible to any others processes - * immediatelly after succesfull competeion of function. - * - * Essentially a concept of "automatic size management" is simple and useful: - * - There are the lower and upper bound of the database file size; - * - There is the growth step by which the database file will be increased, - * in case of lack of space. - * - There is the threshold for unused space, beyond which the database file - * will be shrunk. - * - The size of the memory map is also the maximum size of the database. - * - MDBX will automatically manage both the size of the database and the size - * of memory map, according to the given parameters. - * - * So, there some considerations about choosing these parameters: - * - The lower bound allows you to prevent database shrinking below some - * rational size to avoid unnecessary resizing costs. - * - The upper bound allows you to prevent database growth above some rational - * size. Besides, the upper bound defines the linear address space - * reservation in each process that opens the database. Therefore changing - * the upper bound is costly and may be required reopening environment in - * case of MDBX_MAP_RESIZED errors, and so on. Therefore, this value should - * be chosen reasonable as large as possible, to accommodate future growth - * of the database. - * - The growth step must be greater than zero to allow the database to grow, - * but also reasonable not too small, since increasing the size by little - * steps will result a large overhead. - * - The shrink threshold must be greater than zero to allow the database - * to shrink but also reasonable not too small (to avoid extra overhead) and - * not less than growth step to avoid up-and-down flouncing. - * - The current size (i.e. size_now argument) is an auxiliary parameter for - * simulation legacy mdbx_env_set_mapsize() and as workaround Windows issues - * (see below). - * - * Unfortunately, Windows has is a several issues - * with resizing of memory-mapped file: - * - Windows unable shrinking a memory-mapped file (i.e memory-mapped section) - * in any way except unmapping file entirely and then map again. Moreover, - * it is impossible in any way if a memory-mapped file is used more than - * one process. - * - Windows does not provide the usual API to augment a memory-mapped file - * (that is, a memory-mapped partition), but only by using "Native API" - * in an undocumented way. - * MDBX bypasses all Windows issues, but at a cost: - * - Ability to resize database on the fly requires an additional lock - * and release SlimReadWriteLock during each read-only transaction. - * - During resize all in-process threads should be paused and then resumed. - * - Shrinking of database file is performed only when it used by single - * process, i.e. when a database closes by the last process or opened - * by the first. - * = Therefore, the size_now argument may be useful to set database size - * by the first process which open a database, and thus avoid expensive - * remapping further. - * - * For create a new database with particular parameters, including the page - * size, mdbx_env_set_geometry() should be called after mdbx_env_create() and - * before mdbx_env_open(). Once the database is created, the page size cannot be - * changed. If you do not specify all or some of the parameters, the - * corresponding default values will be used. For instance, the default for - * database size is 10485760 bytes. - * - * If the mapsize is increased by another process, MDBX silently and - * transparently adopt these changes at next transaction start. However, - * mdbx_txn_begin() will return MDBX_MAP_RESIZED if new mapping size could not - * be applied for current process (for instance if address space is busy). - * Therefore, in the case of MDBX_MAP_RESIZED error you need close and reopen - * the environment to resolve error. - * - * NOTE: Actual values may be different than your have specified because of - * rounding to specified database page size, the system page size and/or the - * size of the system virtual memory management unit. You can get actual values - * by mdbx_env_sync_ex() or see by using the tool "mdbx_chk" with the "-v" - * option. - * - * Legacy mdbx_env_set_mapsize() correspond to calling mdbx_env_set_geometry() - * with the arguments size_lower, size_now, size_upper equal to the size - * and -1 (i.e. default) for all other parameters. - * - * [in] env An environment handle returned by mdbx_env_create() - * - * [in] size_lower The lower bound of database sive in bytes. - * Zero value means "minimal acceptable", - * and negative means "keep current or use default". - * - * [in] size_now The size in bytes to setup the database size for now. - * Zero value means "minimal acceptable", - * and negative means "keep current or use default". - * So, it is recommended always pass -1 in this argument - * except some special cases. - * - * [in] size_upper The upper bound of database sive in bytes. - * Zero value means "minimal acceptable", - * and negative means "keep current or use default". - * It is recommended to avoid change upper bound while - * database is used by other processes or threaded - * (i.e. just pass -1 in this argument except absolutely - * necessity). Otherwise you must be ready for - * MDBX_MAP_RESIZED error(s), unexpected pauses during - * remapping and/or system errors like "addtress busy", - * and so on. In other words, there is no way to handle - * a growth of the upper bound robustly because there may - * be a lack of appropriate system resources (which are - * extremely volatile in a multi-process multi-threaded - * environment). - * - * [in] growth_step The growth step in bytes, must be greater than zero - * to allow the database to grow. - * Negative value means "keep current or use default". - * - * [in] shrink_threshold The shrink threshold in bytes, must be greater than - * zero to allow the database to shrink. - * Negative value means "keep current or use default". - * - * [in] pagesize The database page size for new database creation - * or -1 otherwise. Must be power of 2 in the range - * between MDBX_MIN_PAGESIZE and MDBX_MAX_PAGESIZE. - * Zero value means "minimal acceptable", - * and negative means "keep current or use default". - * - * Returns A non-zero error value on failure and 0 on success, - * some possible errors are: - * - MDBX_EINVAL = An invalid parameter was specified, - * or the environment has an active write transaction. - * - MDBX_EPERM = specific for Windows: Shrinking was disabled before and - * now it wanna be enabled, but there are reading threads - * that don't use the additional SRWL (that is required to - * avoid Windows issues). - * - MDBX_EACCESS = The environment opened in read-only. - * - MDBX_MAP_FULL = Specified size smaller than the space already - * consumed by the environment. - * - MDBX_TOO_LARGE = Specified size is too large, i.e. too many pages for - * given size, or a 32-bit process requests too much bytes - * for the 32-bit address space. */ -LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, - intptr_t size_now, intptr_t size_upper, - intptr_t growth_step, - intptr_t shrink_threshold, - intptr_t pagesize); -LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env, size_t size); - -/* Find out whether to use readahead or not, based on the given database size - * and the amount of available memory. - * - * [in] volume The expected database size in bytes. - * [in] redundancy Additional reserve or overload in case of negative value. - * - * Returns: - * - MDBX_RESULT_TRUE = readahead is reasonable. - * - MDBX_RESULT_FALSE = readahead is NOT reasonable, i.e. MDBX_NORDAHEAD - * is useful to open environment by mdbx_env_open(). - * - Otherwise the error code. */ -LIBMDBX_API int mdbx_is_readahead_reasonable(size_t volume, - intptr_t redundancy); - -/* The minimal database page size in bytes. */ -#define MDBX_MIN_PAGESIZE 256 -__inline intptr_t mdbx_limits_pgsize_min(void) { return MDBX_MIN_PAGESIZE; } - -/* The maximal database page size in bytes. */ -#define MDBX_MAX_PAGESIZE 65536 -__inline intptr_t mdbx_limits_pgsize_max(void) { return MDBX_MAX_PAGESIZE; } - -/* Returns minimal database size in bytes for given page size, - * or the negative error code. */ -LIBMDBX_API intptr_t mdbx_limits_dbsize_min(intptr_t pagesize); - -/* Returns maximal database size in bytes for given page size, - * or the negative error code. */ -LIBMDBX_API intptr_t mdbx_limits_dbsize_max(intptr_t pagesize); - -/* Returns maximal key size in bytes for given page size, - * or the negative error code. */ -LIBMDBX_API intptr_t mdbx_limits_keysize_max(intptr_t pagesize); - -/* Returns maximal write transaction size (i.e. limit for summary volume of - * dirty pages) in bytes for given page size, or the negative error code. */ -LIBMDBX_API intptr_t mdbx_limits_txnsize_max(intptr_t pagesize); - -/* Set the maximum number of threads/reader slots for the environment. - * - * This defines the number of slots in the lock table that is used to track - * readers in the the environment. The default is 119 for 4K system page size. - * Starting a read-only transaction normally ties a lock table slot to the - * current thread until the environment closes or the thread exits. If - * MDBX_NOTLS is in use, mdbx_txn_begin() instead ties the slot to the - * MDBX_txn object until it or the MDBX_env object is destroyed. - * This function may only be called after mdbx_env_create() and before - * mdbx_env_open(). - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] readers The maximum number of reader lock table slots. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. - * - MDBX_EPERM = the environment is already open. */ -LIBMDBX_API int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers); - -/* Get the maximum number of threads/reader slots for the environment. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [out] readers Address of an integer to store the number of readers. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers); - -/* Set the maximum number of named databases for the environment. - * - * This function is only needed if multiple databases will be used in the - * environment. Simpler applications that use the environment as a single - * unnamed database can ignore this option. - * This function may only be called after mdbx_env_create() and before - * mdbx_env_open(). - * - * Currently a moderate number of slots are cheap but a huge number gets - * expensive: 7-120 words per transaction, and every mdbx_dbi_open() - * does a linear search of the opened slots. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] dbs The maximum number of databases. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. - * - MDBX_EPERM = the environment is already open. */ -LIBMDBX_API int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs); - -/* Get the maximum size of keys and MDBX_DUPSORT data we can write. - * - * [in] env An environment handle returned by mdbx_env_create(). - * - * Returns The maximum size of a key we can write. */ -LIBMDBX_API int mdbx_env_get_maxkeysize(MDBX_env *env); - -/* Set application information associated with the MDBX_env. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] ctx An arbitrary pointer for whatever the application needs. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_userctx(MDBX_env *env, void *ctx); - -/* Get the application information associated with the MDBX_env. - * - * [in] env An environment handle returned by mdbx_env_create() - * Returns The pointer set by mdbx_env_set_userctx(). */ -LIBMDBX_API void *mdbx_env_get_userctx(MDBX_env *env); - -/* Create a transaction for use with the environment. - * - * The transaction handle may be discarded using mdbx_txn_abort() - * or mdbx_txn_commit(). - * - * NOTE: A transaction and its cursors must only be used by a single thread, - * and a thread may only have a single transaction at a time. If MDBX_NOTLS is - * in use, this does not apply to read-only transactions. - * - * NOTE: Cursors may not span transactions. - * - * [in] env An environment handle returned by mdbx_env_create() - * [in] parent If this parameter is non-NULL, the new transaction will be - * a nested transaction, with the transaction indicated by parent - * as its parent. Transactions may be nested to any level. - * A parent transaction and its cursors may not issue any other - * operations than mdbx_txn_commit and mdbx_txn_abort while it - * has active child transactions. - * [in] flags Special options for this transaction. This parameter - * must be set to 0 or by bitwise OR'ing together one or more - * of the values described here. - * - * - MDBX_RDONLY - * This transaction will not perform any write operations. - * - * - MDBX_TRYTXN - * Do not block when starting a write transaction. - * - * - MDBX_NOSYNC, MDBX_NOMETASYNC or MDBX_MAPASYNC - * Do not sync data to disk corresponding to MDBX_NOMETASYNC - * or MDBX_NOSYNC description (see abobe). - * - * [out] txn Address where the new MDBX_txn handle will be stored - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_PANIC = a fatal error occurred earlier and the environment - * must be shut down. - * - MDBX_MAP_RESIZED = another process wrote data beyond this MDBX_env's - * mapsize and this environment's map must be resized - * as well. See mdbx_env_set_mapsize(). - * - MDBX_READERS_FULL = a read-only transaction was requested and the reader - * lock table is full. See mdbx_env_set_maxreaders(). - * - MDBX_ENOMEM = out of memory. - * - MDBX_BUSY = the write transaction is already started by the - * current thread. */ -LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags, - MDBX_txn **txn); - -/* Information about the transaction */ -typedef struct MDBX_txn_info { - uint64_t txn_id; /* The ID of the transaction. For a READ-ONLY transaction, - this corresponds to the snapshot being read. */ - - uint64_t - txn_reader_lag; /* For READ-ONLY transaction: the lag from a recent - MVCC-snapshot, i.e. the number of committed - transaction since read transaction started. - For WRITE transaction (provided if scan_rlt=true): the - lag of the oldest reader from current transaction (i.e. - atleast 1 if any reader running). */ - - uint64_t txn_space_used; /* Used space by this transaction, i.e. corresponding - to the last used database page. */ - - uint64_t txn_space_limit_soft; /* Current size of database file. */ - - uint64_t - txn_space_limit_hard; /* Upper bound for size the database file, - i.e. the value "size_upper" argument of the - approriate call of mdbx_env_set_geometry(). */ - - uint64_t txn_space_retired; /* For READ-ONLY transaction: The total size of - the database pages that were retired by - committed write transactions after the reader's - MVCC-snapshot, i.e. the space which would be - freed after the Reader releases the - MVCC-snapshot for reuse by completion read - transaction. - For WRITE transaction: The summarized size of - the database pages that were retired for now - due Copy-On-Write during this transaction. */ - - uint64_t - txn_space_leftover; /* For READ-ONLY transaction: the space available for - writer(s) and that must be exhausted for reason to - call the OOM-killer for this read transaction. - For WRITE transaction: the space inside transaction - that left to MDBX_TXN_FULL error. */ - - uint64_t txn_space_dirty; /* For READ-ONLY transaction (provided if - scan_rlt=true): The space that actually become - available for reuse when only this transaction - will be finished. - For WRITE transaction: The summarized size of the - dirty database pages that generated during this - transaction. */ -} MDBX_txn_info; - -/* Return information about the MDBX transaction. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [out] stat The address of an MDBX_txn_info structure - * where the information will be copied. - * [in[ scan_rlt The boolean flag controls the scan of the read lock table to - * provide complete information. Such scan is relatively - * expensive and you can avoid it if corresponding fields are - * not needed (see description of MDBX_txn_info above). - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_txn_info(MDBX_txn *txn, MDBX_txn_info *info, int scan_rlt); - -/* Returns the transaction's MDBX_env. - * - * [in] txn A transaction handle returned by mdbx_txn_begin() */ -LIBMDBX_API MDBX_env *mdbx_txn_env(MDBX_txn *txn); - -/* Return the transaction's flags. - * - * This returns the flags associated with this transaction. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A transaction flags, valid if input is an valid transaction, - * otherwise -1. */ -LIBMDBX_API int mdbx_txn_flags(MDBX_txn *txn); - -/* Return the transaction's ID. - * - * This returns the identifier associated with this transaction. For a read-only - * transaction, this corresponds to the snapshot being read; concurrent readers - * will frequently have the same transaction ID. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A transaction ID, valid if input is an active transaction, - * otherwise 0. */ -LIBMDBX_API uint64_t mdbx_txn_id(MDBX_txn *txn); - -/* Commit all the operations of a transaction into the database. - * - * The transaction handle is freed. It and its cursors must not be used again - * after this call, except with mdbx_cursor_renew() and mdbx_cursor_close(). - * - * A cursor must be closed explicitly always, before or after its transaction - * ends. It can be reused with mdbx_cursor_renew() before finally closing it. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. - * - MDBX_ENOSPC = no more disk space. - * - MDBX_EIO = a low-level I/O error occurred while writing. - * - MDBX_ENOMEM = out of memory. */ -LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn); - -/* Abandon all the operations of the transaction instead of saving them. - * - * The transaction handle is freed. It and its cursors must not be used again - * after this call, except with mdbx_cursor_renew() and mdbx_cursor_close(). - * - * A cursor must be closed explicitly always, before or after its transaction - * ends. It can be reused with mdbx_cursor_renew() before finally closing it. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_txn_abort(MDBX_txn *txn); - -/* Reset a read-only transaction. - * - * Abort the read-only transaction like mdbx_txn_abort(), but keep the - * transaction handle. Therefore mdbx_txn_renew() may reuse the handle. This - * saves allocation overhead if the process will start a new read-only - * transaction soon, and also locking overhead if MDBX_NOTLS is in use. The - * reader table lock is released, but the table slot stays tied to its thread or - * MDBX_txn. Use mdbx_txn_abort() to discard a reset handle, and to free its - * lock table slot if MDBX_NOTLS is in use. - * - * Cursors opened within the transaction must not be used again after this call, - * except with mdbx_cursor_renew() and mdbx_cursor_close(). - * - * Reader locks generally don't interfere with writers, but they keep old - * versions of database pages allocated. Thus they prevent the old pages from - * being reused when writers commit new data, and so under heavy load the - * database size may grow much more rapidly than otherwise. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_txn_reset(MDBX_txn *txn); - -/* Renew a read-only transaction. - * - * This acquires a new reader lock for a transaction handle that had been - * released by mdbx_txn_reset(). It must be called before a reset transaction - * may be used again. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_PANIC = a fatal error occurred earlier and the environment - * must be shut down. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_txn_renew(MDBX_txn *txn); - -/* The fours integers markers (aka "canary") associated with the environment. - * - * The `x`, `y` and `z` values could be set by mdbx_canary_put(), while the 'v' - * will be always set to the transaction number. Updated values becomes visible - * outside the current transaction only after it was committed. Current values - * could be retrieved by mdbx_canary_get(). */ -typedef struct mdbx_canary { - uint64_t x, y, z, v; -} mdbx_canary; - -/* Set integers markers (aka "canary") associated with the environment. - * - * [in] txn A transaction handle returned by mdbx_txn_begin() - * [in] canary A optional pointer to mdbx_canary structure for `x`, `y` - * and `z` values from. - * - If canary is NOT NULL then the `x`, `y` and `z` values will be - * updated from given canary argument, but the 'v' be always set - * to the current transaction number if at least one `x`, `y` or - * `z` values have changed (i.e. if `x`, `y` and `z` have the same - * values as currently present then nothing will be changes or - * updated). - * - if canary is NULL then the `v` value will be explicitly update - * to the current transaction number without changes `x`, `y` nor - * `z`. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary); - -/* Returns fours integers markers (aka "canary") associated with the - * environment. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] canary The address of an mdbx_canary structure where the information - * will be copied. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary); - -/* A callback function used to compare two keys in a database */ -typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b); - -/* Open a database in the environment. - * - * A database handle denotes the name and parameters of a database, - * independently of whether such a database exists. The database handle may be - * discarded by calling mdbx_dbi_close(). The old database handle is returned if - * the database was already open. The handle may only be closed once. - * - * (!) A notable difference between MDBX and LMDB is that MDBX make handles - * opened for existing databases immediately available for other transactions, - * regardless this transaction will be aborted or reset. The REASON for this is - * to avoiding the requirement for multiple opening a same handles in concurrent - * read transactions, and tracking of such open but hidden handles until the - * completion of read transactions which opened them. - * - * Nevertheless, the handle for the NEWLY CREATED database will be invisible for - * other transactions until the this write transaction is successfully - * committed. If the write transaction is aborted the handle will be closed - * automatically. After a successful commit the such handle will reside in the - * shared environment, and may be used by other transactions. - * - * In contrast to LMDB, the MDBX allow this function to be called from multiple - * concurrent transactions or threads in the same process. - * - * Legacy mdbx_dbi_open() correspond to calling mdbx_dbi_open_ex() with the null - * keycmp and datacmp arguments. - * - * To use named database (with name != NULL), mdbx_env_set_maxdbs() - * must be called before opening the environment. Table names are - * keys in the internal unnamed database, and may be read but not written. - * - * [in] txn transaction handle returned by mdbx_txn_begin(). - * [in] name The name of the database to open. If only a single - * database is needed in the environment, this value may be NULL. - * [in] flags Special options for this database. This parameter must be set - * to 0 or by bitwise OR'ing together one or more of the values - * described here: - * - MDBX_REVERSEKEY - * Keys are strings to be compared in reverse order, from the end - * of the strings to the beginning. By default, Keys are treated as - * strings and compared from beginning to end. - * - MDBX_DUPSORT - * Duplicate keys may be used in the database. Or, from another point of - * view, keys may have multiple data items, stored in sorted order. By - * default keys must be unique and may have only a single data item. - * - MDBX_INTEGERKEY - * Keys are binary integers in native byte order, either uin32_t or - * uint64_t, and will be sorted as such. The keys must all be of the - * same size. - * - MDBX_DUPFIXED - * This flag may only be used in combination with MDBX_DUPSORT. This - * option tells the library that the data items for this database are - * all the same size, which allows further optimizations in storage and - * retrieval. When all data items are the same size, the MDBX_GET_MULTIPLE, - * MDBX_NEXT_MULTIPLE and MDBX_PREV_MULTIPLE cursor operations may be used - * to retrieve multiple items at once. - * - MDBX_INTEGERDUP - * This option specifies that duplicate data items are binary integers, - * similar to MDBX_INTEGERKEY keys. - * - MDBX_REVERSEDUP - * This option specifies that duplicate data items should be compared as - * strings in reverse order (the comparison is performed in the direction - * from the last byte to the first). - * - MDBX_CREATE - * Create the named database if it doesn't exist. This option is not - * allowed in a read-only transaction or a read-only environment. - * - * [in] keycmp Optional custom key comparison function for a database. - * [in] datacmp Optional custom data comparison function for a database, takes - * effect only if database was opened with the MDB_DUPSORT flag. - * [out] dbi Address where the new MDBX_dbi handle will be stored. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = the specified database doesn't exist in the - * environment and MDBX_CREATE was not specified. - * - MDBX_DBS_FULL = too many databases have been opened. - * See mdbx_env_set_maxdbs(). - * - MDBX_INCOMPATIBLE = Database is incompatible with given flags, - * i.e. the passed flags is different with which the - * database was created, or the database was already - * opened with a different comparison function(s). */ -LIBMDBX_API int mdbx_dbi_open_ex(MDBX_txn *txn, const char *name, - unsigned flags, MDBX_dbi *dbi, - MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp); -LIBMDBX_API int mdbx_dbi_open(MDBX_txn *txn, const char *name, unsigned flags, - MDBX_dbi *dbi); - -/* Retrieve statistics for a database. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [out] stat The address of an MDBX_stat structure where the statistics - * will be copied. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *stat, - size_t bytes); - -/* Retrieve the DB flags and status for a database handle. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [out] flags Address where the flags will be returned. - * [out] state Address where the state will be returned. - * - * Legacy mdbx_dbi_flags() correspond to calling mdbx_dbi_flags_ex() with - * discarding result from the last argument. - * - * Returns A non-zero error value on failure and 0 on success. */ -#define MDBX_TBL_DIRTY 0x01 /* DB was written in this txn */ -#define MDBX_TBL_STALE 0x02 /* Named-DB record is older than txnID */ -#define MDBX_TBL_FRESH 0x04 /* Named-DB handle opened in this txn */ -#define MDBX_TBL_CREAT 0x08 /* Named-DB handle created in this txn */ -LIBMDBX_API int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, - unsigned *state); -LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags); - -/* Close a database handle. Normally unnecessary. - * - * NOTE: Use with care. - * This call is synchronized via mutex with mdbx_dbi_close(), but NOT with - * other transactions running by other threads. The "next" version of libmdbx - * (MithrilDB) will solve this issue. - * - * Handles should only be closed if no other threads are going to reference - * the database handle or one of its cursors any further. Do not close a handle - * if an existing transaction has modified its database. Doing so can cause - * misbehavior from database corruption to errors like MDBX_BAD_VALSIZE (since - * the DB name is gone). - * - * Closing a database handle is not necessary, but lets mdbx_dbi_open() reuse - * the handle value. Usually it's better to set a bigger mdbx_env_set_maxdbs(), - * unless that value would be large. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi); - -/* Empty or delete and close a database. - * - * See mdbx_dbi_close() for restrictions about closing the DB handle. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] del 0 to empty the DB, 1 to delete it from the environment - * and close the DB handle. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del); - -/* Get items from a database. - * - * This function retrieves key/data pairs from the database. The address - * and length of the data associated with the specified key are returned - * in the structure to which data refers. - * If the database supports duplicate keys (MDBX_DUPSORT) then the - * first data item for the key will be returned. Retrieval of other - * items requires the use of mdbx_cursor_get(). - * - * NOTE: The memory pointed to by the returned values is owned by the - * database. The caller need not dispose of the memory, and may not - * modify it in any way. For values returned in a read-only transaction - * any modification attempts will cause a SIGSEGV. - * - * NOTE: Values returned from the database are valid only until a - * subsequent update operation, or the end of the transaction. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to search for in the database. - * [in,out] data The data corresponding to the key. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = the key was not in the database. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data); - -/* Get items from a database and optionaly number of data items for a given key. - * - * Briefly this function does the same as mdbx_get() with a few differences: - * 1. If values_count is NOT NULL, then returns the count - * of multi-values/duplicates for a given key. - * 2. Updates BOTH the key and the data for pointing to the actual key-value - * pair inside the database. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in,out] key The key to search for in the database. - * [in,out] data The data corresponding to the key. - * [out] values_count The optional address to return number of values - * associated with given key, i.e. - * = 0 - in case MDBX_NOTFOUND error; - * = 1 - exactly for databases WITHOUT MDBX_DUPSORT; - * >= 1 for databases WITH MDBX_DUPSORT. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = the key was not in the database. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data, size_t *values_count); - -/* Get nearest items from a database. - * - * Briefly this function does the same as mdbx_get() with a few differences: - * 1. Return nearest (i.e. equal or great due comparison function) key-value - * pair, but not only exactly matching with the key. - * 2. On success return MDBX_SUCCESS if key found exactly, - * and MDBX_RESULT_TRUE otherwise. Moreover, for databases with MDBX_DUPSORT - * flag the data argument also will be used to match over - * multi-value/duplicates, and MDBX_SUCCESS will be returned only when BOTH - * the key and the data match exactly. - * 3. Updates BOTH the key and the data for pointing to the actual key-value - * pair inside the database. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in,out] key The key to search for in the database. - * [in,out] data The data corresponding to the key. - * - * Returns A non-zero error value on failure and MDBX_RESULT_TRUE (0) or - * MDBX_RESULT_TRUE on success (as described above). - * Some possible errors are: - * - MDBX_NOTFOUND = the key was not in the database. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_get_nearest(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data); - -/* Store items into a database. - * - * This function stores key/data pairs in the database. The default behavior - * is to enter the new key/data pair, replacing any previously existing key - * if duplicates are disallowed, or adding a duplicate data item if - * duplicates are allowed (MDBX_DUPSORT). - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to store in the database. - * [in,out] data The data to store. - * [in] flags Special options for this operation. This parameter must be - * set to 0 or by bitwise OR'ing together one or more of the - * values described here. - * - * - MDBX_NODUPDATA - * Enter the new key/data pair only if it does not already appear - * in the database. This flag may only be specified if the database - * was opened with MDBX_DUPSORT. The function will return MDBX_KEYEXIST - * if the key/data pair already appears in the database. - * - * - MDBX_NOOVERWRITE - * Enter the new key/data pair only if the key does not already appear - * in the database. The function will return MDBX_KEYEXIST if the key - * already appears in the database, even if the database supports - * duplicates (MDBX_DUPSORT). The data parameter will be set to point - * to the existing item. - * - * - MDBX_CURRENT - * Update an single existing entry, but not add new ones. The function - * will return MDBX_NOTFOUND if the given key not exist in the database. - * Or the MDBX_EMULTIVAL in case duplicates for the given key. - * - * - MDBX_RESERVE - * Reserve space for data of the given size, but don't copy the given - * data. Instead, return a pointer to the reserved space, which the - * caller can fill in later - before the next update operation or the - * transaction ends. This saves an extra memcpy if the data is being - * generated later. MDBX does nothing else with this memory, the caller - * is expected to modify all of the space requested. This flag must not - * be specified if the database was opened with MDBX_DUPSORT. - * - * - MDBX_APPEND - * Append the given key/data pair to the end of the database. This option - * allows fast bulk loading when keys are already known to be in the - * correct order. Loading unsorted keys with this flag will cause - * a MDBX_EKEYMISMATCH error. - * - * - MDBX_APPENDDUP - * As above, but for sorted dup data. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_KEYEXIST - * - MDBX_MAP_FULL = the database is full, see mdbx_env_set_mapsize(). - * - MDBX_TXN_FULL = the transaction has too many dirty pages. - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data, unsigned flags); - -/* Replace items in a database. - * - * This function allows to update or delete an existing value at the same time - * as the previous value is retrieved. If the argument new_data equal is NULL - * zero, the removal is performed, otherwise the update/insert. - * - * The current value may be in an already changed (aka dirty) page. In this - * case, the page will be overwritten during the update, and the old value will - * be lost. Therefore, an additional buffer must be passed via old_data argument - * initially to copy the old value. If the buffer passed in is too small, the - * function will return MDBX_RESULT_TRUE (-1) by setting iov_len field pointed - * by old_data argument to the appropriate value, without performing any - * changes. - * - * For databases with non-unique keys (i.e. with MDBX_DUPSORT flag), another use - * case is also possible, when by old_data argument selects a specific item from - * multi-value/duplicates with the same key for deletion or update. To select - * this scenario in flags should simultaneously specify MDBX_CURRENT and - * MDBX_NOOVERWRITE. This combination is chosen because it makes no sense, and - * thus allows you to identify the request of such a scenario. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to store in the database. - * [in,out] new_data The data to store, if NULL then deletion will be - * performed. - * [in,out] old_data The buffer for retrieve previous value as describe - * above. - * [in] flags Special options for this operation. This parameter must - * be set to 0 or by bitwise OR'ing together one or more of - * the values described in mdbx_put() description above, - * and additionally (MDBX_CURRENT | MDBX_NOOVERWRITE) - * combination for selection particular item from - * multi-value/duplicates. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *new_data, MDBX_val *old_data, - unsigned flags); - -/* Delete items from a database. - * - * This function removes key/data pairs from the database. - * - * NOTE: The data parameter is NOT ignored regardless the database does - * support sorted duplicate data items or not. If the data parameter - * is non-NULL only the matching data item will be deleted. - * - * This function will return MDBX_NOTFOUND if the specified key/data - * pair is not in the database. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to delete from the database. - * [in] data The data to delete. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data); - -/* Create a cursor handle. - * - * A cursor is associated with a specific transaction and database. A cursor - * cannot be used when its database handle is closed. Nor when its transaction - * has ended, except with mdbx_cursor_renew(). Also it can be discarded with - * mdbx_cursor_close(). - * - * A cursor must be closed explicitly always, before or after its transaction - * ends. It can be reused with mdbx_cursor_renew() before finally closing it. - * - * NOTE: In contrast to LMDB, the MDBX required that any opened cursors can be - * reused and must be freed explicitly, regardless ones was opened in a - * read-only or write transaction. The REASON for this is eliminates ambiguity - * which helps to avoid errors such as: use-after-free, double-free, i.e. memory - * corruption and segfaults. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [out] cursor Address where the new MDBX_cursor handle will be stored. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, - MDBX_cursor **cursor); - -/* Close a cursor handle. - * - * The cursor handle will be freed and must not be used again after this call, - * but its transaction may still be live. - * - * NOTE: In contrast to LMDB, the MDBX required that any opened cursors can be - * reused and must be freed explicitly, regardless ones was opened in a - * read-only or write transaction. The REASON for this is eliminates ambiguity - * which helps to avoid errors such as: use-after-free, double-free, i.e. memory - * corruption and segfaults. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). */ -LIBMDBX_API void mdbx_cursor_close(MDBX_cursor *cursor); - -/* Renew a cursor handle. - * - * A cursor is associated with a specific transaction and database. The cursor - * may be associated with a new transaction, and referencing the same database - * handle as it was created with. This may be done whether the previous - * transaction is live or dead. - * - * NOTE: In contrast to LMDB, the MDBX allow any cursor to be re-used by using - * mdbx_cursor_renew(), to avoid unnecessary malloc/free overhead until it freed - * by mdbx_cursor_close(). - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *cursor); - -/* Return the cursor's transaction handle. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). */ -LIBMDBX_API MDBX_txn *mdbx_cursor_txn(MDBX_cursor *cursor); - -/* Return the cursor's database handle. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). */ -LIBMDBX_API MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *cursor); - -/* Retrieve by cursor. - * - * This function retrieves key/data pairs from the database. The address and - * length of the key are returned in the object to which key refers (except - * for the case of the MDBX_SET option, in which the key object is unchanged), - * and the address and length of the data are returned in the object to which - * data refers. See mdbx_get() for restrictions on using the output values. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * [in,out] key The key for a retrieved item. - * [in,out] data The data of a retrieved item. - * [in] op A cursor operation MDBX_cursor_op. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = no matching key found. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_get(MDBX_cursor *cursor, MDBX_val *key, - MDBX_val *data, MDBX_cursor_op op); - -/* Store by cursor. - * - * This function stores key/data pairs into the database. The cursor is - * positioned at the new item, or on failure usually near it. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * [in] key The key operated on. - * [in] data The data operated on. - * [in] flags Options for this operation. This parameter - * must be set to 0 or one of the values described here: - * - * - MDBX_CURRENT - * Replace the item at the current cursor position. The key parameter - * must still be provided, and must match it, otherwise the function - * return MDBX_EKEYMISMATCH. - * - * NOTE: MDBX unlike LMDB allows you to change the size of the data and - * automatically handles reordering for sorted duplicates (MDBX_DUPSORT). - * - * - MDBX_NODUPDATA - * Enter the new key/data pair only if it does not already appear in the - * database. This flag may only be specified if the database was opened - * with MDBX_DUPSORT. The function will return MDBX_KEYEXIST if the - * key/data pair already appears in the database. - * - * - MDBX_NOOVERWRITE - * Enter the new key/data pair only if the key does not already appear - * in the database. The function will return MDBX_KEYEXIST if the key - * already appears in the database, even if the database supports - * duplicates (MDBX_DUPSORT). - * - * - MDBX_RESERVE - * Reserve space for data of the given size, but don't copy the given - * data. Instead, return a pointer to the reserved space, which the - * caller can fill in later - before the next update operation or the - * transaction ends. This saves an extra memcpy if the data is being - * generated later. This flag must not be specified if the database - * was opened with MDBX_DUPSORT. - * - * - MDBX_APPEND - * Append the given key/data pair to the end of the database. No key - * comparisons are performed. This option allows fast bulk loading when - * keys are already known to be in the correct order. Loading unsorted - * keys with this flag will cause a MDBX_KEYEXIST error. - * - * - MDBX_APPENDDUP - * As above, but for sorted dup data. - * - * - MDBX_MULTIPLE - * Store multiple contiguous data elements in a single request. This flag - * may only be specified if the database was opened with MDBX_DUPFIXED. - * The data argument must be an array of two MDBX_vals. The iov_len of the - * first MDBX_val must be the size of a single data element. The iov_base - * of the first MDBX_val must point to the beginning of the array of - * contiguous data elements. The iov_len of the second MDBX_val must be - * the count of the number of data elements to store. On return this - * field will be set to the count of the number of elements actually - * written. The iov_base of the second MDBX_val is unused. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EKEYMISMATCH - * - MDBX_MAP_FULL = the database is full, see mdbx_env_set_mapsize(). - * - MDBX_TXN_FULL = the transaction has too many dirty pages. - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_put(MDBX_cursor *cursor, MDBX_val *key, - MDBX_val *data, unsigned flags); - -/* Delete current key/data pair. - * - * This function deletes the key/data pair to which the cursor refers. This does - * not invalidate the cursor, so operations such as MDBX_NEXT can still be used - * on it. Both MDBX_NEXT and MDBX_GET_CURRENT will return the same record after - * this operation. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * [in] flags Options for this operation. This parameter must be set to 0 - * or one of the values described here. - * - * - MDBX_NODUPDATA - * Delete all of the data items for the current key. This flag may only - * be specified if the database was opened with MDBX_DUPSORT. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_del(MDBX_cursor *cursor, unsigned flags); - -/* Return count of duplicates for current key. - * - * This call is valid for all databases, but reasonable only for that support - * sorted duplicate data items MDBX_DUPSORT. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * [out] countp Address where the count will be stored. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EINVAL = cursor is not initialized, or an invalid parameter - * was specified. */ -LIBMDBX_API int mdbx_cursor_count(MDBX_cursor *cursor, size_t *countp); - -/* Determines whether the cursor is pointed to a key-value pair or not, - * i.e. was not positioned or points to the end of data. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * - * Returns: - * - MDBX_RESULT_TRUE = no more data available or cursor not positioned; - * - MDBX_RESULT_FALSE = data available; - * - Otherwise the error code. */ -LIBMDBX_API int mdbx_cursor_eof(MDBX_cursor *mc); - -/* Determines whether the cursor is pointed to the first key-value pair or not. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * - * Returns: - * - MDBX_RESULT_TRUE = cursor positioned to the first key-value pair. - * - MDBX_RESULT_FALSE = cursor NOT positioned to the first key-value pair. - * - Otherwise the error code. */ -LIBMDBX_API int mdbx_cursor_on_first(MDBX_cursor *mc); - -/* Determines whether the cursor is pointed to the last key-value pair or not. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * - * Returns: - * - MDBX_RESULT_TRUE = cursor positioned to the last key-value pair. - * - MDBX_RESULT_FALSE = cursor NOT positioned to the last key-value pair. - * - Otherwise the error code. */ -LIBMDBX_API int mdbx_cursor_on_last(MDBX_cursor *mc); - -/* Estimates the distance between cursors as a number of elements. The results - * of such estimation can be used to build and/or optimize query execution - * plans. - * - * This function performs a rough estimate based only on b-tree pages that are - * common for the both cursor's stacks. - * - * NOTE: The result varies greatly depending on the filling of specific pages - * and the overall balance of the b-tree: - * - * 1. The number of items is estimated by analyzing the height and fullness of - * the b-tree. The accuracy of the result directly depends on the balance of the - * b-tree, which in turn is determined by the history of previous insert/delete - * operations and the nature of the data (i.e. variability of keys length and so - * on). Therefore, the accuracy of the estimation can vary greatly in a - * particular situation. - * - * 2. To understand the potential spread of results, you should consider a - * possible situations basing on the general criteria for splitting and merging - * b-tree pages: - * - the page is split into two when there is no space for added data; - * - two pages merge if the result fits in half a page; - * - thus, the b-tree can consist of an arbitrary combination of pages filled - * both completely and only 1/4. Therefore, in the worst case, the result - * can diverge 4 times for each level of the b-tree excepting the first and - * the last. - * - * 3. In practice, the probability of extreme cases of the above situation is - * close to zero and in most cases the error does not exceed a few percent. On - * the other hand, it's just a chance you shouldn't overestimate. - * - * Both cursors must be initialized for the same database and the same - * transaction. - * - * [in] first The first cursor for estimation. - * [in] last The second cursor for estimation. - * [out] distance_items A pointer to store estimated distance value, - * i.e. *distance_items = distance(first, last). - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_estimate_distance(const MDBX_cursor *first, - const MDBX_cursor *last, - ptrdiff_t *distance_items); - -/* Estimates the move distance, i.e. between the current cursor position and - * next position after the specified move-operation with given key and data. - * The results of such estimation can be used to build and/or optimize query - * execution plans. Current cursor position and state are preserved. - * - * Please see notes on accuracy of the result in mdbx_estimate_distance() - * description above. - * - * [in] cursor Cursor for estimation. - * [in,out] key The key for a retrieved item. - * [in,out] data The data of a retrieved item. - * [in] op A cursor operation MDBX_cursor_op. - * [out] distance_items A pointer to store estimated move distance - * as the number of elements. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, - MDBX_val *data, MDBX_cursor_op move_op, - ptrdiff_t *distance_items); - -/* Estimates the size of a range as a number of elements. The results - * of such estimation can be used to build and/or optimize query execution - * plans. - * - * Please see notes on accuracy of the result in mdbx_estimate_distance() - * description above. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] begin_key The key of range beginning or NULL for explicit FIRST. - * [in] begin_data Optional additional data to seeking among sorted - * duplicates. Only for MDBX_DUPSORT, NULL otherwise. - * [in] end_key The key of range ending or NULL for explicit LAST. - * [in] end_data Optional additional data to seeking among sorted - * duplicates. Only for MDBX_DUPSORT, NULL otherwise. - * [out] distance_items A pointer to store range estimation result. - * - * Returns A non-zero error value on failure and 0 on success. */ -#define MDBX_EPSILON ((MDBX_val *)((ptrdiff_t)-1)) -LIBMDBX_API int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, - MDBX_val *begin_key, MDBX_val *begin_data, - MDBX_val *end_key, MDBX_val *end_data, - ptrdiff_t *size_items); - -/* Determines whether the given address is on a dirty database page of the - * transaction or not. Ultimately, this allows to avoid copy data from non-dirty - * pages. - * - * "Dirty" pages are those that have already been changed during a write - * transaction. Accordingly, any further changes may result in such pages being - * overwritten. Therefore, all functions libmdbx performing changes inside the - * database as arguments should NOT get pointers to data in those pages. In - * turn, "not dirty" pages before modification will be copied. - * - * In other words, data from dirty pages must either be copied before being - * passed as arguments for further processing or rejected at the argument - * validation stage. Thus, mdbx_is_dirty() allows you to get rid of unnecessary - * copying, and perform a more complete check of the arguments. - * - * NOTE: The address passed must point to the beginning of the data. This is the - * only way to ensure that the actual page header is physically located in the - * same memory page, including for multi-pages with long data. - * - * NOTE: In rare cases the function may return a false positive answer - * (DBX_RESULT_TRUE when data is NOT on a dirty page), but never a false - * negative if the arguments are correct. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] ptr The address of data to check. - * - * Returns: - * - MDBX_RESULT_TRUE = given address is on the dirty page. - * - MDBX_RESULT_FALSE = given address is NOT on the dirty page. - * - Otherwise the error code. */ -LIBMDBX_API int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr); - -/* Sequence generation for a database. - * - * The function allows to create a linear sequence of unique positive integers - * for each database. The function can be called for a read transaction to - * retrieve the current sequence value, and the increment must be zero. - * Sequence changes become visible outside the current write transaction after - * it is committed, and discarded on abort. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [out] result The optional address where the value of sequence before the - * change will be stored. - * [in] increment Value to increase the sequence, - * must be 0 for read-only transactions. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_RESULT_TRUE = Increasing the sequence has resulted in an overflow - * and therefore cannot be executed. */ -LIBMDBX_API int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, - uint64_t increment); - -/* Compare two data items according to a particular database. - * - * This returns a comparison as if the two data items were keys in the - * specified database. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] a The first item to compare. - * [in] b The second item to compare. - * - * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */ -LIBMDBX_API int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, - const MDBX_val *b); - -/* Compare two data items according to a particular database. - * - * This returns a comparison as if the two items were data items of the - * specified database. The database must have the MDBX_DUPSORT flag. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] a The first item to compare. - * [in] b The second item to compare. - * - * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */ -LIBMDBX_API int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, - const MDBX_val *b); - -/* A callback function used to enumerate the reader lock table. - * - * [in] ctx An arbitrary context pointer for the callback. - * [in] num The serial number during enumeration, starting from 1. - * [in] slot The reader lock table slot number. - * [in] txnid The ID of the transaction being read, - * i.e. the MVCC-snaphot number. - * [in] lag The lag from a recent MVCC-snapshot, i.e. the number of - * committed transaction since read transaction started. - * [in] pid The reader process ID. - * [in] thread The reader thread ID. - * [in] bytes_used The number of last used page in the MVCC-snapshot which - * being read, i.e. database file can't shrinked beyond this. - * [in] bytes_retired The total size of the database pages that were retired by - * committed write transactions after the reader's - * MVCC-snapshot, i.e. the space which would be freed after - * the Reader releases the MVCC-snapshot for reuse by - * completion read transaction. - * - * Returns < 0 on failure, >= 0 on success. */ -typedef int(MDBX_reader_list_func)(void *ctx, int num, int slot, mdbx_pid_t pid, - mdbx_tid_t thread, uint64_t txnid, - uint64_t lag, size_t bytes_used, - size_t bytes_retained); - -/* Enumarete the entries in the reader lock table. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] func A MDBX_reader_list_func function. - * [in] ctx An arbitrary context pointer for the enumeration function. - * - * Returns A non-zero error value on failure and 0 on success, - * or MDBX_RESULT_TRUE (-1) if the reader lock table is empty. */ -LIBMDBX_API int mdbx_reader_list(MDBX_env *env, MDBX_reader_list_func *func, - void *ctx); - -/* Check for stale entries in the reader lock table. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [out] dead Number of stale slots that were cleared. - * - * Returns A non-zero error value on failure and 0 on success, - * or MDBX_RESULT_TRUE (-1) if a dead reader(s) found or mutex was recovered. */ -LIBMDBX_API int mdbx_reader_check(MDBX_env *env, int *dead); - -/* Returns a lag of the reading for the given transaction. - * - * Returns an information for estimate how much given read-only - * transaction is lagging relative the to actual head. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [out] percent Percentage of page allocation in the database. - * - * Returns Number of transactions committed after the given was started for - * read, or negative value on failure. */ -LIBMDBX_API int mdbx_txn_straggler(MDBX_txn *txn, int *percent); - -/* A lack-of-space callback function to resolve issues with a laggard readers. - * - * Read transactions prevent reuse of pages freed by newer write transactions, - * thus the database can grow quickly. This callback will be called when there - * is not enough space in the database (ie. before increasing the database size - * or before MDBX_MAP_FULL error) and thus can be used to resolve issues with - * a "long-lived" read transactions. - * - * Depending on the arguments and needs, your implementation may wait, terminate - * a process or thread that is performing a long read, or perform some other - * action. In doing so it is important that the returned code always corresponds - * to the performed action. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] pid A pid of the reader process. - * [in] tid A thread_id of the reader thread. - * [in] txn A transaction number on which stalled. - * [in] gap A lag from the last commited txn. - * [in] space A space that actually become available for reuse after this - * reader finished. The callback function can take this value into - * account to evaluate the impact that a long-running transaction - * has. - * [in] retry A retry number starting from 0. if callback has returned 0 - * at least once, then at end of current OOM-handler loop callback - * will be called additionally with negative value to notify about - * the end of loop. The callback function can use this value to - * implement timeout logic while waiting for readers. - * - * The RETURN CODE determines the further actions libmdbx and must match the - * action which was executed by the callback: - * - * -2 or less = An error condition and the reader was not killed. - * - * -1 = The callback was unable to solve the problem and agreed - * on MDBX_MAP_FULL error, libmdbx should increase the - * database size or return MDBX_MAP_FULL error. - * - * 0 (zero) = The callback solved the problem or just waited for - * a while, libmdbx should rescan the reader lock table and - * retry. This also includes a situation when corresponding - * transaction terminated in normal way by mdbx_txn_abort() - * or mdbx_txn_reset(), and my be restarted. I.e. reader - * slot don't needed to be cleaned from transaction. - * - * 1 = Transaction aborted asynchronous and reader slot should - * be cleared immediately, i.e. read transaction will not - * continue but mdbx_txn_abort() or mdbx_txn_reset() will - * be called later. - * - * 2 or great = The reader process was terminated or killed, and libmdbx - * should entirely reset reader registration. */ -typedef int(MDBX_oom_func)(MDBX_env *env, mdbx_pid_t pid, mdbx_tid_t tid, - uint64_t txn, unsigned gap, size_t space, int retry); - -/* Set the OOM callback. - * - * The callback will only be triggered on lack of space to resolve issues with - * lagging reader(s) (i.e. to kill it) for resume reuse pages from the garbage - * collector. - * - * [in] env An environment handle returned by mdbx_env_create(). - * [in] oom_func A MDBX_oom_func function or NULL to disable. - * - * Returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oom_func); - -/* Get the current oom_func callback. - * - * [in] env An environment handle returned by mdbx_env_create(). - * - * Returns A MDBX_oom_func function or NULL if disabled. */ -LIBMDBX_API MDBX_oom_func *mdbx_env_get_oomfunc(MDBX_env *env); - -/**** B-tree Traversal ********************************************************* - * This is internal API for mdbx_chk tool. You should avoid to use it, except - * some extremal special cases. */ - -/* Page types for traverse the b-tree. */ -typedef enum { - MDBX_page_void, - MDBX_page_meta, - MDBX_page_large, - MDBX_page_branch, - MDBX_page_leaf, - MDBX_page_dupfixed_leaf, - MDBX_subpage_leaf, - MDBX_subpage_dupfixed_leaf -} MDBX_page_type_t; - -#define MDBX_PGWALK_MAIN ((const char *)((ptrdiff_t)0)) -#define MDBX_PGWALK_GC ((const char *)((ptrdiff_t)-1)) -#define MDBX_PGWALK_META ((const char *)((ptrdiff_t)-2)) - -/* Callback function for traverse the b-tree. */ -typedef int -MDBX_pgvisitor_func(const uint64_t pgno, const unsigned number, void *const ctx, - const int deep, const char *const dbi, - const size_t page_size, const MDBX_page_type_t type, - const size_t nentries, const size_t payload_bytes, - const size_t header_bytes, const size_t unused_bytes); - -/* B-tree traversal function. */ -LIBMDBX_API int mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor, - void *ctx); - -/**** Attribute support functions for Nexenta *********************************/ -#ifdef MDBX_NEXENTA_ATTRS -typedef uint_fast64_t mdbx_attr_t; - -/* Store by cursor with attribute. - * - * This function stores key/data pairs into the database. The cursor is - * positioned at the new item, or on failure usually near it. - * - * NOTE: Internally based on MDBX_RESERVE feature, - * therefore doesn't support MDBX_DUPSORT. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open() - * [in] key The key operated on. - * [in] data The data operated on. - * [in] attr The attribute. - * [in] flags Options for this operation. This parameter must be set to 0 - * or one of the values described here: - * - * - MDBX_CURRENT - * Replace the item at the current cursor position. The key parameter - * must still be provided, and must match it, otherwise the function - * return MDBX_EKEYMISMATCH. - * - * - MDBX_APPEND - * Append the given key/data pair to the end of the database. No key - * comparisons are performed. This option allows fast bulk loading when - * keys are already known to be in the correct order. Loading unsorted - * keys with this flag will cause a MDBX_KEYEXIST error. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_EKEYMISMATCH - * - MDBX_MAP_FULL = the database is full, see mdbx_env_set_mapsize(). - * - MDBX_TXN_FULL = the transaction has too many dirty pages. - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key, - MDBX_val *data, mdbx_attr_t attr, - unsigned flags); - -/* Store items and attributes into a database. - * - * This function stores key/data pairs in the database. The default behavior - * is to enter the new key/data pair, replacing any previously existing key - * if duplicates are disallowed. - * - * NOTE: Internally based on MDBX_RESERVE feature, - * therefore doesn't support MDBX_DUPSORT. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to store in the database. - * [in] attr The attribute to store in the database. - * [in,out] data The data to store. - * [in] flags Special options for this operation. This parameter must be - * set to 0 or by bitwise OR'ing together one or more of the - * values described here: - * - * - MDBX_NOOVERWRITE - * Enter the new key/data pair only if the key does not already appear - * in the database. The function will return MDBX_KEYEXIST if the key - * already appears in the database. The data parameter will be set to - * point to the existing item. - * - * - MDBX_CURRENT - * Update an single existing entry, but not add new ones. The function - * will return MDBX_NOTFOUND if the given key not exist in the database. - * Or the MDBX_EMULTIVAL in case duplicates for the given key. - * - * - MDBX_APPEND - * Append the given key/data pair to the end of the database. This option - * allows fast bulk loading when keys are already known to be in the - * correct order. Loading unsorted keys with this flag will cause - * a MDBX_EKEYMISMATCH error. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_KEYEXIST - * - MDBX_MAP_FULL = the database is full, see mdbx_env_set_mapsize(). - * - MDBX_TXN_FULL = the transaction has too many dirty pages. - * - MDBX_EACCES = an attempt was made to write in a read-only transaction. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data, mdbx_attr_t attr, unsigned flags); - -/* Set items attribute from a database. - * - * This function stores key/data pairs attribute to the database. - * - * NOTE: Internally based on MDBX_RESERVE feature, - * therefore doesn't support MDBX_DUPSORT. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to search for in the database. - * [in] data The data to be stored or NULL to save previous value. - * [in] attr The attribute to be stored. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = the key-value pair was not in the database. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data, mdbx_attr_t attr); - -/* Get items attribute from a database cursor. - * - * This function retrieves key/data pairs from the database. The address and - * length of the key are returned in the object to which key refers (except - * for the case of the MDBX_SET option, in which the key object is unchanged), - * and the address and length of the data are returned in the object to which - * data refers. See mdbx_get() for restrictions on using the output values. - * - * [in] cursor A cursor handle returned by mdbx_cursor_open(). - * [in,out] key The key for a retrieved item. - * [in,out] data The data of a retrieved item. - * [in] op A cursor operation MDBX_cursor_op. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = no matching key found. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data, mdbx_attr_t *attrptr, - MDBX_cursor_op op); - -/* Get items attribute from a database. - * - * This function retrieves key/data pairs from the database. The address - * and length of the data associated with the specified key are returned - * in the structure to which data refers. - * If the database supports duplicate keys (MDBX_DUPSORT) then the - * first data item for the key will be returned. Retrieval of other - * items requires the use of mdbx_cursor_get(). - * - * NOTE: The memory pointed to by the returned values is owned by the - * database. The caller need not dispose of the memory, and may not - * modify it in any way. For values returned in a read-only transaction - * any modification attempts will cause a SIGSEGV. - * - * NOTE: Values returned from the database are valid only until a - * subsequent update operation, or the end of the transaction. - * - * [in] txn A transaction handle returned by mdbx_txn_begin(). - * [in] dbi A database handle returned by mdbx_dbi_open(). - * [in] key The key to search for in the database. - * [in,out] data The data corresponding to the key. - * - * Returns A non-zero error value on failure and 0 on success, some - * possible errors are: - * - MDBX_NOTFOUND = the key was not in the database. - * - MDBX_EINVAL = an invalid parameter was specified. */ -LIBMDBX_API int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data, mdbx_attr_t *attrptr); -#endif /* MDBX_NEXENTA_ATTRS */ - -/******************************************************************************* - * LY: temporary workaround for Elbrus's memcmp() bug. */ -#ifndef __GLIBC_PREREQ -#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) -#define __GLIBC_PREREQ(maj, min) \ - ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) -#else -#define __GLIBC_PREREQ(maj, min) (0) -#endif -#endif /* __GLIBC_PREREQ */ -#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) -LIBMDBX_API int mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, - size_t n); -LIBMDBX_API int mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2); -LIBMDBX_API int mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, - size_t n); -LIBMDBX_API size_t mdbx_e2k_strlen_bug_workaround(const char *s); -LIBMDBX_API size_t mdbx_e2k_strnlen_bug_workaround(const char *s, - size_t maxlen); -#include -#include -#undef memcmp -#define memcmp mdbx_e2k_memcmp_bug_workaround -#undef bcmp -#define bcmp mdbx_e2k_memcmp_bug_workaround -#undef strcmp -#define strcmp mdbx_e2k_strcmp_bug_workaround -#undef strncmp -#define strncmp mdbx_e2k_strncmp_bug_workaround -#undef strlen -#define strlen mdbx_e2k_strlen_bug_workaround -#undef strnlen -#define strnlen mdbx_e2k_strnlen_bug_workaround - -#endif /* Elbrus's memcmp() bug. */ - -#ifdef __cplusplus -} -#endif - -#endif /* LIBMDBX_H */ diff --git a/src/contrib/db/libmdbx/packages/rpm/CMakeLists.txt b/src/contrib/db/libmdbx/packages/rpm/CMakeLists.txt deleted file mode 100644 index 5949e9f..0000000 --- a/src/contrib/db/libmdbx/packages/rpm/CMakeLists.txt +++ /dev/null @@ -1,184 +0,0 @@ -cmake_minimum_required(VERSION 2.8.7) -set(TARGET mdbx) -project(${TARGET}) - -set(MDBX_VERSION_MAJOR 0) -set(MDBX_VERSION_MINOR 3) -set(MDBX_VERSION_RELEASE 1) -set(MDBX_VERSION_REVISION 0) - -set(MDBX_VERSION_STRING ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR}.${MDBX_VERSION_RELEASE}) - -enable_language(C) -enable_language(CXX) - -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED on) - -add_definitions(-DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1 -D_GNU_SOURCE=1) - -find_package(Threads REQUIRED) - -get_directory_property(hasParent PARENT_DIRECTORY) -if(hasParent) - set(STANDALONE_BUILD 0) -else() - set(STANDALONE_BUILD 1) - enable_testing() - - if (CMAKE_C_COMPILER_ID MATCHES GNU) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") - endif() - - if (CMAKE_CXX_COMPILER_ID MATCHES GNU) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpointer-arith") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat-security") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wwrite-strings") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=20") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wunused-function -Wunused-variable -Wunused-value -Wmissing-declarations") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-qual") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-functions-called-once") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-packed-bitfield-compat") - - set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g3") - endif() - - if (COVERAGE) - if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - message(FATAL_ERROR "Coverage requires -DCMAKE_BUILD_TYPE=Debug Current value=${CMAKE_BUILD_TYPE}") - endif() - - message(STATUS "Setting coverage compiler flags") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb3 -O0 --coverage -fprofile-arcs -ftest-coverage") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -ggdb3 -O0 --coverage -fprofile-arcs -ftest-coverage") - add_definitions(-DCOVERAGE_TEST) - endif() - - if (NOT TRAVIS) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak -fstack-protector-strong -static-libasan") - endif() -endif() - -set(${TARGET}_SRC - mdbx.h - src/bits.h - src/defs.h - src/lck-linux.c - src/mdbx.c - src/osal.c - src/osal.h - src/version.c - ) - -add_library(${TARGET}_STATIC STATIC - ${${TARGET}_SRC} - ) - -add_library(${TARGET} ALIAS ${TARGET}_STATIC) - -add_library(${TARGET}_SHARED SHARED - ${${TARGET}_SRC} - ) - -set_target_properties(${TARGET}_SHARED PROPERTIES - VERSION ${MDBX_VERSION_STRING} - SOVERSION ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR} - OUTPUT_NAME ${TARGET} - CLEAN_DIRECT_OUTPUT 1 - ) - -set_target_properties(${TARGET}_STATIC PROPERTIES - VERSION ${MDBX_VERSION_STRING} - SOVERSION ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR} - OUTPUT_NAME ${TARGET} - CLEAN_DIRECT_OUTPUT 1 - ) - -target_include_directories(${TARGET}_STATIC PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(${TARGET}_SHARED PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(${TARGET}_STATIC ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(${TARGET}_SHARED ${CMAKE_THREAD_LIBS_INIT}) -if(UNIX AND NOT APPLE) - target_link_libraries(${TARGET}_STATIC rt) - target_link_libraries(${TARGET}_SHARED rt) -endif() - -install(TARGETS ${TARGET}_STATIC DESTINATION ${CMAKE_INSTALL_PREFIX}/lib64 COMPONENT mdbx) -install(TARGETS ${TARGET}_SHARED DESTINATION ${CMAKE_INSTALL_PREFIX}/lib64 COMPONENT mdbx) -install(FILES mdbx.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include COMPONENT mdbx-devel) - -add_subdirectory(src/tools) -add_subdirectory(test) -add_subdirectory(test/pcrf) -add_subdirectory(tutorial) - -############################################################################## - -set(CPACK_GENERATOR "RPM") -set(CPACK_RPM_COMPONENT_INSTALL ON) - -# Version -if (NOT "$ENV{BUILD_NUMBER}" STREQUAL "") - set(CPACK_PACKAGE_RELEASE $ENV{BUILD_NUMBER}) -else() - if (NOT "$ENV{CI_PIPELINE_ID}" STREQUAL "") - set(CPACK_PACKAGE_RELEASE $ENV{CI_PIPELINE_ID}) - else() - set(CPACK_PACKAGE_RELEASE 1) - endif() -endif() -set(CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE}) - -set(CPACK_PACKAGE_VERSION ${MDBX_VERSION_STRING}) -set(CPACK_PACKAGE_VERSION_FULL ${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}) - -set(CPACK_RPM_mdbx-devel_PACKAGE_REQUIRES "mdbx = ${CPACK_PACKAGE_VERSION}") - -set(CPACK_RPM_SPEC_INSTALL_POST "/bin/true") -set(CPACK_RPM_mdbx_PACKAGE_NAME mdbx) -set(CPACK_RPM_mdbx-devel_PACKAGE_NAME mdbx-devel) -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The revised and extended descendant of Symas LMDB") - -set(CPACK_PACKAGE_VENDOR "???") -set(CPACK_PACKAGE_CONTACT "Vladimir Romanov") -set(CPACK_PACKAGE_RELOCATABLE false) -set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") -set(CPACK_RPM_PACKAGE_REQUIRES "") -set(CPACK_RPM_PACKAGE_GROUP "Applications/Database") - -set(CPACK_RPM_mdbx_FILE_NAME "${CPACK_RPM_mdbx_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_FULL}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") -set(CPACK_RPM_mdbx-devel_FILE_NAME "${CPACK_RPM_mdbx-devel_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_FULL}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") - -set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION - /usr/local - /usr/local/bin - /usr/local/lib64 - /usr/local/include - /usr/local/man - /usr/local/man/man1 - ) - -include(CPack) diff --git a/src/contrib/db/libmdbx/packages/rpm/build.sh b/src/contrib/db/libmdbx/packages/rpm/build.sh deleted file mode 100644 index 5170882..0000000 --- a/src/contrib/db/libmdbx/packages/rpm/build.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -e -CONFIG=$1 - -if [[ -z "${CONFIG}" ]]; then - CONFIG=Debug -fi -if [[ -r /opt/rh/devtoolset-6/enable ]]; then - source /opt/rh/devtoolset-6/enable -fi -#rm -f -r build || true -mkdir -p cmake-build-${CONFIG} -pushd cmake-build-${CONFIG} &> /dev/null -if [[ ! -r Makefile ]]; then - cmake .. -DCMAKE_BUILD_TYPE=${CONFIG} -fi -make -j8 || exit 1 -popd &> /dev/null diff --git a/src/contrib/db/libmdbx/packages/rpm/package.sh b/src/contrib/db/libmdbx/packages/rpm/package.sh deleted file mode 100644 index d7f9ab2..0000000 --- a/src/contrib/db/libmdbx/packages/rpm/package.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -e - -CONFIG=$1 - -if [[ -z "${CONFIG}" ]]; then - CONFIG=Debug -fi - -DIRNAME=`dirname ${BASH_SOURCE[0]}` -DIRNAME=`readlink --canonicalize ${DIRNAME}` - -if [[ -r /opt/rh/devtoolset-6/enable ]]; then - source /opt/rh/devtoolset-6/enable -fi - -mkdir -p cmake-build-${CONFIG} -pushd cmake-build-${CONFIG} &> /dev/null -if [[ ! -r Makefile ]]; then - cmake .. -DCMAKE_BUILD_TYPE=${CONFIG} -fi -rm -f *.rpm -make -j8 package || exit 1 -rm -f *-Unspecified.rpm -popd &> /dev/null diff --git a/src/contrib/db/libmdbx/src/CMakeLists.txt b/src/contrib/db/libmdbx/src/CMakeLists.txt deleted file mode 100644 index 04aead5..0000000 --- a/src/contrib/db/libmdbx/src/CMakeLists.txt +++ /dev/null @@ -1,225 +0,0 @@ -## -## Copyright 2019 Leonid Yuriev -## and other libmdbx authors: please see AUTHORS file. -## All rights reserved. -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted only as authorized by the OpenLDAP -## Public License. -## -## A copy of this license is available in the file LICENSE in the -## top-level directory of the distribution or, alternatively, at -## . -## - -# Get version -fetch_version(MDBX "${CMAKE_CURRENT_SOURCE_DIR}/../VERSION") -message(STATUS "libmdbx version is ${MDBX_VERSION}") - -if(MDBX_ALLOY_MODE) - set(LIBMDBX_SOURCES alloy.c) -else() - if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - set(LIBMDBX_OSAL windows) - else() - set(LIBMDBX_OSAL posix) - endif() - set(LIBMDBX_SOURCES - elements/defs.h elements/internals.h elements/osal.h - elements/core.c elements/osal.c elements/lck-${LIBMDBX_OSAL}.c) -endif() -list(APPEND LIBMDBX_SOURCES ../mdbx.h - "${CMAKE_CURRENT_SOURCE_DIR}/elements/version.c" - "${CMAKE_CURRENT_SOURCE_DIR}/elements/config.h") - -if(MDBX_BUILD_SHARED_LIBRARY) - add_library(mdbx SHARED ${LIBMDBX_SOURCES}) - target_compile_definitions(mdbx PRIVATE LIBMDBX_EXPORTS INTERFACE LIBMDBX_IMPORTS) - set(MDBX_LIBDEP_MODE PRIVATE) -else() - add_library(mdbx STATIC ${LIBMDBX_SOURCES}) - set(MDBX_LIBDEP_MODE PUBLIC) -endif() - -if(CC_HAS_VISIBILITY AND (LTO_ENABLED OR INTERPROCEDURAL_OPTIMIZATION)) - set_target_properties(mdbx PROPERTIES LINK_FLAGS "-fvisibility=hidden") -endif() - -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - if(MSVC) - if(NOT MSVC_LIB_EXE) - # Find lib.exe - get_filename_component(CL_NAME ${CMAKE_C_COMPILER} NAME) - string(REPLACE cl.exe lib.exe MSVC_LIB_EXE ${CL_NAME}) - find_program(MSVC_LIB_EXE ${MSVC_LIB_EXE}) - endif() - if(MSVC_LIB_EXE) - message(STATUS "Found MSVC's lib tool: ${MSVC_LIB_EXE}") - set(MDBX_NTDLL_EXTRA_IMPLIB ${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.lib) - add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB} - COMMENT "Create extra-import-library for ntdll.dll" - MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" - COMMAND ${MSVC_LIB_EXE} /def:"${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" /out:"${MDBX_NTDLL_EXTRA_IMPLIB}" ${INITIAL_CMAKE_STATIC_LINKER_FLAGS}) - else() - message(SEND_ERROR "MSVC's lib tool not found") - endif() - elseif(MINGW OR MINGW64) - if(NOT DLLTOOL) - # Find dlltool - get_filename_component(GCC_NAME ${CMAKE_C_COMPILER} NAME) - string(REPLACE gcc dlltool DLLTOOL_NAME ${GCC_NAME}) - find_program(DLLTOOL NAMES ${DLLTOOL_NAME}) - endif() - if(DLLTOOL) - message(STATUS "Found dlltool: ${DLLTOOL}") - set(MDBX_NTDLL_EXTRA_IMPLIB "${CMAKE_CURRENT_BINARY_DIR}/mdbx_ntdll_extra.a") - add_custom_command(OUTPUT ${MDBX_NTDLL_EXTRA_IMPLIB} - COMMENT "Create extra-import-library for ntdll.dll" - MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" - COMMAND ${DLLTOOL} -d "${CMAKE_CURRENT_SOURCE_DIR}/elements/ntdll.def" -l "${MDBX_NTDLL_EXTRA_IMPLIB}") - else() - message(SEND_ERROR "dlltool not found") - endif() - endif() -endif() - -target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ${CMAKE_THREAD_LIBS_INIT}) -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll.lib) - if(MDBX_NTDLL_EXTRA_IMPLIB) - # LY: Sometimes Cmake requires a nightmarish magic for simple things. - # 1) create a target out of the library compilation result - add_custom_target(ntdll_extra_target DEPENDS ${MDBX_NTDLL_EXTRA_IMPLIB}) - # 2) create an library target out of the library compilation result - add_library(ntdll_extra STATIC IMPORTED GLOBAL) - add_dependencies(ntdll_extra ntdll_extra_target) - # 3) specify where the library is (and where to find the headers) - set_target_properties(ntdll_extra - PROPERTIES - IMPORTED_LOCATION ${MDBX_NTDLL_EXTRA_IMPLIB}) - target_link_libraries(mdbx ${MDBX_LIBDEP_MODE} ntdll_extra) - endif() -endif() - -set_target_properties(mdbx PROPERTIES - INTERPROCEDURAL_OPTIMIZATION $ - C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON - PUBLIC_HEADER "../mdbx.h") - -if(CC_HAS_FASTMATH) - target_compile_options(mdbx PRIVATE "-ffast-math") -endif() -if(BUILD_FOR_NATIVE_CPU AND CC_HAS_ARCH_NATIVE) - target_compile_options(mdbx PUBLIC "-march=native") -endif() -if(CC_HAS_VISIBILITY) - target_compile_options(mdbx PRIVATE "-fvisibility=hidden") -endif() - -install(TARGETS mdbx - LIBRARY DESTINATION lib COMPONENT runtime - RUNTIME DESTINATION bin COMPONENT runtime - ARCHIVE DESTINATION lib/static COMPONENT devel - PUBLIC_HEADER DESTINATION include - INCLUDES DESTINATION include COMPONENT devel) - -################################################################################ -# -# library build info (used in library version output) -# -set(MDBX_BUILD_FLAGS "") - -# append cmake's build-type flags and defines -if(NOT CMAKE_CONFIGURATION_TYPES) - list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UPPERCASE}}) - list(APPEND MDBX_BUILD_FLAGS ${CMAKE_C_DEFINES_${CMAKE_BUILD_TYPE_UPPERCASE}}) -endif() - -# append linker dll's options -if(LIBMDBX_TYPE STREQUAL "SHARED") - list(APPEND MDBX_BUILD_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) -endif() - -# get definitions -get_target_property(defs_list mdbx COMPILE_DEFINITIONS) -if(defs_list) - list(APPEND MDBX_BUILD_FLAGS ${defs_list}) -endif() - -# get target compile options -get_target_property(options_list mdbx COMPILE_OPTIONS) -if(options_list) - list(APPEND MDBX_BUILD_FLAGS ${options_list}) -endif() - -list(REMOVE_DUPLICATES MDBX_BUILD_FLAGS) -string(REPLACE ";" " " MDBX_BUILD_FLAGS "${MDBX_BUILD_FLAGS}") -if(CMAKE_CONFIGURATION_TYPES) - # add dynamic part via per-configuration define - message(STATUS "MDBX Compile Flags: ${MDBX_BUILD_FLAGS} ") - add_definitions(-DMDBX_BUILD_FLAGS_CONFIG="$<$:${CMAKE_C_FLAGS_DEBUG} ${CMAKE_C_DEFINES_DEBUG}>$<$:${CMAKE_C_FLAGS_RELEASE} ${CMAKE_C_DEFINES_RELEASE}>$<$:${CMAKE_C_FLAGS_RELWITHDEBINFO} ${CMAKE_C_DEFINES_RELWITHDEBINFO}>$<$:${CMAKE_C_FLAGS_MINSIZEREL} ${CMAKE_C_DEFINES_MINSIZEREL}>") -else() - message(STATUS "MDBX Compile Flags: ${MDBX_BUILD_FLAGS}") -endif() - -# get compiler info -execute_process(COMMAND sh -c "${CMAKE_C_COMPILER} --version | head -1" - OUTPUT_VARIABLE MDBX_BUILD_COMPILER - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET - RESULT_VARIABLE rc) -if(rc OR NOT MDBX_BUILD_COMPILER) - string(STRIP "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}" MDBX_BUILD_COMPILER) -endif() - -# make a build-target triplet -if(CMAKE_C_COMPILER_TARGET) - set(MDBX_BUILD_TARGET "${CMAKE_C_COMPILER_TARGET}") -elseif(CMAKE_C_PLATFORM_ID AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) - string(STRIP "${CMAKE_C_PLATFORM_ID}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_LIBRARY_ARCHITECTURE) - string(STRIP "${CMAKE_LIBRARY_ARCHITECTURE}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_GENERATOR_PLATFORM AND NOT CMAKE_C_PLATFORM_ID STREQUAL CMAKE_SYSTEM_NAME) - string(STRIP "${CMAKE_GENERATOR_PLATFORM}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -elseif(CMAKE_SYSTEM_ARCH) - string(STRIP "${CMAKE_SYSTEM_ARCH}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -else() - string(STRIP "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}" MDBX_BUILD_TARGET) -endif() -if(CMAKE_CONFIGURATION_TYPES) - add_definitions(-DMDBX_BUILD_CONFIG="$") -else() - set(MDBX_BUILD_CONFIG ${CMAKE_BUILD_TYPE}) -endif() - -# options -string(TIMESTAMP MDBX_BUILD_TIMESTAMP UTC) -set(options VERSION C_COMPILER CXX_COMPILER) -foreach(item IN LISTS options) - if(DEFINED ${item}) - set(value "${${item}}") - elseif(DEFINED MDBX_${item}) - set(item MDBX_${item}) - set(value "${${item}}") - elseif(DEFINED CMAKE_${item}) - set(item CMAKE_${item}) - set(value "${${item}}") - else() - set(value "undefined") - endif() - message(STATUS "${item}: ${value}") -endforeach(item) - -# generate version and config files -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/elements/version.c.in" - "${CMAKE_CURRENT_SOURCE_DIR}/elements/version.c" ESCAPE_QUOTES) - -file(SHA256 "${CMAKE_CURRENT_SOURCE_DIR}/elements/version.c" MDBX_SOURCERY_DIGEST) -string(MAKE_C_IDENTIFIER "${MDBX_GIT_DESCRIBE}" MDBX_SOURCERY_SUFFIX) -set(MDBX_BUILD_SOURCERY "${MDBX_SOURCERY_DIGEST}_${MDBX_SOURCERY_SUFFIX}") - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/elements/config.h.in" - "${CMAKE_CURRENT_SOURCE_DIR}/elements/config.h" ESCAPE_QUOTES) -add_definitions(-DMDBX_CONFIG_H="config.h") - -add_subdirectory(tools) diff --git a/src/contrib/db/libmdbx/src/alloy.c b/src/contrib/db/libmdbx/src/alloy.c deleted file mode 100644 index 98f3aac..0000000 --- a/src/contrib/db/libmdbx/src/alloy.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -/* Amalgamated build */ -#define MDBX_ALLOY 1 -#include "elements/internals.h" /* must be included fisrt */ - -#include "elements/core.c" -#include "elements/osal.c" -#include "elements/version.c" - -#if defined(_WIN32) || defined(_WIN64) -#include "elements/lck-windows.c" -#else -#include "elements/lck-posix.c" -#endif diff --git a/src/contrib/db/libmdbx/src/elements/config.h.in b/src/contrib/db/libmdbx/src/elements/config.h.in deleted file mode 100644 index 44ae150..0000000 --- a/src/contrib/db/libmdbx/src/elements/config.h.in +++ /dev/null @@ -1,56 +0,0 @@ -/* This is CMake-template for libmdbx's config.h - ******************************************************************************/ - -/* *INDENT-OFF* */ -/* clang-format off */ - -#cmakedefine HAVE_VALGRIND_MEMCHECK_H -#cmakedefine HAS_RELAXED_CONSTEXPR - -#cmakedefine LTO_ENABLED -#cmakedefine MDBX_USE_VALGRIND -#cmakedefine ENABLE_GPROF -#cmakedefine ENABLE_GCOV -#cmakedefine ENABLE_ASAN - -/* Common */ -#cmakedefine01 MDBX_TXN_CHECKPID -#cmakedefine01 MDBX_TXN_CHECKOWNER -#cmakedefine01 MDBX_BUILD_SHARED_LIBRARY - -/* Windows */ -#cmakedefine01 MDBX_CONFIG_MANUAL_TLS_CALLBACK -#cmakedefine01 MDBX_AVOID_CRT - -/* MacOS */ -#cmakedefine01 MDBX_OSX_SPEED_INSTEADOF_DURABILITY - -/* POSIX */ -#cmakedefine01 MDBX_USE_ROBUST -#cmakedefine01 MDBX_USE_OFDLOCKS -#cmakedefine01 MDBX_DISABLE_GNU_SOURCE - -/* Simulate "AUTO" values of tristate options */ -#cmakedefine MDBX_TXN_CHECKPID_AUTO -#ifdef MDBX_TXN_CHECKPID_AUTO -#undef MDBX_TXN_CHECKPID -#endif -#cmakedefine MDBX_USE_ROBUST_AUTO -#ifdef MDBX_USE_ROBUST_AUTO -#undef MDBX_USE_ROBUST -#endif -#cmakedefine MDBX_USE_OFDLOCKS_AUTO -#ifdef MDBX_USE_OFDLOCKS_AUTO -#undef MDBX_USE_OFDLOCKS -#endif - -/* Build Info */ -#cmakedefine MDBX_BUILD_TIMESTAMP "@MDBX_BUILD_TIMESTAMP@" -#cmakedefine MDBX_BUILD_TARGET "@MDBX_BUILD_TARGET@" -#cmakedefine MDBX_BUILD_CONFIG "@MDBX_BUILD_CONFIG@" -#cmakedefine MDBX_BUILD_COMPILER "@MDBX_BUILD_COMPILER@" -#cmakedefine MDBX_BUILD_FLAGS "@MDBX_BUILD_FLAGS@" -#cmakedefine MDBX_BUILD_SOURCERY @MDBX_BUILD_SOURCERY@ - -/* *INDENT-ON* */ -/* clang-format on */ diff --git a/src/contrib/db/libmdbx/src/elements/core.c b/src/contrib/db/libmdbx/src/elements/core.c deleted file mode 100644 index c64259c..0000000 --- a/src/contrib/db/libmdbx/src/elements/core.c +++ /dev/null @@ -1,16709 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * This code is derived from "LMDB engine" written by - * Howard Chu (Symas Corporation), which itself derived from btree.c - * written by Martin Hedenfalk. - * - * --- - * - * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - * - * --- - * - * Portions Copyright (c) 2009, 2010 Martin Hedenfalk - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include "internals.h" - -/*------------------------------------------------------------------------------ - * Internal inlines */ - -static __pure_function __inline bool is_powerof2(size_t x) { - return (x & (x - 1)) == 0; -} - -static __pure_function __inline size_t roundup_powerof2(size_t value, - size_t granularity) { - assert(is_powerof2(granularity)); - return (value + granularity - 1) & ~(granularity - 1); -} - -static __pure_function unsigned log2n(size_t value) { - assert(value > 0 && value < INT32_MAX && is_powerof2(value)); - assert((value & -(int32_t)value) == value); -#if __GNUC_PREREQ(4, 1) || __has_builtin(__builtin_ctzl) - return __builtin_ctzl(value); -#elif defined(_MSC_VER) - unsigned long index; - _BitScanForward(&index, (unsigned long)value); - return index; -#else - static const uint8_t debruijn_ctz32[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; - return debruijn_ctz32[(uint32_t)(value * 0x077CB531u) >> 27]; -#endif -} - -/*------------------------------------------------------------------------------ - * Unaligned access */ - -static __pure_function __maybe_unused __inline unsigned -field_alignment(unsigned alignment_baseline, size_t field_offset) { - unsigned merge = alignment_baseline | (unsigned)field_offset; - return merge & -(int)merge; -} - -/* read-thunk for UB-sanitizer */ -static __pure_function __inline uint8_t peek_u8(const uint8_t *ptr) { - return *ptr; -} - -/* write-thunk for UB-sanitizer */ -static __inline void poke_u8(uint8_t *ptr, const uint8_t v) { *ptr = v; } - -static __pure_function __inline uint16_t -unaligned_peek_u16(const unsigned expected_alignment, const void *ptr) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(uint16_t)) == 0) - return *(const uint16_t *)ptr; - else { - uint16_t v; - memcpy(&v, ptr, sizeof(v)); - return v; - } -} - -static __inline void unaligned_poke_u16(const unsigned expected_alignment, - void *ptr, const uint16_t v) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(v)) == 0) - *(uint16_t *)ptr = v; - else - memcpy(ptr, &v, sizeof(v)); -} - -static __pure_function __inline uint32_t -unaligned_peek_u32(const unsigned expected_alignment, const void *ptr) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(uint32_t)) == 0) - return *(const uint32_t *)ptr; - else if ((expected_alignment % sizeof(uint16_t)) == 0) { - const uint16_t lo = - ((const uint16_t *)ptr)[__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__]; - const uint16_t hi = - ((const uint16_t *)ptr)[__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__]; - return lo | (uint32_t)hi << 16; - } else { - uint32_t v; - memcpy(&v, ptr, sizeof(v)); - return v; - } -} - -static __inline void unaligned_poke_u32(const unsigned expected_alignment, - void *ptr, const uint32_t v) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(v)) == 0) - *(uint32_t *)ptr = v; - else if ((expected_alignment % sizeof(uint16_t)) == 0) { - ((uint16_t *)ptr)[__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__] = (uint16_t)v; - ((uint16_t *)ptr)[__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__] = - (uint16_t)(v >> 16); - } else - memcpy(ptr, &v, sizeof(v)); -} - -static __pure_function __inline uint64_t -unaligned_peek_u64(const unsigned expected_alignment, const void *ptr) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(uint64_t)) == 0) - return *(const uint64_t *)ptr; - else if ((expected_alignment % sizeof(uint32_t)) == 0) { - const uint32_t lo = - ((const uint32_t *)ptr)[__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__]; - const uint32_t hi = - ((const uint32_t *)ptr)[__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__]; - return lo | (uint64_t)hi << 32; - } else { - uint64_t v; - memcpy(&v, ptr, sizeof(v)); - return v; - } -} - -static __inline void unaligned_poke_u64(const unsigned expected_alignment, - void *ptr, const uint64_t v) { - assert((uintptr_t)ptr % expected_alignment == 0); - if (MDBX_UNALIGNED_OK || (expected_alignment % sizeof(v)) == 0) - *(uint64_t *)ptr = v; - else if ((expected_alignment % sizeof(uint32_t)) == 0) { - ((uint32_t *)ptr)[__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__] = (uint32_t)v; - ((uint32_t *)ptr)[__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__] = - (uint32_t)(v >> 32); - } else - memcpy(ptr, &v, sizeof(v)); -} - -#define UNALIGNED_PEEK_8(ptr, struct, field) \ - peek_u8((const uint8_t *)(ptr) + offsetof(struct, field)) -#define UNALIGNED_POKE_8(ptr, struct, field, value) \ - poke_u8((uint8_t *)(ptr) + offsetof(struct, field), value) - -#define UNALIGNED_PEEK_16(ptr, struct, field) \ - unaligned_peek_u16(1, (const char *)(ptr) + offsetof(struct, field)) -#define UNALIGNED_POKE_16(ptr, struct, field, value) \ - unaligned_poke_u16(1, (char *)(ptr) + offsetof(struct, field), value) - -#define UNALIGNED_PEEK_32(ptr, struct, field) \ - unaligned_peek_u32(1, (const char *)(ptr) + offsetof(struct, field)) -#define UNALIGNED_POKE_32(ptr, struct, field, value) \ - unaligned_poke_u32(1, (char *)(ptr) + offsetof(struct, field), value) - -#define UNALIGNED_PEEK_64(ptr, struct, field) \ - unaligned_peek_u64(1, (const char *)(ptr) + offsetof(struct, field)) -#define UNALIGNED_POKE_64(ptr, struct, field, value) \ - unaligned_poke_u64(1, (char *)(ptr) + offsetof(struct, field), value) - -/* Get the page number pointed to by a branch node */ -static __pure_function __inline pgno_t node_pgno(const MDBX_node *node) { - pgno_t pgno = UNALIGNED_PEEK_32(node, MDBX_node, mn_pgno32); - if (sizeof(pgno) > 4) - pgno |= ((uint64_t)UNALIGNED_PEEK_8(node, MDBX_node, mn_extra)) << 32; - return pgno; -} - -/* Set the page number in a branch node */ -static __inline void node_set_pgno(MDBX_node *node, pgno_t pgno) { - assert(pgno >= MIN_PAGENO && pgno <= MAX_PAGENO); - - UNALIGNED_POKE_32(node, MDBX_node, mn_pgno32, (uint32_t)pgno); - if (sizeof(pgno) > 4) - UNALIGNED_POKE_8(node, MDBX_node, mn_extra, - (uint8_t)((uint64_t)pgno >> 32)); -} - -/* Get the size of the data in a leaf node */ -static __pure_function __inline size_t node_ds(const MDBX_node *node) { - return UNALIGNED_PEEK_32(node, MDBX_node, mn_dsize); -} - -/* Set the size of the data for a leaf node */ -static __inline void node_set_ds(MDBX_node *node, size_t size) { - assert(size < INT_MAX); - UNALIGNED_POKE_32(node, MDBX_node, mn_dsize, (uint32_t)size); -} - -/* The size of a key in a node */ -static __pure_function __inline size_t node_ks(const MDBX_node *node) { - return UNALIGNED_PEEK_16(node, MDBX_node, mn_ksize); -} - -/* Set the size of the key for a leaf node */ -static __inline void node_set_ks(MDBX_node *node, size_t size) { - assert(size < INT16_MAX); - UNALIGNED_POKE_16(node, MDBX_node, mn_ksize, (uint16_t)size); -} - -static __pure_function __inline uint8_t node_flags(const MDBX_node *node) { - return UNALIGNED_PEEK_8(node, MDBX_node, mn_flags); -} - -static __inline void node_set_flags(MDBX_node *node, uint8_t flags) { - UNALIGNED_POKE_8(node, MDBX_node, mn_flags, flags); -} - -/* Size of the node header, excluding dynamic data at the end */ -#define NODESIZE offsetof(MDBX_node, mn_data) - -/* Address of the key for the node */ -static __pure_function __inline void *node_key(const MDBX_node *node) { - return (char *)node + NODESIZE; -} - -/* Address of the data for a node */ -static __pure_function __inline void *node_data(const MDBX_node *node) { - return (char *)node_key(node) + node_ks(node); -} - -/* Size of a node in a leaf page with a given key and data. - * This is node header plus key plus data size. */ -static __pure_function __inline size_t node_size(const MDBX_val *key, - const MDBX_val *value) { - return NODESIZE + - EVEN((key ? key->iov_len : 0) + (value ? value->iov_len : 0)); -} - -static __pure_function __inline pgno_t peek_pgno(const void *ptr) { - if (sizeof(pgno_t) == sizeof(uint32_t)) - return (pgno_t)unaligned_peek_u32(1, ptr); - else if (sizeof(pgno_t) == sizeof(uint64_t)) - return (pgno_t)unaligned_peek_u64(1, ptr); - else { - pgno_t pgno; - memcpy(&pgno, ptr, sizeof(pgno)); - return pgno; - } -} - -static __inline void poke_pgno(void *ptr, const pgno_t pgno) { - if (sizeof(pgno) == sizeof(uint32_t)) - unaligned_poke_u32(1, ptr, pgno); - else if (sizeof(pgno) == sizeof(uint64_t)) - unaligned_poke_u64(1, ptr, pgno); - else - memcpy(ptr, &pgno, sizeof(pgno)); -} - -static __pure_function __inline pgno_t -node_largedata_pgno(const MDBX_node *node) { - assert(node_flags(node) & F_BIGDATA); - return peek_pgno(node_data(node)); -} - -/* Calculate the size of a leaf node. - * - * The size depends on the environment's page size; if a data item - * is too large it will be put onto an overflow page and the node - * size will only include the key and not the data. Sizes are always - * rounded up to an even number of bytes, to guarantee 2-byte alignment - * of the MDBX_node headers. - * - * [in] env The environment handle. - * [in] key The key for the node. - * [in] data The data for the node. - * - * Returns The number of bytes needed to store the node. */ -static __pure_function __inline size_t -leaf_size(const MDBX_env *env, const MDBX_val *key, const MDBX_val *data) { - size_t node_bytes = node_size(key, data); - if (node_bytes > env->me_nodemax) { - /* put on overflow page */ - node_bytes = node_size(key, nullptr) + sizeof(pgno_t); - } - - return node_bytes + sizeof(indx_t); -} - -/* Calculate the size of a branch node. - * - * The size should depend on the environment's page size but since - * we currently don't support spilling large keys onto overflow - * pages, it's simply the size of the MDBX_node header plus the - * size of the key. Sizes are always rounded up to an even number - * of bytes, to guarantee 2-byte alignment of the MDBX_node headers. - * - * [in] env The environment handle. - * [in] key The key for the node. - * - * Returns The number of bytes needed to store the node. */ -static __pure_function __inline size_t branch_size(const MDBX_env *env, - const MDBX_val *key) { - /* Size of a node in a branch page with a given key. - * This is just the node header plus the key, there is no data. */ - size_t node_bytes = node_size(key, nullptr); - if (unlikely(node_bytes > env->me_nodemax)) { - /* put on overflow page */ - /* not implemented */ - mdbx_assert_fail(env, "INDXSIZE(key) <= env->me_nodemax", __func__, - __LINE__); - node_bytes = node_size(key, nullptr) + sizeof(pgno_t); - } - - return node_bytes + sizeof(indx_t); -} - -/*----------------------------------------------------------------------------*/ - -static __pure_function __inline size_t pgno2bytes(const MDBX_env *env, - pgno_t pgno) { - mdbx_assert(env, (1u << env->me_psize2log) == env->me_psize); - return ((size_t)pgno) << env->me_psize2log; -} - -static __pure_function __inline MDBX_page *pgno2page(const MDBX_env *env, - pgno_t pgno) { - return (MDBX_page *)(env->me_map + pgno2bytes(env, pgno)); -} - -static __pure_function __inline pgno_t bytes2pgno(const MDBX_env *env, - size_t bytes) { - mdbx_assert(env, (env->me_psize >> env->me_psize2log) == 1); - return (pgno_t)(bytes >> env->me_psize2log); -} - -static __pure_function __inline size_t pgno_align2os_bytes(const MDBX_env *env, - pgno_t pgno) { - return roundup_powerof2(pgno2bytes(env, pgno), env->me_os_psize); -} - -static __pure_function __inline pgno_t pgno_align2os_pgno(const MDBX_env *env, - pgno_t pgno) { - return bytes2pgno(env, pgno_align2os_bytes(env, pgno)); -} - -static __pure_function __inline size_t bytes_align2os_bytes(const MDBX_env *env, - size_t bytes) { - return roundup_powerof2(roundup_powerof2(bytes, env->me_psize), - env->me_os_psize); -} - -/* Address of first usable data byte in a page, after the header */ -static __pure_function __inline void *page_data(const MDBX_page *mp) { - return (char *)mp + PAGEHDRSZ; -} - -static __pure_function __inline const MDBX_page *data_page(const void *data) { - return container_of(data, MDBX_page, mp_ptrs); -} - -static __pure_function __inline MDBX_meta *page_meta(MDBX_page *mp) { - return (MDBX_meta *)page_data(mp); -} - -/* Number of nodes on a page */ -static __pure_function __inline unsigned page_numkeys(const MDBX_page *mp) { - return mp->mp_lower >> 1; -} - -/* The amount of space remaining in the page */ -static __pure_function __inline unsigned page_room(const MDBX_page *mp) { - return mp->mp_upper - mp->mp_lower; -} - -static __pure_function __inline unsigned page_space(const MDBX_env *env) { - STATIC_ASSERT(PAGEHDRSZ % 2 == 0); - return env->me_psize - PAGEHDRSZ; -} - -static __pure_function __inline unsigned page_used(const MDBX_env *env, - const MDBX_page *mp) { - return page_space(env) - page_room(mp); -} - -/* The percentage of space used in the page, in a percents. */ -static __pure_function __maybe_unused __inline double -page_fill(const MDBX_env *env, const MDBX_page *mp) { - return page_used(env, mp) * 100.0 / page_space(env); -} - -static __pure_function __inline bool -page_fill_enough(const MDBX_page *mp, unsigned spaceleft_threshold, - unsigned minkeys_threshold) { - return page_room(mp) < spaceleft_threshold && - page_numkeys(mp) >= minkeys_threshold; -} - -/* The number of overflow pages needed to store the given size. */ -static __pure_function __inline pgno_t number_of_ovpages(const MDBX_env *env, - size_t bytes) { - return bytes2pgno(env, PAGEHDRSZ - 1 + bytes) + 1; -} - -/* Address of node i in page p */ -static __pure_function __inline MDBX_node *page_node(const MDBX_page *mp, - unsigned i) { - assert((mp->mp_flags & (P_LEAF2 | P_OVERFLOW | P_META)) == 0); - assert(page_numkeys(mp) > (unsigned)(i)); - assert(mp->mp_ptrs[i] % 2 == 0); - return (MDBX_node *)((char *)mp + mp->mp_ptrs[i] + PAGEHDRSZ); -} - -/* The address of a key in a LEAF2 page. - * LEAF2 pages are used for MDBX_DUPFIXED sorted-duplicate sub-DBs. - * There are no node headers, keys are stored contiguously. */ -static __pure_function __inline void * -page_leaf2key(const MDBX_page *mp, unsigned i, size_t keysize) { - assert(mp->mp_leaf2_ksize == keysize); - (void)keysize; - return (char *)mp + PAGEHDRSZ + (i * mp->mp_leaf2_ksize); -} - -/* Set the node's key into keyptr. */ -static __inline void get_key(const MDBX_node *node, MDBX_val *keyptr) { - keyptr->iov_len = node_ks(node); - keyptr->iov_base = node_key(node); -} - -/* Set the node's key into keyptr, if requested. */ -static __inline void get_key_optional(const MDBX_node *node, - MDBX_val *keyptr /* __may_null */) { - if (keyptr) - get_key(node, keyptr); -} - -/*------------------------------------------------------------------------------ - * LY: temporary workaround for Elbrus's memcmp() bug. */ - -#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) -int __hot mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, - size_t n) { - if (unlikely(n > 42 - /* LY: align followed access if reasonable possible */ - && (((uintptr_t)s1) & 7) != 0 && - (((uintptr_t)s1) & 7) == (((uintptr_t)s2) & 7))) { - if (((uintptr_t)s1) & 1) { - const int diff = *(uint8_t *)s1 - *(uint8_t *)s2; - if (diff) - return diff; - s1 = (char *)s1 + 1; - s2 = (char *)s2 + 1; - n -= 1; - } - - if (((uintptr_t)s1) & 2) { - const uint16_t a = *(uint16_t *)s1; - const uint16_t b = *(uint16_t *)s2; - if (likely(a != b)) - return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; - s1 = (char *)s1 + 2; - s2 = (char *)s2 + 2; - n -= 2; - } - - if (((uintptr_t)s1) & 4) { - const uint32_t a = *(uint32_t *)s1; - const uint32_t b = *(uint32_t *)s2; - if (likely(a != b)) - return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; - s1 = (char *)s1 + 4; - s2 = (char *)s2 + 4; - n -= 4; - } - } - - while (n >= 8) { - const uint64_t a = *(uint64_t *)s1; - const uint64_t b = *(uint64_t *)s2; - if (likely(a != b)) - return (__builtin_bswap64(a) > __builtin_bswap64(b)) ? 1 : -1; - s1 = (char *)s1 + 8; - s2 = (char *)s2 + 8; - n -= 8; - } - - if (n & 4) { - const uint32_t a = *(uint32_t *)s1; - const uint32_t b = *(uint32_t *)s2; - if (likely(a != b)) - return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; - s1 = (char *)s1 + 4; - s2 = (char *)s2 + 4; - } - - if (n & 2) { - const uint16_t a = *(uint16_t *)s1; - const uint16_t b = *(uint16_t *)s2; - if (likely(a != b)) - return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; - s1 = (char *)s1 + 2; - s2 = (char *)s2 + 2; - } - - return (n & 1) ? *(uint8_t *)s1 - *(uint8_t *)s2 : 0; -} - -int __hot mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2) { - while (true) { - int diff = *(uint8_t *)s1 - *(uint8_t *)s2; - if (likely(diff != 0) || *s1 == '\0') - return diff; - s1 += 1; - s2 += 1; - } -} - -int __hot mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, - size_t n) { - while (n > 0) { - int diff = *(uint8_t *)s1 - *(uint8_t *)s2; - if (likely(diff != 0) || *s1 == '\0') - return diff; - s1 += 1; - s2 += 1; - n -= 1; - } - return 0; -} - -size_t __hot mdbx_e2k_strlen_bug_workaround(const char *s) { - size_t n = 0; - while (*s) { - s += 1; - n += 1; - } - return n; -} - -size_t __hot mdbx_e2k_strnlen_bug_workaround(const char *s, size_t maxlen) { - size_t n = 0; - while (maxlen > n && *s) { - s += 1; - n += 1; - } - return n; -} -#endif /* Elbrus's memcmp() bug. */ - -/*------------------------------------------------------------------------------ - * safe read/write volatile 64-bit fields on 32-bit architectures. */ - -static __inline void atomic_yield(void) { -#if defined(_WIN32) || defined(_WIN64) - YieldProcessor(); -#elif defined(__x86_64__) || defined(__i386__) || defined(__e2k__) - __builtin_ia32_pause(); -#elif defined(__ia64__) -#if defined(__HP_cc__) || defined(__HP_aCC__) - _Asm_hint(_HINT_PAUSE); -#else - __asm__ __volatile__("hint @pause"); -#endif -#elif defined(__arm__) || defined(__aarch64__) -#ifdef __CC_ARM - __yield(); -#else - __asm__ __volatile__("yield"); -#endif -#elif (defined(__mips64) || defined(__mips64__)) && defined(__mips_isa_rev) && \ - __mips_isa_rev >= 2 - __asm__ __volatile__("pause"); -#elif defined(__mips) || defined(__mips__) || defined(__mips64) || \ - defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \ - defined(__MWERKS__) || defined(__sgi) - __asm__ __volatile__(".word 0x00000140"); -#else - pthread_yield(); -#endif -} - -#if MDBX_64BIT_CAS -static __inline bool atomic_cas64(volatile uint64_t *p, uint64_t c, - uint64_t v) { -#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_LLONG_LOCK_FREE) - STATIC_ASSERT(sizeof(long long int) == 8); - STATIC_ASSERT(atomic_is_lock_free(p)); - return atomic_compare_exchange_strong((_Atomic uint64_t *)p, &c, v); -#elif defined(__GNUC__) || defined(__clang__) - return __sync_bool_compare_and_swap(p, c, v); -#elif defined(_MSC_VER) - return c == - (uint64_t)_InterlockedCompareExchange64((volatile int64_t *)p, v, c); -#elif defined(__APPLE__) - return OSAtomicCompareAndSwap64Barrier(c, v, (volatile uint64_t *)p); -#else -#error FIXME: Unsupported compiler -#endif -} -#endif /* MDBX_64BIT_CAS */ - -static __inline bool atomic_cas32(volatile uint32_t *p, uint32_t c, - uint32_t v) { -#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_LONG_LOCK_FREE) - STATIC_ASSERT(sizeof(long int) >= 4); - STATIC_ASSERT(atomic_is_lock_free(p)); - return atomic_compare_exchange_strong((_Atomic uint32_t *)p, &c, v); -#elif defined(__GNUC__) || defined(__clang__) - return __sync_bool_compare_and_swap(p, c, v); -#elif defined(_MSC_VER) - STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t)); - return c == (uint32_t)_InterlockedCompareExchange((volatile long *)p, v, c); -#elif defined(__APPLE__) - return OSAtomicCompareAndSwap32Barrier(c, v, (volatile int32_t *)p); -#else -#error FIXME: Unsupported compiler -#endif -} - -static __inline uint32_t atomic_add32(volatile uint32_t *p, uint32_t v) { -#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_LONG_LOCK_FREE) - STATIC_ASSERT(sizeof(long int) >= 4); - STATIC_ASSERT(atomic_is_lock_free(p)); - return atomic_fetch_add((_Atomic uint32_t *)p, v); -#elif defined(__GNUC__) || defined(__clang__) - return __sync_fetch_and_add(p, v); -#elif defined(_MSC_VER) - STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t)); - return _InterlockedExchangeAdd((volatile long *)p, v); -#elif defined(__APPLE__) - return OSAtomicAdd32Barrier(v, (volatile int32_t *)p); -#else -#error FIXME: Unsupported compiler -#endif -} - -#define atomic_sub32(p, v) atomic_add32(p, 0 - (v)) - -static __maybe_unused __inline bool safe64_is_valid(uint64_t v) { -#if MDBX_WORDBITS >= 64 - return v < SAFE64_INVALID_THRESHOLD; -#else - return (v >> 32) != UINT32_MAX; -#endif /* MDBX_WORDBITS */ -} - -static __maybe_unused __inline bool -safe64_is_valid_ptr(const mdbx_safe64_t *ptr) { - mdbx_compiler_barrier(); -#if MDBX_64BIT_ATOMIC - return ptr->atomic < SAFE64_INVALID_THRESHOLD; -#else - return ptr->high != UINT32_MAX; -#endif /* MDBX_64BIT_ATOMIC */ -} - -static __inline uint64_t safe64_txnid_next(uint64_t txnid) { - txnid += MDBX_TXNID_STEP; -#if !MDBX_64BIT_CAS - /* avoid overflow of low-part in safe64_reset() */ - txnid += (UINT32_MAX == (uint32_t)txnid); -#endif - return txnid; -} - -static __inline void safe64_reset(mdbx_safe64_t *ptr, bool single_writer) { - mdbx_compiler_barrier(); -#if !MDBX_64BIT_CAS - if (!single_writer) { - STATIC_ASSERT(MDBX_TXNID_STEP > 1); - /* it is safe to increment low-part to avoid ABA, since MDBX_TXNID_STEP > 1 - * and overflow was preserved in safe64_txnid_next() */ - atomic_add32(&ptr->low, 1) /* avoid ABA in safe64_reset_compare() */; - ptr->high = UINT32_MAX /* atomically make >= SAFE64_INVALID_THRESHOLD */; - atomic_add32(&ptr->low, 1) /* avoid ABA in safe64_reset_compare() */; - } else -#else - (void)single_writer; -#endif /* !MDBX_64BIT_CAS */ -#if MDBX_64BIT_ATOMIC - ptr->atomic = UINT64_MAX; -#else - /* atomically make value >= SAFE64_INVALID_THRESHOLD */ - ptr->high = UINT32_MAX; -#endif /* MDBX_64BIT_ATOMIC */ - assert(ptr->inconsistent >= SAFE64_INVALID_THRESHOLD); - mdbx_flush_noncoherent_cpu_writeback(); - mdbx_jitter4testing(true); -} - -static __inline bool safe64_reset_compare(mdbx_safe64_t *ptr, txnid_t compare) { - mdbx_compiler_barrier(); - /* LY: This function is used to reset `mr_txnid` from OOM-kick in case - * the asynchronously cancellation of read transaction. Therefore, - * there may be a collision between the cleanup performed here and - * asynchronous termination and restarting of the read transaction - * in another proces/thread. In general we MUST NOT reset the `mr_txnid` - * if a new transaction was started (i.e. if `mr_txnid` was changed). */ -#if MDBX_64BIT_CAS - bool rc = atomic_cas64(&ptr->inconsistent, compare, UINT64_MAX); - mdbx_flush_noncoherent_cpu_writeback(); -#else - /* LY: There is no gold ratio here since shared mutex is too costly, - * in such way we must acquire/release it for every update of mr_txnid, - * i.e. twice for each read transaction). */ - bool rc = false; - if (likely(ptr->low == (uint32_t)compare && - atomic_cas32(&ptr->high, (uint32_t)(compare >> 32), UINT32_MAX))) { - if (unlikely(ptr->low != (uint32_t)compare)) - atomic_cas32(&ptr->high, UINT32_MAX, (uint32_t)(compare >> 32)); - else - rc = true; - } -#endif /* MDBX_64BIT_CAS */ - mdbx_jitter4testing(true); - return rc; -} - -static __inline void safe64_write(mdbx_safe64_t *ptr, const uint64_t v) { - mdbx_compiler_barrier(); - assert(ptr->inconsistent >= SAFE64_INVALID_THRESHOLD); -#if MDBX_64BIT_ATOMIC - ptr->atomic = v; -#else /* MDBX_64BIT_ATOMIC */ - /* update low-part but still value >= SAFE64_INVALID_THRESHOLD */ - ptr->low = (uint32_t)v; - assert(ptr->inconsistent >= SAFE64_INVALID_THRESHOLD); - mdbx_flush_noncoherent_cpu_writeback(); - mdbx_jitter4testing(true); - /* update high-part from SAFE64_INVALID_THRESHOLD to actual value */ - ptr->high = (uint32_t)(v >> 32); -#endif /* MDBX_64BIT_ATOMIC */ - assert(ptr->inconsistent == v); - mdbx_flush_noncoherent_cpu_writeback(); - mdbx_jitter4testing(true); -} - -static __always_inline uint64_t safe64_read(const mdbx_safe64_t *ptr) { - mdbx_compiler_barrier(); - mdbx_jitter4testing(true); - uint64_t v; -#if MDBX_64BIT_ATOMIC - v = ptr->atomic; -#else /* MDBX_64BIT_ATOMIC */ - uint32_t hi, lo; - do { - hi = ptr->high; - mdbx_compiler_barrier(); - mdbx_jitter4testing(true); - lo = ptr->low; - mdbx_compiler_barrier(); - mdbx_jitter4testing(true); - } while (unlikely(hi != ptr->high)); - v = lo | (uint64_t)hi << 32; -#endif /* MDBX_64BIT_ATOMIC */ - mdbx_jitter4testing(true); - return v; -} - -static __inline void safe64_update(mdbx_safe64_t *ptr, const uint64_t v) { - safe64_reset(ptr, true); - safe64_write(ptr, v); -} - -/*----------------------------------------------------------------------------*/ -/* rthc (tls keys and destructors) */ - -typedef struct rthc_entry_t { - MDBX_reader *begin; - MDBX_reader *end; - mdbx_thread_key_t thr_tls_key; - bool key_valid; -} rthc_entry_t; - -#if MDBX_DEBUG -#define RTHC_INITIAL_LIMIT 1 -#else -#define RTHC_INITIAL_LIMIT 16 -#endif - -static bin128_t bootid; -#if defined(_WIN32) || defined(_WIN64) -static CRITICAL_SECTION rthc_critical_section; -static CRITICAL_SECTION lcklist_critical_section; -#else -int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol) - __attribute__((__weak__)); -#ifdef __APPLE__ /* FIXME: Thread-Local Storage destructors & DSO-unloading */ -int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, - void *dso_symbol) { - (void)dtor; - (void)obj; - (void)dso_symbol; - return -1; -} -#endif /* __APPLE__ */ - -static pthread_mutex_t lcklist_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t rthc_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t rthc_cond = PTHREAD_COND_INITIALIZER; -static mdbx_thread_key_t rthc_key; -static volatile uint32_t rthc_pending; - -static void __cold workaround_glibc_bug21031(void) { - /* Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=21031 - * - * Due race between pthread_key_delete() and __nptl_deallocate_tsd() - * The destructor(s) of thread-local-storate object(s) may be running - * in another thread(s) and be blocked or not finished yet. - * In such case we get a SEGFAULT after unload this library DSO. - * - * So just by yielding a few timeslices we give a chance - * to such destructor(s) for completion and avoids segfault. */ - sched_yield(); - sched_yield(); - sched_yield(); -} -#endif - -static unsigned rthc_count, rthc_limit; -static rthc_entry_t *rthc_table; -static rthc_entry_t rthc_table_static[RTHC_INITIAL_LIMIT]; - -static __inline void rthc_lock(void) { -#if defined(_WIN32) || defined(_WIN64) - EnterCriticalSection(&rthc_critical_section); -#else - mdbx_ensure(nullptr, pthread_mutex_lock(&rthc_mutex) == 0); -#endif -} - -static __inline void rthc_unlock(void) { -#if defined(_WIN32) || defined(_WIN64) - LeaveCriticalSection(&rthc_critical_section); -#else - mdbx_ensure(nullptr, pthread_mutex_unlock(&rthc_mutex) == 0); -#endif -} - -static __inline int thread_key_create(mdbx_thread_key_t *key) { - int rc; -#if defined(_WIN32) || defined(_WIN64) - *key = TlsAlloc(); - rc = (*key != TLS_OUT_OF_INDEXES) ? MDBX_SUCCESS : GetLastError(); -#else - rc = pthread_key_create(key, nullptr); -#endif - mdbx_trace("&key = %p, value 0x%x, rc %d", __Wpedantic_format_voidptr(key), - (unsigned)*key, rc); - return rc; -} - -static __inline void thread_key_delete(mdbx_thread_key_t key) { - mdbx_trace("key = 0x%x", (unsigned)key); -#if defined(_WIN32) || defined(_WIN64) - mdbx_ensure(nullptr, TlsFree(key)); -#else - mdbx_ensure(nullptr, pthread_key_delete(key) == 0); - workaround_glibc_bug21031(); -#endif -} - -static __inline void *thread_rthc_get(mdbx_thread_key_t key) { -#if defined(_WIN32) || defined(_WIN64) - return TlsGetValue(key); -#else - return pthread_getspecific(key); -#endif -} - -static void thread_rthc_set(mdbx_thread_key_t key, const void *value) { -#if defined(_WIN32) || defined(_WIN64) - mdbx_ensure(nullptr, TlsSetValue(key, (void *)value)); -#else -#define MDBX_THREAD_RTHC_ZERO 0 -#define MDBX_THREAD_RTHC_REGISTERD 1 -#define MDBX_THREAD_RTHC_COUNTED 2 - static __thread uint32_t thread_registration_state; - if (value && unlikely(thread_registration_state == MDBX_THREAD_RTHC_ZERO)) { - thread_registration_state = MDBX_THREAD_RTHC_REGISTERD; - mdbx_trace("thread registered 0x%" PRIxPTR, (uintptr_t)mdbx_thread_self()); - if (&__cxa_thread_atexit_impl == nullptr || - __cxa_thread_atexit_impl(mdbx_rthc_thread_dtor, - &thread_registration_state, - (void *)&mdbx_version /* dso_anchor */)) { - mdbx_ensure(nullptr, pthread_setspecific( - rthc_key, &thread_registration_state) == 0); - thread_registration_state = MDBX_THREAD_RTHC_COUNTED; - const unsigned count_before = atomic_add32(&rthc_pending, 1); - mdbx_ensure(nullptr, count_before < INT_MAX); - mdbx_trace("fallback to pthreads' tsd, key 0x%x, count %u", - (unsigned)rthc_key, count_before); - (void)count_before; - } - } - mdbx_ensure(nullptr, pthread_setspecific(key, value) == 0); -#endif -} - -__cold void mdbx_rthc_global_init(void) { - rthc_limit = RTHC_INITIAL_LIMIT; - rthc_table = rthc_table_static; -#if defined(_WIN32) || defined(_WIN64) - InitializeCriticalSection(&rthc_critical_section); - InitializeCriticalSection(&lcklist_critical_section); -#else - mdbx_ensure(nullptr, - pthread_key_create(&rthc_key, mdbx_rthc_thread_dtor) == 0); - mdbx_trace("pid %d, &mdbx_rthc_key = %p, value 0x%x", mdbx_getpid(), - __Wpedantic_format_voidptr(&rthc_key), (unsigned)rthc_key); -#endif - /* checking time conversion, this also avoids racing on 32-bit architectures - * during writing calculated 64-bit ratio(s) into memory. */ - uint32_t proba = UINT32_MAX; - while (true) { - unsigned time_conversion_checkup = - mdbx_osal_monotime_to_16dot16(mdbx_osal_16dot16_to_monotime(proba)); - unsigned one_more = (proba < UINT32_MAX) ? proba + 1 : proba; - unsigned one_less = (proba > 0) ? proba - 1 : proba; - mdbx_ensure(nullptr, time_conversion_checkup >= one_less && - time_conversion_checkup <= one_more); - if (proba == 0) - break; - proba >>= 1; - } - - bootid = mdbx_osal_bootid(); -} - -/* dtor called for thread, i.e. for all mdbx's environment objects */ -__cold void mdbx_rthc_thread_dtor(void *ptr) { - rthc_lock(); - mdbx_trace(">> pid %d, thread 0x%" PRIxPTR ", rthc %p", mdbx_getpid(), - (uintptr_t)mdbx_thread_self(), ptr); - - const uint32_t self_pid = mdbx_getpid(); - for (unsigned i = 0; i < rthc_count; ++i) { - if (!rthc_table[i].key_valid) - continue; - const mdbx_thread_key_t key = rthc_table[i].thr_tls_key; - MDBX_reader *const rthc = thread_rthc_get(key); - if (rthc < rthc_table[i].begin || rthc >= rthc_table[i].end) - continue; -#if !defined(_WIN32) && !defined(_WIN64) - if (pthread_setspecific(key, nullptr) != 0) { - mdbx_trace("== thread 0x%" PRIxPTR - ", rthc %p: ignore race with tsd-key deletion", - (uintptr_t)mdbx_thread_self(), ptr); - continue /* ignore race with tsd-key deletion by mdbx_env_close() */; - } -#endif - - mdbx_trace("== thread 0x%" PRIxPTR - ", rthc %p, [%i], %p ... %p (%+i), rtch-pid %i, " - "current-pid %i", - (uintptr_t)mdbx_thread_self(), __Wpedantic_format_voidptr(rthc), - i, __Wpedantic_format_voidptr(rthc_table[i].begin), - __Wpedantic_format_voidptr(rthc_table[i].end), - (int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid); - if (rthc->mr_pid == self_pid) { - mdbx_trace("==== thread 0x%" PRIxPTR ", rthc %p, cleanup", - (uintptr_t)mdbx_thread_self(), - __Wpedantic_format_voidptr(rthc)); - rthc->mr_pid = 0; - } - } - -#if defined(_WIN32) || defined(_WIN64) - mdbx_trace("<< thread 0x%" PRIxPTR ", rthc %p", (uintptr_t)mdbx_thread_self(), - ptr); - rthc_unlock(); -#else - const char self_registration = *(char *)ptr; - *(char *)ptr = MDBX_THREAD_RTHC_ZERO; - mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d", - (uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid(), - self_registration); - if (self_registration == MDBX_THREAD_RTHC_COUNTED) - mdbx_ensure(nullptr, atomic_sub32(&rthc_pending, 1) > 0); - - if (rthc_pending == 0) { - mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, wake", - (uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid()); - mdbx_ensure(nullptr, pthread_cond_broadcast(&rthc_cond) == 0); - } - - mdbx_trace("<< thread 0x%" PRIxPTR ", rthc %p", (uintptr_t)mdbx_thread_self(), - ptr); - /* Allow tail call optimization, i.e. gcc should generate the jmp instruction - * instead of a call for pthread_mutex_unlock() and therefore CPU could not - * return to current DSO's code section, which may be unloaded immediately - * after the mutex got released. */ - pthread_mutex_unlock(&rthc_mutex); -#endif -} - -__cold void mdbx_rthc_global_dtor(void) { - mdbx_trace(">> pid %d", mdbx_getpid()); - - rthc_lock(); -#if !defined(_WIN32) && !defined(_WIN64) - char *rthc = (char *)pthread_getspecific(rthc_key); - mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d", - (uintptr_t)mdbx_thread_self(), __Wpedantic_format_voidptr(rthc), - mdbx_getpid(), rthc ? *rthc : -1); - if (rthc) { - const char self_registration = *(char *)rthc; - *rthc = MDBX_THREAD_RTHC_ZERO; - if (self_registration == MDBX_THREAD_RTHC_COUNTED) - mdbx_ensure(nullptr, atomic_sub32(&rthc_pending, 1) > 0); - } - - struct timespec abstime; - mdbx_ensure(nullptr, clock_gettime(CLOCK_REALTIME, &abstime) == 0); - abstime.tv_nsec += 1000000000l / 10; - if (abstime.tv_nsec >= 1000000000l) { - abstime.tv_nsec -= 1000000000l; - abstime.tv_sec += 1; - } -#if MDBX_DEBUG > 0 - abstime.tv_sec += 600; -#endif - - for (unsigned left; (left = rthc_pending) > 0;) { - mdbx_trace("pid %d, pending %u, wait for...", mdbx_getpid(), left); - const int rc = pthread_cond_timedwait(&rthc_cond, &rthc_mutex, &abstime); - if (rc && rc != EINTR) - break; - } - thread_key_delete(rthc_key); -#endif - - const uint32_t self_pid = mdbx_getpid(); - for (unsigned i = 0; i < rthc_count; ++i) { - if (!rthc_table[i].key_valid) - continue; - const mdbx_thread_key_t key = rthc_table[i].thr_tls_key; - thread_key_delete(key); - for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end; - ++rthc) { - mdbx_trace("== [%i] = key %zu, %p ... %p, rthc %p (%+i), " - "rthc-pid %i, current-pid %i", - i, (size_t)key, - __Wpedantic_format_voidptr(rthc_table[i].begin), - __Wpedantic_format_voidptr(rthc_table[i].end), - __Wpedantic_format_voidptr(rthc), - (int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid); - if (rthc->mr_pid == self_pid) { - rthc->mr_pid = 0; - mdbx_trace("== cleanup %p", __Wpedantic_format_voidptr(rthc)); - } - } - } - - rthc_limit = rthc_count = 0; - if (rthc_table != rthc_table_static) - mdbx_free(rthc_table); - rthc_table = nullptr; - rthc_unlock(); - -#if defined(_WIN32) || defined(_WIN64) - DeleteCriticalSection(&lcklist_critical_section); - DeleteCriticalSection(&rthc_critical_section); -#else - /* LY: yielding a few timeslices to give a more chance - * to racing destructor(s) for completion. */ - workaround_glibc_bug21031(); -#endif - - mdbx_trace("<< pid %d\n", mdbx_getpid()); -} - -__cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin, - MDBX_reader *end) { - int rc; - if (key) { -#ifndef NDEBUG - *key = (mdbx_thread_key_t)0xBADBADBAD; -#endif /* NDEBUG */ - rc = thread_key_create(key); - if (rc != MDBX_SUCCESS) - return rc; - } - - rthc_lock(); - const mdbx_thread_key_t new_key = key ? *key : 0; - mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)new_key, - rthc_count, rthc_limit); - if (rthc_count == rthc_limit) { - rthc_entry_t *new_table = - mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table, - sizeof(rthc_entry_t) * rthc_limit * 2); - if (new_table == nullptr) { - rc = MDBX_ENOMEM; - goto bailout; - } - if (rthc_table == rthc_table_static) - memcpy(new_table, rthc_table_static, sizeof(rthc_table_static)); - rthc_table = new_table; - rthc_limit *= 2; - } - mdbx_trace("== [%i] = key %zu, %p ... %p", rthc_count, (size_t)new_key, - __Wpedantic_format_voidptr(begin), - __Wpedantic_format_voidptr(end)); - rthc_table[rthc_count].key_valid = key ? true : false; - rthc_table[rthc_count].thr_tls_key = key ? new_key : 0; - rthc_table[rthc_count].begin = begin; - rthc_table[rthc_count].end = end; - ++rthc_count; - mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)new_key, - rthc_count, rthc_limit); - rthc_unlock(); - return MDBX_SUCCESS; - -bailout: - if (key) - thread_key_delete(*key); - rthc_unlock(); - return rc; -} - -__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) { - thread_key_delete(key); - rthc_lock(); - mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)key, - rthc_count, rthc_limit); - - for (unsigned i = 0; i < rthc_count; ++i) { - if (rthc_table[i].key_valid && key == rthc_table[i].thr_tls_key) { - const uint32_t self_pid = mdbx_getpid(); - mdbx_trace("== [%i], %p ...%p, current-pid %d", i, - __Wpedantic_format_voidptr(rthc_table[i].begin), - __Wpedantic_format_voidptr(rthc_table[i].end), self_pid); - - for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end; - ++rthc) { - if (rthc->mr_pid == self_pid) { - rthc->mr_pid = 0; - mdbx_trace("== cleanup %p", __Wpedantic_format_voidptr(rthc)); - } - } - if (--rthc_count > 0) - rthc_table[i] = rthc_table[rthc_count]; - else if (rthc_table != rthc_table_static) { - mdbx_free(rthc_table); - rthc_table = rthc_table_static; - rthc_limit = RTHC_INITIAL_LIMIT; - } - break; - } - } - - mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)key, - rthc_count, rthc_limit); - rthc_unlock(); -} - -//------------------------------------------------------------------------------ - -#define RTHC_ENVLIST_END ((MDBX_env *)((size_t)50459)) -static MDBX_env *inprocess_lcklist_head = RTHC_ENVLIST_END; - -static __inline void lcklist_lock(void) { -#if defined(_WIN32) || defined(_WIN64) - EnterCriticalSection(&lcklist_critical_section); -#else - mdbx_ensure(nullptr, pthread_mutex_lock(&lcklist_mutex) == 0); -#endif -} - -static __inline void lcklist_unlock(void) { -#if defined(_WIN32) || defined(_WIN64) - LeaveCriticalSection(&lcklist_critical_section); -#else - mdbx_ensure(nullptr, pthread_mutex_unlock(&lcklist_mutex) == 0); -#endif -} - -static uint64_t rrxmrrxmsx_0(uint64_t v) { - /* Pelle Evensen's mixer, https://bit.ly/2HOfynt */ - v ^= (v << 39 | v >> 25) ^ (v << 14 | v >> 50); - v *= UINT64_C(0xA24BAED4963EE407); - v ^= (v << 40 | v >> 24) ^ (v << 15 | v >> 49); - v *= UINT64_C(0x9FB21C651E98DF25); - return v ^ v >> 28; -} - -static int uniq_peek(const mdbx_mmap_t *pending, mdbx_mmap_t *scan) { - int rc; - uint64_t bait; - if (pending->address) { - bait = pending->lck->mti_bait_uniqueness; - rc = MDBX_SUCCESS; - } else { - bait = 0 /* hush MSVC warning */; - rc = mdbx_msync(scan, 0, sizeof(MDBX_lockinfo), true); - if (rc == MDBX_SUCCESS) - rc = - mdbx_pread(pending->fd, &bait, sizeof(scan->lck->mti_bait_uniqueness), - offsetof(MDBX_lockinfo, mti_bait_uniqueness)); - } - if (likely(rc == MDBX_SUCCESS) && bait == scan->lck->mti_bait_uniqueness) - rc = MDBX_RESULT_TRUE; - - mdbx_trace("uniq-peek: %s, bait 0x%016" PRIx64 ",%s rc %d", - pending->lck ? "mem" : "file", bait, - (rc == MDBX_RESULT_TRUE) ? " found," : (rc ? " FAILED," : ""), rc); - return rc; -} - -static int uniq_poke(const mdbx_mmap_t *pending, mdbx_mmap_t *scan, - uint64_t *abra) { - if (*abra == 0) { - const size_t tid = mdbx_thread_self(); - size_t uit = 0; - memcpy(&uit, &tid, (sizeof(tid) < sizeof(uit)) ? sizeof(tid) : sizeof(uit)); - *abra = - rrxmrrxmsx_0(mdbx_osal_monotime() + UINT64_C(5873865991930747) * uit); - } - const uint64_t cadabra = - rrxmrrxmsx_0(*abra + UINT64_C(7680760450171793) * (unsigned)mdbx_getpid()) - << 24 | - *abra >> 40; - scan->lck->mti_bait_uniqueness = cadabra; - mdbx_flush_noncoherent_cpu_writeback(); - *abra = *abra * UINT64_C(6364136223846793005) + 1; - return uniq_peek(pending, scan); -} - -__cold static int uniq_check(const mdbx_mmap_t *pending, MDBX_env **found) { - *found = nullptr; - uint64_t salt = 0; - for (MDBX_env *scan = inprocess_lcklist_head; scan != RTHC_ENVLIST_END; - scan = scan->me_lcklist_next) { - int err = scan->me_lck_mmap.lck->mti_bait_uniqueness - ? uniq_peek(pending, &scan->me_lck_mmap) - : uniq_poke(pending, &scan->me_lck_mmap, &salt); - if (err == MDBX_ENODATA) { - uint64_t length; - if (likely(mdbx_filesize(pending->fd, &length) == MDBX_SUCCESS && - length == 0)) { - /* LY: skip checking since LCK-file is empty, i.e. just created. */ - mdbx_debug("uniq-probe: %s", "unique (new/empty lck)"); - return MDBX_RESULT_TRUE; - } - } - if (err == MDBX_RESULT_TRUE) - err = uniq_poke(pending, &scan->me_lck_mmap, &salt); - if (err == MDBX_RESULT_TRUE) { - (void)mdbx_msync(&scan->me_lck_mmap, 0, sizeof(MDBX_lockinfo), false); - err = uniq_poke(pending, &scan->me_lck_mmap, &salt); - } - if (err == MDBX_RESULT_TRUE) { - err = uniq_poke(pending, &scan->me_lck_mmap, &salt); - *found = scan; - mdbx_debug("uniq-probe: found %p", __Wpedantic_format_voidptr(*found)); - return MDBX_RESULT_FALSE; - } - if (unlikely(err != MDBX_SUCCESS)) { - mdbx_debug("uniq-probe: failed rc %d", err); - return err; - } - } - - mdbx_debug("uniq-probe: %s", "unique"); - return MDBX_RESULT_TRUE; -} - -static int lcklist_detach_locked(MDBX_env *env) { - MDBX_env *inprocess_neighbor = nullptr; - int rc = MDBX_SUCCESS; - if (env->me_lcklist_next != nullptr) { - mdbx_ensure(env, env->me_lcklist_next != nullptr); - mdbx_ensure(env, inprocess_lcklist_head != RTHC_ENVLIST_END); - for (MDBX_env **ptr = &inprocess_lcklist_head; *ptr != RTHC_ENVLIST_END; - ptr = &(*ptr)->me_lcklist_next) { - if (*ptr == env) { - *ptr = env->me_lcklist_next; - env->me_lcklist_next = nullptr; - break; - } - } - mdbx_ensure(env, env->me_lcklist_next == nullptr); - } - - rc = likely(mdbx_getpid() == env->me_pid) - ? uniq_check(&env->me_lck_mmap, &inprocess_neighbor) - : MDBX_PANIC; - if (!inprocess_neighbor && env->me_live_reader) - (void)mdbx_rpid_clear(env); - if (!MDBX_IS_ERROR(rc)) - rc = mdbx_lck_destroy(env, inprocess_neighbor); - return rc; -} - -/*------------------------------------------------------------------------------ - * LY: State of the art quicksort-based sorting, with internal stack and - * shell-insertion-sort for small chunks (less than half of SORT_THRESHOLD). - */ - -/* LY: Large threshold give some boost due less overhead in the inner qsort - * loops, but also a penalty in cases reverse-sorted data. - * So, 42 is magically but reasonable: - * - 0-3% faster than std::sort (from GNU C++ STL 2018) in most cases. - * - slower by a few ticks in a few cases for sequences shorter than 21. */ -#define SORT_THRESHOLD 42 - -#define SORT_SWAP(TYPE, a, b) \ - do { \ - const TYPE swap_tmp = (a); \ - (a) = (b); \ - (b) = swap_tmp; \ - } while (0) - -#define SORT_SHELLPASS(TYPE, CMP, begin, end, gap) \ - for (TYPE *i = begin + gap; i < end; ++i) { \ - for (TYPE *j = i - (gap); j >= begin && CMP(*i, *j); j -= gap) { \ - const TYPE tmp = *i; \ - do { \ - j[gap] = *j; \ - j -= gap; \ - } while (j >= begin && CMP(tmp, *j)); \ - j[gap] = tmp; \ - break; \ - } \ - } - -#define SORT_PUSH(low, high) \ - do { \ - top->lo = (low); \ - top->hi = (high); \ - ++top; \ - } while (0) - -#define SORT_POP(low, high) \ - do { \ - --top; \ - low = top->lo; \ - high = top->hi; \ - } while (0) - -#define SORT_IMPL(NAME, TYPE, CMP) \ - \ - typedef struct { \ - TYPE *lo, *hi; \ - } NAME##_stack; \ - \ - static __hot void NAME(TYPE *const begin, TYPE *const end) { \ - const ptrdiff_t length = end - begin; \ - if (length < 2) \ - return; \ - \ - if (length > SORT_THRESHOLD / 2) { \ - NAME##_stack stack[sizeof(unsigned) * CHAR_BIT], *top = stack; \ - \ - TYPE *hi = end - 1; \ - TYPE *lo = begin; \ - while (true) { \ - TYPE *mid = lo + ((hi - lo) >> 1); \ - if (CMP(*mid, *lo)) \ - SORT_SWAP(TYPE, *mid, *lo); \ - if (CMP(*hi, *mid)) { \ - SORT_SWAP(TYPE, *hi, *mid); \ - if (CMP(*mid, *lo)) \ - SORT_SWAP(TYPE, *mid, *lo); \ - } \ - \ - TYPE *right = hi - 1; \ - TYPE *left = lo + 1; \ - do { \ - while (CMP(*mid, *right)) \ - --right; \ - while (CMP(*left, *mid)) \ - ++left; \ - if (left < right) { \ - SORT_SWAP(TYPE, *left, *right); \ - if (mid == left) \ - mid = right; \ - else if (mid == right) \ - mid = left; \ - ++left; \ - --right; \ - } else if (left == right) { \ - ++left; \ - --right; \ - break; \ - } \ - } while (left <= right); \ - \ - if (lo + SORT_THRESHOLD > right) { \ - if (left + SORT_THRESHOLD > hi) { \ - if (top == stack) \ - break; \ - else \ - SORT_POP(lo, hi); \ - } else \ - lo = left; \ - } else if (left + SORT_THRESHOLD > hi) \ - hi = right; \ - else if (right - lo > hi - left) { \ - SORT_PUSH(lo, right); \ - lo = left; \ - } else { \ - SORT_PUSH(left, hi); \ - hi = right; \ - } \ - } \ - } \ - \ - SORT_SHELLPASS(TYPE, CMP, begin, end, 8); \ - SORT_SHELLPASS(TYPE, CMP, begin, end, 1); \ - for (TYPE *scan = begin + 1; scan < end; ++scan) \ - assert(CMP(scan[-1], scan[0])); \ - } - -/*------------------------------------------------------------------------------ - * LY: Binary search */ - -#define SEARCH_IMPL(NAME, TYPE_LIST, TYPE_ARG, CMP) \ - static __always_inline TYPE_LIST *NAME(TYPE_LIST *first, unsigned length, \ - const TYPE_ARG item) { \ - TYPE_LIST *const begin = first, *const end = begin + length; \ - \ - while (length > 3) { \ - const unsigned half = length >> 1; \ - TYPE_LIST *const middle = first + half; \ - if (CMP(*middle, item)) { \ - first = middle + 1; \ - length -= half + 1; \ - } else \ - length = half; \ - } \ - \ - switch (length) { \ - case 3: \ - if (!CMP(*first, item)) \ - break; \ - ++first; \ - /* fall through */ \ - __fallthrough; \ - case 2: \ - if (!CMP(*first, item)) \ - break; \ - ++first; \ - /* fall through */ \ - __fallthrough; \ - case 1: \ - if (CMP(*first, item)) \ - ++first; \ - } \ - \ - for (TYPE_LIST *scan = begin; scan < first; ++scan) \ - assert(CMP(*scan, item)); \ - for (TYPE_LIST *scan = first; scan < end; ++scan) \ - assert(!CMP(*scan, item)); \ - (void)begin, (void)end; \ - \ - return first; \ - } - -/*----------------------------------------------------------------------------*/ - -static __inline size_t pnl2bytes(const size_t size) { - assert(size > 0 && size <= MDBX_PNL_MAX * 2); - size_t bytes = roundup_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + - sizeof(pgno_t) * (size + 2), - MDBX_PNL_GRANULATE * sizeof(pgno_t)) - - MDBX_ASSUME_MALLOC_OVERHEAD; - return bytes; -} - -static __inline pgno_t bytes2pnl(const size_t bytes) { - size_t size = bytes / sizeof(pgno_t); - assert(size > 2 && size <= MDBX_PNL_MAX * 2); - return (pgno_t)size - 2; -} - -static MDBX_PNL mdbx_pnl_alloc(size_t size) { - size_t bytes = pnl2bytes(size); - MDBX_PNL pl = mdbx_malloc(bytes); - if (likely(pl)) { -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(malloc_usable_size) - bytes = malloc_usable_size(pl); -#endif /* malloc_usable_size */ - pl[0] = bytes2pnl(bytes); - assert(pl[0] >= size); - pl[1] = 0; - pl += 1; - } - return pl; -} - -static void mdbx_pnl_free(MDBX_PNL pl) { - if (likely(pl)) - mdbx_free(pl - 1); -} - -/* Shrink the PNL to the default size if it has grown larger */ -static void mdbx_pnl_shrink(MDBX_PNL *ppl) { - assert(bytes2pnl(pnl2bytes(MDBX_PNL_INITIAL)) == MDBX_PNL_INITIAL); - assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && - MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); - MDBX_PNL_SIZE(*ppl) = 0; - if (unlikely(MDBX_PNL_ALLOCLEN(*ppl) > - MDBX_PNL_INITIAL * 2 - MDBX_CACHELINE_SIZE / sizeof(pgno_t))) { - size_t bytes = pnl2bytes(MDBX_PNL_INITIAL); - MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes); - if (likely(pl)) { -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(malloc_usable_size) - bytes = malloc_usable_size(pl); -#endif /* malloc_usable_size */ - *pl = bytes2pnl(bytes); - *ppl = pl + 1; - } - } -} - -/* Grow the PNL to the size growed to at least given size */ -static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) { - const size_t allocated = MDBX_PNL_ALLOCLEN(*ppl); - assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && - MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); - if (likely(allocated >= wanna)) - return MDBX_SUCCESS; - - if (unlikely(wanna > /* paranoia */ MDBX_PNL_MAX)) - return MDBX_TXN_FULL; - - const size_t size = (wanna + wanna - allocated < MDBX_PNL_MAX) - ? wanna + wanna - allocated - : MDBX_PNL_MAX; - size_t bytes = pnl2bytes(size); - MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes); - if (likely(pl)) { -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(malloc_usable_size) - bytes = malloc_usable_size(pl); -#endif /* malloc_usable_size */ - *pl = bytes2pnl(bytes); - assert(*pl >= wanna); - *ppl = pl + 1; - return MDBX_SUCCESS; - } - return MDBX_ENOMEM; -} - -/* Make room for num additional elements in an PNL */ -static __inline int __must_check_result mdbx_pnl_need(MDBX_PNL *ppl, - size_t num) { - assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && - MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); - assert(num <= MDBX_PNL_MAX); - const size_t wanna = MDBX_PNL_SIZE(*ppl) + num; - return likely(MDBX_PNL_ALLOCLEN(*ppl) >= wanna) - ? MDBX_SUCCESS - : mdbx_pnl_reserve(ppl, wanna); -} - -static __inline void mdbx_pnl_xappend(MDBX_PNL pl, pgno_t pgno) { - assert(MDBX_PNL_SIZE(pl) < MDBX_PNL_ALLOCLEN(pl)); - if (mdbx_assert_enabled()) { - for (unsigned i = MDBX_PNL_SIZE(pl); i > 0; --i) - assert(pgno != pl[i]); - } - MDBX_PNL_SIZE(pl) += 1; - MDBX_PNL_LAST(pl) = pgno; -} - -/* Append an pgno onto an unsorted PNL */ -static __hot int __must_check_result mdbx_pnl_append(MDBX_PNL *ppl, - pgno_t pgno) { - /* Too big? */ - if (unlikely(MDBX_PNL_SIZE(*ppl) == MDBX_PNL_ALLOCLEN(*ppl))) { - int rc = mdbx_pnl_need(ppl, MDBX_PNL_GRANULATE); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - mdbx_pnl_xappend(*ppl, pgno); - return MDBX_SUCCESS; -} - -/* Append an PNL onto an unsorted PNL */ -static int __must_check_result mdbx_pnl_append_list(MDBX_PNL *ppl, - MDBX_PNL append) { - const unsigned len = MDBX_PNL_SIZE(append); - if (likely(len)) { - int rc = mdbx_pnl_need(ppl, MDBX_PNL_SIZE(append)); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - const MDBX_PNL pnl = *ppl; - unsigned w = MDBX_PNL_SIZE(pnl), r = 1; - do - pnl[++w] = append[r]; - while (++r <= len); - MDBX_PNL_SIZE(pnl) = w; - } - return MDBX_SUCCESS; -} - -/* Append an pgno range onto an unsorted PNL */ -static __hot int __must_check_result mdbx_pnl_append_range(MDBX_PNL *ppl, - pgno_t pgno, - unsigned n) { - assert(n > 0); - int rc = mdbx_pnl_need(ppl, n); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - const MDBX_PNL pnl = *ppl; -#if MDBX_PNL_ASCENDING - unsigned w = MDBX_PNL_SIZE(pnl); - do - pnl[++w] = pgno++; - while (--n); - MDBX_PNL_SIZE(pnl) = w; -#else - unsigned w = MDBX_PNL_SIZE(pnl) + n; - MDBX_PNL_SIZE(pnl) = w; - do - pnl[w--] = --n + pgno; - while (n); -#endif - - return MDBX_SUCCESS; -} - -/* Append an pgno range into the sorted PNL */ -static __hot int __must_check_result mdbx_pnl_insert_range(MDBX_PNL *ppl, - pgno_t pgno, - unsigned n) { - assert(n > 0); - int rc = mdbx_pnl_need(ppl, n); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - const MDBX_PNL pnl = *ppl; - unsigned r = MDBX_PNL_SIZE(pnl), w = r + n; - MDBX_PNL_SIZE(pnl) = w; - while (r && MDBX_PNL_DISORDERED(pnl[r], pgno)) - pnl[w--] = pnl[r--]; - - for (pgno_t fill = MDBX_PNL_ASCENDING ? pgno + n : pgno; w > r; --w) - pnl[w] = MDBX_PNL_ASCENDING ? --fill : fill++; - - return MDBX_SUCCESS; -} - -static bool __hot mdbx_pnl_check(const MDBX_PNL pl, const pgno_t limit) { - assert(limit >= MIN_PAGENO && limit <= MAX_PAGENO + 1); - if (likely(MDBX_PNL_SIZE(pl))) { - assert(MDBX_PNL_LEAST(pl) >= MIN_PAGENO); - assert(MDBX_PNL_MOST(pl) < limit); - assert(MDBX_PNL_SIZE(pl) <= MDBX_PNL_MAX); - if (unlikely(MDBX_PNL_SIZE(pl) > MDBX_PNL_MAX * 3 / 2)) - return false; - if (unlikely(MDBX_PNL_LEAST(pl) < MIN_PAGENO)) - return false; - if (unlikely(MDBX_PNL_MOST(pl) >= limit)) - return false; - for (const pgno_t *scan = &MDBX_PNL_LAST(pl); --scan > pl;) { - assert(MDBX_PNL_ORDERED(scan[0], scan[1])); - if (unlikely(!MDBX_PNL_ORDERED(scan[0], scan[1]))) - return false; - } - } - return true; -} - -static __inline bool mdbx_pnl_check4assert(const MDBX_PNL pl, - const pgno_t limit) { - if (unlikely(pl == nullptr)) - return true; - assert(MDBX_PNL_ALLOCLEN(pl) >= MDBX_PNL_SIZE(pl)); - if (unlikely(MDBX_PNL_ALLOCLEN(pl) < MDBX_PNL_SIZE(pl))) - return false; - return mdbx_pnl_check(pl, limit); -} - -/* Merge an PNL onto an PNL. The destination PNL must be big enough */ -static void __hot mdbx_pnl_xmerge(MDBX_PNL dst, const MDBX_PNL src) { - assert(mdbx_pnl_check4assert(dst, MAX_PAGENO + 1)); - assert(mdbx_pnl_check(src, MAX_PAGENO + 1)); - const size_t total = MDBX_PNL_SIZE(dst) + MDBX_PNL_SIZE(src); - assert(MDBX_PNL_ALLOCLEN(dst) >= total); - pgno_t *w = dst + total; - pgno_t *d = dst + MDBX_PNL_SIZE(dst); - const pgno_t *s = src + MDBX_PNL_SIZE(src); - dst[0] = /* detent for scan below */ (MDBX_PNL_ASCENDING ? 0 : ~(pgno_t)0); - while (s > src) { - while (MDBX_PNL_ORDERED(*s, *d)) - *w-- = *d--; - *w-- = *s--; - } - MDBX_PNL_SIZE(dst) = (pgno_t)total; - assert(mdbx_pnl_check4assert(dst, MAX_PAGENO + 1)); -} - -SORT_IMPL(pgno_sort, pgno_t, MDBX_PNL_ORDERED) -static __hot void mdbx_pnl_sort(MDBX_PNL pnl) { - pgno_sort(MDBX_PNL_BEGIN(pnl), MDBX_PNL_END(pnl)); - assert(mdbx_pnl_check(pnl, MAX_PAGENO + 1)); -} - -/* Search for an pgno in an PNL. - * Returns The index of the first item greater than or equal to pgno. */ -SEARCH_IMPL(pgno_bsearch, pgno_t, pgno_t, MDBX_PNL_ORDERED) - -static __hot unsigned mdbx_pnl_search(MDBX_PNL pnl, pgno_t id) { - assert(mdbx_pnl_check4assert(pnl, MAX_PAGENO + 1)); - pgno_t *begin = MDBX_PNL_BEGIN(pnl); - pgno_t *it = pgno_bsearch(begin, MDBX_PNL_SIZE(pnl), id); - pgno_t *end = begin + MDBX_PNL_SIZE(pnl); - assert(it >= begin && it <= end); - if (it != begin) - assert(MDBX_PNL_ORDERED(it[-1], id)); - if (it != end) - assert(!MDBX_PNL_ORDERED(it[0], id)); - return (unsigned)(it - begin + 1); -} - -static __hot unsigned mdbx_pnl_exist(MDBX_PNL pnl, pgno_t id) { - unsigned n = mdbx_pnl_search(pnl, id); - return (n <= MDBX_PNL_SIZE(pnl) && pnl[n] == id) ? n : 0; -} - -/*----------------------------------------------------------------------------*/ - -static __inline size_t txl2bytes(const size_t size) { - assert(size > 0 && size <= MDBX_TXL_MAX * 2); - size_t bytes = roundup_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + - sizeof(txnid_t) * (size + 2), - MDBX_TXL_GRANULATE * sizeof(txnid_t)) - - MDBX_ASSUME_MALLOC_OVERHEAD; - return bytes; -} - -static __inline size_t bytes2txl(const size_t bytes) { - size_t size = bytes / sizeof(txnid_t); - assert(size > 2 && size <= MDBX_TXL_MAX * 2); - return size - 2; -} - -static MDBX_TXL mdbx_txl_alloc(void) { - size_t bytes = txl2bytes(MDBX_TXL_INITIAL); - MDBX_TXL tl = mdbx_malloc(bytes); - if (likely(tl)) { -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(malloc_usable_size) - bytes = malloc_usable_size(tl); -#endif /* malloc_usable_size */ - tl[0] = bytes2txl(bytes); - assert(tl[0] >= MDBX_TXL_INITIAL); - tl[1] = 0; - tl += 1; - } - return tl; -} - -static void mdbx_txl_free(MDBX_TXL tl) { - if (likely(tl)) - mdbx_free(tl - 1); -} - -static int mdbx_txl_reserve(MDBX_TXL *ptl, const size_t wanna) { - const size_t allocated = (size_t)MDBX_PNL_ALLOCLEN(*ptl); - assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX && - MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl)); - if (likely(allocated >= wanna)) - return MDBX_SUCCESS; - - if (unlikely(wanna > /* paranoia */ MDBX_TXL_MAX)) - return MDBX_TXN_FULL; - - const size_t size = (wanna + wanna - allocated < MDBX_TXL_MAX) - ? wanna + wanna - allocated - : MDBX_TXL_MAX; - size_t bytes = txl2bytes(size); - MDBX_TXL tl = mdbx_realloc(*ptl - 1, bytes); - if (likely(tl)) { -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(malloc_usable_size) - bytes = malloc_usable_size(tl); -#endif /* malloc_usable_size */ - *tl = bytes2txl(bytes); - assert(*tl >= wanna); - *ptl = tl + 1; - return MDBX_SUCCESS; - } - return MDBX_ENOMEM; -} - -static __inline int __must_check_result mdbx_txl_need(MDBX_TXL *ptl, - size_t num) { - assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX && - MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl)); - assert(num <= MDBX_PNL_MAX); - const size_t wanna = (size_t)MDBX_PNL_SIZE(*ptl) + num; - return likely(MDBX_PNL_ALLOCLEN(*ptl) >= wanna) - ? MDBX_SUCCESS - : mdbx_txl_reserve(ptl, wanna); -} - -static __inline void mdbx_txl_xappend(MDBX_TXL tl, txnid_t id) { - assert(MDBX_PNL_SIZE(tl) < MDBX_PNL_ALLOCLEN(tl)); - MDBX_PNL_SIZE(tl) += 1; - MDBX_PNL_LAST(tl) = id; -} - -#define TXNID_SORT_CMP(first, last) ((first) > (last)) -SORT_IMPL(txnid_sort, txnid_t, TXNID_SORT_CMP) -static void mdbx_txl_sort(MDBX_TXL tl) { - txnid_sort(MDBX_PNL_BEGIN(tl), MDBX_PNL_END(tl)); -} - -static int __must_check_result mdbx_txl_append(MDBX_TXL *ptl, txnid_t id) { - if (unlikely(MDBX_PNL_SIZE(*ptl) == MDBX_PNL_ALLOCLEN(*ptl))) { - int rc = mdbx_txl_need(ptl, MDBX_TXL_GRANULATE); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - mdbx_txl_xappend(*ptl, id); - return MDBX_SUCCESS; -} - -/*----------------------------------------------------------------------------*/ - -#define DP_SORT_CMP(first, last) ((first).pgno < (last).pgno) -SORT_IMPL(dp_sort, MDBX_DP, DP_SORT_CMP) -static __inline MDBX_DPL mdbx_dpl_sort(MDBX_DPL dl) { - assert(dl->length <= MDBX_DPL_TXNFULL); - assert(dl->sorted <= dl->length); - if (dl->sorted != dl->length) { - dl->sorted = dl->length; - dp_sort(dl + 1, dl + dl->length + 1); - } - return dl; -} - -/* Returns the index of the first dirty-page whose pgno - * member is greater than or equal to id. */ -#define DP_SEARCH_CMP(dp, id) ((dp).pgno < (id)) -SEARCH_IMPL(dp_bsearch, MDBX_DP, pgno_t, DP_SEARCH_CMP) - -static unsigned __hot mdbx_dpl_search(MDBX_DPL dl, pgno_t pgno) { - if (dl->sorted < dl->length) { - /* unsorted tail case */ -#if MDBX_DEBUG - for (const MDBX_DP *ptr = dl + dl->sorted; --ptr > dl;) { - assert(ptr[0].pgno < ptr[1].pgno); - assert(ptr[0].pgno >= NUM_METAS); - } -#endif - - /* try linear search until the threshold */ - if (dl->length - dl->sorted < SORT_THRESHOLD / 2) { - unsigned i = dl->length; - while (i - dl->sorted > 7) { - if (dl[i].pgno == pgno) - return i; - if (dl[i - 1].pgno == pgno) - return i - 1; - if (dl[i - 2].pgno == pgno) - return i - 2; - if (dl[i - 3].pgno == pgno) - return i - 3; - if (dl[i - 4].pgno == pgno) - return i - 4; - if (dl[i - 5].pgno == pgno) - return i - 5; - if (dl[i - 6].pgno == pgno) - return i - 6; - if (dl[i - 7].pgno == pgno) - return i - 7; - i -= 8; - } - while (i > dl->sorted) { - if (dl[i].pgno == pgno) - return i; - --i; - } - - MDBX_DPL it = dp_bsearch(dl + 1, i, pgno); - return (unsigned)(it - dl); - } - - /* sort a whole */ - dl->sorted = dl->length; - dp_sort(dl + 1, dl + dl->length + 1); - } - -#if MDBX_DEBUG - for (const MDBX_DP *ptr = dl + dl->length; --ptr > dl;) { - assert(ptr[0].pgno < ptr[1].pgno); - assert(ptr[0].pgno >= NUM_METAS); - } -#endif - - MDBX_DPL it = dp_bsearch(dl + 1, dl->length, pgno); - return (unsigned)(it - dl); -} - -static __inline MDBX_page *mdbx_dpl_find(MDBX_DPL dl, pgno_t pgno) { - const unsigned i = mdbx_dpl_search(dl, pgno); - assert((int)i > 0); - return (i <= dl->length && dl[i].pgno == pgno) ? dl[i].ptr : nullptr; -} - -static __hot MDBX_page *mdbx_dpl_remove(MDBX_DPL dl, pgno_t prno) { - unsigned i = mdbx_dpl_search(dl, prno); - assert((int)i > 0); - MDBX_page *mp = nullptr; - if (i <= dl->length && dl[i].pgno == prno) { - dl->sorted -= dl->sorted >= i; - mp = dl[i].ptr; - while (i < dl->length) { - dl[i] = dl[i + 1]; - ++i; - } - dl->length -= 1; - } - return mp; -} - -static __inline int __must_check_result mdbx_dpl_append(MDBX_DPL dl, - pgno_t pgno, - MDBX_page *page) { - assert(dl->length <= MDBX_DPL_TXNFULL); -#if MDBX_DEBUG - for (unsigned i = dl->length; i > 0; --i) { - assert(dl[i].pgno != pgno); - if (unlikely(dl[i].pgno == pgno)) - return MDBX_PROBLEM; - } -#endif - - if (unlikely(dl->length == MDBX_DPL_TXNFULL)) - return MDBX_TXN_FULL; - - /* append page */ - const unsigned n = dl->length + 1; - if (n == 1 || (dl->sorted >= dl->length && dl[n - 1].pgno < pgno)) - dl->sorted = n; - dl->length = n; - dl[n].pgno = pgno; - dl[n].ptr = page; - return MDBX_SUCCESS; -} - -static __inline void mdbx_dpl_clear(MDBX_DPL dl) { - dl->sorted = dl->length = 0; -} - -/*----------------------------------------------------------------------------*/ - -#ifndef MDBX_ALLOY -uint8_t mdbx_runtime_flags = MDBX_RUNTIME_FLAGS_INIT; -uint8_t mdbx_loglevel = MDBX_DEBUG; -MDBX_debug_func *mdbx_debug_logger; -#endif /* MDBX_ALLOY */ - -static bool mdbx_refund(MDBX_txn *txn); -static __must_check_result int mdbx_page_retire(MDBX_cursor *mc, MDBX_page *mp); -static __must_check_result int mdbx_page_loose(MDBX_txn *txn, MDBX_page *mp); -static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, - int flags); -static int mdbx_page_new(MDBX_cursor *mc, uint32_t flags, unsigned num, - MDBX_page **mp); -static int mdbx_page_touch(MDBX_cursor *mc); -static int mdbx_cursor_touch(MDBX_cursor *mc); - -#define MDBX_END_NAMES \ - { \ - "committed", "empty-commit", "abort", "reset", "reset-tmp", "fail-begin", \ - "fail-beginchild" \ - } -enum { - /* mdbx_txn_end operation number, for logging */ - MDBX_END_COMMITTED, - MDBX_END_EMPTY_COMMIT, - MDBX_END_ABORT, - MDBX_END_RESET, - MDBX_END_RESET_TMP, - MDBX_END_FAIL_BEGIN, - MDBX_END_FAIL_BEGINCHILD -}; -#define MDBX_END_OPMASK 0x0F /* mask for mdbx_txn_end() operation number */ -#define MDBX_END_UPDATE 0x10 /* update env state (DBIs) */ -#define MDBX_END_FREE 0x20 /* free txn unless it is MDBX_env.me_txn0 */ -#define MDBX_END_EOTDONE 0x40 /* txn's cursors already closed */ -#define MDBX_END_SLOT 0x80 /* release any reader slot if MDBX_NOTLS */ -static int mdbx_txn_end(MDBX_txn *txn, unsigned mode); - -static int __must_check_result mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, - MDBX_page **mp, int *lvl); -static int __must_check_result mdbx_page_search_root(MDBX_cursor *mc, - MDBX_val *key, int modify); - -#define MDBX_PS_MODIFY 1 -#define MDBX_PS_ROOTONLY 2 -#define MDBX_PS_FIRST 4 -#define MDBX_PS_LAST 8 -static int __must_check_result mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, - int flags); -static int __must_check_result mdbx_page_merge(MDBX_cursor *csrc, - MDBX_cursor *cdst); -static int __must_check_result mdbx_page_flush(MDBX_txn *txn, - const unsigned keep); - -#define MDBX_SPLIT_REPLACE MDBX_APPENDDUP /* newkey is not new */ -static int __must_check_result mdbx_page_split(MDBX_cursor *mc, - const MDBX_val *newkey, - MDBX_val *newdata, - pgno_t newpgno, unsigned nflags); - -static int __must_check_result mdbx_read_header(MDBX_env *env, MDBX_meta *meta, - uint64_t *filesize); -static int __must_check_result mdbx_sync_locked(MDBX_env *env, unsigned flags, - MDBX_meta *const pending); -static int mdbx_env_close0(MDBX_env *env); - -static MDBX_node *mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, int *exactp); - -static int __must_check_result mdbx_node_add_branch(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key, - pgno_t pgno); -static int __must_check_result mdbx_node_add_leaf(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key, - MDBX_val *data, - unsigned flags); -static int __must_check_result mdbx_node_add_leaf2(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key); - -static void mdbx_node_del(MDBX_cursor *mc, size_t ksize); -static void mdbx_node_shrink(MDBX_page *mp, unsigned indx); -static int __must_check_result mdbx_node_move(MDBX_cursor *csrc, - MDBX_cursor *cdst, int fromleft); -static int __must_check_result mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf, - MDBX_val *data); -static int __must_check_result mdbx_rebalance(MDBX_cursor *mc); -static int __must_check_result mdbx_update_key(MDBX_cursor *mc, - const MDBX_val *key); - -static void mdbx_cursor_pop(MDBX_cursor *mc); -static int __must_check_result mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp); - -static int __must_check_result mdbx_audit_ex(MDBX_txn *txn, - unsigned retired_stored, - bool dont_filter_gc); -static __maybe_unused __inline int __must_check_result -mdbx_audit(MDBX_txn *txn) { - return mdbx_audit_ex(txn, 0, (txn->mt_flags & MDBX_RDONLY) != 0); -} - -static int __must_check_result mdbx_page_check(MDBX_env *env, - const MDBX_page *const mp, - bool maybe_unfinished); -static int __must_check_result mdbx_cursor_check(MDBX_cursor *mc, bool pending); -static int __must_check_result mdbx_cursor_del0(MDBX_cursor *mc); -static int __must_check_result mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, - MDBX_val *key, MDBX_val *data, - unsigned flags); -static int __must_check_result mdbx_cursor_sibling(MDBX_cursor *mc, - int move_right); -static int __must_check_result mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data, - MDBX_cursor_op op); -static int __must_check_result mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data, - MDBX_cursor_op op); -static int __must_check_result mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data, - MDBX_cursor_op op, int *exactp); -static int __must_check_result mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data); -static int __must_check_result mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, - MDBX_val *data); - -static int __must_check_result mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, - MDBX_dbi dbi); -static int __must_check_result mdbx_xcursor_init0(MDBX_cursor *mc); -static int __must_check_result mdbx_xcursor_init1(MDBX_cursor *mc, - MDBX_node *node); -static int __must_check_result mdbx_xcursor_init2(MDBX_cursor *mc, - MDBX_xcursor *src_mx, - int force); -static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst); - -static int __must_check_result mdbx_drop0(MDBX_cursor *mc, int subs); -static int __must_check_result mdbx_fetch_sdb(MDBX_txn *txn, MDBX_dbi dbi); - -static MDBX_cmp_func mdbx_cmp_memn, mdbx_cmp_memnr, mdbx_cmp_int_align4, - mdbx_cmp_int_align2, mdbx_cmp_int_unaligned; - -static const char *__mdbx_strerr(int errnum) { - /* Table of descriptions for MDBX errors */ - static const char *const tbl[] = { - "MDBX_KEYEXIST: Key/data pair already exists", - "MDBX_NOTFOUND: No matching key/data pair found", - "MDBX_PAGE_NOTFOUND: Requested page not found", - "MDBX_CORRUPTED: Database is corrupted", - "MDBX_PANIC: Environment had fatal error", - "MDBX_VERSION_MISMATCH: DB version mismatch libmdbx", - "MDBX_INVALID: File is not an MDBX file", - "MDBX_MAP_FULL: Environment mapsize limit reached", - "MDBX_DBS_FULL: Too may DBI (maxdbs reached)", - "MDBX_READERS_FULL: Too many readers (maxreaders reached)", - NULL /* MDBX_TLS_FULL (-30789): unused in MDBX */, - "MDBX_TXN_FULL: Transaction has too many dirty pages, " - "i.e transaction too big", - "MDBX_CURSOR_FULL: Internal error - cursor stack limit reached", - "MDBX_PAGE_FULL: Internal error - page has no more space", - "MDBX_MAP_RESIZED: Database contents grew beyond environment mapsize", - "MDBX_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed", - "MDBX_BAD_RSLOT: Invalid reuse of reader locktable slot", - "MDBX_BAD_TXN: Transaction must abort, has a child, or is invalid", - "MDBX_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong " - "DUPFIXED size", - "MDBX_BAD_DBI: The specified DBI handle was closed/changed unexpectedly", - "MDBX_PROBLEM: Unexpected problem - txn should abort", - "MDBX_BUSY: Another write transaction is running or " - "environment is already used while opening with MDBX_EXCLUSIVE flag", - }; - - if (errnum >= MDBX_KEYEXIST && errnum <= MDBX_LAST_ERRCODE) { - int i = errnum - MDBX_KEYEXIST; - return tbl[i]; - } - - switch (errnum) { - case MDBX_SUCCESS: - return "MDBX_SUCCESS: Successful"; - case MDBX_EMULTIVAL: - return "MDBX_EMULTIVAL: Unable to update multi-value for the given key"; - case MDBX_EBADSIGN: - return "MDBX_EBADSIGN: Wrong signature of a runtime object(s)"; - case MDBX_WANNA_RECOVERY: - return "MDBX_WANNA_RECOVERY: Database should be recovered, but this could " - "NOT be done in a read-only mode"; - case MDBX_EKEYMISMATCH: - return "MDBX_EKEYMISMATCH: The given key value is mismatched to the " - "current cursor position"; - case MDBX_TOO_LARGE: - return "MDBX_TOO_LARGE: Database is too large for current system, " - "e.g. could NOT be mapped into RAM"; - case MDBX_THREAD_MISMATCH: - return "MDBX_THREAD_MISMATCH: A thread has attempted to use a not " - "owned object, e.g. a transaction that started by another thread"; - default: - return NULL; - } -} - -const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) { - const char *msg = __mdbx_strerr(errnum); - if (!msg && buflen > 0 && buflen < INT_MAX) { -#if defined(_WIN32) || defined(_WIN64) - const DWORD size = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen, - NULL); - return size ? buf : NULL; -#elif defined(_GNU_SOURCE) && defined(__GLIBC__) - /* GNU-specific */ - if (errnum > 0) - msg = strerror_r(errnum, buf, buflen); -#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) - /* XSI-compliant */ - if (errnum > 0 && strerror_r(errnum, buf, buflen) == 0) - msg = buf; -#else - if (errnum > 0) { - msg = strerror(errnum); - if (msg) { - strncpy(buf, msg, buflen); - msg = buf; - } - } -#endif - if (!msg) { - (void)snprintf(buf, buflen, "error %d", errnum); - msg = buf; - } - buf[buflen - 1] = '\0'; - } - return msg; -} - -const char *__cold mdbx_strerror(int errnum) { -#if defined(_WIN32) || defined(_WIN64) - static char buf[1024]; - return mdbx_strerror_r(errnum, buf, sizeof(buf)); -#else - const char *msg = __mdbx_strerr(errnum); - if (!msg) { - if (errnum > 0) - msg = strerror(errnum); - if (!msg) { - static char buf[32]; - (void)snprintf(buf, sizeof(buf) - 1, "error %d", errnum); - msg = buf; - } - } - return msg; -#endif -} - -#if defined(_WIN32) || defined(_WIN64) /* Bit of madness for Windows */ -const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, size_t buflen) { - const char *msg = __mdbx_strerr(errnum); - if (!msg && buflen > 0 && buflen < INT_MAX) { - const DWORD size = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen, - NULL); - if (size && CharToOemBuffA(buf, buf, size)) - msg = buf; - } - return msg; -} - -const char *mdbx_strerror_ANSI2OEM(int errnum) { - static char buf[1024]; - return mdbx_strerror_r_ANSI2OEM(errnum, buf, sizeof(buf)); -} -#endif /* Bit of madness for Windows */ - -static txnid_t mdbx_oomkick(MDBX_env *env, const txnid_t laggard); - -void __cold mdbx_debug_log(int level, const char *function, int line, - const char *fmt, ...) { - va_list args; - - va_start(args, fmt); - if (mdbx_debug_logger) - mdbx_debug_logger(level, function, line, fmt, args); - else { -#if defined(_WIN32) || defined(_WIN64) - if (IsDebuggerPresent()) { - int prefix_len = 0; - char *prefix = nullptr; - if (function && line > 0) - prefix_len = mdbx_asprintf(&prefix, "%s:%d ", function, line); - else if (function) - prefix_len = mdbx_asprintf(&prefix, "%s: ", function); - else if (line > 0) - prefix_len = mdbx_asprintf(&prefix, "%d: ", line); - if (prefix_len > 0 && prefix) { - OutputDebugStringA(prefix); - mdbx_free(prefix); - } - char *msg = nullptr; - int msg_len = mdbx_vasprintf(&msg, fmt, args); - if (msg_len > 0 && msg) { - OutputDebugStringA(msg); - mdbx_free(msg); - } - } -#else - if (function && line > 0) - fprintf(stderr, "%s:%d ", function, line); - else if (function) - fprintf(stderr, "%s: ", function); - else if (line > 0) - fprintf(stderr, "%d: ", line); - vfprintf(stderr, fmt, args); - fflush(stderr); -#endif - } - va_end(args); -} - -/* Dump a key in ascii or hexadecimal. */ -const char *mdbx_dump_val(const MDBX_val *key, char *const buf, - const size_t bufsize) { - if (!key) - return ""; - if (!buf || bufsize < 4) - return nullptr; - if (!key->iov_len) - return ""; - - const uint8_t *const data = key->iov_base; - bool is_ascii = true; - unsigned i; - for (i = 0; is_ascii && i < key->iov_len; i++) - if (data[i] < ' ' || data[i] > 127) - is_ascii = false; - - if (is_ascii) { - int len = - snprintf(buf, bufsize, "%.*s", - (key->iov_len > INT_MAX) ? INT_MAX : (int)key->iov_len, data); - assert(len > 0 && (unsigned)len < bufsize); - (void)len; - } else { - char *const detent = buf + bufsize - 2; - char *ptr = buf; - *ptr++ = '<'; - for (i = 0; i < key->iov_len; i++) { - const ptrdiff_t left = detent - ptr; - assert(left > 0); - int len = snprintf(ptr, left, "%02x", data[i]); - if (len < 0 || len >= left) - break; - ptr += len; - } - if (ptr < detent) { - ptr[0] = '>'; - ptr[1] = '\0'; - } - } - return buf; -} - -/*------------------------------------------------------------------------------ - LY: debug stuff */ - -static const char *mdbx_leafnode_type(MDBX_node *n) { - static const char *const tp[2][2] = {{"", ": DB"}, - {": sub-page", ": sub-DB"}}; - return F_ISSET(node_flags(n), F_BIGDATA) - ? ": overflow page" - : tp[F_ISSET(node_flags(n), F_DUPDATA)] - [F_ISSET(node_flags(n), F_SUBDATA)]; -} - -/* Display all the keys in the page. */ -static __maybe_unused void mdbx_page_list(MDBX_page *mp) { - pgno_t pgno = mp->mp_pgno; - const char *type, *state = IS_DIRTY(mp) ? ", dirty" : ""; - MDBX_node *node; - unsigned i, nkeys, nsize, total = 0; - MDBX_val key; - DKBUF; - - switch (mp->mp_flags & - (P_BRANCH | P_LEAF | P_LEAF2 | P_META | P_OVERFLOW | P_SUBP)) { - case P_BRANCH: - type = "Branch page"; - break; - case P_LEAF: - type = "Leaf page"; - break; - case P_LEAF | P_SUBP: - type = "Leaf sub-page"; - break; - case P_LEAF | P_LEAF2: - type = "Leaf2 page"; - break; - case P_LEAF | P_LEAF2 | P_SUBP: - type = "Leaf2 sub-page"; - break; - case P_OVERFLOW: - mdbx_verbose("Overflow page %" PRIaPGNO " pages %u%s\n", pgno, mp->mp_pages, - state); - return; - case P_META: - mdbx_verbose("Meta-page %" PRIaPGNO " txnid %" PRIu64 "\n", pgno, - page_meta(mp)->mm_txnid_a.inconsistent); - return; - default: - mdbx_verbose("Bad page %" PRIaPGNO " flags 0x%X\n", pgno, mp->mp_flags); - return; - } - - nkeys = page_numkeys(mp); - mdbx_verbose("%s %" PRIaPGNO " numkeys %u%s\n", type, pgno, nkeys, state); - - for (i = 0; i < nkeys; i++) { - if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */ - key.iov_len = nsize = mp->mp_leaf2_ksize; - key.iov_base = page_leaf2key(mp, i, nsize); - total += nsize; - mdbx_verbose("key %u: nsize %u, %s\n", i, nsize, DKEY(&key)); - continue; - } - node = page_node(mp, i); - key.iov_len = node_ks(node); - key.iov_base = node->mn_data; - nsize = (unsigned)(NODESIZE + key.iov_len); - if (IS_BRANCH(mp)) { - mdbx_verbose("key %u: page %" PRIaPGNO ", %s\n", i, node_pgno(node), - DKEY(&key)); - total += nsize; - } else { - if (F_ISSET(node_flags(node), F_BIGDATA)) - nsize += sizeof(pgno_t); - else - nsize += (unsigned)node_ds(node); - total += nsize; - nsize += sizeof(indx_t); - mdbx_verbose("key %u: nsize %u, %s%s\n", i, nsize, DKEY(&key), - mdbx_leafnode_type(node)); - } - total = EVEN(total); - } - mdbx_verbose("Total: header %u + contents %u + unused %u\n", - IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower, total, - page_room(mp)); -} - -/*----------------------------------------------------------------------------*/ - -/* Check if there is an inited xcursor, so XCURSOR_REFRESH() is proper */ -#define XCURSOR_INITED(mc) \ - ((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) - -/* Update sub-page pointer, if any, in mc->mc_xcursor. - * Needed when the node which contains the sub-page may have moved. - * Called with mp = mc->mc_pg[mc->mc_top], ki = mc->mc_ki[mc->mc_top]. */ -#define XCURSOR_REFRESH(mc, mp, ki) \ - do { \ - MDBX_page *xr_pg = (mp); \ - MDBX_node *xr_node = page_node(xr_pg, ki); \ - if ((node_flags(xr_node) & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) \ - (mc)->mc_xcursor->mx_cursor.mc_pg[0] = node_data(xr_node); \ - } while (0) - -/* Perform act while tracking temporary cursor mn */ -#define WITH_CURSOR_TRACKING(mn, act) \ - do { \ - mdbx_cassert(&(mn), \ - mn.mc_txn->mt_cursors != NULL /* must be not rdonly txt */); \ - MDBX_cursor mc_dummy, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ - MDBX_cursor *tracked = &(mn); \ - if ((mn).mc_flags & C_SUB) { \ - mc_dummy.mc_flags = C_INITIALIZED; \ - mc_dummy.mc_xcursor = (MDBX_xcursor *)&(mn); \ - tracked = &mc_dummy; \ - } \ - tracked->mc_next = *tp; \ - *tp = tracked; \ - { act; } \ - *tp = tracked->mc_next; \ - } while (0) - -int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, - const MDBX_val *b) { - mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); - return txn->mt_dbxs[dbi].md_cmp(a, b); -} - -int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, - const MDBX_val *b) { - mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); - return txn->mt_dbxs[dbi].md_dcmp(a, b); -} - -/* Allocate memory for a page. - * Re-use old malloc'd pages first for singletons, otherwise just malloc. - * Set MDBX_TXN_ERROR on failure. */ -static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) { - MDBX_env *env = txn->mt_env; - MDBX_page *np = env->me_dpages; - size_t size = env->me_psize; - if (likely(num == 1 && np)) { - ASAN_UNPOISON_MEMORY_REGION(np, size); - VALGRIND_MEMPOOL_ALLOC(env, np, size); - VALGRIND_MAKE_MEM_DEFINED(&np->mp_next, sizeof(np->mp_next)); - env->me_dpages = np->mp_next; - } else { - size = pgno2bytes(env, num); - np = mdbx_malloc(size); - if (unlikely(!np)) { - txn->mt_flags |= MDBX_TXN_ERROR; - return np; - } - VALGRIND_MEMPOOL_ALLOC(env, np, size); - } - - if ((env->me_flags & MDBX_NOMEMINIT) == 0) { - /* For a single page alloc, we init everything after the page header. - * For multi-page, we init the final page; if the caller needed that - * many pages they will be filling in at least up to the last page. */ - size_t skip = PAGEHDRSZ; - if (num > 1) - skip += pgno2bytes(env, num - 1); - memset((char *)np + skip, 0, size - skip); - } -#if MDBX_DEBUG - np->mp_pgno = 0; -#endif - VALGRIND_MAKE_MEM_UNDEFINED(np, size); - np->mp_flags = 0; - np->mp_pages = num; - return np; -} - -/* Free a dirty page */ -static void mdbx_dpage_free(MDBX_env *env, MDBX_page *dp, unsigned pages) { -#if MDBX_DEBUG - dp->mp_pgno = MAX_PAGENO + 1; -#endif - if (pages == 1) { - dp->mp_next = env->me_dpages; - VALGRIND_MEMPOOL_FREE(env, dp); - env->me_dpages = dp; - } else { - /* large pages just get freed directly */ - VALGRIND_MEMPOOL_FREE(env, dp); - mdbx_free(dp); - } -} - -/* Return all dirty pages to dpage list */ -static void mdbx_dlist_free(MDBX_txn *txn) { - MDBX_env *env = txn->mt_env; - const MDBX_DPL dl = txn->tw.dirtylist; - const size_t n = dl->length; - - for (size_t i = 1; i <= n; i++) { - MDBX_page *dp = dl[i].ptr; - mdbx_dpage_free(env, dp, IS_OVERFLOW(dp) ? dp->mp_pages : 1); - } - - mdbx_dpl_clear(dl); -} - -static __inline MDBX_db *mdbx_outer_db(MDBX_cursor *mc) { - mdbx_cassert(mc, (mc->mc_flags & C_SUB) != 0); - MDBX_xcursor *mx = container_of(mc->mc_db, MDBX_xcursor, mx_db); - MDBX_cursor_couple *couple = container_of(mx, MDBX_cursor_couple, inner); - mdbx_cassert(mc, mc->mc_db == &couple->outer.mc_xcursor->mx_db); - mdbx_cassert(mc, mc->mc_dbx == &couple->outer.mc_xcursor->mx_dbx); - return couple->outer.mc_db; -} - -static __cold __maybe_unused bool mdbx_dirtylist_check(MDBX_txn *txn) { - unsigned loose = 0; - for (unsigned i = txn->tw.dirtylist->length; i > 0; --i) { - const MDBX_page *const dp = txn->tw.dirtylist[i].ptr; - if (!dp) - continue; - mdbx_tassert(txn, dp->mp_pgno == txn->tw.dirtylist[i].pgno); - if (unlikely(dp->mp_pgno != txn->tw.dirtylist[i].pgno)) - return false; - - mdbx_tassert(txn, dp->mp_flags & P_DIRTY); - if (unlikely((dp->mp_flags & P_DIRTY) == 0)) - return false; - if (dp->mp_flags & P_LOOSE) { - mdbx_tassert(txn, dp->mp_flags == (P_LOOSE | P_DIRTY)); - if (unlikely(dp->mp_flags != (P_LOOSE | P_DIRTY))) - return false; - loose += 1; - } - - const unsigned num = IS_OVERFLOW(dp) ? dp->mp_pages : 1; - mdbx_tassert(txn, txn->mt_next_pgno >= dp->mp_pgno + num); - if (unlikely(txn->mt_next_pgno < dp->mp_pgno + num)) - return false; - - if (i < txn->tw.dirtylist->sorted) { - mdbx_tassert(txn, txn->tw.dirtylist[i + 1].pgno >= dp->mp_pgno + num); - if (unlikely(txn->tw.dirtylist[i + 1].pgno < dp->mp_pgno + num)) - return false; - } - - const unsigned rpa = mdbx_pnl_search(txn->tw.reclaimed_pglist, dp->mp_pgno); - mdbx_tassert(txn, rpa > MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) || - txn->tw.reclaimed_pglist[rpa] != dp->mp_pgno); - if (rpa <= MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) && - unlikely(txn->tw.reclaimed_pglist[rpa] == dp->mp_pgno)) - return false; - if (num > 1) { - const unsigned rpb = - mdbx_pnl_search(txn->tw.reclaimed_pglist, dp->mp_pgno + num - 1); - mdbx_tassert(txn, rpa == rpb); - if (unlikely(rpa != rpb)) - return false; - } - } - - mdbx_tassert(txn, loose == txn->tw.loose_count); - if (unlikely(loose != txn->tw.loose_count)) - return false; - - if (txn->tw.dirtylist->length - txn->tw.dirtylist->sorted < - SORT_THRESHOLD / 2) { - for (unsigned i = 1; i <= MDBX_PNL_SIZE(txn->tw.retired_pages); ++i) { - const MDBX_page *const dp = - mdbx_dpl_find(txn->tw.dirtylist, txn->tw.retired_pages[i]); - mdbx_tassert(txn, !dp); - if (unlikely(dp)) - return false; - } - } - - return true; -} - -static void mdbx_refund_reclaimed(MDBX_txn *txn) { - /* Scanning in descend order */ - pgno_t next_pgno = txn->mt_next_pgno; - const MDBX_PNL pnl = txn->tw.reclaimed_pglist; - mdbx_tassert(txn, MDBX_PNL_SIZE(pnl) && MDBX_PNL_MOST(pnl) == next_pgno - 1); -#if MDBX_PNL_ASCENDING - unsigned i = MDBX_PNL_SIZE(pnl); - mdbx_tassert(txn, pnl[i] == next_pgno - 1); - while (--next_pgno, --i > 0 && pnl[i] == next_pgno - 1) - ; - MDBX_PNL_SIZE(pnl) = i; -#else - unsigned i = 1; - mdbx_tassert(txn, pnl[i] == next_pgno - 1); - unsigned len = MDBX_PNL_SIZE(pnl); - while (--next_pgno, ++i <= len && pnl[i] == next_pgno - 1) - ; - MDBX_PNL_SIZE(pnl) = len -= i - 1; - for (unsigned move = 0; move < len; ++move) - pnl[1 + move] = pnl[i + move]; -#endif - mdbx_verbose("refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO, - txn->mt_next_pgno - next_pgno, txn->mt_next_pgno, next_pgno); - txn->mt_next_pgno = next_pgno; - mdbx_tassert( - txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, txn->mt_next_pgno)); -} - -static void mdbx_refund_loose(MDBX_txn *txn) { - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - mdbx_tassert(txn, txn->tw.loose_pages != nullptr); - mdbx_tassert(txn, txn->tw.loose_count > 0); - - const MDBX_DPL dl = txn->tw.dirtylist; - mdbx_tassert(txn, dl->length >= txn->tw.loose_count); - mdbx_tassert(txn, txn->tw.spill_pages == nullptr || - dl->length >= MDBX_PNL_SIZE(txn->tw.spill_pages)); - - pgno_t onstack[MDBX_CACHELINE_SIZE * 8 / sizeof(pgno_t)]; - MDBX_PNL suitable = onstack; - - if (dl->length - dl->sorted > txn->tw.loose_count) { - /* Dirty list is useless since unsorted. */ - if (bytes2pnl(sizeof(onstack)) < txn->tw.loose_count) { - suitable = mdbx_pnl_alloc(txn->tw.loose_count); - if (unlikely(!suitable)) - return /* this is not a reason for transaction fail */; - } - - /* Collect loose-pages which may be refunded. */ - mdbx_tassert(txn, txn->mt_next_pgno >= MIN_PAGENO + txn->tw.loose_count); - pgno_t most = MIN_PAGENO; - unsigned w = 0; - for (const MDBX_page *dp = txn->tw.loose_pages; dp; dp = dp->mp_next) { - mdbx_tassert(txn, dp->mp_flags == (P_LOOSE | P_DIRTY)); - mdbx_tassert(txn, txn->mt_next_pgno > dp->mp_pgno); - if (likely(txn->mt_next_pgno - txn->tw.loose_count <= dp->mp_pgno)) { - mdbx_tassert(txn, - w < ((suitable == onstack) ? bytes2pnl(sizeof(onstack)) - : MDBX_PNL_ALLOCLEN(suitable))); - suitable[++w] = dp->mp_pgno; - most = (dp->mp_pgno > most) ? dp->mp_pgno : most; - } - } - - if (most + 1 == txn->mt_next_pgno) { - /* Sort suitable list and refund pages at the tail. */ - MDBX_PNL_SIZE(suitable) = w; - mdbx_pnl_sort(suitable); - - /* Scanning in descend order */ - const int step = MDBX_PNL_ASCENDING ? -1 : 1; - const int begin = MDBX_PNL_ASCENDING ? MDBX_PNL_SIZE(suitable) : 1; - const int end = MDBX_PNL_ASCENDING ? 0 : MDBX_PNL_SIZE(suitable) + 1; - mdbx_tassert(txn, suitable[begin] >= suitable[end - step]); - mdbx_tassert(txn, most == suitable[begin]); - - for (int i = begin + step; i != end; i += step) { - if (suitable[i] != most - 1) - break; - most -= 1; - } - const unsigned refunded = txn->mt_next_pgno - most; - mdbx_verbose("refund-sorted %u pages %" PRIaPGNO " -> %" PRIaPGNO, - refunded, most, txn->mt_next_pgno); - txn->tw.loose_count -= refunded; - txn->tw.dirtyroom += refunded; - txn->mt_next_pgno = most; - - /* Filter-out dirty list */ - unsigned r = 0; - w = 0; - if (dl->sorted) { - do { - if (dl[++r].pgno < most) { - if (++w != r) - dl[w] = dl[r]; - } - } while (r < dl->sorted); - dl->sorted = w; - } - while (r < dl->length) { - if (dl[++r].pgno < most) { - if (++w != r) - dl[w] = dl[r]; - } - } - dl->length = w; - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - goto unlink_loose; - } - } else { - /* Dirtylist is mostly sorted, just refund loose pages at the end. */ - mdbx_dpl_sort(dl); - mdbx_tassert(txn, dl->length < 2 || dl[1].pgno < dl[dl->length].pgno); - mdbx_tassert(txn, dl->sorted == dl->length); - - /* Scan dirtylist tail-forward and cutoff suitable pages. */ - while (dl->length && dl[dl->length].pgno == txn->mt_next_pgno - 1 && - dl[dl->length].ptr->mp_flags == (P_LOOSE | P_DIRTY)) { - MDBX_page *dp = dl[dl->length].ptr; - mdbx_verbose("refund-unsorted page %" PRIaPGNO, dp->mp_pgno); - mdbx_tassert(txn, dp->mp_pgno == dl[dl->length].pgno); - dl->length -= 1; - } - - if (dl->sorted != dl->length) { - const unsigned refunded = dl->sorted - dl->length; - dl->sorted = dl->length; - txn->tw.loose_count -= refunded; - txn->tw.dirtyroom += refunded; - txn->mt_next_pgno -= refunded; - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - - /* Filter-out loose chain & dispose refunded pages. */ - unlink_loose: - for (MDBX_page **link = &txn->tw.loose_pages; *link;) { - MDBX_page *dp = *link; - mdbx_tassert(txn, dp->mp_flags == (P_LOOSE | P_DIRTY)); - if (txn->mt_next_pgno > dp->mp_pgno) { - link = &dp->mp_next; - } else { - *link = dp->mp_next; - if ((txn->mt_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(txn->mt_env, dp, 1); - } - } - } - } - - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - if (suitable != onstack) - mdbx_pnl_free(suitable); - txn->tw.loose_refund_wl = txn->mt_next_pgno; -} - -static bool mdbx_refund(MDBX_txn *txn) { - const pgno_t before = txn->mt_next_pgno; - - if (txn->tw.loose_pages && txn->tw.loose_refund_wl > txn->mt_next_pgno) - mdbx_refund_loose(txn); - - while (true) { - if (MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) == 0 || - MDBX_PNL_MOST(txn->tw.reclaimed_pglist) != txn->mt_next_pgno - 1) - break; - - mdbx_refund_reclaimed(txn); - if (!txn->tw.loose_pages || txn->tw.loose_refund_wl <= txn->mt_next_pgno) - break; - - const pgno_t memo = txn->mt_next_pgno; - mdbx_refund_loose(txn); - if (memo == txn->mt_next_pgno) - break; - } - - return before != txn->mt_next_pgno; -} - -static __cold void mdbx_kill_page(MDBX_env *env, MDBX_page *mp, pgno_t pgno, - unsigned npages) { - mdbx_assert(env, pgno >= NUM_METAS && npages); - if (IS_DIRTY(mp) || (env->me_flags & MDBX_WRITEMAP)) { - const size_t bytes = pgno2bytes(env, npages); - memset(mp, 0, bytes); - mp->mp_pgno = pgno; - if ((env->me_flags & MDBX_WRITEMAP) == 0) - mdbx_pwrite(env->me_fd, mp, bytes, pgno2bytes(env, pgno)); - } else { - struct iovec iov[MDBX_COMMIT_PAGES]; - iov[0].iov_len = env->me_psize; - iov[0].iov_base = (char *)env->me_pbuf + env->me_psize; - size_t iov_off = pgno2bytes(env, pgno); - unsigned n = 1; - while (--npages) { - iov[n] = iov[0]; - if (++n == MDBX_COMMIT_PAGES) { - mdbx_pwritev(env->me_fd, iov, MDBX_COMMIT_PAGES, iov_off, - pgno2bytes(env, MDBX_COMMIT_PAGES)); - iov_off += pgno2bytes(env, MDBX_COMMIT_PAGES); - n = 0; - } - } - mdbx_pwritev(env->me_fd, iov, n, iov_off, pgno2bytes(env, n)); - } -} - -/* Retire, loosen or free a single page. - * - * Saves single pages to a list for future reuse - * in this same txn. It has been pulled from the GC - * and already resides on the dirty list, but has been - * deleted. Use these pages first before pulling again - * from the GC. - * - * If the page wasn't dirtied in this txn, just add it - * to this txn's free list. */ - -static __hot int mdbx_page_loose(MDBX_txn *txn, MDBX_page *mp) { - const unsigned npages = IS_OVERFLOW(mp) ? mp->mp_pages : 1; - const pgno_t pgno = mp->mp_pgno; - - if (txn->mt_parent) { - mdbx_tassert(txn, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0); - mdbx_tassert(txn, mp != pgno2page(txn->mt_env, pgno)); - /* If txn has a parent, make sure the page is in our dirty list. */ - MDBX_page *dp = mdbx_dpl_find(txn->tw.dirtylist, pgno); - /* TODO: use extended flag-mask to track parent's dirty-pages */ - if (dp == nullptr) { - mp->mp_next = txn->tw.retired2parent_pages; - txn->tw.retired2parent_pages = mp; - txn->tw.retired2parent_count += npages; - return MDBX_SUCCESS; - } - if (unlikely(mp != dp)) { /* bad cursor? */ - mdbx_error( - "wrong page 0x%p #%" PRIaPGNO " in the dirtylist, expecting %p", - __Wpedantic_format_voidptr(dp), pgno, __Wpedantic_format_voidptr(mp)); - txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PROBLEM; - } - /* ok, it's ours */ - } - - mdbx_debug("loosen page %" PRIaPGNO, pgno); - const bool is_dirty = IS_DIRTY(mp); - if (MDBX_DEBUG || unlikely((txn->mt_env->me_flags & MDBX_PAGEPERTURB) != 0)) { - mdbx_kill_page(txn->mt_env, mp, pgno, npages); - VALGRIND_MAKE_MEM_UNDEFINED(mp, PAGEHDRSZ); - } - VALGRIND_MAKE_MEM_NOACCESS(page_data(mp), - pgno2bytes(txn->mt_env, npages) - PAGEHDRSZ); - ASAN_POISON_MEMORY_REGION(page_data(mp), - pgno2bytes(txn->mt_env, npages) - PAGEHDRSZ); - - if (unlikely(npages > - 1 /* overflow pages doesn't comes to the loose-list */)) { - if (is_dirty) { - /* Remove from dirty list */ - MDBX_page *dp = mdbx_dpl_remove(txn->tw.dirtylist, pgno); - if (unlikely(dp != mp)) { - mdbx_error("not found page 0x%p #%" PRIaPGNO " in the dirtylist", - __Wpedantic_format_voidptr(mp), pgno); - txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PROBLEM; - } - txn->tw.dirtyroom++; - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - if ((txn->mt_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(txn->mt_env, mp, npages); - } - - if (unlikely(pgno + npages == txn->mt_next_pgno)) { - txn->mt_next_pgno = pgno; - mdbx_refund(txn); - return MDBX_SUCCESS; - } - - int rc = mdbx_pnl_insert_range(&txn->tw.reclaimed_pglist, pgno, npages); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - return MDBX_SUCCESS; - } - - mp->mp_flags = P_LOOSE | P_DIRTY; - mp->mp_next = txn->tw.loose_pages; - txn->tw.loose_pages = mp; - txn->tw.loose_count++; - if (unlikely(txn->mt_next_pgno == mp->mp_pgno + 1)) - mdbx_refund(txn); - - return MDBX_SUCCESS; -} - -static __hot int mdbx_page_retire(MDBX_cursor *mc, MDBX_page *mp) { - const unsigned npages = IS_OVERFLOW(mp) ? mp->mp_pages : 1; - const pgno_t pgno = mp->mp_pgno; - MDBX_txn *const txn = mc->mc_txn; - - if (unlikely(mc->mc_flags & C_SUB)) { - MDBX_db *outer = mdbx_outer_db(mc); - mdbx_cassert(mc, !IS_BRANCH(mp) || outer->md_branch_pages > 0); - outer->md_branch_pages -= IS_BRANCH(mp); - mdbx_cassert(mc, !IS_LEAF(mp) || outer->md_leaf_pages > 0); - outer->md_leaf_pages -= IS_LEAF(mp); - mdbx_cassert(mc, !IS_OVERFLOW(mp)); - } - mdbx_cassert(mc, !IS_BRANCH(mp) || mc->mc_db->md_branch_pages > 0); - mc->mc_db->md_branch_pages -= IS_BRANCH(mp); - mdbx_cassert(mc, !IS_LEAF(mp) || mc->mc_db->md_leaf_pages > 0); - mc->mc_db->md_leaf_pages -= IS_LEAF(mp); - mdbx_cassert(mc, !IS_OVERFLOW(mp) || mc->mc_db->md_overflow_pages >= npages); - mc->mc_db->md_overflow_pages -= IS_OVERFLOW(mp) ? npages : 0; - - if (IS_DIRTY(mp)) { - int rc = mdbx_page_loose(txn, mp); - if (unlikely(rc != MDBX_SUCCESS)) - mc->mc_flags &= ~(C_INITIALIZED | C_EOF); - return rc; - } - - if (txn->tw.spill_pages) { - const unsigned i = mdbx_pnl_exist(txn->tw.spill_pages, pgno << 1); - if (i) { - /* This page is no longer spilled */ - mdbx_tassert(txn, i == MDBX_PNL_SIZE(txn->tw.spill_pages) || - txn->tw.spill_pages[i + 1] >= (pgno + npages) << 1); - txn->tw.spill_pages[i] |= 1; - if (i == MDBX_PNL_SIZE(txn->tw.spill_pages)) - MDBX_PNL_SIZE(txn->tw.spill_pages) -= 1; - int rc = mdbx_page_loose(txn, mp); - if (unlikely(rc != MDBX_SUCCESS)) - mc->mc_flags &= ~(C_INITIALIZED | C_EOF); - return rc; - } - } - - mdbx_tassert(txn, mp == pgno2page(txn->mt_env, pgno)); - int rc = mdbx_pnl_append_range(&txn->tw.retired_pages, pgno, npages); - mdbx_tassert(txn, mdbx_dpl_find(txn->tw.dirtylist, pgno) == nullptr); - return rc; -} - -static __must_check_result __inline int mdbx_retire_pgno(MDBX_cursor *mc, - const pgno_t pgno) { - MDBX_page *mp; - int rc = mdbx_page_get(mc, pgno, &mp, NULL); - if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_page_retire(mc, mp); - return rc; -} - -/* Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn. - * - * [in] mc A cursor handle for the current operation. - * [in] pflags Flags of the pages to update: - * - P_DIRTY to set P_KEEP, - * - P_DIRTY|P_KEEP to clear it. - * [in] all No shortcuts. Needed except after a full mdbx_page_flush(). - * - * Returns 0 on success, non-zero on failure. */ -static int mdbx_pages_xkeep(MDBX_cursor *mc, unsigned pflags, bool all) { - const unsigned Mask = P_SUBP | P_DIRTY | P_LOOSE | P_KEEP; - MDBX_txn *txn = mc->mc_txn; - MDBX_cursor *m3, *m0 = mc; - MDBX_xcursor *mx; - MDBX_page *dp, *mp; - unsigned i, j; - int rc = MDBX_SUCCESS; - - /* Mark pages seen by cursors: First m0, then tracked cursors */ - for (i = txn->mt_numdbs;;) { - if (mc->mc_flags & C_INITIALIZED) { - for (m3 = mc;; m3 = &mx->mx_cursor) { - mp = NULL; - for (j = 0; j < m3->mc_snum; j++) { - mp = m3->mc_pg[j]; - if ((mp->mp_flags & Mask) == pflags) - mp->mp_flags ^= P_KEEP; - } - mx = m3->mc_xcursor; - /* Proceed to mx if it is at a sub-database */ - if (!(mx && (mx->mx_cursor.mc_flags & C_INITIALIZED))) - break; - if (!(mp && IS_LEAF(mp))) - break; - if (!(node_flags(page_node(mp, m3->mc_ki[j - 1])) & F_SUBDATA)) - break; - } - } - mc = mc->mc_next; - for (; !mc || mc == m0; mc = txn->mt_cursors[--i]) - if (i == 0) - goto mark_done; - } - -mark_done: - if (all) { - /* Mark dirty root pages */ - for (i = 0; i < txn->mt_numdbs; i++) { - if (txn->mt_dbflags[i] & DB_DIRTY) { - pgno_t pgno = txn->mt_dbs[i].md_root; - if (pgno == P_INVALID) - continue; - int level; - if (unlikely((rc = mdbx_page_get(m0, pgno, &dp, &level)) != - MDBX_SUCCESS)) - break; - if ((dp->mp_flags & Mask) == pflags && level <= 1) - dp->mp_flags ^= P_KEEP; - } - } - } - - return rc; -} - -/* Spill pages from the dirty list back to disk. - * This is intended to prevent running into MDBX_TXN_FULL situations, - * but note that they may still occur in a few cases: - * - * 1) our estimate of the txn size could be too small. Currently this - * seems unlikely, except with a large number of MDBX_MULTIPLE items. - * - * 2) child txns may run out of space if their parents dirtied a - * lot of pages and never spilled them. TODO: we probably should do - * a preemptive spill during mdbx_txn_begin() of a child txn, if - * the parent's dirtyroom is below a given threshold. - * - * Otherwise, if not using nested txns, it is expected that apps will - * not run into MDBX_TXN_FULL any more. The pages are flushed to disk - * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared. - * If the txn never references them again, they can be left alone. - * If the txn only reads them, they can be used without any fuss. - * If the txn writes them again, they can be dirtied immediately without - * going thru all of the work of mdbx_page_touch(). Such references are - * handled by mdbx_page_unspill(). - * - * Also note, we never spill DB root pages, nor pages of active cursors, - * because we'll need these back again soon anyway. And in nested txns, - * we can't spill a page in a child txn if it was already spilled in a - * parent txn. That would alter the parent txns' data even though - * the child hasn't committed yet, and we'd have no way to undo it if - * the child aborted. - * - * [in] mc cursor A cursor handle identifying the transaction and - * database for which we are checking space. - * [in] key For a put operation, the key being stored. - * [in] data For a put operation, the data being stored. - * - * Returns 0 on success, non-zero on failure. */ -static int mdbx_page_spill(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) { - if (mc->mc_flags & C_SUB) - return MDBX_SUCCESS; - - MDBX_txn *txn = mc->mc_txn; - MDBX_DPL dl = txn->tw.dirtylist; - - /* Estimate how much space this op will take */ - pgno_t i = mc->mc_db->md_depth; - /* Named DBs also dirty the main DB */ - if (mc->mc_dbi >= CORE_DBS) - i += txn->mt_dbs[MAIN_DBI].md_depth; - /* For puts, roughly factor in the key+data size */ - if (key) - i += bytes2pgno(txn->mt_env, node_size(key, data) + txn->mt_env->me_psize); - i += i; /* double it for good measure */ - pgno_t need = i; - - if (txn->tw.dirtyroom > i) - return MDBX_SUCCESS; - - if (!txn->tw.spill_pages) { - txn->tw.spill_pages = mdbx_pnl_alloc(MDBX_DPL_TXNFULL / 8); - if (unlikely(!txn->tw.spill_pages)) - return MDBX_ENOMEM; - } else { - /* purge deleted slots */ - MDBX_PNL sl = txn->tw.spill_pages; - pgno_t num = MDBX_PNL_SIZE(sl), j = 0; - for (i = 1; i <= num; i++) { - if ((sl[i] & 1) == 0) - sl[++j] = sl[i]; - } - MDBX_PNL_SIZE(sl) = j; - } - - /* Preserve pages which may soon be dirtied again */ - int rc = mdbx_pages_xkeep(mc, P_DIRTY, true); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - - /* Less aggressive spill - we originally spilled the entire dirty list, - * with a few exceptions for cursor pages and DB root pages. But this - * turns out to be a lot of wasted effort because in a large txn many - * of those pages will need to be used again. So now we spill only 1/8th - * of the dirty pages. Testing revealed this to be a good tradeoff, - * better than 1/2, 1/4, or 1/10. */ - if (need < MDBX_DPL_TXNFULL / 8) - need = MDBX_DPL_TXNFULL / 8; - - /* Save the page IDs of all the pages we're flushing */ - /* flush from the tail forward, this saves a lot of shifting later on. */ - for (i = dl->length; i && need; i--) { - pgno_t pn = dl[i].pgno << 1; - MDBX_page *dp = dl[i].ptr; - if (dp->mp_flags & (P_LOOSE | P_KEEP)) - continue; - /* Can't spill twice, - * make sure it's not already in a parent's spill list. */ - if (txn->mt_parent) { - MDBX_txn *parent; - for (parent = txn->mt_parent; parent; parent = parent->mt_parent) { - if (parent->tw.spill_pages && - mdbx_pnl_exist(parent->tw.spill_pages, pn)) { - dp->mp_flags |= P_KEEP; - break; - } - } - if (parent) - continue; - } - rc = mdbx_pnl_append(&txn->tw.spill_pages, pn); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - need--; - } - mdbx_pnl_sort(txn->tw.spill_pages); - - /* Flush the spilled part of dirty list */ - rc = mdbx_page_flush(txn, i); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - - /* Reset any dirty pages we kept that page_flush didn't see */ - rc = mdbx_pages_xkeep(mc, P_DIRTY | P_KEEP, i != 0); - -bailout: - txn->mt_flags |= rc ? MDBX_TXN_ERROR : MDBX_TXN_SPILLS; - return rc; -} - -/*----------------------------------------------------------------------------*/ - -#define METAPAGE(env, n) page_meta(pgno2page(env, n)) -#define METAPAGE_END(env) METAPAGE(env, NUM_METAS) - -static __inline txnid_t meta_txnid(const MDBX_env *env, const MDBX_meta *meta, - bool allow_volatile) { - mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); - txnid_t a = safe64_read(&meta->mm_txnid_a); - txnid_t b = safe64_read(&meta->mm_txnid_b); - if (allow_volatile) - return (a == b) ? a : 0; - mdbx_assert(env, a == b); - return a; -} - -static __inline txnid_t mdbx_meta_txnid_stable(const MDBX_env *env, - const MDBX_meta *meta) { - return meta_txnid(env, meta, false); -} - -static __inline txnid_t mdbx_meta_txnid_fluid(const MDBX_env *env, - const MDBX_meta *meta) { - return meta_txnid(env, meta, true); -} - -static __inline void mdbx_meta_update_begin(const MDBX_env *env, - MDBX_meta *meta, txnid_t txnid) { - mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); - mdbx_assert(env, meta->mm_txnid_a.inconsistent < txnid && - meta->mm_txnid_b.inconsistent < txnid); - (void)env; - safe64_update(&meta->mm_txnid_a, txnid); -} - -static __inline void mdbx_meta_update_end(const MDBX_env *env, MDBX_meta *meta, - txnid_t txnid) { - mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); - mdbx_assert(env, meta->mm_txnid_a.inconsistent == txnid); - mdbx_assert(env, meta->mm_txnid_b.inconsistent < txnid); - (void)env; - mdbx_jitter4testing(true); - safe64_update(&meta->mm_txnid_b, txnid); -} - -static __inline void mdbx_meta_set_txnid(const MDBX_env *env, MDBX_meta *meta, - txnid_t txnid) { - mdbx_assert(env, meta < METAPAGE(env, 0) || meta > METAPAGE_END(env)); - (void)env; - /* update inconsistent since this function used ONLY for filling meta-image - * for writing, but not the actual meta-page */ - meta->mm_txnid_a.inconsistent = txnid; - meta->mm_txnid_b.inconsistent = txnid; -} - -static __inline uint64_t mdbx_meta_sign(const MDBX_meta *meta) { - uint64_t sign = MDBX_DATASIGN_NONE; -#if 0 /* TODO */ - sign = hippeus_hash64(...); -#else - (void)meta; -#endif - /* LY: newer returns MDBX_DATASIGN_NONE or MDBX_DATASIGN_WEAK */ - return (sign > MDBX_DATASIGN_WEAK) ? sign : ~sign; -} - -enum meta_choise_mode { prefer_last, prefer_noweak, prefer_steady }; - -static __inline bool mdbx_meta_ot(const enum meta_choise_mode mode, - const MDBX_env *env, const MDBX_meta *a, - const MDBX_meta *b) { - mdbx_jitter4testing(true); - txnid_t txnid_a = mdbx_meta_txnid_fluid(env, a); - txnid_t txnid_b = mdbx_meta_txnid_fluid(env, b); - - mdbx_jitter4testing(true); - switch (mode) { - default: - assert(false); - __unreachable(); - /* fall through */ - __fallthrough; - case prefer_steady: - if (META_IS_STEADY(a) != META_IS_STEADY(b)) - return META_IS_STEADY(b); - /* fall through */ - __fallthrough; - case prefer_noweak: - if (META_IS_WEAK(a) != META_IS_WEAK(b)) - return !META_IS_WEAK(b); - /* fall through */ - __fallthrough; - case prefer_last: - mdbx_jitter4testing(true); - if (txnid_a == txnid_b) - return META_IS_STEADY(b) || (META_IS_WEAK(a) && !META_IS_WEAK(b)); - return txnid_a < txnid_b; - } -} - -static __inline bool mdbx_meta_eq(const MDBX_env *env, const MDBX_meta *a, - const MDBX_meta *b) { - mdbx_jitter4testing(true); - const txnid_t txnid = mdbx_meta_txnid_fluid(env, a); - if (!txnid || txnid != mdbx_meta_txnid_fluid(env, b)) - return false; - - mdbx_jitter4testing(true); - if (META_IS_STEADY(a) != META_IS_STEADY(b)) - return false; - - mdbx_jitter4testing(true); - return true; -} - -static int mdbx_meta_eq_mask(const MDBX_env *env) { - MDBX_meta *m0 = METAPAGE(env, 0); - MDBX_meta *m1 = METAPAGE(env, 1); - MDBX_meta *m2 = METAPAGE(env, 2); - - int rc = mdbx_meta_eq(env, m0, m1) ? 1 : 0; - if (mdbx_meta_eq(env, m1, m2)) - rc += 2; - if (mdbx_meta_eq(env, m2, m0)) - rc += 4; - return rc; -} - -static __inline MDBX_meta *mdbx_meta_recent(const enum meta_choise_mode mode, - const MDBX_env *env, MDBX_meta *a, - MDBX_meta *b) { - const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b); - mdbx_assert(env, !mdbx_meta_eq(env, a, b)); - return a_older_that_b ? b : a; -} - -static __inline MDBX_meta *mdbx_meta_ancient(const enum meta_choise_mode mode, - const MDBX_env *env, MDBX_meta *a, - MDBX_meta *b) { - const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b); - mdbx_assert(env, !mdbx_meta_eq(env, a, b)); - return a_older_that_b ? a : b; -} - -static __inline MDBX_meta * -mdbx_meta_mostrecent(const enum meta_choise_mode mode, const MDBX_env *env) { - MDBX_meta *m0 = METAPAGE(env, 0); - MDBX_meta *m1 = METAPAGE(env, 1); - MDBX_meta *m2 = METAPAGE(env, 2); - - MDBX_meta *head = mdbx_meta_recent(mode, env, m0, m1); - head = mdbx_meta_recent(mode, env, head, m2); - return head; -} - -static __hot MDBX_meta *mdbx_meta_steady(const MDBX_env *env) { - return mdbx_meta_mostrecent(prefer_steady, env); -} - -static __hot MDBX_meta *mdbx_meta_head(const MDBX_env *env) { - return mdbx_meta_mostrecent(prefer_last, env); -} - -static __hot txnid_t mdbx_recent_committed_txnid(const MDBX_env *env) { - while (true) { - const MDBX_meta *head = mdbx_meta_head(env); - const txnid_t recent = mdbx_meta_txnid_fluid(env, head); - mdbx_compiler_barrier(); - if (likely(head == mdbx_meta_head(env) && - recent == mdbx_meta_txnid_fluid(env, head))) - return recent; - } -} - -static __hot txnid_t mdbx_recent_steady_txnid(const MDBX_env *env) { - while (true) { - const MDBX_meta *head = mdbx_meta_steady(env); - const txnid_t recent = mdbx_meta_txnid_fluid(env, head); - mdbx_compiler_barrier(); - if (likely(head == mdbx_meta_steady(env) && - recent == mdbx_meta_txnid_fluid(env, head))) - return recent; - } -} - -static __hot txnid_t mdbx_reclaiming_detent(const MDBX_env *env) { - if (F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC)) - return likely(env->me_txn0->mt_owner == mdbx_thread_self()) - ? env->me_txn0->mt_txnid - MDBX_TXNID_STEP - : mdbx_recent_committed_txnid(env); - - return mdbx_recent_steady_txnid(env); -} - -static const char *mdbx_durable_str(const MDBX_meta *const meta) { - if (META_IS_WEAK(meta)) - return "Weak"; - if (META_IS_STEADY(meta)) - return (meta->mm_datasync_sign == mdbx_meta_sign(meta)) ? "Steady" - : "Tainted"; - return "Legacy"; -} - -/*----------------------------------------------------------------------------*/ - -/* Find oldest txnid still referenced. */ -static txnid_t mdbx_find_oldest(MDBX_txn *txn) { - mdbx_tassert(txn, (txn->mt_flags & MDBX_RDONLY) == 0); - MDBX_env *env = txn->mt_env; - const txnid_t edge = mdbx_reclaiming_detent(env); - mdbx_tassert(txn, edge <= txn->mt_txnid); - - MDBX_lockinfo *const lck = env->me_lck; - if (unlikely(lck == NULL /* exclusive mode */)) - return env->me_lckless_stub.oldest = edge; - - const txnid_t last_oldest = lck->mti_oldest_reader; - mdbx_tassert(txn, edge >= last_oldest); - if (likely(last_oldest == edge)) - return edge; - - const uint32_t nothing_changed = MDBX_STRING_TETRAD("None"); - const uint32_t snap_readers_refresh_flag = lck->mti_readers_refresh_flag; - mdbx_jitter4testing(false); - if (snap_readers_refresh_flag == nothing_changed) - return last_oldest; - - txnid_t oldest = edge; - lck->mti_readers_refresh_flag = nothing_changed; - mdbx_flush_noncoherent_cpu_writeback(); - const unsigned snap_nreaders = lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; ++i) { - if (lck->mti_readers[i].mr_pid) { - /* mdbx_jitter4testing(true); */ - const txnid_t snap = safe64_read(&lck->mti_readers[i].mr_txnid); - if (oldest > snap && last_oldest <= /* ignore pending updates */ snap) { - oldest = snap; - if (oldest == last_oldest) - return oldest; - } - } - } - - if (oldest != last_oldest) { - mdbx_notice("update oldest %" PRIaTXN " -> %" PRIaTXN, last_oldest, oldest); - mdbx_tassert(txn, oldest >= lck->mti_oldest_reader); - lck->mti_oldest_reader = oldest; - } - return oldest; -} - -/* Find largest mvcc-snapshot still referenced. */ -static __cold pgno_t mdbx_find_largest(MDBX_env *env, pgno_t largest) { - MDBX_lockinfo *const lck = env->me_lck; - if (likely(lck != NULL /* exclusive mode */)) { - const unsigned snap_nreaders = lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; ++i) { - retry: - if (lck->mti_readers[i].mr_pid) { - /* mdbx_jitter4testing(true); */ - const pgno_t snap_pages = lck->mti_readers[i].mr_snapshot_pages_used; - const txnid_t snap_txnid = safe64_read(&lck->mti_readers[i].mr_txnid); - mdbx_memory_barrier(); - if (unlikely(snap_pages != lck->mti_readers[i].mr_snapshot_pages_used || - snap_txnid != safe64_read(&lck->mti_readers[i].mr_txnid))) - goto retry; - if (largest < snap_pages && - lck->mti_oldest_reader <= /* ignore pending updates */ snap_txnid && - snap_txnid <= env->me_txn0->mt_txnid) - largest = snap_pages; - } - } - } - - return largest; -} - -/* Add a page to the txn's dirty list */ -static int __must_check_result mdbx_page_dirty(MDBX_txn *txn, MDBX_page *mp) { - const int rc = mdbx_dpl_append(txn->tw.dirtylist, mp->mp_pgno, mp); - if (unlikely(rc != MDBX_SUCCESS)) { - txn->mt_flags |= MDBX_TXN_ERROR; - return rc; - } - txn->tw.dirtyroom--; - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - return MDBX_SUCCESS; -} - -/* Turn on/off readahead. It's harmful when the DB is larger than RAM. */ -static int __cold mdbx_set_readahead(MDBX_env *env, const size_t offset, - const size_t length, const bool enable) { - assert(length > 0); - mdbx_notice("readahead %s %u..%u", enable ? "ON" : "OFF", - bytes2pgno(env, offset), bytes2pgno(env, offset + length)); - -#if defined(F_RDAHEAD) - if (unlikely(fcntl(env->me_fd, F_RDAHEAD, enable) == -1)) - return errno; -#endif /* F_RDAHEAD */ - - if (enable) { -#if defined(F_RDADVISE) - struct radvisory hint; - hint.ra_offset = offset; - hint.ra_count = length; - (void)/* Ignore ENOTTY for DB on the ram-disk and so on */ fcntl( - env->me_fd, F_RDADVISE, &hint); -#endif /* F_RDADVISE */ -#if defined(MADV_WILLNEED) - if (unlikely(madvise(env->me_map + offset, length, MADV_WILLNEED) != 0)) - return errno; -#elif defined(POSIX_MADV_WILLNEED) - rc = posix_madvise(env->me_map + offset, length, POSIX_MADV_WILLNEED); - if (unlikely(rc != 0)) - return errno; -#elif defined(_WIN32) || defined(_WIN64) - if (mdbx_PrefetchVirtualMemory) { - WIN32_MEMORY_RANGE_ENTRY hint; - hint.VirtualAddress = env->me_map + offset; - hint.NumberOfBytes = length; - (void)mdbx_PrefetchVirtualMemory(GetCurrentProcess(), 1, &hint, 0); - } -#elif defined(POSIX_FADV_WILLNEED) - int err = posix_fadvise(env->me_fd, offset, length, POSIX_FADV_WILLNEED); - if (unlikely(err != 0)) - return err; -#endif /* MADV_WILLNEED */ - } else { -#if defined(MADV_RANDOM) - if (unlikely(madvise(env->me_map + offset, length, MADV_RANDOM) != 0)) - return errno; -#elif defined(POSIX_MADV_RANDOM) - int err = posix_madvise(env->me_map + offset, length, POSIX_MADV_RANDOM); - if (unlikely(err != 0)) - return err; -#elif defined(POSIX_FADV_RANDOM) - int err = posix_fadvise(env->me_fd, offset, length, POSIX_FADV_RANDOM); - if (unlikely(err != 0)) - return err; -#endif /* MADV_RANDOM */ - } - return MDBX_SUCCESS; -} - -static __cold int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno, - const pgno_t limit_pgno) { - const size_t limit_bytes = pgno_align2os_bytes(env, limit_pgno); - const size_t size_bytes = pgno_align2os_bytes(env, size_pgno); - - mdbx_verbose("resize datafile/mapping: " - "present %" PRIuPTR " -> %" PRIuPTR ", " - "limit %" PRIuPTR " -> %" PRIuPTR, - env->me_dxb_mmap.current, size_bytes, env->me_dxb_mmap.limit, - limit_bytes); - - mdbx_assert(env, limit_bytes >= size_bytes); - mdbx_assert(env, bytes2pgno(env, size_bytes) >= size_pgno); - mdbx_assert(env, bytes2pgno(env, limit_bytes) >= limit_pgno); - -#if defined(_WIN32) || defined(_WIN64) - /* Acquire guard in exclusive mode for: - * - to avoid collision between read and write txns around env->me_dbgeo; - * - to avoid attachment of new reading threads (see mdbx_rdt_lock); */ - mdbx_srwlock_AcquireExclusive(&env->me_remap_guard); - mdbx_handle_array_t *suspended = NULL; - mdbx_handle_array_t array_onstack; - int rc = MDBX_SUCCESS; - if (limit_bytes == env->me_dxb_mmap.limit && - size_bytes == env->me_dxb_mmap.current && - size_bytes == env->me_dxb_mmap.filesize) - goto bailout; - - /* 1) Windows allows only extending a read-write section, but not a - * corresponing mapped view. Therefore in other cases we must suspend - * the local threads for safe remap. - * 2) At least on Windows 10 1803 the entire mapped section is unavailable - * for short time during NtExtendSection() or VirtualAlloc() execution. - * - * THEREFORE LOCAL THREADS SUSPENDING IS ALWAYS REQUIRED! */ - array_onstack.limit = ARRAY_LENGTH(array_onstack.handles); - array_onstack.count = 0; - suspended = &array_onstack; - rc = mdbx_suspend_threads_before_remap(env, &suspended); - if (rc != MDBX_SUCCESS) { - mdbx_error("failed suspend-for-remap: errcode %d", rc); - goto bailout; - } -#else - /* Acquire guard to avoid collision between read and write txns - * around env->me_dbgeo */ - int rc = mdbx_fastmutex_acquire(&env->me_remap_guard); - if (rc != MDBX_SUCCESS) - return rc; - if (limit_bytes == env->me_dxb_mmap.limit && - size_bytes == env->me_dxb_mmap.current) - goto bailout; -#endif /* Windows */ - - const size_t prev_limit = env->me_dxb_mmap.limit; - const void *const prev_addr = env->me_map; - const size_t prev_size = env->me_dxb_mmap.current; - if (size_bytes < prev_size) { - mdbx_notice("resize-MADV_%s %u..%u", - (env->me_flags & MDBX_WRITEMAP) ? "REMOVE" : "DONTNEED", - size_pgno, bytes2pgno(env, prev_size)); -#if defined(MADV_REMOVE) - if ((env->me_flags & MDBX_WRITEMAP) == 0 || - madvise(env->me_map + size_bytes, prev_size - size_bytes, - MADV_REMOVE) != 0) -#endif -#if defined(MADV_DONTNEED) - (void)madvise(env->me_map + size_bytes, prev_size - size_bytes, - MADV_DONTNEED); -#elif defined(POSIX_MADV_DONTNEED) - (void)posix_madvise(env->me_map + size_bytes, prev_size - size_bytes, - POSIX_MADV_DONTNEED); -#elif defined(POSIX_FADV_DONTNEED) - (void)posix_fadvise(env->me_fd, size_bytes, prev_size - size_bytes, - POSIX_FADV_DONTNEED); -#else - __noop(); -#endif /* MADV_DONTNEED */ - if (*env->me_discarded_tail > size_pgno) - *env->me_discarded_tail = size_pgno; - } - - rc = mdbx_mresize(env->me_flags, &env->me_dxb_mmap, size_bytes, limit_bytes); - if (rc == MDBX_SUCCESS && (env->me_flags & MDBX_NORDAHEAD) == 0) { - rc = mdbx_is_readahead_reasonable(size_bytes, 0); - if (rc == MDBX_RESULT_FALSE) - rc = mdbx_set_readahead( - env, 0, (size_bytes > prev_size) ? size_bytes : prev_size, false); - else if (rc == MDBX_RESULT_TRUE) { - rc = MDBX_SUCCESS; - const size_t readahead_pivot = - (limit_bytes != prev_limit || env->me_dxb_mmap.address != prev_addr -#if defined(_WIN32) || defined(_WIN64) - || prev_size > size_bytes -#endif /* Windows */ - ) - ? 0 /* reassign readahead to the entire map - because it was remapped */ - : prev_size; - if (size_bytes > readahead_pivot) { - *env->me_discarded_tail = size_pgno; - rc = mdbx_set_readahead(env, readahead_pivot, - size_bytes - readahead_pivot, true); - } - } - } - -bailout: - if (rc == MDBX_SUCCESS) { -#if defined(_WIN32) || defined(_WIN64) - mdbx_assert(env, size_bytes == env->me_dxb_mmap.current); - mdbx_assert(env, size_bytes <= env->me_dxb_mmap.filesize); - mdbx_assert(env, limit_bytes == env->me_dxb_mmap.limit); -#endif /* Windows */ -#ifdef MDBX_USE_VALGRIND - if (prev_limit != env->me_dxb_mmap.limit || prev_addr != env->me_map) { - VALGRIND_DISCARD(env->me_valgrind_handle); - env->me_valgrind_handle = 0; - if (env->me_dxb_mmap.limit) - env->me_valgrind_handle = - VALGRIND_CREATE_BLOCK(env->me_map, env->me_dxb_mmap.limit, "mdbx"); - } -#endif /* MDBX_USE_VALGRIND */ - } else { - if (rc != MDBX_RESULT_TRUE) { - mdbx_error("failed resize datafile/mapping: " - "present %" PRIuPTR " -> %" PRIuPTR ", " - "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d", - env->me_dxb_mmap.current, size_bytes, env->me_dxb_mmap.limit, - limit_bytes, rc); - } else { - mdbx_notice("unable resize datafile/mapping: " - "present %" PRIuPTR " -> %" PRIuPTR ", " - "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d", - env->me_dxb_mmap.current, size_bytes, env->me_dxb_mmap.limit, - limit_bytes, rc); - } - if (!env->me_dxb_mmap.address) { - env->me_flags |= MDBX_FATAL_ERROR; - if (env->me_txn) - env->me_txn->mt_flags |= MDBX_TXN_ERROR; - rc = MDBX_PANIC; - } - } - -#if defined(_WIN32) || defined(_WIN64) - int err = MDBX_SUCCESS; - mdbx_srwlock_ReleaseExclusive(&env->me_remap_guard); - if (suspended) { - err = mdbx_resume_threads_after_remap(suspended); - if (suspended != &array_onstack) - mdbx_free(suspended); - } -#else - int err = mdbx_fastmutex_release(&env->me_remap_guard); -#endif /* Windows */ - if (err != MDBX_SUCCESS) { - mdbx_fatal("failed resume-after-remap: errcode %d", err); - return MDBX_PANIC; - } - return rc; -} - -/* Allocate page numbers and memory for writing. Maintain mt_last_reclaimed, - * mt_reclaimed_pglist and mt_next_pgno. Set MDBX_TXN_ERROR on failure. - * - * If there are free pages available from older transactions, they - * are re-used first. Otherwise allocate a new page at mt_next_pgno. - * Do not modify the GC, just merge GC records into mt_reclaimed_pglist - * and move mt_last_reclaimed to say which records were consumed. Only this - * function can create mt_reclaimed_pglist and move - * mt_last_reclaimed/mt_next_pgno. - * - * [in] mc cursor A cursor handle identifying the transaction and - * database for which we are allocating. - * [in] num the number of pages to allocate. - * [out] mp Address of the allocated page(s). Requests for multiple pages - * will always be satisfied by a single contiguous chunk of memory. - * - * Returns 0 on success, non-zero on failure.*/ - -#define MDBX_ALLOC_CACHE 1 -#define MDBX_ALLOC_GC 2 -#define MDBX_ALLOC_NEW 4 -#define MDBX_ALLOC_KICK 8 -#define MDBX_ALLOC_ALL \ - (MDBX_ALLOC_CACHE | MDBX_ALLOC_GC | MDBX_ALLOC_NEW | MDBX_ALLOC_KICK) - -static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, - int flags) { - int rc; - MDBX_txn *txn = mc->mc_txn; - MDBX_env *env = txn->mt_env; - MDBX_page *np; - - if (likely(flags & MDBX_ALLOC_GC)) { - flags |= env->me_flags & (MDBX_COALESCE | MDBX_LIFORECLAIM); - if (unlikely(mc->mc_flags & C_RECLAIMING)) { - /* If mc is updating the GC, then the retired-list cannot play - * catch-up with itself by growing while trying to save it. */ - flags &= - ~(MDBX_ALLOC_GC | MDBX_ALLOC_KICK | MDBX_COALESCE | MDBX_LIFORECLAIM); - } else if (unlikely(txn->mt_dbs[FREE_DBI].md_entries == 0)) { - /* avoid (recursive) search inside empty tree and while tree is updating, - * https://github.com/leo-yuriev/libmdbx/issues/31 */ - flags &= ~MDBX_ALLOC_GC; - } - } - - if (likely(flags & MDBX_ALLOC_CACHE)) { - /* If there are any loose pages, just use them */ - mdbx_assert(env, mp && num); - if (likely(num == 1 && txn->tw.loose_pages)) { - if (txn->tw.loose_refund_wl > txn->mt_next_pgno) { - mdbx_refund(txn); - if (unlikely(!txn->tw.loose_pages)) - goto skip_cache; - } - - np = txn->tw.loose_pages; - txn->tw.loose_pages = np->mp_next; - txn->tw.loose_count--; - mdbx_debug("db %d use loose page %" PRIaPGNO, DDBI(mc), np->mp_pgno); - mdbx_tassert(txn, np->mp_pgno < txn->mt_next_pgno); - mdbx_ensure(env, np->mp_pgno >= NUM_METAS); - VALGRIND_MAKE_MEM_UNDEFINED(page_data(np), page_space(txn->mt_env)); - ASAN_UNPOISON_MEMORY_REGION(page_data(np), page_space(txn->mt_env)); - *mp = np; - return MDBX_SUCCESS; - } - } -skip_cache: - - mdbx_tassert( - txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, txn->mt_next_pgno)); - pgno_t pgno, *re_list = txn->tw.reclaimed_pglist; - unsigned range_begin = 0, re_len = MDBX_PNL_SIZE(re_list); - txnid_t oldest = 0, last = 0; - const unsigned wanna_range = num - 1; - - while (1) { /* oom-kick retry loop */ - /* If our dirty list is already full, we can't do anything */ - if (unlikely(txn->tw.dirtyroom == 0)) { - rc = MDBX_TXN_FULL; - goto fail; - } - - MDBX_cursor recur; - for (MDBX_cursor_op op = MDBX_FIRST;; - op = (flags & MDBX_LIFORECLAIM) ? MDBX_PREV : MDBX_NEXT) { - MDBX_val key, data; - - /* Seek a big enough contiguous page range. - * Prefer pages with lower pgno. */ - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - if (likely(flags & MDBX_ALLOC_CACHE) && re_len > wanna_range && - (!(flags & MDBX_COALESCE) || op == MDBX_FIRST)) { - mdbx_tassert(txn, MDBX_PNL_LAST(re_list) < txn->mt_next_pgno && - MDBX_PNL_FIRST(re_list) < txn->mt_next_pgno); - range_begin = MDBX_PNL_ASCENDING ? 1 : re_len; - pgno = MDBX_PNL_LEAST(re_list); - if (likely(wanna_range == 0)) - goto done; -#if MDBX_PNL_ASCENDING - mdbx_tassert(txn, pgno == re_list[1] && range_begin == 1); - while (true) { - unsigned range_end = range_begin + wanna_range; - if (re_list[range_end] - pgno == wanna_range) - goto done; - if (range_end == re_len) - break; - pgno = re_list[++range_begin]; - } -#else - mdbx_tassert(txn, pgno == re_list[re_len] && range_begin == re_len); - while (true) { - if (re_list[range_begin - wanna_range] - pgno == wanna_range) - goto done; - if (range_begin == wanna_range) - break; - pgno = re_list[--range_begin]; - } -#endif /* MDBX_PNL sort-order */ - } - - if (op == MDBX_FIRST) { /* 1st iteration, setup cursor, etc */ - if (unlikely(!(flags & MDBX_ALLOC_GC))) - break /* reclaiming is prohibited for now */; - - /* Prepare to fetch more and coalesce */ - oldest = (flags & MDBX_LIFORECLAIM) ? mdbx_find_oldest(txn) - : *env->me_oldest; - rc = mdbx_cursor_init(&recur, txn, FREE_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - if (flags & MDBX_LIFORECLAIM) { - /* Begin from oldest reader if any */ - if (oldest > 2) { - last = oldest - 1; - op = MDBX_SET_RANGE; - } - } else if (txn->tw.last_reclaimed) { - /* Continue lookup from txn->tw.last_reclaimed to oldest reader */ - last = txn->tw.last_reclaimed; - op = MDBX_SET_RANGE; - } - - key.iov_base = &last; - key.iov_len = sizeof(last); - } - - if (!(flags & MDBX_LIFORECLAIM)) { - /* Do not try fetch more if the record will be too recent */ - if (op != MDBX_FIRST && ++last >= oldest) { - oldest = mdbx_find_oldest(txn); - if (oldest <= last) - break; - } - } - - rc = mdbx_cursor_get(&recur, &key, NULL, op); - if (rc == MDBX_NOTFOUND && (flags & MDBX_LIFORECLAIM)) { - if (op == MDBX_SET_RANGE) - continue; - txnid_t snap = mdbx_find_oldest(txn); - if (oldest < snap) { - oldest = snap; - last = oldest - 1; - key.iov_base = &last; - key.iov_len = sizeof(last); - op = MDBX_SET_RANGE; - rc = mdbx_cursor_get(&recur, &key, NULL, op); - } - } - if (unlikely(rc)) { - if (rc == MDBX_NOTFOUND) - break; - goto fail; - } - - if (unlikely(key.iov_len != sizeof(txnid_t))) { - rc = MDBX_CORRUPTED; - goto fail; - } - last = unaligned_peek_u64(4, key.iov_base); - if (unlikely(last < 1 || last >= SAFE64_INVALID_THRESHOLD)) { - rc = MDBX_CORRUPTED; - goto fail; - } - if (oldest <= last) { - oldest = mdbx_find_oldest(txn); - if (oldest <= last) { - if (flags & MDBX_LIFORECLAIM) - continue; - break; - } - } - - if (flags & MDBX_LIFORECLAIM) { - /* skip IDs of records that already reclaimed */ - if (txn->tw.lifo_reclaimed) { - unsigned i; - for (i = (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed); i > 0; --i) - if (txn->tw.lifo_reclaimed[i] == last) - break; - if (i) - continue; - } - } - - /* Reading next GC record */ - np = recur.mc_pg[recur.mc_top]; - if (unlikely((rc = mdbx_node_read( - &recur, page_node(np, recur.mc_ki[recur.mc_top]), - &data)) != MDBX_SUCCESS)) - goto fail; - - if ((flags & MDBX_LIFORECLAIM) && !txn->tw.lifo_reclaimed) { - txn->tw.lifo_reclaimed = mdbx_txl_alloc(); - if (unlikely(!txn->tw.lifo_reclaimed)) { - rc = MDBX_ENOMEM; - goto fail; - } - } - - /* Append PNL from GC record to me_reclaimed_pglist */ - mdbx_cassert(mc, (mc->mc_flags & C_GCFREEZE) == 0); - pgno_t *gc_pnl = (pgno_t *)data.iov_base; - mdbx_tassert(txn, data.iov_len >= MDBX_PNL_SIZEOF(gc_pnl)); - if (unlikely(data.iov_len < MDBX_PNL_SIZEOF(gc_pnl) || - !mdbx_pnl_check(gc_pnl, txn->mt_next_pgno))) { - rc = MDBX_CORRUPTED; - goto fail; - } - const unsigned gc_len = MDBX_PNL_SIZE(gc_pnl); - rc = mdbx_pnl_need(&txn->tw.reclaimed_pglist, gc_len); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - re_list = txn->tw.reclaimed_pglist; - - /* Remember ID of GC record */ - if (flags & MDBX_LIFORECLAIM) { - if ((rc = mdbx_txl_append(&txn->tw.lifo_reclaimed, last)) != 0) - goto fail; - } - txn->tw.last_reclaimed = last; - - if (mdbx_log_enabled(MDBX_LOG_EXTRA)) { - mdbx_debug_extra("PNL read txn %" PRIaTXN " root %" PRIaPGNO - " num %u, PNL", - last, txn->mt_dbs[FREE_DBI].md_root, gc_len); - unsigned i; - for (i = gc_len; i; i--) - mdbx_debug_extra_print(" %" PRIaPGNO, gc_pnl[i]); - mdbx_debug_extra_print("%s", "\n"); - } - - /* Merge in descending sorted order */ - const unsigned prev_re_len = MDBX_PNL_SIZE(re_list); - mdbx_pnl_xmerge(re_list, gc_pnl); - /* re-check to avoid duplicates */ - if (unlikely(!mdbx_pnl_check(re_list, txn->mt_next_pgno))) { - rc = MDBX_CORRUPTED; - goto fail; - } - - re_len = MDBX_PNL_SIZE(re_list); - mdbx_tassert(txn, re_len == 0 || re_list[re_len] < txn->mt_next_pgno); - if (re_len && unlikely(MDBX_PNL_MOST(re_list) == txn->mt_next_pgno - 1)) { - /* Refund suitable pages into "unallocated" space */ - mdbx_refund(txn); - re_list = txn->tw.reclaimed_pglist; - re_len = MDBX_PNL_SIZE(re_list); - } - - if (unlikely((flags & MDBX_ALLOC_CACHE) == 0)) { - /* Done for a kick-reclaim mode, actually no page needed */ - return MDBX_SUCCESS; - } - - /* Don't try to coalesce too much. */ - if (unlikely(re_len > MDBX_DPL_TXNFULL / 4)) - break; - if (re_len /* current size */ >= env->me_maxgc_ov1page || - (re_len > prev_re_len && re_len - prev_re_len /* delta from prev */ >= - env->me_maxgc_ov1page / 2)) - flags &= ~MDBX_COALESCE; - } - - if ((flags & (MDBX_COALESCE | MDBX_ALLOC_CACHE)) == - (MDBX_COALESCE | MDBX_ALLOC_CACHE) && - re_len > wanna_range) { - range_begin = MDBX_PNL_ASCENDING ? 1 : re_len; - pgno = MDBX_PNL_LEAST(re_list); - if (likely(wanna_range == 0)) - goto done; -#if MDBX_PNL_ASCENDING - mdbx_tassert(txn, pgno == re_list[1] && range_begin == 1); - while (true) { - unsigned range_end = range_begin + wanna_range; - if (re_list[range_end] - pgno == wanna_range) - goto done; - if (range_end == re_len) - break; - pgno = re_list[++range_begin]; - } -#else - mdbx_tassert(txn, pgno == re_list[re_len] && range_begin == re_len); - while (true) { - if (re_list[range_begin - wanna_range] - pgno == wanna_range) - goto done; - if (range_begin == wanna_range) - break; - pgno = re_list[--range_begin]; - } -#endif /* MDBX_PNL sort-order */ - } - - /* Use new pages from the map when nothing suitable in the GC */ - range_begin = 0; - pgno = txn->mt_next_pgno; - rc = MDBX_MAP_FULL; - const pgno_t next = pgno_add(pgno, num); - if (likely(next <= txn->mt_end_pgno)) { - rc = MDBX_NOTFOUND; - if (likely(flags & MDBX_ALLOC_NEW)) - goto done; - } - - const MDBX_meta *head = mdbx_meta_head(env); - if ((flags & MDBX_ALLOC_GC) && - ((flags & MDBX_ALLOC_KICK) || rc == MDBX_MAP_FULL)) { - MDBX_meta *steady = mdbx_meta_steady(env); - - if (oldest == mdbx_meta_txnid_stable(env, steady) && - !META_IS_STEADY(head) && META_IS_STEADY(steady)) { - /* LY: Here an oom was happened: - * - all pages had allocated; - * - reclaiming was stopped at the last steady-sync; - * - the head-sync is weak. - * Now we need make a sync to resume reclaiming. If both - * MDBX_NOSYNC and MDBX_MAPASYNC flags are set, then assume that - * utterly no-sync write mode was requested. In such case - * don't make a steady-sync, but only a legacy-mode checkpoint, - * just for resume reclaiming only, not for data consistency. */ - - mdbx_debug("kick-gc: head %" PRIaTXN "-%s, tail %" PRIaTXN - "-%s, oldest %" PRIaTXN, - mdbx_meta_txnid_stable(env, head), mdbx_durable_str(head), - mdbx_meta_txnid_stable(env, steady), - mdbx_durable_str(steady), oldest); - - const unsigned syncflags = F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC) - ? env->me_flags - : env->me_flags & MDBX_WRITEMAP; - MDBX_meta meta = *head; - if (mdbx_sync_locked(env, syncflags, &meta) == MDBX_SUCCESS) { - txnid_t snap = mdbx_find_oldest(txn); - if (snap > oldest) - continue; - } - } - - if (rc == MDBX_MAP_FULL && oldest < txn->mt_txnid - MDBX_TXNID_STEP) { - if (mdbx_oomkick(env, oldest) > oldest) - continue; - } - } - - if (rc == MDBX_MAP_FULL && next < head->mm_geo.upper) { - mdbx_assert(env, next > txn->mt_end_pgno); - pgno_t aligned = pgno_align2os_pgno( - env, pgno_add(next, head->mm_geo.grow - next % head->mm_geo.grow)); - - if (aligned > head->mm_geo.upper) - aligned = head->mm_geo.upper; - mdbx_assert(env, aligned > txn->mt_end_pgno); - - mdbx_verbose("try growth datafile to %" PRIaPGNO " pages (+%" PRIaPGNO - ")", - aligned, aligned - txn->mt_end_pgno); - rc = mdbx_mapresize(env, aligned, head->mm_geo.upper); - if (rc == MDBX_SUCCESS) { - env->me_txn->mt_end_pgno = aligned; - if (!mp) - return rc; - goto done; - } - - mdbx_warning("unable growth datafile to %" PRIaPGNO "pages (+%" PRIaPGNO - "), errcode %d", - aligned, aligned - txn->mt_end_pgno, rc); - } - - fail: - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - if (mp) { - *mp = NULL; - txn->mt_flags |= MDBX_TXN_ERROR; - } - mdbx_assert(env, rc != MDBX_SUCCESS); - return rc; - } - -done: - mdbx_tassert(txn, mp && num); - mdbx_ensure(env, pgno >= NUM_METAS); - if (env->me_flags & MDBX_WRITEMAP) { - np = pgno2page(env, pgno); - /* LY: reset no-access flag from mdbx_loose_page() */ - VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num)); - ASAN_UNPOISON_MEMORY_REGION(np, pgno2bytes(env, num)); - } else { - if (unlikely(!(np = mdbx_page_malloc(txn, num)))) { - rc = MDBX_ENOMEM; - goto fail; - } - } - - if (range_begin) { - mdbx_cassert(mc, (mc->mc_flags & C_GCFREEZE) == 0); - mdbx_tassert(txn, pgno < txn->mt_next_pgno); - mdbx_tassert(txn, pgno == re_list[range_begin]); - /* Cutoff allocated pages from me_reclaimed_pglist */ -#if MDBX_PNL_ASCENDING - for (unsigned i = range_begin + num; i <= re_len;) - re_list[range_begin++] = re_list[i++]; - MDBX_PNL_SIZE(re_list) = re_len = range_begin - 1; -#else - MDBX_PNL_SIZE(re_list) = re_len -= num; - for (unsigned i = range_begin - num; i < re_len;) - re_list[++i] = re_list[++range_begin]; -#endif - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - } else { - txn->mt_next_pgno = pgno + num; - mdbx_assert(env, txn->mt_next_pgno <= txn->mt_end_pgno); - } - - if (unlikely(env->me_flags & MDBX_PAGEPERTURB)) - memset(np, -1, pgno2bytes(env, num)); - VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num)); - - np->mp_pgno = pgno; - np->mp_leaf2_ksize = 0; - np->mp_flags = 0; - np->mp_pages = num; - rc = mdbx_page_dirty(txn, np); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - *mp = np; - - mdbx_tassert( - txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, txn->mt_next_pgno)); - return MDBX_SUCCESS; -} - -/* Copy the used portions of a non-overflow page. - * [in] dst page to copy into - * [in] src page to copy from - * [in] psize size of a page */ -__hot static void mdbx_page_copy(MDBX_page *dst, MDBX_page *src, - unsigned psize) { - STATIC_ASSERT(UINT16_MAX > MAX_PAGESIZE - PAGEHDRSZ); - STATIC_ASSERT(MIN_PAGESIZE > PAGEHDRSZ + NODESIZE * 4); - if (!IS_LEAF2(src)) { - size_t upper = src->mp_upper, lower = src->mp_lower, unused = upper - lower; - - /* If page isn't full, just copy the used portion. Adjust - * alignment so memcpy may copy words instead of bytes. */ - if (unused > sizeof(void *) * 42) { - lower = roundup_powerof2(lower + PAGEHDRSZ, sizeof(void *)); - upper = (upper + PAGEHDRSZ) & ~(sizeof(void *) - 1); - memcpy(dst, src, lower); - memcpy((char *)dst + upper, (char *)src + upper, psize - upper); - return; - } - } - memcpy(dst, src, psize); -} - -/* Pull a page off the txn's spill list, if present. - * - * If a page being referenced was spilled to disk in this txn, bring - * it back and make it dirty/writable again. - * - * [in] txn the transaction handle. - * [in] mp the page being referenced. It must not be dirty. - * [out] ret the writable page, if any. - * ret is unchanged if mp wasn't spilled. */ -__hot static int __must_check_result mdbx_page_unspill(MDBX_txn *txn, - MDBX_page *mp, - MDBX_page **ret) { - MDBX_env *env = txn->mt_env; - pgno_t pgno = mp->mp_pgno, pn = pgno << 1; - - for (const MDBX_txn *tx2 = txn; tx2; tx2 = tx2->mt_parent) { - if (!tx2->tw.spill_pages) - continue; - unsigned i = mdbx_pnl_exist(tx2->tw.spill_pages, pn); - if (!i) - continue; - if (txn->tw.dirtyroom == 0) - return MDBX_TXN_FULL; - unsigned num = IS_OVERFLOW(mp) ? mp->mp_pages : 1; - MDBX_page *np = mp; - if ((env->me_flags & MDBX_WRITEMAP) == 0) { - np = mdbx_page_malloc(txn, num); - if (unlikely(!np)) - return MDBX_ENOMEM; - if (unlikely(num > 1)) - memcpy(np, mp, pgno2bytes(env, num)); - else - mdbx_page_copy(np, mp, env->me_psize); - } - mdbx_debug("unspill page %" PRIaPGNO, mp->mp_pgno); - if (tx2 == txn) { - /* If in current txn, this page is no longer spilled. - * If it happens to be the last page, truncate the spill list. - * Otherwise mark it as deleted by setting the LSB. */ - txn->tw.spill_pages[i] |= 1; - if (i == MDBX_PNL_SIZE(txn->tw.spill_pages)) - MDBX_PNL_SIZE(txn->tw.spill_pages) -= 1; - } /* otherwise, if belonging to a parent txn, the - * page remains spilled until child commits */ - - int rc = mdbx_page_dirty(txn, np); - if (likely(rc == MDBX_SUCCESS)) { - np->mp_flags |= P_DIRTY; - *ret = np; - } - return rc; - } - return MDBX_SUCCESS; -} - -/* Touch a page: make it dirty and re-insert into tree with updated pgno. - * Set MDBX_TXN_ERROR on failure. - * - * [in] mc cursor pointing to the page to be touched - * - * Returns 0 on success, non-zero on failure. */ -__hot static int mdbx_page_touch(MDBX_cursor *mc) { - MDBX_page *mp = mc->mc_pg[mc->mc_top], *np; - MDBX_txn *txn = mc->mc_txn; - MDBX_cursor *m2, *m3; - pgno_t pgno; - int rc; - - mdbx_cassert(mc, !IS_OVERFLOW(mp)); - if (!F_ISSET(mp->mp_flags, P_DIRTY)) { - if (txn->mt_flags & MDBX_TXN_SPILLS) { - np = NULL; - rc = mdbx_page_unspill(txn, mp, &np); - if (unlikely(rc)) - goto fail; - if (likely(np)) - goto done; - } - - if (unlikely((rc = mdbx_pnl_need(&txn->tw.retired_pages, 1)) || - (rc = mdbx_page_alloc(mc, 1, &np, MDBX_ALLOC_ALL)))) - goto fail; - pgno = np->mp_pgno; - mdbx_debug("touched db %d page %" PRIaPGNO " -> %" PRIaPGNO, DDBI(mc), - mp->mp_pgno, pgno); - mdbx_cassert(mc, mp->mp_pgno != pgno); - mdbx_pnl_xappend(txn->tw.retired_pages, mp->mp_pgno); - mdbx_tassert(txn, mdbx_dpl_find(txn->tw.dirtylist, mp->mp_pgno) == nullptr); - /* Update the parent page, if any, to point to the new page */ - if (mc->mc_top) { - MDBX_page *parent = mc->mc_pg[mc->mc_top - 1]; - MDBX_node *node = page_node(parent, mc->mc_ki[mc->mc_top - 1]); - node_set_pgno(node, pgno); - } else { - mc->mc_db->md_root = pgno; - } - } else if (txn->mt_parent && !IS_SUBP(mp)) { - mdbx_tassert(txn, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0); - pgno = mp->mp_pgno; - /* If txn has a parent, make sure the page is in our dirty list. */ - const MDBX_page *const dp = mdbx_dpl_find(txn->tw.dirtylist, pgno); - if (dp) { - if (unlikely(mp != dp)) { /* bad cursor? */ - mdbx_error("wrong page 0x%p #%" PRIaPGNO - " in the dirtylist, expecting %p", - __Wpedantic_format_voidptr(dp), pgno, - __Wpedantic_format_voidptr(mp)); - mc->mc_flags &= ~(C_INITIALIZED | C_EOF); - rc = MDBX_PROBLEM; - goto fail; - } - return MDBX_SUCCESS; - } - - mdbx_debug("clone db %d page %" PRIaPGNO, DDBI(mc), mp->mp_pgno); - mdbx_cassert(mc, txn->tw.dirtylist->length <= MDBX_DPL_TXNFULL); - /* No - copy it */ - np = mdbx_page_malloc(txn, 1); - if (unlikely(!np)) { - rc = MDBX_ENOMEM; - goto fail; - } - rc = mdbx_dpl_append(txn->tw.dirtylist, pgno, np); - if (unlikely(rc)) { - mdbx_dpage_free(txn->mt_env, np, 1); - goto fail; - } - } else { - return MDBX_SUCCESS; - } - - mdbx_page_copy(np, mp, txn->mt_env->me_psize); - np->mp_pgno = pgno; - np->mp_flags |= P_DIRTY; - -done: - /* Adjust cursors pointing to mp */ - mc->mc_pg[mc->mc_top] = np; - m2 = txn->mt_cursors[mc->mc_dbi]; - if (mc->mc_flags & C_SUB) { - for (; m2; m2 = m2->mc_next) { - m3 = &m2->mc_xcursor->mx_cursor; - if (m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) - m3->mc_pg[mc->mc_top] = np; - } - } else { - for (; m2; m2 = m2->mc_next) { - if (m2->mc_snum < mc->mc_snum) - continue; - if (m2 == mc) - continue; - if (m2->mc_pg[mc->mc_top] == mp) { - m2->mc_pg[mc->mc_top] = np; - if (XCURSOR_INITED(m2) && IS_LEAF(np)) - XCURSOR_REFRESH(m2, np, m2->mc_ki[mc->mc_top]); - } - } - } - return MDBX_SUCCESS; - -fail: - txn->mt_flags |= MDBX_TXN_ERROR; - return rc; -} - -__cold int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - unsigned flags = env->me_flags & ~MDBX_NOMETASYNC; - if (unlikely(flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) - return MDBX_EACCESS; - - if (unlikely(!env->me_map)) - return MDBX_EPERM; - - int rc = MDBX_RESULT_TRUE /* means "nothing to sync" */; - bool need_unlock = false; - if (nonblock && *env->me_unsynced_pages == 0) - goto fastpath; - - const bool outside_txn = (env->me_txn0->mt_owner != mdbx_thread_self()); - if (outside_txn) { - int err = mdbx_txn_lock(env, nonblock); - if (unlikely(err != MDBX_SUCCESS)) - return err; - need_unlock = true; - } - - const MDBX_meta *head = mdbx_meta_head(env); - pgno_t unsynced_pages = *env->me_unsynced_pages; - if (!META_IS_STEADY(head) || unsynced_pages) { - const pgno_t autosync_threshold = *env->me_autosync_threshold; - const uint64_t autosync_period = *env->me_autosync_period; - if (force || (autosync_threshold && unsynced_pages >= autosync_threshold) || - (autosync_period && - mdbx_osal_monotime() - *env->me_sync_timestamp >= autosync_period)) - flags &= MDBX_WRITEMAP /* clear flags for full steady sync */; - - if (outside_txn) { - if (unsynced_pages > /* FIXME: define threshold */ 16 && - (flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) == 0) { - mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); - const size_t usedbytes = pgno_align2os_bytes(env, head->mm_geo.next); - - mdbx_txn_unlock(env); - - /* LY: pre-sync without holding lock to reduce latency for writer(s) */ - int err = (flags & MDBX_WRITEMAP) - ? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes, false) - : mdbx_filesync(env->me_fd, MDBX_SYNC_DATA); - if (unlikely(err != MDBX_SUCCESS)) - return err; - - err = mdbx_txn_lock(env, nonblock); - if (unlikely(err != MDBX_SUCCESS)) - return err; - - /* LY: head and unsynced_pages may be changed. */ - head = mdbx_meta_head(env); - unsynced_pages = *env->me_unsynced_pages; - } - env->me_txn0->mt_txnid = meta_txnid(env, head, false); - mdbx_find_oldest(env->me_txn0); - rc = MDBX_RESULT_FALSE /* means "some data was synced" */; - } - - if (!META_IS_STEADY(head) || - ((flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) == 0 && unsynced_pages)) { - mdbx_debug("meta-head %" PRIaPGNO ", %s, sync_pending %" PRIaPGNO, - data_page(head)->mp_pgno, mdbx_durable_str(head), - unsynced_pages); - MDBX_meta meta = *head; - int err = mdbx_sync_locked(env, flags | MDBX_SHRINK_ALLOWED, &meta); - if (unlikely(err != MDBX_SUCCESS)) { - if (need_unlock) - mdbx_txn_unlock(env); - return err; - } - rc = MDBX_RESULT_FALSE /* means "some data was synced" */; - } - } - -fastpath: - /* LY: sync meta-pages if MDBX_NOMETASYNC enabled - * and someone was not synced above. */ - if (rc == MDBX_RESULT_TRUE && (env->me_flags & MDBX_NOMETASYNC) != 0) { - const txnid_t head_txnid = mdbx_recent_committed_txnid(env); - if (*env->me_meta_sync_txnid != (uint32_t)head_txnid) { - rc = (flags & MDBX_WRITEMAP) - ? mdbx_msync(&env->me_dxb_mmap, 0, pgno2bytes(env, NUM_METAS), - false) - : mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ); - if (likely(rc == MDBX_SUCCESS)) - *env->me_meta_sync_txnid = (uint32_t)head_txnid; - } - } - if (need_unlock) - mdbx_txn_unlock(env); - return rc; -} - -__cold int mdbx_env_sync(MDBX_env *env) { - return mdbx_env_sync_ex(env, true, false); -} - -__cold int mdbx_env_sync_poll(MDBX_env *env) { - return mdbx_env_sync_ex(env, false, true); -} - -/* Back up parent txn's cursors, then grab the originals for tracking */ -static int mdbx_cursor_shadow(MDBX_txn *src, MDBX_txn *dst) { - MDBX_cursor *mc, *bk; - MDBX_xcursor *mx; - - for (int i = src->mt_numdbs; --i >= 0;) { - dst->mt_cursors[i] = NULL; - if ((mc = src->mt_cursors[i]) != NULL) { - size_t size = sizeof(MDBX_cursor); - if (mc->mc_xcursor) - size += sizeof(MDBX_xcursor); - for (; mc; mc = bk->mc_next) { - bk = mdbx_malloc(size); - if (unlikely(!bk)) - return MDBX_ENOMEM; - *bk = *mc; - mc->mc_backup = bk; - mc->mc_db = &dst->mt_dbs[i]; - /* Kill pointers into src to reduce abuse: The - * user may not use mc until dst ends. But we need a valid - * txn pointer here for cursor fixups to keep working. */ - mc->mc_txn = dst; - mc->mc_dbflag = &dst->mt_dbflags[i]; - if ((mx = mc->mc_xcursor) != NULL) { - *(MDBX_xcursor *)(bk + 1) = *mx; - mx->mx_cursor.mc_txn = dst; - } - mc->mc_next = dst->mt_cursors[i]; - dst->mt_cursors[i] = mc; - } - } - } - return MDBX_SUCCESS; -} - -/* Close this write txn's cursors, give parent txn's cursors back to parent. - * - * [in] txn the transaction handle. - * [in] merge true to keep changes to parent cursors, false to revert. - * - * Returns 0 on success, non-zero on failure. */ -static void mdbx_cursors_eot(MDBX_txn *txn, unsigned merge) { - MDBX_cursor **cursors = txn->mt_cursors, *mc, *next, *bk; - MDBX_xcursor *mx; - int i; - - for (i = txn->mt_numdbs; --i >= 0;) { - for (mc = cursors[i]; mc; mc = next) { - unsigned stage = mc->mc_signature; - mdbx_ensure(txn->mt_env, - stage == MDBX_MC_SIGNATURE || stage == MDBX_MC_WAIT4EOT); - next = mc->mc_next; - mdbx_tassert(txn, !next || next->mc_signature == MDBX_MC_SIGNATURE || - next->mc_signature == MDBX_MC_WAIT4EOT); - if ((bk = mc->mc_backup) != NULL) { - if (merge) { - /* Commit changes to parent txn */ - mc->mc_next = bk->mc_next; - mc->mc_backup = bk->mc_backup; - mc->mc_txn = bk->mc_txn; - mc->mc_db = bk->mc_db; - mc->mc_dbflag = bk->mc_dbflag; - if ((mx = mc->mc_xcursor) != NULL) - mx->mx_cursor.mc_txn = bk->mc_txn; - } else { - /* Abort nested txn */ - *mc = *bk; - if ((mx = mc->mc_xcursor) != NULL) - *mx = *(MDBX_xcursor *)(bk + 1); - } - bk->mc_signature = 0; - mdbx_free(bk); - } - if (stage == MDBX_MC_WAIT4EOT) { - mc->mc_signature = 0; - mdbx_free(mc); - } else { - mc->mc_signature = MDBX_MC_READY4CLOSE; - mc->mc_flags = 0 /* reset C_UNTRACK */; - } - } - cursors[i] = NULL; - } -} - -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) -/* Find largest mvcc-snapshot still referenced by this process. */ -static pgno_t mdbx_find_largest_this(MDBX_env *env, pgno_t largest) { - MDBX_lockinfo *const lck = env->me_lck; - if (likely(lck != NULL /* exclusive mode */)) { - const unsigned snap_nreaders = lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; ++i) { - retry: - if (lck->mti_readers[i].mr_pid == env->me_pid) { - /* mdbx_jitter4testing(true); */ - const pgno_t snap_pages = lck->mti_readers[i].mr_snapshot_pages_used; - const txnid_t snap_txnid = safe64_read(&lck->mti_readers[i].mr_txnid); - mdbx_memory_barrier(); - if (unlikely(snap_pages != lck->mti_readers[i].mr_snapshot_pages_used || - snap_txnid != safe64_read(&lck->mti_readers[i].mr_txnid))) - goto retry; - if (largest < snap_pages && - lck->mti_oldest_reader <= /* ignore pending updates */ snap_txnid && - snap_txnid < SAFE64_INVALID_THRESHOLD) - largest = snap_pages; - } - } - } - return largest; -} - -static void mdbx_txn_valgrind(MDBX_env *env, MDBX_txn *txn) { -#if !defined(__SANITIZE_ADDRESS__) - if (!RUNNING_ON_VALGRIND) - return; -#endif - - if (txn) { /* transaction start */ - if (env->me_poison_edge < txn->mt_next_pgno) - env->me_poison_edge = txn->mt_next_pgno; - VALGRIND_MAKE_MEM_DEFINED(env->me_map, pgno2bytes(env, txn->mt_next_pgno)); - ASAN_UNPOISON_MEMORY_REGION(env->me_map, - pgno2bytes(env, txn->mt_next_pgno)); - /* don't touch more, it should be already poisoned */ - } else { /* transaction end */ - bool should_unlock = false; - pgno_t last = MAX_PAGENO; - if (env->me_txn0 && env->me_txn0->mt_owner == mdbx_thread_self()) { - /* inside write-txn */ - MDBX_meta *head = mdbx_meta_head(env); - last = head->mm_geo.next; - } else if (mdbx_txn_lock(env, true) == MDBX_SUCCESS) { - /* no write-txn */ - last = NUM_METAS; - should_unlock = true; - } else { - /* write txn is running, therefore shouldn't poison any memory range */ - return; - } - - last = mdbx_find_largest_this(env, last); - const pgno_t edge = env->me_poison_edge; - if (edge > last) { - mdbx_assert(env, last >= NUM_METAS); - env->me_poison_edge = last; - VALGRIND_MAKE_MEM_NOACCESS(env->me_map + pgno2bytes(env, last), - pgno2bytes(env, edge - last)); - ASAN_POISON_MEMORY_REGION(env->me_map + pgno2bytes(env, last), - pgno2bytes(env, edge - last)); - } - if (should_unlock) - mdbx_txn_unlock(env); - } -} -#endif /* MDBX_USE_VALGRIND */ - -/* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */ -static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { - MDBX_env *env = txn->mt_env; - int rc; - -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - STATIC_ASSERT(sizeof(MDBX_reader) == 32); -#ifdef MDBX_OSAL_LOCK - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_wmutex) % MDBX_CACHELINE_SIZE == 0); - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_rmutex) % MDBX_CACHELINE_SIZE == 0); -#else - STATIC_ASSERT( - offsetof(MDBX_lockinfo, mti_oldest_reader) % MDBX_CACHELINE_SIZE == 0); - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE == - 0); -#endif - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == - 0); - - if (flags & MDBX_RDONLY) { - txn->mt_flags = MDBX_RDONLY | (env->me_flags & MDBX_NOTLS); - MDBX_reader *r = txn->to.reader; - STATIC_ASSERT(sizeof(size_t) == sizeof(r->mr_tid)); - if (likely(env->me_flags & MDBX_ENV_TXKEY)) { - mdbx_assert(env, !(env->me_flags & MDBX_NOTLS)); - r = thread_rthc_get(env->me_txkey); - if (likely(r)) { - mdbx_assert(env, r->mr_pid == env->me_pid); - mdbx_assert(env, r->mr_tid == mdbx_thread_self()); - } - } else { - mdbx_assert(env, !env->me_lck || (env->me_flags & MDBX_NOTLS)); - } - - if (likely(r)) { - if (unlikely(r->mr_pid != env->me_pid || - r->mr_txnid.inconsistent < SAFE64_INVALID_THRESHOLD)) - return MDBX_BAD_RSLOT; - } else if (env->me_lck) { - unsigned slot, nreaders; - const size_t tid = mdbx_thread_self(); - mdbx_assert(env, env->me_lck->mti_magic_and_version == MDBX_LOCK_MAGIC); - mdbx_assert(env, env->me_lck->mti_os_and_format == MDBX_LOCK_FORMAT); - - rc = mdbx_rdt_lock(env); - if (unlikely(MDBX_IS_ERROR(rc))) - return rc; - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { - mdbx_rdt_unlock(env); - return MDBX_PANIC; - } -#if defined(_WIN32) || defined(_WIN64) - if (unlikely(!env->me_map)) { - mdbx_rdt_unlock(env); - return MDBX_EPERM; - } -#endif /* Windows */ - rc = MDBX_SUCCESS; - - if (unlikely(env->me_live_reader != env->me_pid)) { - rc = mdbx_rpid_set(env); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_rdt_unlock(env); - return rc; - } - env->me_live_reader = env->me_pid; - } - - while (1) { - nreaders = env->me_lck->mti_numreaders; - for (slot = 0; slot < nreaders; slot++) - if (env->me_lck->mti_readers[slot].mr_pid == 0) - break; - - if (likely(slot < env->me_maxreaders)) - break; - - rc = mdbx_reader_check0(env, true, NULL); - if (rc != MDBX_RESULT_TRUE) { - mdbx_rdt_unlock(env); - return (rc == MDBX_SUCCESS) ? MDBX_READERS_FULL : rc; - } - } - - r = &env->me_lck->mti_readers[slot]; - /* Claim the reader slot, carefully since other code - * uses the reader table un-mutexed: First reset the - * slot, next publish it in lck->mti_numreaders. After - * that, it is safe for mdbx_env_close() to touch it. - * When it will be closed, we can finally claim it. */ - r->mr_pid = 0; - safe64_reset(&r->mr_txnid, true); - if (slot == nreaders) - env->me_lck->mti_numreaders = ++nreaders; - r->mr_tid = tid; - r->mr_pid = env->me_pid; - mdbx_rdt_unlock(env); - - if (likely(env->me_flags & MDBX_ENV_TXKEY)) { - mdbx_assert(env, env->me_live_reader == env->me_pid); - thread_rthc_set(env->me_txkey, r); - } - } - - while (1) { - MDBX_meta *const meta = mdbx_meta_head(env); - mdbx_jitter4testing(false); - const txnid_t snap = mdbx_meta_txnid_fluid(env, meta); - mdbx_jitter4testing(false); - if (likely(r)) { - safe64_reset(&r->mr_txnid, false); - r->mr_snapshot_pages_used = meta->mm_geo.next; - r->mr_snapshot_pages_retired = meta->mm_pages_retired; - safe64_write(&r->mr_txnid, snap); - mdbx_jitter4testing(false); - mdbx_assert(env, r->mr_pid == mdbx_getpid()); - mdbx_assert(env, r->mr_tid == mdbx_thread_self()); - mdbx_assert(env, r->mr_txnid.inconsistent == snap); - mdbx_compiler_barrier(); - env->me_lck->mti_readers_refresh_flag = true; - mdbx_flush_noncoherent_cpu_writeback(); - } - mdbx_jitter4testing(true); - - /* Snap the state from current meta-head */ - txn->mt_txnid = snap; - txn->mt_geo = meta->mm_geo; - memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - txn->mt_canary = meta->mm_canary; - - /* LY: Retry on a race, ITS#7970. */ - mdbx_compiler_barrier(); - if (likely(meta == mdbx_meta_head(env) && - snap == mdbx_meta_txnid_fluid(env, meta) && - snap >= *env->me_oldest)) { - mdbx_jitter4testing(false); - break; - } - } - - if (unlikely(txn->mt_txnid == 0 || - txn->mt_txnid >= SAFE64_INVALID_THRESHOLD)) { - mdbx_error("%s", "environment corrupted by died writer, must shutdown!"); - rc = MDBX_WANNA_RECOVERY; - goto bailout; - } - mdbx_assert(env, txn->mt_txnid >= *env->me_oldest); - txn->to.reader = r; - txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */ - mdbx_ensure(env, txn->mt_txnid >= - /* paranoia is appropriate here */ *env->me_oldest); - } else { - /* Not yet touching txn == env->me_txn0, it may be active */ - mdbx_jitter4testing(false); - rc = mdbx_txn_lock(env, F_ISSET(flags, MDBX_TRYTXN)); - if (unlikely(rc)) - return rc; - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { - mdbx_txn_unlock(env); - return MDBX_PANIC; - } -#if defined(_WIN32) || defined(_WIN64) - if (unlikely(!env->me_map)) { - mdbx_txn_unlock(env); - return MDBX_EPERM; - } -#endif /* Windows */ - - mdbx_jitter4testing(false); - MDBX_meta *meta = mdbx_meta_head(env); - mdbx_jitter4testing(false); - txn->mt_canary = meta->mm_canary; - const txnid_t snap = mdbx_meta_txnid_stable(env, meta); - txn->mt_txnid = safe64_txnid_next(snap); - if (unlikely(txn->mt_txnid >= SAFE64_INVALID_THRESHOLD)) { - mdbx_debug("%s", "txnid overflow!"); - rc = MDBX_TXN_FULL; - goto bailout; - } - - txn->mt_flags = flags; - txn->mt_child = NULL; - txn->tw.loose_pages = NULL; - txn->tw.loose_count = 0; - txn->tw.dirtyroom = MDBX_DPL_TXNFULL; - txn->tw.dirtylist = env->me_dirtylist; - mdbx_dpl_clear(txn->tw.dirtylist); - MDBX_PNL_SIZE(txn->tw.retired_pages) = 0; - txn->tw.spill_pages = NULL; - txn->tw.last_reclaimed = 0; - if (txn->tw.lifo_reclaimed) - MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) = 0; - env->me_txn = txn; - memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned)); - /* Copy the DB info and flags */ - memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - /* Moved to here to avoid a data race in read TXNs */ - txn->mt_geo = meta->mm_geo; - txn->tw.loose_refund_wl = txn->mt_next_pgno; - } - - /* Setup db info */ - txn->mt_numdbs = env->me_numdbs; - mdbx_compiler_barrier(); - for (unsigned i = CORE_DBS; i < txn->mt_numdbs; i++) { - unsigned x = env->me_dbflags[i]; - txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS; - txn->mt_dbflags[i] = - (x & MDBX_VALID) ? DB_VALID | DB_USRVALID | DB_STALE : 0; - } - txn->mt_dbflags[MAIN_DBI] = DB_VALID | DB_USRVALID; - txn->mt_dbflags[FREE_DBI] = DB_VALID; - - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { - mdbx_warning("%s", "environment had fatal error, must shutdown!"); - rc = MDBX_PANIC; - } else { - const size_t size = pgno2bytes(env, txn->mt_end_pgno); - if (unlikely(size > env->me_dxb_mmap.limit)) { - if (txn->mt_geo.upper > MAX_PAGENO || - bytes2pgno(env, pgno2bytes(env, txn->mt_geo.upper)) != - txn->mt_geo.upper) { - rc = MDBX_MAP_RESIZED; - goto bailout; - } - rc = mdbx_mapresize(env, txn->mt_end_pgno, txn->mt_geo.upper); - if (rc != MDBX_SUCCESS) { - if (rc == MDBX_RESULT_TRUE) - rc = MDBX_MAP_RESIZED; - goto bailout; - } - } - if (txn->mt_flags & MDBX_RDONLY) { -#if defined(_WIN32) || defined(_WIN64) - if (size > env->me_dbgeo.lower && env->me_dbgeo.shrink) { - txn->mt_flags |= MDBX_SHRINK_ALLOWED; - mdbx_srwlock_AcquireShared(&env->me_remap_guard); - } -#endif - } else { - env->me_dxb_mmap.current = size; - } -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - mdbx_txn_valgrind(env, txn); -#endif - txn->mt_owner = mdbx_thread_self(); - return MDBX_SUCCESS; - } -bailout: - mdbx_tassert(txn, rc != MDBX_SUCCESS); - mdbx_txn_end(txn, MDBX_END_SLOT | MDBX_END_FAIL_BEGIN); - return rc; -} - -static __always_inline int check_txn(const MDBX_txn *txn, int bad_bits) { - if (unlikely(!txn)) - return MDBX_EINVAL; - - if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(txn->mt_flags & bad_bits)) - return MDBX_BAD_TXN; - -#if MDBX_TXN_CHECKOWNER - if ((txn->mt_flags & MDBX_NOTLS) == 0 && - unlikely(txn->mt_owner != mdbx_thread_self())) - return txn->mt_owner ? MDBX_THREAD_MISMATCH : MDBX_BAD_TXN; -#endif /* MDBX_TXN_CHECKOWNER */ - - return MDBX_SUCCESS; -} - -static __always_inline int check_txn_rw(const MDBX_txn *txn, int bad_bits) { - if (unlikely(!txn)) - return MDBX_EINVAL; - - if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(txn->mt_flags & bad_bits)) - return MDBX_BAD_TXN; - - if (unlikely(F_ISSET(txn->mt_flags, MDBX_RDONLY))) - return MDBX_EACCESS; - -#if MDBX_TXN_CHECKOWNER - if (unlikely(txn->mt_owner != mdbx_thread_self())) - return txn->mt_owner ? MDBX_THREAD_MISMATCH : MDBX_BAD_TXN; -#endif /* MDBX_TXN_CHECKOWNER */ - - return MDBX_SUCCESS; -} - -int mdbx_txn_renew(MDBX_txn *txn) { - int rc; - - if (unlikely(!txn)) - return MDBX_EINVAL; - - if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely((txn->mt_flags & MDBX_RDONLY) == 0)) - return MDBX_EINVAL; - - if (unlikely(txn->mt_owner != 0)) - return MDBX_THREAD_MISMATCH; - - rc = mdbx_txn_renew0(txn, MDBX_RDONLY); - if (rc == MDBX_SUCCESS) { - txn->mt_owner = mdbx_thread_self(); - mdbx_debug("renew txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO - "/%" PRIaPGNO, - txn->mt_txnid, (txn->mt_flags & MDBX_RDONLY) ? 'r' : 'w', - (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root, - txn->mt_dbs[FREE_DBI].md_root); - } - return rc; -} - -int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags, - MDBX_txn **ret) { - MDBX_txn *txn; - int rc; - unsigned size, tsize; - - if (unlikely(!ret)) - return MDBX_EINVAL; - *ret = NULL; - - if (unlikely(!env)) - return MDBX_EINVAL; - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) - env->me_flags |= MDBX_FATAL_ERROR; -#endif /* MDBX_TXN_CHECKPID */ - - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) - return MDBX_PANIC; - -#if !defined(_WIN32) && !defined(_WIN64) - /* Don't check env->me_map until lock to - * avoid race with re-mapping for shrinking */ - if (unlikely(!env->me_map)) - return MDBX_EPERM; -#endif /* Windows */ - - if (unlikely(flags & ~MDBX_TXN_BEGIN_FLAGS)) - return MDBX_EINVAL; - - if (unlikely(env->me_flags & MDBX_RDONLY & - ~flags)) /* write txn in RDONLY env */ - return MDBX_EACCESS; - - flags |= env->me_flags & MDBX_WRITEMAP; - - if (parent) { - /* Nested transactions: Max 1 child, write txns only, no writemap */ - rc = check_txn_rw(parent, MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - -#if defined(_WIN32) || defined(_WIN64) - if (unlikely(!env->me_map)) - return MDBX_EPERM; -#endif /* Windows */ - - flags |= parent->mt_flags & - (MDBX_TXN_BEGIN_FLAGS | MDBX_SHRINK_ALLOWED | MDBX_TXN_SPILLS); - /* Child txns save MDBX_pgstate and use own copy of cursors */ - size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1); - size += tsize = sizeof(MDBX_txn); - } else if (flags & MDBX_RDONLY) { - if (env->me_txn0 && unlikely(env->me_txn0->mt_owner == mdbx_thread_self())) - return MDBX_BUSY; - size = env->me_maxdbs * (sizeof(MDBX_db) + 1); - size += tsize = sizeof(MDBX_txn); - } else { - /* Reuse preallocated write txn. However, do not touch it until - * mdbx_txn_renew0() succeeds, since it currently may be active. */ - txn = env->me_txn0; - if (unlikely(txn->mt_owner == mdbx_thread_self())) - return MDBX_BUSY; - goto renew; - } - if (unlikely((txn = mdbx_malloc(size)) == NULL)) { - mdbx_debug("calloc: %s", "failed"); - return MDBX_ENOMEM; - } - memset(txn, 0, tsize); - txn->mt_dbxs = env->me_dbxs; /* static */ - txn->mt_dbs = (MDBX_db *)((char *)txn + tsize); - txn->mt_dbflags = (uint8_t *)txn + size - env->me_maxdbs; - txn->mt_flags = flags; - txn->mt_env = env; - - if (parent) { - mdbx_tassert(txn, mdbx_dirtylist_check(parent)); - txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs); - txn->mt_dbiseqs = parent->mt_dbiseqs; - txn->tw.dirtylist = mdbx_malloc(sizeof(MDBX_DP) * (MDBX_DPL_TXNFULL + 1)); - txn->tw.reclaimed_pglist = - mdbx_pnl_alloc(MDBX_PNL_ALLOCLEN(parent->tw.reclaimed_pglist)); - if (!txn->tw.dirtylist || !txn->tw.reclaimed_pglist) { - mdbx_pnl_free(txn->tw.reclaimed_pglist); - mdbx_free(txn->tw.dirtylist); - mdbx_free(txn); - return MDBX_ENOMEM; - } - mdbx_dpl_clear(txn->tw.dirtylist); - memcpy(txn->tw.reclaimed_pglist, parent->tw.reclaimed_pglist, - MDBX_PNL_SIZEOF(parent->tw.reclaimed_pglist)); - mdbx_assert(env, mdbx_pnl_check4assert( - txn->tw.reclaimed_pglist, - (txn->mt_next_pgno /* LY: intentional assigment here, - only for assertion */ - = parent->mt_next_pgno))); - - txn->tw.last_reclaimed = parent->tw.last_reclaimed; - if (parent->tw.lifo_reclaimed) { - txn->tw.lifo_reclaimed = parent->tw.lifo_reclaimed; - parent->tw.lifo_reclaimed = - (void *)(intptr_t)MDBX_PNL_SIZE(parent->tw.lifo_reclaimed); - } - - txn->tw.retired_pages = parent->tw.retired_pages; - parent->tw.retired_pages = - (void *)(intptr_t)MDBX_PNL_SIZE(parent->tw.retired_pages); - - txn->mt_txnid = parent->mt_txnid; - txn->tw.dirtyroom = parent->tw.dirtyroom; - txn->mt_geo = parent->mt_geo; - txn->tw.loose_refund_wl = parent->tw.loose_refund_wl; - txn->mt_canary = parent->mt_canary; - parent->mt_flags |= MDBX_TXN_HAS_CHILD; - parent->mt_child = txn; - txn->mt_parent = parent; - txn->mt_numdbs = parent->mt_numdbs; - txn->mt_owner = parent->mt_owner; - memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db)); - /* Copy parent's mt_dbflags, but clear DB_NEW */ - for (unsigned i = 0; i < txn->mt_numdbs; i++) - txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~(DB_FRESH | DB_CREAT); - mdbx_tassert(parent, - parent->mt_parent || - parent->tw.dirtyroom + parent->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - env->me_txn = txn; - rc = mdbx_cursor_shadow(parent, txn); - if (unlikely(rc != MDBX_SUCCESS)) - mdbx_txn_end(txn, MDBX_END_FAIL_BEGINCHILD); - } else { /* MDBX_RDONLY */ - txn->mt_dbiseqs = env->me_dbiseqs; - renew: - rc = mdbx_txn_renew0(txn, flags); - } - - if (unlikely(rc != MDBX_SUCCESS)) { - if (txn != env->me_txn0) - mdbx_free(txn); - } else { - mdbx_assert(env, (txn->mt_flags & - ~(MDBX_RDONLY | MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED | - MDBX_NOMETASYNC | MDBX_NOSYNC | MDBX_MAPASYNC)) == 0); - txn->mt_signature = MDBX_MT_SIGNATURE; - *ret = txn; - mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO - "/%" PRIaPGNO, - txn->mt_txnid, (flags & MDBX_RDONLY) ? 'r' : 'w', (void *)txn, - (void *)env, txn->mt_dbs[MAIN_DBI].md_root, - txn->mt_dbs[FREE_DBI].md_root); - } - - return rc; -} - -int mdbx_txn_info(MDBX_txn *txn, MDBX_txn_info *info, int scan_rlt) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_HAS_CHILD); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!info)) - return MDBX_EINVAL; - - MDBX_env *const env = txn->mt_env; -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - info->txn_id = txn->mt_txnid; - info->txn_space_used = pgno2bytes(env, txn->mt_geo.next); - - if (txn->mt_flags & MDBX_RDONLY) { - const MDBX_meta *head_meta; - txnid_t head_txnid; - uint64_t head_retired; - do { - /* fetch info from volatile head */ - head_meta = mdbx_meta_head(env); - head_txnid = mdbx_meta_txnid_fluid(env, head_meta); - head_retired = head_meta->mm_pages_retired; - info->txn_space_limit_soft = pgno2bytes(env, head_meta->mm_geo.now); - info->txn_space_limit_hard = pgno2bytes(env, head_meta->mm_geo.upper); - info->txn_space_leftover = - pgno2bytes(env, head_meta->mm_geo.now - head_meta->mm_geo.next); - mdbx_compiler_barrier(); - } while (unlikely(head_meta != mdbx_meta_head(env) || - head_txnid != mdbx_meta_txnid_fluid(env, head_meta))); - - info->txn_reader_lag = head_txnid - info->txn_id; - info->txn_space_dirty = info->txn_space_retired = 0; - if (txn->to.reader && - head_retired > txn->to.reader->mr_snapshot_pages_retired) { - info->txn_space_dirty = info->txn_space_retired = - pgno2bytes(env, (pgno_t)(head_retired - - txn->to.reader->mr_snapshot_pages_retired)); - - size_t retired_next_reader = 0; - MDBX_lockinfo *const lck = env->me_lck; - if (scan_rlt && info->txn_reader_lag > 1 && lck) { - /* find next more recent reader */ - txnid_t next_reader = head_txnid; - const unsigned snap_nreaders = lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; ++i) { - retry: - if (lck->mti_readers[i].mr_pid) { - mdbx_jitter4testing(true); - const txnid_t snap_txnid = - safe64_read(&lck->mti_readers[i].mr_txnid); - const uint64_t snap_retired = - lck->mti_readers[i].mr_snapshot_pages_retired; - mdbx_compiler_barrier(); - if (unlikely(snap_retired != - lck->mti_readers[i].mr_snapshot_pages_retired) || - snap_txnid != safe64_read(&lck->mti_readers[i].mr_txnid)) - goto retry; - if (snap_txnid <= txn->mt_txnid) { - retired_next_reader = 0; - break; - } - if (snap_txnid < next_reader) { - next_reader = snap_txnid; - retired_next_reader = pgno2bytes( - env, (pgno_t)(snap_retired - - txn->to.reader->mr_snapshot_pages_retired)); - } - } - } - } - info->txn_space_dirty = retired_next_reader; - } - } else { - info->txn_space_limit_soft = pgno2bytes(env, txn->mt_geo.now); - info->txn_space_limit_hard = pgno2bytes(env, txn->mt_geo.upper); - info->txn_space_retired = pgno2bytes( - env, txn->mt_child ? (unsigned)(uintptr_t)txn->tw.retired_pages - : MDBX_PNL_SIZE(txn->tw.retired_pages)); - info->txn_space_leftover = pgno2bytes(env, txn->tw.dirtyroom); - info->txn_space_dirty = - pgno2bytes(env, MDBX_DPL_TXNFULL - txn->tw.dirtyroom); - info->txn_reader_lag = INT64_MAX; - MDBX_lockinfo *const lck = env->me_lck; - if (scan_rlt && lck) { - txnid_t oldest_snapshot = txn->mt_txnid; - const unsigned snap_nreaders = lck->mti_numreaders; - if (snap_nreaders) { - oldest_snapshot = mdbx_find_oldest(txn); - if (oldest_snapshot == txn->mt_txnid - 1) { - /* check if there is at least one reader */ - bool exists = false; - for (unsigned i = 0; i < snap_nreaders; ++i) { - if (lck->mti_readers[i].mr_pid && - txn->mt_txnid > safe64_read(&lck->mti_readers[i].mr_txnid)) { - exists = true; - break; - } - } - oldest_snapshot += !exists; - } - } - info->txn_reader_lag = txn->mt_txnid - oldest_snapshot; - } - } - - return MDBX_SUCCESS; -} - -MDBX_env *mdbx_txn_env(MDBX_txn *txn) { - if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE || - txn->mt_env->me_signature != MDBX_ME_SIGNATURE)) - return NULL; - return txn->mt_env; -} - -uint64_t mdbx_txn_id(MDBX_txn *txn) { - if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) - return 0; - return txn->mt_txnid; -} - -int mdbx_txn_flags(MDBX_txn *txn) { - if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) - return -1; - return txn->mt_flags; -} - -/* Export or close DBI handles opened in this txn. */ -static void mdbx_dbis_update(MDBX_txn *txn, int keep) { - MDBX_dbi n = txn->mt_numdbs; - if (n) { - bool locked = false; - MDBX_env *env = txn->mt_env; - uint8_t *tdbflags = txn->mt_dbflags; - - for (unsigned i = n; --i >= CORE_DBS;) { - if (likely((tdbflags[i] & DB_CREAT) == 0)) - continue; - if (!locked) { - mdbx_ensure(env, - mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS); - locked = true; - } - if (keep) { - env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDBX_VALID; - mdbx_compiler_barrier(); - if (env->me_numdbs <= i) - env->me_numdbs = i + 1; - } else { - char *ptr = env->me_dbxs[i].md_name.iov_base; - if (ptr) { - env->me_dbxs[i].md_name.iov_len = 0; - mdbx_compiler_barrier(); - mdbx_assert(env, env->me_dbflags[i] == 0); - env->me_dbiseqs[i]++; - env->me_dbxs[i].md_name.iov_base = NULL; - mdbx_free(ptr); - } - } - } - - if (unlikely(locked)) - mdbx_ensure(env, - mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); - } -} - -/* End a transaction, except successful commit of a nested transaction. - * May be called twice for readonly txns: First reset it, then abort. - * [in] txn the transaction handle to end - * [in] mode why and how to end the transaction */ -static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) { - MDBX_env *env = txn->mt_env; - static const char *const names[] = MDBX_END_NAMES; - -#if MDBX_TXN_CHECKPID - if (unlikely(txn->mt_env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - mdbx_debug("%s txn %" PRIaTXN "%c %p on mdbenv %p, root page %" PRIaPGNO - "/%" PRIaPGNO, - names[mode & MDBX_END_OPMASK], txn->mt_txnid, - (txn->mt_flags & MDBX_RDONLY) ? 'r' : 'w', (void *)txn, - (void *)env, txn->mt_dbs[MAIN_DBI].md_root, - txn->mt_dbs[FREE_DBI].md_root); - - mdbx_ensure(env, txn->mt_txnid >= - /* paranoia is appropriate here */ *env->me_oldest); - - int rc = MDBX_SUCCESS; - if (F_ISSET(txn->mt_flags, MDBX_RDONLY)) { - if (txn->to.reader) { - MDBX_reader *slot = txn->to.reader; - mdbx_assert(env, slot->mr_pid == env->me_pid); - if (likely(!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED))) { - mdbx_assert(env, txn->mt_txnid == slot->mr_txnid.inconsistent && - slot->mr_txnid.inconsistent >= - env->me_lck->mti_oldest_reader); -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - mdbx_txn_valgrind(env, nullptr); -#endif - slot->mr_snapshot_pages_used = 0; - safe64_reset(&slot->mr_txnid, false); - env->me_lck->mti_readers_refresh_flag = true; - mdbx_flush_noncoherent_cpu_writeback(); - } else { - mdbx_assert(env, slot->mr_pid == env->me_pid); - mdbx_assert(env, - slot->mr_txnid.inconsistent >= SAFE64_INVALID_THRESHOLD); - } - if (mode & MDBX_END_SLOT) { - if ((env->me_flags & MDBX_ENV_TXKEY) == 0) - slot->mr_pid = 0; - txn->to.reader = NULL; - } - } -#if defined(_WIN32) || defined(_WIN64) - if (txn->mt_flags & MDBX_SHRINK_ALLOWED) - mdbx_srwlock_ReleaseShared(&env->me_remap_guard); -#endif - txn->mt_numdbs = 0; /* prevent further DBI activity */ - txn->mt_flags = MDBX_RDONLY | MDBX_TXN_FINISHED; - txn->mt_owner = 0; - } else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) { -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - if (txn == env->me_txn0) - mdbx_txn_valgrind(env, nullptr); -#endif - /* Export or close DBI handles created in this txn */ - mdbx_dbis_update(txn, mode & MDBX_END_UPDATE); - if (!(mode & MDBX_END_EOTDONE)) /* !(already closed cursors) */ - mdbx_cursors_eot(txn, 0); - if (!(env->me_flags & MDBX_WRITEMAP)) - mdbx_dlist_free(txn); - - txn->mt_flags = MDBX_TXN_FINISHED; - txn->mt_owner = 0; - env->me_txn = txn->mt_parent; - if (txn == env->me_txn0) { - mdbx_assert(env, txn->mt_parent == NULL); - mdbx_pnl_shrink(&txn->tw.retired_pages); - mdbx_pnl_shrink(&txn->tw.reclaimed_pglist); - /* The writer mutex was locked in mdbx_txn_begin. */ - mdbx_txn_unlock(env); - } else { - mdbx_assert(env, txn->mt_parent != NULL); - mdbx_assert(env, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - MDBX_txn *const parent = txn->mt_parent; - env->me_txn->mt_child = NULL; - env->me_txn->mt_flags &= ~MDBX_TXN_HAS_CHILD; - mdbx_pnl_free(txn->tw.reclaimed_pglist); - mdbx_pnl_free(txn->tw.spill_pages); - - if (txn->tw.lifo_reclaimed) { - mdbx_assert(env, MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) >= - (unsigned)(uintptr_t)parent->tw.lifo_reclaimed); - MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) = - (unsigned)(uintptr_t)parent->tw.lifo_reclaimed; - parent->tw.lifo_reclaimed = txn->tw.lifo_reclaimed; - } - - if (txn->tw.retired_pages) { - mdbx_assert(env, MDBX_PNL_SIZE(txn->tw.retired_pages) >= - (unsigned)(uintptr_t)parent->tw.retired_pages); - MDBX_PNL_SIZE(txn->tw.retired_pages) = - (unsigned)(uintptr_t)parent->tw.retired_pages; - parent->tw.retired_pages = txn->tw.retired_pages; - } - - mdbx_free(txn->tw.dirtylist); - - if (parent->mt_geo.upper != txn->mt_geo.upper || - parent->mt_geo.now != txn->mt_geo.now) { - /* undo resize performed by child txn */ - rc = mdbx_mapresize(env, parent->mt_geo.now, parent->mt_geo.upper); - if (rc == MDBX_RESULT_TRUE) { - /* unable undo resize (it is regular for Windows), - * therefore promote size changes from child to the parent txn */ - mdbx_notice("unable undo resize performed by child txn, promote to " - "the parent (%u->%u, %u->%u)", - txn->mt_geo.now, parent->mt_geo.now, txn->mt_geo.upper, - parent->mt_geo.upper); - parent->mt_geo.now = txn->mt_geo.now; - parent->mt_geo.upper = txn->mt_geo.upper; - rc = MDBX_SUCCESS; - } else if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_error("error %d while undo resize performed by child txn, fail " - "the parent", - rc); - parent->mt_flags |= MDBX_TXN_ERROR; - if (!env->me_dxb_mmap.address) - env->me_flags |= MDBX_FATAL_ERROR; - } - } - } - } - - mdbx_assert(env, txn == env->me_txn0 || txn->mt_owner == 0); - if ((mode & MDBX_END_FREE) != 0 && txn != env->me_txn0) { - txn->mt_signature = 0; - mdbx_free(txn); - } - - return rc; -} - -int mdbx_txn_reset(MDBX_txn *txn) { - int rc = check_txn(txn, 0); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - /* This call is only valid for read-only txns */ - if (unlikely((txn->mt_flags & MDBX_RDONLY) == 0)) - return MDBX_EINVAL; - - /* LY: don't close DBI-handles */ - rc = mdbx_txn_end(txn, MDBX_END_RESET | MDBX_END_UPDATE); - if (rc == MDBX_SUCCESS) { - mdbx_tassert(txn, txn->mt_signature == MDBX_MT_SIGNATURE); - mdbx_tassert(txn, txn->mt_owner == 0); - } - return rc; -} - -int mdbx_txn_abort(MDBX_txn *txn) { - int rc = check_txn(txn, 0); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (F_ISSET(txn->mt_flags, MDBX_RDONLY)) - /* LY: don't close DBI-handles */ - return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_UPDATE | MDBX_END_SLOT | - MDBX_END_FREE); - - if (txn->mt_child) - mdbx_txn_abort(txn->mt_child); - - return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_SLOT | MDBX_END_FREE); -} - -static __inline int mdbx_backlog_size(MDBX_txn *txn) { - int reclaimed = MDBX_PNL_SIZE(txn->tw.reclaimed_pglist); - return reclaimed + txn->tw.loose_count; -} - -static __inline int mdbx_backlog_extragap(MDBX_env *env) { - /* LY: extra page(s) for b-tree rebalancing */ - return (env->me_flags & MDBX_LIFORECLAIM) ? 2 : 1; -} - -/* LY: Prepare a backlog of pages to modify GC itself, - * while reclaiming is prohibited. It should be enough to prevent search - * in mdbx_page_alloc() during a deleting, when GC tree is unbalanced. */ -static int mdbx_prep_backlog(MDBX_txn *txn, MDBX_cursor *mc) { - /* LY: extra page(s) for b-tree rebalancing */ - const int extra = - mdbx_backlog_extragap(txn->mt_env) + - MDBX_PNL_SIZEOF(txn->tw.retired_pages) / txn->mt_env->me_maxkey_limit; - - if (mdbx_backlog_size(txn) < mc->mc_db->md_depth + extra) { - mc->mc_flags &= ~C_RECLAIMING; - int rc = mdbx_cursor_touch(mc); - if (unlikely(rc)) - return rc; - - while (unlikely(mdbx_backlog_size(txn) < extra)) { - rc = mdbx_page_alloc(mc, 1, NULL, MDBX_ALLOC_GC); - if (unlikely(rc)) { - if (rc != MDBX_NOTFOUND) - return rc; - break; - } - } - mc->mc_flags |= C_RECLAIMING; - } - - return MDBX_SUCCESS; -} - -static void mdbx_prep_backlog_data(MDBX_txn *txn, MDBX_cursor *mc, - size_t bytes) { - const int wanna = (int)number_of_ovpages(txn->mt_env, bytes) + - mdbx_backlog_extragap(txn->mt_env); - if (unlikely(wanna > mdbx_backlog_size(txn))) { - mc->mc_flags &= ~C_RECLAIMING; - do { - if (mdbx_page_alloc(mc, 1, NULL, MDBX_ALLOC_GC) != MDBX_SUCCESS) - break; - } while (wanna > mdbx_backlog_size(txn)); - mc->mc_flags |= C_RECLAIMING; - } -} - -/* Count all the pages in each DB and in the freelist and make sure - * it matches the actual number of pages being used. - * All named DBs must be open for a correct count. */ -static __cold int mdbx_audit_ex(MDBX_txn *txn, unsigned retired_stored, - bool dont_filter_gc) { - pgno_t pending = 0; - if ((txn->mt_flags & MDBX_RDONLY) == 0) { - pending = txn->tw.loose_count + MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) + - (MDBX_PNL_SIZE(txn->tw.retired_pages) - retired_stored) + - txn->tw.retired2parent_count; - for (MDBX_txn *parent = txn->mt_parent; parent; parent = parent->mt_parent) - pending += parent->tw.loose_count; - } - - MDBX_cursor_couple cx; - int rc = mdbx_cursor_init(&cx.outer, txn, FREE_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - pgno_t freecount = 0; - MDBX_val key, data; - while ((rc = mdbx_cursor_get(&cx.outer, &key, &data, MDBX_NEXT)) == 0) { - if (!dont_filter_gc) { - if (unlikely(key.iov_len != sizeof(txnid_t))) - return MDBX_CORRUPTED; - txnid_t id = unaligned_peek_u64(4, key.iov_base); - if (txn->tw.lifo_reclaimed) { - for (unsigned i = 1; i <= MDBX_PNL_SIZE(txn->tw.lifo_reclaimed); ++i) - if (id == txn->tw.lifo_reclaimed[i]) - goto skip; - } else if (id <= txn->tw.last_reclaimed) - goto skip; - } - - freecount += *(pgno_t *)data.iov_base; - skip:; - } - mdbx_tassert(txn, rc == MDBX_NOTFOUND); - - for (MDBX_dbi i = FREE_DBI; i < txn->mt_numdbs; i++) - txn->mt_dbflags[i] &= ~DB_AUDITED; - - pgno_t count = 0; - for (MDBX_dbi i = FREE_DBI; i <= MAIN_DBI; i++) { - if (!(txn->mt_dbflags[i] & DB_VALID)) - continue; - rc = mdbx_cursor_init(&cx.outer, txn, i); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - txn->mt_dbflags[i] |= DB_AUDITED; - if (txn->mt_dbs[i].md_root == P_INVALID) - continue; - count += txn->mt_dbs[i].md_branch_pages + txn->mt_dbs[i].md_leaf_pages + - txn->mt_dbs[i].md_overflow_pages; - - if (i != MAIN_DBI) - continue; - rc = mdbx_page_search(&cx.outer, NULL, MDBX_PS_FIRST); - while (rc == MDBX_SUCCESS) { - MDBX_page *mp = cx.outer.mc_pg[cx.outer.mc_top]; - for (unsigned j = 0; j < page_numkeys(mp); j++) { - MDBX_node *node = page_node(mp, j); - if (node_flags(node) == F_SUBDATA) { - if (unlikely(node_ds(node) < sizeof(MDBX_db))) - return MDBX_CORRUPTED; - MDBX_db db_copy, *db; - memcpy(db = &db_copy, node_data(node), sizeof(db_copy)); - if ((txn->mt_flags & MDBX_RDONLY) == 0) { - for (MDBX_dbi k = txn->mt_numdbs; --k > MAIN_DBI;) { - if ((txn->mt_dbflags[k] & DB_VALID) && - /* txn->mt_dbxs[k].md_name.iov_len > 0 && */ - node_ks(node) == txn->mt_dbxs[k].md_name.iov_len && - memcmp(node_key(node), txn->mt_dbxs[k].md_name.iov_base, - node_ks(node)) == 0) { - txn->mt_dbflags[k] |= DB_AUDITED; - if (txn->mt_dbflags[k] & DB_DIRTY) { - mdbx_tassert(txn, (txn->mt_dbflags[k] & DB_STALE) == 0); - db = txn->mt_dbs + k; - } - break; - } - } - } - count += - db->md_branch_pages + db->md_leaf_pages + db->md_overflow_pages; - } - } - rc = mdbx_cursor_sibling(&cx.outer, 1); - } - mdbx_tassert(txn, rc == MDBX_NOTFOUND); - } - - for (MDBX_dbi i = FREE_DBI; i < txn->mt_numdbs; i++) { - if ((txn->mt_dbflags[i] & (DB_VALID | DB_AUDITED | DB_STALE)) != DB_VALID) - continue; - if (F_ISSET(txn->mt_dbflags[i], DB_DIRTY | DB_CREAT)) { - count += txn->mt_dbs[i].md_branch_pages + txn->mt_dbs[i].md_leaf_pages + - txn->mt_dbs[i].md_overflow_pages; - } else { - mdbx_warning("audit %s@%" PRIaTXN - ": unable account dbi %d / \"%*s\", state 0x%02x", - txn->mt_parent ? "nested-" : "", txn->mt_txnid, i, - (int)txn->mt_dbxs[i].md_name.iov_len, - (const char *)txn->mt_dbxs[i].md_name.iov_base, - txn->mt_dbflags[i]); - } - } - - if (pending + freecount + count + NUM_METAS == txn->mt_next_pgno) - return MDBX_SUCCESS; - - if ((txn->mt_flags & MDBX_RDONLY) == 0) - mdbx_error("audit @%" PRIaTXN ": %u(pending) = %u(loose-count) + " - "%u(reclaimed-list) + %u(retired-pending) - %u(retired-stored) " - "+ %u(retired2parent)", - txn->mt_txnid, pending, txn->tw.loose_count, - MDBX_PNL_SIZE(txn->tw.reclaimed_pglist), - txn->tw.retired_pages ? MDBX_PNL_SIZE(txn->tw.retired_pages) : 0, - retired_stored, txn->tw.retired2parent_count); - mdbx_error("audit @%" PRIaTXN ": %" PRIaPGNO "(pending) + %" PRIaPGNO - "(free) + %" PRIaPGNO "(count) = %" PRIaPGNO - "(total) <> %" PRIaPGNO "(next-pgno)", - txn->mt_txnid, pending, freecount, count + NUM_METAS, - pending + freecount + count + NUM_METAS, txn->mt_next_pgno); - return MDBX_PROBLEM; -} - -static __inline void clean_reserved_gc_pnl(MDBX_env *env, MDBX_val pnl) { - /* PNL is initially empty, zero out at least the length */ - memset(pnl.iov_base, 0, sizeof(pgno_t)); - if ((env->me_flags & (MDBX_WRITEMAP | MDBX_NOMEMINIT)) == 0) - /* zero out to avoid leaking values from uninitialized malloc'ed memory - * to the file in non-writemap mode if length of the saving page-list - * was changed during space reservation. */ - memset(pnl.iov_base, 0, pnl.iov_len); -} - -/* Cleanup reclaimed GC records, than save the retired-list as of this - * transaction to GC (aka freeDB). This recursive changes the reclaimed-list - * loose-list and retired-list. Keep trying until it stabilizes. */ -static int mdbx_update_gc(MDBX_txn *txn) { - /* txn->tw.reclaimed_pglist[] can grow and shrink during this call. - * txn->tw.last_reclaimed and txn->tw.retired_pages[] can only grow. - * Page numbers cannot disappear from txn->tw.retired_pages[]. */ - MDBX_env *const env = txn->mt_env; - const bool lifo = (env->me_flags & MDBX_LIFORECLAIM) != 0; - const char *dbg_prefix_mode = lifo ? " lifo" : " fifo"; - (void)dbg_prefix_mode; - mdbx_trace("\n>>> @%" PRIaTXN, txn->mt_txnid); - - unsigned retired_stored = 0, loop = 0; - MDBX_cursor mc; - int rc = mdbx_cursor_init(&mc, txn, FREE_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout_notracking; - - mc.mc_flags |= C_RECLAIMING; - mc.mc_next = txn->mt_cursors[FREE_DBI]; - txn->mt_cursors[FREE_DBI] = &mc; - -retry: - mdbx_trace("%s", " >> restart"); - mdbx_tassert( - txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, txn->mt_next_pgno)); - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - mdbx_tassert(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - if (unlikely(/* paranoia */ ++loop > 42)) { - mdbx_error("too more loops %u, bailout", loop); - rc = MDBX_PROBLEM; - goto bailout; - } - - unsigned settled = 0, cleaned_gc_slot = 0, reused_gc_slot = 0, - filled_gc_slot = ~0u; - txnid_t cleaned_gc_id = 0, gc_rid = txn->tw.last_reclaimed; - while (true) { - /* Come back here after each Put() in case retired-list changed */ - MDBX_val key, data; - mdbx_trace("%s", " >> continue"); - - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - if (txn->tw.lifo_reclaimed) { - if (cleaned_gc_slot < MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)) { - settled = 0; - cleaned_gc_slot = 0; - reused_gc_slot = 0; - filled_gc_slot = ~0u; - /* LY: cleanup reclaimed records. */ - do { - cleaned_gc_id = txn->tw.lifo_reclaimed[++cleaned_gc_slot]; - mdbx_tassert(txn, - cleaned_gc_slot > 0 && cleaned_gc_id < *env->me_oldest); - key.iov_base = &cleaned_gc_id; - key.iov_len = sizeof(cleaned_gc_id); - rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET); - if (rc == MDBX_NOTFOUND) - continue; - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - rc = mdbx_prep_backlog(txn, &mc); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - mdbx_tassert(txn, cleaned_gc_id < *env->me_oldest); - mdbx_trace("%s.cleanup-reclaimed-id [%u]%" PRIaTXN, dbg_prefix_mode, - cleaned_gc_slot, cleaned_gc_id); - rc = mdbx_cursor_del(&mc, 0); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } while (cleaned_gc_slot < MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); - mdbx_txl_sort(txn->tw.lifo_reclaimed); - gc_rid = MDBX_PNL_LAST(txn->tw.lifo_reclaimed); - } - } else { - /* If using records from GC which we have not yet deleted, - * now delete them and any we reserved for me_reclaimed_pglist. */ - while (cleaned_gc_id <= txn->tw.last_reclaimed) { - gc_rid = cleaned_gc_id; - settled = 0; - rc = mdbx_cursor_first(&mc, &key, NULL); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc == MDBX_NOTFOUND) - break; - goto bailout; - } - if (unlikely(key.iov_len != sizeof(txnid_t))) { - rc = MDBX_CORRUPTED; - goto bailout; - } - cleaned_gc_id = unaligned_peek_u64(4, key.iov_base); - if (unlikely(cleaned_gc_id < 1 || - cleaned_gc_id >= SAFE64_INVALID_THRESHOLD)) { - rc = MDBX_CORRUPTED; - goto bailout; - } - if (cleaned_gc_id > txn->tw.last_reclaimed) - break; - if (cleaned_gc_id < txn->tw.last_reclaimed) { - rc = mdbx_prep_backlog(txn, &mc); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - mdbx_tassert(txn, cleaned_gc_id <= txn->tw.last_reclaimed); - mdbx_tassert(txn, cleaned_gc_id < *env->me_oldest); - mdbx_trace("%s.cleanup-reclaimed-id %" PRIaTXN, dbg_prefix_mode, - cleaned_gc_id); - rc = mdbx_cursor_del(&mc, 0); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - } - - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - mdbx_tassert(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - if (mdbx_audit_enabled()) { - rc = mdbx_audit_ex(txn, retired_stored, false); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - - /* return suitable into unallocated space */ - if (mdbx_refund(txn)) { - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - if (mdbx_audit_enabled()) { - rc = mdbx_audit_ex(txn, retired_stored, false); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - } - - /* handle loose pages - put ones into the reclaimed- or retired-list */ - if (txn->tw.loose_pages) { - /* Return loose page numbers to me_reclaimed_pglist, - * though usually none are left at this point. - * The pages themselves remain in dirtylist. */ - if (unlikely(!txn->tw.lifo_reclaimed && txn->tw.last_reclaimed < 1)) { - if (txn->tw.loose_count > 0) { - /* Put loose page numbers in tw.retired_pages, - * since unable to return them to me_reclaimed_pglist. */ - if (unlikely((rc = mdbx_pnl_need(&txn->tw.retired_pages, - txn->tw.loose_count)) != 0)) - goto bailout; - for (MDBX_page *mp = txn->tw.loose_pages; mp; mp = mp->mp_next) - mdbx_pnl_xappend(txn->tw.retired_pages, mp->mp_pgno); - mdbx_trace("%s: append %u loose-pages to retired-pages", - dbg_prefix_mode, txn->tw.loose_count); - } - } else { - /* Room for loose pages + temp PNL with same */ - rc = mdbx_pnl_need(&txn->tw.reclaimed_pglist, - 2 * txn->tw.loose_count + 2); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - MDBX_PNL loose = txn->tw.reclaimed_pglist + - MDBX_PNL_ALLOCLEN(txn->tw.reclaimed_pglist) - - txn->tw.loose_count - 1; - unsigned count = 0; - for (MDBX_page *mp = txn->tw.loose_pages; mp; mp = mp->mp_next) { - mdbx_tassert(txn, mp->mp_flags == (P_LOOSE | P_DIRTY)); - loose[++count] = mp->mp_pgno; - } - mdbx_tassert(txn, count == txn->tw.loose_count); - MDBX_PNL_SIZE(loose) = count; - mdbx_pnl_sort(loose); - mdbx_pnl_xmerge(txn->tw.reclaimed_pglist, loose); - mdbx_trace("%s: append %u loose-pages to reclaimed-pages", - dbg_prefix_mode, txn->tw.loose_count); - } - - /* filter-out list of dirty-pages from loose-pages */ - const MDBX_DPL dl = txn->tw.dirtylist; - unsigned w = 0; - for (unsigned r = w; ++r <= dl->length;) { - MDBX_page *dp = dl[r].ptr; - mdbx_tassert(txn, (dp->mp_flags & P_DIRTY)); - mdbx_tassert(txn, dl[r].pgno + (IS_OVERFLOW(dp) ? dp->mp_pages : 1) <= - txn->mt_next_pgno); - if ((dp->mp_flags & P_LOOSE) == 0) { - if (++w != r) - dl[w] = dl[r]; - } else { - mdbx_tassert(txn, dp->mp_flags == (P_LOOSE | P_DIRTY)); - if ((env->me_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(env, dp, 1); - } - } - mdbx_trace("%s: filtered-out loose-pages from %u -> %u dirty-pages", - dbg_prefix_mode, dl->length, w); - mdbx_tassert(txn, txn->tw.loose_count == dl->length - w); - dl->length = w; - dl->sorted = 0; - txn->tw.dirtyroom += txn->tw.loose_count; - txn->tw.loose_pages = NULL; - txn->tw.loose_count = 0; - } - - /* handle retired-list - store ones into single gc-record */ - if (retired_stored < MDBX_PNL_SIZE(txn->tw.retired_pages)) { - if (unlikely(!retired_stored)) { - /* Make sure last page of GC is touched and on retired-list */ - mc.mc_flags &= ~C_RECLAIMING; - rc = mdbx_page_search(&mc, NULL, MDBX_PS_LAST | MDBX_PS_MODIFY); - mc.mc_flags |= C_RECLAIMING; - if (unlikely(rc != MDBX_SUCCESS) && rc != MDBX_NOTFOUND) - goto bailout; - } - /* Write to last page of GC */ - key.iov_len = sizeof(txn->mt_txnid); - key.iov_base = &txn->mt_txnid; - do { - data.iov_len = MDBX_PNL_SIZEOF(txn->tw.retired_pages); - mdbx_prep_backlog_data(txn, &mc, data.iov_len); - rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - /* Retry if tw.retired_pages[] grew during the Put() */ - } while (data.iov_len < MDBX_PNL_SIZEOF(txn->tw.retired_pages)); - - retired_stored = (unsigned)MDBX_PNL_SIZE(txn->tw.retired_pages); - mdbx_pnl_sort(txn->tw.retired_pages); - mdbx_assert(env, data.iov_len == MDBX_PNL_SIZEOF(txn->tw.retired_pages)); - memcpy(data.iov_base, txn->tw.retired_pages, data.iov_len); - - mdbx_trace("%s.put-retired #%u @ %" PRIaTXN, dbg_prefix_mode, - retired_stored, txn->mt_txnid); - - if (mdbx_log_enabled(MDBX_LOG_EXTRA)) { - unsigned i = retired_stored; - mdbx_debug_extra("PNL write txn %" PRIaTXN " root %" PRIaPGNO - " num %u, PNL", - txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i); - for (; i; i--) - mdbx_debug_extra_print(" %" PRIaPGNO, txn->tw.retired_pages[i]); - mdbx_debug_extra_print("%s", "\n"); - } - continue; - } - - /* handle reclaimed and loost pages - merge and store both into gc */ - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - mdbx_tassert(txn, txn->tw.loose_count == 0); - - mdbx_trace("%s", " >> reserving"); - if (mdbx_audit_enabled()) { - rc = mdbx_audit_ex(txn, retired_stored, false); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - const unsigned amount = (unsigned)MDBX_PNL_SIZE(txn->tw.reclaimed_pglist); - const unsigned left = amount - settled; - mdbx_trace("%s: amount %u, settled %d, left %d, lifo-reclaimed-slots %u, " - "reused-gc-slots %u", - dbg_prefix_mode, amount, settled, (int)left, - txn->tw.lifo_reclaimed - ? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - : 0, - reused_gc_slot); - if (0 >= (int)left) - break; - - const unsigned prefer_max_scatter = 257; - txnid_t reservation_gc_id; - if (lifo) { - const unsigned lifo_len = - txn->tw.lifo_reclaimed - ? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - : 0; - if (lifo_len < prefer_max_scatter && - left > (lifo_len - reused_gc_slot) * env->me_maxgc_ov1page) { - /* LY: need just a txn-id for save page list. */ - mc.mc_flags &= ~C_RECLAIMING; - rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK); - mc.mc_flags |= C_RECLAIMING; - if (likely(rc == MDBX_SUCCESS)) { - /* LY: ok, reclaimed from GC. */ - mdbx_trace("%s: took @%" PRIaTXN " from GC, continue", - dbg_prefix_mode, MDBX_PNL_LAST(txn->tw.lifo_reclaimed)); - continue; - } - if (unlikely(rc != MDBX_NOTFOUND)) - /* LY: other troubles... */ - goto bailout; - - /* LY: GC is empty, will look any free txn-id in high2low order. */ - if (unlikely(gc_rid == 0)) { - mdbx_tassert(txn, txn->tw.last_reclaimed == 0); - txn->tw.last_reclaimed = gc_rid = mdbx_find_oldest(txn) - 1; - if (txn->tw.lifo_reclaimed == nullptr) { - txn->tw.lifo_reclaimed = mdbx_txl_alloc(); - if (unlikely(!txn->tw.lifo_reclaimed)) { - rc = MDBX_ENOMEM; - goto bailout; - } - } - } - - mdbx_tassert(txn, txn->tw.lifo_reclaimed != nullptr); - rc = MDBX_RESULT_TRUE; - do { - if (unlikely(gc_rid <= 1)) { - if (unlikely(MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) <= - reused_gc_slot)) { - mdbx_notice("** restart: reserve depleted (reused_gc_slot %u >= " - "lifo_reclaimed %u" PRIaTXN, - reused_gc_slot, - (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); - goto retry; - } - break; - } - - mdbx_tassert(txn, gc_rid > 1 && gc_rid < SAFE64_INVALID_THRESHOLD); - rc = mdbx_txl_append(&txn->tw.lifo_reclaimed, --gc_rid); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - cleaned_gc_slot += 1 /* mark GC cleanup is not needed. */; - - mdbx_trace("%s: append @%" PRIaTXN - " to lifo-reclaimed, cleaned-gc-slot = %u", - dbg_prefix_mode, gc_rid, cleaned_gc_slot); - } while (gc_rid && - MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) < prefer_max_scatter && - left > ((unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - - reused_gc_slot) * - env->me_maxgc_ov1page); - if (reused_gc_slot && rc != MDBX_RESULT_TRUE) { - mdbx_trace("%s: restart innter-loop since reused_gc_slot %u > 0", - dbg_prefix_mode, reused_gc_slot); - continue; - } - } - - const unsigned i = - (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - reused_gc_slot; - mdbx_tassert(txn, i > 0 && i <= MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); - reservation_gc_id = txn->tw.lifo_reclaimed[i]; - mdbx_trace("%s: take @%" PRIaTXN " from lifo-reclaimed[%u]", - dbg_prefix_mode, reservation_gc_id, i); - } else { - mdbx_tassert(txn, txn->tw.lifo_reclaimed == NULL); - if (unlikely(gc_rid == 0)) { - gc_rid = mdbx_find_oldest(txn) - 1; - rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_FIRST); - if (rc == MDBX_SUCCESS) { - if (unlikely(key.iov_len != sizeof(txnid_t))) { - rc = MDBX_CORRUPTED; - goto bailout; - } - txnid_t gc_first = unaligned_peek_u64(4, key.iov_base); - if (unlikely(gc_first < 1 || gc_first >= SAFE64_INVALID_THRESHOLD)) { - rc = MDBX_CORRUPTED; - goto bailout; - } - if (gc_rid >= gc_first) - gc_rid = gc_first - 1; - if (unlikely(gc_rid == 0)) { - mdbx_error("%s", "** no GC tail-space to store"); - rc = MDBX_PROBLEM; - goto bailout; - } - } else if (rc != MDBX_NOTFOUND) - goto bailout; - mdbx_tassert(txn, txn->tw.last_reclaimed == 0); - txn->tw.last_reclaimed = gc_rid; - } - reservation_gc_id = gc_rid--; - mdbx_trace("%s: take @%" PRIaTXN " from head-gc-id", dbg_prefix_mode, - reservation_gc_id); - } - ++reused_gc_slot; - - unsigned chunk = left; - if (unlikely(chunk > env->me_maxgc_ov1page)) { - const unsigned avail_gc_slots = - txn->tw.lifo_reclaimed - ? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - - reused_gc_slot + 1 - : (gc_rid < INT16_MAX) ? (unsigned)gc_rid : INT16_MAX; - if (avail_gc_slots > 1) { - if (chunk < env->me_maxgc_ov1page * 2) - chunk /= 2; - else { - const unsigned threshold = - env->me_maxgc_ov1page * ((avail_gc_slots < prefer_max_scatter) - ? avail_gc_slots - : prefer_max_scatter); - if (left < threshold) - chunk = env->me_maxgc_ov1page; - else { - const unsigned tail = left - threshold + env->me_maxgc_ov1page + 1; - unsigned span = 1; - unsigned avail = (unsigned)((pgno2bytes(env, span) - PAGEHDRSZ) / - sizeof(pgno_t)) /*- 1 + span */; - if (tail > avail) { - for (unsigned i = amount - span; i > 0; --i) { - if (MDBX_PNL_ASCENDING - ? (txn->tw.reclaimed_pglist[i] + span) - : (txn->tw.reclaimed_pglist[i] - span) == - txn->tw.reclaimed_pglist[i + span]) { - span += 1; - avail = (unsigned)((pgno2bytes(env, span) - PAGEHDRSZ) / - sizeof(pgno_t)) - - 1 + span; - if (avail >= tail) - break; - } - } - } - - chunk = (avail >= tail) ? tail - span - : (avail_gc_slots > 3 && - reused_gc_slot < prefer_max_scatter - 3) - ? avail - span - : tail; - } - } - } - } - mdbx_tassert(txn, chunk > 0); - - mdbx_trace("%s: rc_rid %" PRIaTXN ", reused_gc_slot %u, reservation-id " - "%" PRIaTXN, - dbg_prefix_mode, gc_rid, reused_gc_slot, reservation_gc_id); - - mdbx_trace("%s: chunk %u, gc-per-ovpage %u", dbg_prefix_mode, chunk, - env->me_maxgc_ov1page); - - mdbx_tassert(txn, reservation_gc_id < *env->me_oldest); - if (unlikely(reservation_gc_id < 1 || - reservation_gc_id >= *env->me_oldest)) { - mdbx_error("%s", "** internal error (reservation_gc_id)"); - rc = MDBX_PROBLEM; - goto bailout; - } - - key.iov_len = sizeof(reservation_gc_id); - key.iov_base = &reservation_gc_id; - data.iov_len = (chunk + 1) * sizeof(pgno_t); - mdbx_trace("%s.reserve: %u [%u...%u] @%" PRIaTXN, dbg_prefix_mode, chunk, - settled + 1, settled + chunk + 1, reservation_gc_id); - mdbx_prep_backlog_data(txn, &mc, data.iov_len); - rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE | MDBX_NOOVERWRITE); - mdbx_tassert(txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, - txn->mt_next_pgno)); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - - clean_reserved_gc_pnl(env, data); - settled += chunk; - mdbx_trace("%s.settled %u (+%u), continue", dbg_prefix_mode, settled, - chunk); - - if (txn->tw.lifo_reclaimed && - unlikely(amount < MDBX_PNL_SIZE(txn->tw.reclaimed_pglist))) { - mdbx_notice("** restart: reclaimed-list growth %u -> %u", amount, - (unsigned)MDBX_PNL_SIZE(txn->tw.reclaimed_pglist)); - goto retry; - } - - continue; - } - - mdbx_tassert( - txn, - cleaned_gc_slot == - (txn->tw.lifo_reclaimed ? MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) : 0)); - - mdbx_trace("%s", " >> filling"); - /* Fill in the reserved records */ - filled_gc_slot = - txn->tw.lifo_reclaimed - ? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - reused_gc_slot - : reused_gc_slot; - rc = MDBX_SUCCESS; - mdbx_tassert( - txn, mdbx_pnl_check4assert(txn->tw.reclaimed_pglist, txn->mt_next_pgno)); - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - if (MDBX_PNL_SIZE(txn->tw.reclaimed_pglist)) { - MDBX_val key, data; - key.iov_len = data.iov_len = 0; /* avoid MSVC warning */ - key.iov_base = data.iov_base = NULL; - - const unsigned amount = MDBX_PNL_SIZE(txn->tw.reclaimed_pglist); - unsigned left = amount; - if (txn->tw.lifo_reclaimed == nullptr) { - mdbx_tassert(txn, lifo == 0); - rc = mdbx_cursor_first(&mc, &key, &data); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } else { - mdbx_tassert(txn, lifo != 0); - } - - while (true) { - txnid_t fill_gc_id; - mdbx_trace("%s: left %u of %u", dbg_prefix_mode, left, - (unsigned)MDBX_PNL_SIZE(txn->tw.reclaimed_pglist)); - if (txn->tw.lifo_reclaimed == nullptr) { - mdbx_tassert(txn, lifo == 0); - fill_gc_id = unaligned_peek_u64(4, key.iov_base); - if (filled_gc_slot-- == 0 || fill_gc_id > txn->tw.last_reclaimed) { - mdbx_notice( - "** restart: reserve depleted (filled_slot %u, fill_id %" PRIaTXN - " > last_reclaimed %" PRIaTXN, - filled_gc_slot, fill_gc_id, txn->tw.last_reclaimed); - goto retry; - } - } else { - mdbx_tassert(txn, lifo != 0); - if (++filled_gc_slot > - (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)) { - mdbx_notice("** restart: reserve depleted (filled_gc_slot %u > " - "lifo_reclaimed %u" PRIaTXN, - filled_gc_slot, - (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); - goto retry; - } - fill_gc_id = txn->tw.lifo_reclaimed[filled_gc_slot]; - mdbx_trace("%s.seek-reservation @%" PRIaTXN " at lifo_reclaimed[%u]", - dbg_prefix_mode, fill_gc_id, filled_gc_slot); - key.iov_base = &fill_gc_id; - key.iov_len = sizeof(fill_gc_id); - rc = mdbx_cursor_get(&mc, &key, &data, MDBX_SET_KEY); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - mdbx_tassert(txn, cleaned_gc_slot == - (txn->tw.lifo_reclaimed - ? MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - : 0)); - mdbx_tassert(txn, fill_gc_id > 0 && fill_gc_id < *env->me_oldest); - key.iov_base = &fill_gc_id; - key.iov_len = sizeof(fill_gc_id); - - mdbx_tassert(txn, data.iov_len >= sizeof(pgno_t) * 2); - mc.mc_flags |= C_GCFREEZE; - unsigned chunk = (unsigned)(data.iov_len / sizeof(pgno_t)) - 1; - if (unlikely(chunk > left)) { - mdbx_trace("%s: chunk %u > left %u, @%" PRIaTXN, dbg_prefix_mode, chunk, - left, fill_gc_id); - if ((loop < 5 && chunk - left > loop / 2) || - chunk - left > env->me_maxgc_ov1page) { - data.iov_len = (left + 1) * sizeof(pgno_t); - if (loop < 7) - mc.mc_flags &= ~C_GCFREEZE; - } - chunk = left; - } - rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT | MDBX_RESERVE); - mc.mc_flags &= ~C_GCFREEZE; - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - clean_reserved_gc_pnl(env, data); - - if (unlikely(txn->tw.loose_count || - amount != MDBX_PNL_SIZE(txn->tw.reclaimed_pglist))) { - mdbx_notice("** restart: reclaimed-list changed (%u -> %u, %u)", amount, - MDBX_PNL_SIZE(txn->tw.reclaimed_pglist), - txn->tw.loose_count); - goto retry; - } - if (unlikely(txn->tw.lifo_reclaimed - ? cleaned_gc_slot < MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - : cleaned_gc_id < txn->tw.last_reclaimed)) { - mdbx_notice("%s", "** restart: reclaimed-slots changed"); - goto retry; - } - - pgno_t *dst = data.iov_base; - *dst++ = chunk; - pgno_t *src = MDBX_PNL_BEGIN(txn->tw.reclaimed_pglist) + left - chunk; - memcpy(dst, src, chunk * sizeof(pgno_t)); - pgno_t *from = src, *to = src + chunk; - mdbx_trace("%s.fill: %u [ %u:%" PRIaPGNO "...%u:%" PRIaPGNO - "] @%" PRIaTXN, - dbg_prefix_mode, chunk, - (unsigned)(from - txn->tw.reclaimed_pglist), from[0], - (unsigned)(to - txn->tw.reclaimed_pglist), to[-1], fill_gc_id); - - left -= chunk; - if (mdbx_audit_enabled()) { - rc = mdbx_audit_ex(txn, retired_stored + amount - left, true); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } - if (left == 0) { - rc = MDBX_SUCCESS; - break; - } - - if (txn->tw.lifo_reclaimed == nullptr) { - mdbx_tassert(txn, lifo == 0); - rc = mdbx_cursor_next(&mc, &key, &data, MDBX_NEXT); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } else { - mdbx_tassert(txn, lifo != 0); - } - } - } - - mdbx_tassert(txn, rc == MDBX_SUCCESS); - if (unlikely(txn->tw.loose_count != 0 || - filled_gc_slot != - (txn->tw.lifo_reclaimed - ? (unsigned)MDBX_PNL_SIZE(txn->tw.lifo_reclaimed) - : 0))) { - mdbx_notice("** restart: reserve excess (filled-slot %u, loose-count %u)", - filled_gc_slot, txn->tw.loose_count); - goto retry; - } - - mdbx_tassert(txn, - txn->tw.lifo_reclaimed == NULL || - cleaned_gc_slot == MDBX_PNL_SIZE(txn->tw.lifo_reclaimed)); - -bailout: - txn->mt_cursors[FREE_DBI] = mc.mc_next; - -bailout_notracking: - MDBX_PNL_SIZE(txn->tw.reclaimed_pglist) = 0; - mdbx_trace("<<< %u loops, rc = %d", loop, rc); - return rc; -} - -static int mdbx_flush_iov(MDBX_txn *const txn, struct iovec *iov, - unsigned iov_items, size_t iov_off, - size_t iov_bytes) { - MDBX_env *const env = txn->mt_env; - int rc = mdbx_pwritev(env->me_fd, iov, iov_items, iov_off, iov_bytes); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_error("Write error: %s", mdbx_strerror(rc)); - txn->mt_flags |= MDBX_TXN_ERROR; - } - - for (unsigned i = 0; i < iov_items; i++) - mdbx_dpage_free(env, (MDBX_page *)iov[i].iov_base, - bytes2pgno(env, iov[i].iov_len)); - - return rc; -} - -/* Flush (some) dirty pages to the map, after clearing their dirty flag. - * [in] txn the transaction that's being committed - * [in] keep number of initial pages in dirtylist to keep dirty. - * Returns 0 on success, non-zero on failure. */ -static int mdbx_page_flush(MDBX_txn *txn, const unsigned keep) { - struct iovec iov[MDBX_COMMIT_PAGES]; - const MDBX_DPL dl = (keep || txn->tw.loose_count > 1) - ? mdbx_dpl_sort(txn->tw.dirtylist) - : txn->tw.dirtylist; - MDBX_env *const env = txn->mt_env; - pgno_t flush_begin = MAX_PAGENO; - pgno_t flush_end = MIN_PAGENO; - unsigned iov_items = 0; - size_t iov_bytes = 0; - size_t iov_off = 0; - unsigned r, w; - for (r = w = keep; ++r <= dl->length;) { - MDBX_page *dp = dl[r].ptr; - mdbx_tassert(txn, - dp->mp_pgno >= MIN_PAGENO && dp->mp_pgno < txn->mt_next_pgno); - mdbx_tassert(txn, dp->mp_flags & P_DIRTY); - - /* Don't flush this page yet */ - if (dp->mp_flags & (P_LOOSE | P_KEEP)) { - dp->mp_flags &= ~P_KEEP; - dl[++w] = dl[r]; - continue; - } - - const unsigned npages = IS_OVERFLOW(dp) ? dp->mp_pages : 1; - flush_begin = (flush_begin < dp->mp_pgno) ? flush_begin : dp->mp_pgno; - flush_end = - (flush_end > dp->mp_pgno + npages) ? flush_end : dp->mp_pgno + npages; - *env->me_unsynced_pages += npages; - dp->mp_flags &= ~P_DIRTY; - dp->mp_validator = 0 /* TODO */; - - if ((env->me_flags & MDBX_WRITEMAP) == 0) { - const size_t size = pgno2bytes(env, npages); - if (iov_off + iov_bytes != pgno2bytes(env, dp->mp_pgno) || - iov_items == ARRAY_LENGTH(iov) || iov_bytes + size > MAX_WRITE) { - if (iov_items) { - int rc = mdbx_flush_iov(txn, iov, iov_items, iov_off, iov_bytes); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; -#if MDBX_CPU_CACHE_MMAP_NONCOHERENT -#if defined(__linux__) || defined(__gnu_linux__) - if (mdbx_linux_kernel_version >= 0x02060b00) - /* Linux kernels older than version 2.6.11 ignore the addr and nbytes - * arguments, making this function fairly expensive. Therefore, the - * whole cache is always flushed. */ -#endif /* Linux */ - mdbx_invalidate_mmap_noncoherent_cache(env->me_map + iov_off, - iov_bytes); -#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ - iov_items = 0; - iov_bytes = 0; - } - iov_off = pgno2bytes(env, dp->mp_pgno); - } - iov[iov_items].iov_base = dp; - iov[iov_items].iov_len = size; - iov_items += 1; - iov_bytes += size; - } - } - - if (iov_items) { - int rc = mdbx_flush_iov(txn, iov, iov_items, iov_off, iov_bytes); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - -#if MDBX_CPU_CACHE_MMAP_NONCOHERENT && \ - (defined(__linux__) || defined(__gnu_linux__)) - if ((env->me_flags & MDBX_WRITEMAP) == 0 && - mdbx_linux_kernel_version < 0x02060b00) - /* Linux kernels older than version 2.6.11 ignore the addr and nbytes - * arguments, making this function fairly expensive. Therefore, the - * whole cache is always flushed. */ - mdbx_invalidate_mmap_noncoherent_cache( - env->me_map + pgno2bytes(env, flush_begin), - pgno2bytes(env, flush_end - flush_begin)); -#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT && Linux */ - - /* TODO: use flush_begin & flush_end for msync() & sync_file_range(). */ - (void)flush_begin; - (void)flush_end; - - txn->tw.dirtyroom += r - 1 - w; - dl->length = w; - mdbx_tassert(txn, txn->mt_parent || - txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - return MDBX_SUCCESS; -} - -/* Check for misused dbi handles */ -#define TXN_DBI_CHANGED(txn, dbi) \ - ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi]) - -/* Import DBI which opened after txn started into context */ -static __cold bool mdbx_txn_import_dbi(MDBX_txn *txn, MDBX_dbi dbi) { - MDBX_env *env = txn->mt_env; - if (dbi < CORE_DBS || dbi >= env->me_numdbs) - return false; - - mdbx_ensure(env, mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS); - const unsigned snap_numdbs = env->me_numdbs; - mdbx_compiler_barrier(); - for (unsigned i = CORE_DBS; i < snap_numdbs; ++i) { - if (i >= txn->mt_numdbs) - txn->mt_dbflags[i] = 0; - if (!(txn->mt_dbflags[i] & DB_USRVALID) && - (env->me_dbflags[i] & MDBX_VALID)) { - txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS; - txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE; - mdbx_tassert(txn, txn->mt_dbxs[i].md_cmp != NULL); - } - } - txn->mt_numdbs = snap_numdbs; - - mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); - return txn->mt_dbflags[dbi] & DB_USRVALID; -} - -/* Check txn and dbi arguments to a function */ -static __inline bool TXN_DBI_EXIST(MDBX_txn *txn, MDBX_dbi dbi, - unsigned validity) { - if (likely(dbi < txn->mt_numdbs && (txn->mt_dbflags[dbi] & validity))) - return true; - - return mdbx_txn_import_dbi(txn, dbi); -} - -int mdbx_txn_commit(MDBX_txn *txn) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_HAS_CHILD); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - MDBX_env *env = txn->mt_env; -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - /* mdbx_txn_end() mode for a commit which writes nothing */ - unsigned end_mode = - MDBX_END_EMPTY_COMMIT | MDBX_END_UPDATE | MDBX_END_SLOT | MDBX_END_FREE; - if (unlikely(F_ISSET(txn->mt_flags, MDBX_RDONLY))) - goto done; - - if (txn->mt_child) { - rc = mdbx_txn_commit(txn->mt_child); - mdbx_tassert(txn, txn->mt_child == NULL); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - - if (unlikely(txn != env->me_txn)) { - mdbx_debug("%s", "attempt to commit unknown transaction"); - rc = MDBX_EINVAL; - goto fail; - } - - if (txn->mt_parent) { - MDBX_txn *const parent = txn->mt_parent; - mdbx_tassert(txn, mdbx_dirtylist_check(txn)); - - /* Preserve space for spill list to avoid parent's state corruption - * if allocation fails. */ - if (txn->tw.spill_pages && parent->tw.spill_pages) { - rc = mdbx_pnl_need(&parent->tw.spill_pages, - MDBX_PNL_SIZE(txn->tw.spill_pages)); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - - //------------------------------------------------------------------------- - - parent->tw.lifo_reclaimed = txn->tw.lifo_reclaimed; - txn->tw.lifo_reclaimed = NULL; - - parent->tw.retired_pages = txn->tw.retired_pages; - txn->tw.retired_pages = NULL; - - mdbx_pnl_free(parent->tw.reclaimed_pglist); - parent->tw.reclaimed_pglist = txn->tw.reclaimed_pglist; - txn->tw.reclaimed_pglist = NULL; - parent->tw.last_reclaimed = txn->tw.last_reclaimed; - - parent->mt_geo = txn->mt_geo; - parent->mt_canary = txn->mt_canary; - parent->mt_flags = txn->mt_flags; - - /* Merge our cursors into parent's and close them */ - mdbx_cursors_eot(txn, 1); - - /* Update parent's DB table. */ - memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db)); - parent->mt_numdbs = txn->mt_numdbs; - parent->mt_dbflags[FREE_DBI] = txn->mt_dbflags[FREE_DBI]; - parent->mt_dbflags[MAIN_DBI] = txn->mt_dbflags[MAIN_DBI]; - for (unsigned i = CORE_DBS; i < txn->mt_numdbs; i++) { - /* preserve parent's DB_NEW status */ - parent->mt_dbflags[i] = - txn->mt_dbflags[i] | (parent->mt_dbflags[i] & (DB_CREAT | DB_FRESH)); - } - - /* Remove refunded pages from parent's dirty & spill lists */ - MDBX_DPL dst = mdbx_dpl_sort(parent->tw.dirtylist); - while (dst->length && dst[dst->length].pgno >= parent->mt_next_pgno) { - MDBX_page *mp = dst[dst->length].ptr; - if (mp && (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(txn->mt_env, mp, IS_OVERFLOW(mp) ? mp->mp_pages : 1); - dst->length -= 1; - } - parent->tw.dirtyroom += dst->sorted - dst->length; - dst->sorted = dst->length; - mdbx_tassert(parent, - parent->mt_parent || - parent->tw.dirtyroom + parent->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - - if (parent->tw.spill_pages && MDBX_PNL_SIZE(parent->tw.spill_pages) > 0 && - MDBX_PNL_MOST(parent->tw.spill_pages) >= parent->mt_next_pgno << 1) { - const MDBX_PNL ps = parent->tw.spill_pages; -#if MDBX_PNL_ASCENDING - unsigned i = MDBX_PNL_SIZE(ps); - assert(MDBX_PNL_MOST(ps) == MDBX_PNL_LAST(ps)); - do - i -= 1; - while (i && ps[i] >= parent->mt_next_pgno << 1); - MDBX_PNL_SIZE(ps) = i; -#else - assert(MDBX_PNL_MOST(ps) == MDBX_PNL_FIRST(ps)); - unsigned i = 1, len = MDBX_PNL_SIZE(ps); - while (i < len && ps[i + 1] >= parent->mt_next_pgno << 1) - ++i; - MDBX_PNL_SIZE(ps) = len -= i; - for (unsigned k = 1; k <= len; ++k) - ps[k] = ps[k + i]; -#endif - } - - /* Remove anything in our dirty list from parent's spill list */ - MDBX_DPL src = mdbx_dpl_sort(txn->tw.dirtylist); - if (likely(src->length > 0) && parent->tw.spill_pages && - MDBX_PNL_SIZE(parent->tw.spill_pages) > 0) { - MDBX_PNL sp = parent->tw.spill_pages; - assert(mdbx_pnl_check4assert(sp, txn->mt_next_pgno)); - - const unsigned len = MDBX_PNL_SIZE(parent->tw.spill_pages); - MDBX_PNL_SIZE(sp) = ~(pgno_t)0; - - /* Mark our dirty pages as deleted in parent spill list */ - unsigned r, w, i = 1; - w = r = len; - do { - pgno_t pn = src[i].pgno << 1; - while (pn > sp[r]) - r--; - if (pn == sp[r]) { - sp[r] = 1; - w = --r; - } - } while (++i <= src->length); - - /* Squash deleted pagenums if we deleted any */ - for (r = w; ++r <= len;) - if ((sp[r] & 1) == 0) - sp[++w] = sp[r]; - MDBX_PNL_SIZE(sp) = w; - assert(mdbx_pnl_check4assert(sp, txn->mt_next_pgno << 1)); - } - - /* Remove anything in our spill list from parent's dirty list */ - if (txn->tw.spill_pages && MDBX_PNL_SIZE(txn->tw.spill_pages) > 0) { - const MDBX_PNL sp = txn->tw.spill_pages; - mdbx_pnl_sort(sp); - /* Scanning in ascend order */ - const int step = MDBX_PNL_ASCENDING ? 1 : -1; - const int begin = MDBX_PNL_ASCENDING ? 1 : MDBX_PNL_SIZE(sp); - const int end = MDBX_PNL_ASCENDING ? MDBX_PNL_SIZE(sp) + 1 : 0; - mdbx_tassert(txn, sp[begin] <= sp[end - step]); - - unsigned r, w = r = mdbx_dpl_search(dst, sp[begin] >> 1); - mdbx_tassert(txn, dst->sorted == dst->length); - for (int i = begin; r <= dst->length;) { - mdbx_tassert(txn, (sp[i] & 1) == 0); - const pgno_t pgno = sp[i] >> 1; - if (dst[r].pgno < pgno) { - dst[w++] = dst[r++]; - } else if (dst[r].pgno > pgno) { - i += step; - if (i == end) - while (r <= dst->length) - dst[w++] = dst[r++]; - } else { - MDBX_page *dp = dst[r++].ptr; - if ((env->me_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(env, dp, IS_OVERFLOW(dp) ? dp->mp_pages : 1); - } - } - mdbx_tassert(txn, r == dst->length + 1); - dst->length = w; - parent->tw.dirtyroom += r - w; - } - assert(dst->sorted == dst->length); - mdbx_tassert(parent, - parent->mt_parent || - parent->tw.dirtyroom + parent->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - - unsigned d, s, l; - /* Find length of merging our dirty list with parent's */ - for (l = 0, d = dst->length, s = src->length; d > 0 && s > 0; ++l) { - const pgno_t s_pgno = src[s].pgno; - const pgno_t d_pgno = dst[d].pgno; - d -= d_pgno >= s_pgno; - s -= d_pgno <= s_pgno; - } - assert(dst->sorted == dst->length); - dst->sorted = l += d + s; - assert(dst->sorted >= dst->length); - parent->tw.dirtyroom -= dst->sorted - dst->length; - - /* Merge our dirty list into parent's */ - for (d = dst->length, s = src->length; d > 0 && s > 0; --l) { - if (dst[d].pgno > src[s].pgno) - dst[l] = dst[d--]; - else if (dst[d].pgno < src[s].pgno) - dst[l] = src[s--]; - else { - MDBX_page *dp = dst[d--].ptr; - if (dp && (env->me_flags & MDBX_WRITEMAP) == 0) - mdbx_dpage_free(env, dp, IS_OVERFLOW(dp) ? dp->mp_pgno : 1); - dst[l] = src[s--]; - } - } - if (s) { - do - dst[l--] = src[s--]; - while (s > 0); - } else if (d) { - do - dst[l--] = dst[d--]; - while (d > 0); - } - assert(l == 0); - dst->length = dst->sorted; - mdbx_free(txn->tw.dirtylist); - txn->tw.dirtylist = nullptr; - mdbx_tassert(parent, - parent->mt_parent || - parent->tw.dirtyroom + parent->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - - if (txn->tw.spill_pages) { - if (parent->tw.spill_pages) { - /* Must not fail since space was preserved above. */ - rc = mdbx_pnl_append_list(&parent->tw.spill_pages, txn->tw.spill_pages); - mdbx_assert(env, rc == MDBX_SUCCESS); - (void)rc; - mdbx_pnl_free(txn->tw.spill_pages); - mdbx_pnl_sort(parent->tw.spill_pages); - } else { - parent->tw.spill_pages = txn->tw.spill_pages; - } - } - if (parent->tw.spill_pages) - assert(mdbx_pnl_check4assert(parent->tw.spill_pages, - parent->mt_next_pgno << 1)); - - /* Append our loose page list to parent's */ - if (txn->tw.loose_pages) { - MDBX_page **lp = &parent->tw.loose_pages; - while (*lp) - lp = &(*lp)->mp_next; - *lp = txn->tw.loose_pages; - parent->tw.loose_count += txn->tw.loose_count; - } - if (txn->tw.retired2parent_pages) { - MDBX_page *mp = txn->tw.retired2parent_pages; - do { - MDBX_page *next = mp->mp_next; - rc = mdbx_page_loose(parent, mp); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - mp = next; - } while (mp); - } - - env->me_txn = parent; - parent->mt_child = NULL; - txn->mt_signature = 0; - mdbx_free(txn); - mdbx_tassert(parent, mdbx_dirtylist_check(parent)); - - /* Scan parent's loose page for suitable for refund */ - for (MDBX_page *mp = parent->tw.loose_pages; mp; mp = mp->mp_next) { - if (mp->mp_pgno == parent->mt_next_pgno - 1) { - mdbx_refund(parent); - break; - } - } - mdbx_tassert(parent, mdbx_dirtylist_check(parent)); - return MDBX_SUCCESS; - } - - mdbx_tassert(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - mdbx_cursors_eot(txn, 0); - end_mode |= MDBX_END_EOTDONE; - - if (txn->tw.dirtylist->length == 0 && - (txn->mt_flags & (MDBX_TXN_DIRTY | MDBX_TXN_SPILLS)) == 0) - goto done; - - mdbx_debug("committing txn %" PRIaTXN " %p on mdbenv %p, root page %" PRIaPGNO - "/%" PRIaPGNO, - txn->mt_txnid, (void *)txn, (void *)env, - txn->mt_dbs[MAIN_DBI].md_root, txn->mt_dbs[FREE_DBI].md_root); - - /* Update DB root pointers */ - if (txn->mt_numdbs > CORE_DBS) { - MDBX_cursor mc; - MDBX_val data; - data.iov_len = sizeof(MDBX_db); - - rc = mdbx_cursor_init(&mc, txn, MAIN_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - for (MDBX_dbi i = CORE_DBS; i < txn->mt_numdbs; i++) { - if (txn->mt_dbflags[i] & DB_DIRTY) { - if (unlikely(TXN_DBI_CHANGED(txn, i))) { - rc = MDBX_BAD_DBI; - goto fail; - } - MDBX_db *db = &txn->mt_dbs[i]; - db->md_mod_txnid = txn->mt_txnid; - data.iov_base = db; - WITH_CURSOR_TRACKING(mc, - rc = mdbx_cursor_put(&mc, &txn->mt_dbxs[i].md_name, - &data, F_SUBDATA)); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - } - } - - rc = mdbx_update_gc(txn); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - - if (mdbx_audit_enabled()) { - rc = mdbx_audit_ex(txn, MDBX_PNL_SIZE(txn->tw.retired_pages), true); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - - rc = mdbx_page_flush(txn, 0); - if (likely(rc == MDBX_SUCCESS)) { - if (txn->mt_dbs[MAIN_DBI].md_flags & DB_DIRTY) - txn->mt_dbs[MAIN_DBI].md_mod_txnid = txn->mt_txnid; - - MDBX_meta meta, *head = mdbx_meta_head(env); - meta.mm_magic_and_version = head->mm_magic_and_version; - meta.mm_extra_flags = head->mm_extra_flags; - meta.mm_validator_id = head->mm_validator_id; - meta.mm_extra_pagehdr = head->mm_extra_pagehdr; - meta.mm_pages_retired = - head->mm_pages_retired + MDBX_PNL_SIZE(txn->tw.retired_pages); - - meta.mm_geo = txn->mt_geo; - meta.mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI]; - meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; - meta.mm_canary = txn->mt_canary; - mdbx_meta_set_txnid(env, &meta, txn->mt_txnid); - - rc = mdbx_sync_locked( - env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED, &meta); - } - if (unlikely(rc != MDBX_SUCCESS)) { - env->me_flags |= MDBX_FATAL_ERROR; - goto fail; - } - - if (likely(env->me_lck)) - env->me_lck->mti_readers_refresh_flag = false; - end_mode = MDBX_END_COMMITTED | MDBX_END_UPDATE | MDBX_END_EOTDONE; - -done: - return mdbx_txn_end(txn, end_mode); - -fail: - mdbx_txn_abort(txn); - return rc; -} - -/* Read the environment parameters of a DB environment - * before mapping it into memory. */ -static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *dest, - uint64_t *filesize) { - int rc = mdbx_filesize(env->me_fd, filesize); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - memset(dest, 0, sizeof(MDBX_meta)); - dest->mm_datasync_sign = MDBX_DATASIGN_WEAK; - rc = MDBX_CORRUPTED; - - /* Read twice all meta pages so we can find the latest one. */ - unsigned loop_limit = NUM_METAS * 2; - for (unsigned loop_count = 0; loop_count < loop_limit; ++loop_count) { - /* We don't know the page size on first time. - * So, just guess it. */ - unsigned guess_pagesize = dest->mm_psize; - if (guess_pagesize == 0) - guess_pagesize = - (loop_count > NUM_METAS) ? env->me_psize : env->me_os_psize; - - const unsigned meta_number = loop_count % NUM_METAS; - const unsigned offset = guess_pagesize * meta_number; - - char buffer[MIN_PAGESIZE]; - unsigned retryleft = 42; - while (1) { - mdbx_trace("reading meta[%d]: offset %u, bytes %u, retry-left %u", - meta_number, offset, MIN_PAGESIZE, retryleft); - int err = mdbx_pread(env->me_fd, buffer, MIN_PAGESIZE, offset); - if (err != MDBX_SUCCESS) { - if (err == MDBX_ENODATA && offset == 0 && loop_count == 0 && - *filesize == 0 && (env->me_flags & MDBX_RDONLY) == 0) - mdbx_notice("read meta: empty file (%d, %s)", err, - mdbx_strerror(err)); - else - mdbx_error("read meta[%u,%u]: %i, %s", offset, MIN_PAGESIZE, err, - mdbx_strerror(err)); - return err; - } - - char again[MIN_PAGESIZE]; - err = mdbx_pread(env->me_fd, again, MIN_PAGESIZE, offset); - if (err != MDBX_SUCCESS) { - mdbx_error("read meta[%u,%u]: %i, %s", offset, MIN_PAGESIZE, err, - mdbx_strerror(err)); - return err; - } - - if (memcmp(buffer, again, MIN_PAGESIZE) == 0 || --retryleft == 0) - break; - - mdbx_verbose("meta[%u] was updated, re-read it", meta_number); - } - - MDBX_page *const page = (MDBX_page *)buffer; - MDBX_meta *const meta = page_meta(page); - if (meta->mm_magic_and_version != MDBX_DATA_MAGIC && - meta->mm_magic_and_version != MDBX_DATA_MAGIC_DEVEL) { - mdbx_error("meta[%u] has invalid magic/version %" PRIx64, meta_number, - meta->mm_magic_and_version); - return ((meta->mm_magic_and_version >> 8) != MDBX_MAGIC) - ? MDBX_INVALID - : MDBX_VERSION_MISMATCH; - } - - if (page->mp_pgno != meta_number) { - mdbx_error("meta[%u] has invalid pageno %" PRIaPGNO, meta_number, - page->mp_pgno); - return MDBX_INVALID; - } - - if (page->mp_flags != P_META) { - mdbx_error("page #%u not a meta-page", meta_number); - return MDBX_INVALID; - } - - if (!retryleft) { - mdbx_error("meta[%u] is too volatile, skip it", meta_number); - continue; - } - - /* LY: check pagesize */ - if (!is_powerof2(meta->mm_psize) || meta->mm_psize < MIN_PAGESIZE || - meta->mm_psize > MAX_PAGESIZE) { - mdbx_notice("meta[%u] has invalid pagesize (%u), skip it", meta_number, - meta->mm_psize); - rc = is_powerof2(meta->mm_psize) ? MDBX_VERSION_MISMATCH : MDBX_INVALID; - continue; - } - - if (meta_number == 0 && guess_pagesize != meta->mm_psize) { - dest->mm_psize = meta->mm_psize; - mdbx_verbose("meta[%u] took pagesize %u", meta_number, meta->mm_psize); - } - - if (safe64_read(&meta->mm_txnid_a) != safe64_read(&meta->mm_txnid_b)) { - mdbx_warning("meta[%u] not completely updated, skip it", meta_number); - continue; - } - - /* LY: check signature as a checksum */ - if (META_IS_STEADY(meta) && - meta->mm_datasync_sign != mdbx_meta_sign(meta)) { - mdbx_notice("meta[%u] has invalid steady-checksum (0x%" PRIx64 - " != 0x%" PRIx64 "), skip it", - meta_number, meta->mm_datasync_sign, mdbx_meta_sign(meta)); - continue; - } - - mdbx_debug("read meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO - ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO - " +%u -%u, txn_id %" PRIaTXN ", %s", - page->mp_pgno, meta->mm_dbs[MAIN_DBI].md_root, - meta->mm_dbs[FREE_DBI].md_root, meta->mm_geo.lower, - meta->mm_geo.next, meta->mm_geo.now, meta->mm_geo.upper, - meta->mm_geo.grow, meta->mm_geo.shrink, - meta->mm_txnid_a.inconsistent, mdbx_durable_str(meta)); - - /* LY: check min-pages value */ - if (meta->mm_geo.lower < MIN_PAGENO || meta->mm_geo.lower > MAX_PAGENO) { - mdbx_notice("meta[%u] has invalid min-pages (%" PRIaPGNO "), skip it", - meta_number, meta->mm_geo.lower); - rc = MDBX_INVALID; - continue; - } - - /* LY: check max-pages value */ - if (meta->mm_geo.upper < MIN_PAGENO || meta->mm_geo.upper > MAX_PAGENO || - meta->mm_geo.upper < meta->mm_geo.lower) { - mdbx_notice("meta[%u] has invalid max-pages (%" PRIaPGNO "), skip it", - meta_number, meta->mm_geo.upper); - rc = MDBX_INVALID; - continue; - } - - /* LY: check last_pgno */ - if (meta->mm_geo.next < MIN_PAGENO || meta->mm_geo.next - 1 > MAX_PAGENO) { - mdbx_notice("meta[%u] has invalid next-pageno (%" PRIaPGNO "), skip it", - meta_number, meta->mm_geo.next); - rc = MDBX_CORRUPTED; - continue; - } - - /* LY: check filesize & used_bytes */ - const uint64_t used_bytes = meta->mm_geo.next * (uint64_t)meta->mm_psize; - if (used_bytes > *filesize) { - /* Here could be a race with DB-shrinking performed by other process */ - rc = mdbx_filesize(env->me_fd, filesize); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - if (used_bytes > *filesize) { - mdbx_notice("meta[%u] used-bytes (%" PRIu64 - ") beyond filesize (%" PRIu64 "), skip it", - meta_number, used_bytes, *filesize); - rc = MDBX_CORRUPTED; - continue; - } - } - - /* LY: check mapsize limits */ - const uint64_t mapsize_min = meta->mm_geo.lower * (uint64_t)meta->mm_psize; - STATIC_ASSERT(MAX_MAPSIZE < PTRDIFF_MAX - MAX_PAGESIZE); - STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE); - if (mapsize_min < MIN_MAPSIZE || mapsize_min > MAX_MAPSIZE) { - mdbx_notice("meta[%u] has invalid min-mapsize (%" PRIu64 "), skip it", - meta_number, mapsize_min); - rc = MDBX_VERSION_MISMATCH; - continue; - } - - const uint64_t mapsize_max = meta->mm_geo.upper * (uint64_t)meta->mm_psize; - STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE); - if (mapsize_max > MAX_MAPSIZE || - MAX_PAGENO < roundup_powerof2((size_t)mapsize_max, env->me_os_psize) / - (size_t)meta->mm_psize) { - if (meta->mm_geo.next - 1 > MAX_PAGENO || used_bytes > MAX_MAPSIZE) { - mdbx_notice("meta[%u] has too large max-mapsize (%" PRIu64 "), skip it", - meta_number, mapsize_max); - rc = MDBX_TOO_LARGE; - continue; - } - - /* allow to open large DB from a 32-bit environment */ - mdbx_notice("meta[%u] has too large max-mapsize (%" PRIu64 "), " - "but size of used space still acceptable (%" PRIu64 ")", - meta_number, mapsize_max, used_bytes); - meta->mm_geo.upper = (pgno_t)(MAX_MAPSIZE / meta->mm_psize); - } - - /* LY: check and silently put mm_geo.now into [geo.lower...geo.upper]. - * - * Copy-with-compaction by previous version of libmdbx could produce DB-file - * less than meta.geo.lower bound, in case actual filling is low or no data - * at all. This is not a problem as there is no damage or loss of data. - * Therefore it is better not to consider such situation as an error, but - * silently correct it. */ - if (meta->mm_geo.now < meta->mm_geo.lower) - meta->mm_geo.now = meta->mm_geo.lower; - if (meta->mm_geo.now > meta->mm_geo.upper && - meta->mm_geo.next <= meta->mm_geo.upper) - meta->mm_geo.now = meta->mm_geo.upper; - - if (meta->mm_geo.next > meta->mm_geo.now) { - mdbx_notice("meta[%u] next-pageno (%" PRIaPGNO - ") is beyond end-pgno (%" PRIaPGNO "), skip it", - meta_number, meta->mm_geo.next, meta->mm_geo.now); - rc = MDBX_CORRUPTED; - continue; - } - - /* LY: GC root */ - if (meta->mm_dbs[FREE_DBI].md_root == P_INVALID) { - if (meta->mm_dbs[FREE_DBI].md_branch_pages || - meta->mm_dbs[FREE_DBI].md_depth || - meta->mm_dbs[FREE_DBI].md_entries || - meta->mm_dbs[FREE_DBI].md_leaf_pages || - meta->mm_dbs[FREE_DBI].md_overflow_pages) { - mdbx_notice("meta[%u] has false-empty GC, skip it", meta_number); - rc = MDBX_CORRUPTED; - continue; - } - } else if (meta->mm_dbs[FREE_DBI].md_root >= meta->mm_geo.next) { - mdbx_notice("meta[%u] has invalid GC-root %" PRIaPGNO ", skip it", - meta_number, meta->mm_dbs[FREE_DBI].md_root); - rc = MDBX_CORRUPTED; - continue; - } - - /* LY: MainDB root */ - if (meta->mm_dbs[MAIN_DBI].md_root == P_INVALID) { - if (meta->mm_dbs[MAIN_DBI].md_branch_pages || - meta->mm_dbs[MAIN_DBI].md_depth || - meta->mm_dbs[MAIN_DBI].md_entries || - meta->mm_dbs[MAIN_DBI].md_leaf_pages || - meta->mm_dbs[MAIN_DBI].md_overflow_pages) { - mdbx_notice("meta[%u] has false-empty maindb", meta_number); - rc = MDBX_CORRUPTED; - continue; - } - } else if (meta->mm_dbs[MAIN_DBI].md_root >= meta->mm_geo.next) { - mdbx_notice("meta[%u] has invalid maindb-root %" PRIaPGNO ", skip it", - meta_number, meta->mm_dbs[MAIN_DBI].md_root); - rc = MDBX_CORRUPTED; - continue; - } - - if (safe64_read(&meta->mm_txnid_a) == 0) { - mdbx_warning("meta[%u] has zero txnid, skip it", meta_number); - continue; - } - - if (mdbx_meta_ot(prefer_noweak, env, dest, meta)) { - *dest = *meta; - if (META_IS_WEAK(dest)) - loop_limit += 1; /* LY: should re-read to hush race with update */ - mdbx_verbose("latch meta[%u]", meta_number); - } - } - - if (META_IS_WEAK(dest)) { - mdbx_error("%s", "no usable meta-pages, database is corrupted"); - return rc; - } - - return MDBX_SUCCESS; -} - -static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model, - unsigned num) { - - mdbx_ensure(env, is_powerof2(env->me_psize)); - mdbx_ensure(env, env->me_psize >= MIN_PAGESIZE); - mdbx_ensure(env, env->me_psize <= MAX_PAGESIZE); - mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE); - mdbx_ensure(env, env->me_dbgeo.upper <= MAX_MAPSIZE); - mdbx_ensure(env, env->me_dbgeo.now >= env->me_dbgeo.lower); - mdbx_ensure(env, env->me_dbgeo.now <= env->me_dbgeo.upper); - - memset(model, 0, sizeof(*model)); - model->mp_pgno = num; - model->mp_flags = P_META; - MDBX_meta *const model_meta = page_meta(model); - model_meta->mm_magic_and_version = MDBX_DATA_MAGIC; - - model_meta->mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); - model_meta->mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); - model_meta->mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); - model_meta->mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); - model_meta->mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); - model_meta->mm_geo.next = NUM_METAS; - - mdbx_ensure(env, model_meta->mm_geo.lower >= MIN_PAGENO); - mdbx_ensure(env, model_meta->mm_geo.upper <= MAX_PAGENO); - mdbx_ensure(env, model_meta->mm_geo.now >= model_meta->mm_geo.lower); - mdbx_ensure(env, model_meta->mm_geo.now <= model_meta->mm_geo.upper); - mdbx_ensure(env, model_meta->mm_geo.next >= MIN_PAGENO); - mdbx_ensure(env, model_meta->mm_geo.next <= model_meta->mm_geo.now); - mdbx_ensure(env, - model_meta->mm_geo.grow == bytes2pgno(env, env->me_dbgeo.grow)); - mdbx_ensure(env, model_meta->mm_geo.shrink == - bytes2pgno(env, env->me_dbgeo.shrink)); - - model_meta->mm_psize = env->me_psize; - model_meta->mm_flags = (uint16_t)env->me_flags; - model_meta->mm_flags |= - MDBX_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */ - model_meta->mm_dbs[FREE_DBI].md_root = P_INVALID; - model_meta->mm_dbs[MAIN_DBI].md_root = P_INVALID; - mdbx_meta_set_txnid(env, model_meta, MIN_TXNID + num); - model_meta->mm_datasync_sign = mdbx_meta_sign(model_meta); - return (MDBX_page *)((uint8_t *)model + env->me_psize); -} - -/* Fill in most of the zeroed meta-pages for an empty database environment. - * Return pointer to recenly (head) meta-page. */ -static MDBX_meta *__cold mdbx_init_metas(const MDBX_env *env, void *buffer) { - MDBX_page *page0 = (MDBX_page *)buffer; - MDBX_page *page1 = mdbx_meta_model(env, page0, 0); - MDBX_page *page2 = mdbx_meta_model(env, page1, 1); - mdbx_meta_model(env, page2, 2); - mdbx_assert(env, !mdbx_meta_eq(env, page_meta(page0), page_meta(page1))); - mdbx_assert(env, !mdbx_meta_eq(env, page_meta(page1), page_meta(page2))); - mdbx_assert(env, !mdbx_meta_eq(env, page_meta(page2), page_meta(page0))); - return page_meta(page2); -} - -static int mdbx_sync_locked(MDBX_env *env, unsigned flags, - MDBX_meta *const pending) { - mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); - MDBX_meta *const meta0 = METAPAGE(env, 0); - MDBX_meta *const meta1 = METAPAGE(env, 1); - MDBX_meta *const meta2 = METAPAGE(env, 2); - MDBX_meta *const head = mdbx_meta_head(env); - - mdbx_assert(env, mdbx_meta_eq_mask(env) == 0); - mdbx_assert(env, - pending < METAPAGE(env, 0) || pending > METAPAGE(env, NUM_METAS)); - mdbx_assert(env, (env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)) == 0); - mdbx_assert(env, !META_IS_STEADY(head) || *env->me_unsynced_pages != 0); - mdbx_assert(env, pending->mm_geo.next <= pending->mm_geo.now); - - if (flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) { - /* Check auto-sync conditions */ - const pgno_t autosync_threshold = *env->me_autosync_threshold; - const uint64_t autosync_period = *env->me_autosync_period; - if ((autosync_threshold && *env->me_unsynced_pages >= autosync_threshold) || - (autosync_period && - mdbx_osal_monotime() - *env->me_sync_timestamp >= autosync_period)) - flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED; /* force steady */ - } - - pgno_t shrink = 0; - if (flags & MDBX_SHRINK_ALLOWED) { - /* LY: check conditions to discard unused pages */ - const pgno_t largest_pgno = mdbx_find_largest( - env, (head->mm_geo.next > pending->mm_geo.next) ? head->mm_geo.next - : pending->mm_geo.next); - mdbx_assert(env, largest_pgno >= NUM_METAS); -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - const pgno_t edge = env->me_poison_edge; - if (edge > largest_pgno) { - env->me_poison_edge = largest_pgno; - VALGRIND_MAKE_MEM_NOACCESS(env->me_map + pgno2bytes(env, largest_pgno), - pgno2bytes(env, edge - largest_pgno)); - ASAN_POISON_MEMORY_REGION(env->me_map + pgno2bytes(env, largest_pgno), - pgno2bytes(env, edge - largest_pgno)); - } -#endif /* MDBX_USE_VALGRIND */ -#if defined(MADV_DONTNEED) - const size_t largest_aligned2os_bytes = - pgno_align2os_bytes(env, largest_pgno); - const pgno_t largest_aligned2os_pgno = - bytes2pgno(env, largest_aligned2os_bytes); - const pgno_t prev_discarded_pgno = *env->me_discarded_tail; - if (prev_discarded_pgno > - largest_aligned2os_pgno + - /* 1M threshold to avoid unreasonable madvise() call */ - bytes2pgno(env, MEGABYTE)) { - mdbx_notice("open-MADV_%s %u..%u", "DONTNEED", *env->me_discarded_tail, - largest_pgno); - *env->me_discarded_tail = largest_aligned2os_pgno; - const size_t prev_discarded_bytes = - pgno2bytes(env, prev_discarded_pgno) & ~(env->me_os_psize - 1); - mdbx_ensure(env, prev_discarded_bytes > largest_aligned2os_bytes); - int advise = MADV_DONTNEED; -#if defined(MADV_FREE) && \ - 0 /* MADV_FREE works for only anon vma at the moment */ - if ((env->me_flags & MDBX_WRITEMAP) && - mdbx_linux_kernel_version > 0x04050000) - advise = MADV_FREE; -#endif /* MADV_FREE */ - int err = madvise(env->me_map + largest_aligned2os_bytes, - prev_discarded_bytes - largest_aligned2os_bytes, advise) - ? errno - : MDBX_SUCCESS; - mdbx_assert(env, err == MDBX_SUCCESS); - (void)err; - } -#endif /* MADV_FREE || MADV_DONTNEED */ - - /* LY: check conditions to shrink datafile */ - const pgno_t backlog_gap = - pending->mm_dbs[FREE_DBI].md_depth + mdbx_backlog_extragap(env); - if (pending->mm_geo.shrink && pending->mm_geo.now - pending->mm_geo.next > - pending->mm_geo.shrink + backlog_gap) { - if (pending->mm_geo.now > largest_pgno && - pending->mm_geo.now - largest_pgno > - pending->mm_geo.shrink + backlog_gap) { - const pgno_t aligner = pending->mm_geo.grow ? pending->mm_geo.grow - : pending->mm_geo.shrink; - const pgno_t with_backlog_gap = largest_pgno + backlog_gap; - const pgno_t aligned = pgno_align2os_pgno( - env, with_backlog_gap + aligner - with_backlog_gap % aligner); - const pgno_t bottom = - (aligned > pending->mm_geo.lower) ? aligned : pending->mm_geo.lower; - if (pending->mm_geo.now > bottom) { - flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED; /* force steady */ - shrink = pending->mm_geo.now - bottom; - pending->mm_geo.now = bottom; - if (mdbx_meta_txnid_stable(env, head) == - pending->mm_txnid_a.inconsistent) - mdbx_meta_set_txnid( - env, pending, - safe64_txnid_next(pending->mm_txnid_a.inconsistent)); - } - } - } - } - - /* LY: step#1 - sync previously written/updated data-pages */ - int rc = *env->me_unsynced_pages ? MDBX_RESULT_TRUE /* carry non-steady */ - : MDBX_RESULT_FALSE /* carry steady */; - if (rc != MDBX_RESULT_FALSE && (flags & MDBX_NOSYNC) == 0) { - mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); - MDBX_meta *const recent_steady_meta = mdbx_meta_steady(env); - if (flags & MDBX_WRITEMAP) { - const size_t usedbytes = pgno_align2os_bytes(env, pending->mm_geo.next); - rc = mdbx_msync(&env->me_dxb_mmap, 0, usedbytes, flags & MDBX_MAPASYNC); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - rc = MDBX_RESULT_TRUE /* carry non-steady */; - if ((flags & MDBX_MAPASYNC) == 0) { - if (unlikely(pending->mm_geo.next > recent_steady_meta->mm_geo.now)) { - rc = mdbx_filesync(env->me_fd, MDBX_SYNC_SIZE); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - rc = MDBX_RESULT_FALSE /* carry steady */; - } - } else { - rc = mdbx_filesync(env->me_fd, - (pending->mm_geo.next > recent_steady_meta->mm_geo.now) - ? MDBX_SYNC_DATA | MDBX_SYNC_SIZE - : MDBX_SYNC_DATA); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } - } - - /* Steady or Weak */ - if (rc == MDBX_RESULT_FALSE /* carry steady */) { - pending->mm_datasync_sign = mdbx_meta_sign(pending); - *env->me_unsynced_pages = 0; - *env->me_sync_timestamp = mdbx_osal_monotime(); - } else { - assert(rc == MDBX_RESULT_TRUE /* carry non-steady */); - pending->mm_datasync_sign = F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC) - ? MDBX_DATASIGN_NONE - : MDBX_DATASIGN_WEAK; - } - - MDBX_meta *target = nullptr; - if (mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a.inconsistent) { - mdbx_assert(env, memcmp(&head->mm_dbs, &pending->mm_dbs, - sizeof(head->mm_dbs)) == 0); - mdbx_assert(env, memcmp(&head->mm_canary, &pending->mm_canary, - sizeof(head->mm_canary)) == 0); - mdbx_assert(env, memcmp(&head->mm_geo, &pending->mm_geo, - sizeof(pending->mm_geo)) == 0); - if (!META_IS_STEADY(head) && META_IS_STEADY(pending)) - target = head; - else { - mdbx_ensure(env, mdbx_meta_eq(env, head, pending)); - mdbx_debug("%s", "skip update meta"); - return MDBX_SUCCESS; - } - } else if (head == meta0) - target = mdbx_meta_ancient(prefer_steady, env, meta1, meta2); - else if (head == meta1) - target = mdbx_meta_ancient(prefer_steady, env, meta0, meta2); - else { - mdbx_assert(env, head == meta2); - target = mdbx_meta_ancient(prefer_steady, env, meta0, meta1); - } - - /* LY: step#2 - update meta-page. */ - mdbx_debug("writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO - ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO - " +%u -%u, txn_id %" PRIaTXN ", %s", - data_page(target)->mp_pgno, pending->mm_dbs[MAIN_DBI].md_root, - pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower, - pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper, - pending->mm_geo.grow, pending->mm_geo.shrink, - pending->mm_txnid_a.inconsistent, mdbx_durable_str(pending)); - - mdbx_debug("meta0: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO - "/%" PRIaPGNO, - (meta0 == head) ? "head" : (meta0 == target) ? "tail" : "stay", - mdbx_durable_str(meta0), mdbx_meta_txnid_fluid(env, meta0), - meta0->mm_dbs[MAIN_DBI].md_root, meta0->mm_dbs[FREE_DBI].md_root); - mdbx_debug("meta1: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO - "/%" PRIaPGNO, - (meta1 == head) ? "head" : (meta1 == target) ? "tail" : "stay", - mdbx_durable_str(meta1), mdbx_meta_txnid_fluid(env, meta1), - meta1->mm_dbs[MAIN_DBI].md_root, meta1->mm_dbs[FREE_DBI].md_root); - mdbx_debug("meta2: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO - "/%" PRIaPGNO, - (meta2 == head) ? "head" : (meta2 == target) ? "tail" : "stay", - mdbx_durable_str(meta2), mdbx_meta_txnid_fluid(env, meta2), - meta2->mm_dbs[MAIN_DBI].md_root, meta2->mm_dbs[FREE_DBI].md_root); - - mdbx_assert(env, !mdbx_meta_eq(env, pending, meta0)); - mdbx_assert(env, !mdbx_meta_eq(env, pending, meta1)); - mdbx_assert(env, !mdbx_meta_eq(env, pending, meta2)); - - mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); - mdbx_ensure(env, target == head || mdbx_meta_txnid_stable(env, target) < - pending->mm_txnid_a.inconsistent); - if (env->me_flags & MDBX_WRITEMAP) { - mdbx_jitter4testing(true); - if (likely(target != head)) { - /* LY: 'invalidate' the meta. */ - mdbx_meta_update_begin(env, target, pending->mm_txnid_a.inconsistent); - target->mm_datasync_sign = MDBX_DATASIGN_WEAK; -#ifndef NDEBUG - /* debug: provoke failure to catch a violators, but don't touch mm_psize - * and mm_flags to allow readers catch actual pagesize. */ - uint8_t *provoke_begin = (uint8_t *)&target->mm_dbs[FREE_DBI].md_root; - uint8_t *provoke_end = (uint8_t *)&target->mm_datasync_sign; - memset(provoke_begin, 0xCC, provoke_end - provoke_begin); - mdbx_jitter4testing(false); -#endif - - /* LY: update info */ - target->mm_geo = pending->mm_geo; - target->mm_dbs[FREE_DBI] = pending->mm_dbs[FREE_DBI]; - target->mm_dbs[MAIN_DBI] = pending->mm_dbs[MAIN_DBI]; - target->mm_canary = pending->mm_canary; - target->mm_pages_retired = pending->mm_pages_retired; - mdbx_jitter4testing(true); - mdbx_flush_noncoherent_cpu_writeback(); - - /* LY: 'commit' the meta */ - mdbx_meta_update_end(env, target, pending->mm_txnid_b.inconsistent); - mdbx_jitter4testing(true); - } else { - /* dangerous case (target == head), only mm_datasync_sign could - * me updated, check assertions once again */ - mdbx_ensure(env, mdbx_meta_txnid_stable(env, head) == - pending->mm_txnid_a.inconsistent && - !META_IS_STEADY(head) && META_IS_STEADY(pending)); - mdbx_ensure(env, memcmp(&head->mm_geo, &pending->mm_geo, - sizeof(head->mm_geo)) == 0); - mdbx_ensure(env, memcmp(&head->mm_dbs, &pending->mm_dbs, - sizeof(head->mm_dbs)) == 0); - mdbx_ensure(env, memcmp(&head->mm_canary, &pending->mm_canary, - sizeof(head->mm_canary)) == 0); - } - target->mm_datasync_sign = pending->mm_datasync_sign; - mdbx_flush_noncoherent_cpu_writeback(); - mdbx_jitter4testing(true); - } else { - rc = mdbx_pwrite(env->me_fd, pending, sizeof(MDBX_meta), - (uint8_t *)target - env->me_map); - if (unlikely(rc != MDBX_SUCCESS)) { - undo: - mdbx_debug("%s", "write failed, disk error?"); - /* On a failure, the pagecache still contains the new data. - * Try write some old data back, to prevent it from being used. */ - mdbx_pwrite(env->me_fd, (void *)target, sizeof(MDBX_meta), - (uint8_t *)target - env->me_map); - goto fail; - } - mdbx_invalidate_mmap_noncoherent_cache(target, sizeof(MDBX_meta)); - } - - /* LY: step#3 - sync meta-pages. */ - mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); - if ((flags & (MDBX_NOSYNC | MDBX_NOMETASYNC)) == 0) { - mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); - if (flags & MDBX_WRITEMAP) { - const size_t offset = (uint8_t *)data_page(head) - env->me_dxb_mmap.dxb; - const size_t paged_offset = offset & ~(env->me_os_psize - 1); - const size_t paged_length = roundup_powerof2( - env->me_psize + offset - paged_offset, env->me_os_psize); - rc = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, - flags & MDBX_MAPASYNC); - if (unlikely(rc != MDBX_SUCCESS)) - goto fail; - } else { - rc = mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ); - if (rc != MDBX_SUCCESS) - goto undo; - } - *env->me_meta_sync_txnid = (uint32_t)pending->mm_txnid_a.inconsistent; - } - - /* LY: shrink datafile if needed */ - if (unlikely(shrink)) { - mdbx_verbose("shrink to %" PRIaPGNO " pages (-%" PRIaPGNO ")", - pending->mm_geo.now, shrink); - rc = mdbx_mapresize(env, pending->mm_geo.now, pending->mm_geo.upper); - if (MDBX_IS_ERROR(rc)) - goto fail; - } - - return MDBX_SUCCESS; - -fail: - env->me_flags |= MDBX_FATAL_ERROR; - return rc; -} - -int __cold mdbx_env_get_maxkeysize(MDBX_env *env) { - if (!env || env->me_signature != MDBX_ME_SIGNATURE || !env->me_maxkey_limit) - return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; - return env->me_maxkey_limit; -} - -#define mdbx_nodemax(pagesize) \ - (((((pagesize)-PAGEHDRSZ) / MDBX_MINKEYS) & ~(uintptr_t)1) - sizeof(indx_t)) - -#define mdbx_maxkey(nodemax) ((nodemax)-NODESIZE - sizeof(MDBX_db)) - -#define mdbx_maxgc_ov1page(pagesize) \ - (((pagesize)-PAGEHDRSZ) / sizeof(pgno_t) - 1) - -static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) { - STATIC_ASSERT(PTRDIFF_MAX > MAX_MAPSIZE); - STATIC_ASSERT(MIN_PAGESIZE > sizeof(MDBX_page) + sizeof(MDBX_meta)); - mdbx_ensure(env, is_powerof2(pagesize)); - mdbx_ensure(env, pagesize >= MIN_PAGESIZE); - mdbx_ensure(env, pagesize <= MAX_PAGESIZE); - env->me_psize = (unsigned)pagesize; - - STATIC_ASSERT(mdbx_maxgc_ov1page(MIN_PAGESIZE) > 4); - STATIC_ASSERT(mdbx_maxgc_ov1page(MAX_PAGESIZE) < MDBX_DPL_TXNFULL); - const intptr_t maxgc_ov1page = (pagesize - PAGEHDRSZ) / sizeof(pgno_t) - 1; - mdbx_ensure(env, - maxgc_ov1page > 42 && maxgc_ov1page < (intptr_t)MDBX_DPL_TXNFULL); - env->me_maxgc_ov1page = (unsigned)maxgc_ov1page; - - STATIC_ASSERT(mdbx_nodemax(MIN_PAGESIZE) > 42); - STATIC_ASSERT(mdbx_nodemax(MAX_PAGESIZE) < UINT16_MAX); - const intptr_t nodemax = mdbx_nodemax(pagesize); - mdbx_ensure(env, nodemax > 42 && nodemax < UINT16_MAX && nodemax % 2 == 0); - env->me_nodemax = (unsigned)nodemax; - - STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) > 42); - STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) < MIN_PAGESIZE); - STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) > 42); - STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) < MAX_PAGESIZE); - const intptr_t maxkey_limit = mdbx_maxkey(env->me_nodemax); - mdbx_ensure(env, maxkey_limit > 42 && (size_t)maxkey_limit < pagesize && - maxkey_limit % 2 == 0); - env->me_maxkey_limit = (unsigned)maxkey_limit; - - env->me_psize2log = log2n(pagesize); - mdbx_assert(env, pgno2bytes(env, 1) == pagesize); - mdbx_assert(env, bytes2pgno(env, pagesize + pagesize) == 2); -} - -int __cold mdbx_env_create(MDBX_env **penv) { - MDBX_env *env = mdbx_calloc(1, sizeof(MDBX_env)); - if (unlikely(!env)) - return MDBX_ENOMEM; - - env->me_maxreaders = DEFAULT_READERS; - env->me_maxdbs = env->me_numdbs = CORE_DBS; - env->me_fd = INVALID_HANDLE_VALUE; - env->me_lfd = INVALID_HANDLE_VALUE; - env->me_pid = mdbx_getpid(); - - int rc; - const size_t os_psize = mdbx_syspagesize(); - if (unlikely(!is_powerof2(os_psize) || os_psize < MIN_PAGESIZE)) { - mdbx_error("unsuitable system pagesize %" PRIuPTR, os_psize); - rc = MDBX_INCOMPATIBLE; - goto bailout; - } - env->me_os_psize = (unsigned)os_psize; - mdbx_setup_pagesize(env, env->me_os_psize); - - rc = mdbx_fastmutex_init(&env->me_dbi_lock); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - -#if defined(_WIN32) || defined(_WIN64) - mdbx_srwlock_Init(&env->me_remap_guard); - InitializeCriticalSection(&env->me_windowsbug_lock); -#else - rc = mdbx_fastmutex_init(&env->me_remap_guard); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_fastmutex_destroy(&env->me_dbi_lock); - goto bailout; - } - rc = mdbx_fastmutex_init(&env->me_lckless_stub.wmutex); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_fastmutex_destroy(&env->me_remap_guard); - mdbx_fastmutex_destroy(&env->me_dbi_lock); - goto bailout; - } -#endif /* Windows */ - - VALGRIND_CREATE_MEMPOOL(env, 0, 0); - env->me_signature = MDBX_ME_SIGNATURE; - *penv = env; - return MDBX_SUCCESS; - -bailout: - mdbx_free(env); - *penv = nullptr; - return rc; -} - -__cold LIBMDBX_API int -mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, - intptr_t size_upper, intptr_t growth_step, - intptr_t shrink_threshold, intptr_t pagesize) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) - env->me_flags |= MDBX_FATAL_ERROR; -#endif /* MDBX_TXN_CHECKPID */ - - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) - return MDBX_PANIC; - - const bool inside_txn = - (env->me_txn0 && env->me_txn0->mt_owner == mdbx_thread_self()); - -#if MDBX_DEBUG - if (growth_step < 0) - growth_step = 1; - if (shrink_threshold < 0) - shrink_threshold = 1; -#endif - - bool need_unlock = false; - int rc = MDBX_PROBLEM; - if (env->me_map) { - /* env already mapped */ - if (unlikely(env->me_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - if (!inside_txn) { - int err = mdbx_txn_lock(env, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - need_unlock = true; - } - MDBX_meta *head = mdbx_meta_head(env); - if (!inside_txn) { - env->me_txn0->mt_txnid = meta_txnid(env, head, false); - mdbx_find_oldest(env->me_txn0); - } - - /* get untouched params from DB */ - if (pagesize < 0) - pagesize = env->me_psize; - if (size_lower < 0) - size_lower = pgno2bytes(env, head->mm_geo.lower); - if (size_now < 0) - size_now = pgno2bytes(env, head->mm_geo.now); - if (size_upper < 0) - size_upper = pgno2bytes(env, head->mm_geo.upper); - if (growth_step < 0) - growth_step = pgno2bytes(env, head->mm_geo.grow); - if (shrink_threshold < 0) - shrink_threshold = pgno2bytes(env, head->mm_geo.shrink); - - if (pagesize != (intptr_t)env->me_psize) { - rc = MDBX_EINVAL; - goto bailout; - } - const size_t usedbytes = - pgno2bytes(env, mdbx_find_largest(env, head->mm_geo.next)); - if ((size_t)size_upper < usedbytes) { - rc = MDBX_MAP_FULL; - goto bailout; - } - if ((size_t)size_now < usedbytes) - size_now = usedbytes; - } else { - /* env NOT yet mapped */ - if (unlikely(inside_txn)) - return MDBX_PANIC; - - if (pagesize < 0) { - pagesize = env->me_os_psize; - if ((uintptr_t)pagesize > MAX_PAGESIZE) - pagesize = MAX_PAGESIZE; - mdbx_assert(env, (uintptr_t)pagesize >= MIN_PAGESIZE); - } - } - - if (pagesize == 0) - pagesize = MIN_PAGESIZE; - else if (pagesize == INTPTR_MAX) - pagesize = MAX_PAGESIZE; - - if (pagesize < (intptr_t)MIN_PAGESIZE || pagesize > (intptr_t)MAX_PAGESIZE || - !is_powerof2(pagesize)) { - rc = MDBX_EINVAL; - goto bailout; - } - - if (size_lower <= 0) { - size_lower = MIN_MAPSIZE; - if (MIN_MAPSIZE / pagesize < MIN_PAGENO) - size_lower = MIN_PAGENO * pagesize; - } - - if (size_now <= 0) { - size_now = DEFAULT_MAPSIZE; - if (size_now < size_lower) - size_now = size_lower; - if (size_upper >= size_lower && size_now > size_upper) - size_now = size_upper; - } - - if (size_upper <= 0) { - if ((size_t)size_now >= MAX_MAPSIZE / 2) - size_upper = MAX_MAPSIZE; - else if (MAX_MAPSIZE != MAX_MAPSIZE32 && - (size_t)size_now >= MAX_MAPSIZE32 / 2 && - (size_t)size_now <= MAX_MAPSIZE32 / 4 * 3) - size_upper = MAX_MAPSIZE32; - else { - size_upper = size_now + size_now; - if ((size_t)size_upper < DEFAULT_MAPSIZE * 2) - size_upper = DEFAULT_MAPSIZE * 2; - } - if ((size_t)size_upper / pagesize > MAX_PAGENO) - size_upper = pagesize * MAX_PAGENO; - } - - if (unlikely(size_lower < (intptr_t)MIN_MAPSIZE || size_lower > size_upper)) { - rc = MDBX_EINVAL; - goto bailout; - } - - if ((uint64_t)size_lower / pagesize < MIN_PAGENO) { - rc = MDBX_EINVAL; - goto bailout; - } - - if (unlikely((size_t)size_upper > MAX_MAPSIZE || - (uint64_t)size_upper / pagesize > MAX_PAGENO)) { - rc = MDBX_TOO_LARGE; - goto bailout; - } - - size_lower = roundup_powerof2(size_lower, env->me_os_psize); - size_upper = roundup_powerof2(size_upper, env->me_os_psize); - size_now = roundup_powerof2(size_now, env->me_os_psize); - - /* LY: подбираем значение size_upper: - * - кратное размеру ÑиÑтемной Ñтраницы - * - без Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñ MAX_MAPSIZE и MAX_PAGENO */ - while (unlikely((size_t)size_upper > MAX_MAPSIZE || - (uint64_t)size_upper / pagesize > MAX_PAGENO)) { - if ((size_t)size_upper < env->me_os_psize + MIN_MAPSIZE || - (size_t)size_upper < env->me_os_psize * (MIN_PAGENO + 1)) { - /* паранойа на Ñлучай Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ невероÑтных значениÑÑ… */ - rc = MDBX_EINVAL; - goto bailout; - } - size_upper -= env->me_os_psize; - if ((size_t)size_upper < (size_t)size_lower) - size_lower = size_upper; - } - mdbx_assert(env, (size_upper - size_lower) % env->me_os_psize == 0); - - if (size_now < size_lower) - size_now = size_lower; - if (size_now > size_upper) - size_now = size_upper; - - if (growth_step < 0) { - growth_step = ((size_t)(size_upper - size_lower)) / 42; - if (growth_step > size_lower) - growth_step = size_lower; - if (growth_step < 65536) - growth_step = 65536; - if ((size_t)growth_step > MEGABYTE * 16) - growth_step = MEGABYTE * 16; - } - if (growth_step == 0 && shrink_threshold > 0) - growth_step = 1; - growth_step = roundup_powerof2(growth_step, env->me_os_psize); - if (bytes2pgno(env, growth_step) > UINT16_MAX) - growth_step = pgno2bytes(env, UINT16_MAX); - - if (shrink_threshold < 0) - shrink_threshold = growth_step + growth_step; - shrink_threshold = roundup_powerof2(shrink_threshold, env->me_os_psize); - if (bytes2pgno(env, shrink_threshold) > UINT16_MAX) - shrink_threshold = pgno2bytes(env, UINT16_MAX); - - /* save user's geo-params for future open/create */ - env->me_dbgeo.lower = size_lower; - env->me_dbgeo.now = size_now; - env->me_dbgeo.upper = size_upper; - env->me_dbgeo.grow = growth_step; - env->me_dbgeo.shrink = shrink_threshold; - rc = MDBX_SUCCESS; - - mdbx_ensure(env, pagesize >= MIN_PAGESIZE); - mdbx_ensure(env, pagesize <= MAX_PAGESIZE); - mdbx_ensure(env, is_powerof2(pagesize)); - mdbx_ensure(env, is_powerof2(env->me_os_psize)); - - mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE); - mdbx_ensure(env, env->me_dbgeo.lower / pagesize >= MIN_PAGENO); - mdbx_ensure(env, env->me_dbgeo.lower % pagesize == 0); - mdbx_ensure(env, env->me_dbgeo.lower % env->me_os_psize == 0); - - mdbx_ensure(env, env->me_dbgeo.upper <= MAX_MAPSIZE); - mdbx_ensure(env, env->me_dbgeo.upper / pagesize <= MAX_PAGENO); - mdbx_ensure(env, env->me_dbgeo.upper % pagesize == 0); - mdbx_ensure(env, env->me_dbgeo.upper % env->me_os_psize == 0); - - mdbx_ensure(env, env->me_dbgeo.now >= env->me_dbgeo.lower); - mdbx_ensure(env, env->me_dbgeo.now <= env->me_dbgeo.upper); - mdbx_ensure(env, env->me_dbgeo.now % pagesize == 0); - mdbx_ensure(env, env->me_dbgeo.now % env->me_os_psize == 0); - - mdbx_ensure(env, env->me_dbgeo.grow % pagesize == 0); - mdbx_ensure(env, env->me_dbgeo.grow % env->me_os_psize == 0); - mdbx_ensure(env, env->me_dbgeo.shrink % pagesize == 0); - mdbx_ensure(env, env->me_dbgeo.shrink % env->me_os_psize == 0); - - if (env->me_map) { - /* apply new params to opened environment */ - mdbx_ensure(env, pagesize == (intptr_t)env->me_psize); - MDBX_meta meta; - MDBX_meta *head = nullptr; - const mdbx_geo_t *current_geo; - if (inside_txn) { - current_geo = &env->me_txn->mt_geo; - } else { - head = mdbx_meta_head(env); - meta = *head; - current_geo = &meta.mm_geo; - } - - mdbx_geo_t new_geo; - new_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); - new_geo.now = bytes2pgno(env, env->me_dbgeo.now); - new_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); - new_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); - new_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); - new_geo.next = current_geo->next; - - mdbx_ensure(env, - pgno_align2os_bytes(env, new_geo.lower) == env->me_dbgeo.lower); - mdbx_ensure(env, - pgno_align2os_bytes(env, new_geo.upper) == env->me_dbgeo.upper); - mdbx_ensure(env, - pgno_align2os_bytes(env, new_geo.now) == env->me_dbgeo.now); - mdbx_ensure(env, - pgno_align2os_bytes(env, new_geo.grow) == env->me_dbgeo.grow); - mdbx_ensure(env, pgno_align2os_bytes(env, new_geo.shrink) == - env->me_dbgeo.shrink); - - mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE); - mdbx_ensure(env, new_geo.lower >= MIN_PAGENO); - mdbx_ensure(env, env->me_dbgeo.upper <= MAX_MAPSIZE); - mdbx_ensure(env, new_geo.upper <= MAX_PAGENO); - mdbx_ensure(env, new_geo.now >= new_geo.next); - mdbx_ensure(env, new_geo.upper >= new_geo.now); - mdbx_ensure(env, new_geo.now >= new_geo.lower); - - if (memcmp(current_geo, &new_geo, sizeof(mdbx_geo_t)) != 0) { -#if defined(_WIN32) || defined(_WIN64) - /* Was DB shrinking disabled before and now it will be enabled? */ - if (new_geo.lower < new_geo.upper && new_geo.shrink && - !(current_geo->lower < current_geo->upper && current_geo->shrink)) { - if (!env->me_lck) { - rc = MDBX_EPERM; - goto bailout; - } - rc = mdbx_rdt_lock(env); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - - /* Check if there are any reading threads that do not use the SRWL */ - const size_t CurrentTid = GetCurrentThreadId(); - const MDBX_reader *const begin = env->me_lck->mti_readers; - const MDBX_reader *const end = begin + env->me_lck->mti_numreaders; - for (const MDBX_reader *reader = begin; reader < end; ++reader) { - if (reader->mr_pid == env->me_pid && reader->mr_tid && - reader->mr_tid != CurrentTid) { - /* At least one thread may don't use SRWL */ - rc = MDBX_EPERM; - break; - } - } - - mdbx_rdt_unlock(env); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - } -#endif - - if (new_geo.now != current_geo->now || - new_geo.upper != current_geo->upper) { - rc = mdbx_mapresize(env, new_geo.now, new_geo.upper); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - mdbx_assert(env, (head == nullptr) == inside_txn); - if (head) - head = /* base address could be changed */ mdbx_meta_head(env); - } - if (inside_txn) { - env->me_txn->mt_geo = new_geo; - if ((env->me_txn->mt_flags & MDBX_TXN_DIRTY) == 0) { - env->me_txn->mt_flags |= MDBX_TXN_DIRTY; - *env->me_unsynced_pages += 1; - } - } else { - *env->me_unsynced_pages += 1; - mdbx_meta_set_txnid( - env, &meta, safe64_txnid_next(mdbx_meta_txnid_stable(env, head))); - rc = mdbx_sync_locked(env, env->me_flags, &meta); - } - } - } else if (pagesize != (intptr_t)env->me_psize) { - mdbx_setup_pagesize(env, pagesize); - } - -bailout: - if (need_unlock) - mdbx_txn_unlock(env); - return rc; -} - -int __cold mdbx_env_set_mapsize(MDBX_env *env, size_t size) { - return mdbx_env_set_geometry(env, size, size, size, -1, -1, -1); -} - -int __cold mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { - if (unlikely(dbs > MAX_DBI)) - return MDBX_EINVAL; - - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(env->me_map)) - return MDBX_EPERM; - - env->me_maxdbs = dbs + CORE_DBS; - return MDBX_SUCCESS; -} - -int __cold mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) { - if (unlikely(readers < 1 || readers > MDBX_READERS_LIMIT)) - return MDBX_EINVAL; - - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(env->me_map)) - return MDBX_EPERM; - - env->me_maxreaders = readers; - return MDBX_SUCCESS; -} - -int __cold mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers) { - if (!env || !readers) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - *readers = env->me_maxreaders; - return MDBX_SUCCESS; -} - -/* Further setup required for opening an MDBX environment */ -static int __cold mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { - uint64_t filesize_before; - MDBX_meta meta; - int rc = MDBX_RESULT_FALSE; - int err = mdbx_read_header(env, &meta, &filesize_before); - if (unlikely(err != MDBX_SUCCESS)) { - if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE || err != MDBX_ENODATA || - (env->me_flags & MDBX_RDONLY) != 0) - return err; - - mdbx_debug("%s", "create new database"); - rc = /* new database */ MDBX_RESULT_TRUE; - - if (!env->me_dbgeo.now) { - /* set defaults if not configured */ - err = mdbx_env_set_mapsize(env, DEFAULT_MAPSIZE); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - - void *buffer = mdbx_calloc(NUM_METAS, env->me_psize); - if (!buffer) - return MDBX_ENOMEM; - - meta = *mdbx_init_metas(env, buffer); - err = mdbx_pwrite(env->me_fd, buffer, env->me_psize * NUM_METAS, 0); - mdbx_free(buffer); - if (unlikely(err != MDBX_SUCCESS)) - return err; - - err = mdbx_ftruncate(env->me_fd, filesize_before = env->me_dbgeo.now); - if (unlikely(err != MDBX_SUCCESS)) - return err; - -#ifndef NDEBUG /* just for checking */ - err = mdbx_read_header(env, &meta, &filesize_before); - if (unlikely(err != MDBX_SUCCESS)) - return err; -#endif - } - - mdbx_verbose("header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO - "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO - " +%u -%u, txn_id %" PRIaTXN ", %s", - meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, - meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, - meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, - meta.mm_txnid_a.inconsistent, mdbx_durable_str(&meta)); - - mdbx_setup_pagesize(env, meta.mm_psize); - const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next); - const size_t used_aligned2os_bytes = - roundup_powerof2(used_bytes, env->me_os_psize); - if ((env->me_flags & MDBX_RDONLY) /* readonly */ - || lck_rc != MDBX_RESULT_TRUE /* not exclusive */) { - /* use present params from db */ - const size_t pagesize = meta.mm_psize; - err = mdbx_env_set_geometry( - env, meta.mm_geo.lower * pagesize, meta.mm_geo.now * pagesize, - meta.mm_geo.upper * pagesize, meta.mm_geo.grow * pagesize, - meta.mm_geo.shrink * pagesize, meta.mm_psize); - if (unlikely(err != MDBX_SUCCESS)) { - mdbx_error("%s", "could not use present dbsize-params from db"); - return MDBX_INCOMPATIBLE; - } - } else if (env->me_dbgeo.now) { - /* silently growth to last used page */ - if (env->me_dbgeo.now < used_aligned2os_bytes) - env->me_dbgeo.now = used_aligned2os_bytes; - if (env->me_dbgeo.upper < used_aligned2os_bytes) - env->me_dbgeo.upper = used_aligned2os_bytes; - - /* apply preconfigured params, but only if substantial changes: - * - upper or lower limit changes - * - shrink threshold or growth step - * But ignore change just a 'now/current' size. */ - if (bytes_align2os_bytes(env, env->me_dbgeo.upper) != - pgno2bytes(env, meta.mm_geo.upper) || - bytes_align2os_bytes(env, env->me_dbgeo.lower) != - pgno2bytes(env, meta.mm_geo.lower) || - bytes_align2os_bytes(env, env->me_dbgeo.shrink) != - pgno2bytes(env, meta.mm_geo.shrink) || - bytes_align2os_bytes(env, env->me_dbgeo.grow) != - pgno2bytes(env, meta.mm_geo.grow)) { - - if (env->me_dbgeo.shrink && env->me_dbgeo.now > used_bytes) - /* pre-shrink if enabled */ - env->me_dbgeo.now = used_bytes + env->me_dbgeo.shrink - - used_bytes % env->me_dbgeo.shrink; - - err = mdbx_env_set_geometry(env, env->me_dbgeo.lower, env->me_dbgeo.now, - env->me_dbgeo.upper, env->me_dbgeo.grow, - env->me_dbgeo.shrink, meta.mm_psize); - if (unlikely(err != MDBX_SUCCESS)) { - mdbx_error("%s", "could not apply preconfigured dbsize-params to db"); - return MDBX_INCOMPATIBLE; - } - - /* update meta fields */ - meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); - meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); - meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); - meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); - meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); - - mdbx_verbose("amended: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO - "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO - " +%u -%u, txn_id %" PRIaTXN ", %s", - meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, - meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, - meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, - meta.mm_txnid_a.inconsistent, mdbx_durable_str(&meta)); - } else { - /* fetch back 'now/current' size, since it was ignored during comparison - * and may differ. */ - env->me_dbgeo.now = pgno_align2os_bytes(env, meta.mm_geo.now); - } - mdbx_ensure(env, meta.mm_geo.now >= meta.mm_geo.next); - } else { - /* geo-params are not pre-configured by user, - * get current values from the meta. */ - env->me_dbgeo.now = pgno2bytes(env, meta.mm_geo.now); - env->me_dbgeo.lower = pgno2bytes(env, meta.mm_geo.lower); - env->me_dbgeo.upper = pgno2bytes(env, meta.mm_geo.upper); - env->me_dbgeo.grow = pgno2bytes(env, meta.mm_geo.grow); - env->me_dbgeo.shrink = pgno2bytes(env, meta.mm_geo.shrink); - } - - mdbx_ensure(env, - pgno_align2os_bytes(env, meta.mm_geo.now) == env->me_dbgeo.now); - mdbx_ensure(env, env->me_dbgeo.now >= used_bytes); - if (unlikely(filesize_before != env->me_dbgeo.now)) { - if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE) { - mdbx_verbose("filesize mismatch (expect %" PRIuPTR "b/%" PRIaPGNO - "p, have %" PRIu64 "b/%" PRIaPGNO "p), " - "assume other process working", - env->me_dbgeo.now, bytes2pgno(env, env->me_dbgeo.now), - filesize_before, bytes2pgno(env, (size_t)filesize_before)); - } else { - mdbx_notice("filesize mismatch (expect %" PRIuSIZE "b/%" PRIaPGNO - "p, have %" PRIu64 "b/%" PRIaPGNO "p)", - env->me_dbgeo.now, bytes2pgno(env, env->me_dbgeo.now), - filesize_before, bytes2pgno(env, (size_t)filesize_before)); - if (filesize_before < used_bytes) { - mdbx_error("last-page beyond end-of-file (last %" PRIaPGNO - ", have %" PRIaPGNO ")", - meta.mm_geo.next, bytes2pgno(env, (size_t)filesize_before)); - return MDBX_CORRUPTED; - } - - if (env->me_flags & MDBX_RDONLY) { - if (filesize_before & (env->me_os_psize - 1)) { - mdbx_error("%s", "filesize should be rounded-up to system page"); - return MDBX_WANNA_RECOVERY; - } - mdbx_warning("%s", "ignore filesize mismatch in readonly-mode"); - } else { - mdbx_verbose("will resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO - " pages", - env->me_dbgeo.now, bytes2pgno(env, env->me_dbgeo.now)); - } - } - } - - err = mdbx_mmap(env->me_flags, &env->me_dxb_mmap, env->me_dbgeo.now, - env->me_dbgeo.upper, lck_rc); - if (unlikely(err != MDBX_SUCCESS)) - return err; - -#if defined(MADV_DODUMP) && defined(MADV_DONTDUMP) - const size_t meta_length = pgno2bytes(env, NUM_METAS); - (void)madvise(env->me_map, meta_length, MADV_DODUMP); - (void)madvise(env->me_map + meta_length, env->me_dxb_mmap.limit - meta_length, - (mdbx_runtime_flags & MDBX_DBG_DUMP) ? MADV_DODUMP - : MADV_DONTDUMP); -#endif - - *env->me_discarded_tail = bytes2pgno(env, used_aligned2os_bytes); - if (used_aligned2os_bytes < env->me_dxb_mmap.current) { -#if defined(MADV_REMOVE) - if (lck_rc && (env->me_flags & MDBX_WRITEMAP) != 0) { - mdbx_notice("open-MADV_%s %u..%u", "REMOVE", *env->me_discarded_tail, - bytes2pgno(env, env->me_dxb_mmap.current)); - (void)madvise(env->me_map + used_aligned2os_bytes, - env->me_dxb_mmap.current - used_aligned2os_bytes, - MADV_REMOVE); - } -#endif /* MADV_REMOVE */ -#if defined(MADV_DONTNEED) - mdbx_notice("open-MADV_%s %u..%u", "DONTNEED", *env->me_discarded_tail, - bytes2pgno(env, env->me_dxb_mmap.current)); - (void)madvise(env->me_map + used_aligned2os_bytes, - env->me_dxb_mmap.current - used_aligned2os_bytes, - MADV_DONTNEED); -#elif defined(POSIX_MADV_DONTNEED) - (void)madvise(env->me_map + used_aligned2os_bytes, - env->me_dxb_mmap.current - used_aligned2os_bytes, - POSIX_MADV_DONTNEED); -#elif defined(POSIX_FADV_DONTNEED) - (void)posix_fadvise(env->me_fd, used_aligned2os_bytes, - env->me_dxb_mmap.current - used_aligned2os_bytes, - POSIX_FADV_DONTNEED); -#endif /* MADV_DONTNEED */ - } - -#ifdef MDBX_USE_VALGRIND - env->me_valgrind_handle = - VALGRIND_CREATE_BLOCK(env->me_map, env->me_dxb_mmap.limit, "mdbx"); -#endif - - const bool readahead = (env->me_flags & MDBX_NORDAHEAD) == 0 && - mdbx_is_readahead_reasonable(env->me_dxb_mmap.current, - 0) == MDBX_RESULT_TRUE; - err = mdbx_set_readahead(env, 0, env->me_dxb_mmap.current, readahead); - if (err != MDBX_SUCCESS) - return err; - - mdbx_assert(env, used_bytes >= pgno2bytes(env, NUM_METAS) && - used_bytes <= env->me_dxb_mmap.limit); -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - VALGRIND_MAKE_MEM_NOACCESS(env->me_map + used_bytes, - env->me_dxb_mmap.limit - used_bytes); - ASAN_POISON_MEMORY_REGION(env->me_map + used_bytes, - env->me_dxb_mmap.limit - used_bytes); - env->me_poison_edge = bytes2pgno(env, env->me_dxb_mmap.limit); -#endif /* MDBX_USE_VALGRIND */ - - /* NOTE: AddressSanitizer (at least GCC 7.x, 8.x) could generate - * false-positive alarm here. I have no other explanation for this - * except due to an internal ASAN error, as the problem is reproduced - * in a single-threaded application under the active assert() above. */ - const unsigned meta_clash_mask = mdbx_meta_eq_mask(env); - if (meta_clash_mask) { - mdbx_error("meta-pages are clashed: mask 0x%d", meta_clash_mask); - return MDBX_WANNA_RECOVERY; - } - - while (1) { - MDBX_meta *head = mdbx_meta_head(env); - const txnid_t head_txnid = mdbx_meta_txnid_fluid(env, head); - if (head_txnid == meta.mm_txnid_a.inconsistent) - break; - - if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) { - mdbx_assert(env, META_IS_STEADY(&meta) && !META_IS_STEADY(head)); - if (env->me_flags & MDBX_RDONLY) { - mdbx_error("rollback needed: (from head %" PRIaTXN - " to steady %" PRIaTXN "), but unable in read-only mode", - head_txnid, meta.mm_txnid_a.inconsistent); - return MDBX_WANNA_RECOVERY /* LY: could not recovery/rollback */; - } - - const MDBX_meta *const meta0 = METAPAGE(env, 0); - const MDBX_meta *const meta1 = METAPAGE(env, 1); - const MDBX_meta *const meta2 = METAPAGE(env, 2); - txnid_t undo_txnid = 0 /* zero means undo is unneeded */; - while ( - (head != meta0 && mdbx_meta_txnid_fluid(env, meta0) == undo_txnid) || - (head != meta1 && mdbx_meta_txnid_fluid(env, meta1) == undo_txnid) || - (head != meta2 && mdbx_meta_txnid_fluid(env, meta2) == undo_txnid)) - undo_txnid = safe64_txnid_next(undo_txnid); - if (unlikely(undo_txnid >= meta.mm_txnid_a.inconsistent)) { - mdbx_fatal("rollback failed: no suitable txnid (0,1,2) < %" PRIaTXN, - meta.mm_txnid_a.inconsistent); - return MDBX_PANIC /* LY: could not recovery/rollback */; - } - - /* LY: rollback weak checkpoint */ - mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN " as %" PRIaTXN, - head_txnid, meta.mm_txnid_a.inconsistent, undo_txnid); - mdbx_ensure(env, head_txnid == mdbx_meta_txnid_stable(env, head)); - - if (env->me_flags & MDBX_WRITEMAP) { - /* It is possible to update txnid without safe64_write(), - * since DB opened exclusive for now */ - head->mm_txnid_a.inconsistent = undo_txnid; - head->mm_datasync_sign = MDBX_DATASIGN_WEAK; - head->mm_txnid_b.inconsistent = undo_txnid; - const size_t offset = (uint8_t *)data_page(head) - env->me_dxb_mmap.dxb; - const size_t paged_offset = offset & ~(env->me_os_psize - 1); - const size_t paged_length = roundup_powerof2( - env->me_psize + offset - paged_offset, env->me_os_psize); - err = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, false); - } else { - MDBX_meta rollback = *head; - mdbx_meta_set_txnid(env, &rollback, undo_txnid); - rollback.mm_datasync_sign = MDBX_DATASIGN_WEAK; - err = mdbx_pwrite(env->me_fd, &rollback, sizeof(MDBX_meta), - (uint8_t *)head - (uint8_t *)env->me_map); - } - if (err) { - mdbx_error("error %d rollback from %" PRIaTXN ", to %" PRIaTXN - " as %" PRIaTXN, - err, head_txnid, meta.mm_txnid_a.inconsistent, undo_txnid); - return err; - } - - mdbx_invalidate_mmap_noncoherent_cache(env->me_map, - pgno2bytes(env, NUM_METAS)); - mdbx_ensure(env, undo_txnid == mdbx_meta_txnid_fluid(env, head)); - mdbx_ensure(env, 0 == mdbx_meta_eq_mask(env)); - continue; - } - - if (!env->me_lck) { - /* LY: without-lck (read-only) mode, so it is imposible that other - * process made weak checkpoint. */ - mdbx_error("%s", "without-lck, unable recovery/rollback"); - return MDBX_WANNA_RECOVERY; - } - - /* LY: assume just have a collision with other running process, - * or someone make a weak checkpoint */ - mdbx_verbose("%s", "assume collision or online weak checkpoint"); - break; - } - - const MDBX_meta *head = mdbx_meta_head(env); - if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) { - /* re-check size after mmap */ - if ((env->me_dxb_mmap.current & (env->me_os_psize - 1)) != 0 || - env->me_dxb_mmap.current < used_bytes) { - mdbx_error("unacceptable/unexpected datafile size %" PRIuPTR, - env->me_dxb_mmap.current); - return MDBX_PROBLEM; - } - if (env->me_dxb_mmap.current != env->me_dbgeo.now && - (env->me_flags & MDBX_RDONLY) == 0) { - meta.mm_geo.now = bytes2pgno(env, env->me_dxb_mmap.current); - mdbx_verbose("update meta-geo to filesize %" PRIuPTR " bytes, %" PRIaPGNO - " pages", - env->me_dxb_mmap.current, meta.mm_geo.now); - } - - if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) { - const txnid_t txnid = mdbx_meta_txnid_stable(env, head); - const txnid_t next_txnid = safe64_txnid_next(txnid); - mdbx_verbose("updating meta.geo: " - "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO - "/s%u-g%u (txn#%" PRIaTXN "), " - "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO - "/s%u-g%u (txn#%" PRIaTXN ")", - head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, - head->mm_geo.shrink, head->mm_geo.grow, txnid, - meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, - meta.mm_geo.shrink, meta.mm_geo.grow, next_txnid); - - mdbx_ensure(env, mdbx_meta_eq(env, &meta, head)); - mdbx_meta_set_txnid(env, &meta, next_txnid); - *env->me_unsynced_pages += 1; - err = mdbx_sync_locked(env, env->me_flags | MDBX_SHRINK_ALLOWED, &meta); - if (err) { - mdbx_error("error %d, while updating meta.geo: " - "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO - "/s%u-g%u (txn#%" PRIaTXN "), " - "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO - "/s%u-g%u (txn#%" PRIaTXN ")", - err, head->mm_geo.lower, head->mm_geo.now, - head->mm_geo.upper, head->mm_geo.shrink, head->mm_geo.grow, - txnid, meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, - meta.mm_geo.shrink, meta.mm_geo.grow, next_txnid); - return err; - } - } - } - - return rc; -} - -/******************************************************************************/ - -/* Open and/or initialize the lock region for the environment. */ -static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname, - mode_t mode) { - mdbx_assert(env, env->me_fd != INVALID_HANDLE_VALUE); - mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE); - - int err = mdbx_openfile(lck_pathname, O_RDWR | O_CREAT, mode, &env->me_lfd, - (env->me_flags & MDBX_EXCLUSIVE) ? true : false); - if (err != MDBX_SUCCESS) { - if (!(err == MDBX_ENOFILE && (env->me_flags & MDBX_EXCLUSIVE)) && - !((err == MDBX_EROFS || err == MDBX_EACCESS || err == MDBX_EPERM) && - (env->me_flags & MDBX_RDONLY))) - return err; - - /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ - /* beginning of a locked section ---------------------------------------- */ - lcklist_lock(); - mdbx_assert(env, env->me_lcklist_next == nullptr); - env->me_lfd = INVALID_HANDLE_VALUE; - const int rc = mdbx_lck_seize(env); - if (MDBX_IS_ERROR(rc)) { - /* Calling lcklist_detach_locked() is required to restore POSIX-filelock - * and this job will be done by mdbx_env_close0(). */ - lcklist_unlock(); - return rc; - } - /* insert into inprocess lck-list */ - env->me_lcklist_next = inprocess_lcklist_head; - inprocess_lcklist_head = env; - lcklist_unlock(); - /* end of a locked section ---------------------------------------------- */ - - env->me_oldest = &env->me_lckless_stub.oldest; - env->me_sync_timestamp = &env->me_lckless_stub.sync_timestamp; - env->me_autosync_period = &env->me_lckless_stub.autosync_period; - env->me_unsynced_pages = &env->me_lckless_stub.autosync_pending; - env->me_autosync_threshold = &env->me_lckless_stub.autosync_threshold; - env->me_discarded_tail = &env->me_lckless_stub.discarded_tail; - env->me_meta_sync_txnid = &env->me_lckless_stub.meta_sync_txnid; - env->me_maxreaders = UINT_MAX; -#ifdef MDBX_OSAL_LOCK - env->me_wmutex = &env->me_lckless_stub.wmutex; -#endif - mdbx_debug("lck-setup:%s%s%s", " lck-less", - (env->me_flags & MDBX_RDONLY) ? " readonly" : "", - (rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative"); - return rc; - } - - /* beginning of a locked section ------------------------------------------ */ - lcklist_lock(); - mdbx_assert(env, env->me_lcklist_next == nullptr); - - /* Try to get exclusive lock. If we succeed, then - * nobody is using the lock region and we should initialize it. */ - err = mdbx_lck_seize(env); - if (MDBX_IS_ERROR(err)) { - bailout: - /* Calling lcklist_detach_locked() is required to restore POSIX-filelock - * and this job will be done by mdbx_env_close0(). */ - lcklist_unlock(); - return err; - } - - MDBX_env *inprocess_neighbor = nullptr; - if (err == MDBX_RESULT_TRUE) { - err = uniq_check(&env->me_lck_mmap, &inprocess_neighbor); - if (MDBX_IS_ERROR(err)) - goto bailout; - if (inprocess_neighbor && - ((mdbx_runtime_flags & MDBX_DBG_LEGACY_MULTIOPEN) == 0 || - (inprocess_neighbor->me_flags & MDBX_EXCLUSIVE) != 0)) { - err = MDBX_BUSY; - goto bailout; - } - } - const int lck_seize_rc = err; - - mdbx_debug("lck-setup:%s%s%s", " with-lck", - (env->me_flags & MDBX_RDONLY) ? " readonly" : "", - (lck_seize_rc == MDBX_RESULT_TRUE) ? " exclusive" - : " cooperative"); - - uint64_t size; - err = mdbx_filesize(env->me_lfd, &size); - if (unlikely(err != MDBX_SUCCESS)) - goto bailout; - - if (lck_seize_rc == MDBX_RESULT_TRUE) { - size = roundup_powerof2(env->me_maxreaders * sizeof(MDBX_reader) + - sizeof(MDBX_lockinfo), - env->me_os_psize); -#ifndef NDEBUG - err = mdbx_ftruncate(env->me_lfd, 0); - if (unlikely(err != MDBX_SUCCESS)) - goto bailout; -#endif - mdbx_jitter4testing(false); - } else { - if (env->me_flags & MDBX_EXCLUSIVE) { - err = MDBX_BUSY; - goto bailout; - } - if (size > INT_MAX || (size & (env->me_os_psize - 1)) != 0 || - size < env->me_os_psize) { - mdbx_error("lck-file has invalid size %" PRIu64 " bytes", size); - err = MDBX_PROBLEM; - goto bailout; - } - } - - const size_t maxreaders = - ((size_t)size - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader); - if (size > 65536 || maxreaders < 2 || maxreaders > MDBX_READERS_LIMIT) { - mdbx_error("lck-size too big (up to %" PRIuPTR " readers)", maxreaders); - err = MDBX_PROBLEM; - goto bailout; - } - env->me_maxreaders = (unsigned)maxreaders; - - err = mdbx_mmap(MDBX_WRITEMAP, &env->me_lck_mmap, (size_t)size, (size_t)size, - lck_seize_rc); - if (unlikely(err != MDBX_SUCCESS)) - goto bailout; - -#ifdef MADV_DODUMP - (void)madvise(env->me_lck, size, MADV_DODUMP); -#endif - -#ifdef MADV_WILLNEED - if (madvise(env->me_lck, size, MADV_WILLNEED) < 0) - goto bailout; -#endif - - if (lck_seize_rc == MDBX_RESULT_TRUE) { - /* LY: exlcusive mode, reset lck */ - memset(env->me_lck, 0, (size_t)size); - mdbx_jitter4testing(false); - env->me_lck->mti_magic_and_version = MDBX_LOCK_MAGIC; - env->me_lck->mti_os_and_format = MDBX_LOCK_FORMAT; - } else { - if (env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC) { - mdbx_error("%s", "lock region has invalid magic/version"); - err = ((env->me_lck->mti_magic_and_version >> 8) != MDBX_MAGIC) - ? MDBX_INVALID - : MDBX_VERSION_MISMATCH; - goto bailout; - } - if (env->me_lck->mti_os_and_format != MDBX_LOCK_FORMAT) { - mdbx_error("lock region has os/format 0x%" PRIx32 ", expected 0x%" PRIx32, - env->me_lck->mti_os_and_format, MDBX_LOCK_FORMAT); - err = MDBX_VERSION_MISMATCH; - goto bailout; - } - } - - err = mdbx_lck_init(env, inprocess_neighbor, lck_seize_rc); - if (MDBX_IS_ERROR(err)) - goto bailout; - - mdbx_ensure(env, env->me_lcklist_next == nullptr); - /* insert into inprocess lck-list */ - env->me_lcklist_next = inprocess_lcklist_head; - inprocess_lcklist_head = env; - lcklist_unlock(); - /* end of a locked section ------------------------------------------------ */ - - mdbx_assert(env, !MDBX_IS_ERROR(lck_seize_rc)); - env->me_oldest = &env->me_lck->mti_oldest_reader; - env->me_sync_timestamp = &env->me_lck->mti_sync_timestamp; - env->me_autosync_period = &env->me_lck->mti_autosync_period; - env->me_unsynced_pages = &env->me_lck->mti_unsynced_pages; - env->me_autosync_threshold = &env->me_lck->mti_autosync_threshold; - env->me_discarded_tail = &env->me_lck->mti_discarded_tail; - env->me_meta_sync_txnid = &env->me_lck->mti_meta_sync_txnid; -#ifdef MDBX_OSAL_LOCK - env->me_wmutex = &env->me_lck->mti_wmutex; -#endif - return lck_seize_rc; -} - -__cold int mdbx_is_readahead_reasonable(size_t volume, intptr_t redundancy) { - if (volume <= 1024 * 1024 * 4ul) - return MDBX_RESULT_TRUE; - - const intptr_t pagesize = mdbx_syspagesize(); - if (unlikely(pagesize < MIN_PAGESIZE || !is_powerof2(pagesize))) - return MDBX_INCOMPATIBLE; - -#if defined(_WIN32) || defined(_WIN64) - MEMORYSTATUSEX info; - memset(&info, 0, sizeof(info)); - info.dwLength = sizeof(info); - if (!GlobalMemoryStatusEx(&info)) - return GetLastError(); -#endif - const int log2page = log2n(pagesize); - -#if defined(_WIN32) || defined(_WIN64) - const intptr_t total_ram_pages = (intptr_t)(info.ullTotalPhys >> log2page); -#elif defined(_SC_PHYS_PAGES) - const intptr_t total_ram_pages = sysconf(_SC_PHYS_PAGES); - if (total_ram_pages == -1) - return errno; -#elif defined(_SC_AIX_REALMEM) - const intptr_t total_ram_Kb = sysconf(_SC_AIX_REALMEM); - if (total_ram_Kb == -1) - return errno; - const intptr_t total_ram_pages = (total_ram_Kb << 10) >> log2page; -#elif defined(HW_USERMEM) || defined(HW_PHYSMEM64) || defined(HW_MEMSIZE) || \ - defined(HW_PHYSMEM) - size_t ram, len = sizeof(ram); - static const int mib[] = { - CTL_HW, -#if defined(HW_USERMEM) - HW_USERMEM -#elif defined(HW_PHYSMEM64) - HW_PHYSMEM64 -#elif defined(HW_MEMSIZE) - HW_MEMSIZE -#else - HW_PHYSMEM -#endif - }; - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &ram, &len, NULL, 0) != 0) - return errno; - if (len != sizeof(ram)) - return MDBX_ENOSYS; - const intptr_t total_ram_pages = (intptr_t)(ram >> log2page); -#else -#error "FIXME: Get User-accessible or physical RAM" -#endif - if (total_ram_pages < 1) - return MDBX_ENOSYS; - - const intptr_t volume_pages = (volume + pagesize - 1) >> log2page; - const intptr_t redundancy_pages = - (redundancy < 0) ? -(intptr_t)((-redundancy + pagesize - 1) >> log2page) - : (intptr_t)(redundancy + pagesize - 1) >> log2page; - if (volume_pages >= total_ram_pages || - volume_pages + redundancy_pages >= total_ram_pages) - return MDBX_RESULT_FALSE; - -#if defined(_WIN32) || defined(_WIN64) - const intptr_t avail_ram_pages = (intptr_t)(info.ullAvailPhys >> log2page); -#elif defined(_SC_AVPHYS_PAGES) - const intptr_t avail_ram_pages = sysconf(_SC_AVPHYS_PAGES); - if (avail_ram_pages == -1) - return errno; -#elif defined(__MACH__) - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - vm_statistics_data_t vmstat; - mach_port_t mport = mach_host_self(); - kern_return_t kerr = host_statistics(mach_host_self(), HOST_VM_INFO, - (host_info_t)&vmstat, &count); - mach_port_deallocate(mach_task_self(), mport); - if (unlikely(kerr != KERN_SUCCESS)) - return MDBX_ENOSYS; - const intptr_t avail_ram_pages = vmstat.free_count; -#elif defined(VM_TOTAL) || defined(VM_METER) - struct vmtotal info; - size_t len = sizeof(info); - static const int mib[] = { - CTL_VM, -#if defined(VM_TOTAL) - VM_TOTAL -#elif defined(VM_METER) - VM_METER -#endif - }; - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &info, &len, NULL, 0) != 0) - return errno; - if (len != sizeof(info)) - return MDBX_ENOSYS; - const intptr_t avail_ram_pages = info.t_free; -#else -#error "FIXME: Get Available RAM" -#endif - if (avail_ram_pages < 1) - return MDBX_ENOSYS; - - return (volume_pages + redundancy_pages >= avail_ram_pages) - ? MDBX_RESULT_FALSE - : MDBX_RESULT_TRUE; -} - -/* Only a subset of the mdbx_env flags can be changed - * at runtime. Changing other flags requires closing the - * environment and re-opening it with the new flags. */ -#define CHANGEABLE \ - (MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \ - MDBX_COALESCE | MDBX_PAGEPERTURB) -#define CHANGELESS \ - (MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \ - MDBX_LIFORECLAIM | MDBX_EXCLUSIVE) - -#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE | CHANGELESS) -#error "Persistent DB flags & env flags overlap, but both go in mm_flags" -#endif - -int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags, - mode_t mode) { - if (unlikely(!env || !path)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (flags & ~(CHANGEABLE | CHANGELESS)) - return MDBX_EINVAL; - - if (env->me_fd != INVALID_HANDLE_VALUE || - (env->me_flags & MDBX_ENV_ACTIVE) != 0) - return MDBX_EPERM; - - size_t len_full, len = strlen(path); - if (flags & MDBX_NOSUBDIR) { - len_full = len + sizeof(MDBX_LOCK_SUFFIX) + len + 1; - } else { - len_full = len + sizeof(MDBX_LOCKNAME) + len + sizeof(MDBX_DATANAME); - } - char *lck_pathname = mdbx_malloc(len_full); - if (!lck_pathname) - return MDBX_ENOMEM; - - char *dxb_pathname; - if (flags & MDBX_NOSUBDIR) { - dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCK_SUFFIX); - sprintf(lck_pathname, "%s" MDBX_LOCK_SUFFIX, path); - strcpy(dxb_pathname, path); - } else { - dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCKNAME); - sprintf(lck_pathname, "%s" MDBX_LOCKNAME, path); - sprintf(dxb_pathname, "%s" MDBX_DATANAME, path); - } - - int rc = MDBX_SUCCESS; - flags |= env->me_flags; - if (flags & MDBX_RDONLY) { - /* LY: silently ignore irrelevant flags when - * we're only getting read access */ - flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC | - MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT); - } else { - env->me_dirtylist = mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP)); - if (!env->me_dirtylist) - rc = MDBX_ENOMEM; - } - - const uint32_t saved_me_flags = env->me_flags; - env->me_flags = (flags & ~MDBX_FATAL_ERROR) | MDBX_ENV_ACTIVE; - if (rc) - goto bailout; - - env->me_path = mdbx_strdup(path); - env->me_dbxs = mdbx_calloc(env->me_maxdbs, sizeof(MDBX_dbx)); - env->me_dbflags = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbflags[0])); - env->me_dbiseqs = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0])); - if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) { - rc = MDBX_ENOMEM; - goto bailout; - } - env->me_dbxs[FREE_DBI].md_cmp = - mdbx_cmp_int_align4; /* aligned MDBX_INTEGERKEY */ - - int oflags; - if (F_ISSET(flags, MDBX_RDONLY)) - oflags = O_RDONLY; - else if (mode != 0) { - if ((flags & MDBX_NOSUBDIR) == 0) { -#if defined(_WIN32) || defined(_WIN64) - if (!CreateDirectoryA(path, nullptr)) { - rc = GetLastError(); - if (rc != ERROR_ALREADY_EXISTS) - goto bailout; - } -#else - const mode_t dir_mode = - (/* inherit read/write permissions for group and others */ mode & - (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) | - /* always add read/write/search for owner */ S_IRWXU | - ((mode & S_IRGRP) ? /* +search if readable by group */ S_IXGRP : 0) | - ((mode & S_IROTH) ? /* +search if readable by others */ S_IXOTH : 0); - if (mkdir(path, dir_mode)) { - rc = errno; - if (rc != EEXIST) - goto bailout; - } -#endif - } - oflags = O_RDWR | O_CREAT; - } else - oflags = O_RDWR; - - rc = mdbx_openfile(dxb_pathname, oflags, mode, &env->me_fd, - (env->me_flags & MDBX_EXCLUSIVE) ? true : false); - if (rc != MDBX_SUCCESS) - goto bailout; - - const int lck_rc = mdbx_setup_lck(env, lck_pathname, mode); - if (MDBX_IS_ERROR(lck_rc)) { - rc = lck_rc; - goto bailout; - } - - const int dxb_rc = mdbx_setup_dxb(env, lck_rc); - if (MDBX_IS_ERROR(dxb_rc)) { - rc = dxb_rc; - goto bailout; - } - - mdbx_debug("opened dbenv %p", (void *)env); - if (env->me_lck) { - const unsigned mode_flags = - MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC; - if (lck_rc == MDBX_RESULT_TRUE) { - env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY); - rc = mdbx_lck_downgrade(env); - mdbx_debug("lck-downgrade-%s: rc %i", - (env->me_flags & MDBX_EXCLUSIVE) ? "partial" : "full", rc); - if (rc != MDBX_SUCCESS) - goto bailout; - } else { - rc = mdbx_reader_check0(env, false, NULL); - if (MDBX_IS_ERROR(rc)) - goto bailout; - if ((env->me_flags & MDBX_RDONLY) == 0) { - while (env->me_lck->mti_envmode == MDBX_RDONLY) { - if (atomic_cas32(&env->me_lck->mti_envmode, MDBX_RDONLY, - env->me_flags & mode_flags)) - break; - atomic_yield(); - } - if ((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) { - mdbx_error("%s", "current mode/flags incompatible with requested"); - rc = MDBX_INCOMPATIBLE; - goto bailout; - } - } - } - - if ((env->me_flags & MDBX_NOTLS) == 0) { - rc = mdbx_rthc_alloc(&env->me_txkey, &env->me_lck->mti_readers[0], - &env->me_lck->mti_readers[env->me_maxreaders]); - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - env->me_flags |= MDBX_ENV_TXKEY; - } - } - - if ((flags & MDBX_RDONLY) == 0) { - rc = MDBX_ENOMEM; - MDBX_txn *txn; - int tsize = sizeof(MDBX_txn), - size = - tsize + env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + - sizeof(unsigned) + 1); - if ((env->me_pbuf = mdbx_calloc( - 1 /* page buffer */ + 1 /* page killer bufer */, env->me_psize)) && - (txn = mdbx_calloc(1, size))) { - txn->mt_dbs = (MDBX_db *)((char *)txn + tsize); - txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs); - txn->mt_dbiseqs = (unsigned *)(txn->mt_cursors + env->me_maxdbs); - txn->mt_dbflags = (uint8_t *)(txn->mt_dbiseqs + env->me_maxdbs); - txn->mt_env = env; - txn->mt_dbxs = env->me_dbxs; - txn->mt_flags = MDBX_TXN_FINISHED; - env->me_txn0 = txn; - txn->tw.retired_pages = mdbx_pnl_alloc(MDBX_PNL_INITIAL); - txn->tw.reclaimed_pglist = mdbx_pnl_alloc(MDBX_PNL_INITIAL); - if (txn->tw.retired_pages && txn->tw.reclaimed_pglist) - rc = MDBX_SUCCESS; - } - } - -#if MDBX_DEBUG - if (rc == MDBX_SUCCESS) { - MDBX_meta *meta = mdbx_meta_head(env); - MDBX_db *db = &meta->mm_dbs[MAIN_DBI]; - - mdbx_debug("opened database version %u, pagesize %u", - (uint8_t)meta->mm_magic_and_version, env->me_psize); - mdbx_debug("using meta page %" PRIaPGNO ", txn %" PRIaTXN, - data_page(meta)->mp_pgno, mdbx_meta_txnid_fluid(env, meta)); - mdbx_debug("depth: %u", db->md_depth); - mdbx_debug("entries: %" PRIu64, db->md_entries); - mdbx_debug("branch pages: %" PRIaPGNO, db->md_branch_pages); - mdbx_debug("leaf pages: %" PRIaPGNO, db->md_leaf_pages); - mdbx_debug("overflow pages: %" PRIaPGNO, db->md_overflow_pages); - mdbx_debug("root: %" PRIaPGNO, db->md_root); - mdbx_debug("schema_altered: %" PRIaTXN, db->md_mod_txnid); - } -#endif - -bailout: - if (rc) { - rc = mdbx_env_close0(env) ? MDBX_PANIC : rc; - env->me_flags = saved_me_flags | MDBX_FATAL_ERROR; - } - mdbx_free(lck_pathname); - return rc; -} - -/* Destroy resources from mdbx_env_open(), clear our readers & DBIs */ -static int __cold mdbx_env_close0(MDBX_env *env) { - if (!(env->me_flags & MDBX_ENV_ACTIVE)) { - mdbx_ensure(env, env->me_lcklist_next == nullptr); - return MDBX_SUCCESS; - } - - env->me_flags &= ~MDBX_ENV_ACTIVE; - env->me_oldest = nullptr; - env->me_sync_timestamp = nullptr; - env->me_autosync_period = nullptr; - env->me_unsynced_pages = nullptr; - env->me_autosync_threshold = nullptr; - env->me_discarded_tail = nullptr; - env->me_meta_sync_txnid = nullptr; - if (env->me_flags & MDBX_ENV_TXKEY) - mdbx_rthc_remove(env->me_txkey); - - lcklist_lock(); - const int rc = lcklist_detach_locked(env); - lcklist_unlock(); - - if (env->me_map) { - mdbx_munmap(&env->me_dxb_mmap); -#ifdef MDBX_USE_VALGRIND - VALGRIND_DISCARD(env->me_valgrind_handle); - env->me_valgrind_handle = -1; -#endif - } - if (env->me_fd != INVALID_HANDLE_VALUE) { - (void)mdbx_closefile(env->me_fd); - env->me_fd = INVALID_HANDLE_VALUE; - } - - if (env->me_lck) - mdbx_munmap(&env->me_lck_mmap); - - if (env->me_lfd != INVALID_HANDLE_VALUE) { - (void)mdbx_closefile(env->me_lfd); - env->me_lfd = INVALID_HANDLE_VALUE; - } - - if (env->me_dbxs) { - for (unsigned i = env->me_maxdbs; --i >= CORE_DBS;) - mdbx_free(env->me_dbxs[i].md_name.iov_base); - mdbx_free(env->me_dbxs); - } - mdbx_free(env->me_pbuf); - mdbx_free(env->me_dbiseqs); - mdbx_free(env->me_dbflags); - mdbx_free(env->me_path); - mdbx_free(env->me_dirtylist); - if (env->me_txn0) { - mdbx_txl_free(env->me_txn0->tw.lifo_reclaimed); - mdbx_pnl_free(env->me_txn0->tw.retired_pages); - mdbx_pnl_free(env->me_txn0->tw.spill_pages); - mdbx_pnl_free(env->me_txn0->tw.reclaimed_pglist); - mdbx_free(env->me_txn0); - } - env->me_flags = 0; - return rc; -} - -int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) { - MDBX_page *dp; - int rc = MDBX_SUCCESS; - - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - -#if MDBX_TXN_CHECKPID || !(defined(_WIN32) || defined(_WIN64)) - /* Check the PID even if MDBX_TXN_CHECKPID=0 on non-Windows - * platforms (i.e. where fork() is available). - * This is required to legitimize a call after fork() - * from a child process, that should be allowed to free resources. */ - if (unlikely(env->me_pid != mdbx_getpid())) - env->me_flags |= MDBX_FATAL_ERROR; -#endif /* MDBX_TXN_CHECKPID */ - - if ((env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)) == 0) { - if (env->me_txn0 && env->me_txn0->mt_owner && - env->me_txn0->mt_owner != mdbx_thread_self()) - return MDBX_BUSY; - if (!dont_sync) { -#if defined(_WIN32) || defined(_WIN64) - /* On windows, without blocking is impossible to determine whether another - * process is running a writing transaction or not. - * Because in the "owner died" condition kernel don't release - * file lock immediately. */ - rc = mdbx_env_sync_ex(env, true, false); - rc = (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc; -#else - rc = mdbx_env_sync_ex(env, true, true); - rc = (rc == MDBX_BUSY || rc == EAGAIN || rc == EACCES || rc == EBUSY || - rc == EWOULDBLOCK || rc == MDBX_RESULT_TRUE) - ? MDBX_SUCCESS - : rc; -#endif - } - } - - while ((dp = env->me_dpages) != NULL) { - ASAN_UNPOISON_MEMORY_REGION(&dp->mp_next, sizeof(dp->mp_next)); - VALGRIND_MAKE_MEM_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); - env->me_dpages = dp->mp_next; - mdbx_free(dp); - } - VALGRIND_DESTROY_MEMPOOL(env); - - rc = mdbx_env_close0(env) ? MDBX_PANIC : rc; - mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS); -#if defined(_WIN32) || defined(_WIN64) - /* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */ - DeleteCriticalSection(&env->me_windowsbug_lock); -#else - mdbx_ensure(env, - mdbx_fastmutex_destroy(&env->me_remap_guard) == MDBX_SUCCESS); -#endif /* Windows */ - -#ifdef MDBX_OSAL_LOCK - mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_lckless_stub.wmutex) == - MDBX_SUCCESS); -#endif - - mdbx_ensure(env, env->me_lcklist_next == nullptr); - env->me_pid = 0; - env->me_signature = 0; - mdbx_free(env); - - return rc; -} - -__cold int mdbx_env_close(MDBX_env *env) { - return mdbx_env_close_ex(env, false); -} - -/* Compare two items pointing at aligned unsigned int's. */ -static int __hot mdbx_cmp_int_align4(const MDBX_val *a, const MDBX_val *b) { - mdbx_assert(NULL, a->iov_len == b->iov_len); - switch (a->iov_len) { - case 4: - return CMP2INT(unaligned_peek_u32(4, a->iov_base), - unaligned_peek_u32(4, b->iov_base)); - case 8: - return CMP2INT(unaligned_peek_u64(4, a->iov_base), - unaligned_peek_u64(4, b->iov_base)); - default: - mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", __func__, - __LINE__); - return 0; - } -} - -/* Compare two items pointing at 2-byte aligned unsigned int's. */ -static int __hot mdbx_cmp_int_align2(const MDBX_val *a, const MDBX_val *b) { - mdbx_assert(NULL, a->iov_len == b->iov_len); - switch (a->iov_len) { - case 4: - return CMP2INT(unaligned_peek_u32(2, a->iov_base), - unaligned_peek_u32(2, b->iov_base)); - case 8: - return CMP2INT(unaligned_peek_u64(2, a->iov_base), - unaligned_peek_u64(2, b->iov_base)); - default: - mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", __func__, - __LINE__); - return 0; - } -} - -/* Compare two items pointing at unsigneds of unknown alignment. - * - * This is also set as MDBX_INTEGERDUP|MDBX_DUPFIXED's MDBX_dbx.md_dcmp. */ -static int __hot mdbx_cmp_int_unaligned(const MDBX_val *a, const MDBX_val *b) { - mdbx_assert(NULL, a->iov_len == b->iov_len); - switch (a->iov_len) { - case 4: - return CMP2INT(unaligned_peek_u32(1, a->iov_base), - unaligned_peek_u32(1, b->iov_base)); - case 8: - return CMP2INT(unaligned_peek_u64(1, a->iov_base), - unaligned_peek_u64(1, b->iov_base)); - default: - mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", __func__, - __LINE__); - return 0; - } -} - -/* Compare two items lexically */ -static int __hot mdbx_cmp_memn(const MDBX_val *a, const MDBX_val *b) { - if (a->iov_len == b->iov_len) - return memcmp(a->iov_base, b->iov_base, a->iov_len); - - const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; - const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; - int diff_data = memcmp(a->iov_base, b->iov_base, shortest); - return likely(diff_data) ? diff_data : diff_len; -} - -/* Compare two items in reverse byte order */ -static int __hot mdbx_cmp_memnr(const MDBX_val *a, const MDBX_val *b) { - const uint8_t *pa = (const uint8_t *)a->iov_base + a->iov_len; - const uint8_t *pb = (const uint8_t *)b->iov_base + b->iov_len; - const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; - - const uint8_t *const end = pa - shortest; - while (pa != end) { - int diff = *--pa - *--pb; - if (likely(diff)) - return diff; - } - return CMP2INT(a->iov_len, b->iov_len); -} - -/* Search for key within a page, using binary search. - * Returns the smallest entry larger or equal to the key. - * If exactp is non-null, stores whether the found entry was an exact match - * in *exactp (1 or 0). - * Updates the cursor index with the index of the found entry. - * If no entry larger or equal to the key is found, returns NULL. */ -static MDBX_node *__hot mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, - int *exactp) { - int low, high; - int rc = 0; - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - MDBX_node *node = nullptr; - MDBX_val nodekey; - MDBX_cmp_func *cmp; - DKBUF; - - const unsigned nkeys = page_numkeys(mp); - - mdbx_debug("searching %u keys in %s %spage %" PRIaPGNO, nkeys, - IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", - mp->mp_pgno); - - low = IS_LEAF(mp) ? 0 : 1; - high = nkeys - 1; - cmp = mc->mc_dbx->md_cmp; - - /* Branch pages have no data, so if using integer keys, - * alignment is guaranteed. Use faster mdbx_cmp_int_ai. - */ - if (cmp == mdbx_cmp_int_align2 && IS_BRANCH(mp)) - cmp = mdbx_cmp_int_align4; - - unsigned i = 0; - if (IS_LEAF2(mp)) { - mdbx_cassert(mc, mp->mp_leaf2_ksize == mc->mc_db->md_xsize); - nodekey.iov_len = mp->mp_leaf2_ksize; - node = (MDBX_node *)(intptr_t)-1; /* fake */ - while (low <= high) { - i = (low + high) >> 1; - nodekey.iov_base = page_leaf2key(mp, i, nodekey.iov_len); - mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >= - (char *)nodekey.iov_base + nodekey.iov_len); - rc = cmp(key, &nodekey); - mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); - if (rc == 0) - break; - if (rc > 0) - low = i + 1; - else - high = i - 1; - } - } else { - while (low <= high) { - i = (low + high) >> 1; - - node = page_node(mp, i); - nodekey.iov_len = node_ks(node); - nodekey.iov_base = node_key(node); - mdbx_cassert(mc, (char *)mp + mc->mc_txn->mt_env->me_psize >= - (char *)nodekey.iov_base + nodekey.iov_len); - - rc = cmp(key, &nodekey); - if (IS_LEAF(mp)) - mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); - else - mdbx_debug("found branch index %u [%s -> %" PRIaPGNO "], rc = %i", i, - DKEY(&nodekey), node_pgno(node), rc); - if (rc == 0) - break; - if (rc > 0) - low = i + 1; - else - high = i - 1; - } - } - - if (rc > 0) /* Found entry is less than the key. */ - i++; /* Skip to get the smallest entry larger than key. */ - - if (exactp) - *exactp = (rc == 0 && nkeys > 0); - /* store the key index */ - mdbx_cassert(mc, i <= UINT16_MAX); - mc->mc_ki[mc->mc_top] = (indx_t)i; - if (i >= nkeys) - /* There is no entry larger or equal to the key. */ - return NULL; - - /* page_node is fake for LEAF2 */ - return IS_LEAF2(mp) ? node : page_node(mp, i); -} - -#if 0 /* unused for now */ -static void mdbx_cursor_adjust(MDBX_cursor *mc, func) { - MDBX_cursor *m2; - - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { - if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) { - func(mc, m2); - } - } -} -#endif - -/* Pop a page off the top of the cursor's stack. */ -static void mdbx_cursor_pop(MDBX_cursor *mc) { - if (mc->mc_snum) { - mdbx_debug("popped page %" PRIaPGNO " off db %d cursor %p", - mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *)mc); - - mc->mc_snum--; - if (mc->mc_snum) { - mc->mc_top--; - } else { - mc->mc_flags &= ~C_INITIALIZED; - } - } -} - -/* Push a page onto the top of the cursor's stack. - * Set MDBX_TXN_ERROR on failure. */ -static int mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp) { - mdbx_debug("pushing page %" PRIaPGNO " on db %d cursor %p", mp->mp_pgno, - DDBI(mc), (void *)mc); - - if (unlikely(mc->mc_snum >= CURSOR_STACK)) { - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_CURSOR_FULL; - } - - mdbx_cassert(mc, mc->mc_snum < UINT16_MAX); - mc->mc_top = mc->mc_snum++; - mc->mc_pg[mc->mc_top] = mp; - mc->mc_ki[mc->mc_top] = 0; - - return MDBX_SUCCESS; -} - -/* Find the address of the page corresponding to a given page number. - * Set MDBX_TXN_ERROR on failure. - * - * [in] mc the cursor accessing the page. - * [in] pgno the page number for the page to retrieve. - * [out] ret address of a pointer where the page's address will be - * stored. - * [out] lvl dirtylist inheritance level of found page. 1=current txn, - * 0=mapped page. - * - * Returns 0 on success, non-zero on failure. */ -__hot static int mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, MDBX_page **ret, - int *lvl) { - MDBX_txn *txn = mc->mc_txn; - if (unlikely(pgno >= txn->mt_next_pgno)) { - mdbx_debug("page %" PRIaPGNO " not found", pgno); - txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PAGE_NOTFOUND; - } - - MDBX_env *env = txn->mt_env; - MDBX_page *p = NULL; - int level; - if ((txn->mt_flags & (MDBX_RDONLY | MDBX_WRITEMAP)) == 0) { - level = 1; - do { - /* Spilled pages were dirtied in this txn and flushed - * because the dirty list got full. Bring this page - * back in from the map (but don't unspill it here, - * leave that unless page_touch happens again). */ - if (txn->tw.spill_pages && mdbx_pnl_exist(txn->tw.spill_pages, pgno << 1)) - goto mapped; - p = mdbx_dpl_find(txn->tw.dirtylist, pgno); - if (p) - goto done; - level++; - } while ((txn = txn->mt_parent) != NULL); - } - level = 0; - -mapped: - p = pgno2page(env, pgno); - -done: - txn = nullptr /* avoid future use */; - if (unlikely(p->mp_pgno != pgno)) { - mdbx_error("mismatch pgno %" PRIaPGNO " (actual) != %" PRIaPGNO - " (expected)", - p->mp_pgno, pgno); - return MDBX_CORRUPTED; - } - - if (unlikely(p->mp_upper < p->mp_lower || ((p->mp_lower | p->mp_upper) & 1) || - PAGEHDRSZ + p->mp_upper > env->me_psize) && - !IS_OVERFLOW(p)) { - mdbx_error("invalid page lower(%u)/upper(%u), pg-limit %u", p->mp_lower, - p->mp_upper, page_space(env)); - return MDBX_CORRUPTED; - } - /* TODO: more checks here, including p->mp_validator */ - - if (mdbx_audit_enabled()) { - int err = mdbx_page_check(env, p, true); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - - *ret = p; - if (lvl) - *lvl = level; - return MDBX_SUCCESS; -} - -/* Finish mdbx_page_search() / mdbx_page_search_lowest(). - * The cursor is at the root page, set up the rest of it. */ -__hot static int mdbx_page_search_root(MDBX_cursor *mc, MDBX_val *key, - int flags) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - int rc; - DKBUF; - - while (IS_BRANCH(mp)) { - MDBX_node *node; - int i; - - mdbx_debug("branch page %" PRIaPGNO " has %u keys", mp->mp_pgno, - page_numkeys(mp)); - /* Don't assert on branch pages in the GC. We can get here - * while in the process of rebalancing a GC branch page; we must - * let that proceed. ITS#8336 */ - mdbx_cassert(mc, !mc->mc_dbi || page_numkeys(mp) > 1); - mdbx_debug("found index 0 to page %" PRIaPGNO, node_pgno(page_node(mp, 0))); - - if (flags & (MDBX_PS_FIRST | MDBX_PS_LAST)) { - i = 0; - if (flags & MDBX_PS_LAST) { - i = page_numkeys(mp) - 1; - /* if already init'd, see if we're already in right place */ - if (mc->mc_flags & C_INITIALIZED) { - if (mc->mc_ki[mc->mc_top] == i) { - mc->mc_top = mc->mc_snum++; - mp = mc->mc_pg[mc->mc_top]; - goto ready; - } - } - } - } else { - int exact; - node = mdbx_node_search(mc, key, &exact); - if (node == NULL) - i = page_numkeys(mp) - 1; - else { - i = mc->mc_ki[mc->mc_top]; - if (!exact) { - mdbx_cassert(mc, i > 0); - i--; - } - } - mdbx_debug("following index %u for key [%s]", i, DKEY(key)); - } - - mdbx_cassert(mc, i < (int)page_numkeys(mp)); - node = page_node(mp, i); - - if (unlikely((rc = mdbx_page_get(mc, node_pgno(node), &mp, NULL)) != 0)) - return rc; - - mc->mc_ki[mc->mc_top] = (indx_t)i; - if (unlikely(rc = mdbx_cursor_push(mc, mp))) - return rc; - - ready: - if (flags & MDBX_PS_MODIFY) { - if (unlikely((rc = mdbx_page_touch(mc)) != 0)) - return rc; - mp = mc->mc_pg[mc->mc_top]; - } - } - - if (unlikely(!IS_LEAF(mp))) { - mdbx_debug("internal error, index points to a page with 0x%02x flags!?", - mp->mp_flags); - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_CORRUPTED; - } - - mdbx_debug("found leaf page %" PRIaPGNO " for key [%s]", mp->mp_pgno, - DKEY(key)); - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - - return MDBX_SUCCESS; -} - -static int mdbx_fetch_sdb(MDBX_txn *txn, MDBX_dbi dbi) { - MDBX_cursor mc; - if (unlikely(TXN_DBI_CHANGED(txn, dbi))) - return MDBX_BAD_DBI; - int rc = mdbx_cursor_init(&mc, txn, MAIN_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_page_search(&mc, &txn->mt_dbxs[dbi].md_name, 0); - if (unlikely(rc != MDBX_SUCCESS)) - return (rc == MDBX_NOTFOUND) ? MDBX_BAD_DBI : rc; - - MDBX_val data; - int exact = 0; - MDBX_node *node = mdbx_node_search(&mc, &txn->mt_dbxs[dbi].md_name, &exact); - if (unlikely(!exact)) - return MDBX_BAD_DBI; - if (unlikely((node_flags(node) & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA)) - return MDBX_INCOMPATIBLE; /* not a named DB */ - rc = mdbx_node_read(&mc, node, &data); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(data.iov_len < sizeof(MDBX_db))) - return MDBX_INCOMPATIBLE; /* not a named DB */ - - uint16_t md_flags = UNALIGNED_PEEK_16(data.iov_base, MDBX_db, md_flags); - /* The txn may not know this DBI, or another process may - * have dropped and recreated the DB with other flags. */ - if (unlikely((txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS) != md_flags)) - return MDBX_INCOMPATIBLE; - - memcpy(&txn->mt_dbs[dbi], data.iov_base, sizeof(MDBX_db)); - txn->mt_dbflags[dbi] &= ~DB_STALE; - return MDBX_SUCCESS; -} - -/* Search for the lowest key under the current branch page. - * This just bypasses a numkeys check in the current page - * before calling mdbx_page_search_root(), because the callers - * are all in situations where the current page is known to - * be underfilled. */ -__hot static int mdbx_page_search_lowest(MDBX_cursor *mc) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - mdbx_cassert(mc, IS_BRANCH(mp)); - MDBX_node *node = page_node(mp, 0); - int rc; - - if (unlikely((rc = mdbx_page_get(mc, node_pgno(node), &mp, NULL)) != 0)) - return rc; - - mc->mc_ki[mc->mc_top] = 0; - if (unlikely(rc = mdbx_cursor_push(mc, mp))) - return rc; - return mdbx_page_search_root(mc, NULL, MDBX_PS_FIRST); -} - -/* Search for the page a given key should be in. - * Push it and its parent pages on the cursor stack. - * - * [in,out] mc the cursor for this operation. - * [in] key the key to search for, or NULL for first/last page. - * [in] flags If MDBX_PS_MODIFY is set, visited pages in the DB - * are touched (updated with new page numbers). - * If MDBX_PS_FIRST or MDBX_PS_LAST is set, find first or last - * leaf. - * This is used by mdbx_cursor_first() and mdbx_cursor_last(). - * If MDBX_PS_ROOTONLY set, just fetch root node, no further - * lookups. - * - * Returns 0 on success, non-zero on failure. */ -__hot static int mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, int flags) { - int rc; - pgno_t root; - - /* Make sure the txn is still viable, then find the root from - * the txn's db table and set it as the root of the cursor's stack. */ - if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) { - mdbx_debug("%s", "transaction has failed, must abort"); - return MDBX_BAD_TXN; - } - - /* Make sure we're using an up-to-date root */ - if (unlikely(*mc->mc_dbflag & DB_STALE)) { - rc = mdbx_fetch_sdb(mc->mc_txn, mc->mc_dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - root = mc->mc_db->md_root; - - if (unlikely(root == P_INVALID)) { /* Tree is empty. */ - mdbx_debug("%s", "tree is empty"); - return MDBX_NOTFOUND; - } - - mdbx_cassert(mc, root >= NUM_METAS); - if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root) - if (unlikely((rc = mdbx_page_get(mc, root, &mc->mc_pg[0], NULL)) != 0)) - return rc; - - mc->mc_snum = 1; - mc->mc_top = 0; - - mdbx_debug("db %d root page %" PRIaPGNO " has flags 0x%X", DDBI(mc), root, - mc->mc_pg[0]->mp_flags); - - if (flags & MDBX_PS_MODIFY) { - if (unlikely(rc = mdbx_page_touch(mc))) - return rc; - } - - if (flags & MDBX_PS_ROOTONLY) - return MDBX_SUCCESS; - - return mdbx_page_search_root(mc, key, flags); -} - -/* Return the data associated with a given node. - * - * [in] mc The cursor for this operation. - * [in] leaf The node being read. - * [out] data Updated to point to the node's data. - * - * Returns 0 on success, non-zero on failure. */ -static __inline int mdbx_node_read(MDBX_cursor *mc, MDBX_node *node, - MDBX_val *data) { - data->iov_len = node_ds(node); - data->iov_base = node_data(node); - if (unlikely(F_ISSET(node_flags(node), F_BIGDATA))) { - /* Read overflow data. */ - MDBX_page *omp; /* overflow page */ - int rc = mdbx_page_get(mc, node_largedata_pgno(node), &omp, NULL); - if (unlikely((rc != MDBX_SUCCESS))) { - mdbx_debug("read overflow page %" PRIaPGNO " failed", - node_largedata_pgno(node)); - return rc; - } - data->iov_base = page_data(omp); - } - return MDBX_SUCCESS; -} - -int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) { - DKBUF; - mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); - - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key || !data)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - MDBX_cursor_couple cx; - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - int exact = 0; - return mdbx_cursor_set(&cx.outer, key, data, MDBX_SET, &exact); -} - -int mdbx_get_nearest(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, - MDBX_val *data) { - DKBUF; - mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); - - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key || !data)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) - return MDBX_BAD_TXN; - - MDBX_cursor_couple cx; - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - MDBX_val save_data = *data; - int exact = 0; - rc = mdbx_cursor_set(&cx.outer, key, data, MDBX_SET_RANGE, &exact); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (exact && (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) != 0) { - *data = save_data; - exact = 0; - rc = mdbx_cursor_set(&cx.outer, key, data, MDBX_GET_BOTH_RANGE, &exact); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - return exact ? MDBX_SUCCESS : MDBX_RESULT_TRUE; -} - -int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - size_t *values_count) { - DKBUF; - mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); - - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key || !data)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - MDBX_cursor_couple cx; - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - int exact = 0; - rc = mdbx_cursor_set(&cx.outer, key, data, MDBX_SET_KEY, &exact); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc == MDBX_NOTFOUND && values_count) - *values_count = 0; - return rc; - } - - if (values_count) { - *values_count = 1; - if (cx.outer.mc_xcursor != NULL) { - MDBX_node *node = page_node(cx.outer.mc_pg[cx.outer.mc_top], - cx.outer.mc_ki[cx.outer.mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - mdbx_tassert(txn, cx.outer.mc_xcursor == &cx.inner && - (cx.inner.mx_cursor.mc_flags & C_INITIALIZED)); - *values_count = - (sizeof(*values_count) >= sizeof(cx.inner.mx_db.md_entries) || - cx.inner.mx_db.md_entries <= PTRDIFF_MAX) - ? (size_t)cx.inner.mx_db.md_entries - : PTRDIFF_MAX; - } - } - } - return MDBX_SUCCESS; -} - -/* Find a sibling for a page. - * Replaces the page at the top of the cursor's stack with the specified - * sibling, if one exists. - * - * [in] mc The cursor for this operation. - * [in] move_right Non-zero if the right sibling is requested, - * otherwise the left sibling. - * - * Returns 0 on success, non-zero on failure. */ -static int mdbx_cursor_sibling(MDBX_cursor *mc, int move_right) { - int rc; - MDBX_node *indx; - MDBX_page *mp; - - if (unlikely(mc->mc_snum < 2)) - return MDBX_NOTFOUND; /* root has no siblings */ - - mdbx_cursor_pop(mc); - mdbx_debug("parent page is page %" PRIaPGNO ", index %u", - mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top]); - - if (move_right - ? (mc->mc_ki[mc->mc_top] + 1u >= page_numkeys(mc->mc_pg[mc->mc_top])) - : (mc->mc_ki[mc->mc_top] == 0)) { - mdbx_debug("no more keys left, moving to %s sibling", - move_right ? "right" : "left"); - if (unlikely((rc = mdbx_cursor_sibling(mc, move_right)) != MDBX_SUCCESS)) { - /* undo cursor_pop before returning */ - mc->mc_top++; - mc->mc_snum++; - return rc; - } - } else { - if (move_right) - mc->mc_ki[mc->mc_top]++; - else - mc->mc_ki[mc->mc_top]--; - mdbx_debug("just moving to %s index key %u", move_right ? "right" : "left", - mc->mc_ki[mc->mc_top]); - } - mdbx_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top])); - - indx = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (unlikely((rc = mdbx_page_get(mc, node_pgno(indx), &mp, NULL)) != 0)) { - /* mc will be inconsistent if caller does mc_snum++ as above */ - mc->mc_flags &= ~(C_INITIALIZED | C_EOF); - return rc; - } - - rc = mdbx_cursor_push(mc, mp); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - if (!move_right) - mc->mc_ki[mc->mc_top] = (indx_t)page_numkeys(mp) - 1; - - return MDBX_SUCCESS; -} - -/* Move the cursor to the next data item. */ -static int mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - MDBX_cursor_op op) { - MDBX_page *mp; - MDBX_node *node; - int rc; - - if ((mc->mc_flags & C_DEL) && op == MDBX_NEXT_DUP) - return MDBX_NOTFOUND; - - if (!(mc->mc_flags & C_INITIALIZED)) - return mdbx_cursor_first(mc, key, data); - - mp = mc->mc_pg[mc->mc_top]; - if (mc->mc_flags & C_EOF) { - if (mc->mc_ki[mc->mc_top] + 1u >= page_numkeys(mp)) - return MDBX_NOTFOUND; - mc->mc_flags ^= C_EOF; - } - - if (mc->mc_db->md_flags & MDBX_DUPSORT) { - node = page_node(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - if (op == MDBX_NEXT || op == MDBX_NEXT_DUP) { - rc = - mdbx_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT); - if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) { - if (likely(rc == MDBX_SUCCESS)) - get_key_optional(node, key); - return rc; - } - } - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - if (op == MDBX_NEXT_DUP) - return MDBX_NOTFOUND; - } - } - - mdbx_debug("cursor_next: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno, - (void *)mc); - if (mc->mc_flags & C_DEL) { - mc->mc_flags ^= C_DEL; - goto skip; - } - - if (mc->mc_ki[mc->mc_top] + 1u >= page_numkeys(mp)) { - mdbx_debug("%s", "=====> move to next sibling page"); - if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) { - mc->mc_flags |= C_EOF; - return rc; - } - mp = mc->mc_pg[mc->mc_top]; - mdbx_debug("next page is %" PRIaPGNO ", key index %u", mp->mp_pgno, - mc->mc_ki[mc->mc_top]); - } else - mc->mc_ki[mc->mc_top]++; - -skip: - mdbx_debug("==> cursor points to page %" PRIaPGNO - " with %u keys, key index %u", - mp->mp_pgno, page_numkeys(mp), mc->mc_ki[mc->mc_top]); - - if (IS_LEAF2(mp)) { - if (likely(key)) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mp, mc->mc_ki[mc->mc_top], key->iov_len); - } - return MDBX_SUCCESS; - } - - mdbx_cassert(mc, IS_LEAF(mp)); - node = page_node(mp, mc->mc_ki[mc->mc_top]); - - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - if (data) { - if (unlikely((rc = mdbx_node_read(mc, node, data)) != MDBX_SUCCESS)) - return rc; - - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - } - - get_key_optional(node, key); - return MDBX_SUCCESS; -} - -/* Move the cursor to the previous data item. */ -static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - MDBX_cursor_op op) { - MDBX_page *mp; - MDBX_node *node; - int rc; - - if ((mc->mc_flags & C_DEL) && op == MDBX_PREV_DUP) - return MDBX_NOTFOUND; - - if (!(mc->mc_flags & C_INITIALIZED)) { - rc = mdbx_cursor_last(mc, key, data); - if (unlikely(rc)) - return rc; - mc->mc_ki[mc->mc_top]++; - } - - mp = mc->mc_pg[mc->mc_top]; - if ((mc->mc_db->md_flags & MDBX_DUPSORT) && - mc->mc_ki[mc->mc_top] < page_numkeys(mp)) { - node = page_node(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - if (op == MDBX_PREV || op == MDBX_PREV_DUP) { - rc = - mdbx_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV); - if (op != MDBX_PREV || rc != MDBX_NOTFOUND) { - if (likely(rc == MDBX_SUCCESS)) { - get_key_optional(node, key); - mc->mc_flags &= ~C_EOF; - } - return rc; - } - } - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - if (op == MDBX_PREV_DUP) - return MDBX_NOTFOUND; - } - } - - mdbx_debug("cursor_prev: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno, - (void *)mc); - - mc->mc_flags &= ~(C_EOF | C_DEL); - - if (mc->mc_ki[mc->mc_top] == 0) { - mdbx_debug("%s", "=====> move to prev sibling page"); - if ((rc = mdbx_cursor_sibling(mc, 0)) != MDBX_SUCCESS) { - return rc; - } - mp = mc->mc_pg[mc->mc_top]; - mc->mc_ki[mc->mc_top] = (indx_t)page_numkeys(mp) - 1; - mdbx_debug("prev page is %" PRIaPGNO ", key index %u", mp->mp_pgno, - mc->mc_ki[mc->mc_top]); - } else - mc->mc_ki[mc->mc_top]--; - - mdbx_debug("==> cursor points to page %" PRIaPGNO - " with %u keys, key index %u", - mp->mp_pgno, page_numkeys(mp), mc->mc_ki[mc->mc_top]); - - if (IS_LEAF2(mp)) { - if (likely(key)) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mp, mc->mc_ki[mc->mc_top], key->iov_len); - } - return MDBX_SUCCESS; - } - - mdbx_cassert(mc, IS_LEAF(mp)); - node = page_node(mp, mc->mc_ki[mc->mc_top]); - - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - if (data) { - if (unlikely((rc = mdbx_node_read(mc, node, data)) != MDBX_SUCCESS)) - return rc; - - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - } - - get_key_optional(node, key); - return MDBX_SUCCESS; -} - -/* Set the cursor on a specific data item. */ -__hot static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - MDBX_cursor_op op, int *exactp) { - int rc; - MDBX_page *mp; - MDBX_node *node = NULL; - DKBUF; - - if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) && - unlikely(key->iov_len != sizeof(uint32_t) && - key->iov_len != sizeof(uint64_t))) { - mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY"); - return MDBX_BAD_VALSIZE; - } - - if (mc->mc_xcursor) - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - - /* See if we're already on the right page */ - if (mc->mc_flags & C_INITIALIZED) { - MDBX_val nodekey; - - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - mp = mc->mc_pg[mc->mc_top]; - if (!page_numkeys(mp)) { - mc->mc_ki[mc->mc_top] = 0; - return MDBX_NOTFOUND; - } - if (IS_LEAF2(mp)) { - nodekey.iov_len = mc->mc_db->md_xsize; - nodekey.iov_base = page_leaf2key(mp, 0, nodekey.iov_len); - } else { - node = page_node(mp, 0); - get_key(node, &nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (unlikely(rc == 0)) { - /* Probably happens rarely, but first node on the page - * was the one we wanted. */ - mc->mc_ki[mc->mc_top] = 0; - if (exactp) - *exactp = 1; - goto set1; - } - if (rc > 0) { - const unsigned nkeys = page_numkeys(mp); - unsigned i; - if (nkeys > 1) { - if (IS_LEAF2(mp)) { - nodekey.iov_base = page_leaf2key(mp, nkeys - 1, nodekey.iov_len); - } else { - node = page_node(mp, nkeys - 1); - get_key(node, &nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (rc == 0) { - /* last node was the one we wanted */ - mdbx_cassert(mc, nkeys >= 1 && nkeys <= UINT16_MAX + 1); - mc->mc_ki[mc->mc_top] = (indx_t)(nkeys - 1); - if (exactp) - *exactp = 1; - goto set1; - } - if (rc < 0) { - if (mc->mc_ki[mc->mc_top] < page_numkeys(mp)) { - /* This is definitely the right page, skip search_page */ - if (IS_LEAF2(mp)) { - nodekey.iov_base = - page_leaf2key(mp, mc->mc_ki[mc->mc_top], nodekey.iov_len); - } else { - node = page_node(mp, mc->mc_ki[mc->mc_top]); - get_key(node, &nodekey); - } - rc = mc->mc_dbx->md_cmp(key, &nodekey); - if (rc == 0) { - /* current node was the one we wanted */ - if (exactp) - *exactp = 1; - goto set1; - } - } - rc = 0; - mc->mc_flags &= ~C_EOF; - goto set2; - } - } - /* If any parents have right-sibs, search. - * Otherwise, there's nothing further. */ - for (i = 0; i < mc->mc_top; i++) - if (mc->mc_ki[i] < page_numkeys(mc->mc_pg[i]) - 1) - break; - if (i == mc->mc_top) { - /* There are no other pages */ - mdbx_cassert(mc, nkeys <= UINT16_MAX); - mc->mc_ki[mc->mc_top] = (uint16_t)nkeys; - return MDBX_NOTFOUND; - } - } - if (!mc->mc_top) { - /* There are no other pages */ - mc->mc_ki[mc->mc_top] = 0; - if (op == MDBX_SET_RANGE && !exactp) { - rc = 0; - goto set1; - } else - return MDBX_NOTFOUND; - } - } else { - mc->mc_pg[0] = 0; - } - - rc = mdbx_page_search(mc, key, 0); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - mp = mc->mc_pg[mc->mc_top]; - mdbx_cassert(mc, IS_LEAF(mp)); - -set2: - node = mdbx_node_search(mc, key, exactp); - if (exactp != NULL && !*exactp) { - /* MDBX_SET specified and not an exact match. */ - return MDBX_NOTFOUND; - } - - if (node == NULL) { - mdbx_debug("%s", "===> inexact leaf not found, goto sibling"); - if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) { - mc->mc_flags |= C_EOF; - return rc; /* no entries matched */ - } - mp = mc->mc_pg[mc->mc_top]; - mdbx_cassert(mc, IS_LEAF(mp)); - node = page_node(mp, 0); - } - -set1: - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - - if (IS_LEAF2(mp)) { - if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mp, mc->mc_ki[mc->mc_top], key->iov_len); - } - return MDBX_SUCCESS; - } - - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - if (likely(data)) { - if (F_ISSET(node_flags(node), F_DUPDATA)) { - if (op == MDBX_SET || op == MDBX_SET_KEY || op == MDBX_SET_RANGE) { - rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - } else { - int ex2, *ex2p; - if (op == MDBX_GET_BOTH) { - ex2p = &ex2; - ex2 = 0; - } else { - ex2p = NULL; - } - rc = mdbx_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, - MDBX_SET_RANGE, ex2p); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - } else if (op == MDBX_GET_BOTH || op == MDBX_GET_BOTH_RANGE) { - MDBX_val olddata; - if (unlikely((rc = mdbx_node_read(mc, node, &olddata)) != MDBX_SUCCESS)) - return rc; - if (unlikely(mc->mc_dbx->md_dcmp == NULL)) - return MDBX_EINVAL; - rc = mc->mc_dbx->md_dcmp(data, &olddata); - if (rc) { - if (op != MDBX_GET_BOTH_RANGE || rc > 0) - return MDBX_NOTFOUND; - rc = 0; - } - *data = olddata; - } else { - if (mc->mc_xcursor) - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - if (unlikely((rc = mdbx_node_read(mc, node, data)) != MDBX_SUCCESS)) - return rc; - } - } - - /* The key already matches in all other cases */ - if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY) - get_key_optional(node, key); - - mdbx_debug("==> cursor placed on key [%s], data [%s]", DKEY(key), DVAL(data)); - return rc; -} - -/* Move the cursor to the first item in the database. */ -static int mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) { - int rc; - - if (mc->mc_xcursor) - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - - if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { - rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - - mc->mc_flags |= C_INITIALIZED; - mc->mc_flags &= ~C_EOF; - mc->mc_ki[mc->mc_top] = 0; - - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mc->mc_pg[mc->mc_top], 0, key->iov_len); - return MDBX_SUCCESS; - } - - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], 0); - if (likely(data)) { - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (unlikely(rc)) - return rc; - } else { - if (unlikely((rc = mdbx_node_read(mc, node, data)) != MDBX_SUCCESS)) - return rc; - } - } - get_key_optional(node, key); - return MDBX_SUCCESS; -} - -/* Move the cursor to the last item in the database. */ -static int mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) { - int rc; - - if (mc->mc_xcursor) - mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - - if (likely((mc->mc_flags & (C_EOF | C_DEL)) != C_EOF)) { - if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { - rc = mdbx_page_search(mc, NULL, MDBX_PS_LAST); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - } - - mc->mc_ki[mc->mc_top] = (indx_t)page_numkeys(mc->mc_pg[mc->mc_top]) - 1; - mc->mc_flags |= C_INITIALIZED | C_EOF; - - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], - key->iov_len); - return MDBX_SUCCESS; - } - - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (likely(data)) { - if (F_ISSET(node_flags(node), F_DUPDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); - if (unlikely(rc)) - return rc; - } else { - if (unlikely((rc = mdbx_node_read(mc, node, data)) != MDBX_SUCCESS)) - return rc; - } - } - - get_key_optional(node, key); - return MDBX_SUCCESS; -} - -int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - MDBX_cursor_op op) { - if (unlikely(mc == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn(mc->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - int exact = 0; - int (*mfunc)(MDBX_cursor * mc, MDBX_val * key, MDBX_val * data); - switch (op) { - case MDBX_GET_CURRENT: { - if (unlikely(!(mc->mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - const unsigned nkeys = page_numkeys(mp); - if (mc->mc_ki[mc->mc_top] >= nkeys) { - mdbx_cassert(mc, nkeys <= UINT16_MAX); - mc->mc_ki[mc->mc_top] = (uint16_t)nkeys; - return MDBX_NOTFOUND; - } - mdbx_cassert(mc, nkeys > 0); - - rc = MDBX_SUCCESS; - if (IS_LEAF2(mp)) { - key->iov_len = mc->mc_db->md_xsize; - key->iov_base = page_leaf2key(mp, mc->mc_ki[mc->mc_top], key->iov_len); - } else { - MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]); - get_key_optional(node, key); - if (data) { - if (F_ISSET(node_flags(node), F_DUPDATA)) { - if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); - if (unlikely(rc)) - return rc; - } - rc = mdbx_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, - MDBX_GET_CURRENT); - } else { - rc = mdbx_node_read(mc, node, data); - } - if (unlikely(rc)) - return rc; - } - } - break; - } - case MDBX_GET_BOTH: - case MDBX_GET_BOTH_RANGE: - if (unlikely(data == NULL)) - return MDBX_EINVAL; - if (unlikely(mc->mc_xcursor == NULL)) - return MDBX_INCOMPATIBLE; - /* fall through */ - __fallthrough; - case MDBX_SET: - case MDBX_SET_KEY: - case MDBX_SET_RANGE: - if (unlikely(key == NULL)) - return MDBX_EINVAL; - rc = mdbx_cursor_set(mc, key, data, op, - op == MDBX_SET_RANGE ? NULL : &exact); - break; - case MDBX_GET_MULTIPLE: - if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED))) - return MDBX_INCOMPATIBLE; - rc = MDBX_SUCCESS; - if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) || - (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF)) - break; - goto fetchm; - case MDBX_NEXT_MULTIPLE: - if (unlikely(data == NULL)) - return MDBX_EINVAL; - if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED))) - return MDBX_INCOMPATIBLE; - rc = mdbx_cursor_next(mc, key, data, MDBX_NEXT_DUP); - if (rc == MDBX_SUCCESS) { - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - MDBX_cursor *mx; - fetchm: - mx = &mc->mc_xcursor->mx_cursor; - data->iov_len = - page_numkeys(mx->mc_pg[mx->mc_top]) * mx->mc_db->md_xsize; - data->iov_base = page_data(mx->mc_pg[mx->mc_top]); - mx->mc_ki[mx->mc_top] = (indx_t)page_numkeys(mx->mc_pg[mx->mc_top]) - 1; - } else { - rc = MDBX_NOTFOUND; - } - } - break; - case MDBX_PREV_MULTIPLE: - if (data == NULL) - return MDBX_EINVAL; - if (!(mc->mc_db->md_flags & MDBX_DUPFIXED)) - return MDBX_INCOMPATIBLE; - rc = MDBX_SUCCESS; - if (!(mc->mc_flags & C_INITIALIZED)) - rc = mdbx_cursor_last(mc, key, data); - if (rc == MDBX_SUCCESS) { - MDBX_cursor *mx = &mc->mc_xcursor->mx_cursor; - if (mx->mc_flags & C_INITIALIZED) { - rc = mdbx_cursor_sibling(mx, 0); - if (rc == MDBX_SUCCESS) - goto fetchm; - } else { - rc = MDBX_NOTFOUND; - } - } - break; - case MDBX_NEXT: - case MDBX_NEXT_DUP: - case MDBX_NEXT_NODUP: - rc = mdbx_cursor_next(mc, key, data, op); - break; - case MDBX_PREV: - case MDBX_PREV_DUP: - case MDBX_PREV_NODUP: - rc = mdbx_cursor_prev(mc, key, data, op); - break; - case MDBX_FIRST: - rc = mdbx_cursor_first(mc, key, data); - break; - case MDBX_FIRST_DUP: - mfunc = mdbx_cursor_first; - mmove: - if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - if (unlikely(mc->mc_xcursor == NULL)) - return MDBX_INCOMPATIBLE; - if (mc->mc_ki[mc->mc_top] >= page_numkeys(mc->mc_pg[mc->mc_top])) { - mc->mc_ki[mc->mc_top] = (indx_t)page_numkeys(mc->mc_pg[mc->mc_top]); - return MDBX_NOTFOUND; - } - { - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (!F_ISSET(node_flags(node), F_DUPDATA)) { - get_key_optional(node, key); - rc = mdbx_node_read(mc, node, data); - break; - } - } - if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL); - break; - case MDBX_LAST: - rc = mdbx_cursor_last(mc, key, data); - break; - case MDBX_LAST_DUP: - mfunc = mdbx_cursor_last; - goto mmove; - default: - mdbx_debug("unhandled/unimplemented cursor operation %u", op); - return MDBX_EINVAL; - } - - mc->mc_flags &= ~C_DEL; - return rc; -} - -/* Touch all the pages in the cursor stack. Set mc_top. - * Makes sure all the pages are writable, before attempting a write operation. - * [in] mc The cursor to operate on. */ -static int mdbx_cursor_touch(MDBX_cursor *mc) { - int rc = MDBX_SUCCESS; - - if (mc->mc_dbi >= CORE_DBS && - (*mc->mc_dbflag & (DB_DIRTY | DB_DUPDATA)) == 0) { - mdbx_cassert(mc, (mc->mc_flags & C_RECLAIMING) == 0); - /* Touch DB record of named DB */ - MDBX_cursor_couple cx; - if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) - return MDBX_BAD_DBI; - rc = mdbx_cursor_init(&cx.outer, mc->mc_txn, MAIN_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_page_search(&cx.outer, &mc->mc_dbx->md_name, MDBX_PS_MODIFY); - if (unlikely(rc)) - return rc; - *mc->mc_dbflag |= DB_DIRTY; - } - mc->mc_top = 0; - if (mc->mc_snum) { - do { - rc = mdbx_page_touch(mc); - } while (!rc && ++(mc->mc_top) < mc->mc_snum); - mc->mc_top = mc->mc_snum - 1; - } - return rc; -} - -int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - unsigned flags) { - MDBX_env *env; - MDBX_page *fp, *sub_root = NULL; - uint16_t fp_flags; - MDBX_val xdata, *rdata, dkey, olddata; - MDBX_db nested_dupdb; - unsigned mcount = 0, dcount = 0, nospill; - size_t nsize; - int rc2; - unsigned nflags; - DKBUF; - - if (unlikely(mc == NULL || key == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn_rw(mc->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - env = mc->mc_txn->mt_env; - - /* Check this first so counter will always be zero on any early failures. */ - if (flags & MDBX_MULTIPLE) { - if (unlikely(!F_ISSET(mc->mc_db->md_flags, MDBX_DUPFIXED))) - return MDBX_INCOMPATIBLE; - if (unlikely(data[1].iov_len >= INT_MAX)) - return MDBX_EINVAL; - dcount = (unsigned)data[1].iov_len; - data[1].iov_len = 0; - } - - if (flags & MDBX_RESERVE) { - if (unlikely(mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_REVERSEDUP))) - return MDBX_INCOMPATIBLE; - data->iov_base = nullptr; - } - - nospill = flags & MDBX_NOSPILL; - flags &= ~MDBX_NOSPILL; - - if (unlikely(mc->mc_txn->mt_flags & (MDBX_RDONLY | MDBX_TXN_BLOCKED))) - return (mc->mc_txn->mt_flags & MDBX_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; - - if (unlikely(key->iov_len > env->me_maxkey_limit)) - return MDBX_BAD_VALSIZE; - - if (unlikely(data->iov_len > ((mc->mc_db->md_flags & MDBX_DUPSORT) - ? env->me_maxkey_limit - : MDBX_MAXDATASIZE))) - return MDBX_BAD_VALSIZE; - - if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) && - unlikely(key->iov_len != sizeof(uint32_t) && - key->iov_len != sizeof(uint64_t))) { - mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY"); - return MDBX_BAD_VALSIZE; - } - - if ((mc->mc_db->md_flags & MDBX_INTEGERDUP) && - unlikely(data->iov_len != sizeof(uint32_t) && - data->iov_len != sizeof(uint64_t))) { - mdbx_cassert(mc, !"data-size is invalid MDBX_INTEGERDUP"); - return MDBX_BAD_VALSIZE; - } - - mdbx_debug("==> put db %d key [%s], size %" PRIuPTR - ", data [%s] size %" PRIuPTR, - DDBI(mc), DKEY(key), key ? key->iov_len : 0, - DVAL((flags & MDBX_RESERVE) ? nullptr : data), data->iov_len); - - int dupdata_flag = 0; - if ((flags & MDBX_CURRENT) != 0 && (mc->mc_flags & C_SUB) == 0) { - /* ÐžÐ¿Ñ†Ð¸Ñ MDBX_CURRENT означает, что запрошено обновление текущей запиÑи, - * на которой ÑÐµÐ¹Ñ‡Ð°Ñ Ñтоит курÑор. ПроверÑем что переданный ключ Ñовпадает - * Ñо значением в текущей позиции курÑора. - * ЗдеÑÑŒ проще вызвать mdbx_cursor_get(), так как Ð´Ð»Ñ Ð¾Ð±ÑÐ»ÑƒÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† - * Ñ MDBX_DUPSORT также требуетÑÑ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¹ размер данных. */ - MDBX_val current_key, current_data; - rc = mdbx_cursor_get(mc, ¤t_key, ¤t_data, MDBX_GET_CURRENT); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - if (mc->mc_dbx->md_cmp(key, ¤t_key) != 0) - return MDBX_EKEYMISMATCH; - - if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) { - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - mdbx_cassert(mc, - mc->mc_xcursor != NULL && - (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)); - /* ЕÑли за ключом более одного значениÑ, либо еÑли размер данных - * отличаетÑÑ, то вмеÑто inplace Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ и - * поÑÐ»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð²Ñтавка. */ - if (mc->mc_xcursor->mx_db.md_entries > 1 || - current_data.iov_len != data->iov_len) { - rc = mdbx_cursor_del(mc, 0); - if (rc != MDBX_SUCCESS) - return rc; - flags -= MDBX_CURRENT; - } - } else if (unlikely(node_size(key, data) > env->me_nodemax)) { - rc = mdbx_cursor_del(mc, 0); - if (rc != MDBX_SUCCESS) - return rc; - flags -= MDBX_CURRENT; - } - } - } - - if (mc->mc_db->md_root == P_INVALID) { - /* new database, cursor has nothing to point to */ - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_flags &= ~C_INITIALIZED; - rc = MDBX_NO_ROOT; - } else if ((flags & MDBX_CURRENT) == 0) { - int exact = 0; - MDBX_val d2; - if (flags & MDBX_APPEND) { - MDBX_val k2; - rc = mdbx_cursor_last(mc, &k2, &d2); - if (rc == 0) { - rc = mc->mc_dbx->md_cmp(key, &k2); - if (rc > 0) { - rc = MDBX_NOTFOUND; - mc->mc_ki[mc->mc_top]++; - } else if (unlikely(rc < 0 || (flags & MDBX_APPENDDUP) == 0)) { - /* new key is <= last key */ - rc = MDBX_EKEYMISMATCH; - } - } - } else { - rc = mdbx_cursor_set(mc, key, &d2, MDBX_SET, &exact); - } - if ((flags & MDBX_NOOVERWRITE) && - (rc == MDBX_SUCCESS || rc == MDBX_EKEYMISMATCH)) { - mdbx_debug("duplicate key [%s]", DKEY(key)); - *data = d2; - return MDBX_KEYEXIST; - } - if (rc && unlikely(rc != MDBX_NOTFOUND)) - return rc; - } - - mc->mc_flags &= ~C_DEL; - - /* Cursor is positioned, check for room in the dirty list */ - if (!nospill) { - if (flags & MDBX_MULTIPLE) { - rdata = &xdata; - xdata.iov_len = data->iov_len * dcount; - } else { - rdata = data; - } - if (unlikely(rc2 = mdbx_page_spill(mc, key, rdata))) - return rc2; - } - - if (rc == MDBX_NO_ROOT) { - MDBX_page *np; - /* new database, write a root leaf page */ - mdbx_debug("%s", "allocating new root leaf page"); - if (unlikely(rc2 = mdbx_page_new(mc, P_LEAF, 1, &np))) { - return rc2; - } - rc2 = mdbx_cursor_push(mc, np); - if (unlikely(rc2 != MDBX_SUCCESS)) - return rc2; - mc->mc_db->md_root = np->mp_pgno; - mc->mc_db->md_depth++; - *mc->mc_dbflag |= DB_DIRTY; - if ((mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_DUPFIXED)) == MDBX_DUPFIXED) - np->mp_flags |= P_LEAF2; - mc->mc_flags |= C_INITIALIZED; - } else { - /* make sure all cursor pages are writable */ - rc2 = mdbx_cursor_touch(mc); - if (unlikely(rc2)) - return rc2; - } - - bool insert_key, insert_data, do_sub = false; - insert_key = insert_data = (rc != MDBX_SUCCESS); - if (insert_key) { - /* The key does not exist */ - mdbx_debug("inserting key at index %i", mc->mc_ki[mc->mc_top]); - if ((mc->mc_db->md_flags & MDBX_DUPSORT) && - node_size(key, data) > env->me_nodemax) { - /* Too big for a node, insert in sub-DB. Set up an empty - * "old sub-page" for prep_subDB to expand to a full page. */ - fp_flags = P_LEAF | P_DIRTY; - fp = env->me_pbuf; - fp->mp_leaf2_ksize = (uint16_t)data->iov_len; /* used if MDBX_DUPFIXED */ - fp->mp_lower = fp->mp_upper = 0; - olddata.iov_len = PAGEHDRSZ; - goto prep_subDB; - } - } else { - /* there's only a key anyway, so this is a no-op */ - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - char *ptr; - unsigned ksize = mc->mc_db->md_xsize; - if (key->iov_len != ksize) - return MDBX_BAD_VALSIZE; - ptr = page_leaf2key(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize); - memcpy(ptr, key->iov_base, ksize); - fix_parent: - /* if overwriting slot 0 of leaf, need to - * update branch key if there is a parent page */ - if (mc->mc_top && !mc->mc_ki[mc->mc_top]) { - unsigned dtop = 1; - mc->mc_top--; - /* slot 0 is always an empty key, find real slot */ - while (mc->mc_top && !mc->mc_ki[mc->mc_top]) { - mc->mc_top--; - dtop++; - } - if (mc->mc_ki[mc->mc_top]) - rc2 = mdbx_update_key(mc, key); - else - rc2 = MDBX_SUCCESS; - mdbx_cassert(mc, mc->mc_top + dtop < UINT16_MAX); - mc->mc_top += (uint16_t)dtop; - if (rc2) - return rc2; - } - - if (mdbx_audit_enabled()) { - int err = mdbx_cursor_check(mc, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - return MDBX_SUCCESS; - } - - more:; - if (mdbx_audit_enabled()) { - int err = mdbx_cursor_check(mc, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - - /* overflow page overwrites need special handling */ - if (unlikely(F_ISSET(node_flags(node), F_BIGDATA))) { - int level, ovpages, - dpages = (node_size(key, data) > env->me_nodemax) - ? number_of_ovpages(env, data->iov_len) - : 0; - - const pgno_t pg = node_largedata_pgno(node); - MDBX_page *omp; - if (unlikely((rc2 = mdbx_page_get(mc, pg, &omp, &level)) != 0)) - return rc2; - ovpages = omp->mp_pages; - - /* Is the ov page large enough? */ - if (unlikely(mc->mc_flags & C_GCFREEZE) - ? ovpages >= dpages - : ovpages == - /* LY: add configurable threshold to keep reserve space */ - dpages) { - if (!IS_DIRTY(omp) && (level || (env->me_flags & MDBX_WRITEMAP))) { - rc = mdbx_page_unspill(mc->mc_txn, omp, &omp); - if (unlikely(rc)) - return rc; - level = 0; /* dirty in this txn or clean */ - } - /* Is it dirty? */ - if (IS_DIRTY(omp)) { - /* yes, overwrite it. Note in this case we don't - * bother to try shrinking the page if the new data - * is smaller than the overflow threshold. */ - if (unlikely(level > 1)) { - /* It is writable only in a parent txn */ - MDBX_page *np = mdbx_page_malloc(mc->mc_txn, ovpages); - if (unlikely(!np)) - return MDBX_ENOMEM; - /* Note - this page is already counted in parent's dirtyroom */ - rc2 = mdbx_dpl_append(mc->mc_txn->tw.dirtylist, pg, np); - if (unlikely(rc2 != MDBX_SUCCESS)) { - rc = rc2; - mdbx_dpage_free(env, np, ovpages); - goto fail; - } - - /* Currently we make the page look as with put() in the - * parent txn, in case the user peeks at MDBX_RESERVEd - * or unused parts. Some users treat ovpages specially. */ - const size_t whole = pgno2bytes(env, ovpages); - /* Skip the part where MDBX will put *data. - * Copy end of page, adjusting alignment so - * compiler may copy words instead of bytes. */ - const size_t off = - (PAGEHDRSZ + data->iov_len) & -(intptr_t)sizeof(size_t); - memcpy((size_t *)((char *)np + off), (size_t *)((char *)omp + off), - whole - off); - memcpy(np, omp, PAGEHDRSZ); /* Copy header of page */ - omp = np; - } - node_set_ds(node, data->iov_len); - if (F_ISSET(flags, MDBX_RESERVE)) - data->iov_base = page_data(omp); - else - memcpy(page_data(omp), data->iov_base, data->iov_len); - - if (mdbx_audit_enabled()) { - int err = mdbx_cursor_check(mc, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - return MDBX_SUCCESS; - } - } - if ((rc2 = mdbx_page_retire(mc, omp)) != MDBX_SUCCESS) - return rc2; - } else { - olddata.iov_len = node_ds(node); - olddata.iov_base = node_data(node); - mdbx_cassert(mc, (char *)olddata.iov_base + olddata.iov_len <= - (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize); - - /* DB has dups? */ - if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) { - /* Prepare (sub-)page/sub-DB to accept the new item, if needed. - * fp: old sub-page or a header faking it. - * mp: new (sub-)page. offset: growth in page size. - * xdata: node data with new page or DB. */ - unsigned i; - size_t offset = 0; - MDBX_page *mp = fp = xdata.iov_base = env->me_pbuf; - mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno; - - /* Was a single item before, must convert now */ - if (!F_ISSET(node_flags(node), F_DUPDATA)) { - - /* Just overwrite the current item */ - if (flags & MDBX_CURRENT) { - mdbx_cassert(mc, node_size(key, data) <= env->me_nodemax); - goto current; - } - - /* does data match? */ - if (!mc->mc_dbx->md_dcmp(data, &olddata)) { - if (unlikely(flags & (MDBX_NODUPDATA | MDBX_APPENDDUP))) - return MDBX_KEYEXIST; - /* overwrite it */ - mdbx_cassert(mc, node_size(key, data) <= env->me_nodemax); - goto current; - } - - /* Back up original data item */ - dupdata_flag = 1; - dkey.iov_len = olddata.iov_len; - dkey.iov_base = memcpy(fp + 1, olddata.iov_base, olddata.iov_len); - - /* Make sub-page header for the dup items, with dummy body */ - fp->mp_flags = P_LEAF | P_DIRTY | P_SUBP; - fp->mp_lower = 0; - xdata.iov_len = PAGEHDRSZ + dkey.iov_len + data->iov_len; - if (mc->mc_db->md_flags & MDBX_DUPFIXED) { - fp->mp_flags |= P_LEAF2; - fp->mp_leaf2_ksize = (uint16_t)data->iov_len; - xdata.iov_len += 2 * data->iov_len; /* leave space for 2 more */ - mdbx_cassert(mc, xdata.iov_len <= env->me_psize); - } else { - xdata.iov_len += 2 * (sizeof(indx_t) + NODESIZE) + - (dkey.iov_len & 1) + (data->iov_len & 1); - mdbx_cassert(mc, xdata.iov_len <= env->me_psize); - } - fp->mp_upper = (uint16_t)(xdata.iov_len - PAGEHDRSZ); - olddata.iov_len = xdata.iov_len; /* pretend olddata is fp */ - } else if (node_flags(node) & F_SUBDATA) { - /* Data is on sub-DB, just store it */ - flags |= F_DUPDATA | F_SUBDATA; - goto put_sub; - } else { - /* Data is on sub-page */ - fp = olddata.iov_base; - switch (flags) { - default: - if (!(mc->mc_db->md_flags & MDBX_DUPFIXED)) { - offset = node_size(data, nullptr) + sizeof(indx_t); - break; - } - offset = fp->mp_leaf2_ksize; - if (page_room(fp) < offset) { - offset *= 4; /* space for 4 more */ - break; - } - /* FALLTHRU: Big enough MDBX_DUPFIXED sub-page */ - __fallthrough; - case MDBX_CURRENT | MDBX_NODUPDATA: - case MDBX_CURRENT: - fp->mp_flags |= P_DIRTY; - fp->mp_pgno = mp->mp_pgno; - mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; - flags |= F_DUPDATA; - goto put_sub; - } - xdata.iov_len = olddata.iov_len + offset; - } - - fp_flags = fp->mp_flags; - if (NODESIZE + node_ks(node) + xdata.iov_len > env->me_nodemax) { - /* Too big for a sub-page, convert to sub-DB */ - fp_flags &= ~P_SUBP; - prep_subDB: - nested_dupdb.md_xsize = 0; - nested_dupdb.md_flags = 0; - if (mc->mc_db->md_flags & MDBX_DUPFIXED) { - fp_flags |= P_LEAF2; - nested_dupdb.md_xsize = fp->mp_leaf2_ksize; - nested_dupdb.md_flags = MDBX_DUPFIXED; - if (mc->mc_db->md_flags & MDBX_INTEGERDUP) - nested_dupdb.md_flags |= MDBX_INTEGERKEY; - } - nested_dupdb.md_depth = 1; - nested_dupdb.md_branch_pages = 0; - nested_dupdb.md_leaf_pages = 1; - nested_dupdb.md_overflow_pages = 0; - nested_dupdb.md_entries = page_numkeys(fp); - xdata.iov_len = sizeof(nested_dupdb); - xdata.iov_base = &nested_dupdb; - if ((rc = mdbx_page_alloc(mc, 1, &mp, MDBX_ALLOC_ALL))) - return rc; - mc->mc_db->md_leaf_pages += 1; - mdbx_cassert(mc, env->me_psize > olddata.iov_len); - offset = env->me_psize - (unsigned)olddata.iov_len; - flags |= F_DUPDATA | F_SUBDATA; - nested_dupdb.md_root = mp->mp_pgno; - nested_dupdb.md_seq = nested_dupdb.md_mod_txnid = 0; - sub_root = mp; - } - if (mp != fp) { - mp->mp_flags = fp_flags | P_DIRTY; - mp->mp_leaf2_ksize = fp->mp_leaf2_ksize; - mp->mp_lower = fp->mp_lower; - mdbx_cassert(mc, fp->mp_upper + offset <= UINT16_MAX); - mp->mp_upper = (indx_t)(fp->mp_upper + offset); - if (unlikely(fp_flags & P_LEAF2)) { - memcpy(page_data(mp), page_data(fp), - page_numkeys(fp) * fp->mp_leaf2_ksize); - } else { - memcpy((char *)mp + mp->mp_upper + PAGEHDRSZ, - (char *)fp + fp->mp_upper + PAGEHDRSZ, - olddata.iov_len - fp->mp_upper - PAGEHDRSZ); - memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs), - page_numkeys(fp) * sizeof(mp->mp_ptrs[0])); - for (i = 0; i < page_numkeys(fp); i++) { - mdbx_cassert(mc, mp->mp_ptrs[i] + offset <= UINT16_MAX); - mp->mp_ptrs[i] += (indx_t)offset; - } - } - } - - rdata = &xdata; - flags |= F_DUPDATA; - do_sub = true; - if (!insert_key) - mdbx_node_del(mc, 0); - goto new_sub; - } - - /* MDBX passes F_SUBDATA in 'flags' to write a DB record */ - if (unlikely((node_flags(node) ^ flags) & F_SUBDATA)) - return MDBX_INCOMPATIBLE; - - current: - if (data->iov_len == olddata.iov_len) { - mdbx_cassert(mc, EVEN(key->iov_len) == EVEN(node_ks(node))); - /* same size, just replace it. Note that we could - * also reuse this node if the new data is smaller, - * but instead we opt to shrink the node in that case. */ - if (F_ISSET(flags, MDBX_RESERVE)) - data->iov_base = olddata.iov_base; - else if (!(mc->mc_flags & C_SUB)) - memcpy(olddata.iov_base, data->iov_base, data->iov_len); - else { - mdbx_cassert(mc, page_numkeys(mc->mc_pg[mc->mc_top]) == 1); - mdbx_cassert(mc, PAGETYPE(mc->mc_pg[mc->mc_top]) == P_LEAF); - mdbx_cassert(mc, node_ds(node) == 0); - mdbx_cassert(mc, node_flags(node) == 0); - mdbx_cassert(mc, key->iov_len < UINT16_MAX); - node_set_ks(node, key->iov_len); - memcpy(node_key(node), key->iov_base, key->iov_len); - mdbx_cassert(mc, (char *)node_key(node) + node_ds(node) < - (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize); - goto fix_parent; - } - - if (mdbx_audit_enabled()) { - int err = mdbx_cursor_check(mc, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - return MDBX_SUCCESS; - } - } - mdbx_node_del(mc, 0); - } - - rdata = data; - -new_sub: - nflags = flags & NODE_ADD_FLAGS; - nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->iov_len - : leaf_size(env, key, rdata); - if (page_room(mc->mc_pg[mc->mc_top]) < nsize) { - if ((flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) - nflags &= ~MDBX_APPEND; /* sub-page may need room to grow */ - if (!insert_key) - nflags |= MDBX_SPLIT_REPLACE; - rc = mdbx_page_split(mc, key, rdata, P_INVALID, nflags); - if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) - rc = mdbx_cursor_check(mc, false); - } else { - /* There is room already in this leaf page. */ - if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { - mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0 && - rdata->iov_len == 0); - rc = mdbx_node_add_leaf2(mc, mc->mc_ki[mc->mc_top], key); - } else - rc = mdbx_node_add_leaf(mc, mc->mc_ki[mc->mc_top], key, rdata, nflags); - if (likely(rc == 0)) { - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2, *m3; - MDBX_dbi dbi = mc->mc_dbi; - unsigned i = mc->mc_top; - MDBX_page *mp = mc->mc_pg[i]; - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp) - continue; - if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) { - m3->mc_ki[i]++; - } - if (XCURSOR_INITED(m3)) - XCURSOR_REFRESH(m3, mp, m3->mc_ki[i]); - } - } - } - - if (likely(rc == MDBX_SUCCESS)) { - /* Now store the actual data in the child DB. Note that we're - * storing the user data in the keys field, so there are strict - * size limits on dupdata. The actual data fields of the child - * DB are all zero size. */ - if (do_sub) { - int xflags; - size_t ecount; - put_sub: - xdata.iov_len = 0; - xdata.iov_base = nullptr; - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (flags & MDBX_CURRENT) { - xflags = (flags & MDBX_NODUPDATA) - ? MDBX_CURRENT | MDBX_NOOVERWRITE | MDBX_NOSPILL - : MDBX_CURRENT | MDBX_NOSPILL; - } else { - rc2 = mdbx_xcursor_init1(mc, node); - if (unlikely(rc2 != MDBX_SUCCESS)) - return rc2; - xflags = (flags & MDBX_NODUPDATA) ? MDBX_NOOVERWRITE | MDBX_NOSPILL - : MDBX_NOSPILL; - } - if (sub_root) - mc->mc_xcursor->mx_cursor.mc_pg[0] = sub_root; - /* converted, write the original data first */ - if (dupdata_flag) { - rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); - if (unlikely(rc)) - goto bad_sub; - /* we've done our job */ - dkey.iov_len = 0; - } - if (!(node_flags(node) & F_SUBDATA) || sub_root) { - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2; - MDBX_xcursor *mx = mc->mc_xcursor; - unsigned i = mc->mc_top; - MDBX_page *mp = mc->mc_pg[i]; - const int nkeys = page_numkeys(mp); - - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { - if (m2 == mc || m2->mc_snum < mc->mc_snum) - continue; - if (!(m2->mc_flags & C_INITIALIZED)) - continue; - if (m2->mc_pg[i] == mp) { - if (m2->mc_ki[i] == mc->mc_ki[i]) { - rc2 = mdbx_xcursor_init2(m2, mx, dupdata_flag); - if (unlikely(rc2 != MDBX_SUCCESS)) - return rc2; - } else if (!insert_key && m2->mc_ki[i] < nkeys) { - XCURSOR_REFRESH(m2, mp, m2->mc_ki[i]); - } - } - } - } - mdbx_cassert(mc, mc->mc_xcursor->mx_db.md_entries < PTRDIFF_MAX); - ecount = (size_t)mc->mc_xcursor->mx_db.md_entries; - if (flags & MDBX_APPENDDUP) - xflags |= MDBX_APPEND; - rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); - if (flags & F_SUBDATA) { - void *db = node_data(node); - memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db)); - } - insert_data = (ecount != (size_t)mc->mc_xcursor->mx_db.md_entries); - } - /* Increment count unless we just replaced an existing item. */ - if (insert_data) - mc->mc_db->md_entries++; - if (insert_key) { - /* Invalidate txn if we created an empty sub-DB */ - if (unlikely(rc)) - goto bad_sub; - /* If we succeeded and the key didn't exist before, - * make sure the cursor is marked valid. */ - mc->mc_flags |= C_INITIALIZED; - } - if (flags & MDBX_MULTIPLE) { - if (!rc) { - mcount++; - /* let caller know how many succeeded, if any */ - data[1].iov_len = mcount; - if (mcount < dcount) { - data[0].iov_base = (char *)data[0].iov_base + data[0].iov_len; - insert_key = insert_data = false; - goto more; - } - } - } - if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) - rc = mdbx_cursor_check(mc, false); - return rc; - bad_sub: - if (unlikely(rc == MDBX_KEYEXIST)) - mdbx_error("unexpected %s", "MDBX_KEYEXIST"); - /* should not happen, we deleted that item */ - rc = MDBX_PROBLEM; - } -fail: - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return rc; -} - -int mdbx_cursor_del(MDBX_cursor *mc, unsigned flags) { - if (unlikely(!mc)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn_rw(mc->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!(mc->mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - - if (unlikely(mc->mc_ki[mc->mc_top] >= page_numkeys(mc->mc_pg[mc->mc_top]))) - return MDBX_NOTFOUND; - - if (unlikely(!(flags & MDBX_NOSPILL) && - (rc = mdbx_page_spill(mc, NULL, NULL)))) - return rc; - - rc = mdbx_cursor_touch(mc); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - if (IS_LEAF2(mp)) - goto del_key; - - MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - if (flags & MDBX_NODUPDATA) { - /* mdbx_cursor_del0() will subtract the final entry */ - mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1; - mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; - } else { - if (!F_ISSET(node_flags(node), F_SUBDATA)) { - mc->mc_xcursor->mx_cursor.mc_pg[0] = node_data(node); - } - rc = mdbx_cursor_del(&mc->mc_xcursor->mx_cursor, MDBX_NOSPILL); - if (unlikely(rc)) - return rc; - /* If sub-DB still has entries, we're done */ - if (mc->mc_xcursor->mx_db.md_entries) { - if (node_flags(node) & F_SUBDATA) { - /* update subDB info */ - void *db = node_data(node); - memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db)); - } else { - MDBX_cursor *m2; - /* shrink fake page */ - mdbx_node_shrink(mp, mc->mc_ki[mc->mc_top]); - node = page_node(mp, mc->mc_ki[mc->mc_top]); - mc->mc_xcursor->mx_cursor.mc_pg[0] = node_data(node); - /* fix other sub-DB cursors pointed at fake pages on this page */ - for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { - if (m2 == mc || m2->mc_snum < mc->mc_snum) - continue; - if (!(m2->mc_flags & C_INITIALIZED)) - continue; - if (m2->mc_pg[mc->mc_top] == mp) { - MDBX_node *inner = node; - if (m2->mc_ki[mc->mc_top] >= page_numkeys(mp)) - continue; - if (m2->mc_ki[mc->mc_top] != mc->mc_ki[mc->mc_top]) { - inner = page_node(mp, m2->mc_ki[mc->mc_top]); - if (node_flags(inner) & F_SUBDATA) - continue; - } - m2->mc_xcursor->mx_cursor.mc_pg[0] = node_data(inner); - } - } - } - mc->mc_db->md_entries--; - mdbx_cassert(mc, mc->mc_db->md_entries > 0 && mc->mc_db->md_depth > 0 && - mc->mc_db->md_root != P_INVALID); - return rc; - } else { - mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; - } - /* otherwise fall thru and delete the sub-DB */ - } - - if (node_flags(node) & F_SUBDATA) { - /* add all the child DB's pages to the free list */ - rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0); - if (unlikely(rc)) - goto fail; - } - } - /* MDBX passes F_SUBDATA in 'flags' to delete a DB record */ - else if (unlikely((node_flags(node) ^ flags) & F_SUBDATA)) { - rc = MDBX_INCOMPATIBLE; - goto fail; - } - - /* add overflow pages to free list */ - if (F_ISSET(node_flags(node), F_BIGDATA)) { - MDBX_page *omp; - if (unlikely( - (rc = mdbx_page_get(mc, node_largedata_pgno(node), &omp, NULL)) || - (rc = mdbx_page_retire(mc, omp)))) - goto fail; - } - -del_key: - return mdbx_cursor_del0(mc); - -fail: - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return rc; -} - -/* Allocate and initialize new pages for a database. - * Set MDBX_TXN_ERROR on failure. - * - * [in] mc a cursor on the database being added to. - * [in] flags flags defining what type of page is being allocated. - * [in] num the number of pages to allocate. This is usually 1, - * unless allocating overflow pages for a large record. - * [out] mp Address of a page, or NULL on failure. - * - * Returns 0 on success, non-zero on failure. */ -static int mdbx_page_new(MDBX_cursor *mc, unsigned flags, unsigned num, - MDBX_page **mp) { - MDBX_page *np; - int rc; - - if (unlikely((rc = mdbx_page_alloc(mc, num, &np, MDBX_ALLOC_ALL)))) - return rc; - *mp = np; - mdbx_debug("allocated new page #%" PRIaPGNO ", size %u", np->mp_pgno, - mc->mc_txn->mt_env->me_psize); - np->mp_flags = (uint16_t)(flags | P_DIRTY); - np->mp_lower = 0; - np->mp_upper = (indx_t)(mc->mc_txn->mt_env->me_psize - PAGEHDRSZ); - - mc->mc_db->md_branch_pages += IS_BRANCH(np); - mc->mc_db->md_leaf_pages += IS_LEAF(np); - if (unlikely(IS_OVERFLOW(np))) { - mc->mc_db->md_overflow_pages += num; - np->mp_pages = num; - mdbx_cassert(mc, !(mc->mc_flags & C_SUB)); - } else if (unlikely(mc->mc_flags & C_SUB)) { - MDBX_db *outer = mdbx_outer_db(mc); - outer->md_branch_pages += IS_BRANCH(np); - outer->md_leaf_pages += IS_LEAF(np); - } - - return MDBX_SUCCESS; -} - -static int __must_check_result mdbx_node_add_leaf2(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - DKBUF; - mdbx_debug("add to leaf2-%spage %" PRIaPGNO " index %i, " - " key size %" PRIuPTR " [%s]", - IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, - key ? key->iov_len : 0, DKEY(key)); - - mdbx_cassert(mc, key); - mdbx_cassert(mc, PAGETYPE(mp) == (P_LEAF | P_LEAF2)); - const unsigned ksize = mc->mc_db->md_xsize; - mdbx_cassert(mc, ksize == key->iov_len); - const unsigned nkeys = page_numkeys(mp); - - /* Just using these for counting */ - const intptr_t lower = mp->mp_lower + sizeof(indx_t); - const intptr_t upper = mp->mp_upper - (ksize - sizeof(indx_t)); - if (unlikely(lower > upper)) { - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PAGE_FULL; - } - mp->mp_lower = (indx_t)lower; - mp->mp_upper = (indx_t)upper; - - char *const ptr = page_leaf2key(mp, indx, ksize); - mdbx_cassert(mc, nkeys >= indx); - const unsigned diff = nkeys - indx; - if (likely(diff > 0)) - /* Move higher keys up one slot. */ - memmove(ptr + ksize, ptr, diff * ksize); - /* insert new key */ - memcpy(ptr, key->iov_base, ksize); - return MDBX_SUCCESS; -} - -static int __must_check_result mdbx_node_add_branch(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key, - pgno_t pgno) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - DKBUF; - mdbx_debug("add to branch-%spage %" PRIaPGNO " index %i, node-pgno %" PRIaPGNO - " key size %" PRIuPTR " [%s]", - IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, pgno, - key ? key->iov_len : 0, DKEY(key)); - - mdbx_cassert(mc, PAGETYPE(mp) == P_BRANCH); - STATIC_ASSERT(NODESIZE % 2 == 0); - - /* Move higher pointers up one slot. */ - const unsigned nkeys = page_numkeys(mp); - mdbx_cassert(mc, nkeys >= indx); - for (unsigned i = nkeys; i > indx; --i) - mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; - - /* Adjust free space offsets. */ - const size_t branch_bytes = branch_size(mc->mc_txn->mt_env, key); - const intptr_t lower = mp->mp_lower + sizeof(indx_t); - const intptr_t upper = mp->mp_upper - (branch_bytes - sizeof(indx_t)); - if (unlikely(lower > upper)) { - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PAGE_FULL; - } - mp->mp_lower = (indx_t)lower; - mp->mp_ptrs[indx] = mp->mp_upper = (indx_t)upper; - - /* Write the node data. */ - MDBX_node *node = page_node(mp, indx); - node_set_pgno(node, pgno); - node_set_flags(node, 0); - UNALIGNED_POKE_8(node, MDBX_node, mn_extra, 0); - node_set_ks(node, 0); - if (likely(key != NULL)) { - node_set_ks(node, key->iov_len); - memcpy(node_key(node), key->iov_base, key->iov_len); - } - return MDBX_SUCCESS; -} - -static int __must_check_result mdbx_node_add_leaf(MDBX_cursor *mc, - unsigned indx, - const MDBX_val *key, - MDBX_val *data, - unsigned flags) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - DKBUF; - mdbx_debug("add to leaf-%spage %" PRIaPGNO " index %i, data size %" PRIuPTR - " key size %" PRIuPTR " [%s]", - IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, - data ? data->iov_len : 0, key ? key->iov_len : 0, DKEY(key)); - mdbx_cassert(mc, key != NULL && data != NULL); - mdbx_cassert(mc, PAGETYPE(mp) == P_LEAF); - MDBX_page *largepage = NULL; - - size_t leaf_bytes = 0; - if (unlikely(flags & F_BIGDATA)) { - /* Data already on overflow page. */ - STATIC_ASSERT(sizeof(pgno_t) % 2 == 0); - leaf_bytes = node_size(key, nullptr) + sizeof(pgno_t) + sizeof(indx_t); - } else if (unlikely(node_size(key, data) > mc->mc_txn->mt_env->me_nodemax)) { - /* Put data on overflow page. */ - mdbx_cassert(mc, !F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)); - const pgno_t ovpages = number_of_ovpages(mc->mc_txn->mt_env, data->iov_len); - int rc = mdbx_page_new(mc, P_OVERFLOW, ovpages, &largepage); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mdbx_debug("allocated %u overflow page(s) %" PRIaPGNO "for %" PRIuPTR - " data bytes", - largepage->mp_pages, largepage->mp_pgno, data->iov_len); - flags |= F_BIGDATA; - leaf_bytes = node_size(key, nullptr) + sizeof(pgno_t) + sizeof(indx_t); - } else { - leaf_bytes = node_size(key, data) + sizeof(indx_t); - } - mdbx_cassert(mc, leaf_bytes == leaf_size(mc->mc_txn->mt_env, key, data)); - - /* Move higher pointers up one slot. */ - const unsigned nkeys = page_numkeys(mp); - mdbx_cassert(mc, nkeys >= indx); - for (unsigned i = nkeys; i > indx; --i) - mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; - - /* Adjust free space offsets. */ - const intptr_t lower = mp->mp_lower + sizeof(indx_t); - const intptr_t upper = mp->mp_upper - (leaf_bytes - sizeof(indx_t)); - if (unlikely(lower > upper)) { - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PAGE_FULL; - } - mp->mp_lower = (indx_t)lower; - mp->mp_ptrs[indx] = mp->mp_upper = (indx_t)upper; - - /* Write the node data. */ - MDBX_node *node = page_node(mp, indx); - node_set_ks(node, key->iov_len); - node_set_flags(node, (uint8_t)flags); - UNALIGNED_POKE_8(node, MDBX_node, mn_extra, 0); - node_set_ds(node, data->iov_len); - memcpy(node_key(node), key->iov_base, key->iov_len); - - void *nodedata = node_data(node); - if (likely(largepage == NULL)) { - if (unlikely(flags & F_BIGDATA)) - memcpy(nodedata, data->iov_base, sizeof(pgno_t)); - else if (unlikely(flags & MDBX_RESERVE)) - data->iov_base = nodedata; - else if (likely(nodedata != data->iov_base)) - memcpy(nodedata, data->iov_base, data->iov_len); - } else { - poke_pgno(nodedata, largepage->mp_pgno); - nodedata = page_data(largepage); - if (unlikely(flags & MDBX_RESERVE)) - data->iov_base = nodedata; - else if (likely(nodedata != data->iov_base)) - memcpy(nodedata, data->iov_base, data->iov_len); - } - return MDBX_SUCCESS; -} - -/* Delete the specified node from a page. - * [in] mc Cursor pointing to the node to delete. - * [in] ksize The size of a node. Only used if the page is - * part of a MDBX_DUPFIXED database. */ -static void mdbx_node_del(MDBX_cursor *mc, size_t ksize) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - int indx = mc->mc_ki[mc->mc_top]; - int i, j, nkeys, ptr; - MDBX_node *node; - char *base; - - mdbx_debug("delete node %u on %s page %" PRIaPGNO, indx, - IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno); - nkeys = page_numkeys(mp); - mdbx_cassert(mc, indx < nkeys); - - if (IS_LEAF2(mp)) { - mdbx_cassert(mc, ksize >= sizeof(indx_t)); - unsigned diff = nkeys - 1 - indx; - base = page_leaf2key(mp, indx, ksize); - if (diff) - memmove(base, base + ksize, diff * ksize); - mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t)); - mp->mp_lower -= sizeof(indx_t); - mdbx_cassert(mc, - (size_t)UINT16_MAX - mp->mp_upper >= ksize - sizeof(indx_t)); - mp->mp_upper += (indx_t)(ksize - sizeof(indx_t)); - return; - } - - node = page_node(mp, indx); - size_t sz = NODESIZE + node_ks(node); - if (IS_LEAF(mp)) { - if (F_ISSET(node_flags(node), F_BIGDATA)) - sz += sizeof(pgno_t); - else - sz += node_ds(node); - } - sz = EVEN(sz); - - ptr = mp->mp_ptrs[indx]; - for (i = j = 0; i < nkeys; i++) { - if (i != indx) { - mp->mp_ptrs[j] = mp->mp_ptrs[i]; - if (mp->mp_ptrs[i] < ptr) { - mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_ptrs[j] >= sz); - mp->mp_ptrs[j] += (indx_t)sz; - } - j++; - } - } - - base = (char *)mp + mp->mp_upper + PAGEHDRSZ; - memmove(base + sz, base, ptr - mp->mp_upper); - - mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t)); - mp->mp_lower -= sizeof(indx_t); - mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_upper >= sz); - mp->mp_upper += (indx_t)sz; -} - -/* Compact the main page after deleting a node on a subpage. - * [in] mp The main page to operate on. - * [in] indx The index of the subpage on the main page. */ -static void mdbx_node_shrink(MDBX_page *mp, unsigned indx) { - MDBX_node *node; - MDBX_page *sp, *xp; - char *base; - size_t nsize, delta, len, ptr; - int i; - - node = page_node(mp, indx); - sp = (MDBX_page *)node_data(node); - delta = page_room(sp); - assert(delta > 0); - - /* Prepare to shift upward, set len = length(subpage part to shift) */ - if (IS_LEAF2(sp)) { - delta &= /* do not make the node uneven-sized */ ~1u; - if (unlikely(delta) == 0) - return; - nsize = node_ds(node) - delta; - assert(nsize % 1 == 0); - len = nsize; - } else { - xp = (MDBX_page *)((char *)sp + delta); /* destination subpage */ - for (i = page_numkeys(sp); --i >= 0;) { - assert(sp->mp_ptrs[i] >= delta); - xp->mp_ptrs[i] = (indx_t)(sp->mp_ptrs[i] - delta); - } - nsize = node_ds(node) - delta; - len = PAGEHDRSZ; - } - sp->mp_upper = sp->mp_lower; - sp->mp_pgno = mp->mp_pgno; - node_set_ds(node, nsize); - - /* Shift upward */ - base = (char *)mp + mp->mp_upper + PAGEHDRSZ; - memmove(base + delta, base, (char *)sp + len - base); - - ptr = mp->mp_ptrs[indx]; - for (i = page_numkeys(mp); --i >= 0;) { - if (mp->mp_ptrs[i] <= ptr) { - assert((size_t)UINT16_MAX - mp->mp_ptrs[i] >= delta); - mp->mp_ptrs[i] += (indx_t)delta; - } - } - assert((size_t)UINT16_MAX - mp->mp_upper >= delta); - mp->mp_upper += (indx_t)delta; -} - -/* Initial setup of a sorted-dups cursor. - * - * Sorted duplicates are implemented as a sub-database for the given key. - * The duplicate data items are actually keys of the sub-database. - * Operations on the duplicate data items are performed using a sub-cursor - * initialized when the sub-database is first accessed. This function does - * the preliminary setup of the sub-cursor, filling in the fields that - * depend only on the parent DB. - * - * [in] mc The main cursor whose sorted-dups cursor is to be initialized. */ -static int mdbx_xcursor_init0(MDBX_cursor *mc) { - MDBX_xcursor *mx = mc->mc_xcursor; - if (unlikely(mx == nullptr)) - return MDBX_CORRUPTED; - - mx->mx_cursor.mc_xcursor = NULL; - mx->mx_cursor.mc_txn = mc->mc_txn; - mx->mx_cursor.mc_db = &mx->mx_db; - mx->mx_cursor.mc_dbx = &mx->mx_dbx; - mx->mx_cursor.mc_dbi = mc->mc_dbi; - mx->mx_cursor.mc_dbflag = &mx->mx_dbflag; - mx->mx_cursor.mc_snum = 0; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags = C_SUB; - mx->mx_dbx.md_name.iov_len = 0; - mx->mx_dbx.md_name.iov_base = NULL; - mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp; - mx->mx_dbx.md_dcmp = NULL; - return MDBX_SUCCESS; -} - -/* Final setup of a sorted-dups cursor. - * Sets up the fields that depend on the data from the main cursor. - * [in] mc The main cursor whose sorted-dups cursor is to be initialized. - * [in] node The data containing the MDBX_db record for the sorted-dup database. - */ -static int mdbx_xcursor_init1(MDBX_cursor *mc, MDBX_node *node) { - MDBX_xcursor *mx = mc->mc_xcursor; - if (unlikely(mx == nullptr)) - return MDBX_CORRUPTED; - - if (node_flags(node) & F_SUBDATA) { - if (unlikely(node_ds(node) != sizeof(MDBX_db))) - return MDBX_CORRUPTED; - memcpy(&mx->mx_db, node_data(node), sizeof(MDBX_db)); - mx->mx_cursor.mc_pg[0] = 0; - mx->mx_cursor.mc_snum = 0; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags = C_SUB; - } else { - if (unlikely(node_ds(node) <= PAGEHDRSZ)) - return MDBX_CORRUPTED; - MDBX_page *fp = node_data(node); - mx->mx_db.md_xsize = 0; - mx->mx_db.md_flags = 0; - mx->mx_db.md_depth = 1; - mx->mx_db.md_branch_pages = 0; - mx->mx_db.md_leaf_pages = 1; - mx->mx_db.md_overflow_pages = 0; - mx->mx_db.md_entries = page_numkeys(fp); - mx->mx_db.md_root = fp->mp_pgno; - mx->mx_cursor.mc_snum = 1; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags = C_INITIALIZED | C_SUB; - mx->mx_cursor.mc_pg[0] = fp; - mx->mx_cursor.mc_ki[0] = 0; - if (mc->mc_db->md_flags & MDBX_DUPFIXED) { - mx->mx_db.md_flags = MDBX_DUPFIXED; - mx->mx_db.md_xsize = fp->mp_leaf2_ksize; - if (mc->mc_db->md_flags & MDBX_INTEGERDUP) - mx->mx_db.md_flags |= MDBX_INTEGERKEY; - } - } - mdbx_debug("Sub-db -%u root page %" PRIaPGNO, mx->mx_cursor.mc_dbi, - mx->mx_db.md_root); - mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA; - return MDBX_SUCCESS; -} - -/* Fixup a sorted-dups cursor due to underlying update. - * Sets up some fields that depend on the data from the main cursor. - * Almost the same as init1, but skips initialization steps if the - * xcursor had already been used. - * [in] mc The main cursor whose sorted-dups cursor is to be fixed up. - * [in] src_mx The xcursor of an up-to-date cursor. - * [in] new_dupdata True if converting from a non-F_DUPDATA item. */ -static int mdbx_xcursor_init2(MDBX_cursor *mc, MDBX_xcursor *src_mx, - int new_dupdata) { - MDBX_xcursor *mx = mc->mc_xcursor; - if (unlikely(mx == nullptr)) - return MDBX_CORRUPTED; - - if (new_dupdata) { - mx->mx_cursor.mc_snum = 1; - mx->mx_cursor.mc_top = 0; - mx->mx_cursor.mc_flags |= C_INITIALIZED; - mx->mx_cursor.mc_ki[0] = 0; - mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA; - mx->mx_dbx.md_cmp = src_mx->mx_dbx.md_cmp; - } else if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) { - return MDBX_SUCCESS; - } - mx->mx_db = src_mx->mx_db; - mx->mx_cursor.mc_pg[0] = src_mx->mx_cursor.mc_pg[0]; - mdbx_debug("Sub-db -%u root page %" PRIaPGNO, mx->mx_cursor.mc_dbi, - mx->mx_db.md_root); - return MDBX_SUCCESS; -} - -/* Initialize a cursor for a given transaction and database. */ -static int mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, MDBX_dbi dbi) { - mc->mc_signature = MDBX_MC_SIGNATURE; - mc->mc_next = NULL; - mc->mc_backup = NULL; - mc->mc_dbi = dbi; - mc->mc_txn = txn; - mc->mc_db = &txn->mt_dbs[dbi]; - mc->mc_dbx = &txn->mt_dbxs[dbi]; - mc->mc_dbflag = &txn->mt_dbflags[dbi]; - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_pg[0] = 0; - mc->mc_flags = 0; - mc->mc_ki[0] = 0; - mc->mc_xcursor = NULL; - - if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) { - STATIC_ASSERT(offsetof(MDBX_cursor_couple, outer) == 0); - MDBX_xcursor *mx = &container_of(mc, MDBX_cursor_couple, outer)->inner; - mdbx_tassert(txn, mx != NULL); - mx->mx_cursor.mc_signature = MDBX_MC_SIGNATURE; - mc->mc_xcursor = mx; - int rc = mdbx_xcursor_init0(mc); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - int rc = MDBX_SUCCESS; - if (unlikely(*mc->mc_dbflag & DB_STALE)) { - rc = mdbx_page_search(mc, NULL, MDBX_PS_ROOTONLY); - rc = (rc != MDBX_NOTFOUND) ? rc : MDBX_SUCCESS; - } - return rc; -} - -int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) { - if (unlikely(!ret)) - return MDBX_EINVAL; - *ret = NULL; - - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) - return MDBX_EINVAL; - - if (unlikely(dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDBX_RDONLY))) - return MDBX_EACCESS; - - const size_t size = (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) - ? sizeof(MDBX_cursor_couple) - : sizeof(MDBX_cursor); - - MDBX_cursor *mc; - if (likely((mc = mdbx_malloc(size)) != NULL)) { - rc = mdbx_cursor_init(mc, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_free(mc); - return rc; - } - if (txn->mt_cursors) { - mc->mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = mc; - mc->mc_flags |= C_UNTRACK; - } - } else { - return MDBX_ENOMEM; - } - - *ret = mc; - return MDBX_SUCCESS; -} - -int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) { - if (unlikely(!mc)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE && - mc->mc_signature != MDBX_MC_READY4CLOSE)) - return MDBX_EINVAL; - - int rc = check_txn(mc->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID))) - return MDBX_EINVAL; - - if (unlikely(mc->mc_backup)) - return MDBX_EINVAL; - - if (unlikely((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)) { - MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; - while (*prev && *prev != mc) - prev = &(*prev)->mc_next; - if (*prev == mc) - *prev = mc->mc_next; - mc->mc_signature = MDBX_MC_READY4CLOSE; - } - - if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) - return MDBX_BAD_TXN; - - return mdbx_cursor_init(mc, txn, mc->mc_dbi); -} - -/* Return the count of duplicate data items for the current key */ -int mdbx_cursor_count(MDBX_cursor *mc, size_t *countp) { - if (unlikely(mc == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn(mc->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(countp == NULL || !(mc->mc_flags & C_INITIALIZED))) - return MDBX_EINVAL; - - if (!mc->mc_snum) { - *countp = 0; - return MDBX_NOTFOUND; - } - - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - if ((mc->mc_flags & C_EOF) && mc->mc_ki[mc->mc_top] >= page_numkeys(mp)) { - *countp = 0; - return MDBX_NOTFOUND; - } - - *countp = 1; - if (mc->mc_xcursor != NULL) { - MDBX_node *node = page_node(mp, mc->mc_ki[mc->mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - mdbx_cassert(mc, mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags & - C_INITIALIZED)); - *countp = unlikely(mc->mc_xcursor->mx_db.md_entries > PTRDIFF_MAX) - ? PTRDIFF_MAX - : (size_t)mc->mc_xcursor->mx_db.md_entries; - } - } - return MDBX_SUCCESS; -} - -void mdbx_cursor_close(MDBX_cursor *mc) { - if (mc) { - mdbx_ensure(NULL, mc->mc_signature == MDBX_MC_SIGNATURE || - mc->mc_signature == MDBX_MC_READY4CLOSE); - if (!mc->mc_backup) { - /* Remove from txn, if tracked. - * A read-only txn (!C_UNTRACK) may have been freed already, - * so do not peek inside it. Only write txns track cursors. */ - if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { - MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; - while (*prev && *prev != mc) - prev = &(*prev)->mc_next; - if (*prev == mc) - *prev = mc->mc_next; - } - mc->mc_signature = 0; - mdbx_free(mc); - } else { - /* cursor closed before nested txn ends */ - mdbx_cassert(mc, mc->mc_signature == MDBX_MC_SIGNATURE); - mc->mc_signature = MDBX_MC_WAIT4EOT; - } - } -} - -MDBX_txn *mdbx_cursor_txn(MDBX_cursor *mc) { - if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE)) - return NULL; - MDBX_txn *txn = mc->mc_txn; - if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) - return NULL; - if (unlikely(txn->mt_flags & MDBX_TXN_FINISHED)) - return NULL; - return txn; -} - -MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *mc) { - if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE)) - return UINT_MAX; - return mc->mc_dbi; -} - -/* Replace the key for a branch node with a new key. - * Set MDBX_TXN_ERROR on failure. - * [in] mc Cursor pointing to the node to operate on. - * [in] key The new key to use. - * Returns 0 on success, non-zero on failure. */ -static int mdbx_update_key(MDBX_cursor *mc, const MDBX_val *key) { - MDBX_page *mp; - MDBX_node *node; - char *base; - size_t len; - int delta, ksize, oksize; - int ptr, i, nkeys, indx; - DKBUF; - - indx = mc->mc_ki[mc->mc_top]; - mp = mc->mc_pg[mc->mc_top]; - node = page_node(mp, indx); - ptr = mp->mp_ptrs[indx]; - if (MDBX_DEBUG) { - MDBX_val k2; - char kbuf2[DKBUF_MAXKEYSIZE * 2 + 1]; - k2.iov_base = node_key(node); - k2.iov_len = node_ks(node); - mdbx_debug("update key %u (ofs %u) [%s] to [%s] on page %" PRIaPGNO, indx, - ptr, mdbx_dump_val(&k2, kbuf2, sizeof(kbuf2)), DKEY(key), - mp->mp_pgno); - } - - /* Sizes must be 2-byte aligned. */ - ksize = EVEN(key->iov_len); - oksize = EVEN(node_ks(node)); - delta = ksize - oksize; - - /* Shift node contents if EVEN(key length) changed. */ - if (delta) { - if (delta > (int)page_room(mp)) { - /* not enough space left, do a delete and split */ - mdbx_debug("Not enough room, delta = %d, splitting...", delta); - pgno_t pgno = node_pgno(node); - mdbx_node_del(mc, 0); - int rc = mdbx_page_split(mc, key, NULL, pgno, MDBX_SPLIT_REPLACE); - if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) - rc = mdbx_cursor_check(mc, true); - return rc; - } - - nkeys = page_numkeys(mp); - for (i = 0; i < nkeys; i++) { - if (mp->mp_ptrs[i] <= ptr) { - mdbx_cassert(mc, mp->mp_ptrs[i] >= delta); - mp->mp_ptrs[i] -= (indx_t)delta; - } - } - - base = (char *)mp + mp->mp_upper + PAGEHDRSZ; - len = ptr - mp->mp_upper + NODESIZE; - memmove(base - delta, base, len); - mdbx_cassert(mc, mp->mp_upper >= delta); - mp->mp_upper -= (indx_t)delta; - - node = page_node(mp, indx); - } - - /* But even if no shift was needed, update ksize */ - node_set_ks(node, key->iov_len); - - if (key->iov_len) - memcpy(node_key(node), key->iov_base, key->iov_len); - return MDBX_SUCCESS; -} - -/* Move a node from csrc to cdst. */ -static int mdbx_node_move(MDBX_cursor *csrc, MDBX_cursor *cdst, int fromleft) { - int rc; - DKBUF; - - MDBX_page *psrc = csrc->mc_pg[csrc->mc_top]; - MDBX_page *pdst = cdst->mc_pg[cdst->mc_top]; - mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); - mdbx_cassert(csrc, csrc->mc_dbi == cdst->mc_dbi); - mdbx_cassert(csrc, csrc->mc_top == cdst->mc_top); - if (unlikely(PAGETYPE(psrc) != PAGETYPE(pdst))) { - bailout: - csrc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return MDBX_PROBLEM; - } - - MDBX_val key4move; - switch (PAGETYPE(psrc)) { - case P_BRANCH: { - const MDBX_node *srcnode = page_node(psrc, csrc->mc_ki[csrc->mc_top]); - mdbx_cassert(csrc, node_flags(srcnode) == 0); - const pgno_t srcpg = node_pgno(srcnode); - key4move.iov_len = node_ks(srcnode); - key4move.iov_base = node_key(srcnode); - - if (csrc->mc_ki[csrc->mc_top] == 0) { - const uint16_t snum = csrc->mc_snum; - mdbx_cassert(csrc, snum > 0); - /* must find the lowest key below src */ - rc = mdbx_page_search_lowest(csrc); - MDBX_page *lowest_page = csrc->mc_pg[csrc->mc_top]; - if (unlikely(rc)) - return rc; - mdbx_cassert(csrc, IS_LEAF(lowest_page)); - if (unlikely(!IS_LEAF(lowest_page))) - goto bailout; - if (IS_LEAF2(lowest_page)) { - key4move.iov_len = csrc->mc_db->md_xsize; - key4move.iov_base = page_leaf2key(lowest_page, 0, key4move.iov_len); - } else { - const MDBX_node *lowest_node = page_node(lowest_page, 0); - key4move.iov_len = node_ks(lowest_node); - key4move.iov_base = node_key(lowest_node); - } - - /* restore cursor after mdbx_page_search_lowest() */ - csrc->mc_snum = snum; - csrc->mc_top = snum - 1; - csrc->mc_ki[csrc->mc_top] = 0; - - /* paranoia */ - mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); - mdbx_cassert(csrc, IS_BRANCH(psrc)); - if (unlikely(!IS_BRANCH(psrc))) - goto bailout; - } - - if (cdst->mc_ki[cdst->mc_top] == 0) { - const uint16_t snum = cdst->mc_snum; - mdbx_cassert(csrc, snum > 0); - MDBX_cursor mn; - mdbx_cursor_copy(cdst, &mn); - mn.mc_xcursor = NULL; - /* must find the lowest key below dst */ - rc = mdbx_page_search_lowest(&mn); - if (unlikely(rc)) - return rc; - MDBX_page *const lowest_page = mn.mc_pg[mn.mc_top]; - mdbx_cassert(cdst, IS_LEAF(lowest_page)); - if (unlikely(!IS_LEAF(lowest_page))) - goto bailout; - MDBX_val key; - if (IS_LEAF2(lowest_page)) { - key.iov_len = mn.mc_db->md_xsize; - key.iov_base = page_leaf2key(lowest_page, 0, key.iov_len); - } else { - MDBX_node *lowest_node = page_node(lowest_page, 0); - key.iov_len = node_ks(lowest_node); - key.iov_base = node_key(lowest_node); - } - - /* restore cursor after mdbx_page_search_lowest() */ - mn.mc_snum = snum; - mn.mc_top = snum - 1; - mn.mc_ki[mn.mc_top] = 0; - - const intptr_t delta = - EVEN(key.iov_len) - EVEN(node_ks(page_node(mn.mc_pg[mn.mc_top], 0))); - const intptr_t needed = - branch_size(cdst->mc_txn->mt_env, &key4move) + delta; - const intptr_t have = page_room(pdst); - if (unlikely(needed > have)) - return MDBX_RESULT_TRUE; - - if (unlikely((rc = mdbx_page_touch(csrc)) || - (rc = mdbx_page_touch(cdst)))) - return rc; - psrc = csrc->mc_pg[csrc->mc_top]; - pdst = cdst->mc_pg[cdst->mc_top]; - - rc = mdbx_update_key(&mn, &key); - if (unlikely(rc)) - return rc; - } else { - const size_t needed = branch_size(cdst->mc_txn->mt_env, &key4move); - const size_t have = page_room(pdst); - if (unlikely(needed > have)) - return MDBX_RESULT_TRUE; - - if (unlikely((rc = mdbx_page_touch(csrc)) || - (rc = mdbx_page_touch(cdst)))) - return rc; - psrc = csrc->mc_pg[csrc->mc_top]; - pdst = cdst->mc_pg[cdst->mc_top]; - } - - mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO - " to node %u on page %" PRIaPGNO, - "branch", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), - psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); - /* Add the node to the destination page. */ - rc = - mdbx_node_add_branch(cdst, cdst->mc_ki[cdst->mc_top], &key4move, srcpg); - } break; - - case P_LEAF: { - /* Mark src and dst as dirty. */ - if (unlikely((rc = mdbx_page_touch(csrc)) || (rc = mdbx_page_touch(cdst)))) - return rc; - psrc = csrc->mc_pg[csrc->mc_top]; - pdst = cdst->mc_pg[cdst->mc_top]; - const MDBX_node *srcnode = page_node(psrc, csrc->mc_ki[csrc->mc_top]); - MDBX_val data; - data.iov_len = node_ds(srcnode); - data.iov_base = node_data(srcnode); - key4move.iov_len = node_ks(srcnode); - key4move.iov_base = node_key(srcnode); - mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO - " to node %u on page %" PRIaPGNO, - "leaf", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), - psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); - /* Add the node to the destination page. */ - rc = mdbx_node_add_leaf(cdst, cdst->mc_ki[cdst->mc_top], &key4move, &data, - node_flags(srcnode)); - } break; - - case P_LEAF | P_LEAF2: { - /* Mark src and dst as dirty. */ - if (unlikely((rc = mdbx_page_touch(csrc)) || (rc = mdbx_page_touch(cdst)))) - return rc; - psrc = csrc->mc_pg[csrc->mc_top]; - pdst = cdst->mc_pg[cdst->mc_top]; - key4move.iov_len = csrc->mc_db->md_xsize; - key4move.iov_base = - page_leaf2key(psrc, csrc->mc_ki[csrc->mc_top], key4move.iov_len); - mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO - " to node %u on page %" PRIaPGNO, - "leaf2", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), - psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); - /* Add the node to the destination page. */ - rc = mdbx_node_add_leaf2(cdst, cdst->mc_ki[cdst->mc_top], &key4move); - } break; - - default: - goto bailout; - } - - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - /* Delete the node from the source page. */ - mdbx_node_del(csrc, key4move.iov_len); - - mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); - mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); - mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); - - { - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2, *m3; - const MDBX_dbi dbi = csrc->mc_dbi; - mdbx_cassert(csrc, csrc->mc_top == cdst->mc_top); - if (fromleft) { - /* If we're adding on the left, bump others up */ - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) - continue; - if (m3 != cdst && m3->mc_pg[csrc->mc_top] == pdst && - m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) { - m3->mc_ki[csrc->mc_top]++; - } - if (m3 != csrc && m3->mc_pg[csrc->mc_top] == psrc && - m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) { - m3->mc_pg[csrc->mc_top] = pdst; - m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; - mdbx_cassert(csrc, csrc->mc_top > 0); - m3->mc_ki[csrc->mc_top - 1]++; - } - if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) - XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]); - } - } else { - /* Adding on the right, bump others down */ - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == csrc) - continue; - if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) - continue; - if (m3->mc_pg[csrc->mc_top] == psrc) { - if (!m3->mc_ki[csrc->mc_top]) { - m3->mc_pg[csrc->mc_top] = pdst; - m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; - mdbx_cassert(csrc, csrc->mc_top > 0); - m3->mc_ki[csrc->mc_top - 1]--; - } else { - m3->mc_ki[csrc->mc_top]--; - } - if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) - XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], - m3->mc_ki[csrc->mc_top]); - } - } - } - } - - /* Update the parent separators. */ - if (csrc->mc_ki[csrc->mc_top] == 0) { - mdbx_cassert(csrc, csrc->mc_top > 0); - if (csrc->mc_ki[csrc->mc_top - 1] != 0) { - MDBX_val key; - if (IS_LEAF2(psrc)) { - key.iov_len = psrc->mp_leaf2_ksize; - key.iov_base = page_leaf2key(psrc, 0, key.iov_len); - } else { - MDBX_node *srcnode = page_node(psrc, 0); - key.iov_len = node_ks(srcnode); - key.iov_base = node_key(srcnode); - } - mdbx_debug("update separator for source page %" PRIaPGNO " to [%s]", - psrc->mp_pgno, DKEY(&key)); - MDBX_cursor mn; - mdbx_cursor_copy(csrc, &mn); - mn.mc_xcursor = NULL; - mdbx_cassert(csrc, mn.mc_snum > 0); - mn.mc_snum--; - mn.mc_top--; - /* We want mdbx_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key)); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - if (IS_BRANCH(psrc)) { - const MDBX_val nullkey = {0, 0}; - const indx_t ix = csrc->mc_ki[csrc->mc_top]; - csrc->mc_ki[csrc->mc_top] = 0; - rc = mdbx_update_key(csrc, &nullkey); - csrc->mc_ki[csrc->mc_top] = ix; - mdbx_cassert(csrc, rc == MDBX_SUCCESS); - } - } - - if (cdst->mc_ki[cdst->mc_top] == 0) { - mdbx_cassert(cdst, cdst->mc_top > 0); - if (cdst->mc_ki[cdst->mc_top - 1] != 0) { - MDBX_val key; - if (IS_LEAF2(pdst)) { - key.iov_len = pdst->mp_leaf2_ksize; - key.iov_base = page_leaf2key(pdst, 0, key.iov_len); - } else { - MDBX_node *srcnode = page_node(pdst, 0); - key.iov_len = node_ks(srcnode); - key.iov_base = node_key(srcnode); - } - mdbx_debug("update separator for destination page %" PRIaPGNO " to [%s]", - pdst->mp_pgno, DKEY(&key)); - MDBX_cursor mn; - mdbx_cursor_copy(cdst, &mn); - mn.mc_xcursor = NULL; - mdbx_cassert(cdst, mn.mc_snum > 0); - mn.mc_snum--; - mn.mc_top--; - /* We want mdbx_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key)); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - if (IS_BRANCH(pdst)) { - const MDBX_val nullkey = {0, 0}; - const indx_t ix = cdst->mc_ki[cdst->mc_top]; - cdst->mc_ki[cdst->mc_top] = 0; - rc = mdbx_update_key(cdst, &nullkey); - cdst->mc_ki[cdst->mc_top] = ix; - mdbx_cassert(cdst, rc == MDBX_SUCCESS); - } - } - - return MDBX_SUCCESS; -} - -/* Merge one page into another. - * - * The nodes from the page pointed to by csrc will be copied to the page - * pointed to by cdst and then the csrc page will be freed. - * - * [in] csrc Cursor pointing to the source page. - * [in] cdst Cursor pointing to the destination page. - * - * Returns 0 on success, non-zero on failure. */ -static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) { - MDBX_val key; - int rc; - - mdbx_cassert(csrc, csrc != cdst); - const MDBX_page *const psrc = csrc->mc_pg[csrc->mc_top]; - MDBX_page *pdst = cdst->mc_pg[cdst->mc_top]; - mdbx_debug("merging page %" PRIaPGNO " into %" PRIaPGNO, psrc->mp_pgno, - pdst->mp_pgno); - - mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); - mdbx_cassert(csrc, - csrc->mc_dbi == cdst->mc_dbi && csrc->mc_db == cdst->mc_db); - mdbx_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */ - mdbx_cassert(cdst, cdst->mc_snum > 1); - mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || - IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); - mdbx_cassert(csrc, csrc->mc_snum < csrc->mc_db->md_depth || - IS_LEAF(csrc->mc_pg[csrc->mc_db->md_depth - 1])); - mdbx_cassert(cdst, page_room(pdst) >= page_used(cdst->mc_txn->mt_env, psrc)); - const int pagetype = PAGETYPE(psrc); - - /* Move all nodes from src to dst */ - const unsigned dst_nkeys = page_numkeys(pdst); - const unsigned src_nkeys = page_numkeys(psrc); - if (likely(src_nkeys)) { - unsigned j = dst_nkeys; - if (unlikely(pagetype & P_LEAF2)) { - /* Mark dst as dirty. */ - if (unlikely(rc = mdbx_page_touch(cdst))) - return rc; - - key.iov_len = csrc->mc_db->md_xsize; - key.iov_base = page_data(psrc); - unsigned i = 0; - do { - rc = mdbx_node_add_leaf2(cdst, j++, &key); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - key.iov_base = (char *)key.iov_base + key.iov_len; - } while (++i != src_nkeys); - } else { - MDBX_node *srcnode = page_node(psrc, 0); - key.iov_len = node_ks(srcnode); - key.iov_base = node_key(srcnode); - if (pagetype & P_BRANCH) { - MDBX_cursor mn; - mdbx_cursor_copy(csrc, &mn); - mn.mc_xcursor = NULL; - /* must find the lowest key below src */ - rc = mdbx_page_search_lowest(&mn); - if (unlikely(rc)) - return rc; - if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { - key.iov_len = mn.mc_db->md_xsize; - key.iov_base = page_leaf2key(mn.mc_pg[mn.mc_top], 0, key.iov_len); - } else { - MDBX_node *lowest = page_node(mn.mc_pg[mn.mc_top], 0); - key.iov_len = node_ks(lowest); - key.iov_base = node_key(lowest); - - const size_t dst_room = page_room(pdst); - const size_t src_used = page_used(cdst->mc_txn->mt_env, psrc); - const size_t space_needed = src_used - node_ks(srcnode) + key.iov_len; - if (unlikely(space_needed > dst_room)) - return MDBX_RESULT_TRUE; - } - } - - /* Mark dst as dirty. */ - if (unlikely(rc = mdbx_page_touch(cdst))) - return rc; - - unsigned i = 0; - while (true) { - if (pagetype & P_LEAF) { - MDBX_val data; - data.iov_len = node_ds(srcnode); - data.iov_base = node_data(srcnode); - rc = mdbx_node_add_leaf(cdst, j++, &key, &data, node_flags(srcnode)); - } else { - mdbx_cassert(csrc, node_flags(srcnode) == 0); - rc = mdbx_node_add_branch(cdst, j++, &key, node_pgno(srcnode)); - } - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (++i == src_nkeys) - break; - srcnode = page_node(psrc, i); - key.iov_len = node_ks(srcnode); - key.iov_base = node_key(srcnode); - } - } - - pdst = cdst->mc_pg[cdst->mc_top]; - mdbx_debug("dst page %" PRIaPGNO " now has %u keys (%.1f%% filled)", - pdst->mp_pgno, page_numkeys(pdst), - page_fill(cdst->mc_txn->mt_env, pdst)); - - mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); - mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); - } - - /* Unlink the src page from parent and add to free list. */ - csrc->mc_top--; - mdbx_node_del(csrc, 0); - if (csrc->mc_ki[csrc->mc_top] == 0) { - const MDBX_val nullkey = {0, 0}; - rc = mdbx_update_key(csrc, &nullkey); - if (unlikely(rc)) { - csrc->mc_top++; - return rc; - } - } - csrc->mc_top++; - - mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); - mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); - - { - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2, *m3; - const MDBX_dbi dbi = csrc->mc_dbi; - const unsigned top = csrc->mc_top; - - for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == csrc || top >= m3->mc_snum) - continue; - if (m3->mc_pg[top] == psrc) { - m3->mc_pg[top] = pdst; - mdbx_cassert(m3, dst_nkeys + m3->mc_ki[top] <= UINT16_MAX); - m3->mc_ki[top] += (indx_t)dst_nkeys; - m3->mc_ki[top - 1] = cdst->mc_ki[top - 1]; - } else if (m3->mc_pg[top - 1] == csrc->mc_pg[top - 1] && - m3->mc_ki[top - 1] > csrc->mc_ki[top - 1]) { - m3->mc_ki[top - 1]--; - } - if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) - XCURSOR_REFRESH(m3, m3->mc_pg[top], m3->mc_ki[top]); - } - } - - /* If not operating on GC, allow this page to be reused - * in this txn. Otherwise just add to free list. */ - rc = mdbx_page_retire(csrc, (MDBX_page *)psrc); - if (unlikely(rc)) - return rc; - - mdbx_cassert(cdst, cdst->mc_db->md_entries > 0); - mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth); - mdbx_cassert(cdst, cdst->mc_top > 0); - mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1); - MDBX_page *const top_page = cdst->mc_pg[cdst->mc_top]; - const indx_t top_indx = cdst->mc_ki[cdst->mc_top]; - const uint16_t save_snum = cdst->mc_snum; - const uint16_t save_depth = cdst->mc_db->md_depth; - mdbx_cursor_pop(cdst); - rc = mdbx_rebalance(cdst); - if (unlikely(rc)) - return rc; - - mdbx_cassert(cdst, cdst->mc_db->md_entries > 0); - mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth); - mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1); - - if (IS_LEAF(cdst->mc_pg[cdst->mc_top])) { - /* LY: don't touch cursor if top-page is a LEAF */ - mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || - PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); - return MDBX_SUCCESS; - } - - if (pagetype != PAGETYPE(top_page)) { - /* LY: LEAF-page becomes BRANCH, unable restore cursor's stack */ - goto bailout; - } - - if (top_page == cdst->mc_pg[cdst->mc_top]) { - /* LY: don't touch cursor if prev top-page already on the top */ - mdbx_cassert(cdst, cdst->mc_ki[cdst->mc_top] == top_indx); - mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || - PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); - return MDBX_SUCCESS; - } - - const int new_snum = save_snum - save_depth + cdst->mc_db->md_depth; - if (unlikely(new_snum < 1 || new_snum > cdst->mc_db->md_depth)) { - /* LY: out of range, unable restore cursor's stack */ - goto bailout; - } - - if (top_page == cdst->mc_pg[new_snum - 1]) { - mdbx_cassert(cdst, cdst->mc_ki[new_snum - 1] == top_indx); - /* LY: restore cursor stack */ - cdst->mc_snum = (uint16_t)new_snum; - cdst->mc_top = (uint16_t)new_snum - 1; - mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || - IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); - mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || - PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); - return MDBX_SUCCESS; - } - - MDBX_page *const stub_page = (MDBX_page *)(~(uintptr_t)top_page); - const indx_t stub_indx = top_indx; - if (save_depth > cdst->mc_db->md_depth && - ((cdst->mc_pg[save_snum - 1] == top_page && - cdst->mc_ki[save_snum - 1] == top_indx) || - (cdst->mc_pg[save_snum - 1] == stub_page && - cdst->mc_ki[save_snum - 1] == stub_indx))) { - /* LY: restore cursor stack */ - cdst->mc_pg[new_snum - 1] = top_page; - cdst->mc_ki[new_snum - 1] = top_indx; - cdst->mc_pg[new_snum] = (MDBX_page *)(~(uintptr_t)cdst->mc_pg[new_snum]); - cdst->mc_ki[new_snum] = ~cdst->mc_ki[new_snum]; - cdst->mc_snum = (uint16_t)new_snum; - cdst->mc_top = (uint16_t)new_snum - 1; - mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || - IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); - mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || - PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); - return MDBX_SUCCESS; - } - -bailout: - /* LY: unable restore cursor's stack */ - cdst->mc_flags &= ~C_INITIALIZED; - return MDBX_CURSOR_FULL; -} - -/* Copy the contents of a cursor. - * [in] csrc The cursor to copy from. - * [out] cdst The cursor to copy to. */ -static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst) { - unsigned i; - - mdbx_cassert(csrc, - csrc->mc_txn->mt_txnid >= *csrc->mc_txn->mt_env->me_oldest); - cdst->mc_txn = csrc->mc_txn; - cdst->mc_dbi = csrc->mc_dbi; - cdst->mc_db = csrc->mc_db; - cdst->mc_dbx = csrc->mc_dbx; - cdst->mc_snum = csrc->mc_snum; - cdst->mc_top = csrc->mc_top; - cdst->mc_flags = csrc->mc_flags; - - for (i = 0; i < csrc->mc_snum; i++) { - cdst->mc_pg[i] = csrc->mc_pg[i]; - cdst->mc_ki[i] = csrc->mc_ki[i]; - } -} - -/* Rebalance the tree after a delete operation. - * [in] mc Cursor pointing to the page where rebalancing should begin. - * Returns 0 on success, non-zero on failure. */ -static int mdbx_rebalance(MDBX_cursor *mc) { - int rc; - - mdbx_cassert(mc, mc->mc_snum > 0); - mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || - IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); - const int pagetype = PAGETYPE(mc->mc_pg[mc->mc_top]); - - const unsigned minkeys = (P_BRANCH == 1) ? (pagetype & P_BRANCH) + 1 - : (pagetype & P_BRANCH) ? 2 : 1; - - /* The threshold of minimum page fill factor, in form of a negative binary - * exponent, i.e. 2 means 1/(2**3) == 1/4 == 25%. Pages emptier than this - * are candidates for merging. */ - const unsigned threshold_fill_exp2 = 2; - - /* The threshold of minimum page fill factor, as a number of free bytes on a - * page. Pages emptier than this are candidates for merging. */ - const unsigned spaceleft_threshold = - page_space(mc->mc_txn->mt_env) - - (page_space(mc->mc_txn->mt_env) >> threshold_fill_exp2); - - mdbx_debug("rebalancing %s page %" PRIaPGNO " (has %u keys, %.1f%% full)", - (pagetype & P_LEAF) ? "leaf" : "branch", - mc->mc_pg[mc->mc_top]->mp_pgno, - page_numkeys(mc->mc_pg[mc->mc_top]), - page_fill(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top])); - - if (page_fill_enough(mc->mc_pg[mc->mc_top], spaceleft_threshold, minkeys)) { - mdbx_debug("no need to rebalance page %" PRIaPGNO ", above fill threshold", - mc->mc_pg[mc->mc_top]->mp_pgno); - mdbx_cassert(mc, mc->mc_db->md_entries > 0); - return MDBX_SUCCESS; - } - - if (mc->mc_snum < 2) { - MDBX_page *const mp = mc->mc_pg[0]; - const unsigned nkeys = page_numkeys(mp); - mdbx_cassert(mc, (mc->mc_db->md_entries == 0) == (nkeys == 0)); - if (IS_SUBP(mp)) { - mdbx_debug("%s", "Can't rebalance a subpage, ignoring"); - mdbx_cassert(mc, pagetype & P_LEAF); - return MDBX_SUCCESS; - } - if (nkeys == 0) { - mdbx_cassert(mc, IS_LEAF(mp)); - mdbx_debug("%s", "tree is completely empty"); - mc->mc_db->md_root = P_INVALID; - mc->mc_db->md_depth = 0; - mdbx_cassert(mc, mc->mc_db->md_branch_pages == 0 && - mc->mc_db->md_overflow_pages == 0 && - mc->mc_db->md_leaf_pages == 1); - /* Adjust cursors pointing to mp */ - const MDBX_dbi dbi = mc->mc_dbi; - for (MDBX_cursor *m2 = mc->mc_txn->mt_cursors[dbi]; m2; - m2 = m2->mc_next) { - MDBX_cursor *m3 = - (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc || !(m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_pg[0] == mp) { - m3->mc_snum = 0; - m3->mc_top = 0; - m3->mc_flags &= ~C_INITIALIZED; - } - } - mc->mc_snum = 0; - mc->mc_top = 0; - mc->mc_flags &= ~C_INITIALIZED; - - rc = mdbx_page_retire(mc, mp); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } else if (IS_BRANCH(mp) && nkeys == 1) { - mdbx_debug("%s", "collapsing root page!"); - mc->mc_db->md_root = node_pgno(page_node(mp, 0)); - rc = mdbx_page_get(mc, mc->mc_db->md_root, &mc->mc_pg[0], NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mc->mc_db->md_depth--; - mc->mc_ki[0] = mc->mc_ki[1]; - for (int i = 1; i < mc->mc_db->md_depth; i++) { - mc->mc_pg[i] = mc->mc_pg[i + 1]; - mc->mc_ki[i] = mc->mc_ki[i + 1]; - } - - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2, *m3; - MDBX_dbi dbi = mc->mc_dbi; - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc || !(m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_pg[0] == mp) { - for (int i = 0; i < mc->mc_db->md_depth; i++) { - m3->mc_pg[i] = m3->mc_pg[i + 1]; - m3->mc_ki[i] = m3->mc_ki[i + 1]; - } - m3->mc_snum--; - m3->mc_top--; - } - } - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || - PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); - mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || - IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); - - rc = mdbx_page_retire(mc, mp); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } else { - mdbx_debug("root page %" PRIaPGNO - " doesn't need rebalancing (flags 0x%x)", - mp->mp_pgno, mp->mp_flags); - } - return MDBX_SUCCESS; - } - - /* The parent (branch page) must have at least 2 pointers, - * otherwise the tree is invalid. */ - const unsigned pre_top = mc->mc_top - 1; - mdbx_cassert(mc, IS_BRANCH(mc->mc_pg[pre_top])); - mdbx_cassert(mc, !IS_SUBP(mc->mc_pg[0])); - mdbx_cassert(mc, page_numkeys(mc->mc_pg[pre_top]) > 1); - - /* Leaf page fill factor is below the threshold. - * Try to move keys from left or right neighbor, or - * merge with a neighbor page. */ - - /* Find neighbors. */ - MDBX_cursor mn; - mdbx_cursor_copy(mc, &mn); - mn.mc_xcursor = NULL; - - MDBX_page *left = nullptr, *right = nullptr; - if (mn.mc_ki[pre_top] > 0) { - rc = mdbx_page_get( - &mn, node_pgno(page_node(mn.mc_pg[pre_top], mn.mc_ki[pre_top] - 1)), - &left, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mdbx_cassert(mc, PAGETYPE(left) == PAGETYPE(mc->mc_pg[mc->mc_top])); - } - if (mn.mc_ki[pre_top] + 1u < page_numkeys(mn.mc_pg[pre_top])) { - rc = mdbx_page_get( - &mn, node_pgno(page_node(mn.mc_pg[pre_top], mn.mc_ki[pre_top] + 1)), - &right, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mdbx_cassert(mc, PAGETYPE(right) == PAGETYPE(mc->mc_pg[mc->mc_top])); - } - - int ki = mc->mc_ki[mc->mc_top]; - bool fromleft; - if (!left || (right && page_room(left) < page_room(right))) { - mdbx_debug("merging %s neighbor", "right"); - mn.mc_pg[mn.mc_top] = right; - mn.mc_ki[pre_top] += 1; - mn.mc_ki[mn.mc_top] = 0; - mc->mc_ki[mc->mc_top] = (indx_t)page_numkeys(mc->mc_pg[mc->mc_top]); - fromleft = false; - } else { - mdbx_debug("merging %s neighbor", "left"); - mn.mc_pg[mn.mc_top] = left; - mn.mc_ki[pre_top] -= 1; - mn.mc_ki[mn.mc_top] = (indx_t)page_numkeys(mn.mc_pg[mn.mc_top]) - 1; - mc->mc_ki[mc->mc_top] = 0; - fromleft = true; - } - - mdbx_debug("found neighbor page %" PRIaPGNO " (%u keys, %.1f%% full)", - mn.mc_pg[mn.mc_top]->mp_pgno, page_numkeys(mn.mc_pg[mn.mc_top]), - page_fill(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top])); - - /* If the neighbor page is above threshold and has enough keys, - * move one key from it. Otherwise we should try to merge them. - * (A branch page must never have less than 2 keys.) */ - if (page_fill_enough(mn.mc_pg[mn.mc_top], spaceleft_threshold, minkeys + 1)) { - rc = mdbx_node_move(&mn, mc, fromleft); - if (likely(rc == MDBX_SUCCESS)) - ki += fromleft /* if we inserted on left, bump position up */; - else if (unlikely(rc != MDBX_RESULT_TRUE)) - return rc; - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || - PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); - mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || - IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); - } else { - if (!fromleft) { - rc = mdbx_page_merge(&mn, mc); - if (unlikely(MDBX_IS_ERROR(rc))) - return rc; - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || - PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); - mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || - IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); - } else { - int new_ki = ki + page_numkeys(mn.mc_pg[mn.mc_top]); - mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1; - /* We want mdbx_rebalance to find mn when doing fixups */ - WITH_CURSOR_TRACKING(mn, rc = mdbx_page_merge(mc, &mn)); - if (likely(rc == MDBX_SUCCESS)) { - ki = new_ki; - mdbx_cursor_copy(&mn, mc); - } else if (unlikely(rc != MDBX_RESULT_TRUE)) - return rc; - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || - PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); - mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || - IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); - } - } - mc->mc_ki[mc->mc_top] = (indx_t)ki; - return MDBX_SUCCESS; -} - -static __cold int mdbx_page_check(MDBX_env *env, const MDBX_page *const mp, - bool maybe_unfinished) { - const unsigned nkeys = page_numkeys(mp); - char *const end_of_page = (char *)mp + env->me_psize; - mdbx_assert(env, mp->mp_pgno >= MIN_PAGENO && mp->mp_pgno <= MAX_PAGENO); - if (unlikely(mp->mp_pgno < MIN_PAGENO || mp->mp_pgno > MAX_PAGENO)) - return MDBX_CORRUPTED; - if (IS_OVERFLOW(mp)) { - mdbx_assert(env, mp->mp_pages >= 1 && mp->mp_pages < MAX_PAGENO / 2); - if (unlikely(mp->mp_pages < 1 && mp->mp_pages >= MAX_PAGENO / 2)) - return MDBX_CORRUPTED; - mdbx_assert(env, mp->mp_pgno <= MAX_PAGENO - mp->mp_pages); - if (unlikely(mp->mp_pgno > MAX_PAGENO - mp->mp_pages)) - return MDBX_CORRUPTED; - return MDBX_SUCCESS; - } - if (!(IS_DIRTY(mp) && maybe_unfinished)) { - mdbx_assert(env, nkeys >= 2 || !IS_BRANCH(mp)); - if (unlikely(nkeys < 2 && IS_BRANCH(mp))) - return MDBX_CORRUPTED; - } - - for (unsigned i = IS_LEAF(mp) ? 0 : 1; i < nkeys; ++i) { - if (IS_LEAF2(mp)) { - const size_t ksize = mp->mp_leaf2_ksize; - const char *const key = page_leaf2key(mp, i, ksize); - mdbx_assert(env, key + ksize <= end_of_page); - if (unlikely(end_of_page < key + ksize)) - return MDBX_CORRUPTED; - } else { - const MDBX_node *const node = page_node(mp, i); - const char *node_end = (char *)node + NODESIZE; - mdbx_assert(env, node_end <= end_of_page); - if (unlikely(node_end > end_of_page)) - return MDBX_CORRUPTED; - if (IS_LEAF(mp) || i > 0) { - size_t ksize = node_ks(node); - char *key = node_key(node); - mdbx_assert(env, key + ksize <= end_of_page); - if (unlikely(end_of_page < key + ksize)) - return MDBX_CORRUPTED; - } - if (IS_BRANCH(mp)) - continue; - if (node_flags(node) == F_BIGDATA /* data on large-page */) { - continue; - } - const size_t dsize = node_ds(node); - const char *const data = node_data(node); - mdbx_assert(env, data + dsize <= end_of_page); - if (unlikely(end_of_page < data + dsize)) - return MDBX_CORRUPTED; - - switch (node_flags(node)) { - default: - mdbx_assert(env, false); - return MDBX_CORRUPTED; - case 0 /* usual */: - break; - case F_SUBDATA /* sub-db */: - mdbx_assert(env, dsize >= sizeof(MDBX_db)); - if (unlikely(dsize < sizeof(MDBX_db))) - return MDBX_CORRUPTED; - break; - case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: - mdbx_assert(env, dsize == sizeof(MDBX_db)); - if (unlikely(dsize != sizeof(MDBX_db))) - return MDBX_CORRUPTED; - break; - case F_DUPDATA /* short sub-page */: - mdbx_assert(env, dsize > PAGEHDRSZ); - if (unlikely(dsize <= PAGEHDRSZ)) - return MDBX_CORRUPTED; - else { - const MDBX_page *const sp = (MDBX_page *)data; - const char *const end_of_subpage = data + dsize; - const int nsubkeys = page_numkeys(sp); - switch (sp->mp_flags & ~P_DIRTY /* ignore for sub-pages */) { - case P_LEAF | P_SUBP: - case P_LEAF | P_LEAF2 | P_SUBP: - break; - default: - mdbx_assert(env, false); - return MDBX_CORRUPTED; - } - - for (int j = 0; j < nsubkeys; j++) { - if (IS_LEAF2(sp)) { - /* LEAF2 pages have no mp_ptrs[] or node headers */ - size_t sub_ksize = sp->mp_leaf2_ksize; - char *sub_key = page_leaf2key(sp, j, sub_ksize); - mdbx_assert(env, sub_key + sub_ksize <= end_of_subpage); - if (unlikely(end_of_subpage < sub_key + sub_ksize)) - return MDBX_CORRUPTED; - } else { - mdbx_assert(env, IS_LEAF(sp)); - if (unlikely(!IS_LEAF(sp))) - return MDBX_CORRUPTED; - const MDBX_node *const sub_node = page_node(sp, j); - const char *sub_node_end = (char *)sub_node + NODESIZE; - mdbx_assert(env, sub_node_end <= end_of_subpage); - if (unlikely(sub_node_end > end_of_subpage)) - return MDBX_CORRUPTED; - mdbx_assert(env, node_flags(sub_node) == 0); - if (unlikely(node_flags(sub_node) != 0)) - return MDBX_CORRUPTED; - - size_t sub_ksize = node_ks(sub_node); - char *sub_key = node_key(sub_node); - size_t sub_dsize = node_ds(sub_node); - char *sub_data = node_data(sub_node); - mdbx_assert(env, sub_key + sub_ksize <= end_of_subpage); - if (unlikely(end_of_subpage < sub_key + sub_ksize)) - return MDBX_CORRUPTED; - mdbx_assert(env, sub_data + sub_dsize <= end_of_subpage); - if (unlikely(end_of_subpage < sub_data + sub_dsize)) - return MDBX_CORRUPTED; - } - } - } - break; - } - } - } - return MDBX_SUCCESS; -} - -static __cold int mdbx_cursor_check(MDBX_cursor *mc, bool pending) { - mdbx_tassert(mc->mc_txn, mc->mc_txn->mt_parent || - mc->mc_txn->tw.dirtyroom + - mc->mc_txn->tw.dirtylist->length == - MDBX_DPL_TXNFULL); - mdbx_cassert(mc, mc->mc_top == mc->mc_snum - 1); - if (unlikely(mc->mc_top != mc->mc_snum - 1)) - return MDBX_CURSOR_FULL; - mdbx_cassert(mc, pending ? mc->mc_snum <= mc->mc_db->md_depth - : mc->mc_snum == mc->mc_db->md_depth); - if (unlikely(pending ? mc->mc_snum > mc->mc_db->md_depth - : mc->mc_snum != mc->mc_db->md_depth)) - return MDBX_CURSOR_FULL; - - for (int n = 0; n < mc->mc_snum; ++n) { - MDBX_page *mp = mc->mc_pg[n]; - const unsigned nkeys = page_numkeys(mp); - const bool expect_branch = (n < mc->mc_db->md_depth - 1) ? true : false; - const bool expect_nested_leaf = - (n + 1 == mc->mc_db->md_depth - 1) ? true : false; - const bool branch = IS_BRANCH(mp) ? true : false; - mdbx_cassert(mc, branch == expect_branch); - if (unlikely(branch != expect_branch)) - return MDBX_CURSOR_FULL; - if (!pending) { - mdbx_cassert(mc, - nkeys > mc->mc_ki[n] || (!branch && nkeys == mc->mc_ki[n] && - (mc->mc_flags & C_EOF) != 0)); - if (unlikely(nkeys <= mc->mc_ki[n] && - !(!branch && nkeys == mc->mc_ki[n] && - (mc->mc_flags & C_EOF) != 0))) - return MDBX_CURSOR_FULL; - } else { - mdbx_cassert(mc, nkeys + 1 >= mc->mc_ki[n]); - if (unlikely(nkeys + 1 < mc->mc_ki[n])) - return MDBX_CURSOR_FULL; - } - - int err = mdbx_page_check(mc->mc_txn->mt_env, mp, pending); - if (unlikely(err != MDBX_SUCCESS)) - return err; - - for (unsigned i = 0; i < nkeys; ++i) { - if (branch) { - MDBX_node *node = page_node(mp, i); - mdbx_cassert(mc, node_flags(node) == 0); - if (unlikely(node_flags(node) != 0)) - return MDBX_CURSOR_FULL; - pgno_t pgno = node_pgno(node); - MDBX_page *np; - int rc = mdbx_page_get(mc, pgno, &np, NULL); - mdbx_cassert(mc, rc == MDBX_SUCCESS); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - const bool nested_leaf = IS_LEAF(np) ? true : false; - mdbx_cassert(mc, nested_leaf == expect_nested_leaf); - if (unlikely(nested_leaf != expect_nested_leaf)) - return MDBX_CURSOR_FULL; - err = mdbx_page_check(mc->mc_txn->mt_env, np, pending); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - } - } - return MDBX_SUCCESS; -} - -/* Complete a delete operation started by mdbx_cursor_del(). */ -static int mdbx_cursor_del0(MDBX_cursor *mc) { - int rc; - MDBX_page *mp; - indx_t ki; - unsigned nkeys; - MDBX_cursor *m2, *m3; - MDBX_dbi dbi = mc->mc_dbi; - - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - ki = mc->mc_ki[mc->mc_top]; - mp = mc->mc_pg[mc->mc_top]; - mdbx_node_del(mc, mc->mc_db->md_xsize); - mc->mc_db->md_entries--; - { - /* Adjust other cursors pointing to mp */ - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc || !(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) { - if (m3->mc_ki[mc->mc_top] == ki) { - m3->mc_flags |= C_DEL; - if (mc->mc_db->md_flags & MDBX_DUPSORT) { - /* Sub-cursor referred into dataset which is gone */ - m3->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); - } - continue; - } else if (m3->mc_ki[mc->mc_top] > ki) { - m3->mc_ki[mc->mc_top]--; - } - if (XCURSOR_INITED(m3)) - XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); - } - } - } - rc = mdbx_rebalance(mc); - - if (likely(rc == MDBX_SUCCESS)) { - /* DB is totally empty now, just bail out. - * Other cursors adjustments were already done - * by mdbx_rebalance and aren't needed here. */ - if (!mc->mc_snum) { - mdbx_cassert(mc, mc->mc_db->md_entries == 0 && mc->mc_db->md_depth == 0 && - mc->mc_db->md_root == P_INVALID); - mc->mc_flags |= C_DEL | C_EOF; - return rc; - } - - ki = mc->mc_ki[mc->mc_top]; - mp = mc->mc_pg[mc->mc_top]; - mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); - nkeys = page_numkeys(mp); - mdbx_cassert(mc, (mc->mc_db->md_entries > 0 && nkeys > 0) || - ((mc->mc_flags & C_SUB) && - mc->mc_db->md_entries == 0 && nkeys == 0)); - - /* Adjust THIS and other cursors pointing to mp */ - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc || !(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (m3->mc_snum < mc->mc_snum) - continue; - if (m3->mc_pg[mc->mc_top] == mp) { - /* if m3 points past last node in page, find next sibling */ - if (m3->mc_ki[mc->mc_top] >= nkeys) { - rc = mdbx_cursor_sibling(m3, true); - if (rc == MDBX_NOTFOUND) { - m3->mc_flags |= C_EOF; - rc = MDBX_SUCCESS; - continue; - } else if (unlikely(rc != MDBX_SUCCESS)) - break; - } - if (m3->mc_ki[mc->mc_top] >= ki || m3->mc_pg[mc->mc_top] != mp) { - if ((mc->mc_db->md_flags & MDBX_DUPSORT) != 0 && - (m3->mc_flags & C_EOF) == 0) { - MDBX_node *node = - page_node(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]); - /* If this node has dupdata, it may need to be reinited - * because its data has moved. - * If the xcursor was not initd it must be reinited. - * Else if node points to a subDB, nothing is needed. */ - if (node_flags(node) & F_DUPDATA) { - if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - if (!(node_flags(node) & F_SUBDATA)) - m3->mc_xcursor->mx_cursor.mc_pg[0] = node_data(node); - } else { - rc = mdbx_xcursor_init1(m3, node); - if (unlikely(rc != MDBX_SUCCESS)) - break; - m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL; - } - } - } - } - } - } - - if (mc->mc_ki[mc->mc_top] >= nkeys) { - rc = mdbx_cursor_sibling(mc, true); - if (rc == MDBX_NOTFOUND) { - mc->mc_flags |= C_EOF; - rc = MDBX_SUCCESS; - } - } - if ((mc->mc_db->md_flags & MDBX_DUPSORT) != 0 && - (mc->mc_flags & C_EOF) == 0) { - MDBX_node *node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - /* If this node has dupdata, it may need to be reinited - * because its data has moved. - * If the xcursor was not initd it must be reinited. - * Else if node points to a subDB, nothing is needed. */ - if (node_flags(node) & F_DUPDATA) { - if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { - if (!(node_flags(node) & F_SUBDATA)) - mc->mc_xcursor->mx_cursor.mc_pg[0] = node_data(node); - } else { - rc = mdbx_xcursor_init1(mc, node); - if (likely(rc != MDBX_SUCCESS)) - mc->mc_xcursor->mx_cursor.mc_flags |= C_DEL; - } - } - } - mc->mc_flags |= C_DEL; - } - - if (unlikely(rc)) - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - else if (mdbx_audit_enabled()) - rc = mdbx_cursor_check(mc, false); - - return rc; -} - -int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) { - int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(txn->mt_flags & (MDBX_RDONLY | MDBX_TXN_BLOCKED))) - return (txn->mt_flags & MDBX_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; - - return mdbx_del0(txn, dbi, key, data, 0); -} - -static int mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - unsigned flags) { - MDBX_cursor_couple cx; - MDBX_cursor_op op; - MDBX_val rdata; - int rc, exact = 0; - DKBUF; - - mdbx_debug("====> delete db %u key [%s], data [%s]", dbi, DKEY(key), - DVAL(data)); - - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (data) { - op = MDBX_GET_BOTH; - rdata = *data; - data = &rdata; - } else { - op = MDBX_SET; - flags |= MDBX_NODUPDATA; - } - rc = mdbx_cursor_set(&cx.outer, key, data, op, &exact); - if (likely(rc == MDBX_SUCCESS)) { - /* let mdbx_page_split know about this cursor if needed: - * delete will trigger a rebalance; if it needs to move - * a node from one page to another, it will have to - * update the parent's separator key(s). If the new sepkey - * is larger than the current one, the parent page may - * run out of space, triggering a split. We need this - * cursor to be consistent until the end of the rebalance. */ - cx.outer.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &cx.outer; - rc = mdbx_cursor_del(&cx.outer, flags); - txn->mt_cursors[dbi] = cx.outer.mc_next; - } - return rc; -} - -/* Split a page and insert a new node. - * Set MDBX_TXN_ERROR on failure. - * [in,out] mc Cursor pointing to the page and desired insertion index. - * The cursor will be updated to point to the actual page and index where - * the node got inserted after the split. - * [in] newkey The key for the newly inserted node. - * [in] newdata The data for the newly inserted node. - * [in] newpgno The page number, if the new node is a branch node. - * [in] nflags The NODE_ADD_FLAGS for the new node. - * Returns 0 on success, non-zero on failure. */ -static int mdbx_page_split(MDBX_cursor *mc, const MDBX_val *newkey, - MDBX_val *newdata, pgno_t newpgno, unsigned nflags) { - unsigned flags; - int rc = MDBX_SUCCESS, foliage = 0, did_split = 0; - pgno_t pgno = 0; - unsigned i, ptop; - MDBX_env *env = mc->mc_txn->mt_env; - MDBX_node *node; - MDBX_val sepkey, rkey, xdata; - MDBX_page *copy = NULL; - MDBX_page *rp, *pp; - MDBX_cursor mn; - DKBUF; - - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - unsigned newindx = mc->mc_ki[mc->mc_top]; - unsigned nkeys = page_numkeys(mp); - if (mdbx_audit_enabled()) { - rc = mdbx_cursor_check(mc, true); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - mdbx_debug("-----> splitting %s page %" PRIaPGNO - " and adding [%s] at index %i/%i", - IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno, DKEY(newkey), - mc->mc_ki[mc->mc_top], nkeys); - - /* Create a right sibling. */ - if ((rc = mdbx_page_new(mc, mp->mp_flags, 1, &rp))) - return rc; - rp->mp_leaf2_ksize = mp->mp_leaf2_ksize; - mdbx_debug("new right sibling: page %" PRIaPGNO, rp->mp_pgno); - - /* Usually when splitting the root page, the cursor - * height is 1. But when called from mdbx_update_key, - * the cursor height may be greater because it walks - * up the stack while finding the branch slot to update. */ - if (mc->mc_top < 1) { - if ((rc = mdbx_page_new(mc, P_BRANCH, 1, &pp))) - goto done; - /* shift current top to make room for new parent */ - mdbx_cassert(mc, mc->mc_snum < 2 && mc->mc_db->md_depth > 0); - mc->mc_pg[2] = mc->mc_pg[1]; - mc->mc_ki[2] = mc->mc_ki[1]; - mc->mc_pg[1] = mc->mc_pg[0]; - mc->mc_ki[1] = mc->mc_ki[0]; - mc->mc_pg[0] = pp; - mc->mc_ki[0] = 0; - mc->mc_db->md_root = pp->mp_pgno; - mdbx_debug("root split! new root = %" PRIaPGNO, pp->mp_pgno); - foliage = mc->mc_db->md_depth++; - - /* Add left (implicit) pointer. */ - if (unlikely((rc = mdbx_node_add_branch(mc, 0, NULL, mp->mp_pgno)) != - MDBX_SUCCESS)) { - /* undo the pre-push */ - mc->mc_pg[0] = mc->mc_pg[1]; - mc->mc_ki[0] = mc->mc_ki[1]; - mc->mc_db->md_root = mp->mp_pgno; - mc->mc_db->md_depth--; - goto done; - } - mc->mc_snum++; - mc->mc_top++; - ptop = 0; - } else { - ptop = mc->mc_top - 1; - mdbx_debug("parent branch page is %" PRIaPGNO, mc->mc_pg[ptop]->mp_pgno); - } - - mdbx_cursor_copy(mc, &mn); - mn.mc_xcursor = NULL; - mn.mc_pg[mn.mc_top] = rp; - mn.mc_ki[mn.mc_top] = 0; - mn.mc_ki[ptop] = mc->mc_ki[ptop] + 1; - - unsigned split_indx; - if (nflags & MDBX_APPEND) { - mn.mc_ki[mn.mc_top] = 0; - sepkey = *newkey; - split_indx = newindx; - nkeys = 0; - } else { - split_indx = (nkeys + 1) / 2; - if (IS_LEAF2(rp)) { - char *split, *ins; - int x; - unsigned lsize, rsize, ksize; - /* Move half of the keys to the right sibling */ - x = mc->mc_ki[mc->mc_top] - split_indx; - ksize = mc->mc_db->md_xsize; - split = page_leaf2key(mp, split_indx, ksize); - rsize = (nkeys - split_indx) * ksize; - lsize = (nkeys - split_indx) * sizeof(indx_t); - mdbx_cassert(mc, mp->mp_lower >= lsize); - mp->mp_lower -= (indx_t)lsize; - mdbx_cassert(mc, rp->mp_lower + lsize <= UINT16_MAX); - rp->mp_lower += (indx_t)lsize; - mdbx_cassert(mc, mp->mp_upper + rsize - lsize <= UINT16_MAX); - mp->mp_upper += (indx_t)(rsize - lsize); - mdbx_cassert(mc, rp->mp_upper >= rsize - lsize); - rp->mp_upper -= (indx_t)(rsize - lsize); - sepkey.iov_len = ksize; - if (newindx == split_indx) { - sepkey.iov_base = newkey->iov_base; - } else { - sepkey.iov_base = split; - } - if (x < 0) { - mdbx_cassert(mc, ksize >= sizeof(indx_t)); - ins = page_leaf2key(mp, mc->mc_ki[mc->mc_top], ksize); - memcpy(rp->mp_ptrs, split, rsize); - sepkey.iov_base = rp->mp_ptrs; - memmove(ins + ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize); - memcpy(ins, newkey->iov_base, ksize); - mdbx_cassert(mc, UINT16_MAX - mp->mp_lower >= (int)sizeof(indx_t)); - mp->mp_lower += sizeof(indx_t); - mdbx_cassert(mc, mp->mp_upper >= ksize - sizeof(indx_t)); - mp->mp_upper -= (indx_t)(ksize - sizeof(indx_t)); - } else { - if (x) - memcpy(rp->mp_ptrs, split, x * ksize); - ins = page_leaf2key(rp, x, ksize); - memcpy(ins, newkey->iov_base, ksize); - memcpy(ins + ksize, split + x * ksize, rsize - x * ksize); - mdbx_cassert(mc, UINT16_MAX - rp->mp_lower >= (int)sizeof(indx_t)); - rp->mp_lower += sizeof(indx_t); - mdbx_cassert(mc, rp->mp_upper >= ksize - sizeof(indx_t)); - rp->mp_upper -= (indx_t)(ksize - sizeof(indx_t)); - mdbx_cassert(mc, x <= UINT16_MAX); - mc->mc_ki[mc->mc_top] = (indx_t)x; - } - } else { - size_t psize, nsize, k; - /* Maximum free space in an empty page */ - const unsigned pmax = page_space(env); - nsize = IS_LEAF(mp) ? leaf_size(env, newkey, newdata) - : branch_size(env, newkey); - - /* grab a page to hold a temporary copy */ - copy = mdbx_page_malloc(mc->mc_txn, 1); - if (unlikely(copy == NULL)) { - rc = MDBX_ENOMEM; - goto done; - } - copy->mp_pgno = mp->mp_pgno; - copy->mp_flags = mp->mp_flags; - copy->mp_lower = 0; - copy->mp_upper = (indx_t)page_space(env); - - /* prepare to insert */ - for (unsigned j = i = 0; i < nkeys; i++) { - if (i == newindx) - copy->mp_ptrs[j++] = 0; - copy->mp_ptrs[j++] = mp->mp_ptrs[i]; - } - - /* When items are relatively large the split point needs - * to be checked, because being off-by-one will make the - * difference between success or failure in mdbx_node_add. - * - * It's also relevant if a page happens to be laid out - * such that one half of its nodes are all "small" and - * the other half of its nodes are "large." If the new - * item is also "large" and falls on the half with - * "large" nodes, it also may not fit. - * - * As a final tweak, if the new item goes on the last - * spot on the page (and thus, onto the new page), bias - * the split so the new page is emptier than the old page. - * This yields better packing during sequential inserts. - */ - int dir; - if (nkeys < 32 || nsize > pmax / 16 || newindx >= nkeys) { - /* Find split point */ - psize = 0; - if (newindx <= split_indx || newindx >= nkeys) { - i = 0; - dir = 1; - k = (newindx >= nkeys) ? nkeys : split_indx + 1 + IS_LEAF(mp); - } else { - i = nkeys; - dir = -1; - k = split_indx - 1; - } - for (; i != k; i += dir) { - if (i == newindx) { - psize += nsize; - node = NULL; - } else { - node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ); - psize += NODESIZE + node_ks(node) + sizeof(indx_t); - if (IS_LEAF(mp)) { - if (F_ISSET(node_flags(node), F_BIGDATA)) - psize += sizeof(pgno_t); - else - psize += node_ds(node); - } - psize = EVEN(psize); - } - if (psize > pmax || i == k - dir) { - split_indx = i + (dir < 0); - break; - } - } - } - if (split_indx == newindx) { - sepkey.iov_len = newkey->iov_len; - sepkey.iov_base = newkey->iov_base; - } else { - node = - (MDBX_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEHDRSZ); - sepkey.iov_len = node_ks(node); - sepkey.iov_base = node_key(node); - } - } - } - - mdbx_debug("separator is %d [%s]", split_indx, DKEY(&sepkey)); - if (mdbx_audit_enabled()) { - rc = mdbx_cursor_check(mc, true); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - rc = mdbx_cursor_check(&mn, true); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - } - - /* Copy separator key to the parent. */ - if (page_room(mn.mc_pg[ptop]) < branch_size(env, &sepkey)) { - const int snum = mc->mc_snum; - const int depth = mc->mc_db->md_depth; - mn.mc_snum--; - mn.mc_top--; - did_split = 1; - /* We want other splits to find mn when doing fixups */ - WITH_CURSOR_TRACKING( - mn, rc = mdbx_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0)); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - mdbx_cassert(mc, mc->mc_snum - snum == mc->mc_db->md_depth - depth); - if (mdbx_audit_enabled()) { - rc = mdbx_cursor_check(mc, true); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - } - - /* root split? */ - ptop += mc->mc_snum - snum; - - /* Right page might now have changed parent. - * Check if left page also changed parent. */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= page_numkeys(mc->mc_pg[ptop])) { - for (i = 0; i < ptop; i++) { - mc->mc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - mc->mc_pg[ptop] = mn.mc_pg[ptop]; - if (mn.mc_ki[ptop]) { - mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1; - } else { - /* find right page's left sibling */ - mc->mc_ki[ptop] = mn.mc_ki[ptop]; - rc = mdbx_cursor_sibling(mc, false); - } - } - } else { - mn.mc_top--; - rc = mdbx_node_add_branch(&mn, mn.mc_ki[ptop], &sepkey, rp->mp_pgno); - mn.mc_top++; - } - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc == MDBX_NOTFOUND) /* improper mdbx_cursor_sibling() result */ { - mdbx_error("unexpected %s", "MDBX_NOTFOUND"); - rc = MDBX_PROBLEM; - } - goto done; - } - - if (nflags & MDBX_APPEND) { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[mc->mc_top] = 0; - switch (PAGETYPE(rp)) { - case P_BRANCH: { - mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); - mdbx_cassert(mc, newpgno != 0 && newpgno != P_INVALID); - rc = mdbx_node_add_branch(mc, 0, newkey, newpgno); - } break; - case P_LEAF: { - mdbx_cassert(mc, newpgno == 0 || newpgno == P_INVALID); - rc = mdbx_node_add_leaf(mc, 0, newkey, newdata, nflags); - } break; - case P_LEAF | P_LEAF2: { - mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); - mdbx_cassert(mc, newpgno == 0 || newpgno == P_INVALID); - rc = mdbx_node_add_leaf2(mc, 0, newkey); - } break; - default: - rc = MDBX_CORRUPTED; - } - if (rc) - goto done; - for (i = 0; i < mc->mc_top; i++) - mc->mc_ki[i] = mn.mc_ki[i]; - } else if (!IS_LEAF2(mp)) { - /* Move nodes */ - mc->mc_pg[mc->mc_top] = rp; - i = split_indx; - indx_t n = 0; - do { - MDBX_val *rdata = NULL; - if (i == newindx) { - rkey.iov_base = newkey->iov_base; - rkey.iov_len = newkey->iov_len; - if (IS_LEAF(mp)) { - rdata = newdata; - } else - pgno = newpgno; - flags = nflags; - /* Update index for the new key. */ - mc->mc_ki[mc->mc_top] = n; - } else { - node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ); - rkey.iov_base = node_key(node); - rkey.iov_len = node_ks(node); - if (IS_LEAF(mp)) { - xdata.iov_base = node_data(node); - xdata.iov_len = node_ds(node); - rdata = &xdata; - } else - pgno = node_pgno(node); - flags = node_flags(node); - } - - switch (PAGETYPE(rp)) { - case P_BRANCH: { - mdbx_cassert(mc, 0 == (uint16_t)flags); - if (n == 0) { - /* First branch index doesn't need key data. */ - rkey.iov_len = 0; - } - rc = mdbx_node_add_branch(mc, n, &rkey, pgno); - } break; - case P_LEAF: { - mdbx_cassert(mc, pgno == 0); - mdbx_cassert(mc, rdata != NULL); - rc = mdbx_node_add_leaf(mc, n, &rkey, rdata, flags); - } break; - /* case P_LEAF | P_LEAF2: { - mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); - mdbx_cassert(mc, gno == 0); - rc = mdbx_node_add_leaf2(mc, n, &rkey); - } break; */ - default: - rc = MDBX_CORRUPTED; - } - if (rc) - goto done; - - if (i == nkeys) { - i = 0; - n = 0; - mc->mc_pg[mc->mc_top] = copy; - } else { - i++; - n++; - } - } while (i != split_indx); - - nkeys = page_numkeys(copy); - for (i = 0; i < nkeys; i++) - mp->mp_ptrs[i] = copy->mp_ptrs[i]; - mp->mp_lower = copy->mp_lower; - mp->mp_upper = copy->mp_upper; - memcpy(page_node(mp, nkeys - 1), page_node(copy, nkeys - 1), - env->me_psize - copy->mp_upper - PAGEHDRSZ); - - /* reset back to original page */ - if (newindx < split_indx) { - mc->mc_pg[mc->mc_top] = mp; - } else { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[ptop]++; - /* Make sure mc_ki is still valid. */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= page_numkeys(mc->mc_pg[ptop])) { - for (i = 0; i <= ptop; i++) { - mc->mc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - } - } - if (nflags & MDBX_RESERVE) { - node = page_node(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); - if (!(node_flags(node) & F_BIGDATA)) - newdata->iov_base = node_data(node); - } - } else { - if (newindx >= split_indx) { - mc->mc_pg[mc->mc_top] = rp; - mc->mc_ki[ptop]++; - /* Make sure mc_ki is still valid. */ - if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && - mc->mc_ki[ptop] >= page_numkeys(mc->mc_pg[ptop])) { - for (i = 0; i <= ptop; i++) { - mc->mc_pg[i] = mn.mc_pg[i]; - mc->mc_ki[i] = mn.mc_ki[i]; - } - } - } - } - - { - /* Adjust other cursors pointing to mp */ - MDBX_cursor *m2, *m3; - MDBX_dbi dbi = mc->mc_dbi; - nkeys = page_numkeys(mp); - - for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { - m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; - if (m3 == mc) - continue; - if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) - continue; - if (foliage) { - int k; - /* sub cursors may be on different DB */ - if (m3->mc_pg[0] != mp) - continue; - /* root split */ - for (k = foliage; k >= 0; k--) { - m3->mc_ki[k + 1] = m3->mc_ki[k]; - m3->mc_pg[k + 1] = m3->mc_pg[k]; - } - m3->mc_ki[0] = (m3->mc_ki[0] >= nkeys) ? 1 : 0; - m3->mc_pg[0] = mc->mc_pg[0]; - m3->mc_snum++; - m3->mc_top++; - } - if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) { - if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDBX_SPLIT_REPLACE)) - m3->mc_ki[mc->mc_top]++; - if (m3->mc_ki[mc->mc_top] >= nkeys) { - m3->mc_pg[mc->mc_top] = rp; - mdbx_cassert(mc, m3->mc_ki[mc->mc_top] >= nkeys); - m3->mc_ki[mc->mc_top] -= (indx_t)nkeys; - for (i = 0; i < mc->mc_top; i++) { - m3->mc_ki[i] = mn.mc_ki[i]; - m3->mc_pg[i] = mn.mc_pg[i]; - } - } - } else if (!did_split && m3->mc_top >= ptop && - m3->mc_pg[ptop] == mc->mc_pg[ptop] && - m3->mc_ki[ptop] >= mc->mc_ki[ptop]) { - m3->mc_ki[ptop]++; - } - if (XCURSOR_INITED(m3) && IS_LEAF(mp)) - XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); - } - } - mdbx_debug("mp left: %d, rp left: %d", page_room(mp), page_room(rp)); - -done: - if (copy) /* tmp page */ - mdbx_dpage_free(env, copy, 1); - if (unlikely(rc)) - mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; - return rc; -} - -int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - unsigned flags) { - int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key || !data)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE | - MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT))) - return MDBX_EINVAL; - - if (unlikely(txn->mt_flags & (MDBX_RDONLY | MDBX_TXN_BLOCKED))) - return (txn->mt_flags & MDBX_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; - - MDBX_cursor_couple cx; - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - cx.outer.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &cx.outer; - - /* LY: support for update (explicit overwrite) */ - if (flags & MDBX_CURRENT) { - rc = mdbx_cursor_get(&cx.outer, key, NULL, MDBX_SET); - if (likely(rc == MDBX_SUCCESS) && - (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT)) { - /* LY: allows update (explicit overwrite) only for unique keys */ - MDBX_node *node = page_node(cx.outer.mc_pg[cx.outer.mc_top], - cx.outer.mc_ki[cx.outer.mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - mdbx_tassert(txn, XCURSOR_INITED(&cx.outer) && - cx.outer.mc_xcursor->mx_db.md_entries > 1); - rc = MDBX_EMULTIVAL; - } - } - } - - if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_cursor_put(&cx.outer, key, data, flags); - txn->mt_cursors[dbi] = cx.outer.mc_next; - - return rc; -} - -/**** COPYING *****************************************************************/ - -#ifndef MDBX_WBUF -#define MDBX_WBUF ((size_t)1024 * 1024) -#endif -#define MDBX_EOF 0x10 /* mdbx_env_copyfd1() is done reading */ - -/* State needed for a double-buffering compacting copy. */ -typedef struct mdbx_copy { - MDBX_env *mc_env; - MDBX_txn *mc_txn; - mdbx_condmutex_t mc_condmutex; - uint8_t *mc_wbuf[2]; - uint8_t *mc_over[2]; - size_t mc_wlen[2]; - size_t mc_olen[2]; - mdbx_filehandle_t mc_fd; - volatile int mc_error; - pgno_t mc_next_pgno; - short mc_toggle; /* Buffer number in provider */ - short mc_new; /* (0-2 buffers to write) | (MDBX_EOF at end) */ - /* Error code. Never cleared if set. Both threads can set nonzero - * to fail the copy. Not mutex-protected, MDBX expects atomic int. */ -} mdbx_copy; - -/* Dedicated writer thread for compacting copy. */ -static THREAD_RESULT __cold THREAD_CALL mdbx_env_copythr(void *arg) { - mdbx_copy *my = arg; - uint8_t *ptr; - int toggle = 0; - int rc; - - mdbx_condmutex_lock(&my->mc_condmutex); - while (!my->mc_error) { - while (!my->mc_new) - mdbx_condmutex_wait(&my->mc_condmutex); - if (my->mc_new == 0 + MDBX_EOF) /* 0 buffers, just EOF */ - break; - size_t wsize = my->mc_wlen[toggle]; - ptr = my->mc_wbuf[toggle]; - again: - if (wsize > 0 && !my->mc_error) { - rc = mdbx_write(my->mc_fd, ptr, wsize); - if (rc != MDBX_SUCCESS) { - my->mc_error = rc; - break; - } - } - - /* If there's an overflow page tail, write it too */ - if (my->mc_olen[toggle]) { - wsize = my->mc_olen[toggle]; - ptr = my->mc_over[toggle]; - my->mc_olen[toggle] = 0; - goto again; - } - my->mc_wlen[toggle] = 0; - toggle ^= 1; - /* Return the empty buffer to provider */ - my->mc_new--; - mdbx_condmutex_signal(&my->mc_condmutex); - } - mdbx_condmutex_unlock(&my->mc_condmutex); - return (THREAD_RESULT)0; -} - -/* Give buffer and/or MDBX_EOF to writer thread, await unused buffer. - * - * [in] my control structure. - * [in] adjust (1 to hand off 1 buffer) | (MDBX_EOF when ending). */ -static int __cold mdbx_env_cthr_toggle(mdbx_copy *my, int adjust) { - mdbx_condmutex_lock(&my->mc_condmutex); - my->mc_new += (short)adjust; - mdbx_condmutex_signal(&my->mc_condmutex); - while (my->mc_new & 2) /* both buffers in use */ - mdbx_condmutex_wait(&my->mc_condmutex); - mdbx_condmutex_unlock(&my->mc_condmutex); - - my->mc_toggle ^= (adjust & 1); - /* Both threads reset mc_wlen, to be safe from threading errors */ - my->mc_wlen[my->mc_toggle] = 0; - return my->mc_error; -} - -/* Depth-first tree traversal for compacting copy. - * [in] my control structure. - * [in,out] pg database root. - * [in] flags includes F_DUPDATA if it is a sorted-duplicate sub-DB. */ -static int __cold mdbx_env_cwalk(mdbx_copy *my, pgno_t *pg, int flags) { - MDBX_cursor mc; - MDBX_page *mo, *mp, *leaf; - char *buf, *ptr; - int rc, toggle; - unsigned i; - - /* Empty DB, nothing to do */ - if (*pg == P_INVALID) - return MDBX_SUCCESS; - - memset(&mc, 0, sizeof(mc)); - mc.mc_snum = 1; - mc.mc_txn = my->mc_txn; - - rc = mdbx_page_get(&mc, *pg, &mc.mc_pg[0], NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_page_search_root(&mc, NULL, MDBX_PS_FIRST); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - /* Make cursor pages writable */ - buf = ptr = mdbx_malloc(pgno2bytes(my->mc_env, mc.mc_snum)); - if (buf == NULL) - return MDBX_ENOMEM; - - for (i = 0; i < mc.mc_top; i++) { - mdbx_page_copy((MDBX_page *)ptr, mc.mc_pg[i], my->mc_env->me_psize); - mc.mc_pg[i] = (MDBX_page *)ptr; - ptr += my->mc_env->me_psize; - } - - /* This is writable space for a leaf page. Usually not needed. */ - leaf = (MDBX_page *)ptr; - - toggle = my->mc_toggle; - while (mc.mc_snum > 0) { - unsigned n; - mp = mc.mc_pg[mc.mc_top]; - n = page_numkeys(mp); - - if (IS_LEAF(mp)) { - if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) { - for (i = 0; i < n; i++) { - MDBX_node *node = page_node(mp, i); - if (node_flags(node) & F_BIGDATA) { - MDBX_page *omp; - - /* Need writable leaf */ - if (mp != leaf) { - mc.mc_pg[mc.mc_top] = leaf; - mdbx_page_copy(leaf, mp, my->mc_env->me_psize); - mp = leaf; - node = page_node(mp, i); - } - - const pgno_t pgno = node_largedata_pgno(node); - poke_pgno(node_data(node), my->mc_next_pgno); - rc = mdbx_page_get(&mc, pgno, &omp, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - if (my->mc_wlen[toggle] >= MDBX_WBUF) { - rc = mdbx_env_cthr_toggle(my, 1); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - toggle = my->mc_toggle; - } - mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); - memcpy(mo, omp, my->mc_env->me_psize); - mo->mp_pgno = my->mc_next_pgno; - my->mc_next_pgno += omp->mp_pages; - my->mc_wlen[toggle] += my->mc_env->me_psize; - if (omp->mp_pages > 1) { - my->mc_olen[toggle] = pgno2bytes(my->mc_env, omp->mp_pages - 1); - my->mc_over[toggle] = (uint8_t *)omp + my->mc_env->me_psize; - rc = mdbx_env_cthr_toggle(my, 1); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - toggle = my->mc_toggle; - } - } else if (node_flags(node) & F_SUBDATA) { - if (node_ds(node) < sizeof(MDBX_db)) { - rc = MDBX_CORRUPTED; - goto done; - } - - /* Need writable leaf */ - if (mp != leaf) { - mc.mc_pg[mc.mc_top] = leaf; - mdbx_page_copy(leaf, mp, my->mc_env->me_psize); - mp = leaf; - node = page_node(mp, i); - } - - MDBX_db db; - memcpy(&db, node_data(node), sizeof(MDBX_db)); - my->mc_toggle = (short)toggle; - rc = mdbx_env_cwalk(my, &db.md_root, node_flags(node) & F_DUPDATA); - if (rc) - goto done; - toggle = my->mc_toggle; - memcpy(node_data(node), &db, sizeof(MDBX_db)); - } - } - } - } else { - mc.mc_ki[mc.mc_top]++; - if (mc.mc_ki[mc.mc_top] < n) { - again: - rc = mdbx_page_get(&mc, node_pgno(page_node(mp, mc.mc_ki[mc.mc_top])), - &mp, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - mc.mc_top++; - mc.mc_snum++; - mc.mc_ki[mc.mc_top] = 0; - if (IS_BRANCH(mp)) { - /* Whenever we advance to a sibling branch page, - * we must proceed all the way down to its first leaf. */ - mdbx_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize); - goto again; - } else - mc.mc_pg[mc.mc_top] = mp; - continue; - } - } - if (my->mc_wlen[toggle] >= MDBX_WBUF) { - rc = mdbx_env_cthr_toggle(my, 1); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - toggle = my->mc_toggle; - } - mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); - mdbx_page_copy(mo, mp, my->mc_env->me_psize); - mo->mp_pgno = my->mc_next_pgno++; - my->mc_wlen[toggle] += my->mc_env->me_psize; - if (mc.mc_top) { - /* Update parent if there is one */ - node_set_pgno(page_node(mc.mc_pg[mc.mc_top - 1], mc.mc_ki[mc.mc_top - 1]), - mo->mp_pgno); - mdbx_cursor_pop(&mc); - } else { - /* Otherwise we're done */ - *pg = mo->mp_pgno; - break; - } - } -done: - mdbx_free(buf); - return rc; -} - -static __cold void compact_fixup_meta(MDBX_env *env, MDBX_meta *meta) { - /* Calculate filesize taking in account shrink/growing thresholds */ - if (meta->mm_geo.next > meta->mm_geo.now) { - const pgno_t aligned = pgno_align2os_pgno( - env, - pgno_add(meta->mm_geo.next, - meta->mm_geo.grow - meta->mm_geo.next % meta->mm_geo.grow)); - meta->mm_geo.now = aligned; - } else if (meta->mm_geo.next < meta->mm_geo.now) { - meta->mm_geo.now = meta->mm_geo.next; - const pgno_t aligner = - meta->mm_geo.grow ? meta->mm_geo.grow : meta->mm_geo.shrink; - const pgno_t aligned = pgno_align2os_pgno( - env, meta->mm_geo.next + aligner - meta->mm_geo.next % aligner); - meta->mm_geo.now = aligned; - } - - if (meta->mm_geo.now < meta->mm_geo.lower) - meta->mm_geo.now = meta->mm_geo.lower; - if (meta->mm_geo.now > meta->mm_geo.upper) - meta->mm_geo.now = meta->mm_geo.upper; - - /* Update signature */ - assert(meta->mm_geo.now >= meta->mm_geo.next); - meta->mm_datasync_sign = mdbx_meta_sign(meta); -} - -/* Copy environment with compaction. */ -static int __cold mdbx_env_compact(MDBX_env *env, MDBX_txn *read_txn, - mdbx_filehandle_t fd, uint8_t *buffer, - const bool dest_is_pipe) { - const size_t meta_bytes = pgno2bytes(env, NUM_METAS); - uint8_t *const data_buffer = - buffer + roundup_powerof2(meta_bytes, env->me_os_psize); - MDBX_meta *const meta = mdbx_init_metas(env, buffer); - /* copy canary sequenses if present */ - if (read_txn->mt_canary.v) { - meta->mm_canary = read_txn->mt_canary; - meta->mm_canary.v = mdbx_meta_txnid_stable(env, meta); - } - - /* Set metapage 1 with current main DB */ - pgno_t new_root, root = read_txn->mt_dbs[MAIN_DBI].md_root; - if ((new_root = root) == P_INVALID) { - /* When the DB is empty, handle it specially to - * fix any breakage like page leaks from ITS#8174. */ - meta->mm_dbs[MAIN_DBI].md_flags = read_txn->mt_dbs[MAIN_DBI].md_flags; - compact_fixup_meta(env, meta); - if (dest_is_pipe) { - int rc = mdbx_write(fd, buffer, meta_bytes); - if (rc != MDBX_SUCCESS) - return rc; - } - } else { - /* Count free pages + GC pages. Subtract from last_pg - * to find the new last_pg, which also becomes the new root. */ - pgno_t freecount = 0; - MDBX_cursor mc; - MDBX_val key, data; - - int rc = mdbx_cursor_init(&mc, read_txn, FREE_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - while ((rc = mdbx_cursor_get(&mc, &key, &data, MDBX_NEXT)) == 0) - freecount += *(pgno_t *)data.iov_base; - if (unlikely(rc != MDBX_NOTFOUND)) - return rc; - - freecount += read_txn->mt_dbs[FREE_DBI].md_branch_pages + - read_txn->mt_dbs[FREE_DBI].md_leaf_pages + - read_txn->mt_dbs[FREE_DBI].md_overflow_pages; - - new_root = read_txn->mt_next_pgno - 1 - freecount; - meta->mm_geo.next = new_root + 1; - meta->mm_dbs[MAIN_DBI] = read_txn->mt_dbs[MAIN_DBI]; - meta->mm_dbs[MAIN_DBI].md_root = new_root; - - mdbx_copy ctx; - memset(&ctx, 0, sizeof(ctx)); - rc = mdbx_condmutex_init(&ctx.mc_condmutex); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - memset(data_buffer, 0, MDBX_WBUF * 2); - ctx.mc_wbuf[0] = data_buffer; - ctx.mc_wbuf[1] = data_buffer + MDBX_WBUF; - ctx.mc_next_pgno = NUM_METAS; - ctx.mc_env = env; - ctx.mc_fd = fd; - ctx.mc_txn = read_txn; - - mdbx_thread_t thread; - int thread_err = mdbx_thread_create(&thread, mdbx_env_copythr, &ctx); - if (likely(thread_err == MDBX_SUCCESS)) { - if (dest_is_pipe) { - compact_fixup_meta(env, meta); - rc = mdbx_write(fd, buffer, meta_bytes); - } - if (rc == MDBX_SUCCESS) - rc = mdbx_env_cwalk(&ctx, &root, 0); - mdbx_env_cthr_toggle(&ctx, 1 | MDBX_EOF); - thread_err = mdbx_thread_join(thread); - mdbx_condmutex_destroy(&ctx.mc_condmutex); - } - if (unlikely(thread_err != MDBX_SUCCESS)) - return thread_err; - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - if (unlikely(ctx.mc_error != MDBX_SUCCESS)) - return ctx.mc_error; - - if (dest_is_pipe) { - if (root != new_root) { - mdbx_error("post-compactification root %" PRIaPGNO - " NE expected %" PRIaPGNO - " (source DB corrupted or has a page leak(s))", - root, new_root); - return MDBX_CORRUPTED; /* page leak or corrupt DB */ - } - } else { - if (root > new_root) { - mdbx_error("post-compactification root %" PRIaPGNO - " GT expected %" PRIaPGNO " (source DB corrupted)", - root, new_root); - return MDBX_CORRUPTED; /* page leak or corrupt DB */ - } - if (root < new_root) { - mdbx_notice("post-compactification root %" PRIaPGNO - " LT expected %" PRIaPGNO " (page leak(s) in source DB)", - root, new_root); - /* fixup meta */ - meta->mm_dbs[MAIN_DBI].md_root = root; - meta->mm_geo.next = root + 1; - } - compact_fixup_meta(env, meta); - } - } - - /* Extend file if required */ - if (meta->mm_geo.now != meta->mm_geo.next) { - const size_t whole_size = pgno2bytes(env, meta->mm_geo.now); - if (!dest_is_pipe) - return mdbx_ftruncate(fd, whole_size); - - const size_t used_size = pgno2bytes(env, meta->mm_geo.next); - memset(data_buffer, 0, MDBX_WBUF); - for (size_t offset = used_size; offset < whole_size;) { - const size_t chunk = - (MDBX_WBUF < whole_size - offset) ? MDBX_WBUF : whole_size - offset; - /* copy to avoit EFAULT in case swapped-out */ - int rc = mdbx_write(fd, data_buffer, chunk); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - offset += chunk; - } - } - return MDBX_SUCCESS; -} - -/* Copy environment as-is. */ -static int __cold mdbx_env_copy_asis(MDBX_env *env, MDBX_txn *read_txn, - mdbx_filehandle_t fd, uint8_t *buffer, - const bool dest_is_pipe) { - /* We must start the actual read txn after blocking writers */ - int rc = mdbx_txn_end(read_txn, MDBX_END_RESET_TMP); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - /* Temporarily block writers until we snapshot the meta pages */ - rc = mdbx_txn_lock(env, false); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - rc = mdbx_txn_renew0(read_txn, MDBX_RDONLY); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_txn_unlock(env); - return rc; - } - - mdbx_jitter4testing(false); - const size_t meta_bytes = pgno2bytes(env, NUM_METAS); - /* Make a snapshot of meta-pages, - * but writing ones after the data was flushed */ - memcpy(buffer, env->me_map, meta_bytes); - MDBX_meta *const headcopy = /* LY: get pointer to the spanshot copy */ - (MDBX_meta *)(buffer + ((uint8_t *)mdbx_meta_head(env) - env->me_map)); - /* Update signature to steady */ - headcopy->mm_datasync_sign = mdbx_meta_sign(headcopy); - mdbx_txn_unlock(env); - - /* Copy the data */ - const size_t whole_size = pgno_align2os_bytes(env, read_txn->mt_end_pgno); - const size_t used_size = pgno2bytes(env, read_txn->mt_next_pgno); - mdbx_jitter4testing(false); - - if (dest_is_pipe) - rc = mdbx_write(fd, buffer, meta_bytes); - - uint8_t *const data_buffer = - buffer + roundup_powerof2(meta_bytes, env->me_os_psize); - for (size_t offset = meta_bytes; rc == MDBX_SUCCESS && offset < used_size;) { - if (dest_is_pipe) { -#if defined(__linux__) || defined(__gnu_linux__) - off_t in_offset = offset; - const intptr_t written = - sendfile(fd, env->me_fd, &in_offset, used_size - offset); - if (unlikely(written <= 0)) { - rc = written ? errno : MDBX_ENODATA; - break; - } - offset = in_offset; - continue; -#endif - } else { -#if __GLIBC_PREREQ(2, 27) && defined(_GNU_SOURCE) - off_t in_offset = offset, out_offset = offset; - ssize_t bytes_copied = copy_file_range( - env->me_fd, &in_offset, fd, &out_offset, used_size - offset, 0); - if (unlikely(bytes_copied <= 0)) { - rc = bytes_copied ? errno : MDBX_ENODATA; - break; - } - offset = in_offset; - continue; -#endif - } - - /* fallback to portable */ - const size_t chunk = - (MDBX_WBUF < used_size - offset) ? MDBX_WBUF : used_size - offset; - /* copy to avoit EFAULT in case swapped-out */ - memcpy(data_buffer, env->me_map + offset, chunk); - rc = mdbx_write(fd, data_buffer, chunk); - offset += chunk; - } - - /* Extend file if required */ - if (likely(rc == MDBX_SUCCESS) && whole_size != used_size) { - if (!dest_is_pipe) - rc = mdbx_ftruncate(fd, whole_size); - else { - memset(data_buffer, 0, MDBX_WBUF); - for (size_t offset = used_size; - rc == MDBX_SUCCESS && offset < whole_size;) { - const size_t chunk = - (MDBX_WBUF < whole_size - offset) ? MDBX_WBUF : whole_size - offset; - /* copy to avoit EFAULT in case swapped-out */ - rc = mdbx_write(fd, data_buffer, chunk); - offset += chunk; - } - } - } - - return rc; -} - -int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd, - unsigned flags) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - const int dest_is_pipe = mdbx_is_pipe(fd); - if (MDBX_IS_ERROR(dest_is_pipe)) - return dest_is_pipe; - - if (!dest_is_pipe) { - int rc = mdbx_fseek(fd, 0); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - const size_t buffer_size = - pgno_align2os_bytes(env, NUM_METAS) + - roundup_powerof2(((flags & MDBX_CP_COMPACT) ? MDBX_WBUF * 2 : MDBX_WBUF), - env->me_os_psize); - - uint8_t *buffer = NULL; - int rc = mdbx_memalign_alloc(env->me_os_psize, buffer_size, (void **)&buffer); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - MDBX_txn *read_txn = NULL; - /* Do the lock/unlock of the reader mutex before starting the - * write txn. Otherwise other read txns could block writers. */ - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &read_txn); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_memalign_free(buffer); - return rc; - } - - if (!dest_is_pipe) { - /* Firstly write a stub to meta-pages. - * Now we sure to incomplete copy will not be used. */ - memset(buffer, -1, pgno2bytes(env, NUM_METAS)); - rc = mdbx_write(fd, buffer, pgno2bytes(env, NUM_METAS)); - } - - if (likely(rc == MDBX_SUCCESS)) { - memset(buffer, 0, pgno2bytes(env, NUM_METAS)); - rc = (flags & MDBX_CP_COMPACT) - ? mdbx_env_compact(env, read_txn, fd, buffer, dest_is_pipe) - : mdbx_env_copy_asis(env, read_txn, fd, buffer, dest_is_pipe); - } - mdbx_txn_abort(read_txn); - - if (!dest_is_pipe) { - if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_SIZE | MDBX_SYNC_IODQ); - - /* Write actual meta */ - if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0); - - if (likely(rc == MDBX_SUCCESS)) - rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ); - } - - mdbx_memalign_free(buffer); - return rc; -} - -int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path, unsigned flags) { - if (unlikely(!env || !dest_path)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - char *dxb_pathname; - mdbx_filehandle_t newfd = INVALID_HANDLE_VALUE; - - if (env->me_flags & MDBX_NOSUBDIR) { - dxb_pathname = (char *)dest_path; - } else { - size_t len = strlen(dest_path); - len += sizeof(MDBX_DATANAME); - dxb_pathname = mdbx_malloc(len); - if (!dxb_pathname) - return MDBX_ENOMEM; - sprintf(dxb_pathname, "%s" MDBX_DATANAME, dest_path); - } - - /* The destination path must exist, but the destination file must not. - * We don't want the OS to cache the writes, since the source data is - * already in the OS cache. */ - int rc = mdbx_openfile(dxb_pathname, O_WRONLY | O_CREAT | O_EXCL, 0640, - &newfd, true); - if (rc == MDBX_SUCCESS) { - if (env->me_psize >= env->me_os_psize) { -#ifdef F_NOCACHE /* __APPLE__ */ - (void)fcntl(newfd, F_NOCACHE, 1); -#elif defined(O_DIRECT) && defined(F_GETFL) - /* Set O_DIRECT if the file system supports it */ - if ((rc = fcntl(newfd, F_GETFL)) != -1) - (void)fcntl(newfd, F_SETFL, rc | O_DIRECT); -#endif - } - rc = mdbx_env_copy2fd(env, newfd, flags); - } - - if (newfd != INVALID_HANDLE_VALUE) { - int err = mdbx_closefile(newfd); - if (rc == MDBX_SUCCESS && err != rc) - rc = err; - if (rc != MDBX_SUCCESS) - (void)mdbx_removefile(dxb_pathname); - } - - if (dxb_pathname != dest_path) - mdbx_free(dxb_pathname); - - return rc; -} - -/******************************************************************************/ - -int __cold mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(flags & ~CHANGEABLE)) - return MDBX_EPERM; - - if (unlikely(env->me_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - if (unlikely(env->me_txn0->mt_owner == mdbx_thread_self())) - return MDBX_BUSY; - - int rc = mdbx_txn_lock(env, false); - if (unlikely(rc)) - return rc; - - if (onoff) - env->me_flags |= flags; - else - env->me_flags &= ~flags; - - mdbx_txn_unlock(env); - return MDBX_SUCCESS; -} - -int __cold mdbx_env_get_flags(MDBX_env *env, unsigned *arg) { - if (unlikely(!env || !arg)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - *arg = env->me_flags & (CHANGEABLE | CHANGELESS); - return MDBX_SUCCESS; -} - -int __cold mdbx_env_set_userctx(MDBX_env *env, void *ctx) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - env->me_userctx = ctx; - return MDBX_SUCCESS; -} - -void *__cold mdbx_env_get_userctx(MDBX_env *env) { - return env ? env->me_userctx : NULL; -} - -int __cold mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - -#if MDBX_DEBUG - env->me_assert_func = func; - return MDBX_SUCCESS; -#else - (void)func; - return MDBX_ENOSYS; -#endif -} - -int __cold mdbx_env_get_path(MDBX_env *env, const char **arg) { - if (unlikely(!env || !arg)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - *arg = env->me_path; - return MDBX_SUCCESS; -} - -int __cold mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *arg) { - if (unlikely(!env || !arg)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - *arg = env->me_fd; - return MDBX_SUCCESS; -} - -/* Common code for mdbx_dbi_stat() and mdbx_env_stat(). - * [in] env the environment to operate in. - * [in] db the MDBX_db record containing the stats to return. - * [out] arg the address of an MDBX_stat structure to receive the stats. - * Returns 0, this function always succeeds. */ -static void mdbx_stat0(const MDBX_env *env, const MDBX_db *db, MDBX_stat *dest, - size_t bytes) { - dest->ms_psize = env->me_psize; - dest->ms_depth = db->md_depth; - dest->ms_branch_pages = db->md_branch_pages; - dest->ms_leaf_pages = db->md_leaf_pages; - dest->ms_overflow_pages = db->md_overflow_pages; - dest->ms_entries = db->md_entries; - if (likely(bytes >= - offsetof(MDBX_stat, ms_mod_txnid) + sizeof(dest->ms_mod_txnid))) - dest->ms_mod_txnid = db->md_mod_txnid; -} - -int __cold mdbx_env_stat(MDBX_env *env, MDBX_stat *dest, size_t bytes) { - return mdbx_env_stat_ex(env, NULL, dest, bytes); -} - -int __cold mdbx_env_stat_ex(const MDBX_env *env, const MDBX_txn *txn, - MDBX_stat *dest, size_t bytes) { - if (unlikely((env == NULL && txn == NULL) || dest == NULL)) - return MDBX_EINVAL; - - if (txn) { - int err = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - if (env) { - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - if (txn && unlikely(txn->mt_env != env)) - return MDBX_EINVAL; - } - - const size_t size_before_modtxnid = offsetof(MDBX_stat, ms_mod_txnid); - if (unlikely(bytes != sizeof(MDBX_stat)) && bytes != size_before_modtxnid) - return MDBX_EINVAL; - - if (txn) { - mdbx_stat0(txn->mt_env, &txn->mt_dbs[MAIN_DBI], dest, bytes); - return MDBX_SUCCESS; - } - - while (1) { - const MDBX_meta *const recent_meta = mdbx_meta_head(env); - const txnid_t txnid = mdbx_meta_txnid_fluid(env, recent_meta); - mdbx_stat0(env, &recent_meta->mm_dbs[MAIN_DBI], dest, bytes); - mdbx_compiler_barrier(); - if (likely(txnid == mdbx_meta_txnid_fluid(env, recent_meta) && - recent_meta == mdbx_meta_head(env))) - return MDBX_SUCCESS; - } -} - -int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) { - return mdbx_env_info_ex(env, NULL, arg, bytes); -} - -int __cold mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, - MDBX_envinfo *arg, size_t bytes) { - if (unlikely((env == NULL && txn == NULL) || arg == NULL)) - return MDBX_EINVAL; - - if (txn) { - int err = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - if (env) { - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - if (txn && unlikely(txn->mt_env != env)) - return MDBX_EINVAL; - } else { - env = txn->mt_env; - } - - const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid); - if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid) - return MDBX_EINVAL; - - const MDBX_meta *const meta0 = METAPAGE(env, 0); - const MDBX_meta *const meta1 = METAPAGE(env, 1); - const MDBX_meta *const meta2 = METAPAGE(env, 2); - pgno_t unsynced_pages; - while (1) { - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) - return MDBX_PANIC; - - const MDBX_meta *const recent_meta = mdbx_meta_head(env); - arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, recent_meta); - arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0); - arg->mi_meta0_sign = meta0->mm_datasync_sign; - arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1); - arg->mi_meta1_sign = meta1->mm_datasync_sign; - arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); - arg->mi_meta2_sign = meta2->mm_datasync_sign; - - const MDBX_meta *txn_meta = recent_meta; - arg->mi_last_pgno = txn_meta->mm_geo.next - 1; - arg->mi_geo.current = pgno2bytes(env, txn_meta->mm_geo.now); - if (txn) { - arg->mi_last_pgno = txn->mt_next_pgno - 1; - arg->mi_geo.current = pgno2bytes(env, txn->mt_end_pgno); - - const txnid_t wanna_meta_txnid = (txn->mt_flags & MDBX_RDONLY) - ? txn->mt_txnid - : txn->mt_txnid - MDBX_TXNID_STEP; - txn_meta = (arg->mi_meta0_txnid == wanna_meta_txnid) ? meta0 : txn_meta; - txn_meta = (arg->mi_meta1_txnid == wanna_meta_txnid) ? meta1 : txn_meta; - txn_meta = (arg->mi_meta2_txnid == wanna_meta_txnid) ? meta2 : txn_meta; - } - arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower); - arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper); - arg->mi_geo.shrink = pgno2bytes(env, txn_meta->mm_geo.shrink); - arg->mi_geo.grow = pgno2bytes(env, txn_meta->mm_geo.grow); - unsynced_pages = *env->me_unsynced_pages + - (*env->me_meta_sync_txnid != (uint32_t)arg->mi_last_pgno); - - arg->mi_mapsize = env->me_dxb_mmap.limit; - mdbx_compiler_barrier(); - if (likely(arg->mi_meta0_txnid == mdbx_meta_txnid_fluid(env, meta0) && - arg->mi_meta0_sign == meta0->mm_datasync_sign && - arg->mi_meta1_txnid == mdbx_meta_txnid_fluid(env, meta1) && - arg->mi_meta1_sign == meta1->mm_datasync_sign && - arg->mi_meta2_txnid == mdbx_meta_txnid_fluid(env, meta2) && - arg->mi_meta2_sign == meta2->mm_datasync_sign && - recent_meta == mdbx_meta_head(env) && - arg->mi_recent_txnid == mdbx_meta_txnid_fluid(env, recent_meta))) - break; - } - - arg->mi_maxreaders = env->me_maxreaders; - arg->mi_numreaders = env->me_lck ? env->me_lck->mti_numreaders : INT32_MAX; - arg->mi_dxb_pagesize = env->me_psize; - arg->mi_sys_pagesize = env->me_os_psize; - - const MDBX_lockinfo *const lck = env->me_lck; - if (likely(bytes > size_before_bootid)) { - arg->mi_unsync_volume = pgno2bytes(env, unsynced_pages); - const uint64_t monotime_now = mdbx_osal_monotime(); - arg->mi_since_sync_seconds16dot16 = - mdbx_osal_monotime_to_16dot16(monotime_now - *env->me_sync_timestamp); - arg->mi_since_reader_check_seconds16dot16 = - lck ? mdbx_osal_monotime_to_16dot16(monotime_now - - lck->mti_reader_check_timestamp) - : 0; - arg->mi_autosync_threshold = pgno2bytes(env, *env->me_autosync_threshold); - arg->mi_autosync_period_seconds16dot16 = - mdbx_osal_monotime_to_16dot16(*env->me_autosync_period); - arg->mi_bootid[0] = lck ? lck->mti_bootid.x : 0; - arg->mi_bootid[1] = lck ? lck->mti_bootid.y : 0; - arg->mi_mode = lck ? lck->mti_envmode : env->me_flags; - } - - arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = 0; - if (lck) { - arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = - arg->mi_recent_txnid; - for (unsigned i = 0; i < arg->mi_numreaders; ++i) { - const uint32_t pid = lck->mti_readers[i].mr_pid; - if (pid) { - const txnid_t txnid = safe64_read(&lck->mti_readers[i].mr_txnid); - if (arg->mi_latter_reader_txnid > txnid) - arg->mi_latter_reader_txnid = txnid; - if (pid == env->me_pid && arg->mi_self_latter_reader_txnid > txnid) - arg->mi_self_latter_reader_txnid = txnid; - } - } - } - - return MDBX_SUCCESS; -} - -static MDBX_cmp_func *mdbx_default_keycmp(unsigned flags) { - return (flags & MDBX_REVERSEKEY) - ? mdbx_cmp_memnr - : (flags & MDBX_INTEGERKEY) ? mdbx_cmp_int_align2 : mdbx_cmp_memn; -} - -static MDBX_cmp_func *mdbx_default_datacmp(unsigned flags) { - return !(flags & MDBX_DUPSORT) - ? mdbx_cmp_memn - : ((flags & MDBX_INTEGERDUP) - ? mdbx_cmp_int_unaligned - : ((flags & MDBX_REVERSEDUP) ? mdbx_cmp_memnr - : mdbx_cmp_memn)); -} - -static int mdbx_dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, - MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp) { - /* LY: so, accepting only three cases for the table's flags: - * 1) user_flags and both comparators are zero - * = assume that a by-default mode/flags is requested for reading; - * 2) user_flags exactly the same - * = assume that the target mode/flags are requested properly; - * 3) user_flags differs, but table is empty and MDBX_CREATE is provided - * = assume that a properly create request with custom flags; - */ - if ((user_flags ^ txn->mt_dbs[dbi].md_flags) & PERSISTENT_FLAGS) { - /* flags ara differs, check other conditions */ - if (!user_flags && (!keycmp || keycmp == txn->mt_dbxs[dbi].md_cmp) && - (!datacmp || datacmp == txn->mt_dbxs[dbi].md_dcmp)) { - /* no comparators were provided and flags are zero, - * seems that is case #1 above */ - user_flags = txn->mt_dbs[dbi].md_flags; - } else if ((user_flags & MDBX_CREATE) && txn->mt_dbs[dbi].md_entries == 0) { - if (txn->mt_flags & MDBX_RDONLY) - return /* FIXME: return extended info */ MDBX_EACCESS; - /* make sure flags changes get committed */ - txn->mt_dbs[dbi].md_flags = user_flags & PERSISTENT_FLAGS; - txn->mt_flags |= MDBX_TXN_DIRTY; - } else { - return /* FIXME: return extended info */ MDBX_INCOMPATIBLE; - } - } - - if (!txn->mt_dbxs[dbi].md_cmp || MDBX_DEBUG) { - if (!keycmp) - keycmp = mdbx_default_keycmp(user_flags); - mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_cmp || - txn->mt_dbxs[dbi].md_cmp == keycmp); - txn->mt_dbxs[dbi].md_cmp = keycmp; - } - - if (!txn->mt_dbxs[dbi].md_dcmp || MDBX_DEBUG) { - if (!datacmp) - datacmp = mdbx_default_datacmp(user_flags); - mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_dcmp || - txn->mt_dbxs[dbi].md_dcmp == datacmp); - txn->mt_dbxs[dbi].md_dcmp = datacmp; - } - - return MDBX_SUCCESS; -} - -int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, - MDBX_dbi *dbi, MDBX_cmp_func *keycmp, - MDBX_cmp_func *datacmp) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!dbi || (user_flags & ~VALID_FLAGS) != 0)) - return MDBX_EINVAL; - - switch (user_flags & - (MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT | MDBX_REVERSEDUP)) { - default: - return MDBX_EINVAL; - case MDBX_DUPSORT: - case MDBX_DUPSORT | MDBX_REVERSEDUP: - case MDBX_DUPSORT | MDBX_DUPFIXED: - case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_REVERSEDUP: - case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP: - case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP: - case 0: - break; - } - - /* main table? */ - if (!table_name) { - *dbi = MAIN_DBI; - return mdbx_dbi_bind(txn, MAIN_DBI, user_flags, keycmp, datacmp); - } - - if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) { - txn->mt_dbxs[MAIN_DBI].md_cmp = - mdbx_default_keycmp(txn->mt_dbs[MAIN_DBI].md_flags); - txn->mt_dbxs[MAIN_DBI].md_dcmp = - mdbx_default_datacmp(txn->mt_dbs[MAIN_DBI].md_flags); - } - - /* Is the DB already open? */ - size_t len = strlen(table_name); - MDBX_dbi scan, slot; - for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) { - if (!txn->mt_dbxs[scan].md_name.iov_len) { - /* Remember this free slot */ - slot = scan; - continue; - } - if (len == txn->mt_dbxs[scan].md_name.iov_len && - !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) { - *dbi = scan; - return mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp); - } - } - - /* Fail, if no free slot and max hit */ - MDBX_env *env = txn->mt_env; - if (unlikely(slot >= env->me_maxdbs)) - return MDBX_DBS_FULL; - - /* Cannot mix named table with some main-table flags */ - if (unlikely(txn->mt_dbs[MAIN_DBI].md_flags & - (MDBX_DUPSORT | MDBX_INTEGERKEY))) - return (user_flags & MDBX_CREATE) ? MDBX_INCOMPATIBLE : MDBX_NOTFOUND; - - /* Find the DB info */ - int exact = 0; - MDBX_val key, data; - key.iov_len = len; - key.iov_base = (void *)table_name; - MDBX_cursor mc; - rc = mdbx_cursor_init(&mc, txn, MAIN_DBI); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_cursor_set(&mc, &key, &data, MDBX_SET, &exact); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc != MDBX_NOTFOUND || !(user_flags & MDBX_CREATE)) - return rc; - } else { - /* make sure this is actually a table */ - MDBX_node *node = page_node(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]); - if (unlikely((node_flags(node) & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA)) - return MDBX_INCOMPATIBLE; - if (unlikely(data.iov_len < sizeof(MDBX_db))) - return MDBX_CORRUPTED; - } - - if (rc != MDBX_SUCCESS && unlikely(txn->mt_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - /* Done here so we cannot fail after creating a new DB */ - char *namedup = mdbx_strdup(table_name); - if (unlikely(!namedup)) - return MDBX_ENOMEM; - - int err = mdbx_fastmutex_acquire(&env->me_dbi_lock); - if (unlikely(err != MDBX_SUCCESS)) { - mdbx_free(namedup); - return err; - } - - if (txn->mt_numdbs < env->me_numdbs) { - for (unsigned i = txn->mt_numdbs; i < env->me_numdbs; ++i) { - txn->mt_dbflags[i] = 0; - if (env->me_dbflags[i] & MDBX_VALID) { - txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS; - txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE; - mdbx_tassert(txn, txn->mt_dbxs[i].md_cmp != NULL); - } - } - txn->mt_numdbs = env->me_numdbs; - } - - for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) { - if (!txn->mt_dbxs[scan].md_name.iov_len) { - /* Remember this free slot */ - slot = scan; - continue; - } - if (len == txn->mt_dbxs[scan].md_name.iov_len && - !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) { - *dbi = scan; - rc = mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp); - goto bailout; - } - } - - if (unlikely(slot >= env->me_maxdbs)) { - rc = MDBX_DBS_FULL; - goto bailout; - } - - unsigned dbflag = DB_FRESH | DB_VALID | DB_USRVALID; - MDBX_db db_dummy; - if (unlikely(rc)) { - /* MDBX_NOTFOUND and MDBX_CREATE: Create new DB */ - mdbx_tassert(txn, rc == MDBX_NOTFOUND); - memset(&db_dummy, 0, sizeof(db_dummy)); - db_dummy.md_root = P_INVALID; - db_dummy.md_flags = user_flags & PERSISTENT_FLAGS; - data.iov_len = sizeof(db_dummy); - data.iov_base = &db_dummy; - WITH_CURSOR_TRACKING( - mc, - rc = mdbx_cursor_put(&mc, &key, &data, F_SUBDATA | MDBX_NOOVERWRITE)); - - if (unlikely(rc != MDBX_SUCCESS)) - goto bailout; - - dbflag |= DB_DIRTY | DB_CREAT; - } - - /* Got info, register DBI in this txn */ - txn->mt_dbxs[slot].md_cmp = nullptr; - txn->mt_dbxs[slot].md_dcmp = nullptr; - txn->mt_dbs[slot] = *(MDBX_db *)data.iov_base; - env->me_dbflags[slot] = 0; - rc = mdbx_dbi_bind(txn, slot, user_flags, keycmp, datacmp); - if (unlikely(rc != MDBX_SUCCESS)) { - mdbx_tassert(txn, (dbflag & DB_CREAT) == 0); - bailout: - mdbx_free(namedup); - } else { - txn->mt_dbflags[slot] = (uint8_t)dbflag; - txn->mt_dbxs[slot].md_name.iov_base = namedup; - txn->mt_dbxs[slot].md_name.iov_len = len; - txn->mt_numdbs += (slot == txn->mt_numdbs); - if ((dbflag & DB_CREAT) == 0) { - env->me_dbflags[slot] = txn->mt_dbs[slot].md_flags | MDBX_VALID; - mdbx_compiler_barrier(); - if (env->me_numdbs <= slot) - env->me_numdbs = slot + 1; - } else { - env->me_dbiseqs[slot] += 1; - } - txn->mt_dbiseqs[slot] = env->me_dbiseqs[slot]; - *dbi = slot; - } - - mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); - return rc; -} - -int mdbx_dbi_open(MDBX_txn *txn, const char *table_name, unsigned table_flags, - MDBX_dbi *dbi) { - return mdbx_dbi_open_ex(txn, table_name, table_flags, dbi, nullptr, nullptr); -} - -int __cold mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *dest, - size_t bytes) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!dest)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) - return MDBX_EINVAL; - - const size_t size_before_modtxnid = offsetof(MDBX_stat, ms_mod_txnid); - if (unlikely(bytes != sizeof(MDBX_stat)) && bytes != size_before_modtxnid) - return MDBX_EINVAL; - - if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) - return MDBX_BAD_TXN; - - if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) { - rc = mdbx_fetch_sdb(txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - mdbx_stat0(txn->mt_env, &txn->mt_dbs[dbi], dest, bytes); - return MDBX_SUCCESS; -} - -static int mdbx_dbi_close_locked(MDBX_env *env, MDBX_dbi dbi) { - if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs)) - return MDBX_EINVAL; - - char *ptr = env->me_dbxs[dbi].md_name.iov_base; - /* If there was no name, this was already closed */ - if (unlikely(!ptr)) - return MDBX_BAD_DBI; - - env->me_dbflags[dbi] = 0; - env->me_dbxs[dbi].md_name.iov_len = 0; - mdbx_compiler_barrier(); - env->me_dbiseqs[dbi]++; - env->me_dbxs[dbi].md_name.iov_base = NULL; - mdbx_free(ptr); - return MDBX_SUCCESS; -} - -int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs)) - return MDBX_EINVAL; - - int rc = mdbx_fastmutex_acquire(&env->me_dbi_lock); - if (likely(rc == MDBX_SUCCESS)) { - rc = mdbx_dbi_close_locked(env, dbi); - mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); - } - return rc; -} - -int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, - unsigned *state) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!flags || !state)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) - return MDBX_EINVAL; - - *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS; - *state = txn->mt_dbflags[dbi] & (DB_FRESH | DB_CREAT | DB_DIRTY | DB_STALE); - - return MDBX_SUCCESS; -} - -int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { - unsigned state; - return mdbx_dbi_flags_ex(txn, dbi, flags, &state); -} - -/* Add all the DB's pages to the free list. - * [in] mc Cursor on the DB to free. - * [in] subs non-Zero to check for sub-DBs in this DB. - * Returns 0 on success, non-zero on failure. */ -static int mdbx_drop0(MDBX_cursor *mc, int subs) { - int rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST); - if (likely(rc == MDBX_SUCCESS)) { - MDBX_txn *txn = mc->mc_txn; - MDBX_cursor mx; - unsigned i; - - /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves. - * This also avoids any P_LEAF2 pages, which have no nodes. - * Also if the DB doesn't have sub-DBs and has no overflow - * pages, omit scanning leaves. */ - if ((mc->mc_flags & C_SUB) || (subs | mc->mc_db->md_overflow_pages) == 0) - mdbx_cursor_pop(mc); - - rc = mdbx_pnl_need(&txn->tw.retired_pages, - mc->mc_db->md_branch_pages + mc->mc_db->md_leaf_pages + - mc->mc_db->md_overflow_pages); - if (unlikely(rc)) - goto done; - - mdbx_cursor_copy(mc, &mx); - while (mc->mc_snum > 0) { - MDBX_page *mp = mc->mc_pg[mc->mc_top]; - unsigned n = page_numkeys(mp); - if (IS_LEAF(mp)) { - for (i = 0; i < n; i++) { - MDBX_node *node = page_node(mp, i); - if (node_flags(node) & F_BIGDATA) { - MDBX_page *omp; - rc = mdbx_page_get(mc, node_largedata_pgno(node), &omp, NULL); - if (unlikely(rc)) - goto done; - mdbx_cassert(mc, IS_OVERFLOW(omp)); - rc = mdbx_page_retire(mc, omp); - if (unlikely(rc)) - goto done; - if (!mc->mc_db->md_overflow_pages && !subs) - break; - } else if (subs && (node_flags(node) & F_SUBDATA)) { - rc = mdbx_xcursor_init1(mc, node); - if (unlikely(rc != MDBX_SUCCESS)) - goto done; - rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0); - if (unlikely(rc)) - goto done; - } - } - if (!subs && !mc->mc_db->md_overflow_pages) - goto pop; - } else { - for (i = 0; i < n; i++) { - /* free it */ - rc = mdbx_retire_pgno(mc, node_pgno(page_node(mp, i))); - if (unlikely(rc)) - goto done; - } - } - if (!mc->mc_top) - break; - mdbx_cassert(mc, i <= UINT16_MAX); - mc->mc_ki[mc->mc_top] = (indx_t)i; - rc = mdbx_cursor_sibling(mc, 1); - if (rc) { - if (unlikely(rc != MDBX_NOTFOUND)) - goto done; - /* no more siblings, go back to beginning - * of previous level. */ - pop: - mdbx_cursor_pop(mc); - mc->mc_ki[0] = 0; - for (i = 1; i < mc->mc_snum; i++) { - mc->mc_ki[i] = 0; - mc->mc_pg[i] = mx.mc_pg[i]; - } - } - } - /* free it */ - rc = mdbx_retire_pgno(mc, mc->mc_db->md_root); - done: - if (unlikely(rc)) - txn->mt_flags |= MDBX_TXN_ERROR; - } else if (rc == MDBX_NOTFOUND) { - rc = MDBX_SUCCESS; - } - mc->mc_flags &= ~C_INITIALIZED; - return rc; -} - -int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del) { - int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(1 < (unsigned)del)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(TXN_DBI_CHANGED(txn, dbi))) - return MDBX_BAD_DBI; - - MDBX_cursor *mc; - rc = mdbx_cursor_open(txn, dbi, &mc); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) { - rc = MDBX_EINVAL; - goto bailout; - } - - if (unlikely(TXN_DBI_CHANGED(txn, dbi))) { - rc = MDBX_BAD_DBI; - goto bailout; - } - - rc = mdbx_drop0(mc, mc->mc_db->md_flags & MDBX_DUPSORT); - /* Invalidate the dropped DB's cursors */ - for (MDBX_cursor *m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) - m2->mc_flags &= ~(C_INITIALIZED | C_EOF); - if (unlikely(rc)) - goto bailout; - - /* Can't delete the main DB */ - if (del && dbi >= CORE_DBS) { - rc = mdbx_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA); - if (likely(rc == MDBX_SUCCESS)) { - txn->mt_dbflags[dbi] = DB_STALE; - MDBX_env *env = txn->mt_env; - rc = mdbx_fastmutex_acquire(&env->me_dbi_lock); - if (unlikely(rc != MDBX_SUCCESS)) { - txn->mt_flags |= MDBX_TXN_ERROR; - goto bailout; - } - mdbx_dbi_close_locked(env, dbi); - mdbx_ensure(env, - mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); - } else { - txn->mt_flags |= MDBX_TXN_ERROR; - } - } else { - /* reset the DB record, mark it dirty */ - txn->mt_dbflags[dbi] |= DB_DIRTY; - txn->mt_dbs[dbi].md_depth = 0; - txn->mt_dbs[dbi].md_branch_pages = 0; - txn->mt_dbs[dbi].md_leaf_pages = 0; - txn->mt_dbs[dbi].md_overflow_pages = 0; - txn->mt_dbs[dbi].md_entries = 0; - txn->mt_dbs[dbi].md_root = P_INVALID; - txn->mt_dbs[dbi].md_seq = 0; - txn->mt_flags |= MDBX_TXN_DIRTY; - } - -bailout: - mdbx_cursor_close(mc); - return rc; -} - -int mdbx_set_compare(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - txn->mt_dbxs[dbi].md_cmp = cmp; - return MDBX_SUCCESS; -} - -int mdbx_set_dupsort(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - txn->mt_dbxs[dbi].md_dcmp = cmp; - return MDBX_SUCCESS; -} - -int __cold mdbx_reader_list(MDBX_env *env, MDBX_reader_list_func *func, - void *ctx) { - if (unlikely(!env || !func)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = MDBX_RESULT_TRUE; - int serial = 0; - if (likely(env->me_lck)) { - const unsigned snap_nreaders = env->me_lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; i++) { - const MDBX_reader *r = env->me_lck->mti_readers + i; - retry_reader:; - const uint32_t pid = r->mr_pid; - if (!pid) - continue; - txnid_t txnid = safe64_read(&r->mr_txnid); - const size_t tid = r->mr_tid; - const pgno_t pages_used = r->mr_snapshot_pages_used; - const uint64_t reader_pages_retired = r->mr_snapshot_pages_retired; - mdbx_compiler_barrier(); - if (unlikely(tid != r->mr_tid || - pages_used != r->mr_snapshot_pages_used || - reader_pages_retired != r->mr_snapshot_pages_retired || - txnid != safe64_read(&r->mr_txnid) || pid != r->mr_pid)) - goto retry_reader; - - mdbx_assert(env, txnid > 0); - if (txnid >= SAFE64_INVALID_THRESHOLD) - txnid = 0; - - size_t bytes_used = 0; - size_t bytes_retained = 0; - uint64_t lag = 0; - if (txnid) { - retry_header:; - const MDBX_meta *const recent_meta = mdbx_meta_head(env); - const uint64_t head_pages_retired = recent_meta->mm_pages_retired; - const txnid_t head_txnid = mdbx_meta_txnid_fluid(env, recent_meta); - mdbx_compiler_barrier(); - if (unlikely(recent_meta != mdbx_meta_head(env) || - head_pages_retired != recent_meta->mm_pages_retired) || - head_txnid != mdbx_meta_txnid_fluid(env, recent_meta)) - goto retry_header; - - lag = (head_txnid - txnid) / MDBX_TXNID_STEP; - bytes_used = pgno2bytes(env, pages_used); - bytes_retained = (head_pages_retired > reader_pages_retired) - ? pgno2bytes(env, (pgno_t)(head_pages_retired - - reader_pages_retired)) - : 0; - } - rc = func(ctx, ++serial, i, pid, (mdbx_tid_t)tid, txnid, lag, bytes_used, - bytes_retained); - if (unlikely(rc != MDBX_SUCCESS)) - break; - } - } - - return rc; -} - -/* Insert pid into list if not already present. - * return -1 if already present. */ -static int __cold mdbx_pid_insert(uint32_t *ids, uint32_t pid) { - /* binary search of pid in list */ - unsigned base = 0; - unsigned cursor = 1; - int val = 0; - unsigned n = ids[0]; - - while (n > 0) { - unsigned pivot = n >> 1; - cursor = base + pivot + 1; - val = pid - ids[cursor]; - - if (val < 0) { - n = pivot; - } else if (val > 0) { - base = cursor; - n -= pivot + 1; - } else { - /* found, so it's a duplicate */ - return -1; - } - } - - if (val > 0) - ++cursor; - - ids[0]++; - for (n = ids[0]; n > cursor; n--) - ids[n] = ids[n - 1]; - ids[n] = pid; - return 0; -} - -int __cold mdbx_reader_check(MDBX_env *env, int *dead) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (dead) - *dead = 0; - return mdbx_reader_check0(env, false, dead); -} - -/* Return: - * MDBX_RESULT_TRUE - done and mutex recovered - * MDBX_SUCCESS - done - * Otherwise errcode. */ -int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) { - mdbx_assert(env, rdt_locked >= 0); - -#if MDBX_TXN_CHECKPID - if (unlikely(env->me_pid != mdbx_getpid())) { - env->me_flags |= MDBX_FATAL_ERROR; - return MDBX_PANIC; - } -#endif /* MDBX_TXN_CHECKPID */ - - MDBX_lockinfo *const lck = env->me_lck; - if (unlikely(lck == NULL)) { - /* exclusive mode */ - if (dead) - *dead = 0; - return MDBX_SUCCESS; - } - - lck->mti_reader_check_timestamp = mdbx_osal_monotime(); - const unsigned snap_nreaders = lck->mti_numreaders; - uint32_t pidsbuf_onstask[142]; - uint32_t *const pids = - (snap_nreaders < ARRAY_LENGTH(pidsbuf_onstask)) - ? pidsbuf_onstask - : mdbx_malloc((snap_nreaders + 1) * sizeof(uint32_t)); - if (unlikely(!pids)) - return MDBX_ENOMEM; - - pids[0] = 0; - - int rc = MDBX_SUCCESS, count = 0; - for (unsigned i = 0; i < snap_nreaders; i++) { - const uint32_t pid = lck->mti_readers[i].mr_pid; - if (pid == 0) - continue /* skip empty */; - if (pid == env->me_pid) - continue /* skip self */; - if (mdbx_pid_insert(pids, pid) != 0) - continue /* such pid already processed */; - - int err = mdbx_rpid_check(env, pid); - if (err == MDBX_RESULT_TRUE) - continue /* reader is live */; - - if (err != MDBX_SUCCESS) { - rc = err; - break /* mdbx_rpid_check() failed */; - } - - /* stale reader found */ - if (!rdt_locked) { - err = mdbx_rdt_lock(env); - if (MDBX_IS_ERROR(err)) { - rc = err; - break; - } - - rdt_locked = -1; - if (err == MDBX_RESULT_TRUE) { - /* mutex recovered, the mdbx_mutex_failed() checked all readers */ - rc = MDBX_RESULT_TRUE; - break; - } - - /* a other process may have clean and reused slot, recheck */ - if (lck->mti_readers[i].mr_pid != pid) - continue; - - err = mdbx_rpid_check(env, pid); - if (MDBX_IS_ERROR(err)) { - rc = err; - break; - } - - if (err != MDBX_SUCCESS) - continue /* the race with other process, slot reused */; - } - - /* clean it */ - for (unsigned j = i; j < snap_nreaders; j++) { - if (lck->mti_readers[j].mr_pid == pid) { - mdbx_debug("clear stale reader pid %" PRIuPTR " txn %" PRIaTXN, - (size_t)pid, lck->mti_readers[j].mr_txnid.inconsistent); - lck->mti_readers[j].mr_pid = 0; - lck->mti_readers_refresh_flag = true; - count++; - } - } - } - - if (rdt_locked < 0) - mdbx_rdt_unlock(env); - - if (pids != pidsbuf_onstask) - mdbx_free(pids); - - if (dead) - *dead = count; - return rc; -} - -int __cold mdbx_setup_debug(int loglevel, int flags, MDBX_debug_func *logger) { - const int rc = mdbx_runtime_flags | (mdbx_loglevel << 16); - -#if !MDBX_DEBUG - (void)loglevel; -#else - if (loglevel != -1) - mdbx_loglevel = (uint8_t)loglevel; -#endif - - if (flags != -1) { -#if !MDBX_DEBUG - flags &= MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN; -#else - flags &= MDBX_DBG_ASSERT | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | - MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN; -#endif -#if defined(__linux__) || defined(__gnu_linux__) - if ((mdbx_runtime_flags ^ flags) & MDBX_DBG_DUMP) { - /* http://man7.org/linux/man-pages/man5/core.5.html */ - const unsigned long dump_bits = - 1 << 3 /* Dump file-backed shared mappings */ - | 1 << 6 /* Dump shared huge pages */ - | 1 << 8 /* Dump shared DAX pages */; - const int core_filter_fd = - open("/proc/self/coredump_filter", O_TRUNC | O_RDWR); - if (core_filter_fd != -1) { - char buf[32]; - intptr_t bytes = pread(core_filter_fd, buf, sizeof(buf), 0); - if (bytes > 0 && (size_t)bytes < sizeof(buf)) { - buf[bytes] = 0; - const unsigned long present_mask = strtoul(buf, NULL, 16); - const unsigned long wanna_mask = (flags & MDBX_DBG_DUMP) - ? present_mask | dump_bits - : present_mask & ~dump_bits; - if (wanna_mask != present_mask) { - bytes = snprintf(buf, sizeof(buf), "0x%lx\n", wanna_mask); - if (bytes > 0 && (size_t)bytes < sizeof(buf)) { - bytes = pwrite(core_filter_fd, buf, bytes, 0); - (void)bytes; - } - } - } - close(core_filter_fd); - } - } -#endif /* Linux */ - mdbx_runtime_flags = (uint8_t)flags; - } - - if (-1 != (intptr_t)logger) - mdbx_debug_logger = logger; - return rc; -} - -static txnid_t __cold mdbx_oomkick(MDBX_env *env, const txnid_t laggard) { - mdbx_debug("%s", "DB size maxed out"); - - int retry; - for (retry = 0; retry < INT_MAX; ++retry) { - txnid_t oldest = mdbx_reclaiming_detent(env); - mdbx_assert(env, oldest < env->me_txn0->mt_txnid); - mdbx_assert(env, oldest >= laggard); - mdbx_assert(env, oldest >= *env->me_oldest); - if (oldest == laggard || unlikely(env->me_lck == NULL /* exclusive mode */)) - return oldest; - - if (MDBX_IS_ERROR(mdbx_reader_check0(env, false, NULL))) - break; - - MDBX_reader *asleep = nullptr; - MDBX_lockinfo *const lck = env->me_lck; - uint64_t oldest_retired = UINT64_MAX; - const unsigned snap_nreaders = lck->mti_numreaders; - for (unsigned i = 0; i < snap_nreaders; ++i) { - retry: - if (lck->mti_readers[i].mr_pid) { - /* mdbx_jitter4testing(true); */ - const uint64_t snap_retired = - lck->mti_readers[i].mr_snapshot_pages_retired; - const txnid_t snap_txnid = safe64_read(&lck->mti_readers[i].mr_txnid); - mdbx_memory_barrier(); - if (unlikely(snap_retired != - lck->mti_readers[i].mr_snapshot_pages_retired || - snap_txnid != safe64_read(&lck->mti_readers[i].mr_txnid))) - goto retry; - if (oldest > snap_txnid && - laggard <= /* ignore pending updates */ snap_txnid) { - oldest = snap_txnid; - oldest_retired = snap_retired; - asleep = &lck->mti_readers[i]; - } - } - } - - if (laggard < oldest || !asleep) { - if (retry && env->me_oom_func) { - /* LY: notify end of oom-loop */ - const txnid_t gap = oldest - laggard; - env->me_oom_func(env, 0, 0, laggard, - (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, 0, - -retry); - } - mdbx_notice("oom-kick: update oldest %" PRIaTXN " -> %" PRIaTXN, - *env->me_oldest, oldest); - mdbx_assert(env, *env->me_oldest <= oldest); - return *env->me_oldest = oldest; - } - - if (!env->me_oom_func) - break; - - uint32_t pid = asleep->mr_pid; - size_t tid = asleep->mr_tid; - if (safe64_read(&asleep->mr_txnid) != laggard || pid <= 0) - continue; - - const MDBX_meta *head_meta = mdbx_meta_head(env); - const txnid_t gap = - (mdbx_meta_txnid_stable(env, head_meta) - laggard) / MDBX_TXNID_STEP; - const uint64_t head_retired = head_meta->mm_pages_retired; - const size_t space = - (oldest_retired > head_retired) - ? pgno2bytes(env, (pgno_t)(oldest_retired - head_retired)) - : 0; - int rc = env->me_oom_func(env, pid, (mdbx_tid_t)tid, laggard, - (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, - space, retry); - if (rc < 0) - break; - - if (rc > 0) { - if (rc == 1) { - safe64_reset_compare(&asleep->mr_txnid, laggard); - } else { - safe64_reset(&asleep->mr_txnid, true); - asleep->mr_tid = 0; - asleep->mr_pid = 0; - } - lck->mti_readers_refresh_flag = true; - mdbx_flush_noncoherent_cpu_writeback(); - } - } - - if (retry && env->me_oom_func) { - /* LY: notify end of oom-loop */ - env->me_oom_func(env, 0, 0, laggard, 0, 0, -retry); - } - return mdbx_find_oldest(env->me_txn); -} - -int __cold mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) - return MDBX_EACCESS; - - if (unlikely(!env->me_map)) - return MDBX_EPERM; - - *env->me_autosync_threshold = bytes2pgno(env, threshold + env->me_psize - 1); - if (threshold) { - int err = mdbx_env_sync_poll(env); - if (unlikely(MDBX_IS_ERROR(err))) - return err; - } - return MDBX_SUCCESS; -} - -int __cold mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - if (unlikely(env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) - return MDBX_EACCESS; - - if (unlikely(!env->me_map)) - return MDBX_EPERM; - - *env->me_autosync_period = mdbx_osal_16dot16_to_monotime(seconds_16dot16); - if (seconds_16dot16) { - int err = mdbx_env_sync_poll(env); - if (unlikely(MDBX_IS_ERROR(err))) - return err; - } - return MDBX_SUCCESS; -} - -int __cold mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oomfunc) { - if (unlikely(!env)) - return MDBX_EINVAL; - - if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) - return MDBX_EBADSIGN; - - env->me_oom_func = oomfunc; - return MDBX_SUCCESS; -} - -MDBX_oom_func *__cold mdbx_env_get_oomfunc(MDBX_env *env) { - return likely(env && env->me_signature == MDBX_ME_SIGNATURE) - ? env->me_oom_func - : NULL; -} - -#ifdef __SANITIZE_THREAD__ -/* LY: avoid tsan-trap by me_txn, mm_last_pg and mt_next_pgno */ -__attribute__((__no_sanitize_thread__, __noinline__)) -#endif -int mdbx_txn_straggler(MDBX_txn *txn, int *percent) -{ - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return (rc > 0) ? -rc : rc; - - MDBX_env *env = txn->mt_env; - if (unlikely((txn->mt_flags & MDBX_RDONLY) == 0)) { - if (percent) - *percent = - (int)((txn->mt_next_pgno * UINT64_C(100) + txn->mt_end_pgno / 2) / - txn->mt_end_pgno); - return 0; - } - - txnid_t recent; - MDBX_meta *meta; - do { - meta = mdbx_meta_head(env); - recent = mdbx_meta_txnid_fluid(env, meta); - if (percent) { - const pgno_t maxpg = meta->mm_geo.now; - *percent = (int)((meta->mm_geo.next * UINT64_C(100) + maxpg / 2) / maxpg); - } - } while (unlikely(recent != mdbx_meta_txnid_fluid(env, meta))); - - txnid_t lag = (recent - txn->mt_txnid) / MDBX_TXNID_STEP; - return (lag > INT_MAX) ? INT_MAX : (int)lag; -} - -typedef struct mdbx_walk_ctx { - void *mw_user; - MDBX_pgvisitor_func *mw_visitor; - MDBX_cursor mw_cursor; -} mdbx_walk_ctx_t; - -/* Depth-first tree traversal. */ -static int __cold mdbx_env_walk(mdbx_walk_ctx_t *ctx, const char *dbi, - pgno_t pgno, int deep) { - if (unlikely(pgno == P_INVALID)) - return MDBX_SUCCESS; /* empty db */ - - MDBX_page *mp; - int rc = mdbx_page_get(&ctx->mw_cursor, pgno, &mp, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - rc = mdbx_page_check(ctx->mw_cursor.mc_txn->mt_env, mp, false); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - const int nkeys = page_numkeys(mp); - size_t header_size = IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower; - size_t unused_size = page_room(mp); - size_t payload_size = 0; - size_t align_bytes = 0; - MDBX_page_type_t type; - - /* LY: Don't use mask here, e.g bitwise - * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP). - * Pages should not me marked dirty/loose or otherwise. */ - switch (mp->mp_flags) { - case P_BRANCH: - type = MDBX_page_branch; - if (unlikely(nkeys < 2)) - return MDBX_CORRUPTED; - break; - case P_LEAF: - type = MDBX_page_leaf; - break; - case P_LEAF | P_LEAF2: - type = MDBX_page_dupfixed_leaf; - break; - default: - return MDBX_CORRUPTED; - } - - for (int i = 0; i < nkeys; - align_bytes += ((payload_size + align_bytes) & 1), i++) { - if (type == MDBX_page_dupfixed_leaf) { - /* LEAF2 pages have no mp_ptrs[] or node headers */ - payload_size += mp->mp_leaf2_ksize; - continue; - } - - MDBX_node *node = page_node(mp, i); - payload_size += NODESIZE + node_ks(node); - - if (type == MDBX_page_branch) { - assert(i > 0 || node_ks(node) == 0); - continue; - } - - assert(type == MDBX_page_leaf); - switch (node_flags(node)) { - case 0 /* usual node */: { - payload_size += node_ds(node); - } break; - - case F_BIGDATA /* long data on the large/overflow page */: { - payload_size += sizeof(pgno_t); - - const pgno_t large_pgno = node_largedata_pgno(node); - MDBX_page *op; - rc = mdbx_page_get(&ctx->mw_cursor, large_pgno, &op, NULL); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_page_check(ctx->mw_cursor.mc_txn->mt_env, op, false); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - /* LY: Don't use mask here, e.g bitwise - * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP). - * Pages should not me marked dirty/loose or otherwise. */ - if (unlikely(P_OVERFLOW != op->mp_flags)) - return MDBX_CORRUPTED; - - const size_t over_header = PAGEHDRSZ; - const size_t over_payload = node_ds(node); - const size_t over_unused = - pgno2bytes(ctx->mw_cursor.mc_txn->mt_env, op->mp_pages) - - over_payload - over_header; - - rc = ctx->mw_visitor( - large_pgno, op->mp_pages, ctx->mw_user, deep, dbi, - pgno2bytes(ctx->mw_cursor.mc_txn->mt_env, op->mp_pages), - MDBX_page_large, 1, over_payload, over_header, over_unused); - } break; - - case F_SUBDATA /* sub-db */: { - const size_t namelen = node_ks(node); - if (unlikely(namelen == 0 || node_ds(node) < sizeof(MDBX_db))) - return MDBX_CORRUPTED; - payload_size += node_ds(node); - } break; - - case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: { - if (unlikely(node_ds(node) != sizeof(MDBX_db))) - return MDBX_CORRUPTED; - payload_size += sizeof(MDBX_db); - } break; - - case F_DUPDATA /* short sub-page */: { - if (unlikely(node_ds(node) <= PAGEHDRSZ)) - return MDBX_CORRUPTED; - - MDBX_page *sp = node_data(node); - const int nsubkeys = page_numkeys(sp); - size_t subheader_size = - IS_LEAF2(sp) ? PAGEHDRSZ : PAGEHDRSZ + sp->mp_lower; - size_t subunused_size = page_room(sp); - size_t subpayload_size = 0; - size_t subalign_bytes = 0; - MDBX_page_type_t subtype; - - switch (sp->mp_flags & ~P_DIRTY /* ignore for sub-pages */) { - case P_LEAF | P_SUBP: - subtype = MDBX_subpage_leaf; - break; - case P_LEAF | P_LEAF2 | P_SUBP: - subtype = MDBX_subpage_dupfixed_leaf; - break; - default: - return MDBX_CORRUPTED; - } - - for (int j = 0; j < nsubkeys; - subalign_bytes += ((subpayload_size + subalign_bytes) & 1), j++) { - - if (subtype == MDBX_subpage_dupfixed_leaf) { - /* LEAF2 pages have no mp_ptrs[] or node headers */ - subpayload_size += sp->mp_leaf2_ksize; - } else { - assert(subtype == MDBX_subpage_leaf); - MDBX_node *subnode = page_node(sp, j); - subpayload_size += NODESIZE + node_ks(subnode) + node_ds(subnode); - if (unlikely(node_flags(subnode) != 0)) - return MDBX_CORRUPTED; - } - } - - rc = ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, dbi, node_ds(node), - subtype, nsubkeys, subpayload_size, subheader_size, - subunused_size + subalign_bytes); - header_size += subheader_size; - unused_size += subunused_size; - payload_size += subpayload_size; - align_bytes += subalign_bytes; - } break; - - default: - return MDBX_CORRUPTED; - } - - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - rc = ctx->mw_visitor(mp->mp_pgno, 1, ctx->mw_user, deep, dbi, - ctx->mw_cursor.mc_txn->mt_env->me_psize, type, nkeys, - payload_size, header_size, unused_size + align_bytes); - - if (unlikely(rc != MDBX_SUCCESS)) - return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc; - - for (int i = 0; i < nkeys; i++) { - if (type == MDBX_page_dupfixed_leaf) - continue; - - MDBX_node *node = page_node(mp, i); - if (type == MDBX_page_branch) { - rc = mdbx_env_walk(ctx, dbi, node_pgno(node), deep + 1); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc != MDBX_RESULT_TRUE) - return rc; - break; - } - continue; - } - - assert(type == MDBX_page_leaf); - MDBX_db db; - switch (node_flags(node)) { - default: - continue; - - case F_SUBDATA /* sub-db */: { - const size_t namelen = node_ks(node); - if (unlikely(namelen == 0 || node_ds(node) != sizeof(MDBX_db))) - return MDBX_CORRUPTED; - - char namebuf_onstask[142]; - char *const name = (namelen < sizeof(namebuf_onstask)) - ? namebuf_onstask - : mdbx_malloc(namelen + 1); - if (name) { - memcpy(name, node_key(node), namelen); - name[namelen] = 0; - memcpy(&db, node_data(node), sizeof(db)); - rc = mdbx_env_walk(ctx, name, db.md_root, deep + 1); - if (name != namebuf_onstask) - mdbx_free(name); - } else { - rc = MDBX_ENOMEM; - } - } break; - - case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: - if (unlikely(node_ds(node) != sizeof(MDBX_db))) - return MDBX_CORRUPTED; - - memcpy(&db, node_data(node), sizeof(db)); - rc = mdbx_env_walk(ctx, dbi, db.md_root, deep + 1); - break; - } - - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - return MDBX_SUCCESS; -} - -int __cold mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor, - void *user) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - mdbx_walk_ctx_t ctx; - memset(&ctx, 0, sizeof(ctx)); - ctx.mw_cursor.mc_snum = 1; - ctx.mw_cursor.mc_txn = txn; - ctx.mw_user = user; - ctx.mw_visitor = visitor; - - rc = visitor(0, NUM_METAS, user, 0, MDBX_PGWALK_META, - pgno2bytes(txn->mt_env, NUM_METAS), MDBX_page_meta, NUM_METAS, - sizeof(MDBX_meta) * NUM_METAS, PAGEHDRSZ * NUM_METAS, - (txn->mt_env->me_psize - sizeof(MDBX_meta) - PAGEHDRSZ) * - NUM_METAS); - if (!MDBX_IS_ERROR(rc)) - rc = mdbx_env_walk(&ctx, MDBX_PGWALK_GC, txn->mt_dbs[FREE_DBI].md_root, 0); - if (!MDBX_IS_ERROR(rc)) - rc = - mdbx_env_walk(&ctx, MDBX_PGWALK_MAIN, txn->mt_dbs[MAIN_DBI].md_root, 0); - if (!MDBX_IS_ERROR(rc)) - rc = visitor(P_INVALID, 0, user, INT_MIN, NULL, 0, MDBX_page_void, 0, 0, 0, - 0); - return rc; -} - -int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary) { - int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (likely(canary)) { - if (txn->mt_canary.x == canary->x && txn->mt_canary.y == canary->y && - txn->mt_canary.z == canary->z) - return MDBX_SUCCESS; - txn->mt_canary.x = canary->x; - txn->mt_canary.y = canary->y; - txn->mt_canary.z = canary->z; - } - txn->mt_canary.v = txn->mt_txnid; - - if ((txn->mt_flags & MDBX_TXN_DIRTY) == 0) { - txn->mt_flags |= MDBX_TXN_DIRTY; - *txn->mt_env->me_unsynced_pages += 1; - } - return MDBX_SUCCESS; -} - -int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(canary == NULL)) - return MDBX_EINVAL; - - *canary = txn->mt_canary; - return MDBX_SUCCESS; -} - -int mdbx_cursor_on_first(MDBX_cursor *mc) { - if (unlikely(mc == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - if (!(mc->mc_flags & C_INITIALIZED)) - return MDBX_RESULT_FALSE; - - for (unsigned i = 0; i < mc->mc_snum; ++i) { - if (mc->mc_ki[i]) - return MDBX_RESULT_FALSE; - } - - return MDBX_RESULT_TRUE; -} - -int mdbx_cursor_on_last(MDBX_cursor *mc) { - if (unlikely(mc == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - if (!(mc->mc_flags & C_INITIALIZED)) - return MDBX_RESULT_FALSE; - - for (unsigned i = 0; i < mc->mc_snum; ++i) { - unsigned nkeys = page_numkeys(mc->mc_pg[i]); - if (mc->mc_ki[i] < nkeys - 1) - return MDBX_RESULT_FALSE; - } - - return MDBX_RESULT_TRUE; -} - -int mdbx_cursor_eof(MDBX_cursor *mc) { - if (unlikely(mc == NULL)) - return MDBX_EINVAL; - - if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - if ((mc->mc_flags & C_INITIALIZED) == 0) - return MDBX_RESULT_TRUE; - - if (mc->mc_snum == 0) - return MDBX_RESULT_TRUE; - - if ((mc->mc_flags & C_EOF) && - mc->mc_ki[mc->mc_top] >= page_numkeys(mc->mc_pg[mc->mc_top])) - return MDBX_RESULT_TRUE; - - return MDBX_RESULT_FALSE; -} - -//------------------------------------------------------------------------------ - -struct diff_result { - ptrdiff_t diff; - int level; - int root_nkeys; -}; - -/* calculates: r = x - y */ -__hot static int cursor_diff(const MDBX_cursor *const __restrict x, - const MDBX_cursor *const __restrict y, - struct diff_result *const __restrict r) { - r->diff = 0; - r->level = 0; - r->root_nkeys = 0; - - if (unlikely(y->mc_signature != MDBX_MC_SIGNATURE || - x->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn(x->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(x->mc_txn != y->mc_txn)) - return MDBX_BAD_TXN; - - if (unlikely(y->mc_dbi != x->mc_dbi)) - return MDBX_EINVAL; - - if (unlikely(!(y->mc_flags & x->mc_flags & C_INITIALIZED))) - return MDBX_ENODATA; - - while (likely(r->level < y->mc_snum && r->level < x->mc_snum)) { - if (unlikely(y->mc_pg[r->level] != x->mc_pg[r->level])) - return MDBX_PROBLEM; - - int nkeys = page_numkeys(y->mc_pg[r->level]); - assert(nkeys > 0); - if (r->level == 0) - r->root_nkeys = nkeys; - - const int limit_ki = nkeys - 1; - const int x_ki = x->mc_ki[r->level]; - const int y_ki = y->mc_ki[r->level]; - r->diff = ((x_ki < limit_ki) ? x_ki : limit_ki) - - ((y_ki < limit_ki) ? y_ki : limit_ki); - if (r->diff == 0) { - r->level += 1; - continue; - } - - while (unlikely(r->diff == 1) && - likely(r->level + 1 < y->mc_snum && r->level + 1 < x->mc_snum)) { - r->level += 1; - /* DB'PAGEs: 0------------------>MAX - * - * CURSORs: y < x - * STACK[i ]: | - * STACK[+1]: ...y++N|0++x... - */ - nkeys = page_numkeys(y->mc_pg[r->level]); - r->diff = (nkeys - y->mc_ki[r->level]) + x->mc_ki[r->level]; - assert(r->diff > 0); - } - - while (unlikely(r->diff == -1) && - likely(r->level + 1 < y->mc_snum && r->level + 1 < x->mc_snum)) { - r->level += 1; - /* DB'PAGEs: 0------------------>MAX - * - * CURSORs: x < y - * STACK[i ]: | - * STACK[+1]: ...x--N|0--y... - */ - nkeys = page_numkeys(x->mc_pg[r->level]); - r->diff = -(nkeys - x->mc_ki[r->level]) - y->mc_ki[r->level]; - assert(r->diff < 0); - } - - return MDBX_SUCCESS; - } - - r->diff = CMP2INT(x->mc_flags & C_EOF, y->mc_flags & C_EOF); - return MDBX_SUCCESS; -} - -__hot static ptrdiff_t estimate(const MDBX_db *db, - struct diff_result *const __restrict dr) { - /* root: branch-page => scale = leaf-factor * branch-factor^(N-1) - * level-1: branch-page(s) => scale = leaf-factor * branch-factor^2 - * level-2: branch-page(s) => scale = leaf-factor * branch-factor - * level-N: branch-page(s) => scale = leaf-factor - * leaf-level: leaf-page(s) => scale = 1 - */ - ptrdiff_t btree_power = db->md_depth - 2 - dr->level; - if (btree_power < 0) - return dr->diff; - - ptrdiff_t estimated = - (ptrdiff_t)db->md_entries * dr->diff / (ptrdiff_t)db->md_leaf_pages; - if (btree_power == 0) - return estimated; - - if (db->md_depth < 4) { - assert(dr->level == 0 && btree_power == 1); - return (ptrdiff_t)db->md_entries * dr->diff / (ptrdiff_t)dr->root_nkeys; - } - - /* average_branchpage_fillfactor = total(branch_entries) / branch_pages - total(branch_entries) = leaf_pages + branch_pages - 1 (root page) */ - const size_t log2_fixedpoint = sizeof(size_t) - 1; - const size_t half = UINT64_C(1) << (log2_fixedpoint - 1); - const size_t factor = - ((db->md_leaf_pages + db->md_branch_pages - 1) << log2_fixedpoint) / - db->md_branch_pages; - while (1) { - switch ((size_t)btree_power) { - default: { - const size_t square = (factor * factor + half) >> log2_fixedpoint; - const size_t quad = (square * square + half) >> log2_fixedpoint; - do { - estimated = estimated * quad + half; - estimated >>= log2_fixedpoint; - btree_power -= 4; - } while (btree_power >= 4); - continue; - } - case 3: - estimated = estimated * factor + half; - estimated >>= log2_fixedpoint; - __fallthrough /* fall through */; - case 2: - estimated = estimated * factor + half; - estimated >>= log2_fixedpoint; - __fallthrough /* fall through */; - case 1: - estimated = estimated * factor + half; - estimated >>= log2_fixedpoint; - __fallthrough /* fall through */; - case 0: - if (unlikely(estimated > (ptrdiff_t)db->md_entries)) - return (ptrdiff_t)db->md_entries; - if (unlikely(estimated < -(ptrdiff_t)db->md_entries)) - return -(ptrdiff_t)db->md_entries; - return estimated; - } - } -} - -__hot int mdbx_estimate_distance(const MDBX_cursor *first, - const MDBX_cursor *last, - ptrdiff_t *distance_items) { - if (unlikely(first == NULL || last == NULL || distance_items == NULL)) - return MDBX_EINVAL; - - *distance_items = 0; - struct diff_result dr; - int rc = cursor_diff(last, first, &dr); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(dr.diff == 0) && - F_ISSET(first->mc_db->md_flags & first->mc_db->md_flags, - MDBX_DUPSORT | C_INITIALIZED)) { - first = &first->mc_xcursor->mx_cursor; - last = &last->mc_xcursor->mx_cursor; - rc = cursor_diff(first, last, &dr); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - if (likely(dr.diff != 0)) - *distance_items = estimate(first->mc_db, &dr); - - return MDBX_SUCCESS; -} - -int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, - MDBX_cursor_op move_op, ptrdiff_t *distance_items) { - if (unlikely(cursor == NULL || distance_items == NULL || - move_op == MDBX_GET_CURRENT || move_op == MDBX_GET_MULTIPLE)) - return MDBX_EINVAL; - - if (unlikely(cursor->mc_signature != MDBX_MC_SIGNATURE)) - return MDBX_EBADSIGN; - - int rc = check_txn(cursor->mc_txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (!(cursor->mc_flags & C_INITIALIZED)) - return MDBX_ENODATA; - - MDBX_cursor_couple next; - mdbx_cursor_copy(cursor, &next.outer); - next.outer.mc_xcursor = NULL; - if (cursor->mc_db->md_flags & MDBX_DUPSORT) { - next.outer.mc_xcursor = &next.inner; - rc = mdbx_xcursor_init0(&next.outer); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - MDBX_xcursor *mx = &container_of(cursor, MDBX_cursor_couple, outer)->inner; - mdbx_cursor_copy(&mx->mx_cursor, &next.inner.mx_cursor); - } - - MDBX_val stub = {0, 0}; - if (data == NULL) { - const unsigned mask = - 1 << MDBX_GET_BOTH | 1 << MDBX_GET_BOTH_RANGE | 1 << MDBX_SET_KEY; - if (unlikely(mask & (1 << move_op))) - return MDBX_EINVAL; - data = &stub; - } - - if (key == NULL) { - const unsigned mask = 1 << MDBX_GET_BOTH | 1 << MDBX_GET_BOTH_RANGE | - 1 << MDBX_SET_KEY | 1 << MDBX_SET | - 1 << MDBX_SET_RANGE; - if (unlikely(mask & (1 << move_op))) - return MDBX_EINVAL; - key = &stub; - } - - rc = mdbx_cursor_get(&next.outer, key, data, move_op); - if (unlikely(rc != MDBX_SUCCESS && - (rc != MDBX_NOTFOUND || !(next.outer.mc_flags & C_INITIALIZED)))) - return rc; - - return mdbx_estimate_distance(cursor, &next.outer, distance_items); -} - -static int mdbx_is_samedata(const MDBX_val *a, const MDBX_val *b) { - return a->iov_len == b->iov_len && - memcmp(a->iov_base, b->iov_base, a->iov_len) == 0; -} - -int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key, - MDBX_val *begin_data, MDBX_val *end_key, - MDBX_val *end_data, ptrdiff_t *size_items) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!size_items)) - return MDBX_EINVAL; - - if (unlikely(begin_data && (begin_key == NULL || begin_key == MDBX_EPSILON))) - return MDBX_EINVAL; - - if (unlikely(end_data && (end_key == NULL || end_key == MDBX_EPSILON))) - return MDBX_EINVAL; - - if (unlikely(begin_key == MDBX_EPSILON && end_key == MDBX_EPSILON)) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - MDBX_cursor_couple begin; - /* LY: first, initialize cursor to refresh a DB in case it have DB_STALE */ - rc = mdbx_cursor_init(&begin.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(begin.outer.mc_db->md_entries == 0)) { - *size_items = 0; - return MDBX_SUCCESS; - } - - if (!begin_key) { - if (unlikely(!end_key)) { - /* LY: FIRST..LAST case */ - *size_items = (ptrdiff_t)begin.outer.mc_db->md_entries; - return MDBX_SUCCESS; - } - MDBX_val stub = {0, 0}; - rc = mdbx_cursor_first(&begin.outer, &stub, &stub); - if (unlikely(end_key == MDBX_EPSILON)) { - /* LY: FIRST..+epsilon case */ - return (rc == MDBX_SUCCESS) - ? mdbx_cursor_count(&begin.outer, (size_t *)size_items) - : rc; - } - } else { - if (unlikely(begin_key == MDBX_EPSILON)) { - if (end_key == NULL) { - /* LY: -epsilon..LAST case */ - MDBX_val stub = {0, 0}; - rc = mdbx_cursor_last(&begin.outer, &stub, &stub); - return (rc == MDBX_SUCCESS) - ? mdbx_cursor_count(&begin.outer, (size_t *)size_items) - : rc; - } - /* LY: -epsilon..value case */ - assert(end_key != MDBX_EPSILON); - begin_key = end_key; - } else if (unlikely(end_key == MDBX_EPSILON)) { - /* LY: value..+epsilon case */ - assert(begin_key != MDBX_EPSILON); - end_key = begin_key; - } - if (end_key && !begin_data && !end_data && - (begin_key == end_key || mdbx_is_samedata(begin_key, end_key))) { - /* LY: single key case */ - int exact = 0; - rc = mdbx_cursor_set(&begin.outer, begin_key, NULL, MDBX_SET, &exact); - if (unlikely(rc != MDBX_SUCCESS)) { - *size_items = 0; - return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; - } - *size_items = 1; - if (begin.outer.mc_xcursor != NULL) { - MDBX_node *node = page_node(begin.outer.mc_pg[begin.outer.mc_top], - begin.outer.mc_ki[begin.outer.mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - /* LY: return the number of duplicates for given key */ - mdbx_tassert(txn, - begin.outer.mc_xcursor == &begin.inner && - (begin.inner.mx_cursor.mc_flags & C_INITIALIZED)); - *size_items = - (sizeof(*size_items) >= sizeof(begin.inner.mx_db.md_entries) || - begin.inner.mx_db.md_entries <= PTRDIFF_MAX) - ? (size_t)begin.inner.mx_db.md_entries - : PTRDIFF_MAX; - } - } - return MDBX_SUCCESS; - } else { - rc = mdbx_cursor_set(&begin.outer, begin_key, begin_data, - begin_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE, - NULL); - } - } - - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc != MDBX_NOTFOUND || !(begin.outer.mc_flags & C_INITIALIZED)) - return rc; - } - - MDBX_cursor_couple end; - rc = mdbx_cursor_init(&end.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - if (!end_key) { - MDBX_val stub = {0, 0}; - rc = mdbx_cursor_last(&end.outer, &stub, &stub); - } else { - rc = mdbx_cursor_set(&end.outer, end_key, end_data, - end_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE, NULL); - } - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc != MDBX_NOTFOUND || !(end.outer.mc_flags & C_INITIALIZED)) - return rc; - } - - rc = mdbx_estimate_distance(&begin.outer, &end.outer, size_items); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - assert(*size_items >= -(ptrdiff_t)begin.outer.mc_db->md_entries && - *size_items <= (ptrdiff_t)begin.outer.mc_db->md_entries); - -#if 0 /* LY: Was decided to returns as-is (i.e. negative) the estimation \ - * results for an inverted ranges. */ - - /* Commit 8ddfd1f34ad7cf7a3c4aa75d2e248ca7e639ed63 - Change-Id: If59eccf7311123ab6384c4b93f9b1fed5a0a10d1 */ - - if (*size_items < 0) { - /* LY: inverted range case */ - *size_items += (ptrdiff_t)begin.outer.mc_db->md_entries; - } else if (*size_items == 0 && begin_key && end_key) { - int cmp = begin.outer.mc_dbx->md_cmp(&origin_begin_key, &origin_end_key); - if (cmp == 0 && (begin.inner.mx_cursor.mc_flags & C_INITIALIZED) && - begin_data && end_data) - cmp = begin.outer.mc_dbx->md_dcmp(&origin_begin_data, &origin_end_data); - if (cmp > 0) { - /* LY: inverted range case with empty scope */ - *size_items = (ptrdiff_t)begin.outer.mc_db->md_entries; - } - } - assert(*size_items >= 0 && - *size_items <= (ptrdiff_t)begin.outer.mc_db->md_entries); -#endif - - return MDBX_SUCCESS; -} - -//------------------------------------------------------------------------------ - -/* ПозволÑет обновить или удалить ÑущеÑтвующую запиÑÑŒ Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸ÐµÐ¼ - * в old_data предыдущего Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…. При Ñтом еÑли new_data равен - * нулю, то выполнÑетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ, иначе обновление/вÑтавка. - * - * Текущее значение может находитьÑÑ Ð² уже измененной (грÑзной) Ñтранице. - * Ð’ Ñтом Ñлучае Ñтраница будет перезапиÑана при обновлении, а Ñамо Ñтарое - * значение утрачено. ПоÑтому иÑходно в old_data должен быть передан - * дополнительный буфер Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтарого значениÑ. - * ЕÑли переданный буфер Ñлишком мал, то Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐµÑ€Ð½ÐµÑ‚ -1, уÑтановив - * old_data->iov_len в ÑоответÑтвующее значение. - * - * Ð”Ð»Ñ Ð½Ðµ-уникальных ключей также возможен второй Ñценарий иÑпользованиÑ, - * когда поÑредÑтвом old_data из запиÑей Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼ ключом Ð´Ð»Ñ - * удалениÑ/Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ð¸Ñ€Ð°ÐµÑ‚ÑÑ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð°Ñ. Ð”Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° Ñтого ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ - * во flags Ñледует одновременно указать MDBX_CURRENT и MDBX_NOOVERWRITE. - * Именно Ñта ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð°, так как она лишена ÑмыÑла, и Ñтим позволÑет - * идентифицировать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ñ‚Ð°ÐºÐ¾Ð³Ð¾ ÑценариÑ. - * - * Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть замещена ÑоответÑтвующими операциÑми Ñ ÐºÑƒÑ€Ñорами - * поÑле двух доработок (TODO): - * - внешнÑÑ Ð°Ð»Ð»Ð¾ÐºÐ°Ñ†Ð¸Ñ ÐºÑƒÑ€Ñоров, в том чиÑле на Ñтеке (без malloc). - * - Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑтатуÑа Ñтраницы по адреÑу (знать о P_DIRTY). - */ -int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *new_data, - MDBX_val *old_data, unsigned flags) { - int rc = check_txn_rw(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!key || !old_data || old_data == new_data)) - return MDBX_EINVAL; - - if (unlikely(old_data->iov_base == NULL && old_data->iov_len)) - return MDBX_EINVAL; - - if (unlikely(new_data == NULL && !(flags & MDBX_CURRENT))) - return MDBX_EINVAL; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE | - MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT))) - return MDBX_EINVAL; - - MDBX_cursor_couple cx; - rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - cx.outer.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &cx.outer; - - MDBX_val present_key = *key; - if (F_ISSET(flags, MDBX_CURRENT | MDBX_NOOVERWRITE)) { - /* в old_data значение Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° конкретного дубликата */ - if (unlikely(!(txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT))) { - rc = MDBX_EINVAL; - goto bailout; - } - - /* убираем лишний бит, он был признаком запрошенного режима */ - flags -= MDBX_NOOVERWRITE; - - rc = mdbx_cursor_get(&cx.outer, &present_key, old_data, MDBX_GET_BOTH); - if (rc != MDBX_SUCCESS) - goto bailout; - - if (new_data) { - /* обновление конкретного дубликата */ - if (mdbx_is_samedata(old_data, new_data)) - /* еÑли данные Ñовпадают, то ничего делать не надо */ - goto bailout; - } - } else { - /* в old_data буфер Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰ÐµÐ³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ */ - if (unlikely(new_data && old_data->iov_base == new_data->iov_base)) - return MDBX_EINVAL; - MDBX_val present_data; - rc = mdbx_cursor_get(&cx.outer, &present_key, &present_data, MDBX_SET_KEY); - if (unlikely(rc != MDBX_SUCCESS)) { - old_data->iov_base = NULL; - old_data->iov_len = 0; - if (rc != MDBX_NOTFOUND || (flags & MDBX_CURRENT)) - goto bailout; - } else if (flags & MDBX_NOOVERWRITE) { - rc = MDBX_KEYEXIST; - *old_data = present_data; - goto bailout; - } else { - MDBX_page *page = cx.outer.mc_pg[cx.outer.mc_top]; - if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) { - if (flags & MDBX_CURRENT) { - /* Ð´Ð»Ñ Ð½Ðµ-уникальных ключей позволÑем update/delete только еÑли ключ - * один */ - MDBX_node *node = page_node(page, cx.outer.mc_ki[cx.outer.mc_top]); - if (F_ISSET(node_flags(node), F_DUPDATA)) { - mdbx_tassert(txn, XCURSOR_INITED(&cx.outer) && - cx.outer.mc_xcursor->mx_db.md_entries > 1); - if (cx.outer.mc_xcursor->mx_db.md_entries > 1) { - rc = MDBX_EMULTIVAL; - goto bailout; - } - } - /* еÑли данные Ñовпадают, то ничего делать не надо */ - if (new_data && mdbx_is_samedata(&present_data, new_data)) { - *old_data = *new_data; - goto bailout; - } - /* Ð’ оригинальной LMDB флажок MDBX_CURRENT здеÑÑŒ приведет - * к замене данных без учета MDBX_DUPSORT Ñортировки, - * но здеÑÑŒ Ñто в любом Ñлучае допуÑтимо, так как мы - * проверили что Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð° еÑть только одно значение. */ - } else if ((flags & MDBX_NODUPDATA) && - mdbx_is_samedata(&present_data, new_data)) { - /* еÑли данные Ñовпадают и уÑтановлен MDBX_NODUPDATA */ - rc = MDBX_KEYEXIST; - goto bailout; - } - } else { - /* еÑли данные Ñовпадают, то ничего делать не надо */ - if (new_data && mdbx_is_samedata(&present_data, new_data)) { - *old_data = *new_data; - goto bailout; - } - flags |= MDBX_CURRENT; - } - - if (IS_DIRTY(page)) { - if (unlikely(old_data->iov_len < present_data.iov_len)) { - old_data->iov_base = NULL; - old_data->iov_len = present_data.iov_len; - rc = MDBX_RESULT_TRUE; - goto bailout; - } - memcpy(old_data->iov_base, present_data.iov_base, present_data.iov_len); - old_data->iov_len = present_data.iov_len; - } else { - *old_data = present_data; - } - } - } - - if (likely(new_data)) - rc = mdbx_cursor_put(&cx.outer, key, new_data, flags); - else - rc = mdbx_cursor_del(&cx.outer, 0); - -bailout: - txn->mt_cursors[dbi] = cx.outer.mc_next; - return rc; -} - -/* Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ñообщает находитÑÑ Ð»Ð¸ указанный Ð°Ð´Ñ€ÐµÑ Ð² "грÑзной" Ñтранице у - * заданной пишущей транзакции. Ð’ конечном Ñчете Ñто позволÑет избавитьÑÑ Ð¾Ñ‚ - * лишнего ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… из ÐЕ-грÑзных Ñтраниц. - * - * "ГрÑзные" Ñтраницы - Ñто те, которые уже были изменены в ходе пишущей - * транзакции. СоответÑтвенно, какие-либо дальнейшие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ привеÑти - * к перезапиÑи таких Ñтраниц. ПоÑтому вÑе функции, выполнÑющие изменениÑ, в - * качеÑтве аргументов ÐЕ должны получать указатели на данные в таких - * Ñтраницах. Ð’ Ñвою очередь "ÐЕ грÑзные" Ñтраницы перед модификацией будут - * Ñкопированы. - * - * Другими Ñловами, данные из "грÑзных" Ñтраниц должны быть либо Ñкопированы - * перед передачей в качеÑтве аргументов Ð´Ð»Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ñ… модификаций, либо - * отвергнуты на Ñтадии проверки корректноÑти аргументов. - * - * Таким образом, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет как избавитьÑÑ Ð¾Ñ‚ лишнего копированиÑ, - * так и выполнить более полную проверку аргументов. - * - * Ð’ÐЖÐО: Передаваемый указатель должен указывать на начало данных. Только - * так гарантируетÑÑ Ñ‡Ñ‚Ð¾ актуальный заголовок Ñтраницы будет физичеÑки - * раÑположен в той-же Ñтранице памÑти, в том чиÑле Ð´Ð»Ñ Ð¼Ð½Ð¾Ð³Ð¾Ñтраничных - * P_OVERFLOW Ñтраниц Ñ Ð´Ð»Ð¸Ð½Ð½Ñ‹Ð¼Ð¸ данными. */ -int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (txn->mt_flags & MDBX_RDONLY) - return MDBX_RESULT_FALSE; - - const MDBX_env *env = txn->mt_env; - const ptrdiff_t offset = (uint8_t *)ptr - env->me_map; - if (offset >= 0) { - const pgno_t pgno = bytes2pgno(env, offset); - if (likely(pgno < txn->mt_next_pgno)) { - const MDBX_page *page = pgno2page(env, pgno); - if (unlikely(page->mp_pgno != pgno)) { - /* The ptr pointed into middle of a large page, - * not to the beginning of a data. */ - return MDBX_EINVAL; - } - if (unlikely(page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP))) - return MDBX_RESULT_TRUE; - if (likely(txn->tw.spill_pages == nullptr)) - return MDBX_RESULT_FALSE; - return mdbx_pnl_exist(txn->tw.spill_pages, pgno << 1) ? MDBX_RESULT_TRUE - : MDBX_RESULT_FALSE; - } - if ((size_t)offset < env->me_dxb_mmap.limit) { - /* Указатель адреÑует что-то в пределах mmap, но за границей - * раÑпределенных Ñтраниц. Такое может ÑлучитÑÑ ÐµÑли mdbx_is_dirty() - * вызывает поÑле операции, в ходе которой Ð³Ñ€Ð°Ð·Ð½Ð°Ñ Ñтраница попала - * в loose и затем была возвращена в нераÑпределенное проÑтранÑтво. */ - return MDBX_RESULT_TRUE; - } - } - - /* Страница вне иÑпользуемого mmap-диапазона, Ñ‚.е. либо в функцию был - * передан некорректный адреÑ, либо Ð°Ð´Ñ€ÐµÑ Ð² теневой Ñтранице, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±Ñ‹Ð»Ð° - * выделена поÑредÑтвом malloc(). - * - * Ð”Ð»Ñ WRITE_MAP режима Ñ‚Ð°ÐºÐ°Ñ Ñтраница однозначно "не грÑзнаÑ", - * а Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð¾Ð² без WRITE_MAP Ñледует проÑматривать ÑпиÑки dirty - * и spilled Ñтраниц у каких-либо транзакций (в том чиÑле дочерних). - * - * ПоÑтому Ð´Ð»Ñ WRITE_MAP возвращаем false, а Ð´Ð»Ñ Ð¾Ñтальных режимов - * вÑегда true. Ð¢Ð°ÐºÐ°Ñ Ð»Ð¾Ð³Ð¸ÐºÐ° имеет Ñ€Ñд преимущеÑтв: - * - не тратим Ð²Ñ€ÐµÐ¼Ñ Ð½Ð° проÑмотр ÑпиÑков; - * - результат вÑегда безопаÑен (может быть ложно-положительным, - * но не ложно-отрицательным); - * - результат не завиÑит от вложенноÑти транзакций и от отноÑительного - * Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð½Ð½Ð¾Ð¹ транзакции в Ñтой рекурÑии. */ - return (env->me_flags & MDBX_WRITEMAP) ? MDBX_RESULT_FALSE : MDBX_RESULT_TRUE; -} - -int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, - uint64_t increment) { - int rc = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(TXN_DBI_CHANGED(txn, dbi))) - return MDBX_BAD_DBI; - - if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) { - rc = mdbx_fetch_sdb(txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } - - MDBX_db *dbs = &txn->mt_dbs[dbi]; - if (likely(result)) - *result = dbs->md_seq; - - if (likely(increment > 0)) { - if (unlikely(txn->mt_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - uint64_t new = dbs->md_seq + increment; - if (unlikely(new < increment)) - return MDBX_RESULT_TRUE; - - mdbx_tassert(txn, new > dbs->md_seq); - dbs->md_seq = new; - txn->mt_flags |= MDBX_TXN_DIRTY; - txn->mt_dbflags[dbi] |= DB_DIRTY; - } - - return MDBX_SUCCESS; -} - -/*----------------------------------------------------------------------------*/ - -__cold intptr_t mdbx_limits_keysize_max(intptr_t pagesize) { - if (pagesize < 1) - pagesize = (intptr_t)mdbx_syspagesize(); - else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || - pagesize > (intptr_t)MAX_PAGESIZE || - !is_powerof2((size_t)pagesize))) - return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; - - return mdbx_maxkey(mdbx_nodemax(pagesize)); -} - -__cold intptr_t mdbx_limits_dbsize_min(intptr_t pagesize) { - if (pagesize < 1) - pagesize = (intptr_t)mdbx_syspagesize(); - else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || - pagesize > (intptr_t)MAX_PAGESIZE || - !is_powerof2((size_t)pagesize))) - return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; - - return MIN_PAGENO * pagesize; -} - -__cold intptr_t mdbx_limits_dbsize_max(intptr_t pagesize) { - if (pagesize < 1) - pagesize = (intptr_t)mdbx_syspagesize(); - else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || - pagesize > (intptr_t)MAX_PAGESIZE || - !is_powerof2((size_t)pagesize))) - return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; - - const uint64_t limit = MAX_PAGENO * (uint64_t)pagesize; - return (limit < (intptr_t)MAX_MAPSIZE) ? (intptr_t)limit - : (intptr_t)MAX_MAPSIZE; -} - -__cold intptr_t mdbx_limits_txnsize_max(intptr_t pagesize) { - if (pagesize < 1) - pagesize = (intptr_t)mdbx_syspagesize(); - else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || - pagesize > (intptr_t)MAX_PAGESIZE || - !is_powerof2((size_t)pagesize))) - return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; - - return pagesize * (MDBX_DPL_TXNFULL - 1); -} - -/*** Attribute support functions for Nexenta **********************************/ -#ifdef MDBX_NEXENTA_ATTRS - -static __inline int mdbx_attr_peek(MDBX_val *data, mdbx_attr_t *attrptr) { - if (unlikely(data->iov_len < sizeof(mdbx_attr_t))) - return MDBX_INCOMPATIBLE; - - if (likely(attrptr != NULL)) - *attrptr = *(mdbx_attr_t *)data->iov_base; - data->iov_len -= sizeof(mdbx_attr_t); - data->iov_base = - likely(data->iov_len > 0) ? ((mdbx_attr_t *)data->iov_base) + 1 : NULL; - - return MDBX_SUCCESS; -} - -static __inline int mdbx_attr_poke(MDBX_val *reserved, MDBX_val *data, - mdbx_attr_t attr, unsigned flags) { - mdbx_attr_t *space = reserved->iov_base; - if (flags & MDBX_RESERVE) { - if (likely(data != NULL)) { - data->iov_base = data->iov_len ? space + 1 : NULL; - } - } else { - *space = attr; - if (likely(data != NULL)) { - memcpy(space + 1, data->iov_base, data->iov_len); - } - } - - return MDBX_SUCCESS; -} - -int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, - mdbx_attr_t *attrptr, MDBX_cursor_op op) { - int rc = mdbx_cursor_get(mc, key, data, op); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - return mdbx_attr_peek(data, attrptr); -} - -int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - uint64_t *attrptr) { - int rc = mdbx_get(txn, dbi, key, data); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - return mdbx_attr_peek(data, attrptr); -} - -int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - mdbx_attr_t attr, unsigned flags) { - MDBX_val reserve; - reserve.iov_base = NULL; - reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t); - - int rc = mdbx_put(txn, dbi, key, &reserve, flags | MDBX_RESERVE); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - return mdbx_attr_poke(&reserve, data, attr, flags); -} - -int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, - mdbx_attr_t attr, unsigned flags) { - MDBX_val reserve; - reserve.iov_base = NULL; - reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t); - - int rc = mdbx_cursor_put(cursor, key, &reserve, flags | MDBX_RESERVE); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - return mdbx_attr_poke(&reserve, data, attr, flags); -} - -int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, - mdbx_attr_t attr) { - if (unlikely(!key || !txn)) - return MDBX_EINVAL; - - if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) - return MDBX_VERSION_MISMATCH; - - if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) - return MDBX_EINVAL; - - if (unlikely(txn->mt_flags & (MDBX_RDONLY | MDBX_TXN_BLOCKED))) - return (txn->mt_flags & MDBX_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; - - MDBX_cursor_couple cx; - MDBX_val old_data; - int rc = mdbx_cursor_init(&cx.outer, txn, dbi); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - rc = mdbx_cursor_set(&cx.outer, key, &old_data, MDBX_SET, NULL); - if (unlikely(rc != MDBX_SUCCESS)) { - if (rc == MDBX_NOTFOUND && data) { - cx.outer.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &cx.outer; - rc = mdbx_cursor_put_attr(&cx.outer, key, data, attr, 0); - txn->mt_cursors[dbi] = cx.outer.mc_next; - } - return rc; - } - - mdbx_attr_t old_attr = 0; - rc = mdbx_attr_peek(&old_data, &old_attr); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (old_attr == attr && (!data || (data->iov_len == old_data.iov_len && - memcmp(data->iov_base, old_data.iov_base, - old_data.iov_len) == 0))) - return MDBX_SUCCESS; - - cx.outer.mc_next = txn->mt_cursors[dbi]; - txn->mt_cursors[dbi] = &cx.outer; - rc = mdbx_cursor_put_attr(&cx.outer, key, data ? data : &old_data, attr, - MDBX_CURRENT); - txn->mt_cursors[dbi] = cx.outer.mc_next; - return rc; -} -#endif /* MDBX_NEXENTA_ATTRS */ - -/******************************************************************************/ -/* *INDENT-OFF* */ -/* clang-format off */ - -__dll_export -#ifdef __attribute_used__ - __attribute_used__ -#elif defined(__GNUC__) || __has_attribute(__used__) - __attribute__((__used__)) -#endif -#ifdef __attribute_externally_visible__ - __attribute_externally_visible__ -#elif (defined(__GNUC__) && !defined(__clang__)) || \ - __has_attribute(__externally_visible__) - __attribute__((__externally_visible__)) -#endif - const mdbx_build_info mdbx_build = { -#ifdef MDBX_BUILD_TIMESTAMP - MDBX_BUILD_TIMESTAMP -#else - __DATE__ " " __TIME__ -#endif /* MDBX_BUILD_TIMESTAMP */ - - , -#ifdef MDBX_BUILD_TARGET - MDBX_BUILD_TARGET -#else - #if defined(__ANDROID__) - "Android" - #elif defined(__linux__) || defined(__gnu_linux__) - "Linux" - #elif defined(EMSCRIPTEN) || defined(__EMSCRIPTEN__) - "webassembly" - #elif defined(__CYGWIN__) - "CYGWIN" - #elif defined(_WIN64) || defined(_WIN32) || defined(__TOS_WIN__) \ - || defined(__WINDOWS__) - "Windows" - #elif defined(__APPLE__) - #if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ - || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR) - "iOS" - #else - "MacOS" - #endif - #elif defined(__FreeBSD__) - "FreeBSD" - #elif defined(__DragonFly__) - "DragonFlyBSD" - #elif defined(__NetBSD__) || defined(__NETBSD__) - "NetBSD" - #elif defined(__OpenBSD__) - "OpenBSD" - #elif defined(__bsdi__) - "UnixBSDI" - #elif defined(__MACH__) - "MACH" - #elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) - "HPUX" - #elif defined(_AIX) - "AIX" - #elif defined(__sun) && defined(__SVR4) - "Solaris" - #elif defined(__BSD__) || defined(BSD) - "UnixBSD" - #elif defined(__unix__) || defined(UNIX) || defined(__unix) \ - || defined(__UNIX) || defined(__UNIX__) - "UNIX" - #elif defined(_POSIX_VERSION) - "POSIX" STRINGIFY(_POSIX_VERSION) - #else - "UnknownOS" - #endif /* Target OS */ - - "-" - - #if defined(__amd64__) - "AMD64" - #elif defined(__ia32__) - "IA32" - #elif defined(__e2k__) || defined(__elbrus__) - "Elbrus" - #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) - "Alpha" - #elif defined(__aarch64__) || defined(_M_ARM64) - "ARM64" - #elif defined(__arm__) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) \ - || defined(__TARGET_ARCH_THUMB) || defined(_ARM) || defined(_M_ARM) \ - || defined(_M_ARMT) || defined(__arm) - "ARM" - #elif defined(__mips64) || defined(__mips64__) || (defined(__mips) && (__mips >= 64)) - "MIPS64" - #elif if defined(__mips__) || defined(__mips) || defined(_R4000) || defined(__MIPS__) - "MIPS" - #elif defined(__hppa64__) || defined(__HPPA64__) || defined(__hppa64) - "PARISC64" - #elif defined(__hppa__) || defined(__HPPA__) || defined(__hppa) - "PARISC" - #elif defined(__ia64__) || defined(__ia64) || defined(_IA64) \ - || defined(__IA64__) || defined(_M_IA64) || defined(__itanium__) - "Itanium" - #elif defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) \ - || defined(__powerpc64) || defined(_ARCH_PPC64) - "PowerPC64" - #elif defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) \ - || defined(__ppc) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__POWERPC__) - "PowerPC" - #elif defined(__sparc64__) || defined(__sparc64) - "SPARC64" - #elif defined(__sparc__) || defined(__sparc) - "SPARC" - #elif defined(__s390__) || defined(__s390) || defined(__zarch__) || defined(__zarch) - "S390" - #else - "UnknownARCH" - #endif -#endif /* MDBX_BUILD_TARGET */ - -#ifdef MDBX_BUILD_CONFIG -# if defined(_MSC_VER) -# pragma message("Configuration-depended MDBX_BUILD_CONFIG: " MDBX_BUILD_CONFIG) -# endif - "-" MDBX_BUILD_CONFIG -#endif /* MDBX_BUILD_CONFIG */ - , - "MDBX_DEBUG=" STRINGIFY(MDBX_DEBUG) -#ifdef MDBX_LOGLEVEL_BUILD - " MDBX_LOGLEVEL_BUILD=" STRINGIFY(MDBX_LOGLEVEL_BUILD) -#endif /* MDBX_LOGLEVEL_BUILD */ - " MDBX_WORDBITS=" STRINGIFY(MDBX_WORDBITS) - " BYTE_ORDER=" -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - "LITTLE_ENDIAN" -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - "BIG_ENDIAN" -#else - #error "FIXME: Unsupported byte order" -#endif /* __BYTE_ORDER__ */ - " MDBX_TXN_CHECKPID=" MDBX_TXN_CHECKPID_CONFIG - " MDBX_TXN_CHECKOWNER=" MDBX_TXN_CHECKOWNER_CONFIG - " MDBX_64BIT_ATOMIC=" MDBX_64BIT_ATOMIC_CONFIG - " MDBX_64BIT_CAS=" MDBX_64BIT_CAS_CONFIG - " MDBX_TRUST_RTC=" MDBX_TRUST_RTC_CONFIG -#ifdef __SANITIZE_ADDRESS__ - " SANITIZE_ADDRESS=YES" -#endif /* __SANITIZE_ADDRESS__ */ -#ifdef MDBX_USE_VALGRIND - " MDBX_USE_VALGRIND=YES" -#endif /* MDBX_USE_VALGRIND */ -#ifdef _GNU_SOURCE - " _GNU_SOURCE=YES" -#else - " _GNU_SOURCE=NO" -#endif /* _GNU_SOURCE */ -#ifdef __APPLE__ - " MDBX_OSX_SPEED_INSTEADOF_DURABILITY=" STRINGIFY(MDBX_OSX_SPEED_INSTEADOF_DURABILITY) -#endif /* MacOS */ -#if defined(_WIN32) || defined(_WIN64) - " MDBX_AVOID_CRT=" STRINGIFY(MDBX_AVOID_CRT) - " MDBX_CONFIG_MANUAL_TLS_CALLBACK=" STRINGIFY(MDBX_CONFIG_MANUAL_TLS_CALLBACK) - " MDBX_BUILD_SHARED_LIBRARY=" STRINGIFY(MDBX_BUILD_SHARED_LIBRARY) - " WINVER=" STRINGIFY(WINVER) -#else /* Windows */ - " MDBX_USE_ROBUST=" MDBX_USE_ROBUST_CONFIG - " MDBX_USE_OFDLOCKS=" MDBX_USE_OFDLOCKS_CONFIG -#endif /* !Windows */ -#ifdef MDBX_OSAL_LOCK - " MDBX_OSAL_LOCK=" STRINGIFY(MDBX_OSAL_LOCK) -#endif - " MDBX_CACHELINE_SIZE=" STRINGIFY(MDBX_CACHELINE_SIZE) - " MDBX_CPU_WRITEBACK_IS_COHERENT=" STRINGIFY(MDBX_CPU_WRITEBACK_IS_COHERENT) - " MDBX_UNALIGNED_OK=" STRINGIFY(MDBX_UNALIGNED_OK) - " MDBX_PNL_ASCENDING=" STRINGIFY(MDBX_PNL_ASCENDING) - , -#ifdef MDBX_BUILD_COMPILER - MDBX_BUILD_COMPILER -#else - #ifdef __INTEL_COMPILER - "Intel C/C++ " STRINGIFY(__INTEL_COMPILER) - #elsif defined(__apple_build_version__) - "Apple clang " STRINGIFY(__apple_build_version__) - #elif defined(__ibmxl__) - "IBM clang C " STRINGIFY(__ibmxl_version__) "." STRINGIFY(__ibmxl_release__) - "." STRINGIFY(__ibmxl_modification__) "." STRINGIFY(__ibmxl_ptf_fix_level__) - #elif defined(__clang__) - "clang " STRINGIFY(__clang_version__) - #elif defined(__MINGW64__) - "MINGW-64 " STRINGIFY(__MINGW64_MAJOR_VERSION) "." STRINGIFY(__MINGW64_MINOR_VERSION) - #elif defined(__MINGW32__) - "MINGW-32 " STRINGIFY(__MINGW32_MAJOR_VERSION) "." STRINGIFY(__MINGW32_MINOR_VERSION) - #elif defined(__IBMC__) - "IBM C " STRINGIFY(__IBMC__) - #elif defined(__GNUC__) - "GNU C/C++ " - #ifdef __VERSION__ - __VERSION__ - #else - STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__) - #endif - #elif defined(_MSC_VER) - "MSVC " STRINGIFY(_MSC_FULL_VER) "-" STRINGIFY(_MSC_BUILD) - #else - "Unknown compiler" - #endif -#endif /* MDBX_BUILD_COMPILER */ - , -#ifdef MDBX_BUILD_FLAGS - MDBX_BUILD_FLAGS -#endif /* MDBX_BUILD_FLAGS */ -#ifdef MDBX_BUILD_FLAGS_CONFIG - MDBX_BUILD_FLAGS_CONFIG -#endif /* MDBX_BUILD_FLAGS_CONFIG */ -}; - -#ifdef __SANITIZE_ADDRESS__ -LIBMDBX_API __attribute__((__weak__)) const char *__asan_default_options() { - return "symbolize=1:allow_addr2line=1:" -#ifdef _DEBUG - "debug=1:" -#endif /* _DEBUG */ - "report_globals=1:" - "replace_str=1:replace_intrin=1:" - "malloc_context_size=9:" - "detect_leaks=1:" - "check_printf=1:" - "detect_deadlocks=1:" -#ifndef LTO_ENABLED - "check_initialization_order=1:" -#endif - "detect_stack_use_after_return=1:" - "intercept_tls_get_addr=1:" - "decorate_proc_maps=1:" - "abort_on_error=1"; -} -#endif /* __SANITIZE_ADDRESS__ */ - -/* *INDENT-ON* */ -/* clang-format on */ diff --git a/src/contrib/db/libmdbx/src/elements/defs.h b/src/contrib/db/libmdbx/src/elements/defs.h deleted file mode 100644 index aba07f9..0000000 --- a/src/contrib/db/libmdbx/src/elements/defs.h +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once -/* *INDENT-OFF* */ -/* clang-format off */ - -#ifndef __GNUC_PREREQ -# if defined(__GNUC__) && defined(__GNUC_MINOR__) -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -# else -# define __GNUC_PREREQ(maj, min) (0) -# endif -#endif /* __GNUC_PREREQ */ - -#ifndef __CLANG_PREREQ -# ifdef __clang__ -# define __CLANG_PREREQ(maj,min) \ - ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) -# else -# define __CLANG_PREREQ(maj,min) (0) -# endif -#endif /* __CLANG_PREREQ */ - -#ifndef __GLIBC_PREREQ -# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) -# define __GLIBC_PREREQ(maj, min) \ - ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) -# else -# define __GLIBC_PREREQ(maj, min) (0) -# endif -#endif /* __GLIBC_PREREQ */ - -#ifndef __has_attribute -# define __has_attribute(x) (0) -#endif - -#ifndef __has_feature -# define __has_feature(x) (0) -#endif - -#ifndef __has_extension -# define __has_extension(x) (0) -#endif - -#ifndef __has_builtin -# define __has_builtin(x) (0) -#endif - -#ifndef __has_warning -# define __has_warning(x) (0) -#endif - -#ifndef __has_include -# define __has_include(x) (0) -#endif - -#if __has_feature(thread_sanitizer) -# define __SANITIZE_THREAD__ 1 -#endif - -#if __has_feature(address_sanitizer) -# define __SANITIZE_ADDRESS__ 1 -#endif - -/*----------------------------------------------------------------------------*/ - -#ifndef __extern_C -# ifdef __cplusplus -# define __extern_C extern "C" -# else -# define __extern_C -# endif -#endif /* __extern_C */ - -#ifndef __cplusplus -# ifndef bool -# define bool _Bool -# endif -# ifndef true -# define true (1) -# endif -# ifndef false -# define false (0) -# endif -#endif - -#if !defined(nullptr) && !defined(__cplusplus) || (__cplusplus < 201103L && !defined(_MSC_VER)) -# define nullptr NULL -#endif - -/*----------------------------------------------------------------------------*/ - -#ifndef __always_inline -# if defined(__GNUC__) || __has_attribute(__always_inline__) -# define __always_inline __inline __attribute__((__always_inline__)) -# elif defined(_MSC_VER) -# define __always_inline __forceinline -# else -# define __always_inline -# endif -#endif /* __always_inline */ - -#ifndef __noinline -# if defined(__GNUC__) || __has_attribute(__noinline__) -# define __noinline __attribute__((__noinline__)) -# elif defined(_MSC_VER) -# define __noinline __declspec(noinline) -# elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) -# define __noinline inline -# elif !defined(__INTEL_COMPILER) -# define __noinline /* FIXME ? */ -# endif -#endif /* __noinline */ - -#ifndef __must_check_result -# if defined(__GNUC__) || __has_attribute(__warn_unused_result__) -# define __must_check_result __attribute__((__warn_unused_result__)) -# else -# define __must_check_result -# endif -#endif /* __must_check_result */ - -#ifndef __maybe_unused -# if defined(__GNUC__) || __has_attribute(__unused__) -# define __maybe_unused __attribute__((__unused__)) -# else -# define __maybe_unused -# endif -#endif /* __maybe_unused */ - -#ifndef __deprecated -# if defined(__GNUC__) || __has_attribute(__deprecated__) -# define __deprecated __attribute__((__deprecated__)) -# elif defined(_MSC_VER) -# define __deprecated __declspec(deprecated) -# else -# define __deprecated -# endif -#endif /* __deprecated */ - -#if !defined(__noop) && !defined(_MSC_VER) -# define __noop(...) do {} while(0) -#endif /* __noop */ - -#ifndef __fallthrough -# if __GNUC_PREREQ(7, 0) || __has_attribute(__fallthrough__) -# define __fallthrough __attribute__((__fallthrough__)) -# else -# define __fallthrough __noop() -# endif -#endif /* __fallthrough */ - -#ifndef __unreachable -# if __GNUC_PREREQ(4,5) -# define __unreachable() __builtin_unreachable() -# elif defined(_MSC_VER) -# define __unreachable() __assume(0) -# else -# define __unreachable() __noop() -# endif -#endif /* __unreachable */ - -#ifndef __prefetch -# if defined(__GNUC__) || defined(__clang__) -# define __prefetch(ptr) __builtin_prefetch(ptr) -# else -# define __prefetch(ptr) __noop(ptr) -# endif -#endif /* __prefetch */ - -#ifndef __noreturn -# if defined(__GNUC__) || __has_attribute(__noreturn__) -# define __noreturn __attribute__((__noreturn__)) -# elif defined(_MSC_VER) -# define __noreturn __declspec(noreturn) -# else -# define __noreturn -# endif -#endif /* __noreturn */ - -#ifndef __nothrow -# if defined(__cplusplus) -# if __cplusplus < 201703L -# define __nothrow throw() -# else -# define __nothrow noexcept(true) -# endif /* __cplusplus */ -# elif defined(__GNUC__) || __has_attribute(__nothrow__) -# define __nothrow __attribute__((__nothrow__)) -# elif defined(_MSC_VER) && defined(__cplusplus) -# define __nothrow __declspec(nothrow) -# else -# define __nothrow -# endif -#endif /* __nothrow */ - -#ifndef __pure_function - /* Many functions have no effects except the return value and their - * return value depends only on the parameters and/or global variables. - * Such a function can be subject to common subexpression elimination - * and loop optimization just as an arithmetic operator would be. - * These functions should be declared with the attribute pure. */ -# if defined(__GNUC__) || __has_attribute(__pure__) -# define __pure_function __attribute__((__pure__)) -# else -# define __pure_function -# endif -#endif /* __pure_function */ - -#ifndef __const_function - /* Many functions do not examine any values except their arguments, - * and have no effects except the return value. Basically this is just - * slightly more strict class than the PURE attribute, since function - * is not allowed to read global memory. - * - * Note that a function that has pointer arguments and examines the - * data pointed to must not be declared const. Likewise, a function - * that calls a non-const function usually must not be const. - * It does not make sense for a const function to return void. */ -# if defined(__GNUC__) || __has_attribute(__const__) -# define __const_function __attribute__((__const__)) -# else -# define __const_function -# endif -#endif /* __const_function */ - -#ifndef __hidden -# if defined(__GNUC__) || __has_attribute(__visibility__) -# define __hidden __attribute__((__visibility__("hidden"))) -# else -# define __hidden -# endif -#endif /* __hidden */ - -#ifndef __optimize -# if defined(__OPTIMIZE__) -# if defined(__clang__) && !__has_attribute(__optimize__) -# define __optimize(ops) -# elif defined(__GNUC__) || __has_attribute(__optimize__) -# define __optimize(ops) __attribute__((__optimize__(ops))) -# else -# define __optimize(ops) -# endif -# else -# define __optimize(ops) -# endif -#endif /* __optimize */ - -#ifndef __hot -# if defined(__OPTIMIZE__) -# if defined(__e2k__) -# define __hot __attribute__((__hot__)) __optimize(3) -# elif defined(__clang__) && !__has_attribute(__hot_) \ - && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__)) - /* just put frequently used functions in separate section */ -# define __hot __attribute__((__section__("text.hot"))) __optimize("O3") -# elif defined(__GNUC__) || __has_attribute(__hot__) -# define __hot __attribute__((__hot__)) __optimize("O3") -# else -# define __hot __optimize("O3") -# endif -# else -# define __hot -# endif -#endif /* __hot */ - -#ifndef __cold -# if defined(__OPTIMIZE__) -# if defined(__e2k__) -# define __cold __attribute__((__cold__)) __optimize(1) -# elif defined(__clang__) && !__has_attribute(cold) \ - && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__)) - /* just put infrequently used functions in separate section */ -# define __cold __attribute__((__section__("text.unlikely"))) __optimize("Os") -# elif defined(__GNUC__) || __has_attribute(cold) -# define __cold __attribute__((__cold__)) __optimize("Os") -# else -# define __cold __optimize("Os") -# endif -# else -# define __cold -# endif -#endif /* __cold */ - -#ifndef __flatten -# if defined(__OPTIMIZE__) && (defined(__GNUC__) || __has_attribute(__flatten__)) -# define __flatten __attribute__((__flatten__)) -# else -# define __flatten -# endif -#endif /* __flatten */ - -#ifndef likely -# if (defined(__GNUC__) || defined(__clang__)) && !defined(__COVERITY__) -# define likely(cond) __builtin_expect(!!(cond), 1) -# else -# define likely(x) (x) -# endif -#endif /* likely */ - -#ifndef unlikely -# if (defined(__GNUC__) || defined(__clang__)) && !defined(__COVERITY__) -# define unlikely(cond) __builtin_expect(!!(cond), 0) -# else -# define unlikely(x) (x) -# endif -#endif /* unlikely */ - -/* Workaround for Coverity Scan */ -#if defined(__COVERITY__) && __GNUC_PREREQ(7, 0) && !defined(__cplusplus) -typedef float _Float32; -typedef double _Float32x; -typedef double _Float64; -typedef long double _Float64x; -typedef float _Float128 __attribute__((__mode__(__TF__))); -typedef __complex__ float __cfloat128 __attribute__ ((__mode__ (__TC__))); -typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); -#endif /* Workaround for Coverity Scan */ - -#ifndef __printf_args -# if defined(__GNUC__) || __has_attribute(__format__) -# define __printf_args(format_index, first_arg) \ - __attribute__((__format__(printf, format_index, first_arg))) -# else -# define __printf_args(format_index, first_arg) -# endif -#endif /* __printf_args */ - -#ifndef __anonymous_struct_extension__ -# if defined(__GNUC__) -# define __anonymous_struct_extension__ __extension__ -# else -# define __anonymous_struct_extension__ -# endif -#endif /* __anonymous_struct_extension__ */ - -#ifndef __Wpedantic_format_voidptr - static __inline const void* __pure_function - __Wpedantic_format_voidptr(const void* ptr) {return ptr;} -# define __Wpedantic_format_voidptr(ARG) __Wpedantic_format_voidptr(ARG) -#endif /* __Wpedantic_format_voidptr */ - -/*----------------------------------------------------------------------------*/ - -#if defined(MDBX_USE_VALGRIND) -# include -# ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE - /* LY: available since Valgrind 3.10 */ -# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) -# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) -# endif -#elif !defined(RUNNING_ON_VALGRIND) -# define VALGRIND_CREATE_MEMPOOL(h,r,z) -# define VALGRIND_DESTROY_MEMPOOL(h) -# define VALGRIND_MEMPOOL_TRIM(h,a,s) -# define VALGRIND_MEMPOOL_ALLOC(h,a,s) -# define VALGRIND_MEMPOOL_FREE(h,a) -# define VALGRIND_MEMPOOL_CHANGE(h,a,b,s) -# define VALGRIND_MAKE_MEM_NOACCESS(a,s) -# define VALGRIND_MAKE_MEM_DEFINED(a,s) -# define VALGRIND_MAKE_MEM_UNDEFINED(a,s) -# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) -# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) -# define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,s) (0) -# define VALGRIND_CHECK_MEM_IS_DEFINED(a,s) (0) -# define RUNNING_ON_VALGRIND (0) -#endif /* MDBX_USE_VALGRIND */ - -#ifdef __SANITIZE_ADDRESS__ -# include -#elif !defined(ASAN_POISON_MEMORY_REGION) -# define ASAN_POISON_MEMORY_REGION(addr, size) \ - ((void)(addr), (void)(size)) -# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ - ((void)(addr), (void)(size)) -#endif /* __SANITIZE_ADDRESS__ */ - -/*----------------------------------------------------------------------------*/ - -#ifndef ARRAY_LENGTH -# ifdef __cplusplus - template - char (&__ArraySizeHelper(T (&array)[N]))[N]; -# define ARRAY_LENGTH(array) (sizeof(::__ArraySizeHelper(array))) -# else -# define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) -# endif -#endif /* ARRAY_LENGTH */ - -#ifndef ARRAY_END -# define ARRAY_END(array) (&array[ARRAY_LENGTH(array)]) -#endif /* ARRAY_END */ - -#ifndef STRINGIFY -# define STRINGIFY_HELPER(x) #x -# define STRINGIFY(x) STRINGIFY_HELPER(x) -#endif /* STRINGIFY */ - -#define CONCAT(a,b) a##b -#define XCONCAT(a,b) CONCAT(a,b) - -#ifndef offsetof -# define offsetof(type, member) __builtin_offsetof(type, member) -#endif /* offsetof */ - -#ifndef container_of -# define container_of(ptr, type, member) \ - ((type *)((char *)(ptr) - offsetof(type, member))) -#endif /* container_of */ - -#define MDBX_TETRAD(a, b, c, d) \ - ((uint32_t)(a) << 24 | (uint32_t)(b) << 16 | (uint32_t)(c) << 8 | (d)) - -#define MDBX_STRING_TETRAD(str) MDBX_TETRAD(str[0], str[1], str[2], str[3]) - -#define FIXME "FIXME: " __FILE__ ", " STRINGIFY(__LINE__) - -#ifndef STATIC_ASSERT_MSG -# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ - || __has_feature(c_static_assert) -# define STATIC_ASSERT_MSG(expr, msg) _Static_assert(expr, msg) -# elif defined(static_assert) -# define STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg) -# elif defined(_MSC_VER) -# include -# define STATIC_ASSERT_MSG(expr, msg) _STATIC_ASSERT(expr) -# else -# define STATIC_ASSERT_MSG(expr, msg) switch (0) {case 0:case (expr):;} -# endif -#endif /* STATIC_ASSERT */ - -#ifndef STATIC_ASSERT -# define STATIC_ASSERT(expr) STATIC_ASSERT_MSG(expr, #expr) -#endif - -/* *INDENT-ON* */ -/* clang-format on */ diff --git a/src/contrib/db/libmdbx/src/elements/internals.h b/src/contrib/db/libmdbx/src/elements/internals.h deleted file mode 100644 index 6aba374..0000000 --- a/src/contrib/db/libmdbx/src/elements/internals.h +++ /dev/null @@ -1,1367 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#pragma once -#ifdef MDBX_CONFIG_H -#include MDBX_CONFIG_H -#endif - -/* *INDENT-OFF* */ -/* clang-format off */ - -/* In case the MDBX_DEBUG is undefined set it corresponding to NDEBUG */ -#ifndef MDBX_DEBUG -# ifdef NDEBUG -# define MDBX_DEBUG 0 -# else -# define MDBX_DEBUG 1 -# endif -#endif - -/* Undefine the NDEBUG if debugging is enforced by MDBX_DEBUG */ -#if MDBX_DEBUG -# undef NDEBUG -#endif - -#define MDBX_OSX_WANNA_DURABILITY 0 /* using fcntl(F_FULLFSYNC) with 5-10 times slowdown */ -#define MDBX_OSX_WANNA_SPEED 1 /* using fsync() with chance of data lost on power failure */ -#ifndef MDBX_OSX_SPEED_INSTEADOF_DURABILITY -# define MDBX_OSX_SPEED_INSTEADOF_DURABILITY MDBX_OSX_WANNA_DURABILITY -#endif - -#ifdef MDBX_ALLOY -/* Amalgamated build */ -# define MDBX_INTERNAL_FUNC static -# define MDBX_INTERNAL_VAR static -#else -/* Non-amalgamated build */ -# define MDBX_INTERNAL_FUNC -# define MDBX_INTERNAL_VAR extern -#endif /* MDBX_ALLOY */ - -#ifndef MDBX_DISABLE_GNU_SOURCE -#define MDBX_DISABLE_GNU_SOURCE 0 -#endif -#if MDBX_DISABLE_GNU_SOURCE -#undef _GNU_SOURCE -#elif defined(__linux__) || defined(__gnu_linux__) -#define _GNU_SOURCE -#endif - -/*----------------------------------------------------------------------------*/ - -/* Should be defined before any includes */ -#ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -#endif - -#ifdef __APPLE__ -#define _DARWIN_C_SOURCE -#endif - -#ifdef _MSC_VER -# if _MSC_VER < 1400 -# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required" -# endif -# ifndef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS -# endif -#if _MSC_VER > 1800 -# pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#if _MSC_VER > 1913 -# pragma warning(disable : 5045) /* Compiler will insert Spectre mitigation... */ -#endif -#pragma warning(disable : 4710) /* 'xyz': function not inlined */ -#pragma warning(disable : 4711) /* function 'xyz' selected for automatic inline expansion */ -#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct / union */ -#pragma warning(disable : 4702) /* unreachable code */ -#pragma warning(disable : 4706) /* assignment within conditional expression */ -#pragma warning(disable : 4127) /* conditional expression is constant */ -#pragma warning(disable : 4324) /* 'xyz': structure was padded due to alignment specifier */ -#pragma warning(disable : 4310) /* cast truncates constant value */ -#pragma warning(disable : 4820) /* bytes padding added after data member for aligment */ -#pragma warning(disable : 4548) /* expression before comma has no effect; expected expression with side - effect */ -#pragma warning(disable : 4366) /* the result of the unary '&' operator may be unaligned */ -#pragma warning(disable : 4200) /* nonstandard extension used: zero-sized array in struct/union */ -#endif /* _MSC_VER (warnings) */ - -#include "../../mdbx.h" -#include "defs.h" - -#if defined(__GNUC__) && !__GNUC_PREREQ(4,2) - /* Actualy libmdbx was not tested with compilers older than GCC from RHEL6. - * But you could remove this #error and try to continue at your own risk. - * In such case please don't rise up an issues related ONLY to old compilers. - */ -# warning "libmdbx required GCC >= 4.2" -#endif - -#if defined(__clang__) && !__CLANG_PREREQ(3,8) - /* Actualy libmdbx was not tested with CLANG older than 3.8. - * But you could remove this #error and try to continue at your own risk. - * In such case please don't rise up an issues related ONLY to old compilers. - */ -# warning "libmdbx required CLANG >= 3.8" -#endif - -#if defined(__GLIBC__) && !__GLIBC_PREREQ(2,12) - /* Actualy libmdbx was not tested with something older than glibc 2.12 (from RHEL6). - * But you could remove this #error and try to continue at your own risk. - * In such case please don't rise up an issues related ONLY to old systems. - */ -# warning "libmdbx required at least GLIBC 2.12." -#endif - -#ifdef __SANITIZE_THREAD__ -# warning "libmdbx don't compatible with ThreadSanitizer, you will get a lot of false-positive issues." -#endif /* __SANITIZE_THREAD__ */ - -#if __has_warning("-Wconstant-logical-operand") -# if defined(__clang__) -# pragma clang diagnostic ignored "-Wconstant-logical-operand" -# elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wconstant-logical-operand" -# else -# pragma warning disable "constant-logical-operand" -# endif -#endif /* -Wconstant-logical-operand */ - -#if defined(__LCC__) && (__LCC__ <= 121) - /* bug #2798 */ -# pragma diag_suppress alignment_reduction_ignored -#elif defined(__ICC) -# pragma warning(disable: 3453 1366) -#elif __has_warning("-Walignment-reduction-ignored") -# if defined(__clang__) -# pragma clang diagnostic ignored "-Walignment-reduction-ignored" -# elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Walignment-reduction-ignored" -# else -# pragma warning disable "alignment-reduction-ignored" -# endif -#endif /* -Walignment-reduction-ignored */ - -#include "osal.h" - -/* *INDENT-ON* */ -/* clang-format on */ - -#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul -#define MDBX_WORDBITS 64 -#else -#define MDBX_WORDBITS 32 -#endif /* MDBX_WORDBITS */ - -#ifndef MDBX_64BIT_ATOMIC -#if MDBX_WORDBITS >= 64 -#define MDBX_64BIT_ATOMIC 1 -#else -#define MDBX_64BIT_ATOMIC 0 -#endif -#define MDBX_64BIT_ATOMIC_CONFIG "AUTO=" STRINGIFY(MDBX_64BIT_ATOMIC) -#else -#define MDBX_64BIT_ATOMIC_CONFIG STRINGIFY(MDBX_64BIT_ATOMIC) -#endif /* MDBX_64BIT_ATOMIC */ - -#ifndef MDBX_64BIT_CAS -#if defined(ATOMIC_LLONG_LOCK_FREE) -#if ATOMIC_LLONG_LOCK_FREE > 1 -#define MDBX_64BIT_CAS 1 -#else -#define MDBX_64BIT_CAS 0 -#endif -#elif defined(__GCC_ATOMIC_LLONG_LOCK_FREE) -#if __GCC_ATOMIC_LLONG_LOCK_FREE > 1 -#define MDBX_64BIT_CAS 1 -#else -#define MDBX_64BIT_CAS 0 -#endif -#elif defined(__CLANG_ATOMIC_LLONG_LOCK_FREE) -#if __CLANG_ATOMIC_LLONG_LOCK_FREE > 1 -#define MDBX_64BIT_CAS 1 -#else -#define MDBX_64BIT_CAS 0 -#endif -#elif defined(_MSC_VER) || defined(__APPLE__) -#define MDBX_64BIT_CAS 1 -#else -#define MDBX_64BIT_CAS MDBX_64BIT_ATOMIC -#endif -#define MDBX_64BIT_CAS_CONFIG "AUTO=" STRINGIFY(MDBX_64BIT_CAS) -#else -#define MDBX_64BIT_CAS_CONFIG STRINGIFY(MDBX_64BIT_CAS) -#endif /* MDBX_64BIT_CAS */ - -/* Some platforms define the EOWNERDEAD error code even though they - * don't support Robust Mutexes. Compile with -DMDBX_USE_ROBUST=0. */ -#ifndef MDBX_USE_ROBUST -/* Howard Chu: Android currently lacks Robust Mutex support */ -#if defined(EOWNERDEAD) && !defined(__ANDROID__) && !defined(__APPLE__) && \ - (!defined(__GLIBC__) || \ - __GLIBC_PREREQ( \ - 2, \ - 10) /* LY: glibc before 2.10 has a troubles with Robust Mutex too. */ \ - || _POSIX_C_SOURCE >= 200809L) -#define MDBX_USE_ROBUST 1 -#else -#define MDBX_USE_ROBUST 0 -#endif -#define MDBX_USE_ROBUST_CONFIG "AUTO=" STRINGIFY(MDBX_USE_ROBUST) -#else -#define MDBX_USE_ROBUST_CONFIG STRINGIFY(MDBX_USE_ROBUST) -#endif /* MDBX_USE_ROBUST */ - -#ifndef MDBX_USE_OFDLOCKS -#if defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && defined(F_OFD_GETLK) && \ - !defined(MDBX_SAFE4QEMU) -#define MDBX_USE_OFDLOCKS 1 -#else -#define MDBX_USE_OFDLOCKS 0 -#endif -#define MDBX_USE_OFDLOCKS_CONFIG "AUTO=" STRINGIFY(MDBX_USE_OFDLOCKS) -#else -#define MDBX_USE_OFDLOCKS_CONFIG STRINGIFY(MDBX_USE_OFDLOCKS) -#endif /* MDBX_USE_OFDLOCKS */ - -/* Controls checking PID against reuse DB environment after the fork() */ -#ifndef MDBX_TXN_CHECKPID -#if defined(MADV_DONTFORK) || defined(_WIN32) || defined(_WIN64) -/* PID check could be ommited: - * - on Linux when madvise(MADV_DONTFORK) is available. i.e. after the fork() - * mapped pages will not be available for child process. - * - in Windows where fork() not available. */ -#define MDBX_TXN_CHECKPID 0 -#else -#define MDBX_TXN_CHECKPID 1 -#endif -#define MDBX_TXN_CHECKPID_CONFIG "AUTO=" STRINGIFY(MDBX_TXN_CHECKPID) -#else -#define MDBX_TXN_CHECKPID_CONFIG STRINGIFY(MDBX_TXN_CHECKPID) -#endif /* MDBX_TXN_CHECKPID */ - -/* Controls checking transaction owner thread against misuse transactions from - * other threads. */ -#ifndef MDBX_TXN_CHECKOWNER -#define MDBX_TXN_CHECKOWNER 1 -#define MDBX_TXN_CHECKOWNER_CONFIG "AUTO=" STRINGIFY(MDBX_TXN_CHECKOWNER) -#else -#define MDBX_TXN_CHECKOWNER_CONFIG STRINGIFY(MDBX_TXN_CHECKOWNER) -#endif /* MDBX_TXN_CHECKOWNER */ - -#define mdbx_sourcery_anchor XCONCAT(mdbx_sourcery_, MDBX_BUILD_SOURCERY) -#if defined(MDBX_TOOLS) -extern LIBMDBX_API const char *const mdbx_sourcery_anchor; -#endif - -/* Does a system have battery-backed Real-Time Clock or just a fake. */ -#ifndef MDBX_TRUST_RTC -#if defined(__linux__) || defined(__gnu_linux__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) -#define MDBX_TRUST_RTC 0 /* a lot of embedded systems have a fake RTC */ -#else -#define MDBX_TRUST_RTC 1 -#endif -#define MDBX_TRUST_RTC_CONFIG "AUTO=" STRINGIFY(MDBX_TRUST_RTC) -#else -#define MDBX_TRUST_RTC_CONFIG STRINGIFY(MDBX_TRUST_RTC) -#endif /* MDBX_TRUST_RTC */ - -/*----------------------------------------------------------------------------*/ -/* Basic constants and types */ - -/* The minimum number of keys required in a database page. - * Setting this to a larger value will place a smaller bound on the - * maximum size of a data item. Data items larger than this size will - * be pushed into overflow pages instead of being stored directly in - * the B-tree node. This value used to default to 4. With a page size - * of 4096 bytes that meant that any item larger than 1024 bytes would - * go into an overflow page. That also meant that on average 2-3KB of - * each overflow page was wasted space. The value cannot be lower than - * 2 because then there would no longer be a tree structure. With this - * value, items larger than 2KB will go into overflow pages, and on - * average only 1KB will be wasted. */ -#define MDBX_MINKEYS 2 - -/* A stamp that identifies a file as an MDBX file. - * There's nothing special about this value other than that it is easily - * recognizable, and it will reflect any byte order mismatches. */ -#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11) - -/* The version number for a database's datafile format. */ -#define MDBX_DATA_VERSION 2 -/* The version number for a database's lockfile format. */ -#define MDBX_LOCK_VERSION 3 - -/* handle for the DB used to track free pages. */ -#define FREE_DBI 0 -/* handle for the default DB. */ -#define MAIN_DBI 1 -/* Number of DBs in metapage (free and main) - also hardcoded elsewhere */ -#define CORE_DBS 2 -#define MAX_DBI (INT16_MAX - CORE_DBS) -#if MAX_DBI != MDBX_MAX_DBI -#error "Opps, MAX_DBI != MDBX_MAX_DBI" -#endif - -/* Number of meta pages - also hardcoded elsewhere */ -#define NUM_METAS 3 - -/* A page number in the database. - * - * MDBX uses 32 bit for page numbers. This limits database - * size up to 2^44 bytes, in case of 4K pages. */ -typedef uint32_t pgno_t; -#define PRIaPGNO PRIu32 -#define MAX_PAGENO UINT32_C(0x7FFFffff) -#define MIN_PAGENO NUM_METAS - -/* A transaction ID. */ -typedef uint64_t txnid_t; -#define PRIaTXN PRIi64 -#define MIN_TXNID UINT64_C(1) -/* LY: for testing non-atomic 64-bit txnid on 32-bit arches. - * #define MDBX_TXNID_STEP (UINT32_MAX / 3) */ -#ifndef MDBX_TXNID_STEP -#if MDBX_64BIT_CAS -#define MDBX_TXNID_STEP 1u -#else -#define MDBX_TXNID_STEP 2u -#endif -#endif /* MDBX_TXNID_STEP */ - -/* Used for offsets within a single page. - * Since memory pages are typically 4 or 8KB in size, 12-13 bits, - * this is plenty. */ -typedef uint16_t indx_t; - -#define MEGABYTE ((size_t)1 << 20) - -/*----------------------------------------------------------------------------*/ -/* Core structures for database and shared memory (i.e. format definition) */ -#pragma pack(push, 1) - -typedef union mdbx_safe64 { - volatile uint64_t inconsistent; -#if MDBX_64BIT_ATOMIC - volatile uint64_t atomic; -#endif /* MDBX_64BIT_ATOMIC */ - struct { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - volatile uint32_t low; - volatile uint32_t high; -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - volatile uint32_t high; - volatile uint32_t low; -#else -#error "FIXME: Unsupported byte order" -#endif /* __BYTE_ORDER__ */ - }; -} mdbx_safe64_t; - -#define SAFE64_INVALID_THRESHOLD UINT64_C(0xffffFFFF00000000) - -/* Information about a single database in the environment. */ -typedef struct MDBX_db { - uint16_t md_flags; /* see mdbx_dbi_open */ - uint16_t md_depth; /* depth of this tree */ - uint32_t md_xsize; /* also ksize for LEAF2 pages */ - pgno_t md_root; /* the root page of this tree */ - pgno_t md_branch_pages; /* number of internal pages */ - pgno_t md_leaf_pages; /* number of leaf pages */ - pgno_t md_overflow_pages; /* number of overflow pages */ - uint64_t md_seq; /* table sequence counter */ - uint64_t md_entries; /* number of data items */ - uint64_t md_mod_txnid; /* txnid of last commited modification */ -} MDBX_db; - -/* database size-related parameters */ -typedef struct mdbx_geo_t { - uint16_t grow; /* datafile growth step in pages */ - uint16_t shrink; /* datafile shrink threshold in pages */ - pgno_t lower; /* minimal size of datafile in pages */ - pgno_t upper; /* maximal size of datafile in pages */ - pgno_t now; /* current size of datafile in pages */ - pgno_t next; /* first unused page in the datafile, - * but actually the file may be shorter. */ -} mdbx_geo_t; - -/* Meta page content. - * A meta page is the start point for accessing a database snapshot. - * Pages 0-1 are meta pages. Transaction N writes meta page (N % 2). */ -typedef struct MDBX_meta { - /* Stamp identifying this as an MDBX file. - * It must be set to MDBX_MAGIC with MDBX_DATA_VERSION. */ - uint64_t mm_magic_and_version; - - /* txnid that committed this page, the first of a two-phase-update pair */ - mdbx_safe64_t mm_txnid_a; - - uint16_t mm_extra_flags; /* extra DB flags, zero (nothing) for now */ - uint8_t mm_validator_id; /* ID of checksum and page validation method, - * zero (nothing) for now */ - uint8_t mm_extra_pagehdr; /* extra bytes in the page header, - * zero (nothing) for now */ - - mdbx_geo_t mm_geo; /* database size-related parameters */ - - MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ - /* The size of pages used in this DB */ -#define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags - mdbx_canary mm_canary; - -#define MDBX_DATASIGN_NONE 0u -#define MDBX_DATASIGN_WEAK 1u -#define SIGN_IS_WEAK(sign) ((sign) == MDBX_DATASIGN_WEAK) -#define SIGN_IS_STEADY(sign) ((sign) > MDBX_DATASIGN_WEAK) -#define META_IS_WEAK(meta) SIGN_IS_WEAK((meta)->mm_datasync_sign) -#define META_IS_STEADY(meta) SIGN_IS_STEADY((meta)->mm_datasync_sign) - volatile uint64_t mm_datasync_sign; - - /* txnid that committed this page, the second of a two-phase-update pair */ - mdbx_safe64_t mm_txnid_b; - - /* Number of non-meta pages which were put in GC after COW. May be 0 in case - * DB was previously handled by libmdbx without corresponding feature. - * This value in couple with mr_snapshot_pages_retired allows fast estimation - * of "how much reader is restraining GC recycling". */ - uint64_t mm_pages_retired; -} MDBX_meta; - -/* Common header for all page types. The page type depends on mp_flags. - * - * P_BRANCH and P_LEAF pages have unsorted 'MDBX_node's at the end, with - * sorted mp_ptrs[] entries referring to them. Exception: P_LEAF2 pages - * omit mp_ptrs and pack sorted MDBX_DUPFIXED values after the page header. - * - * P_OVERFLOW records occupy one or more contiguous pages where only the - * first has a page header. They hold the real data of F_BIGDATA nodes. - * - * P_SUBP sub-pages are small leaf "pages" with duplicate data. - * A node with flag F_DUPDATA but not F_SUBDATA contains a sub-page. - * (Duplicate data can also go in sub-databases, which use normal pages.) - * - * P_META pages contain MDBX_meta, the start point of an MDBX snapshot. - * - * Each non-metapage up to MDBX_meta.mm_last_pg is reachable exactly once - * in the snapshot: Either used by a database or listed in a GC record. */ -typedef struct MDBX_page { - union { - struct MDBX_page *mp_next; /* for in-memory list of freed pages */ - uint64_t mp_validator; /* checksum of page content or a txnid during - * which the page has been updated */ - }; - uint16_t mp_leaf2_ksize; /* key size if this is a LEAF2 page */ -#define P_BRANCH 0x01 /* branch page */ -#define P_LEAF 0x02 /* leaf page */ -#define P_OVERFLOW 0x04 /* overflow page */ -#define P_META 0x08 /* meta page */ -#define P_DIRTY 0x10 /* dirty page, also set for P_SUBP pages */ -#define P_LEAF2 0x20 /* for MDBX_DUPFIXED records */ -#define P_SUBP 0x40 /* for MDBX_DUPSORT sub-pages */ -#define P_LOOSE 0x4000 /* page was dirtied then freed, can be reused */ -#define P_KEEP 0x8000 /* leave this page alone during spill */ - uint16_t mp_flags; - union { - struct { - indx_t mp_lower; /* lower bound of free space */ - indx_t mp_upper; /* upper bound of free space */ - }; - uint32_t mp_pages; /* number of overflow pages */ - }; - pgno_t mp_pgno; /* page number */ - - /* dynamic size */ - indx_t mp_ptrs[/* C99 */]; -} MDBX_page; - -/* Size of the page header, excluding dynamic data at the end */ -#define PAGEHDRSZ ((unsigned)offsetof(MDBX_page, mp_ptrs)) - -#pragma pack(pop) - -/* Reader Lock Table - * - * Readers don't acquire any locks for their data access. Instead, they - * simply record their transaction ID in the reader table. The reader - * mutex is needed just to find an empty slot in the reader table. The - * slot's address is saved in thread-specific data so that subsequent - * read transactions started by the same thread need no further locking to - * proceed. - * - * If MDBX_NOTLS is set, the slot address is not saved in thread-specific data. - * No reader table is used if the database is on a read-only filesystem. - * - * Since the database uses multi-version concurrency control, readers don't - * actually need any locking. This table is used to keep track of which - * readers are using data from which old transactions, so that we'll know - * when a particular old transaction is no longer in use. Old transactions - * that have discarded any data pages can then have those pages reclaimed - * for use by a later write transaction. - * - * The lock table is constructed such that reader slots are aligned with the - * processor's cache line size. Any slot is only ever used by one thread. - * This alignment guarantees that there will be no contention or cache - * thrashing as threads update their own slot info, and also eliminates - * any need for locking when accessing a slot. - * - * A writer thread will scan every slot in the table to determine the oldest - * outstanding reader transaction. Any freed pages older than this will be - * reclaimed by the writer. The writer doesn't use any locks when scanning - * this table. This means that there's no guarantee that the writer will - * see the most up-to-date reader info, but that's not required for correct - * operation - all we need is to know the upper bound on the oldest reader, - * we don't care at all about the newest reader. So the only consequence of - * reading stale information here is that old pages might hang around a - * while longer before being reclaimed. That's actually good anyway, because - * the longer we delay reclaiming old pages, the more likely it is that a - * string of contiguous pages can be found after coalescing old pages from - * many old transactions together. */ - -/* The actual reader record, with cacheline padding. */ -typedef struct MDBX_reader { - /* Current Transaction ID when this transaction began, or (txnid_t)-1. - * Multiple readers that start at the same time will probably have the - * same ID here. Again, it's not important to exclude them from - * anything; all we need to know is which version of the DB they - * started from so we can avoid overwriting any data used in that - * particular version. */ - mdbx_safe64_t /* txnid_t */ mr_txnid; - - /* The information we store in a single slot of the reader table. - * In addition to a transaction ID, we also record the process and - * thread ID that owns a slot, so that we can detect stale information, - * e.g. threads or processes that went away without cleaning up. - * - * NOTE: We currently don't check for stale records. - * We simply re-init the table when we know that we're the only process - * opening the lock file. */ - - /* The thread ID of the thread owning this txn. */ -#if MDBX_WORDBITS >= 64 - volatile uint64_t mr_tid; -#else - volatile uint32_t mr_tid; - volatile uint32_t mr_aba_curer; /* CSN to resolve ABA_problems on 32-bit arch, - unused for now */ -#endif - /* The process ID of the process owning this reader txn. */ - volatile uint32_t mr_pid; - - /* The number of pages used in the reader's MVCC snapshot, - * i.e. the value of meta->mm_geo.next and txn->mt_next_pgno */ - volatile pgno_t mr_snapshot_pages_used; - /* Number of retired pages at the time this reader starts transaction. So, - * at any time the difference mm_pages_retired - mr_snapshot_pages_retired - * will give the number of pages which this reader restraining from reuse. */ - volatile uint64_t mr_snapshot_pages_retired; -} MDBX_reader; - -/* The header for the reader table (a memory-mapped lock file). */ -typedef struct MDBX_lockinfo { - /* Stamp identifying this as an MDBX file. - * It must be set to MDBX_MAGIC with with MDBX_LOCK_VERSION. */ - uint64_t mti_magic_and_version; - - /* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */ - uint32_t mti_os_and_format; - - /* Flags which environment was opened. */ - volatile uint32_t mti_envmode; - - /* Threshold of un-synced-with-disk pages for auto-sync feature, - * zero means no-threshold, i.e. auto-sync is disabled. */ - volatile pgno_t mti_autosync_threshold; - - /* Low 32-bit of txnid with which meta-pages was synced, - * i.e. for sync-polling in the MDBX_NOMETASYNC mode. */ - volatile uint32_t mti_meta_sync_txnid; - - /* Period for timed auto-sync feature, i.e. at the every steady checkpoint - * the mti_unsynced_timeout sets to the current_time + mti_autosync_period. - * The time value is represented in a suitable system-dependent form, for - * example clock_gettime(CLOCK_BOOTTIME) or clock_gettime(CLOCK_MONOTONIC). - * Zero means timed auto-sync is disabled. */ - volatile uint64_t mti_autosync_period; - - /* Marker to distinguish uniqueness of DB/CLK.*/ - volatile uint64_t mti_bait_uniqueness; - - /* The analogue /proc/sys/kernel/random/boot_id or similar to determine - * whether the system was rebooted after the last use of the database files. - * If there was no reboot, but there is no need to rollback to the last - * steady sync point. Zeros mean that no relevant information is available - * from the system. */ - volatile bin128_t mti_bootid; - - alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ -#ifdef MDBX_OSAL_LOCK - /* Mutex protecting write-txn. */ - MDBX_OSAL_LOCK mti_wmutex; -#endif - - volatile txnid_t mti_oldest_reader; - - /* Timestamp of the last steady sync. Value is represented in a suitable - * system-dependent form, for example clock_gettime(CLOCK_BOOTTIME) or - * clock_gettime(CLOCK_MONOTONIC). */ - volatile uint64_t mti_sync_timestamp; - - /* Number un-synced-with-disk pages for auto-sync feature. */ - volatile pgno_t mti_unsynced_pages; - - /* Number of page which was discarded last time by madvise(MADV_FREE). */ - volatile pgno_t mti_discarded_tail; - - /* Timestamp of the last readers check. */ - volatile uint64_t mti_reader_check_timestamp; - - alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ - -#ifdef MDBX_OSAL_LOCK - /* Mutex protecting readers registration access to this table. */ - MDBX_OSAL_LOCK mti_rmutex; -#endif - - /* The number of slots that have been used in the reader table. - * This always records the maximum count, it is not decremented - * when readers release their slots. */ - volatile unsigned mti_numreaders; - volatile unsigned mti_readers_refresh_flag; - - alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ - MDBX_reader mti_readers[/* C99 */]; -} MDBX_lockinfo; - -/* Lockfile format signature: version, features and field layout */ -#define MDBX_LOCK_FORMAT \ - (MDBX_OSAL_LOCK_SIGN * 27733 + (unsigned)sizeof(MDBX_reader) * 13 + \ - (unsigned)offsetof(MDBX_reader, mr_snapshot_pages_used) * 251 + \ - (unsigned)offsetof(MDBX_lockinfo, mti_oldest_reader) * 83 + \ - (unsigned)offsetof(MDBX_lockinfo, mti_numreaders) * 37 + \ - (unsigned)offsetof(MDBX_lockinfo, mti_readers) * 29) - -#define MDBX_DATA_MAGIC ((MDBX_MAGIC << 8) + MDBX_DATA_VERSION) -#define MDBX_DATA_MAGIC_DEVEL ((MDBX_MAGIC << 8) + 255) - -#define MDBX_LOCK_MAGIC ((MDBX_MAGIC << 8) + MDBX_LOCK_VERSION) - -#ifndef MDBX_ASSUME_MALLOC_OVERHEAD -#define MDBX_ASSUME_MALLOC_OVERHEAD (sizeof(void *) * 2u) -#endif /* MDBX_ASSUME_MALLOC_OVERHEAD */ - -/* The maximum size of a database page. - * - * It is 64K, but value-PAGEHDRSZ must fit in MDBX_page.mp_upper. - * - * MDBX will use database pages < OS pages if needed. - * That causes more I/O in write transactions: The OS must - * know (read) the whole page before writing a partial page. - * - * Note that we don't currently support Huge pages. On Linux, - * regular data files cannot use Huge pages, and in general - * Huge pages aren't actually pageable. We rely on the OS - * demand-pager to read our data and page it out when memory - * pressure from other processes is high. So until OSs have - * actual paging support for Huge pages, they're not viable. */ -#define MAX_PAGESIZE MDBX_MAX_PAGESIZE -#define MIN_PAGESIZE MDBX_MIN_PAGESIZE - -#define MIN_MAPSIZE (MIN_PAGESIZE * MIN_PAGENO) -#if defined(_WIN32) || defined(_WIN64) -#define MAX_MAPSIZE32 UINT32_C(0x38000000) -#else -#define MAX_MAPSIZE32 UINT32_C(0x7ff80000) -#endif -#define MAX_MAPSIZE64 (MAX_PAGENO * (uint64_t)MAX_PAGESIZE) - -#if MDBX_WORDBITS >= 64 -#define MAX_MAPSIZE MAX_MAPSIZE64 -#define MDBX_READERS_LIMIT \ - ((65536 - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader)) -#else -#define MDBX_READERS_LIMIT 1024 -#define MAX_MAPSIZE MAX_MAPSIZE32 -#endif /* MDBX_WORDBITS */ - -/*----------------------------------------------------------------------------*/ -/* Two kind lists of pages (aka PNL) */ - -/* An PNL is an Page Number List, a sorted array of IDs. The first element of - * the array is a counter for how many actual page-numbers are in the list. - * PNLs are sorted in descending order, this allow cut off a page with lowest - * pgno (at the tail) just truncating the list */ -#define MDBX_PNL_ASCENDING 0 -typedef pgno_t *MDBX_PNL; - -#if MDBX_PNL_ASCENDING -#define MDBX_PNL_ORDERED(first, last) ((first) < (last)) -#define MDBX_PNL_DISORDERED(first, last) ((first) >= (last)) -#else -#define MDBX_PNL_ORDERED(first, last) ((first) > (last)) -#define MDBX_PNL_DISORDERED(first, last) ((first) <= (last)) -#endif - -/* List of txnid, only for MDBX_txn.tw.lifo_reclaimed */ -typedef txnid_t *MDBX_TXL; - -/* An Dirty-Page list item is an pgno/pointer pair. */ -typedef union MDBX_DP { - struct { - pgno_t pgno; - MDBX_page *ptr; - }; - struct { - unsigned sorted; - unsigned length; - }; -} MDBX_DP; - -/* An DPL (dirty-page list) is a sorted array of MDBX_DPs. - * The first element's length member is a count of how many actual - * elements are in the array. */ -typedef MDBX_DP *MDBX_DPL; - -/* PNL sizes - likely should be even bigger */ -#define MDBX_PNL_GRANULATE 1024 -#define MDBX_PNL_INITIAL \ - (MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t)) -#define MDBX_PNL_MAX \ - ((1u << 24) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t)) -#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 4) - -#define MDBX_TXL_GRANULATE 32 -#define MDBX_TXL_INITIAL \ - (MDBX_TXL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t)) -#define MDBX_TXL_MAX \ - ((1u << 17) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t)) - -#define MDBX_PNL_ALLOCLEN(pl) ((pl)[-1]) -#define MDBX_PNL_SIZE(pl) ((pl)[0]) -#define MDBX_PNL_FIRST(pl) ((pl)[1]) -#define MDBX_PNL_LAST(pl) ((pl)[MDBX_PNL_SIZE(pl)]) -#define MDBX_PNL_BEGIN(pl) (&(pl)[1]) -#define MDBX_PNL_END(pl) (&(pl)[MDBX_PNL_SIZE(pl) + 1]) - -#if MDBX_PNL_ASCENDING -#define MDBX_PNL_LEAST(pl) MDBX_PNL_FIRST(pl) -#define MDBX_PNL_MOST(pl) MDBX_PNL_LAST(pl) -#else -#define MDBX_PNL_LEAST(pl) MDBX_PNL_LAST(pl) -#define MDBX_PNL_MOST(pl) MDBX_PNL_FIRST(pl) -#endif - -#define MDBX_PNL_SIZEOF(pl) ((MDBX_PNL_SIZE(pl) + 1) * sizeof(pgno_t)) -#define MDBX_PNL_IS_EMPTY(pl) (MDBX_PNL_SIZE(pl) == 0) - -/*----------------------------------------------------------------------------*/ -/* Internal structures */ - -/* Auxiliary DB info. - * The information here is mostly static/read-only. There is - * only a single copy of this record in the environment. */ -typedef struct MDBX_dbx { - MDBX_val md_name; /* name of the database */ - MDBX_cmp_func *md_cmp; /* function for comparing keys */ - MDBX_cmp_func *md_dcmp; /* function for comparing data items */ -} MDBX_dbx; - -/* A database transaction. - * Every operation requires a transaction handle. */ -struct MDBX_txn { -#define MDBX_MT_SIGNATURE UINT32_C(0x93D53A31) - size_t mt_signature; - MDBX_txn *mt_parent; /* parent of a nested txn */ - /* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */ - MDBX_txn *mt_child; - mdbx_geo_t mt_geo; - /* next unallocated page */ -#define mt_next_pgno mt_geo.next - /* corresponding to the current size of datafile */ -#define mt_end_pgno mt_geo.now - - /* Transaction Flags */ - /* mdbx_txn_begin() flags */ -#define MDBX_TXN_BEGIN_FLAGS \ - (MDBX_NOMETASYNC | MDBX_NOSYNC | MDBX_MAPASYNC | MDBX_RDONLY | MDBX_TRYTXN) - /* internal txn flags */ -#define MDBX_TXN_FINISHED 0x01 /* txn is finished or never began */ -#define MDBX_TXN_ERROR 0x02 /* txn is unusable after an error */ -#define MDBX_TXN_DIRTY 0x04 /* must write, even if dirty list is empty */ -#define MDBX_TXN_SPILLS 0x08 /* txn or a parent has spilled pages */ -#define MDBX_TXN_HAS_CHILD 0x10 /* txn has an MDBX_txn.mt_child */ - /* most operations on the txn are currently illegal */ -#define MDBX_TXN_BLOCKED \ - (MDBX_TXN_FINISHED | MDBX_TXN_ERROR | MDBX_TXN_HAS_CHILD) - unsigned mt_flags; - /* The ID of this transaction. IDs are integers incrementing from 1. - * Only committed write transactions increment the ID. If a transaction - * aborts, the ID may be re-used by the next writer. */ - txnid_t mt_txnid; - MDBX_env *mt_env; /* the DB environment */ - /* Array of records for each DB known in the environment. */ - MDBX_dbx *mt_dbxs; - /* Array of MDBX_db records for each known DB */ - MDBX_db *mt_dbs; - /* Array of sequence numbers for each DB handle */ - unsigned *mt_dbiseqs; - - /* Transaction DB Flags */ -#define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */ -#define DB_STALE MDBX_TBL_STALE /* Named-DB record is older than txnID */ -#define DB_FRESH MDBX_TBL_FRESH /* Named-DB handle opened in this txn */ -#define DB_CREAT MDBX_TBL_CREAT /* Named-DB handle created in this txn */ -#define DB_VALID 0x10 /* DB handle is valid, see also MDBX_VALID */ -#define DB_USRVALID 0x20 /* As DB_VALID, but not set for FREE_DBI */ -#define DB_DUPDATA 0x40 /* DB is MDBX_DUPSORT data */ -#define DB_AUDITED 0x80 /* Internal flag for accounting during audit */ - /* In write txns, array of cursors for each DB */ - MDBX_cursor **mt_cursors; - /* Array of flags for each DB */ - uint8_t *mt_dbflags; - /* Number of DB records in use, or 0 when the txn is finished. - * This number only ever increments until the txn finishes; we - * don't decrement it when individual DB handles are closed. */ - MDBX_dbi mt_numdbs; - size_t mt_owner; /* thread ID that owns this transaction */ - mdbx_canary mt_canary; - - union { - struct { - /* For read txns: This thread/txn's reader table slot, or NULL. */ - MDBX_reader *reader; - } to; - struct { - pgno_t *reclaimed_pglist; /* Reclaimed GC pages */ - txnid_t last_reclaimed; /* ID of last used record */ - pgno_t loose_refund_wl /* FIXME: describe */; - /* dirtylist room: Dirty array size - dirty pages visible to this txn. - * Includes ancestor txns' dirty pages not hidden by other txns' - * dirty/spilled pages. Thus commit(nested txn) has room to merge - * dirtylist into mt_parent after freeing hidden mt_parent pages. */ - unsigned dirtyroom; - /* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */ - MDBX_DPL dirtylist; - /* The list of reclaimed txns from GC */ - MDBX_TXL lifo_reclaimed; - /* The list of pages that became unused during this transaction. */ - MDBX_PNL retired_pages; - /* The list of loose pages that became unused and may be reused - * in this transaction, linked through `mp_next`. */ - MDBX_page *loose_pages; - /* Number of loose pages (tw.loose_pages) */ - unsigned loose_count; - /* Number of retired to parent pages (tw.retired2parent_pages) */ - unsigned retired2parent_count; - /* The list of parent's txn dirty pages that retired (became unused) - * in this transaction, linked through `mp_next`. */ - MDBX_page *retired2parent_pages; - /* The sorted list of dirty pages we temporarily wrote to disk - * because the dirty list was full. page numbers in here are - * shifted left by 1, deleted slots have the LSB set. */ - MDBX_PNL spill_pages; - } tw; - }; -}; - -/* Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. - * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to - * raise this on a 64 bit machine. */ -#if MDBX_WORDBITS >= 64 -#define CURSOR_STACK 28 -#else -#define CURSOR_STACK 20 -#endif - -struct MDBX_xcursor; - -/* Cursors are used for all DB operations. - * A cursor holds a path of (page pointer, key index) from the DB - * root to a position in the DB, plus other state. MDBX_DUPSORT - * cursors include an xcursor to the current data item. Write txns - * track their cursors and keep them up to date when data moves. - * Exception: An xcursor's pointer to a P_SUBP page can be stale. - * (A node with F_DUPDATA but no F_SUBDATA contains a subpage). */ -struct MDBX_cursor { -#define MDBX_MC_SIGNATURE UINT32_C(0xFE05D5B1) -#define MDBX_MC_READY4CLOSE UINT32_C(0x2817A047) -#define MDBX_MC_WAIT4EOT UINT32_C(0x90E297A7) - uint32_t mc_signature; - /* The database handle this cursor operates on */ - MDBX_dbi mc_dbi; - /* Next cursor on this DB in this txn */ - MDBX_cursor *mc_next; - /* Backup of the original cursor if this cursor is a shadow */ - MDBX_cursor *mc_backup; - /* Context used for databases with MDBX_DUPSORT, otherwise NULL */ - struct MDBX_xcursor *mc_xcursor; - /* The transaction that owns this cursor */ - MDBX_txn *mc_txn; - /* The database record for this cursor */ - MDBX_db *mc_db; - /* The database auxiliary record for this cursor */ - MDBX_dbx *mc_dbx; - /* The mt_dbflag for this database */ - uint8_t *mc_dbflag; - uint16_t mc_snum; /* number of pushed pages */ - uint16_t mc_top; /* index of top page, normally mc_snum-1 */ - /* Cursor state flags. */ -#define C_INITIALIZED 0x01 /* cursor has been initialized and is valid */ -#define C_EOF 0x02 /* No more data */ -#define C_SUB 0x04 /* Cursor is a sub-cursor */ -#define C_DEL 0x08 /* last op was a cursor_del */ -#define C_UNTRACK 0x10 /* Un-track cursor when closing */ -#define C_RECLAIMING 0x20 /* GC lookup is prohibited */ -#define C_GCFREEZE 0x40 /* reclaimed_pglist must not be updated */ - unsigned mc_flags; /* see mdbx_cursor */ - MDBX_page *mc_pg[CURSOR_STACK]; /* stack of pushed pages */ - indx_t mc_ki[CURSOR_STACK]; /* stack of page indices */ -}; - -/* Context for sorted-dup records. - * We could have gone to a fully recursive design, with arbitrarily - * deep nesting of sub-databases. But for now we only handle these - * levels - main DB, optional sub-DB, sorted-duplicate DB. */ -typedef struct MDBX_xcursor { - /* A sub-cursor for traversing the Dup DB */ - MDBX_cursor mx_cursor; - /* The database record for this Dup DB */ - MDBX_db mx_db; - /* The auxiliary DB record for this Dup DB */ - MDBX_dbx mx_dbx; - /* The mt_dbflag for this Dup DB */ - uint8_t mx_dbflag; -} MDBX_xcursor; - -typedef struct MDBX_cursor_couple { - MDBX_cursor outer; - MDBX_xcursor inner; -} MDBX_cursor_couple; - -/* The database environment. */ -struct MDBX_env { -#define MDBX_ME_SIGNATURE UINT32_C(0x9A899641) - size_t me_signature; - mdbx_mmap_t me_dxb_mmap; /* The main data file */ -#define me_map me_dxb_mmap.dxb -#define me_fd me_dxb_mmap.fd - mdbx_mmap_t me_lck_mmap; /* The lock file */ -#define me_lfd me_lck_mmap.fd -#define me_lck me_lck_mmap.lck - - /* Failed to update the meta page. Probably an I/O error. */ -#define MDBX_FATAL_ERROR UINT32_C(0x80000000) - /* Additional flag for mdbx_sync_locked() */ -#define MDBX_SHRINK_ALLOWED UINT32_C(0x40000000) - /* Some fields are initialized. */ -#define MDBX_ENV_ACTIVE UINT32_C(0x20000000) - /* me_txkey is set */ -#define MDBX_ENV_TXKEY UINT32_C(0x10000000) - uint32_t me_flags; /* see mdbx_env */ - unsigned me_psize; /* DB page size, inited from me_os_psize */ - unsigned me_psize2log; /* log2 of DB page size */ - unsigned me_os_psize; /* OS page size, from mdbx_syspagesize() */ - unsigned me_maxreaders; /* size of the reader table */ - mdbx_fastmutex_t me_dbi_lock; - MDBX_dbi me_numdbs; /* number of DBs opened */ - MDBX_dbi me_maxdbs; /* size of the DB table */ - uint32_t me_pid; /* process ID of this env */ - mdbx_thread_key_t me_txkey; /* thread-key for readers */ - char *me_path; /* path to the DB files */ - void *me_pbuf; /* scratch area for DUPSORT put() */ - MDBX_txn *me_txn; /* current write transaction */ - MDBX_txn *me_txn0; /* prealloc'd write transaction */ -#ifdef MDBX_OSAL_LOCK - MDBX_OSAL_LOCK *me_wmutex; /* write-txn mutex */ -#endif - MDBX_dbx *me_dbxs; /* array of static DB info */ - uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */ - unsigned *me_dbiseqs; /* array of dbi sequence numbers */ - volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */ - MDBX_page *me_dpages; /* list of malloc'd blocks for re-use */ - /* PNL of pages that became unused in a write txn */ - MDBX_PNL me_retired_pages; - /* MDBX_DP of pages written during a write txn. Length MDBX_DPL_TXNFULL. */ - MDBX_DPL me_dirtylist; - /* Number of freelist items that can fit in a single overflow page */ - unsigned me_maxgc_ov1page; - /* Max size of a node on a page */ - unsigned me_nodemax; - unsigned me_maxkey_limit; /* max size of a key */ - uint32_t me_live_reader; /* have liveness lock in reader table */ - void *me_userctx; /* User-settable context */ - volatile uint64_t *me_sync_timestamp; - volatile uint64_t *me_autosync_period; - volatile pgno_t *me_unsynced_pages; - volatile pgno_t *me_autosync_threshold; - volatile pgno_t *me_discarded_tail; - volatile uint32_t *me_meta_sync_txnid; - MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */ - struct { -#ifdef MDBX_OSAL_LOCK - MDBX_OSAL_LOCK wmutex; -#endif - txnid_t oldest; - uint64_t sync_timestamp; - uint64_t autosync_period; - pgno_t autosync_pending; - pgno_t autosync_threshold; - pgno_t discarded_tail; - uint32_t meta_sync_txnid; - } me_lckless_stub; -#if MDBX_DEBUG - MDBX_assert_func *me_assert_func; /* Callback for assertion failures */ -#endif -#ifdef MDBX_USE_VALGRIND - int me_valgrind_handle; -#endif -#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) - pgno_t me_poison_edge; -#endif - MDBX_env *me_lcklist_next; - - /* struct me_dbgeo used for accepting db-geo params from user for the new - * database creation, i.e. when mdbx_env_set_geometry() was called before - * mdbx_env_open(). */ - struct { - size_t lower; /* minimal size of datafile */ - size_t upper; /* maximal size of datafile */ - size_t now; /* current size of datafile */ - size_t grow; /* step to grow datafile */ - size_t shrink; /* threshold to shrink datafile */ - } me_dbgeo; - -#if defined(_WIN32) || defined(_WIN64) - MDBX_srwlock me_remap_guard; - /* Workaround for LockFileEx and WriteFile multithread bug */ - CRITICAL_SECTION me_windowsbug_lock; -#else - mdbx_fastmutex_t me_remap_guard; -#endif -}; - -/*----------------------------------------------------------------------------*/ -/* Debug and Logging stuff */ - -#define MDBX_RUNTIME_FLAGS_INIT \ - ((MDBX_DEBUG) > 0) * MDBX_DBG_ASSERT + ((MDBX_DEBUG) > 1) * MDBX_DBG_AUDIT - -#ifndef mdbx_runtime_flags /* avoid override from tools */ -MDBX_INTERNAL_VAR uint8_t mdbx_runtime_flags; -#endif -#ifndef mdbx_runtime_flags /* avoid override from tools */ -MDBX_INTERNAL_VAR uint8_t mdbx_loglevel; -#endif -MDBX_INTERNAL_VAR MDBX_debug_func *mdbx_debug_logger; - -MDBX_INTERNAL_FUNC void mdbx_debug_log(int type, const char *function, int line, - const char *fmt, ...) - __printf_args(4, 5); - -MDBX_INTERNAL_FUNC void mdbx_panic(const char *fmt, ...) __printf_args(1, 2); - -#if MDBX_DEBUG - -#define mdbx_assert_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_ASSERT) - -#define mdbx_audit_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_AUDIT) - -#ifdef MDBX_LOGLEVEL_BUILD -#define mdbx_log_enabled(msg) \ - (msg <= MDBX_LOGLEVEL_BUILD && unlikely(msg <= mdbx_loglevel)) -#else -#define mdbx_log_enabled(msg) unlikely(msg <= mdbx_loglevel) -#endif /* MDBX_LOGLEVEL_BUILD */ - -#else /* MDBX_DEBUG */ - -#define mdbx_audit_enabled() (0) - -#if !defined(NDEBUG) || defined(MDBX_FORCE_ASSERT) -#define mdbx_assert_enabled() (1) -#else -#define mdbx_assert_enabled() (0) -#endif /* NDEBUG */ - -#ifdef MDBX_LOGLEVEL_BUILD -#define mdbx_log_enabled(msg) (msg <= MDBX_LOGLEVEL_BUILD) -#else -#define mdbx_log_enabled(msg) (0) -#endif /* MDBX_LOGLEVEL_BUILD */ - -#endif /* MDBX_DEBUG */ - -MDBX_INTERNAL_FUNC void mdbx_assert_fail(const MDBX_env *env, const char *msg, - const char *func, int line); - -#define mdbx_debug_extra(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_EXTRA)) \ - mdbx_debug_log(MDBX_LOG_EXTRA, __func__, __LINE__, fmt, __VA_ARGS__); \ - } while (0) - -#define mdbx_debug_extra_print(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_EXTRA)) \ - mdbx_debug_log(MDBX_LOG_EXTRA, NULL, 0, fmt, __VA_ARGS__); \ - } while (0) - -#define mdbx_trace(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_TRACE)) \ - mdbx_debug_log(MDBX_LOG_TRACE, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_debug(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_DEBUG)) \ - mdbx_debug_log(MDBX_LOG_DEBUG, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_debug_print(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_DEBUG)) \ - mdbx_debug_log(MDBX_LOG_DEBUG, NULL, 0, fmt, __VA_ARGS__); \ - } while (0) - -#define mdbx_verbose(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_VERBOSE)) \ - mdbx_debug_log(MDBX_LOG_VERBOSE, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_notice(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_NOTICE)) \ - mdbx_debug_log(MDBX_LOG_NOTICE, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_warning(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_WARN)) \ - mdbx_debug_log(MDBX_LOG_WARN, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_error(fmt, ...) \ - do { \ - if (mdbx_log_enabled(MDBX_LOG_ERROR)) \ - mdbx_debug_log(MDBX_LOG_ERROR, __func__, __LINE__, fmt "\n", \ - __VA_ARGS__); \ - } while (0) - -#define mdbx_fatal(fmt, ...) \ - mdbx_debug_log(MDBX_LOG_FATAL, __func__, __LINE__, fmt "\n", __VA_ARGS__); - -#define mdbx_ensure_msg(env, expr, msg) \ - do { \ - if (unlikely(!(expr))) \ - mdbx_assert_fail(env, msg, __func__, __LINE__); \ - } while (0) - -#define mdbx_ensure(env, expr) mdbx_ensure_msg(env, expr, #expr) - -/* assert(3) variant in environment context */ -#define mdbx_assert(env, expr) \ - do { \ - if (mdbx_assert_enabled()) \ - mdbx_ensure(env, expr); \ - } while (0) - -/* assert(3) variant in cursor context */ -#define mdbx_cassert(mc, expr) mdbx_assert((mc)->mc_txn->mt_env, expr) - -/* assert(3) variant in transaction context */ -#define mdbx_tassert(txn, expr) mdbx_assert((txn)->mt_env, expr) - -#ifndef MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#undef assert -#define assert(expr) mdbx_assert(NULL, expr) -#endif - -/*----------------------------------------------------------------------------*/ -/* Internal prototypes */ - -MDBX_INTERNAL_FUNC int mdbx_reader_check0(MDBX_env *env, int rlocked, - int *dead); -MDBX_INTERNAL_FUNC int mdbx_rthc_alloc(mdbx_thread_key_t *key, - MDBX_reader *begin, MDBX_reader *end); -MDBX_INTERNAL_FUNC void mdbx_rthc_remove(const mdbx_thread_key_t key); - -MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); -MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); -MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); - -#define MDBX_IS_ERROR(rc) \ - ((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE) - -/* Internal error codes, not exposed outside libmdbx */ -#define MDBX_NO_ROOT (MDBX_LAST_ERRCODE + 10) - -/* Debuging output value of a cursor DBI: Negative in a sub-cursor. */ -#define DDBI(mc) \ - (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) - -/* Key size which fits in a DKBUF. */ -#define DKBUF_MAXKEYSIZE 511 /* FIXME */ - -#if MDBX_DEBUG -#define DKBUF char _kbuf[DKBUF_MAXKEYSIZE * 4 + 2] -#define DKEY(x) mdbx_dump_val(x, _kbuf, DKBUF_MAXKEYSIZE * 2 + 1) -#define DVAL(x) \ - mdbx_dump_val(x, _kbuf + DKBUF_MAXKEYSIZE * 2 + 1, DKBUF_MAXKEYSIZE * 2 + 1) -#else -#define DKBUF ((void)(0)) -#define DKEY(x) ("-") -#define DVAL(x) ("-") -#endif - -/* An invalid page number. - * Mainly used to denote an empty tree. */ -#define P_INVALID (~(pgno_t)0) - -/* Test if the flags f are set in a flag word w. */ -#define F_ISSET(w, f) (((w) & (f)) == (f)) - -/* Round n up to an even number. */ -#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */ - -/* Default size of memory map. - * This is certainly too small for any actual applications. Apps should - * always set the size explicitly using mdbx_env_set_mapsize(). */ -#define DEFAULT_MAPSIZE MEGABYTE - -/* Number of slots in the reader table. - * This value was chosen somewhat arbitrarily. The 61 is a prime number, - * and such readers plus a couple mutexes fit into single 4KB page. - * Applications should set the table size using mdbx_env_set_maxreaders(). */ -#define DEFAULT_READERS 61 - -/* Test if a page is a leaf page */ -#define IS_LEAF(p) (((p)->mp_flags & P_LEAF) != 0) -/* Test if a page is a LEAF2 page */ -#define IS_LEAF2(p) unlikely(((p)->mp_flags & P_LEAF2) != 0) -/* Test if a page is a branch page */ -#define IS_BRANCH(p) (((p)->mp_flags & P_BRANCH) != 0) -/* Test if a page is an overflow page */ -#define IS_OVERFLOW(p) unlikely(((p)->mp_flags & P_OVERFLOW) != 0) -/* Test if a page is a sub page */ -#define IS_SUBP(p) (((p)->mp_flags & P_SUBP) != 0) -/* Test if a page is dirty */ -#define IS_DIRTY(p) (((p)->mp_flags & P_DIRTY) != 0) - -#define PAGETYPE(p) ((p)->mp_flags & (P_BRANCH | P_LEAF | P_LEAF2 | P_OVERFLOW)) - -/* Header for a single key/data pair within a page. - * Used in pages of type P_BRANCH and P_LEAF without P_LEAF2. - * We guarantee 2-byte alignment for 'MDBX_node's. - * - * mn_lo and mn_hi are used for data size on leaf nodes, and for child - * pgno on branch nodes. On 64 bit platforms, mn_flags is also used - * for pgno. (Branch nodes have no flags). Lo and hi are in host byte - * order in case some accesses can be optimized to 32-bit word access. - * - * Leaf node flags describe node contents. F_BIGDATA says the node's - * data part is the page number of an overflow page with actual data. - * F_DUPDATA and F_SUBDATA can be combined giving duplicate data in - * a sub-page/sub-database, and named databases (just F_SUBDATA). */ -typedef struct MDBX_node { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - union { - struct { - uint16_t mn_lo, mn_hi; /* part of data size or pgno */ - }; - uint32_t mn_dsize; - uint32_t mn_pgno32; - }; - uint8_t mn_flags; /* see mdbx_node flags */ - uint8_t mn_extra; - uint16_t mn_ksize; /* key size */ -#else - uint16_t mn_ksize; /* key size */ - uint8_t mn_extra; - uint8_t mn_flags; /* see mdbx_node flags */ - union { - uint32_t mn_pgno32; - uint32_t mn_dsize; - struct { - uint16_t mn_hi, mn_lo; /* part of data size or pgno */ - }; - }; -#endif - - /* mdbx_node Flags */ -#define F_BIGDATA 0x01 /* data put on overflow page */ -#define F_SUBDATA 0x02 /* data is a sub-database */ -#define F_DUPDATA 0x04 /* data has duplicates */ - - /* valid flags for mdbx_node_add() */ -#define NODE_ADD_FLAGS (F_DUPDATA | F_SUBDATA | MDBX_RESERVE | MDBX_APPEND) - uint8_t mn_data[/* C99 */]; /* key and data are appended here */ -} MDBX_node; - -#define MDBX_VALID 0x8000 /* DB handle is valid, for me_dbflags */ -#define PERSISTENT_FLAGS (0xffff & ~(MDBX_VALID)) -/* mdbx_dbi_open() flags */ -#define VALID_FLAGS \ - (MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_INTEGERKEY | MDBX_DUPFIXED | \ - MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_CREATE) - -/* max number of pages to commit in one writev() call */ -#define MDBX_COMMIT_PAGES 64 -#if defined(IOV_MAX) && IOV_MAX < MDBX_COMMIT_PAGES /* sysconf(_SC_IOV_MAX) */ -#undef MDBX_COMMIT_PAGES -#define MDBX_COMMIT_PAGES IOV_MAX -#endif - -/* - * / - * | -1, a < b - * CMP2INT(a,b) = < 0, a == b - * | 1, a > b - * \ - */ -#if 1 -/* LY: fast enough on most systems */ -#define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) -#else -#define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) -#endif - -/* Do not spill pages to disk if txn is getting full, may fail instead */ -#define MDBX_NOSPILL 0x8000 - -static __maybe_unused __inline pgno_t pgno_add(pgno_t base, pgno_t augend) { - assert(base <= MAX_PAGENO); - return (augend < MAX_PAGENO - base) ? base + augend : MAX_PAGENO; -} - -static __maybe_unused __inline pgno_t pgno_sub(pgno_t base, pgno_t subtrahend) { - assert(base >= MIN_PAGENO); - return (subtrahend < base - MIN_PAGENO) ? base - subtrahend : MIN_PAGENO; -} - -static __maybe_unused __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} diff --git a/src/contrib/db/libmdbx/src/elements/lck-posix.c b/src/contrib/db/libmdbx/src/elements/lck-posix.c deleted file mode 100644 index 147778d..0000000 --- a/src/contrib/db/libmdbx/src/elements/lck-posix.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "internals.h" - -/*----------------------------------------------------------------------------*/ -/* global constructor/destructor */ - -#if defined(__linux__) || defined(__gnu_linux__) -#include -#ifndef MDBX_ALLOY -uint32_t mdbx_linux_kernel_version; -#endif /* MDBX_ALLOY */ -#endif /* Linux */ - -static __cold __attribute__((__constructor__)) void -mdbx_global_constructor(void) { -#if defined(__linux__) || defined(__gnu_linux__) - struct utsname buffer; - if (uname(&buffer) == 0) { - int i = 0; - char *p = buffer.release; - while (*p && i < 4) { - if (*p >= '0' && *p <= '9') { - long number = strtol(p, &p, 10); - if (number > 0) { - if (number > 255) - number = 255; - mdbx_linux_kernel_version += number << (24 - i * 8); - } - ++i; - } else { - ++p; - } - } - } -#endif /* Linux */ - - mdbx_rthc_global_init(); -} - -static __cold __attribute__((__destructor__)) void -mdbx_global_destructor(void) { - mdbx_rthc_global_dtor(); -} - -/*----------------------------------------------------------------------------*/ -/* lck */ - -/* ОпиÑание реализации блокировок Ð´Ð»Ñ POSIX & Linux: - * - * lck-файл отображаетÑÑ Ð² памÑть, в нём организуетÑÑ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° читателей и - * размещаютÑÑ ÑовмеÑтно иÑпользуемые posix-мьютекÑÑ‹ (futex). ПоÑредÑтвом - * Ñтих мьютекÑов (Ñм struct MDBX_lockinfo) реализуютÑÑ: - * - Блокировка таблицы читателей Ð´Ð»Ñ Ñ€ÐµÐ³Ð¸Ñтрации, - * Ñ‚.е. функции mdbx_rdt_lock() и mdbx_rdt_unlock(). - * - Блокировка БД Ð´Ð»Ñ Ð¿Ð¸ÑˆÑƒÑ‰Ð¸Ñ… транзакций, - * Ñ‚.е. функции mdbx_txn_lock() и mdbx_txn_unlock(). - * - * ОÑтальной функционал реализуетÑÑ Ð¾Ñ‚Ð´ÐµÐ»ÑŒÐ½Ð¾ поÑредÑтвом файловых блокировок: - * - Первоначальный захват БД в режиме exclusive/shared и поÑледующий перевод - * в операционный режим, функции mdbx_lck_seize() и mdbx_lck_downgrade(). - * - Проверка приÑутÑтвие процеÑÑов-читателей, - * Ñ‚.е. функции mdbx_rpid_set(), mdbx_rpid_clear() и mdbx_rpid_check(). - * - * Ð”Ð»Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ файлов иÑпользуетÑÑ fcntl(F_SETLK), так как: - * - lockf() оперирует только ÑкÑклюзивной блокировкой и требует - * Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° в RW-режиме. - * - flock() не гарантирует атомарноÑти при Ñмене блокировок - * и оперирует только вÑем файлом целиком. - * - Ð”Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑÑов-читателей иÑпользуютÑÑ Ð¾Ð´Ð½Ð¾Ð±Ð°Ð¹Ñ‚Ð¾Ð²Ñ‹Ðµ - * range-блокировки lck-файла поÑредÑтвом fcntl(F_SETLK). При Ñтом - * в качеÑтве позиции иÑпользуетÑÑ pid процеÑÑа-читателÑ. - * - Ð”Ð»Ñ Ð¿ÐµÑ€Ð²Ð¾Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ захвата и shared/exclusive выполнÑетÑÑ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ° - * оÑновного файла БД и при уÑпехе lck-файла. - * - * ---------------------------------------------------------------------------- - * УДЕРЖИВÐЕМЫЕ БЛОКИРОВКИ Ð’ ЗÐВИСИМОСТИ ОТ РЕЖИМРИ СОСТОЯÐИЯ - * - * ЭкÑклюзивный режим без lck-файла: - * = заблокирован веÑÑŒ dxb-файл поÑредÑтвом F_RDLCK или F_WRLCK, - * в завиÑимоÑти от MDBX_RDONLY. - * - * Ðе-операционный режим на Ð²Ñ€ÐµÐ¼Ñ Ð¿ÐµÑ€Ðµ-инициализации и разрушении lck-файла: - * = F_WRLCK блокировка первого байта lck-файла, другие процеÑÑÑ‹ ждут её - * ÑнÑÑ‚Ð¸Ñ Ð¿Ñ€Ð¸ получении F_RDLCK через F_SETLKW. - * - блокировки dxb-файла могут менÑтьÑÑ Ð´Ð¾ ÑнÑтие ÑкÑклюзивной блокировки - * lck-файла: - * + Ð´Ð»Ñ ÐЕ-ÑкÑклюзивного режима блокировка pid-байта в dxb-файле - * поÑредÑтвом F_RDLCK или F_WRLCK, в завиÑимоÑти от MDBX_RDONLY. - * + Ð´Ð»Ñ Ð­ÐšÐ¡ÐšÐ›Ð®Ð—Ð˜Ð’ÐОГО режима блокировка pid-байта вÑего dxb-файла - * поÑредÑтвом F_RDLCK или F_WRLCK, в завиÑимоÑти от MDBX_RDONLY. - * - * ОПЕРÐЦИОÐÐЫЙ режим Ñ lck-файлом: - * = F_RDLCK блокировка первого байта lck-файла, другие процеÑÑÑ‹ не могут - * получить F_WRLCK и таким образом видÑÑ‚ что БД иÑпользуетÑÑ. - * + F_WRLCK блокировка pid-байта в clk-файле поÑле первой транзакции чтениÑ. - * + Ð´Ð»Ñ ÐЕ-ÑкÑклюзивного режима блокировка pid-байта в dxb-файле - * поÑредÑтвом F_RDLCK или F_WRLCK, в завиÑимоÑти от MDBX_RDONLY. - * + Ð´Ð»Ñ Ð­ÐšÐ¡ÐšÐ›Ð®Ð—Ð˜Ð’ÐОГО режима блокировка pid-байта вÑего dxb-файла - * поÑредÑтвом F_RDLCK или F_WRLCK, в завиÑимоÑти от MDBX_RDONLY. - */ - -#if MDBX_USE_OFDLOCKS -static int op_setlk, op_setlkw, op_getlk; -static void __cold choice_fcntl() { - assert(!op_setlk && !op_setlkw && !op_getlk); - if ((mdbx_runtime_flags & MDBX_DBG_LEGACY_MULTIOPEN) == 0 -#if defined(__linux__) || defined(__gnu_linux__) - && mdbx_linux_kernel_version > - 0x030f0000 /* OFD locks are available since 3.15, but engages here - only for 3.16 and larer kernels (LTS) for reliability reasons */ -#endif /* linux */ - ) { - op_setlk = F_OFD_SETLK; - op_setlkw = F_OFD_SETLKW; - op_getlk = F_OFD_GETLK; - return; - } - op_setlk = F_SETLK; - op_setlkw = F_SETLKW; - op_getlk = F_GETLK; -} -#else -#define op_setlk F_SETLK -#define op_setlkw F_SETLKW -#define op_getlk F_GETLK -#endif /* MDBX_USE_OFDLOCKS */ - -#ifndef OFF_T_MAX -#define OFF_T_MAX \ - ((sizeof(off_t) > 4 ? INT64_MAX : INT32_MAX) & ~(size_t)0xffff) -#endif - -static int lck_op(mdbx_filehandle_t fd, int cmd, int lck, off_t offset, - off_t len) { - mdbx_jitter4testing(true); - for (;;) { - struct flock lock_op; - memset(&lock_op, 0, sizeof(lock_op)); - lock_op.l_type = lck; - lock_op.l_whence = SEEK_SET; - lock_op.l_start = offset; - lock_op.l_len = len; - int rc = fcntl(fd, cmd, &lock_op); - mdbx_jitter4testing(true); - if (rc != -1) { - if (cmd == op_getlk) { - /* Checks reader by pid. Returns: - * MDBX_RESULT_TRUE - if pid is live (unable to acquire lock) - * MDBX_RESULT_FALSE - if pid is dead (lock acquired). */ - return (lock_op.l_type == F_UNLCK) ? MDBX_RESULT_FALSE - : MDBX_RESULT_TRUE; - } - return MDBX_SUCCESS; - } - rc = errno; - if (rc != EINTR || cmd == op_setlkw) { - mdbx_assert(nullptr, MDBX_IS_ERROR(rc)); - return rc; - } - } -} - -MDBX_INTERNAL_FUNC int mdbx_rpid_set(MDBX_env *env) { - assert(env->me_lfd != INVALID_HANDLE_VALUE); - assert(env->me_pid > 0); - if (unlikely(mdbx_getpid() != env->me_pid)) - return MDBX_PANIC; - return lck_op(env->me_lfd, op_setlk, F_WRLCK, env->me_pid, 1); -} - -MDBX_INTERNAL_FUNC int mdbx_rpid_clear(MDBX_env *env) { - assert(env->me_lfd != INVALID_HANDLE_VALUE); - assert(env->me_pid > 0); - return lck_op(env->me_lfd, op_setlk, F_UNLCK, env->me_pid, 1); -} - -MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid) { - assert(env->me_lfd != INVALID_HANDLE_VALUE); - assert(pid > 0); - return lck_op(env->me_lfd, op_getlk, F_WRLCK, pid, 1); -} - -/*---------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) { - assert(env->me_fd != INVALID_HANDLE_VALUE); - if (unlikely(mdbx_getpid() != env->me_pid)) - return MDBX_PANIC; -#if MDBX_USE_OFDLOCKS - if (unlikely(op_setlk == 0)) - choice_fcntl(); -#endif /* MDBX_USE_OFDLOCKS */ - - int rc; - if (env->me_lfd == INVALID_HANDLE_VALUE) { - /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ - rc = - lck_op(env->me_fd, op_setlk, - (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, OFF_T_MAX); - if (rc != MDBX_SUCCESS) { - mdbx_error("%s(%s) failed: errcode %u", __func__, "without-lck", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; - } - return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */; - } - - /* Firstly try to get exclusive locking. */ - rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1); - if (rc == MDBX_SUCCESS) { - continue_dxb_exclusive: - rc = - lck_op(env->me_fd, op_setlk, - (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, OFF_T_MAX); - if (rc == MDBX_SUCCESS) - return MDBX_RESULT_TRUE /* Done: return with exclusive locking. */; - - /* the cause may be a collision with POSIX's file-lock recovery. */ - if (!(rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK || - rc == EDEADLK)) { - mdbx_error("%s(%s) failed: errcode %u", __func__, "dxb-exclusive", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; - } - - /* Fallback to lck-shared */ - rc = lck_op(env->me_lfd, op_setlk, F_RDLCK, 0, 1); - if (rc != MDBX_SUCCESS) { - mdbx_error("%s(%s) failed: errcode %u", __func__, "fallback-shared", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; - } - /* Done: return with shared locking. */ - return MDBX_RESULT_FALSE; - } - - /* Wait for lck-shared now. */ - /* Here may be await during transient processes, for instance until another - * competing process doesn't call lck_downgrade(). */ - rc = lck_op(env->me_lfd, op_setlkw, F_RDLCK, 0, 1); - if (rc != MDBX_SUCCESS) { - mdbx_error("%s(%s) failed: errcode %u", __func__, "try-shared", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; - } - - /* Lock against another process operating in without-lck or exclusive mode. */ - rc = - lck_op(env->me_fd, op_setlk, - (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, env->me_pid, 1); - if (rc != MDBX_SUCCESS) { - mdbx_error("%s(%s) failed: errcode %u", __func__, - "lock-against-without-lck", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; - } - - /* got shared, retry exclusive */ - rc = lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, 1); - if (rc == MDBX_SUCCESS) - goto continue_dxb_exclusive; - - if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK || - rc == EDEADLK) - return MDBX_RESULT_FALSE /* Done: exclusive is unavailable, - but shared locks are alive. */ - ; - - mdbx_error("%s(%s) failed: errcode %u", __func__, "try-exclusive", rc); - mdbx_assert(env, MDBX_IS_ERROR(rc)); - return rc; -} - -MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env) { - assert(env->me_lfd != INVALID_HANDLE_VALUE); - if (unlikely(mdbx_getpid() != env->me_pid)) - return MDBX_PANIC; - - int rc = MDBX_SUCCESS; - if ((env->me_flags & MDBX_EXCLUSIVE) == 0) { - rc = lck_op(env->me_fd, op_setlk, F_UNLCK, 0, env->me_pid); - if (rc == MDBX_SUCCESS) - rc = lck_op(env->me_fd, op_setlk, F_UNLCK, env->me_pid + 1, - OFF_T_MAX - env->me_pid - 1); - } - if (rc == MDBX_SUCCESS) - rc = lck_op(env->me_lfd, op_setlk, F_RDLCK, 0, 1); - if (unlikely(rc != 0)) { - mdbx_error("%s(%s) failed: errcode %u", __func__, "lck", rc); - assert(MDBX_IS_ERROR(rc)); - } - return rc; -} - -MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env, - MDBX_env *inprocess_neighbor) { - if (unlikely(mdbx_getpid() != env->me_pid)) - return MDBX_PANIC; - - int rc = MDBX_SUCCESS; - if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor && - env->me_lck && - /* try get exclusive access */ - lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, OFF_T_MAX) == 0 && - lck_op(env->me_fd, op_setlk, - (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, OFF_T_MAX)) { - mdbx_verbose("%s: got exclusive, drown mutexes", __func__); - rc = pthread_mutex_destroy(&env->me_lck->mti_rmutex); - if (rc == 0) - rc = pthread_mutex_destroy(&env->me_lck->mti_wmutex); - mdbx_assert(env, rc == 0); - if (rc == 0) { - memset(env->me_lck, 0x81, sizeof(MDBX_lockinfo)); - msync(env->me_lck, env->me_os_psize, MS_ASYNC); - } - mdbx_jitter4testing(false); - } - - /* 1) POSIX's fcntl() locks (i.e. when op_setlk == F_SETLK) should be restored - * after file was closed. - * - * 2) File locks would be released (by kernel) while the file-descriptors will - * be closed. But to avoid false-positive EACCESS and EDEADLK from the kernel, - * locks should be released here explicitly with properly order. */ - - /* close dxb and restore lock */ - if (env->me_fd != INVALID_HANDLE_VALUE) { - if (unlikely(close(env->me_fd) != 0) && rc == MDBX_SUCCESS) - rc = errno; - env->me_fd = INVALID_HANDLE_VALUE; - if (op_setlk == F_SETLK && inprocess_neighbor && rc == MDBX_SUCCESS) { - /* restore file-lock */ - rc = lck_op( - inprocess_neighbor->me_fd, F_SETLKW, - (inprocess_neighbor->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, - (inprocess_neighbor->me_flags & MDBX_EXCLUSIVE) - ? 0 - : inprocess_neighbor->me_pid, - (inprocess_neighbor->me_flags & MDBX_EXCLUSIVE) ? OFF_T_MAX : 1); - } - } - - /* close clk and restore locks */ - if (env->me_lfd != INVALID_HANDLE_VALUE) { - if (unlikely(close(env->me_lfd) != 0) && rc == MDBX_SUCCESS) - rc = errno; - env->me_lfd = INVALID_HANDLE_VALUE; - if (op_setlk == F_SETLK && inprocess_neighbor && rc == MDBX_SUCCESS) { - /* restore file-locks */ - rc = lck_op(inprocess_neighbor->me_lfd, F_SETLKW, F_RDLCK, 0, 1); - if (rc == MDBX_SUCCESS && inprocess_neighbor->me_live_reader) - rc = mdbx_rpid_set(inprocess_neighbor); - } - } - - if (inprocess_neighbor && rc != MDBX_SUCCESS) - inprocess_neighbor->me_flags |= MDBX_FATAL_ERROR; - return rc; -} - -/*---------------------------------------------------------------------------*/ - -static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, - const int rc); - -MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env, - MDBX_env *inprocess_neighbor, - int global_uniqueness_flag) { - if (inprocess_neighbor) - return MDBX_SUCCESS /* currently don't need any initialization - if LCK already opened/used inside current process */ - ; - - /* FIXME: Unfortunately, there is no other reliable way but to long testing - * on each platform. On the other hand, behavior like FreeBSD is incorrect - * and we can expect it to be rare. Moreover, even on FreeBSD without - * additional in-process initialization, the probability of an problem - * occurring is vanishingly small, and the symptom is a return of EINVAL - * while locking a mutex. In other words, in the worst case, the problem - * results in an EINVAL error at the start of the transaction, but NOT data - * loss, nor database corruption, nor other fatal troubles. Thus, the code - * below I am inclined to think the workaround for erroneous platforms (like - * FreeBSD), rather than a defect of libmdbx. */ -#if defined(__FreeBSD__) - /* seems that shared mutexes on FreeBSD required in-process initialization */ - (void)global_uniqueness_flag; -#else - /* shared mutexes on many other platforms (including Darwin and Linux's - * futexes) doesn't need any addition in-process initialization */ - if (global_uniqueness_flag != MDBX_RESULT_TRUE) - return MDBX_SUCCESS; -#endif - - pthread_mutexattr_t ma; - int rc = pthread_mutexattr_init(&ma); - if (rc) - return rc; - - rc = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); - if (rc) - goto bailout; - -#if MDBX_USE_ROBUST -#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ - !defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L - rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP); -#else - rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); -#endif - if (rc) - goto bailout; -#endif /* MDBX_USE_ROBUST */ - -#if _POSIX_C_SOURCE >= 199506L && !defined(MDBX_SAFE4QEMU) - rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT); - if (rc == ENOTSUP) - rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE); - if (rc) - goto bailout; -#endif /* PTHREAD_PRIO_INHERIT */ - - rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); - if (rc) - goto bailout; - - rc = pthread_mutex_init(&env->me_lck->mti_rmutex, &ma); - if (rc) - goto bailout; - rc = pthread_mutex_init(&env->me_lck->mti_wmutex, &ma); - -bailout: - pthread_mutexattr_destroy(&ma); - return rc; -} - -static int mdbx_robust_lock(MDBX_env *env, pthread_mutex_t *mutex) { - mdbx_jitter4testing(true); - int rc = pthread_mutex_lock(mutex); - if (unlikely(rc != 0)) - rc = mdbx_mutex_failed(env, mutex, rc); - return rc; -} - -static int mdbx_robust_trylock(MDBX_env *env, pthread_mutex_t *mutex) { - mdbx_jitter4testing(true); - int rc = pthread_mutex_trylock(mutex); - if (unlikely(rc != 0 && rc != EBUSY)) - rc = mdbx_mutex_failed(env, mutex, rc); - return (rc != EBUSY) ? rc : MDBX_BUSY; -} - -static int mdbx_robust_unlock(MDBX_env *env, pthread_mutex_t *mutex) { - int rc = pthread_mutex_unlock(mutex); - mdbx_jitter4testing(true); - if (unlikely(rc != 0)) - env->me_flags |= MDBX_FATAL_ERROR; - return rc; -} - -MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env) { - mdbx_trace("%s", ">>"); - int rc = mdbx_robust_lock(env, &env->me_lck->mti_rmutex); - mdbx_trace("<< rc %d", rc); - return rc; -} - -MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) { - mdbx_trace("%s", ">>"); - int rc = mdbx_robust_unlock(env, &env->me_lck->mti_rmutex); - mdbx_trace("<< rc %d", rc); - if (unlikely(MDBX_IS_ERROR(rc))) - mdbx_panic("%s() failed: errcode %d\n", __func__, rc); -} - -int mdbx_txn_lock(MDBX_env *env, bool dontwait) { - mdbx_trace("%s", ">>"); - int rc = dontwait ? mdbx_robust_trylock(env, env->me_wmutex) - : mdbx_robust_lock(env, env->me_wmutex); - mdbx_trace("<< rc %d", rc); - return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS; -} - -void mdbx_txn_unlock(MDBX_env *env) { - mdbx_trace("%s", ">>"); - int rc = mdbx_robust_unlock(env, env->me_wmutex); - mdbx_trace("<< rc %d", rc); - if (unlikely(MDBX_IS_ERROR(rc))) - mdbx_panic("%s() failed: errcode %d\n", __func__, rc); -} - -static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, - const int err) { - int rc = err; -#if MDBX_USE_ROBUST - if (err == EOWNERDEAD) { - /* We own the mutex. Clean up after dead previous owner. */ - - int rlocked = (env->me_lck && mutex == &env->me_lck->mti_rmutex); - rc = MDBX_SUCCESS; - if (!rlocked) { - if (unlikely(env->me_txn)) { - /* env is hosed if the dead thread was ours */ - env->me_flags |= MDBX_FATAL_ERROR; - env->me_txn = NULL; - rc = MDBX_PANIC; - } - } - mdbx_notice("%cmutex owner died, %s", (rlocked ? 'r' : 'w'), - (rc ? "this process' env is hosed" : "recovering")); - - int check_rc = mdbx_reader_check0(env, rlocked, NULL); - check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc; - -#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ - !defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L - int mreco_rc = pthread_mutex_consistent_np(mutex); -#else - int mreco_rc = pthread_mutex_consistent(mutex); -#endif - check_rc = (mreco_rc == 0) ? check_rc : mreco_rc; - - if (unlikely(mreco_rc)) - mdbx_error("mutex recovery failed, %s", mdbx_strerror(mreco_rc)); - - rc = (rc == MDBX_SUCCESS) ? check_rc : rc; - if (MDBX_IS_ERROR(rc)) - pthread_mutex_unlock(mutex); - return rc; - } -#else - (void)mutex; -#endif /* MDBX_USE_ROBUST */ - - mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err)); - if (rc != EDEADLK) - env->me_flags |= MDBX_FATAL_ERROR; - return rc; -} diff --git a/src/contrib/db/libmdbx/src/elements/lck-windows.c b/src/contrib/db/libmdbx/src/elements/lck-windows.c deleted file mode 100644 index 5d74bb8..0000000 --- a/src/contrib/db/libmdbx/src/elements/lck-windows.c +++ /dev/null @@ -1,777 +0,0 @@ -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "internals.h" - -/* PREAMBLE FOR WINDOWS: - * - * We are not concerned for performance here. - * If you are running Windows a performance could NOT be the goal. - * Otherwise please use Linux. - * - * Regards, - * LY - */ - -static void mdbx_winnt_import(void); - -#if MDBX_BUILD_SHARED_LIBRARY -#if MDBX_AVOID_CRT && defined(NDEBUG) -/* DEBUG/CHECKED builds still require MSVC's CRT for runtime checks. - * - * Define dll's entry point only for Release build when NDEBUG is defined and - * MDBX_AVOID_CRT=ON. if the entry point isn't defined then MSVC's will - * automatically use DllMainCRTStartup() from CRT library, which also - * automatically call DllMain() from our mdbx.dll */ -#pragma comment(linker, "/ENTRY:DllMain") -#endif /* MDBX_AVOID_CRT */ - -BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID reserved) -#else -#if !MDBX_CONFIG_MANUAL_TLS_CALLBACK -static -#endif /* !MDBX_CONFIG_MANUAL_TLS_CALLBACK */ - void NTAPI - mdbx_dll_handler(PVOID module, DWORD reason, PVOID reserved) -#endif /* MDBX_BUILD_SHARED_LIBRARY */ -{ - (void)reserved; - switch (reason) { - case DLL_PROCESS_ATTACH: - mdbx_winnt_import(); - mdbx_rthc_global_init(); - break; - case DLL_PROCESS_DETACH: - mdbx_rthc_global_dtor(); - break; - - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - mdbx_rthc_thread_dtor(module); - break; - } -#if MDBX_BUILD_SHARED_LIBRARY - return TRUE; -#endif -} - -#if !MDBX_BUILD_SHARED_LIBRARY && !MDBX_CONFIG_MANUAL_TLS_CALLBACK -/* *INDENT-OFF* */ -/* clang-format off */ -#if defined(_MSC_VER) -# pragma const_seg(push) -# pragma data_seg(push) - -# ifdef _WIN64 - /* kick a linker to create the TLS directory if not already done */ -# pragma comment(linker, "/INCLUDE:_tls_used") - /* Force some symbol references. */ -# pragma comment(linker, "/INCLUDE:mdbx_tls_anchor") - /* specific const-segment for WIN64 */ -# pragma const_seg(".CRT$XLB") - const -# else - /* kick a linker to create the TLS directory if not already done */ -# pragma comment(linker, "/INCLUDE:__tls_used") - /* Force some symbol references. */ -# pragma comment(linker, "/INCLUDE:_mdbx_tls_anchor") - /* specific data-segment for WIN32 */ -# pragma data_seg(".CRT$XLB") -# endif - - __declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK mdbx_tls_anchor = mdbx_dll_handler; -# pragma data_seg(pop) -# pragma const_seg(pop) - -#elif defined(__GNUC__) -# ifdef _WIN64 - const -# endif - PIMAGE_TLS_CALLBACK mdbx_tls_anchor __attribute__((__section__(".CRT$XLB"), used)) = mdbx_dll_handler; -#else -# error FIXME -#endif -/* *INDENT-ON* */ -/* clang-format on */ -#endif /* !MDBX_BUILD_SHARED_LIBRARY && !MDBX_CONFIG_MANUAL_TLS_CALLBACK */ - -/*----------------------------------------------------------------------------*/ - -#define LCK_SHARED 0 -#define LCK_EXCLUSIVE LOCKFILE_EXCLUSIVE_LOCK -#define LCK_WAITFOR 0 -#define LCK_DONTWAIT LOCKFILE_FAIL_IMMEDIATELY - -static __inline BOOL flock(mdbx_filehandle_t fd, DWORD flags, uint64_t offset, - size_t bytes) { - OVERLAPPED ov; - ov.hEvent = 0; - ov.Offset = (DWORD)offset; - ov.OffsetHigh = HIGH_DWORD(offset); - return LockFileEx(fd, flags, 0, (DWORD)bytes, HIGH_DWORD(bytes), &ov); -} - -static __inline BOOL funlock(mdbx_filehandle_t fd, uint64_t offset, - size_t bytes) { - return UnlockFile(fd, (DWORD)offset, HIGH_DWORD(offset), (DWORD)bytes, - HIGH_DWORD(bytes)); -} - -/*----------------------------------------------------------------------------*/ -/* global `write` lock for write-txt processing, - * exclusive locking both meta-pages) */ - -#define LCK_MAXLEN (1u + (size_t)(MAXSSIZE_T)) -#define LCK_META_OFFSET 0 -#define LCK_META_LEN 0x10000u -#define LCK_BODY_OFFSET LCK_META_LEN -#define LCK_BODY_LEN (LCK_MAXLEN - LCK_BODY_OFFSET) -#define LCK_META LCK_META_OFFSET, LCK_META_LEN -#define LCK_BODY LCK_BODY_OFFSET, LCK_BODY_LEN -#define LCK_WHOLE 0, LCK_MAXLEN - -int mdbx_txn_lock(MDBX_env *env, bool dontwait) { - if (dontwait) { - if (!TryEnterCriticalSection(&env->me_windowsbug_lock)) - return MDBX_BUSY; - } else { - EnterCriticalSection(&env->me_windowsbug_lock); - } - - if ((env->me_flags & MDBX_EXCLUSIVE) || - flock(env->me_fd, - dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT) - : (LCK_EXCLUSIVE | LCK_WAITFOR), - LCK_BODY)) - return MDBX_SUCCESS; - int rc = GetLastError(); - LeaveCriticalSection(&env->me_windowsbug_lock); - return (!dontwait || rc != ERROR_LOCK_VIOLATION) ? rc : MDBX_BUSY; -} - -void mdbx_txn_unlock(MDBX_env *env) { - int rc = - (env->me_flags & MDBX_EXCLUSIVE) ? TRUE : funlock(env->me_fd, LCK_BODY); - LeaveCriticalSection(&env->me_windowsbug_lock); - if (!rc) - mdbx_panic("%s failed: errcode %u", __func__, GetLastError()); -} - -/*----------------------------------------------------------------------------*/ -/* global `read` lock for readers registration, - * exclusive locking `mti_numreaders` (second) cacheline */ - -#define LCK_LO_OFFSET 0 -#define LCK_LO_LEN offsetof(MDBX_lockinfo, mti_numreaders) -#define LCK_UP_OFFSET LCK_LO_LEN -#define LCK_UP_LEN (sizeof(MDBX_lockinfo) - LCK_UP_OFFSET) -#define LCK_LOWER LCK_LO_OFFSET, LCK_LO_LEN -#define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN - -MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env) { - mdbx_srwlock_AcquireShared(&env->me_remap_guard); - if (env->me_lfd == INVALID_HANDLE_VALUE) - return MDBX_SUCCESS; /* readonly database in readonly filesystem */ - - /* transite from S-? (used) to S-E (locked), e.g. exclusive lock upper-part */ - if ((env->me_flags & MDBX_EXCLUSIVE) || - flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) - return MDBX_SUCCESS; - - int rc = GetLastError(); - mdbx_srwlock_ReleaseShared(&env->me_remap_guard); - return rc; -} - -MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) { - if (env->me_lfd != INVALID_HANDLE_VALUE) { - /* transite from S-E (locked) to S-? (used), e.g. unlock upper-part */ - if ((env->me_flags & MDBX_EXCLUSIVE) == 0 && - !funlock(env->me_lfd, LCK_UPPER)) - mdbx_panic("%s failed: errcode %u", __func__, GetLastError()); - } - mdbx_srwlock_ReleaseShared(&env->me_remap_guard); -} - -static int suspend_and_append(mdbx_handle_array_t **array, - const DWORD ThreadId) { - const unsigned limit = (*array)->limit; - if ((*array)->count == limit) { - void *ptr = mdbx_realloc( - (limit > ARRAY_LENGTH((*array)->handles)) - ? *array - : /* don't free initial array on the stack */ NULL, - sizeof(mdbx_handle_array_t) + - sizeof(HANDLE) * (limit * 2 - ARRAY_LENGTH((*array)->handles))); - if (!ptr) - return MDBX_ENOMEM; - if (limit == ARRAY_LENGTH((*array)->handles)) - memcpy(ptr, *array, sizeof(mdbx_handle_array_t)); - *array = (mdbx_handle_array_t *)ptr; - (*array)->limit = limit * 2; - } - - HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, - FALSE, ThreadId); - if (hThread == NULL) - return GetLastError(); - - if (SuspendThread(hThread) == -1) { - int err = GetLastError(); - DWORD ExitCode; - if (err == /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED || - !GetExitCodeThread(hThread, &ExitCode) || ExitCode != STILL_ACTIVE) - err = MDBX_SUCCESS; - CloseHandle(hThread); - return err; - } - - (*array)->handles[(*array)->count++] = hThread; - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int -mdbx_suspend_threads_before_remap(MDBX_env *env, mdbx_handle_array_t **array) { - const size_t CurrentTid = GetCurrentThreadId(); - int rc; - if (env->me_lck) { - /* Scan LCK for threads of the current process */ - const MDBX_reader *const begin = env->me_lck->mti_readers; - const MDBX_reader *const end = begin + env->me_lck->mti_numreaders; - const size_t WriteTxnOwner = env->me_txn0 ? env->me_txn0->mt_owner : 0; - for (const MDBX_reader *reader = begin; reader < end; ++reader) { - if (reader->mr_pid != env->me_pid || !reader->mr_tid) { - skip_lck: - continue; - } - if (reader->mr_tid == CurrentTid || reader->mr_tid == WriteTxnOwner) - goto skip_lck; - if (env->me_flags & MDBX_NOTLS) { - /* Skip duplicates in no-tls mode */ - for (const MDBX_reader *scan = reader; --scan >= begin;) - if (scan->mr_tid == reader->mr_tid) - goto skip_lck; - } - - rc = suspend_and_append(array, (mdbx_tid_t)reader->mr_tid); - if (rc != MDBX_SUCCESS) { - bailout_lck: - (void)mdbx_resume_threads_after_remap(*array); - return rc; - } - } - if (WriteTxnOwner && WriteTxnOwner != CurrentTid) { - rc = suspend_and_append(array, (mdbx_tid_t)WriteTxnOwner); - if (rc != MDBX_SUCCESS) - goto bailout_lck; - } - } else { - /* Without LCK (i.e. read-only mode). - * Walk thougth a snapshot of all running threads */ - mdbx_assert(env, - env->me_txn0 == NULL || (env->me_flags & MDBX_EXCLUSIVE) != 0); - const HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hSnapshot == INVALID_HANDLE_VALUE) - return GetLastError(); - - THREADENTRY32 entry; - entry.dwSize = sizeof(THREADENTRY32); - - if (!Thread32First(hSnapshot, &entry)) { - rc = GetLastError(); - bailout_toolhelp: - CloseHandle(hSnapshot); - (void)mdbx_resume_threads_after_remap(*array); - return rc; - } - - do { - if (entry.th32OwnerProcessID != env->me_pid || - entry.th32ThreadID == CurrentTid) - continue; - - rc = suspend_and_append(array, entry.th32ThreadID); - if (rc != MDBX_SUCCESS) - goto bailout_toolhelp; - - } while (Thread32Next(hSnapshot, &entry)); - - rc = GetLastError(); - if (rc != ERROR_NO_MORE_FILES) - goto bailout_toolhelp; - CloseHandle(hSnapshot); - } - - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int -mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) { - int rc = MDBX_SUCCESS; - for (unsigned i = 0; i < array->count; ++i) { - const HANDLE hThread = array->handles[i]; - if (ResumeThread(hThread) == -1) { - const int err = GetLastError(); - DWORD ExitCode; - if (err != /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED && - GetExitCodeThread(hThread, &ExitCode) && ExitCode == STILL_ACTIVE) - rc = err; - } - CloseHandle(hThread); - } - return rc; -} - -/*----------------------------------------------------------------------------*/ -/* global `initial` lock for lockfile initialization, - * exclusive/shared locking first cacheline */ - -/* Briefly descritpion of locking schema/algorithm: - * - Windows does not support upgrading or downgrading for file locking. - * - Therefore upgrading/downgrading is emulated by shared and exclusive - * locking of upper and lower halves. - * - In other words, we have FSM with possible 9 states, - * i.e. free/shared/exclusive x free/shared/exclusive == 9. - * Only 6 states of FSM are used, which 2 of ones are transitive. - * - * The mdbx_lck_seize() moves the locking-FSM from the initial free/unlocked - * state to the "exclusive write" (and returns MDBX_RESULT_TRUE) if possible, - * or to the "used" (and returns MDBX_RESULT_FALSE). - * - * The mdbx_lck_downgrade() moves the locking-FSM from "exclusive write" - * state to the "used" (i.e. shared) state. - * - * States: - * ?-? = free, i.e. unlocked - * S-? = used, i.e. shared lock - * E-? = exclusive-read, i.e. operational exclusive - * ?-S - * ?-E = middle (transitive state) - * S-S - * S-E = locked (transitive state) - * E-S - * E-E = exclusive-write, i.e. exclusive due (re)initialization - */ - -static void lck_unlock(MDBX_env *env) { - int rc; - - if (env->me_lfd != INVALID_HANDLE_VALUE) { - /* double `unlock` for robustly remove overlapped shared/exclusive locks */ - while (funlock(env->me_lfd, LCK_LOWER)) - ; - rc = GetLastError(); - assert(rc == ERROR_NOT_LOCKED); - (void)rc; - SetLastError(ERROR_SUCCESS); - - while (funlock(env->me_lfd, LCK_UPPER)) - ; - rc = GetLastError(); - assert(rc == ERROR_NOT_LOCKED); - (void)rc; - SetLastError(ERROR_SUCCESS); - } - - if (env->me_fd != INVALID_HANDLE_VALUE) { - /* explicitly unlock to avoid latency for other processes (windows kernel - * releases such locks via deferred queues) */ - while (funlock(env->me_fd, LCK_BODY)) - ; - rc = GetLastError(); - assert(rc == ERROR_NOT_LOCKED); - (void)rc; - SetLastError(ERROR_SUCCESS); - - while (funlock(env->me_fd, LCK_META)) - ; - rc = GetLastError(); - assert(rc == ERROR_NOT_LOCKED); - (void)rc; - SetLastError(ERROR_SUCCESS); - - while (funlock(env->me_fd, LCK_WHOLE)) - ; - rc = GetLastError(); - assert(rc == ERROR_NOT_LOCKED); - (void)rc; - SetLastError(ERROR_SUCCESS); - } -} - -MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env, - MDBX_env *inprocess_neighbor, - int global_uniqueness_flag) { - (void)env; - (void)inprocess_neighbor; - (void)global_uniqueness_flag; - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_lck_destroy(MDBX_env *env, - MDBX_env *inprocess_neighbor) { - (void)inprocess_neighbor; - - /* LY: should unmap before releasing the locks to avoid race condition and - * STATUS_USER_MAPPED_FILE/ERROR_USER_MAPPED_FILE */ - if (env->me_map) - mdbx_munmap(&env->me_dxb_mmap); - if (env->me_lck) - mdbx_munmap(&env->me_lck_mmap); - - lck_unlock(env); - return MDBX_SUCCESS; -} - -/* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE) - * or as 'used' (S-? and returns MDBX_RESULT_FALSE). - * Oherwise returns an error. */ -static int internal_seize_lck(HANDLE lfd) { - int rc; - assert(lfd != INVALID_HANDLE_VALUE); - - /* 1) now on ?-? (free), get ?-E (middle) */ - mdbx_jitter4testing(false); - if (!flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) { - rc = GetLastError() /* 2) something went wrong, give up */; - mdbx_error("%s(%s) failed: errcode %u", __func__, - "?-?(free) >> ?-E(middle)", rc); - return rc; - } - - /* 3) now on ?-E (middle), try E-E (exclusive-write) */ - mdbx_jitter4testing(false); - if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER)) - return MDBX_RESULT_TRUE /* 4) got E-E (exclusive-write), done */; - - /* 5) still on ?-E (middle) */ - rc = GetLastError(); - mdbx_jitter4testing(false); - if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) { - /* 6) something went wrong, give up */ - if (!funlock(lfd, LCK_UPPER)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "?-E(middle) >> ?-?(free)", GetLastError()); - return rc; - } - - /* 7) still on ?-E (middle), try S-E (locked) */ - mdbx_jitter4testing(false); - rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER) ? MDBX_RESULT_FALSE - : GetLastError(); - - mdbx_jitter4testing(false); - if (rc != MDBX_RESULT_FALSE) - mdbx_error("%s(%s) failed: errcode %u", __func__, - "?-E(middle) >> S-E(locked)", rc); - - /* 8) now on S-E (locked) or still on ?-E (middle), - * transite to S-? (used) or ?-? (free) */ - if (!funlock(lfd, LCK_UPPER)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "X-E(locked/middle) >> X-?(used/free)", GetLastError()); - - /* 9) now on S-? (used, DONE) or ?-? (free, FAILURE) */ - return rc; -} - -MDBX_INTERNAL_FUNC int mdbx_lck_seize(MDBX_env *env) { - int rc; - - assert(env->me_fd != INVALID_HANDLE_VALUE); - if (env->me_flags & MDBX_EXCLUSIVE) - return MDBX_RESULT_TRUE /* nope since files were must be opened - non-shareable */ - ; - - if (env->me_lfd == INVALID_HANDLE_VALUE) { - /* LY: without-lck mode (e.g. on read-only filesystem) */ - mdbx_jitter4testing(false); - if (!flock(env->me_fd, LCK_SHARED | LCK_DONTWAIT, LCK_WHOLE)) { - rc = GetLastError(); - mdbx_error("%s(%s) failed: errcode %u", __func__, "without-lck", rc); - return rc; - } - return MDBX_RESULT_FALSE; - } - - rc = internal_seize_lck(env->me_lfd); - mdbx_jitter4testing(false); - if (rc == MDBX_RESULT_TRUE && (env->me_flags & MDBX_RDONLY) == 0) { - /* Check that another process don't operates in without-lck mode. - * Doing such check by exclusive locking the body-part of db. Should be - * noted: - * - we need an exclusive lock for do so; - * - we can't lock meta-pages, otherwise other process could get an error - * while opening db in valid (non-conflict) mode. */ - if (!flock(env->me_fd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_BODY)) { - rc = GetLastError(); - mdbx_error("%s(%s) failed: errcode %u", __func__, - "lock-against-without-lck", rc); - mdbx_jitter4testing(false); - lck_unlock(env); - } else { - mdbx_jitter4testing(false); - if (!funlock(env->me_fd, LCK_BODY)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "unlock-against-without-lck", GetLastError()); - } - } - - return rc; -} - -MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env) { - /* Transite from exclusive state (E-?) to used (S-?) */ - assert(env->me_fd != INVALID_HANDLE_VALUE); - assert(env->me_lfd != INVALID_HANDLE_VALUE); - -#if 1 - if (env->me_flags & MDBX_EXCLUSIVE) - return MDBX_SUCCESS /* nope since files were must be opened non-shareable */ - ; -#else - /* 1) must be at E-E (exclusive-write) */ - if (env->me_flags & MDBX_EXCLUSIVE) { - /* transite from E-E to E_? (exclusive-read) */ - if (!funlock(env->me_lfd, LCK_UPPER)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "E-E(exclusive-write) >> E-?(exclusive-read)", GetLastError()); - return MDBX_SUCCESS /* 2) now at E-? (exclusive-read), done */; - } -#endif - - /* 3) now at E-E (exclusive-write), transite to ?_E (middle) */ - if (!funlock(env->me_lfd, LCK_LOWER)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "E-E(exclusive-write) >> ?-E(middle)", GetLastError()); - - /* 4) now at ?-E (middle), transite to S-E (locked) */ - if (!flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)) { - int rc = GetLastError() /* 5) something went wrong, give up */; - mdbx_error("%s(%s) failed: errcode %u", __func__, - "?-E(middle) >> S-E(locked)", rc); - return rc; - } - - /* 6) got S-E (locked), continue transition to S-? (used) */ - if (!funlock(env->me_lfd, LCK_UPPER)) - mdbx_panic("%s(%s) failed: errcode %u", __func__, - "S-E(locked) >> S-?(used)", GetLastError()); - - return MDBX_SUCCESS /* 7) now at S-? (used), done */; -} - -/*----------------------------------------------------------------------------*/ -/* reader checking (by pid) */ - -MDBX_INTERNAL_FUNC int mdbx_rpid_set(MDBX_env *env) { - (void)env; - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_rpid_clear(MDBX_env *env) { - (void)env; - return MDBX_SUCCESS; -} - -/* Checks reader by pid. - * - * Returns: - * MDBX_RESULT_TRUE, if pid is live (unable to acquire lock) - * MDBX_RESULT_FALSE, if pid is dead (lock acquired) - * or otherwise the errcode. */ -MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid) { - (void)env; - HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); - int rc; - if (likely(hProcess)) { - rc = WaitForSingleObject(hProcess, 0); - if (unlikely(rc == WAIT_FAILED)) - rc = GetLastError(); - CloseHandle(hProcess); - } else { - rc = GetLastError(); - } - - switch (rc) { - case ERROR_INVALID_PARAMETER: - /* pid seems invalid */ - return MDBX_RESULT_FALSE; - case WAIT_OBJECT_0: - /* process just exited */ - return MDBX_RESULT_FALSE; - case WAIT_TIMEOUT: - /* pid running */ - return MDBX_RESULT_TRUE; - default: - /* failure */ - return rc; - } -} - -//---------------------------------------------------------------------------- -// Stub for slim read-write lock -// Copyright (C) 1995-2002 Brad Wilson - -static void WINAPI stub_srwlock_Init(MDBX_srwlock *srwl) { - srwl->readerCount = srwl->writerCount = 0; -} - -static void WINAPI stub_srwlock_AcquireShared(MDBX_srwlock *srwl) { - while (true) { - assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); - - // If there's a writer already, spin without unnecessarily - // interlocking the CPUs - if (srwl->writerCount != 0) { - YieldProcessor(); - continue; - } - - // Add to the readers list - _InterlockedIncrement(&srwl->readerCount); - - // Check for writers again (we may have been pre-empted). If - // there are no writers writing or waiting, then we're done. - if (srwl->writerCount == 0) - break; - - // Remove from the readers list, spin, try again - _InterlockedDecrement(&srwl->readerCount); - YieldProcessor(); - } -} - -static void WINAPI stub_srwlock_ReleaseShared(MDBX_srwlock *srwl) { - assert(srwl->readerCount > 0); - _InterlockedDecrement(&srwl->readerCount); -} - -static void WINAPI stub_srwlock_AcquireExclusive(MDBX_srwlock *srwl) { - while (true) { - assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); - - // If there's a writer already, spin without unnecessarily - // interlocking the CPUs - if (srwl->writerCount != 0) { - YieldProcessor(); - continue; - } - - // See if we can become the writer (expensive, because it inter- - // locks the CPUs, so writing should be an infrequent process) - if (_InterlockedExchange(&srwl->writerCount, 1) == 0) - break; - } - - // Now we're the writer, but there may be outstanding readers. - // Spin until there aren't any more; new readers will wait now - // that we're the writer. - while (srwl->readerCount != 0) { - assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); - YieldProcessor(); - } -} - -static void WINAPI stub_srwlock_ReleaseExclusive(MDBX_srwlock *srwl) { - assert(srwl->writerCount == 1 && srwl->readerCount >= 0); - srwl->writerCount = 0; -} - -MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared, - mdbx_srwlock_ReleaseShared, mdbx_srwlock_AcquireExclusive, - mdbx_srwlock_ReleaseExclusive; - -/*----------------------------------------------------------------------------*/ - -#if 0 /* LY: unused for now */ -static DWORD WINAPI stub_DiscardVirtualMemory(PVOID VirtualAddress, - SIZE_T Size) { - return VirtualAlloc(VirtualAddress, Size, MEM_RESET, PAGE_NOACCESS) - ? ERROR_SUCCESS - : GetLastError(); -} -#endif /* unused for now */ - -static uint64_t WINAPI stub_GetTickCount64(void) { - LARGE_INTEGER Counter, Frequency; - return (QueryPerformanceFrequency(&Frequency) && - QueryPerformanceCounter(&Counter)) - ? Counter.QuadPart * 1000ul / Frequency.QuadPart - : 0; -} - -/*----------------------------------------------------------------------------*/ -#ifndef MDBX_ALLOY -MDBX_GetFileInformationByHandleEx mdbx_GetFileInformationByHandleEx; -MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW; -MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW; -MDBX_SetFileInformationByHandle mdbx_SetFileInformationByHandle; -MDBX_NtFsControlFile mdbx_NtFsControlFile; -MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory; -MDBX_GetTickCount64 mdbx_GetTickCount64; -#if 0 /* LY: unused for now */ -MDBX_DiscardVirtualMemory mdbx_DiscardVirtualMemory; -MDBX_OfferVirtualMemory mdbx_OfferVirtualMemory; -MDBX_ReclaimVirtualMemory mdbx_ReclaimVirtualMemory; -#endif /* unused for now */ -#endif /* MDBX_ALLOY */ - -static void mdbx_winnt_import(void) { - const HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll"); - const MDBX_srwlock_function init = - (MDBX_srwlock_function)GetProcAddress(hKernel32dll, "InitializeSRWLock"); - if (init != NULL) { - mdbx_srwlock_Init = init; - mdbx_srwlock_AcquireShared = (MDBX_srwlock_function)GetProcAddress( - hKernel32dll, "AcquireSRWLockShared"); - mdbx_srwlock_ReleaseShared = (MDBX_srwlock_function)GetProcAddress( - hKernel32dll, "ReleaseSRWLockShared"); - mdbx_srwlock_AcquireExclusive = (MDBX_srwlock_function)GetProcAddress( - hKernel32dll, "AcquireSRWLockExclusive"); - mdbx_srwlock_ReleaseExclusive = (MDBX_srwlock_function)GetProcAddress( - hKernel32dll, "ReleaseSRWLockExclusive"); - } else { - mdbx_srwlock_Init = stub_srwlock_Init; - mdbx_srwlock_AcquireShared = stub_srwlock_AcquireShared; - mdbx_srwlock_ReleaseShared = stub_srwlock_ReleaseShared; - mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive; - mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive; - } - -#define GET_KERNEL32_PROC(ENTRY) \ - mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(hKernel32dll, #ENTRY) - GET_KERNEL32_PROC(GetFileInformationByHandleEx); - GET_KERNEL32_PROC(GetVolumeInformationByHandleW); - GET_KERNEL32_PROC(GetFinalPathNameByHandleW); - GET_KERNEL32_PROC(SetFileInformationByHandle); - GET_KERNEL32_PROC(PrefetchVirtualMemory); - GET_KERNEL32_PROC(GetTickCount64); - if (!mdbx_GetTickCount64) - mdbx_GetTickCount64 = stub_GetTickCount64; -#if 0 /* LY: unused for now */ - GET_KERNEL32_PROC(DiscardVirtualMemory); - if (!mdbx_DiscardVirtualMemory) - mdbx_DiscardVirtualMemory = stub_DiscardVirtualMemory; - GET_KERNEL32_PROC(OfferVirtualMemory); - GET_KERNEL32_PROC(ReclaimVirtualMemory); -#endif /* unused for now */ -#undef GET_KERNEL32_PROC - - const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll"); - mdbx_NtFsControlFile = - (MDBX_NtFsControlFile)GetProcAddress(hNtdll, "NtFsControlFile"); -} diff --git a/src/contrib/db/libmdbx/src/elements/ntdll.def b/src/contrib/db/libmdbx/src/elements/ntdll.def deleted file mode 100644 index e3a6e33..0000000 --- a/src/contrib/db/libmdbx/src/elements/ntdll.def +++ /dev/null @@ -1,1244 +0,0 @@ -LIBRARY ntdll -EXPORTS -CsrAllocateCaptureBuffer -CsrAllocateMessagePointer -CsrCaptureMessageBuffer -CsrCaptureMessageMultiUnicodeStringsInPlace -CsrCaptureMessageString -CsrCaptureTimeout -CsrClientCallServer -CsrClientConnectToServer -CsrFreeCaptureBuffer -CsrGetProcessId -CsrIdentifyAlertableThread -CsrSetPriorityClass -DbgBreakPoint -DbgPrint -DbgPrintEx -DbgPrintReturnControlC -DbgPrompt -DbgQueryDebugFilterState -DbgSetDebugFilterState -DbgUiConnectToDbg -DbgUiContinue -DbgUiConvertStateChangeStructure -DbgUiDebugActiveProcess -DbgUiGetThreadDebugObject -DbgUiIssueRemoteBreakin -DbgUiRemoteBreakin -DbgUiSetThreadDebugObject -DbgUiStopDebugging -DbgUiWaitStateChange -DbgUserBreakPoint -KiRaiseUserExceptionDispatcher -KiUserApcDispatcher -KiUserCallbackDispatcher -KiUserExceptionDispatcher -LdrAccessResource -LdrAddRefDll -LdrDisableThreadCalloutsForDll -LdrEnumResources -LdrEnumerateLoadedModules -LdrFindEntryForAddress -LdrFindResourceDirectory_U -LdrFindResourceEx_U -LdrFindResource_U -LdrFlushAlternateResourceModules -LdrGetDllHandle -LdrGetDllHandleEx -LdrGetProcedureAddress -LdrInitShimEngineDynamic -LdrInitializeThunk -LdrLoadAlternateResourceModule -LdrLoadDll -LdrLockLoaderLock -LdrProcessRelocationBlock -LdrQueryImageFileExecutionOptions -LdrQueryProcessModuleInformation -LdrSetAppCompatDllRedirectionCallback -LdrSetDllManifestProber -LdrShutdownProcess -LdrShutdownThread -LdrUnloadAlternateResourceModule -LdrUnloadDll -LdrUnlockLoaderLock -LdrVerifyImageMatchesChecksum -NlsAnsiCodePage -NlsMbCodePageTag -NlsMbOemCodePageTag -NtAcceptConnectPort -NtAccessCheck -NtAccessCheckAndAuditAlarm -NtAccessCheckByType -NtAccessCheckByTypeAndAuditAlarm -NtAccessCheckByTypeResultList -NtAccessCheckByTypeResultListAndAuditAlarm -NtAccessCheckByTypeResultListAndAuditAlarmByHandle -NtAddAtom -NtAddBootEntry -NtAdjustGroupsToken -NtAdjustPrivilegesToken -NtAlertResumeThread -NtAlertThread -NtAllocateLocallyUniqueId -NtAllocateUserPhysicalPages -NtAllocateUuids -NtAllocateVirtualMemory -NtAreMappedFilesTheSame -NtAssignProcessToJobObject -NtCallbackReturn -NtCancelIoFile -NtCancelTimer -NtClearEvent -NtClose -NtCloseObjectAuditAlarm -NtCompactKeys -NtCompareTokens -NtCompleteConnectPort -NtCompressKey -NtConnectPort -NtContinue -NtCreateDebugObject -NtCreateDirectoryObject -NtCreateEvent -NtCreateEventPair -NtCreateFile -NtCreateIoCompletion -NtCreateJobObject -NtCreateJobSet -NtCreateKey -NtCreateKeyedEvent -NtCreateMailslotFile -NtCreateMutant -NtCreateNamedPipeFile -NtCreatePagingFile -NtCreatePort -NtCreateProcess -NtCreateProcessEx -NtCreateProfile -NtCreateSection -NtCreateSemaphore -NtCreateSymbolicLinkObject -NtCreateThread -NtCreateTimer -NtCreateToken -NtCreateWaitablePort -NtDebugActiveProcess -NtDebugContinue -NtDelayExecution -NtDeleteAtom -NtDeleteBootEntry -NtDeleteFile -NtDeleteKey -NtDeleteObjectAuditAlarm -NtDeleteValueKey -NtDeviceIoControlFile -NtDisplayString -NtDuplicateObject -NtDuplicateToken -NtEnumerateBootEntries -NtEnumerateKey -NtEnumerateSystemEnvironmentValuesEx -NtEnumerateValueKey -NtExtendSection -NtFilterToken -NtFindAtom -NtFlushBuffersFile -NtFlushInstructionCache -NtFlushKey -NtFlushVirtualMemory -NtFlushWriteBuffer -NtFreeUserPhysicalPages -NtFreeVirtualMemory -NtFsControlFile -NtGetContextThread -NtGetDevicePowerState -NtGetWriteWatch -NtImpersonateAnonymousToken -NtImpersonateClientOfPort -NtImpersonateThread -NtInitializeRegistry -NtInitiatePowerAction -NtIsProcessInJob -NtIsSystemResumeAutomatic -NtListenPort -NtLoadDriver -NtLoadKey -NtLoadKey2 -NtLockFile -NtLockProductActivationKeys -NtLockRegistryKey -NtLockVirtualMemory -NtMakePermanentObject -NtMakeTemporaryObject -NtMapUserPhysicalPages -NtMapUserPhysicalPagesScatter -NtMapViewOfSection -NtModifyBootEntry -NtNotifyChangeDirectoryFile -NtNotifyChangeKey -NtNotifyChangeMultipleKeys -NtOpenDirectoryObject -NtOpenEvent -NtOpenEventPair -NtOpenFile -NtOpenIoCompletion -NtOpenJobObject -NtOpenKey -NtOpenKeyedEvent -NtOpenMutant -NtOpenObjectAuditAlarm -NtOpenProcess -NtOpenProcessToken -NtOpenProcessTokenEx -NtOpenSection -NtOpenSemaphore -NtOpenSymbolicLinkObject -NtOpenThread -NtOpenThreadToken -NtOpenThreadTokenEx -NtOpenTimer -NtPlugPlayControl -NtPowerInformation -NtPrivilegeCheck -NtPrivilegeObjectAuditAlarm -NtPrivilegedServiceAuditAlarm -NtProtectVirtualMemory -NtPulseEvent -NtQueryAttributesFile -NtQueryBootEntryOrder -NtQueryBootOptions -NtQueryDebugFilterState -NtQueryDefaultLocale -NtQueryDefaultUILanguage -NtQueryDirectoryFile -NtQueryDirectoryObject -NtQueryEaFile -NtQueryEvent -NtQueryFullAttributesFile -NtQueryInformationAtom -NtQueryInformationFile -NtQueryInformationJobObject -NtQueryInformationPort -NtQueryInformationProcess -NtQueryInformationThread -NtQueryInformationToken -NtQueryInstallUILanguage -NtQueryIntervalProfile -NtQueryIoCompletion -NtQueryKey -NtQueryMultipleValueKey -NtQueryMutant -NtQueryObject -NtQueryOpenSubKeys -NtQueryPerformanceCounter -NtQueryPortInformationProcess -NtQueryQuotaInformationFile -NtQuerySection -NtQuerySecurityObject -NtQuerySemaphore -NtQuerySymbolicLinkObject -NtQuerySystemEnvironmentValue -NtQuerySystemEnvironmentValueEx -NtQuerySystemInformation -NtQuerySystemTime -NtQueryTimer -NtQueryTimerResolution -NtQueryValueKey -NtQueryVirtualMemory -NtQueryVolumeInformationFile -NtQueueApcThread -NtRaiseException -NtRaiseHardError -NtReadFile -NtReadFileScatter -NtReadRequestData -NtReadVirtualMemory -NtRegisterThreadTerminatePort -NtReleaseKeyedEvent -NtReleaseMutant -NtReleaseSemaphore -NtRemoveIoCompletion -NtRemoveProcessDebug -NtRenameKey -NtReplaceKey -NtReplyPort -NtReplyWaitReceivePort -NtReplyWaitReceivePortEx -NtReplyWaitReplyPort -NtRequestPort -NtRequestWaitReplyPort -NtResetEvent -NtResetWriteWatch -NtRestoreKey -NtResumeProcess -NtResumeThread -NtSaveKey -NtSaveKeyEx -NtSaveMergedKeys -NtSecureConnectPort -NtSetBootEntryOrder -NtSetBootOptions -NtSetContextThread -NtSetDebugFilterState -NtSetDefaultHardErrorPort -NtSetDefaultLocale -NtSetDefaultUILanguage -NtSetEaFile -NtSetEvent -NtSetEventBoostPriority -NtSetHighEventPair -NtSetHighWaitLowEventPair -NtSetInformationDebugObject -NtSetInformationFile -NtSetInformationJobObject -NtSetInformationKey -NtSetInformationObject -NtSetInformationProcess -NtSetInformationThread -NtSetInformationToken -NtSetIntervalProfile -NtSetIoCompletion -NtSetLdtEntries -NtSetLowEventPair -NtSetLowWaitHighEventPair -NtSetQuotaInformationFile -NtSetSecurityObject -NtSetSystemEnvironmentValue -NtSetSystemEnvironmentValueEx -NtSetSystemInformation -NtSetSystemPowerState -NtSetSystemTime -NtSetThreadExecutionState -NtSetTimer -NtSetTimerResolution -NtSetUuidSeed -NtSetValueKey -NtSetVolumeInformationFile -NtShutdownSystem -NtSignalAndWaitForSingleObject -NtStartProfile -NtStopProfile -NtSuspendProcess -NtSuspendThread -NtSystemDebugControl -NtTerminateJobObject -NtTerminateProcess -NtTerminateThread -NtTestAlert -NtTraceEvent -NtTranslateFilePath -NtUnloadDriver -NtUnloadKey -NtUnloadKeyEx -NtUnlockFile -NtUnlockVirtualMemory -NtUnmapViewOfSection -NtVdmControl -NtWaitForDebugEvent -NtWaitForKeyedEvent -NtWaitForMultipleObjects -NtWaitForSingleObject -NtWaitHighEventPair -NtWaitLowEventPair -NtWriteFile -NtWriteFileGather -NtWriteRequestData -NtWriteVirtualMemory -NtYieldExecution -PfxFindPrefix -PfxInitialize -PfxInsertPrefix -PfxRemovePrefix -RtlAbortRXact -RtlAbsoluteToSelfRelativeSD -RtlAcquirePebLock -RtlAcquireResourceExclusive -RtlAcquireResourceShared -RtlActivateActivationContext -RtlActivateActivationContextEx -RtlActivateActivationContextUnsafeFast -RtlAddAccessAllowedAce -RtlAddAccessAllowedAceEx -RtlAddAccessAllowedObjectAce -RtlAddAccessDeniedAce -RtlAddAccessDeniedAceEx -RtlAddAccessDeniedObjectAce -RtlAddAce -RtlAddActionToRXact -RtlAddAtomToAtomTable -RtlAddAttributeActionToRXact -RtlAddAuditAccessAce -RtlAddAuditAccessAceEx -RtlAddAuditAccessObjectAce -RtlAddCompoundAce -RtlAddRefActivationContext -RtlAddRefMemoryStream -RtlAddVectoredExceptionHandler -RtlAddressInSectionTable -RtlAdjustPrivilege -RtlAllocateAndInitializeSid -RtlAllocateHandle -RtlAllocateHeap -RtlAnsiCharToUnicodeChar -RtlAnsiStringToUnicodeSize -RtlAnsiStringToUnicodeString -RtlAppendAsciizToString -RtlAppendPathElement -RtlAppendStringToString -RtlAppendUnicodeStringToString -RtlAppendUnicodeToString -RtlApplicationVerifierStop -RtlApplyRXact -RtlApplyRXactNoFlush -RtlAreAllAccessesGranted -RtlAreAnyAccessesGranted -RtlAreBitsClear -RtlAreBitsSet -RtlAssert -RtlCancelTimer -RtlCaptureContext -RtlCaptureStackBackTrace -RtlCharToInteger -RtlCheckForOrphanedCriticalSections -RtlCheckRegistryKey -RtlClearAllBits -RtlClearBits -RtlCloneMemoryStream -RtlCommitMemoryStream -RtlCompactHeap -RtlCompareMemory -RtlCompareMemoryUlong -RtlCompareString -RtlCompareUnicodeString -RtlCompressBuffer -RtlComputeCrc32 -RtlComputeImportTableHash -RtlComputePrivatizedDllName_U -RtlConsoleMultiByteToUnicodeN -RtlConvertExclusiveToShared -RtlConvertSharedToExclusive -RtlConvertSidToUnicodeString -RtlConvertToAutoInheritSecurityObject -RtlCopyLuid -RtlCopyLuidAndAttributesArray -RtlCopyMemoryStreamTo -RtlCopyOutOfProcessMemoryStreamTo -RtlCopySecurityDescriptor -RtlCopySid -RtlCopySidAndAttributesArray -RtlCopyString -RtlCopyUnicodeString -RtlCreateAcl -RtlCreateActivationContext -RtlCreateAndSetSD -RtlCreateAtomTable -RtlCreateBootStatusDataFile -RtlCreateEnvironment -RtlCreateHeap -RtlCreateProcessParameters -RtlCreateQueryDebugBuffer -RtlCreateRegistryKey -RtlCreateSecurityDescriptor -RtlCreateServiceSid -RtlCreateSystemVolumeInformationFolder -RtlCreateTagHeap -RtlCreateTimer -RtlCreateTimerQueue -RtlCreateUnicodeString -RtlCreateUnicodeStringFromAsciiz -RtlCreateUserProcess -RtlCreateUserSecurityObject -RtlCreateUserThread -RtlCustomCPToUnicodeN -RtlCutoverTimeToSystemTime -RtlDeNormalizeProcessParams -RtlDeactivateActivationContext -RtlDeactivateActivationContextUnsafeFast -RtlDebugPrintTimes -RtlDecodePointer -RtlDecodeSystemPointer -RtlDecompressBuffer -RtlDecompressFragment -RtlDefaultNpAcl -RtlDelete -RtlDeleteAce -RtlDeleteAtomFromAtomTable -RtlDeleteCriticalSection -RtlDeleteElementGenericTable -RtlDeleteElementGenericTableAvl -RtlDeleteNoSplay -RtlDeleteRegistryValue -RtlDeleteResource -RtlDeleteSecurityObject -RtlDeleteTimer -RtlDeleteTimerQueue -RtlDeleteTimerQueueEx -RtlDeregisterWait -RtlDeregisterWaitEx -RtlDestroyAtomTable -RtlDestroyEnvironment -RtlDestroyHandleTable -RtlDestroyHeap -RtlDestroyProcessParameters -RtlDestroyQueryDebugBuffer -RtlDetermineDosPathNameType_U -RtlDllShutdownInProgress -RtlDnsHostNameToComputerName -RtlDoesFileExists_U -RtlDosApplyFileIsolationRedirection_Ustr -RtlDosPathNameToNtPathName_U -RtlDosSearchPath_U -RtlDosSearchPath_Ustr -RtlDowncaseUnicodeChar -RtlDowncaseUnicodeString -RtlDumpResource -RtlDuplicateUnicodeString -RtlEmptyAtomTable -RtlEnableEarlyCriticalSectionEventCreation -RtlEncodePointer -RtlEncodeSystemPointer -RtlEnterCriticalSection -RtlEnumProcessHeaps -RtlEnumerateGenericTable -RtlEnumerateGenericTableAvl -RtlEnumerateGenericTableLikeADirectory -RtlEnumerateGenericTableWithoutSplaying -RtlEnumerateGenericTableWithoutSplayingAvl -RtlEqualComputerName -RtlEqualDomainName -RtlEqualLuid -RtlEqualPrefixSid -RtlEqualSid -RtlEqualString -RtlEqualUnicodeString -RtlEraseUnicodeString -RtlExitUserThread -RtlExpandEnvironmentStrings_U -RtlFillMemory -RtlFinalReleaseOutOfProcessMemoryStream -RtlFindActivationContextSectionGuid -RtlFindActivationContextSectionString -RtlFindCharInUnicodeString -RtlFindClearBits -RtlFindClearBitsAndSet -RtlFindClearRuns -RtlFindLastBackwardRunClear -RtlFindLeastSignificantBit -RtlFindLongestRunClear -RtlFindMessage -RtlFindMostSignificantBit -RtlFindNextForwardRunClear -RtlFindSetBits -RtlFindSetBitsAndClear -RtlFirstEntrySList -RtlFirstFreeAce -RtlFlushSecureMemoryCache -RtlFormatCurrentUserKeyPath -RtlFormatMessage -RtlFreeAnsiString -RtlFreeHandle -RtlFreeHeap -RtlFreeOemString -RtlFreeSid -RtlFreeThreadActivationContextStack -RtlFreeUnicodeString -RtlGUIDFromString -RtlGenerate8dot3Name -RtlGetAce -RtlGetActiveActivationContext -RtlGetCallersAddress -RtlGetCompressionWorkSpaceSize -RtlGetControlSecurityDescriptor -RtlGetCurrentDirectory_U -RtlGetCurrentPeb -RtlGetDaclSecurityDescriptor -RtlGetElementGenericTable -RtlGetElementGenericTableAvl -RtlGetFrame -RtlGetFullPathName_U -RtlGetGroupSecurityDescriptor -RtlGetLastNtStatus -RtlGetLastWin32Error -RtlGetLengthWithoutLastFullDosOrNtPathElement -RtlGetLengthWithoutTrailingPathSeperators -RtlGetLongestNtPathLength -RtlGetNativeSystemInformation -RtlGetNtGlobalFlags -RtlGetNtProductType -RtlGetNtVersionNumbers -RtlGetOwnerSecurityDescriptor -RtlGetProcessHeaps -RtlGetSaclSecurityDescriptor -RtlGetSecurityDescriptorRMControl -RtlGetSetBootStatusData -RtlGetUnloadEventTrace -RtlGetUserInfoHeap -RtlGetVersion -RtlHashUnicodeString -RtlIdentifierAuthoritySid -RtlImageDirectoryEntryToData -RtlImageNtHeader -RtlImageRvaToSection -RtlImageRvaToVa -RtlImpersonateSelf -RtlInitAnsiString -RtlInitCodePageTable -RtlInitMemoryStream -RtlInitNlsTables -RtlInitOutOfProcessMemoryStream -RtlInitString -RtlInitUnicodeString -RtlInitUnicodeStringEx -RtlInitializeAtomPackage -RtlInitializeBitMap -RtlInitializeContext -RtlInitializeCriticalSection -RtlInitializeCriticalSectionAndSpinCount -RtlInitializeGenericTable -RtlInitializeGenericTableAvl -RtlInitializeHandleTable -RtlInitializeRXact -RtlInitializeResource -RtlInitializeSListHead -RtlInitializeSid -RtlInsertElementGenericTable -RtlInsertElementGenericTableAvl -RtlInt64ToUnicodeString -RtlIntegerToChar -RtlIntegerToUnicodeString -RtlInterlockedFlushSList -RtlInterlockedPopEntrySList -RtlInterlockedPushEntrySList -RtlInterlockedPushListSList -RtlIpv4AddressToStringA -RtlIpv4AddressToStringExA -RtlIpv4AddressToStringExW -RtlIpv4AddressToStringW -RtlIpv4StringToAddressA -RtlIpv4StringToAddressExA -RtlIpv4StringToAddressExW -RtlIpv4StringToAddressW -RtlIpv6AddressToStringA -RtlIpv6AddressToStringExA -RtlIpv6AddressToStringExW -RtlIpv6AddressToStringW -RtlIpv6StringToAddressA -RtlIpv6StringToAddressExA -RtlIpv6StringToAddressExW -RtlIpv6StringToAddressW -RtlIsActivationContextActive -RtlIsDosDeviceName_U -RtlIsGenericTableEmpty -RtlIsGenericTableEmptyAvl -RtlIsNameLegalDOS8Dot3 -RtlIsTextUnicode -RtlIsThreadWithinLoaderCallout -RtlIsValidHandle -RtlIsValidIndexHandle -RtlLargeIntegerToChar -RtlLeaveCriticalSection -RtlLengthRequiredSid -RtlLengthSecurityDescriptor -RtlLengthSid -RtlLocalTimeToSystemTime -RtlLockBootStatusData -RtlLockHeap -RtlLockMemoryStreamRegion -RtlLogStackBackTrace -RtlLookupAtomInAtomTable -RtlLookupElementGenericTable -RtlLookupElementGenericTableAvl -RtlMakeSelfRelativeSD -RtlMapGenericMask -RtlMapSecurityErrorToNtStatus -RtlMoveMemory -RtlMultiAppendUnicodeStringBuffer -RtlMultiByteToUnicodeN -RtlMultiByteToUnicodeSize -RtlNewInstanceSecurityObject -RtlNewSecurityGrantedAccess -RtlNewSecurityObject -RtlNewSecurityObjectEx -RtlNewSecurityObjectWithMultipleInheritance -RtlNormalizeProcessParams -RtlNtPathNameToDosPathName -RtlNtStatusToDosError -RtlNtStatusToDosErrorNoTeb -RtlNumberGenericTableElements -RtlNumberGenericTableElementsAvl -RtlNumberOfClearBits -RtlNumberOfSetBits -RtlOemStringToUnicodeSize -RtlOemStringToUnicodeString -RtlOemToUnicodeN -RtlOpenCurrentUser -RtlPcToFileHeader -RtlPinAtomInAtomTable -RtlPopFrame -RtlPrefixString -RtlPrefixUnicodeString -RtlProtectHeap -RtlPushFrame -RtlQueryAtomInAtomTable -RtlQueryDepthSList -RtlQueryEnvironmentVariable_U -RtlQueryHeapInformation -RtlQueryInformationAcl -RtlQueryInformationActivationContext -RtlQueryInformationActiveActivationContext -RtlQueryInterfaceMemoryStream -RtlQueryProcessBackTraceInformation -RtlQueryProcessDebugInformation -RtlQueryProcessHeapInformation -RtlQueryProcessLockInformation -RtlQueryRegistryValues -RtlQuerySecurityObject -RtlQueryTagHeap -RtlQueryTimeZoneInformation -RtlQueueApcWow64Thread -RtlQueueWorkItem -RtlRaiseException -RtlRaiseStatus -RtlRandom -RtlRandomEx -RtlReAllocateHeap -RtlReadMemoryStream -RtlReadOutOfProcessMemoryStream -RtlRealPredecessor -RtlRealSuccessor -RtlRegisterSecureMemoryCacheCallback -RtlRegisterWait -RtlReleaseActivationContext -RtlReleaseMemoryStream -RtlReleasePebLock -RtlReleaseResource -RtlRemoteCall -RtlRemoveVectoredExceptionHandler -RtlResetRtlTranslations -RtlRestoreLastWin32Error -RtlRevertMemoryStream -RtlRunDecodeUnicodeString -RtlRunEncodeUnicodeString -RtlSecondsSince1970ToTime -RtlSecondsSince1980ToTime -RtlSeekMemoryStream -RtlSelfRelativeToAbsoluteSD -RtlSelfRelativeToAbsoluteSD2 -RtlSetAllBits -RtlSetAttributesSecurityDescriptor -RtlSetBits -RtlSetControlSecurityDescriptor -RtlSetCriticalSectionSpinCount -RtlSetCurrentDirectory_U -RtlSetCurrentEnvironment -RtlSetDaclSecurityDescriptor -RtlSetEnvironmentVariable -RtlSetGroupSecurityDescriptor -RtlSetHeapInformation -RtlSetInformationAcl -RtlSetIoCompletionCallback -RtlSetLastWin32Error -RtlSetLastWin32ErrorAndNtStatusFromNtStatus -RtlSetMemoryStreamSize -RtlSetOwnerSecurityDescriptor -RtlSetProcessIsCritical -RtlSetSaclSecurityDescriptor -RtlSetSecurityDescriptorRMControl -RtlSetSecurityObject -RtlSetSecurityObjectEx -RtlSetThreadIsCritical -RtlSetThreadPoolStartFunc -RtlSetTimeZoneInformation -RtlSetTimer -RtlSetUserFlagsHeap -RtlSetUserValueHeap -RtlSizeHeap -RtlSplay -RtlStartRXact -RtlStatMemoryStream -RtlStringFromGUID -RtlSubAuthorityCountSid -RtlSubAuthoritySid -RtlSubtreePredecessor -RtlSubtreeSuccessor -RtlSystemTimeToLocalTime -RtlTimeFieldsToTime -RtlTimeToElapsedTimeFields -RtlTimeToSecondsSince1970 -RtlTimeToSecondsSince1980 -RtlTimeToTimeFields -RtlTraceDatabaseAdd -RtlTraceDatabaseCreate -RtlTraceDatabaseDestroy -RtlTraceDatabaseEnumerate -RtlTraceDatabaseFind -RtlTraceDatabaseLock -RtlTraceDatabaseUnlock -RtlTraceDatabaseValidate -RtlTryEnterCriticalSection -RtlUnhandledExceptionFilter -RtlUnhandledExceptionFilter2 -RtlUnicodeStringToAnsiSize -RtlUnicodeStringToAnsiString -RtlUnicodeStringToCountedOemString -RtlUnicodeStringToInteger -RtlUnicodeStringToOemSize -RtlUnicodeStringToOemString -RtlUnicodeToCustomCPN -RtlUnicodeToMultiByteN -RtlUnicodeToMultiByteSize -RtlUnicodeToOemN -RtlUniform -RtlUnlockBootStatusData -RtlUnlockHeap -RtlUnlockMemoryStreamRegion -RtlUnwind -RtlUpcaseUnicodeChar -RtlUpcaseUnicodeString -RtlUpcaseUnicodeStringToAnsiString -RtlUpcaseUnicodeStringToCountedOemString -RtlUpcaseUnicodeStringToOemString -RtlUpcaseUnicodeToCustomCPN -RtlUpcaseUnicodeToMultiByteN -RtlUpcaseUnicodeToOemN -RtlUpdateTimer -RtlUpperChar -RtlUpperString -RtlValidAcl -RtlValidRelativeSecurityDescriptor -RtlValidSecurityDescriptor -RtlValidSid -RtlValidateHeap -RtlValidateProcessHeaps -RtlValidateUnicodeString -RtlVerifyVersionInfo -RtlWalkFrameChain -RtlWalkHeap -RtlWriteMemoryStream -RtlWriteRegistryValue -RtlZeroHeap -RtlZeroMemory -RtlZombifyActivationContext -RtlpApplyLengthFunction -RtlpEnsureBufferSize -RtlpNotOwnerCriticalSection -RtlpNtCreateKey -RtlpNtEnumerateSubKey -RtlpNtMakeTemporaryKey -RtlpNtOpenKey -RtlpNtQueryValueKey -RtlpNtSetValueKey -RtlpUnWaitCriticalSection -RtlpWaitForCriticalSection -RtlxAnsiStringToUnicodeSize -RtlxOemStringToUnicodeSize -RtlxUnicodeStringToAnsiSize -RtlxUnicodeStringToOemSize -VerSetConditionMask -ZwAcceptConnectPort -ZwAccessCheck -ZwAccessCheckAndAuditAlarm -ZwAccessCheckByType -ZwAccessCheckByTypeAndAuditAlarm -ZwAccessCheckByTypeResultList -ZwAccessCheckByTypeResultListAndAuditAlarm -ZwAccessCheckByTypeResultListAndAuditAlarmByHandle -ZwAddAtom -ZwAddBootEntry -ZwAdjustGroupsToken -ZwAdjustPrivilegesToken -ZwAlertResumeThread -ZwAlertThread -ZwAllocateLocallyUniqueId -ZwAllocateUserPhysicalPages -ZwAllocateUuids -ZwAllocateVirtualMemory -ZwAreMappedFilesTheSame -ZwAssignProcessToJobObject -ZwCallbackReturn -ZwCancelIoFile -ZwCancelTimer -ZwClearEvent -ZwClose -ZwCloseObjectAuditAlarm -ZwCompactKeys -ZwCompareTokens -ZwCompleteConnectPort -ZwCompressKey -ZwConnectPort -ZwContinue -ZwCreateDebugObject -ZwCreateDirectoryObject -ZwCreateEvent -ZwCreateEventPair -ZwCreateFile -ZwCreateIoCompletion -ZwCreateJobObject -ZwCreateJobSet -ZwCreateKey -ZwCreateKeyedEvent -ZwCreateMailslotFile -ZwCreateMutant -ZwCreateNamedPipeFile -ZwCreatePagingFile -ZwCreatePort -ZwCreateProcess -ZwCreateProcessEx -ZwCreateProfile -ZwCreateSection -ZwCreateSemaphore -ZwCreateSymbolicLinkObject -ZwCreateThread -ZwCreateTimer -ZwCreateToken -ZwCreateWaitablePort -ZwDebugActiveProcess -ZwDebugContinue -ZwDelayExecution -ZwDeleteAtom -ZwDeleteBootEntry -ZwDeleteFile -ZwDeleteKey -ZwDeleteObjectAuditAlarm -ZwDeleteValueKey -ZwDeviceIoControlFile -ZwDisplayString -ZwDuplicateObject -ZwDuplicateToken -ZwEnumerateBootEntries -ZwEnumerateKey -ZwEnumerateSystemEnvironmentValuesEx -ZwEnumerateValueKey -ZwExtendSection -ZwFilterToken -ZwFindAtom -ZwFlushBuffersFile -ZwFlushInstructionCache -ZwFlushKey -ZwFlushVirtualMemory -ZwFlushWriteBuffer -ZwFreeUserPhysicalPages -ZwFreeVirtualMemory -ZwFsControlFile -ZwGetContextThread -ZwGetDevicePowerState -ZwGetWriteWatch -ZwImpersonateAnonymousToken -ZwImpersonateClientOfPort -ZwImpersonateThread -ZwInitializeRegistry -ZwInitiatePowerAction -ZwIsProcessInJob -ZwIsSystemResumeAutomatic -ZwListenPort -ZwLoadDriver -ZwLoadKey -ZwLoadKey2 -ZwLockFile -ZwLockProductActivationKeys -ZwLockRegistryKey -ZwLockVirtualMemory -ZwMakePermanentObject -ZwMakeTemporaryObject -ZwMapUserPhysicalPages -ZwMapUserPhysicalPagesScatter -ZwMapViewOfSection -ZwModifyBootEntry -ZwNotifyChangeDirectoryFile -ZwNotifyChangeKey -ZwNotifyChangeMultipleKeys -ZwOpenDirectoryObject -ZwOpenEvent -ZwOpenEventPair -ZwOpenFile -ZwOpenIoCompletion -ZwOpenJobObject -ZwOpenKey -ZwOpenKeyedEvent -ZwOpenMutant -ZwOpenObjectAuditAlarm -ZwOpenProcess -ZwOpenProcessToken -ZwOpenProcessTokenEx -ZwOpenSection -ZwOpenSemaphore -ZwOpenSymbolicLinkObject -ZwOpenThread -ZwOpenThreadToken -ZwOpenThreadTokenEx -ZwOpenTimer -ZwPlugPlayControl -ZwPowerInformation -ZwPrivilegeCheck -ZwPrivilegeObjectAuditAlarm -ZwPrivilegedServiceAuditAlarm -ZwProtectVirtualMemory -ZwPulseEvent -ZwQueryAttributesFile -ZwQueryBootEntryOrder -ZwQueryBootOptions -ZwQueryDebugFilterState -ZwQueryDefaultLocale -ZwQueryDefaultUILanguage -ZwQueryDirectoryFile -ZwQueryDirectoryObject -ZwQueryEaFile -ZwQueryEvent -ZwQueryFullAttributesFile -ZwQueryInformationAtom -ZwQueryInformationFile -ZwQueryInformationJobObject -ZwQueryInformationPort -ZwQueryInformationProcess -ZwQueryInformationThread -ZwQueryInformationToken -ZwQueryInstallUILanguage -ZwQueryIntervalProfile -ZwQueryIoCompletion -ZwQueryKey -ZwQueryMultipleValueKey -ZwQueryMutant -ZwQueryObject -ZwQueryOpenSubKeys -ZwQueryPerformanceCounter -ZwQueryPortInformationProcess -ZwQueryQuotaInformationFile -ZwQuerySection -ZwQuerySecurityObject -ZwQuerySemaphore -ZwQuerySymbolicLinkObject -ZwQuerySystemEnvironmentValue -ZwQuerySystemEnvironmentValueEx -ZwQuerySystemInformation -ZwQuerySystemTime -ZwQueryTimer -ZwQueryTimerResolution -ZwQueryValueKey -ZwQueryVirtualMemory -ZwQueryVolumeInformationFile -ZwQueueApcThread -ZwRaiseException -ZwRaiseHardError -ZwReadFile -ZwReadFileScatter -ZwReadRequestData -ZwReadVirtualMemory -ZwRegisterThreadTerminatePort -ZwReleaseKeyedEvent -ZwReleaseMutant -ZwReleaseSemaphore -ZwRemoveIoCompletion -ZwRemoveProcessDebug -ZwRenameKey -ZwReplaceKey -ZwReplyPort -ZwReplyWaitReceivePort -ZwReplyWaitReceivePortEx -ZwReplyWaitReplyPort -ZwRequestPort -ZwRequestWaitReplyPort -ZwResetEvent -ZwResetWriteWatch -ZwRestoreKey -ZwResumeProcess -ZwResumeThread -ZwSaveKey -ZwSaveKeyEx -ZwSaveMergedKeys -ZwSecureConnectPort -ZwSetBootEntryOrder -ZwSetBootOptions -ZwSetContextThread -ZwSetDebugFilterState -ZwSetDefaultHardErrorPort -ZwSetDefaultLocale -ZwSetDefaultUILanguage -ZwSetEaFile -ZwSetEvent -ZwSetEventBoostPriority -ZwSetHighEventPair -ZwSetHighWaitLowEventPair -ZwSetInformationDebugObject -ZwSetInformationFile -ZwSetInformationJobObject -ZwSetInformationKey -ZwSetInformationObject -ZwSetInformationProcess -ZwSetInformationThread -ZwSetInformationToken -ZwSetIntervalProfile -ZwSetIoCompletion -ZwSetLdtEntries -ZwSetLowEventPair -ZwSetLowWaitHighEventPair -ZwSetQuotaInformationFile -ZwSetSecurityObject -ZwSetSystemEnvironmentValue -ZwSetSystemEnvironmentValueEx -ZwSetSystemInformation -ZwSetSystemPowerState -ZwSetSystemTime -ZwSetThreadExecutionState -ZwSetTimer -ZwSetTimerResolution -ZwSetUuidSeed -ZwSetValueKey -ZwSetVolumeInformationFile -ZwShutdownSystem -ZwSignalAndWaitForSingleObject -ZwStartProfile -ZwStopProfile -ZwSuspendProcess -ZwSuspendThread -ZwSystemDebugControl -ZwTerminateJobObject -ZwTerminateProcess -ZwTerminateThread -ZwTestAlert -ZwTraceEvent -ZwTranslateFilePath -ZwUnloadDriver -ZwUnloadKey -ZwUnloadKeyEx -ZwUnlockFile -ZwUnlockVirtualMemory -ZwUnmapViewOfSection -ZwVdmControl -ZwWaitForDebugEvent -ZwWaitForKeyedEvent -ZwWaitForMultipleObjects -ZwWaitForSingleObject -ZwWaitHighEventPair -ZwWaitLowEventPair -ZwWriteFile -ZwWriteFileGather -ZwWriteRequestData -ZwWriteVirtualMemory -ZwYieldExecution -__isascii -__iscsym -__iscsymf -__toascii -_alldiv -_alldvrm -_allmul -_allrem -_allshl -_allshr -_atoi64 -_aulldiv -_aulldvrm -_aullrem -_aullshr -_fltused -_i64toa -_i64tow -_itoa -_itow -_lfind -_ltoa -_ltow -_memccpy -_memicmp -_snprintf -_snwprintf -_splitpath -_strcmpi -_stricmp -_strlwr -_strnicmp -_strupr -_ui64toa -_ui64tow -_ultoa -_ultow -_vsnprintf -_vsnwprintf -_wcsicmp -_wcslwr -_wcsnicmp -_wcsupr -_wtoi -_wtoi64 -_wtol -abs -atan -atoi -atol -bsearch -ceil -cos -fabs -floor -isalnum -isalpha -iscntrl -isdigit -isgraph -islower -isprint -ispunct -isspace -isupper -iswalpha -iswctype -iswdigit -iswlower -iswspace -iswxdigit -isxdigit -labs -log -mbstowcs -memchr -memcmp -memcpy -memmove -memset -pow -qsort -sin -sprintf -sqrt -sscanf -strcat -strchr -strcmp -strcpy -strcspn -strlen -strncat -strncmp -strncpy -strpbrk -strrchr -strspn -strstr -strtol -strtoul -swprintf -tan -tolower -toupper -towlower -towupper -vDbgPrintEx -vDbgPrintExWithPrefix -vsprintf -wcscat -wcschr -wcscmp -wcscpy -wcscspn -wcslen -wcsncat -wcsncmp -wcsncpy -wcspbrk -wcsrchr -wcsspn -wcsstr -wcstol -wcstombs -wcstoul diff --git a/src/contrib/db/libmdbx/src/elements/osal.c b/src/contrib/db/libmdbx/src/elements/osal.c deleted file mode 100644 index 9f13d51..0000000 --- a/src/contrib/db/libmdbx/src/elements/osal.c +++ /dev/null @@ -1,1899 +0,0 @@ -/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "internals.h" - -#if defined(_WIN32) || defined(_WIN64) - -#include - -static int waitstatus2errcode(DWORD result) { - switch (result) { - case WAIT_OBJECT_0: - return MDBX_SUCCESS; - case WAIT_FAILED: - return GetLastError(); - case WAIT_ABANDONED: - return ERROR_ABANDONED_WAIT_0; - case WAIT_IO_COMPLETION: - return ERROR_USER_APC; - case WAIT_TIMEOUT: - return ERROR_TIMEOUT; - default: - return ERROR_UNHANDLED_ERROR; - } -} - -/* Map a result from an NTAPI call to WIN32 error code. */ -static int ntstatus2errcode(NTSTATUS status) { - DWORD dummy; - OVERLAPPED ov; - memset(&ov, 0, sizeof(ov)); - ov.Internal = status; - return GetOverlappedResult(NULL, &ov, &dummy, FALSE) ? MDBX_SUCCESS - : GetLastError(); -} - -/* We use native NT APIs to setup the memory map, so that we can - * let the DB file grow incrementally instead of always preallocating - * the full size. These APIs are defined in and - * but those headers are meant for driver-level development and - * conflict with the regular user-level headers, so we explicitly - * declare them here. Using these APIs also means we must link to - * ntdll.dll, which is not linked by default in user code. */ - -extern NTSTATUS NTAPI NtCreateSection( - OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, - IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, - IN OPTIONAL PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, - IN ULONG AllocationAttributes, IN OPTIONAL HANDLE FileHandle); - -typedef struct _SECTION_BASIC_INFORMATION { - ULONG Unknown; - ULONG SectionAttributes; - LARGE_INTEGER SectionSize; -} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; - -typedef enum _SECTION_INFORMATION_CLASS { - SectionBasicInformation, - SectionImageInformation, - SectionRelocationInformation, // name:wow64:whNtQuerySection_SectionRelocationInformation - MaxSectionInfoClass -} SECTION_INFORMATION_CLASS; - -extern NTSTATUS NTAPI NtQuerySection( - IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS InformationClass, - OUT PVOID InformationBuffer, IN ULONG InformationBufferSize, - OUT PULONG ResultLength OPTIONAL); - -extern NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, - IN PLARGE_INTEGER NewSectionSize); - -typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT; - -extern NTSTATUS NTAPI NtMapViewOfSection( - IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, - IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, - IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, IN OUT PSIZE_T ViewSize, - IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, - IN ULONG Win32Protect); - -extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, - IN OPTIONAL PVOID BaseAddress); - -extern NTSTATUS NTAPI NtClose(HANDLE Handle); - -extern NTSTATUS NTAPI NtAllocateVirtualMemory( - IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, - IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect); - -extern NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID *BaseAddress, - IN OUT PSIZE_T RegionSize, - IN ULONG FreeType); - -#ifndef WOF_CURRENT_VERSION -typedef struct _WOF_EXTERNAL_INFO { - DWORD Version; - DWORD Provider; -} WOF_EXTERNAL_INFO, *PWOF_EXTERNAL_INFO; -#endif /* WOF_CURRENT_VERSION */ - -#ifndef WIM_PROVIDER_CURRENT_VERSION -#define WIM_PROVIDER_HASH_SIZE 20 - -typedef struct _WIM_PROVIDER_EXTERNAL_INFO { - DWORD Version; - DWORD Flags; - LARGE_INTEGER DataSourceId; - BYTE ResourceHash[WIM_PROVIDER_HASH_SIZE]; -} WIM_PROVIDER_EXTERNAL_INFO, *PWIM_PROVIDER_EXTERNAL_INFO; -#endif /* WIM_PROVIDER_CURRENT_VERSION */ - -#ifndef FILE_PROVIDER_CURRENT_VERSION -typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 { - ULONG Version; - ULONG Algorithm; - ULONG Flags; -} FILE_PROVIDER_EXTERNAL_INFO_V1, *PFILE_PROVIDER_EXTERNAL_INFO_V1; -#endif /* FILE_PROVIDER_CURRENT_VERSION */ - -#ifndef STATUS_OBJECT_NOT_EXTERNALLY_BACKED -#define STATUS_OBJECT_NOT_EXTERNALLY_BACKED ((NTSTATUS)0xC000046DL) -#endif -#ifndef STATUS_INVALID_DEVICE_REQUEST -#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L) -#endif - -#ifndef FILE_DEVICE_FILE_SYSTEM -#define FILE_DEVICE_FILE_SYSTEM 0x00000009 -#endif - -#ifndef FSCTL_GET_EXTERNAL_BACKING -#define FSCTL_GET_EXTERNAL_BACKING \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 196, METHOD_BUFFERED, FILE_ANY_ACCESS) -#endif - -#endif /* _WIN32 || _WIN64 */ - -/*----------------------------------------------------------------------------*/ - -#if _POSIX_C_SOURCE > 200212 && \ - /* workaround for avoid musl libc wrong prototype */ ( \ - defined(__GLIBC__) || defined(__GNU_LIBRARY__)) -/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */ -__extern_C void __assert_fail(const char *assertion, const char *file, - unsigned line, const char *function) -#ifdef __THROW - __THROW -#else - __nothrow -#endif /* __THROW */ - __noreturn; - -#elif defined(__APPLE__) || defined(__MACH__) -__extern_C void __assert_rtn(const char *function, const char *file, int line, - const char *assertion) /* __nothrow */ -#ifdef __dead2 - __dead2 -#else - __noreturn -#endif /* __dead2 */ -#ifdef __disable_tail_calls - __disable_tail_calls -#endif /* __disable_tail_calls */ - ; - -#define __assert_fail(assertion, file, line, function) \ - __assert_rtn(function, file, line, assertion) -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ - defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \ - defined(__DragonFly__) -__extern_C void __assert(const char *function, const char *file, int line, - const char *assertion) /* __nothrow */ -#ifdef __dead2 - __dead2 -#else - __noreturn -#endif /* __dead2 */ -#ifdef __disable_tail_calls - __disable_tail_calls -#endif /* __disable_tail_calls */ - ; -#define __assert_fail(assertion, file, line, function) \ - __assert(function, file, line, assertion) - -#endif /* __assert_fail */ - -MDBX_INTERNAL_FUNC void __cold mdbx_assert_fail(const MDBX_env *env, - const char *msg, - const char *func, int line) { -#if MDBX_DEBUG - if (env && env->me_assert_func) { - env->me_assert_func(env, msg, func, line); - return; - } -#else - (void)env; -#endif /* MDBX_DEBUG */ - - if (mdbx_debug_logger) - mdbx_debug_log(MDBX_LOG_FATAL, func, line, "assert: %s\n", msg); - else { -#if defined(_WIN32) || defined(_WIN64) - char *message = nullptr; - const int num = mdbx_asprintf(&message, "\r\nMDBX-ASSERTION: %s, %s:%u", - msg, func ? func : "unknown", line); - if (num < 1 || !message) - message = ""; - OutputDebugStringA(message); - if (IsDebuggerPresent()) - DebugBreak(); -#else - __assert_fail(msg, "mdbx", line, func); -#endif - } - -#if defined(_WIN32) || defined(_WIN64) - FatalExit(ERROR_UNHANDLED_ERROR); -#else - abort(); -#endif -} - -MDBX_INTERNAL_FUNC __cold void mdbx_panic(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - - char *message = nullptr; - const int num = mdbx_vasprintf(&message, fmt, ap); - va_end(ap); - const char *const const_message = - (num < 1 || !message) ? "" - : message; - -#if defined(_WIN32) || defined(_WIN64) - OutputDebugStringA("\r\nMDBX-PANIC: "); - OutputDebugStringA(const_message); - if (IsDebuggerPresent()) - DebugBreak(); - FatalExit(ERROR_UNHANDLED_ERROR); -#else - __assert_fail(const_message, "mdbx", 0, "panic"); - abort(); -#endif -} - -/*----------------------------------------------------------------------------*/ - -#ifndef mdbx_vasprintf -MDBX_INTERNAL_FUNC int mdbx_vasprintf(char **strp, const char *fmt, - va_list ap) { - va_list ones; - va_copy(ones, ap); - int needed = vsnprintf(nullptr, 0, fmt, ap); - - if (unlikely(needed < 0 || needed >= INT_MAX)) { - *strp = nullptr; - va_end(ones); - return needed; - } - - *strp = mdbx_malloc(needed + 1); - if (unlikely(*strp == nullptr)) { - va_end(ones); -#if defined(_WIN32) || defined(_WIN64) - SetLastError(MDBX_ENOMEM); -#else - errno = MDBX_ENOMEM; -#endif - return -1; - } - - int actual = vsnprintf(*strp, needed + 1, fmt, ones); - va_end(ones); - - assert(actual == needed); - if (unlikely(actual < 0)) { - mdbx_free(*strp); - *strp = nullptr; - } - return actual; -} -#endif /* mdbx_vasprintf */ - -#ifndef mdbx_asprintf -MDBX_INTERNAL_FUNC int mdbx_asprintf(char **strp, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int rc = mdbx_vasprintf(strp, fmt, ap); - va_end(ap); - return rc; -} -#endif /* mdbx_asprintf */ - -#ifndef mdbx_memalign_alloc -MDBX_INTERNAL_FUNC int mdbx_memalign_alloc(size_t alignment, size_t bytes, - void **result) { -#if defined(_WIN32) || defined(_WIN64) - (void)alignment; - *result = VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - return *result ? MDBX_SUCCESS : MDBX_ENOMEM /* ERROR_OUTOFMEMORY */; -#elif defined(_ISOC11_SOURCE) - *result = aligned_alloc(alignment, bytes); - return *result ? MDBX_SUCCESS : errno; -#elif _POSIX_VERSION >= 200112L - *result = nullptr; - return posix_memalign(result, alignment, bytes); -#elif __GLIBC_PREREQ(2, 16) || __STDC_VERSION__ >= 201112L - *result = memalign(alignment, bytes); - return *result ? MDBX_SUCCESS : errno; -#else -#error FIXME -#endif -} -#endif /* mdbx_memalign_alloc */ - -#ifndef mdbx_memalign_free -MDBX_INTERNAL_FUNC void mdbx_memalign_free(void *ptr) { -#if defined(_WIN32) || defined(_WIN64) - VirtualFree(ptr, 0, MEM_RELEASE); -#else - mdbx_free(ptr); -#endif -} -#endif /* mdbx_memalign_free */ - -#ifndef mdbx_strdup -char *mdbx_strdup(const char *str) { - if (!str) - return NULL; - size_t bytes = strlen(str) + 1; - char *dup = mdbx_malloc(bytes); - if (dup) - memcpy(dup, str, bytes); - return dup; -} -#endif /* mdbx_strdup */ - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int mdbx_condmutex_init(mdbx_condmutex_t *condmutex) { -#if defined(_WIN32) || defined(_WIN64) - int rc = MDBX_SUCCESS; - condmutex->event = NULL; - condmutex->mutex = CreateMutex(NULL, FALSE, NULL); - if (!condmutex->mutex) - return GetLastError(); - - condmutex->event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!condmutex->event) { - rc = GetLastError(); - (void)CloseHandle(condmutex->mutex); - condmutex->mutex = NULL; - } - return rc; -#else - memset(condmutex, 0, sizeof(mdbx_condmutex_t)); - int rc = pthread_mutex_init(&condmutex->mutex, NULL); - if (rc == 0) { - rc = pthread_cond_init(&condmutex->cond, NULL); - if (rc != 0) - (void)pthread_mutex_destroy(&condmutex->mutex); - } - return rc; -#endif -} - -static bool is_allzeros(const void *ptr, size_t bytes) { - const uint8_t *u8 = ptr; - for (size_t i = 0; i < bytes; ++i) - if (u8[i] != 0) - return false; - return true; -} - -MDBX_INTERNAL_FUNC int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex) { - int rc = MDBX_EINVAL; -#if defined(_WIN32) || defined(_WIN64) - if (condmutex->event) { - rc = CloseHandle(condmutex->event) ? MDBX_SUCCESS : GetLastError(); - if (rc == MDBX_SUCCESS) - condmutex->event = NULL; - } - if (condmutex->mutex) { - rc = CloseHandle(condmutex->mutex) ? MDBX_SUCCESS : GetLastError(); - if (rc == MDBX_SUCCESS) - condmutex->mutex = NULL; - } -#else - if (!is_allzeros(&condmutex->cond, sizeof(condmutex->cond))) { - rc = pthread_cond_destroy(&condmutex->cond); - if (rc == 0) - memset(&condmutex->cond, 0, sizeof(condmutex->cond)); - } - if (!is_allzeros(&condmutex->mutex, sizeof(condmutex->mutex))) { - rc = pthread_mutex_destroy(&condmutex->mutex); - if (rc == 0) - memset(&condmutex->mutex, 0, sizeof(condmutex->mutex)); - } -#endif - return rc; -} - -MDBX_INTERNAL_FUNC int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex) { -#if defined(_WIN32) || defined(_WIN64) - DWORD code = WaitForSingleObject(condmutex->mutex, INFINITE); - return waitstatus2errcode(code); -#else - return pthread_mutex_lock(&condmutex->mutex); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex) { -#if defined(_WIN32) || defined(_WIN64) - return ReleaseMutex(condmutex->mutex) ? MDBX_SUCCESS : GetLastError(); -#else - return pthread_mutex_unlock(&condmutex->mutex); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex) { -#if defined(_WIN32) || defined(_WIN64) - return SetEvent(condmutex->event) ? MDBX_SUCCESS : GetLastError(); -#else - return pthread_cond_signal(&condmutex->cond); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex) { -#if defined(_WIN32) || defined(_WIN64) - DWORD code = - SignalObjectAndWait(condmutex->mutex, condmutex->event, INFINITE, FALSE); - if (code == WAIT_OBJECT_0) - code = WaitForSingleObject(condmutex->mutex, INFINITE); - return waitstatus2errcode(code); -#else - return pthread_cond_wait(&condmutex->cond, &condmutex->mutex); -#endif -} - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex) { -#if defined(_WIN32) || defined(_WIN64) - InitializeCriticalSection(fastmutex); - return MDBX_SUCCESS; -#else - return pthread_mutex_init(fastmutex, NULL); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex) { -#if defined(_WIN32) || defined(_WIN64) - DeleteCriticalSection(fastmutex); - return MDBX_SUCCESS; -#else - return pthread_mutex_destroy(fastmutex); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex) { -#if defined(_WIN32) || defined(_WIN64) - EnterCriticalSection(fastmutex); - return MDBX_SUCCESS; -#else - return pthread_mutex_lock(fastmutex); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) { -#if defined(_WIN32) || defined(_WIN64) - LeaveCriticalSection(fastmutex); - return MDBX_SUCCESS; -#else - return pthread_mutex_unlock(fastmutex); -#endif -} - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) { -#if defined(_WIN32) || defined(_WIN64) - return DeleteFileA(pathname) ? MDBX_SUCCESS : GetLastError(); -#else - return unlink(pathname) ? errno : MDBX_SUCCESS; -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_openfile(const char *pathname, int flags, - mode_t mode, mdbx_filehandle_t *fd, - bool exclusive) { - *fd = INVALID_HANDLE_VALUE; -#if defined(_WIN32) || defined(_WIN64) - (void)mode; - size_t wlen = mbstowcs(nullptr, pathname, INT_MAX); - if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX) - return ERROR_INVALID_NAME; - wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t)); - if (wlen != mbstowcs(pathnameW, pathname, wlen + 1)) - return ERROR_INVALID_NAME; - - DWORD DesiredAccess, ShareMode; - DWORD FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; - switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { - default: - return ERROR_INVALID_PARAMETER; - case O_RDONLY: - DesiredAccess = GENERIC_READ; - ShareMode = - exclusive ? FILE_SHARE_READ : (FILE_SHARE_READ | FILE_SHARE_WRITE); - break; - case O_WRONLY: /* assume for MDBX_env_copy() and friends output */ - DesiredAccess = GENERIC_WRITE; - ShareMode = 0; - FlagsAndAttributes |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; - break; - case O_RDWR: - DesiredAccess = GENERIC_READ | GENERIC_WRITE; - ShareMode = exclusive ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); - break; - } - - DWORD CreationDisposition; - switch (flags & (O_EXCL | O_CREAT)) { - default: - return ERROR_INVALID_PARAMETER; - case 0: - CreationDisposition = OPEN_EXISTING; - break; - case O_EXCL | O_CREAT: - CreationDisposition = CREATE_NEW; - FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; - break; - case O_CREAT: - CreationDisposition = OPEN_ALWAYS; - FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; - break; - } - - *fd = CreateFileW(pathnameW, DesiredAccess, ShareMode, NULL, - CreationDisposition, FlagsAndAttributes, NULL); - - if (*fd == INVALID_HANDLE_VALUE) - return GetLastError(); - if ((flags & O_CREAT) && GetLastError() != ERROR_ALREADY_EXISTS) { - /* set FILE_ATTRIBUTE_NOT_CONTENT_INDEXED for new file */ - DWORD FileAttributes = GetFileAttributesA(pathname); - if (FileAttributes == INVALID_FILE_ATTRIBUTES || - !SetFileAttributesA(pathname, FileAttributes | - FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) { - int rc = GetLastError(); - CloseHandle(*fd); - *fd = INVALID_HANDLE_VALUE; - return rc; - } - } -#else - (void)exclusive; -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif /* O_CLOEXEC */ - *fd = open(pathname, flags, mode); - if (*fd < 0) - return errno; - -#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC) - int fd_flags = fcntl(*fd, F_GETFD); - if (fd_flags != -1) - (void)fcntl(*fd, F_SETFD, fd_flags | FD_CLOEXEC); -#endif /* FD_CLOEXEC && !O_CLOEXEC */ - - if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) { - /* assume for MDBX_env_copy() and friends output */ -#if defined(O_DIRECT) - int fd_flags = fcntl(*fd, F_GETFD); - if (fd_flags != -1) - (void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT); -#endif /* O_DIRECT */ -#if defined(F_NOCACHE) - (void)fcntl(*fd, F_NOCACHE, 1); -#endif /* F_NOCACHE */ - } -#endif - - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_closefile(mdbx_filehandle_t fd) { -#if defined(_WIN32) || defined(_WIN64) - return CloseHandle(fd) ? MDBX_SUCCESS : GetLastError(); -#else - return (close(fd) == 0) ? MDBX_SUCCESS : errno; -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t bytes, - uint64_t offset) { - if (bytes > MAX_WRITE) - return MDBX_EINVAL; -#if defined(_WIN32) || defined(_WIN64) - OVERLAPPED ov; - ov.hEvent = 0; - ov.Offset = (DWORD)offset; - ov.OffsetHigh = HIGH_DWORD(offset); - - DWORD read = 0; - if (unlikely(!ReadFile(fd, buf, (DWORD)bytes, &read, &ov))) { - int rc = GetLastError(); - return (rc == MDBX_SUCCESS) ? /* paranoia */ ERROR_READ_FAULT : rc; - } -#else - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - intptr_t read = pread(fd, buf, bytes, offset); - if (read < 0) { - int rc = errno; - return (rc == MDBX_SUCCESS) ? /* paranoia */ MDBX_EIO : rc; - } -#endif - return (bytes == (size_t)read) ? MDBX_SUCCESS : MDBX_ENODATA; -} - -MDBX_INTERNAL_FUNC int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, - size_t bytes, uint64_t offset) { - while (true) { -#if defined(_WIN32) || defined(_WIN64) - OVERLAPPED ov; - ov.hEvent = 0; - ov.Offset = (DWORD)offset; - ov.OffsetHigh = HIGH_DWORD(offset); - - DWORD written; - if (unlikely(!WriteFile( - fd, buf, likely(bytes <= MAX_WRITE) ? (DWORD)bytes : MAX_WRITE, - &written, &ov))) - return GetLastError(); - if (likely(bytes == written)) - return MDBX_SUCCESS; -#else - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - const intptr_t written = - pwrite(fd, buf, likely(bytes <= MAX_WRITE) ? bytes : MAX_WRITE, offset); - if (likely(bytes == (size_t)written)) - return MDBX_SUCCESS; - if (written < 0) { - const int rc = errno; - if (rc != EINTR) - return rc; - continue; - } -#endif - bytes -= written; - offset += written; - buf = (char *)buf + written; - } -} - -MDBX_INTERNAL_FUNC int mdbx_write(mdbx_filehandle_t fd, const void *buf, - size_t bytes) { - while (true) { -#if defined(_WIN32) || defined(_WIN64) - DWORD written; - if (unlikely(!WriteFile( - fd, buf, likely(bytes <= MAX_WRITE) ? (DWORD)bytes : MAX_WRITE, - &written, nullptr))) - return GetLastError(); - if (likely(bytes == written)) - return MDBX_SUCCESS; -#else - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - const intptr_t written = - write(fd, buf, likely(bytes <= MAX_WRITE) ? bytes : MAX_WRITE); - if (likely(bytes == (size_t)written)) - return MDBX_SUCCESS; - if (written < 0) { - const int rc = errno; - if (rc != EINTR) - return rc; - continue; - } -#endif - bytes -= written; - buf = (char *)buf + written; - } -} - -int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt, - uint64_t offset, size_t expected_written) { -#if defined(_WIN32) || defined(_WIN64) || defined(__APPLE__) - size_t written = 0; - for (int i = 0; i < iovcnt; ++i) { - int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - written += iov[i].iov_len; - offset += iov[i].iov_len; - } - return (expected_written == written) ? MDBX_SUCCESS - : MDBX_EIO /* ERROR_WRITE_FAULT */; -#else - int rc; - intptr_t written; - do { - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - written = pwritev(fd, iov, iovcnt, offset); - if (likely(expected_written == (size_t)written)) - return MDBX_SUCCESS; - rc = errno; - } while (rc == EINTR); - return (written < 0) ? rc : MDBX_EIO /* Use which error code? */; -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_filesync(mdbx_filehandle_t fd, - enum mdbx_syncmode_bits mode_bits) { -#if defined(_WIN32) || defined(_WIN64) - return ((mode_bits & (MDBX_SYNC_DATA | MDBX_SYNC_IODQ)) == 0 || - FlushFileBuffers(fd)) - ? MDBX_SUCCESS - : GetLastError(); -#else - -#if defined(__APPLE__) && \ - MDBX_OSX_SPEED_INSTEADOF_DURABILITY == MDBX_OSX_WANNA_DURABILITY - if (mode_bits & MDBX_SYNC_IODQ) - return likely(fcntl(fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno; -#endif /* MacOS */ -#if defined(__linux__) || defined(__gnu_linux__) - if (mode_bits == MDBX_SYNC_SIZE && mdbx_linux_kernel_version >= 0x03060000) - return MDBX_SUCCESS; -#endif /* Linux */ - int rc; - do { -#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 - /* LY: This code is always safe and without appreciable performance - * degradation, even on a kernel with fdatasync's bug. - * - * For more info about of a corresponding fdatasync() bug - * see http://www.spinics.net/lists/linux-ext4/msg33714.html */ - if ((mode_bits & MDBX_SYNC_SIZE) == 0) { - if (fdatasync(fd) == 0) - return MDBX_SUCCESS; - } else -#else - (void)mode_bits; -#endif - if (fsync(fd) == 0) - return MDBX_SUCCESS; - rc = errno; - } while (rc == EINTR); - return rc; -#endif -} - -int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) { -#if defined(_WIN32) || defined(_WIN64) - BY_HANDLE_FILE_INFORMATION info; - if (!GetFileInformationByHandle(fd, &info)) - return GetLastError(); - *length = info.nFileSizeLow | (uint64_t)info.nFileSizeHigh << 32; -#else - struct stat st; - - STATIC_ASSERT_MSG(sizeof(off_t) <= sizeof(uint64_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - if (fstat(fd, &st)) - return errno; - - *length = st.st_size; -#endif - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_is_pipe(mdbx_filehandle_t fd) { -#if defined(_WIN32) || defined(_WIN64) - switch (GetFileType(fd)) { - case FILE_TYPE_DISK: - return MDBX_RESULT_FALSE; - case FILE_TYPE_CHAR: - case FILE_TYPE_PIPE: - return MDBX_RESULT_TRUE; - default: - return GetLastError(); - } -#else - struct stat info; - if (fstat(fd, &info)) - return errno; - switch (info.st_mode & S_IFMT) { - case S_IFBLK: - case S_IFREG: - return MDBX_RESULT_FALSE; - case S_IFCHR: - case S_IFIFO: - case S_IFSOCK: - return MDBX_RESULT_TRUE; - case S_IFDIR: - case S_IFLNK: - default: - return MDBX_INCOMPATIBLE; - } -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length) { -#if defined(_WIN32) || defined(_WIN64) - if (mdbx_SetFileInformationByHandle) { - FILE_END_OF_FILE_INFO EndOfFileInfo; - EndOfFileInfo.EndOfFile.QuadPart = length; - return mdbx_SetFileInformationByHandle(fd, FileEndOfFileInfo, - &EndOfFileInfo, - sizeof(FILE_END_OF_FILE_INFO)) - ? MDBX_SUCCESS - : GetLastError(); - } else { - LARGE_INTEGER li; - li.QuadPart = length; - return (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) && SetEndOfFile(fd)) - ? MDBX_SUCCESS - : GetLastError(); - } -#else - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - return ftruncate(fd, length) == 0 ? MDBX_SUCCESS : errno; -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos) { -#if defined(_WIN32) || defined(_WIN64) - LARGE_INTEGER li; - li.QuadPart = pos; - return SetFilePointerEx(fd, li, NULL, FILE_BEGIN) ? MDBX_SUCCESS - : GetLastError(); -#else - STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - return (lseek(fd, pos, SEEK_SET) < 0) ? errno : MDBX_SUCCESS; -#endif -} - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int -mdbx_thread_create(mdbx_thread_t *thread, - THREAD_RESULT(THREAD_CALL *start_routine)(void *), - void *arg) { -#if defined(_WIN32) || defined(_WIN64) - *thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL); - return *thread ? MDBX_SUCCESS : GetLastError(); -#else - return pthread_create(thread, NULL, start_routine, arg); -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_thread_join(mdbx_thread_t thread) { -#if defined(_WIN32) || defined(_WIN64) - DWORD code = WaitForSingleObject(thread, INFINITE); - return waitstatus2errcode(code); -#else - void *unused_retval = &unused_retval; - return pthread_join(thread, &unused_retval); -#endif -} - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC int mdbx_msync(mdbx_mmap_t *map, size_t offset, - size_t length, int async) { - uint8_t *ptr = (uint8_t *)map->address + offset; -#if defined(_WIN32) || defined(_WIN64) - if (FlushViewOfFile(ptr, length) && (async || FlushFileBuffers(map->fd))) - return MDBX_SUCCESS; - return GetLastError(); -#else -#if defined(__linux__) || defined(__gnu_linux__) - if (async && mdbx_linux_kernel_version > 0x02061300) - /* Since Linux 2.6.19, MS_ASYNC is in fact a no-op, - since the kernel properly tracks dirty pages and flushes them to storage - as necessary. */ - return MDBX_SUCCESS; -#endif /* Linux */ - const int mode = async ? MS_ASYNC : MS_SYNC; - int rc = (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno; -#if defined(__APPLE__) && \ - MDBX_OSX_SPEED_INSTEADOF_DURABILITY == MDBX_OSX_WANNA_DURABILITY - if (rc == MDBX_SUCCESS && mode == MS_SYNC) - rc = likely(fcntl(map->fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno; -#endif /* MacOS */ - return rc; -#endif -} - -MDBX_INTERNAL_FUNC int mdbx_check4nonlocal(mdbx_filehandle_t handle, - int flags) { -#if defined(_WIN32) || defined(_WIN64) - if (GetFileType(handle) != FILE_TYPE_DISK) - return ERROR_FILE_OFFLINE; - - if (mdbx_GetFileInformationByHandleEx) { - FILE_REMOTE_PROTOCOL_INFO RemoteProtocolInfo; - if (mdbx_GetFileInformationByHandleEx(handle, FileRemoteProtocolInfo, - &RemoteProtocolInfo, - sizeof(RemoteProtocolInfo))) { - - if ((RemoteProtocolInfo.Flags & REMOTE_PROTOCOL_INFO_FLAG_OFFLINE) && - !(flags & MDBX_RDONLY)) - return ERROR_FILE_OFFLINE; - if (!(RemoteProtocolInfo.Flags & REMOTE_PROTOCOL_INFO_FLAG_LOOPBACK) && - !(flags & MDBX_EXCLUSIVE)) - return ERROR_REMOTE_STORAGE_MEDIA_ERROR; - } - } - - if (mdbx_NtFsControlFile) { - NTSTATUS rc; - struct { - WOF_EXTERNAL_INFO wof_info; - union { - WIM_PROVIDER_EXTERNAL_INFO wim_info; - FILE_PROVIDER_EXTERNAL_INFO_V1 file_info; - }; - size_t reserved_for_microsoft_madness[42]; - } GetExternalBacking_OutputBuffer; - IO_STATUS_BLOCK StatusBlock; - rc = mdbx_NtFsControlFile(handle, NULL, NULL, NULL, &StatusBlock, - FSCTL_GET_EXTERNAL_BACKING, NULL, 0, - &GetExternalBacking_OutputBuffer, - sizeof(GetExternalBacking_OutputBuffer)); - if (NT_SUCCESS(rc)) { - if (!(flags & MDBX_EXCLUSIVE)) - return ERROR_REMOTE_STORAGE_MEDIA_ERROR; - } else if (rc != STATUS_OBJECT_NOT_EXTERNALLY_BACKED && - rc != STATUS_INVALID_DEVICE_REQUEST) - return ntstatus2errcode(rc); - } - - if (mdbx_GetVolumeInformationByHandleW && mdbx_GetFinalPathNameByHandleW) { - WCHAR *PathBuffer = mdbx_malloc(sizeof(WCHAR) * INT16_MAX); - if (!PathBuffer) - return MDBX_ENOMEM; - - int rc = MDBX_SUCCESS; - DWORD VolumeSerialNumber, FileSystemFlags; - if (!mdbx_GetVolumeInformationByHandleW(handle, PathBuffer, INT16_MAX, - &VolumeSerialNumber, NULL, - &FileSystemFlags, NULL, 0)) { - rc = GetLastError(); - goto bailout; - } - - if ((flags & MDBX_RDONLY) == 0) { - if (FileSystemFlags & - (FILE_SEQUENTIAL_WRITE_ONCE | FILE_READ_ONLY_VOLUME | - FILE_VOLUME_IS_COMPRESSED)) { - rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; - goto bailout; - } - } - - if (!mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX, - FILE_NAME_NORMALIZED | - VOLUME_NAME_NT)) { - rc = GetLastError(); - goto bailout; - } - - if (_wcsnicmp(PathBuffer, L"\\Device\\Mup\\", 12) == 0) { - if (!(flags & MDBX_EXCLUSIVE)) { - rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; - goto bailout; - } - } else if (mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX, - FILE_NAME_NORMALIZED | - VOLUME_NAME_DOS)) { - UINT DriveType = GetDriveTypeW(PathBuffer); - if (DriveType == DRIVE_NO_ROOT_DIR && - _wcsnicmp(PathBuffer, L"\\\\?\\", 4) == 0 && - _wcsnicmp(PathBuffer + 5, L":\\", 2) == 0) { - PathBuffer[7] = 0; - DriveType = GetDriveTypeW(PathBuffer + 4); - } - switch (DriveType) { - case DRIVE_CDROM: - if (flags & MDBX_RDONLY) - break; - // fall through - case DRIVE_UNKNOWN: - case DRIVE_NO_ROOT_DIR: - case DRIVE_REMOTE: - default: - if (!(flags & MDBX_EXCLUSIVE)) - rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; - // fall through - case DRIVE_REMOVABLE: - case DRIVE_FIXED: - case DRIVE_RAMDISK: - break; - } - } - bailout: - mdbx_free(PathBuffer); - return rc; - } -#else - (void)handle; - /* TODO: check for NFS handle ? */ - (void)flags; -#endif - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_mmap(const int flags, mdbx_mmap_t *map, - const size_t size, const size_t limit, - const bool truncate) { - assert(size <= limit); - map->limit = 0; - map->current = 0; - map->address = nullptr; -#if defined(_WIN32) || defined(_WIN64) - map->section = NULL; - map->filesize = 0; -#endif /* Windows */ - - int err = mdbx_check4nonlocal(map->fd, flags); - if (unlikely(err != MDBX_SUCCESS)) - return err; - - if ((flags & MDBX_RDONLY) == 0 && truncate) { - err = mdbx_ftruncate(map->fd, size); - if (err != MDBX_SUCCESS) - return err; -#if defined(_WIN32) || defined(_WIN64) - map->filesize = size; -#else - map->current = size; -#endif - } else { - uint64_t filesize; - err = mdbx_filesize(map->fd, &filesize); - if (err != MDBX_SUCCESS) - return err; -#if defined(_WIN32) || defined(_WIN64) - map->filesize = filesize; -#else - map->current = (filesize > limit) ? limit : (size_t)filesize; -#endif - } - -#if defined(_WIN32) || defined(_WIN64) - LARGE_INTEGER SectionSize; - SectionSize.QuadPart = size; - err = NtCreateSection( - &map->section, - /* DesiredAccess */ - (flags & MDBX_WRITEMAP) - ? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE | - SECTION_MAP_WRITE - : SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE, - /* ObjectAttributes */ NULL, /* MaximumSize (InitialSize) */ &SectionSize, - /* SectionPageProtection */ - (flags & MDBX_RDONLY) ? PAGE_READONLY : PAGE_READWRITE, - /* AllocationAttributes */ SEC_RESERVE, map->fd); - if (!NT_SUCCESS(err)) - return ntstatus2errcode(err); - - SIZE_T ViewSize = (flags & MDBX_RDONLY) ? 0 : limit; - err = NtMapViewOfSection( - map->section, GetCurrentProcess(), &map->address, - /* ZeroBits */ 0, - /* CommitSize */ 0, - /* SectionOffset */ NULL, &ViewSize, - /* InheritDisposition */ ViewUnmap, - /* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE, - /* Win32Protect */ - (flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY); - if (!NT_SUCCESS(err)) { - NtClose(map->section); - map->section = 0; - map->address = nullptr; - return ntstatus2errcode(err); - } - assert(map->address != MAP_FAILED); - - map->current = (size_t)SectionSize.QuadPart; - map->limit = ViewSize; - -#else - - map->address = mmap( - NULL, limit, (flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ, - MAP_SHARED, map->fd, 0); - - if (unlikely(map->address == MAP_FAILED)) { - map->limit = 0; - map->current = 0; - map->address = nullptr; - return errno; - } - map->limit = limit; - -#ifdef MADV_DONTFORK - if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0)) - return errno; -#endif -#ifdef MADV_NOHUGEPAGE - (void)madvise(map->address, map->limit, MADV_NOHUGEPAGE); -#endif - -#endif - - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_munmap(mdbx_mmap_t *map) { -#if defined(_WIN32) || defined(_WIN64) - if (map->section) - NtClose(map->section); - NTSTATUS rc = NtUnmapViewOfSection(GetCurrentProcess(), map->address); - if (!NT_SUCCESS(rc)) - ntstatus2errcode(rc); -#else - if (unlikely(munmap(map->address, map->limit))) - return errno; -#endif - - map->limit = 0; - map->current = 0; - map->address = nullptr; - return MDBX_SUCCESS; -} - -MDBX_INTERNAL_FUNC int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size, - size_t limit) { - assert(size <= limit); -#if defined(_WIN32) || defined(_WIN64) - assert(size != map->current || limit != map->limit || size < map->filesize); - - NTSTATUS status; - LARGE_INTEGER SectionSize; - int err, rc = MDBX_SUCCESS; - - if (!(flags & MDBX_RDONLY) && limit == map->limit && size > map->current) { - /* growth rw-section */ - SectionSize.QuadPart = size; - status = NtExtendSection(map->section, &SectionSize); - if (NT_SUCCESS(status)) { - map->current = size; - if (map->filesize < size) - map->filesize = size; - } - return ntstatus2errcode(status); - } - - if (limit > map->limit) { - /* check ability of address space for growth before umnap */ - PVOID BaseAddress = (PBYTE)map->address + map->limit; - SIZE_T RegionSize = limit - map->limit; - status = NtAllocateVirtualMemory(GetCurrentProcess(), &BaseAddress, 0, - &RegionSize, MEM_RESERVE, PAGE_NOACCESS); - if (!NT_SUCCESS(status)) - return ntstatus2errcode(status); - - status = NtFreeVirtualMemory(GetCurrentProcess(), &BaseAddress, &RegionSize, - MEM_RELEASE); - if (!NT_SUCCESS(status)) - return ntstatus2errcode(status); - } - - /* Windows unable: - * - shrink a mapped file; - * - change size of mapped view; - * - extend read-only mapping; - * Therefore we should unmap/map entire section. */ - status = NtUnmapViewOfSection(GetCurrentProcess(), map->address); - if (!NT_SUCCESS(status)) - return ntstatus2errcode(status); - status = NtClose(map->section); - map->section = NULL; - PVOID ReservedAddress = NULL; - SIZE_T ReservedSize = limit; - - if (!NT_SUCCESS(status)) { - bailout_ntstatus: - err = ntstatus2errcode(status); - bailout: - map->address = NULL; - map->current = map->limit = 0; - if (ReservedAddress) - (void)NtFreeVirtualMemory(GetCurrentProcess(), &ReservedAddress, - &ReservedSize, MEM_RELEASE); - return err; - } - - /* resizing of the file may take a while, - * therefore we reserve address space to avoid occupy it by other threads */ - ReservedAddress = map->address; - status = NtAllocateVirtualMemory(GetCurrentProcess(), &ReservedAddress, 0, - &ReservedSize, MEM_RESERVE, PAGE_NOACCESS); - if (!NT_SUCCESS(status)) { - ReservedAddress = NULL; - if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018) - goto bailout_ntstatus /* no way to recovery */; - - /* assume we can change base address if mapping size changed or prev address - * couldn't be used */ - map->address = NULL; - } - -retry_file_and_section: - err = mdbx_filesize(map->fd, &map->filesize); - if (err != MDBX_SUCCESS) - goto bailout; - - if ((flags & MDBX_RDONLY) == 0 && map->filesize != size) { - err = mdbx_ftruncate(map->fd, size); - if (err == MDBX_SUCCESS) - map->filesize = size; - /* ignore error, because Windows unable shrink file - * that already mapped (by another process) */ - } - - SectionSize.QuadPart = size; - status = NtCreateSection( - &map->section, - /* DesiredAccess */ - (flags & MDBX_WRITEMAP) - ? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE | - SECTION_MAP_WRITE - : SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE, - /* ObjectAttributes */ NULL, - /* MaximumSize (InitialSize) */ &SectionSize, - /* SectionPageProtection */ - (flags & MDBX_RDONLY) ? PAGE_READONLY : PAGE_READWRITE, - /* AllocationAttributes */ SEC_RESERVE, map->fd); - - if (!NT_SUCCESS(status)) - goto bailout_ntstatus; - - if (ReservedAddress) { - /* release reserved address space */ - status = NtFreeVirtualMemory(GetCurrentProcess(), &ReservedAddress, - &ReservedSize, MEM_RELEASE); - ReservedAddress = NULL; - if (!NT_SUCCESS(status)) - goto bailout_ntstatus; - } - -retry_mapview:; - SIZE_T ViewSize = (flags & MDBX_RDONLY) ? size : limit; - status = NtMapViewOfSection( - map->section, GetCurrentProcess(), &map->address, - /* ZeroBits */ 0, - /* CommitSize */ 0, - /* SectionOffset */ NULL, &ViewSize, - /* InheritDisposition */ ViewUnmap, - /* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE, - /* Win32Protect */ - (flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY); - - if (!NT_SUCCESS(status)) { - if (status == /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 && - map->address) { - /* try remap at another base address */ - map->address = NULL; - goto retry_mapview; - } - NtClose(map->section); - map->section = NULL; - - if (map->address && (size != map->current || limit != map->limit)) { - /* try remap with previously size and limit, - * but will return MDBX_RESULT_TRUE on success */ - rc = MDBX_RESULT_TRUE; - size = map->current; - limit = map->limit; - goto retry_file_and_section; - } - - /* no way to recovery */ - goto bailout_ntstatus; - } - assert(map->address != MAP_FAILED); - - map->current = (size_t)SectionSize.QuadPart; - map->limit = ViewSize; -#else - - uint64_t filesize; - int rc = mdbx_filesize(map->fd, &filesize); - if (rc != MDBX_SUCCESS) - return rc; - - if (flags & MDBX_RDONLY) { - map->current = (filesize > limit) ? limit : (size_t)filesize; - if (map->current != size) - rc = MDBX_RESULT_TRUE; - } else if (filesize != size) { - rc = mdbx_ftruncate(map->fd, size); - if (rc != MDBX_SUCCESS) - return rc; - map->current = size; - } - - if (limit != map->limit) { -#if defined(_GNU_SOURCE) && (defined(__linux__) || defined(__gnu_linux__)) - void *ptr = mremap(map->address, map->limit, limit, - /* LY: in case changing the mapping size calling code - must guarantees the absence of competing threads, - and a willingness to another base address */ - MREMAP_MAYMOVE); - if (ptr == MAP_FAILED) { - rc = errno; - return (rc == EAGAIN || rc == ENOMEM) ? MDBX_RESULT_TRUE : rc; - } - map->address = ptr; - map->limit = limit; - -#ifdef MADV_DONTFORK - if (unlikely(madvise(map->address, map->limit, MADV_DONTFORK) != 0)) - return errno; -#endif - -#ifdef MADV_NOHUGEPAGE - (void)madvise(map->address, map->limit, MADV_NOHUGEPAGE); -#endif - -#else - rc = MDBX_RESULT_TRUE; -#endif /* _GNU_SOURCE && __linux__ */ - } -#endif - return rc; -} - -/*----------------------------------------------------------------------------*/ - -MDBX_INTERNAL_FUNC __cold void mdbx_osal_jitter(bool tiny) { - for (;;) { -#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ - defined(__x86_64__) - const unsigned salt = 277u * (unsigned)__rdtsc(); -#else - const unsigned salt = rand(); -#endif - - const unsigned coin = salt % (tiny ? 29u : 43u); - if (coin < 43 / 3) - break; -#if defined(_WIN32) || defined(_WIN64) - SwitchToThread(); - if (coin > 43 * 2 / 3) - Sleep(1); -#else - sched_yield(); - if (coin > 43 * 2 / 3) - usleep(coin); -#endif - } -} - -#if defined(_WIN32) || defined(_WIN64) -#elif defined(__APPLE__) || defined(__MACH__) -#include -#elif defined(__linux__) || defined(__gnu_linux__) -static __cold clockid_t choice_monoclock(void) { - struct timespec probe; -#if defined(CLOCK_BOOTTIME) - if (clock_gettime(CLOCK_BOOTTIME, &probe) == 0) - return CLOCK_BOOTTIME; -#elif defined(CLOCK_MONOTONIC_RAW) - if (clock_gettime(CLOCK_MONOTONIC_RAW, &probe) == 0) - return CLOCK_MONOTONIC_RAW; -#elif defined(CLOCK_MONOTONIC_COARSE) - if (clock_gettime(CLOCK_MONOTONIC_COARSE, &probe) == 0) - return CLOCK_MONOTONIC_COARSE; -#endif - return CLOCK_MONOTONIC; -} -#endif - -/*----------------------------------------------------------------------------*/ - -#if defined(_WIN32) || defined(_WIN64) -static LARGE_INTEGER performance_frequency; -#elif defined(__APPLE__) || defined(__MACH__) -static uint64_t ratio_16dot16_to_monotine; -#endif - -MDBX_INTERNAL_FUNC uint64_t -mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16) { -#if defined(_WIN32) || defined(_WIN64) - if (unlikely(performance_frequency.QuadPart == 0)) - QueryPerformanceFrequency(&performance_frequency); - const uint64_t ratio = performance_frequency.QuadPart; -#elif defined(__APPLE__) || defined(__MACH__) - if (unlikely(ratio_16dot16_to_monotine == 0)) { - mach_timebase_info_data_t ti; - mach_timebase_info(&ti); - ratio_16dot16_to_monotine = UINT64_C(1000000000) * ti.denom / ti.numer; - } - const uint64_t ratio = ratio_16dot16_to_monotine; -#else - const uint64_t ratio = UINT64_C(1000000000); -#endif - return (ratio * seconds_16dot16 + 32768) >> 16; -} - -MDBX_INTERNAL_FUNC uint32_t mdbx_osal_monotime_to_16dot16(uint64_t monotime) { - static uint64_t limit; - if (unlikely(monotime > limit)) { - if (limit != 0) - return UINT32_MAX; - limit = mdbx_osal_16dot16_to_monotime(UINT32_MAX - 1); - if (monotime > limit) - return UINT32_MAX; - } -#if defined(_WIN32) || defined(_WIN64) - return (uint32_t)((monotime << 16) / performance_frequency.QuadPart); -#elif defined(__APPLE__) || defined(__MACH__) - return (uint32_t)((monotime << 16) / ratio_16dot16_to_monotine); -#else - return (uint32_t)(monotime * 128 / 1953125); -#endif -} - -MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void) { -#if defined(_WIN32) || defined(_WIN64) - LARGE_INTEGER counter; - counter.QuadPart = 0; - QueryPerformanceCounter(&counter); - return counter.QuadPart; -#elif defined(__APPLE__) || defined(__MACH__) - return mach_absolute_time(); -#else - -#if defined(__linux__) || defined(__gnu_linux__) - static clockid_t posix_clockid = -1; - if (unlikely(posix_clockid < 0)) - posix_clockid = choice_monoclock(); -#elif defined(CLOCK_MONOTONIC) -#define posix_clockid CLOCK_MONOTONIC -#else -#define posix_clockid CLOCK_REALTIME -#endif - - struct timespec ts; - if (unlikely(clock_gettime(posix_clockid, &ts) != 0)) { - ts.tv_nsec = 0; - ts.tv_sec = 0; - } - return ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec; -#endif -} - -/*----------------------------------------------------------------------------*/ - -static void bootid_shake(bin128_t *p) { - /* Bob Jenkins's PRNG: https://burtleburtle.net/bob/rand/smallprng.html */ - const uint32_t e = p->a - (p->b << 23 | p->b >> 9); - p->a = p->b ^ (p->c << 16 | p->c >> 16); - p->b = p->c + (p->d << 11 | p->d >> 21); - p->c = p->d + e; - p->d = e + p->a; -} - -static void bootid_collect(bin128_t *p, const void *s, size_t n) { - p->y += UINT64_C(64526882297375213); - bootid_shake(p); - for (size_t i = 0; i < n; ++i) { - bootid_shake(p); - p->y ^= UINT64_C(48797879452804441) * ((const uint8_t *)s)[i]; - bootid_shake(p); - p->y += 14621231; - } - bootid_shake(p); - - /* minor non-linear tomfoolery */ - const unsigned z = p->x % 61; - p->y = p->y << z | p->y >> (64 - z); - bootid_shake(p); - bootid_shake(p); - const unsigned q = p->x % 59; - p->y = p->y << q | p->y >> (64 - q); - bootid_shake(p); - bootid_shake(p); - bootid_shake(p); -} - -#if defined(_WIN32) || defined(_WIN64) - -static uint64_t windows_systemtime_ms() { - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - return ((uint64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10000ul; -} - -static uint64_t windows_bootime(void) { - unsigned confirmed = 0; - uint64_t boottime = 0; - uint64_t up0 = mdbx_GetTickCount64(); - uint64_t st0 = windows_systemtime_ms(); - for (uint64_t fuse = st0; up0 && st0 < fuse + 1000 * 1000u / 42;) { - YieldProcessor(); - const uint64_t up1 = mdbx_GetTickCount64(); - const uint64_t st1 = windows_systemtime_ms(); - if (st1 > fuse && st1 == st0 && up1 == up0) { - uint64_t diff = st1 - up1; - if (boottime == diff) { - if (++confirmed > 4) - return boottime; - } else { - confirmed = 0; - boottime = diff; - } - fuse = st1; - Sleep(1); - } - st0 = st1; - up0 = up1; - } - return 0; -} - -static LSTATUS mdbx_RegGetValue(HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue, - DWORD dwFlags, LPDWORD pdwType, PVOID pvData, - LPDWORD pcbData) { - LSTATUS rc = - RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - if (rc != ERROR_FILE_NOT_FOUND) - return rc; - - rc = RegGetValueW(hkey, lpSubKey, lpValue, - dwFlags | 0x00010000 /* RRF_SUBKEY_WOW6464KEY */, pdwType, - pvData, pcbData); - if (rc != ERROR_FILE_NOT_FOUND) - return rc; - return RegGetValueW(hkey, lpSubKey, lpValue, - dwFlags | 0x00020000 /* RRF_SUBKEY_WOW6432KEY */, pdwType, - pvData, pcbData); -} -#endif - -static __cold __maybe_unused bool bootid_parse_uuid(bin128_t *s, const void *p, - const size_t n) { - if (n > 31) { - unsigned bits = 0; - for (unsigned i = 0; i < n; ++i) /* try parse an UUID in text form */ { - uint8_t c = ((const uint8_t *)p)[i]; - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'a' && c <= 'f') - c -= 'a' - 10; - else if (c >= 'A' && c <= 'F') - c -= 'A' - 10; - else - continue; - assert(c <= 15); - c ^= s->y >> 60; - s->y = s->y << 4 | s->x >> 60; - s->x = s->x << 4 | c; - bits += 4; - } - if (bits > 42 * 3) - /* UUID parsed successfully */ - return true; - } - - if (n > 15) /* is enough handle it as a binary? */ { - if (n == sizeof(bin128_t)) { - bin128_t aligned; - memcpy(&aligned, p, sizeof(bin128_t)); - s->x += aligned.x; - s->y += aligned.y; - } else - bootid_collect(s, p, n); - return true; - } - - if (n) - bootid_collect(s, p, n); - return false; -} - -__cold MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void) { - bin128_t bin = {{0, 0}}; - bool got_machineid = false, got_bootime = false, got_bootseq = false; - -#if defined(__linux__) || defined(__gnu_linux__) - { - const int fd = - open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW); - if (fd != -1) { - struct statvfs fs; - char buf[42]; - const ssize_t len = - (fstatvfs(fd, &fs) == 0 && fs.f_fsid == /* procfs */ 0x00009FA0) - ? read(fd, buf, sizeof(buf)) - : -1; - close(fd); - if (len > 0 && bootid_parse_uuid(&bin, buf, len)) - return bin; - } - } -#endif /* Linux */ - -#if defined(__APPLE__) || defined(__MACH__) - { - char buf[42]; - size_t len = sizeof(buf); - if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) && - bootid_parse_uuid(&bin, buf, len)) - return bin; - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ - __MAC_OS_X_VERSION_MIN_REQUIRED > 1050 - uuid_t uuid; - struct timespec wait = {0, 1000000000u / 42}; - if (!gethostuuid(uuid, &wait) && - bootid_parse_uuid(&bin, uuid, sizeof(uuid))) - got_machineid = true; -#endif /* > 10.5 */ - - struct timeval boottime; - len = sizeof(boottime); - if (!sysctlbyname("kern.boottime", &boottime, &len, nullptr, 0) && - len == sizeof(boottime) && boottime.tv_sec) - got_bootime = true; - } -#endif /* Apple/Darwin */ - -#if defined(_WIN32) || defined(_WIN64) - { - union buf { - DWORD BootId; - DWORD BaseTime; - SYSTEM_TIMEOFDAY_INFORMATION SysTimeOfDayInfo; - struct { - LARGE_INTEGER BootTime; - LARGE_INTEGER CurrentTime; - LARGE_INTEGER TimeZoneBias; - ULONG TimeZoneId; - ULONG Reserved; - ULONGLONG BootTimeBias; - ULONGLONG SleepTimeBias; - } SysTimeOfDayInfoHacked; - wchar_t MachineGuid[42]; - char DigitalProductId[248]; - } buf; - - static const wchar_t HKLM_MicrosoftCryptography[] = - L"SOFTWARE\\Microsoft\\Cryptography"; - DWORD len = sizeof(buf); - /* Windows is madness and must die */ - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_MicrosoftCryptography, - L"MachineGuid", RRF_RT_ANY, NULL, &buf.MachineGuid, - &len) == ERROR_SUCCESS && - len > 42 && len < sizeof(buf)) - got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len); - - if (!got_machineid) { - /* again, Windows is madness */ - static const wchar_t HKLM_WindowsNT[] = - L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; - static const wchar_t HKLM_WindowsNT_DPK[] = - L"SOFTWARE\\Microsoft\\Windows " - L"NT\\CurrentVersion\\DefaultProductKey"; - static const wchar_t HKLM_WindowsNT_DPK2[] = - L"SOFTWARE\\Microsoft\\Windows " - L"NT\\CurrentVersion\\DefaultProductKey2"; - - len = sizeof(buf); - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT, - L"DigitalProductId", RRF_RT_ANY, NULL, - &buf.DigitalProductId, &len) == ERROR_SUCCESS && - len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); - got_machineid = true; - } - len = sizeof(buf); - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT_DPK, - L"DigitalProductId", RRF_RT_ANY, NULL, - &buf.DigitalProductId, &len) == ERROR_SUCCESS && - len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); - got_machineid = true; - } - len = sizeof(buf); - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_WindowsNT_DPK2, - L"DigitalProductId", RRF_RT_ANY, NULL, - &buf.DigitalProductId, &len) == ERROR_SUCCESS && - len > 42 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.DigitalProductId, len); - got_machineid = true; - } - } - - static const wchar_t HKLM_PrefetcherParams[] = - L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory " - L"Management\\PrefetchParameters"; - len = sizeof(buf); - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, L"BootId", - RRF_RT_DWORD, NULL, &buf.BootId, - &len) == ERROR_SUCCESS && - len > 1 && len < sizeof(buf)) { - bootid_collect(&bin, &buf.BootId, len); - got_bootseq = true; - } - - len = sizeof(buf); - if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, L"BaseTime", - RRF_RT_DWORD, NULL, &buf.BaseTime, - &len) == ERROR_SUCCESS && - len >= sizeof(buf.BaseTime) && buf.BaseTime) { - bootid_collect(&bin, &buf.BaseTime, len); - got_bootime = true; - } - - /* BootTime from SYSTEM_TIMEOFDAY_INFORMATION */ - NTSTATUS status = NtQuerySystemInformation( - 0x03 /* SystemTmeOfDayInformation */, &buf.SysTimeOfDayInfo, - sizeof(buf.SysTimeOfDayInfo), &len); - if (NT_SUCCESS(status) && - len >= offsetof(union buf, SysTimeOfDayInfoHacked.BootTime) + - sizeof(buf.SysTimeOfDayInfoHacked.BootTime) && - buf.SysTimeOfDayInfoHacked.BootTime.QuadPart) { - bootid_collect(&bin, &buf.SysTimeOfDayInfoHacked.BootTime, - sizeof(buf.SysTimeOfDayInfoHacked.BootTime)); - got_bootime = true; - } - - if (!got_bootime) { - uint64_t boottime = windows_bootime(); - if (boottime) { - bootid_collect(&bin, &boottime, sizeof(boottime)); - got_bootime = true; - } - } - } -#endif /* Windows */ - -#if defined(CTL_HW) && defined(HW_UUID) - if (!got_machineid) { - static const int mib[] = {CTL_HW, HW_UUID}; - char buf[42]; - size_t len = sizeof(buf); - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); - } -#endif /* CTL_HW && HW_UUID */ - -#if defined(CTL_KERN) && defined(KERN_HOSTUUID) - if (!got_machineid) { - static const int mib[] = {CTL_KERN, KERN_HOSTUUID}; - char buf[42]; - size_t len = sizeof(buf); - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); - } -#endif /* CTL_KERN && KERN_HOSTUUID */ - -#if defined(__NetBSD__) - if (!got_machineid) { - char buf[42]; - size_t len = sizeof(buf); - if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, NULL, 0) == 0) - got_machineid = bootid_parse_uuid(&bin, buf, len); - } -#endif /* __NetBSD__ */ - -#if _XOPEN_SOURCE_EXTENDED - if (!got_machineid) { - const int hostid = gethostid(); - if (hostid > 0) { - bootid_collect(&bin, &hostid, sizeof(hostid)); - got_machineid = true; - } - } -#endif /* _XOPEN_SOURCE_EXTENDED */ - - if (!got_machineid) { - lack: - bin.x = bin.y = 0; - return bin; - } - - /*--------------------------------------------------------------------------*/ - -#if defined(CTL_KERN) && defined(KERN_BOOTTIME) - if (!got_bootime) { - static const int mib[] = {CTL_KERN, KERN_BOOTTIME}; - struct timeval boottime; - size_t len = sizeof(boottime); - if (sysctl( -#ifdef SYSCTL_LEGACY_NONCONST_MIB - (int *) -#endif - mib, - ARRAY_LENGTH(mib), &boottime, &len, NULL, 0) == 0 && - len == sizeof(boottime) && boottime.tv_sec) { - bootid_collect(&bin, &boottime, len); - got_bootime = true; - } - } -#endif /* CTL_KERN && KERN_BOOTTIME */ - -#if defined(__sun) || defined(__SVR4) || defined(__svr4__) - if (!got_bootime) { - kstat_ctl_t *kc = kstat_open(); - if (kc) { - kstat_t *kp = kstat_lookup(kc, "unix", 0, "system_misc"); - if (kp && kstat_read(kc, kp, 0) != -1) { - kstat_named_t *kn = (kstat_named_t *)kstat_data_lookup(kp, "boot_time"); - if (kn) { - switch (kn->data_type) { - case KSTAT_DATA_INT32: - case KSTAT_DATA_UINT32: - bootid_collect(&bin, &kn->value, sizeof(int32_t)); - got_boottime = true; - case KSTAT_DATA_INT64: - case KSTAT_DATA_UINT64: - bootid_collect(&bin, &kn->value, sizeof(int64_t)); - got_boottime = true; - } - } - } - kstat_close(kc); - } - } -#endif /* SunOS / Solaris */ - -#if _XOPEN_SOURCE_EXTENDED && defined(BOOT_TIME) - if (!got_bootime) { - setutxent(); - const struct utmpx id = {.ut_type = BOOT_TIME}; - const struct utmpx *entry = getutxid(&id); - if (entry) { - bootid_collect(&bin, entry, sizeof(*entry)); - got_bootime = true; - while (unlikely((entry = getutxid(&id)) != nullptr)) { - /* have multiple reboot records, assuming we can distinguish next - * bootsession even if RTC is wrong or absent */ - bootid_collect(&bin, entry, sizeof(*entry)); - got_bootseq = true; - } - } - endutxent(); - } -#endif /* _XOPEN_SOURCE_EXTENDED && BOOT_TIME */ - - if (!got_bootseq) { - if (!got_bootime || !MDBX_TRUST_RTC) - goto lack; - -#if defined(_WIN32) || defined(_WIN64) - FILETIME now; - GetSystemTimeAsFileTime(&now); - if (0x1CCCCCC > now.dwHighDateTime) -#else - struct timespec mono, real; - if (clock_gettime(CLOCK_MONOTONIC, &mono) || - clock_gettime(CLOCK_REALTIME, &real) || - /* wrong time, RTC is mad or absent */ - 1555555555l > real.tv_sec || - /* seems no adjustment by RTC/NTP, i.e. a fake time */ - real.tv_sec < mono.tv_sec || 1234567890l > real.tv_sec - mono.tv_sec || - (real.tv_sec - mono.tv_sec) % 900u == 0) -#endif - goto lack; - } - - return bin; -} diff --git a/src/contrib/db/libmdbx/src/elements/osal.h b/src/contrib/db/libmdbx/src/elements/osal.h deleted file mode 100644 index c1988ad..0000000 --- a/src/contrib/db/libmdbx/src/elements/osal.h +++ /dev/null @@ -1,959 +0,0 @@ -/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -/*----------------------------------------------------------------------------*/ -/* Microsoft compiler generates a lot of warning for self includes... */ - -#ifdef _MSC_VER -#pragma warning(push, 1) -#pragma warning(disable : 4548) /* expression before comma has no effect; \ - expected expression with side - effect */ -#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ - * semantics are not enabled. Specify /EHsc */ -#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ - * mode specified; termination on exception is \ - * not guaranteed. Specify /EHsc */ -#endif /* _MSC_VER (warnings) */ - -#if defined(_WIN32) || defined(_WIN64) -#if !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif -#if !defined(_NO_CRT_STDIO_INLINE) && MDBX_BUILD_SHARED_LIBRARY && \ - !defined(MDBX_TOOLS) -#define _NO_CRT_STDIO_INLINE -#endif -#endif /* Windows */ - -/*----------------------------------------------------------------------------*/ -/* C99 includes */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* C11 stdalign.h */ -#if __has_include() -#include -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L -#define alignas(N) _Alignas(N) -#elif defined(_MSC_VER) -#define alignas(N) __declspec(align(N)) -#elif __has_attribute(__aligned__) || defined(__GNUC__) -#define alignas(N) __attribute__((__aligned__(N))) -#else -#error "FIXME: Required _alignas() or equivalent." -#endif - -/*----------------------------------------------------------------------------*/ -/* Systems includes */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ - defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \ - defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__) -#include -#include -#include -#if defined(__FreeBSD__) || defined(__DragonFly__) -#include -#elif defined(__OpenBSD__) || defined(__NetBSD__) -#include -#else -#define SYSCTL_LEGACY_NONCONST_MIB -#endif -#include -#else -#include -#ifndef _POSIX_C_SOURCE -#ifdef _POSIX_SOURCE -#define _POSIX_C_SOURCE 1 -#else -#define _POSIX_C_SOURCE 0 -#endif -#endif -#endif /* !xBSD */ - -#if defined(__FreeBSD__) || defined(__OpenBSD__) || __has_include() -#include -#endif - -#if defined(__APPLE__) || defined(__MACH__) || __has_include() -#include -#endif /* MacOS */ - -#if defined(__MACH__) -#include -#include -#include -#include -#undef P_DIRTY -#endif - -#if defined(__linux__) || defined(__gnu_linux__) -#include -#include -#include -#endif /* Linux */ - -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 0 -#endif - -#ifndef _XOPEN_SOURCE_EXTENDED -#define _XOPEN_SOURCE_EXTENDED 0 -#else -#include -#endif /* _XOPEN_SOURCE_EXTENDED */ - -#if defined(__sun) || defined(__SVR4) || defined(__svr4__) -#include -#endif /* SunOS/Solaris */ - -#if defined(_WIN32) || defined(_WIN64) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include -#include -#define HAVE_SYS_STAT_H -#define HAVE_SYS_TYPES_H -typedef HANDLE mdbx_thread_t; -typedef unsigned mdbx_thread_key_t; -#define MDBX_OSAL_SECTION HANDLE -#define MAP_FAILED NULL -#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0)) -#define THREAD_CALL WINAPI -#define THREAD_RESULT DWORD -typedef struct { - HANDLE mutex; - HANDLE event; -} mdbx_condmutex_t; -typedef CRITICAL_SECTION mdbx_fastmutex_t; - -#if MDBX_AVOID_CRT -#ifndef mdbx_malloc -static inline void *mdbx_malloc(size_t bytes) { - return LocalAlloc(LMEM_FIXED, bytes); -} -#endif /* mdbx_malloc */ - -#ifndef mdbx_calloc -static inline void *mdbx_calloc(size_t nelem, size_t size) { - return LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, nelem * size); -} -#endif /* mdbx_calloc */ - -#ifndef mdbx_realloc -static inline void *mdbx_realloc(void *ptr, size_t bytes) { - return LocalReAlloc(ptr, bytes, LMEM_MOVEABLE); -} -#endif /* mdbx_realloc */ - -#ifndef mdbx_free -#define mdbx_free LocalFree -#endif /* mdbx_free */ -#else -#define mdbx_malloc malloc -#define mdbx_calloc calloc -#define mdbx_realloc realloc -#define mdbx_free free -#define mdbx_strdup _strdup -#endif /* MDBX_AVOID_CRT */ - -#ifndef snprintf -#define snprintf _snprintf /* ntdll */ -#endif - -#ifndef vsnprintf -#define vsnprintf _vsnprintf /* ntdll */ -#endif - -#else /*----------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -typedef pthread_t mdbx_thread_t; -typedef pthread_key_t mdbx_thread_key_t; -#define INVALID_HANDLE_VALUE (-1) -#define THREAD_CALL -#define THREAD_RESULT void * -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; -} mdbx_condmutex_t; -typedef pthread_mutex_t mdbx_fastmutex_t; -#define mdbx_malloc malloc -#define mdbx_calloc calloc -#define mdbx_realloc realloc -#define mdbx_free free -#define mdbx_strdup strdup -#endif /* Platform */ - -#if __GLIBC_PREREQ(2, 12) || defined(__FreeBSD__) || defined(malloc_usable_size) -/* malloc_usable_size() already provided */ -#elif defined(__APPLE__) -#define malloc_usable_size(ptr) malloc_size(ptr) -#elif defined(_MSC_VER) && !MDBX_AVOID_CRT -#define malloc_usable_size(ptr) _msize(ptr) -#endif /* malloc_usable_size */ - -/* *INDENT-OFF* */ -/* clang-format off */ -#if defined(HAVE_SYS_STAT_H) || __has_include() -#include -#endif -#if defined(HAVE_SYS_TYPES_H) || __has_include() -#include -#endif -#if defined(HAVE_SYS_FILE_H) || __has_include() -#include -#endif -/* *INDENT-ON* */ -/* clang-format on */ - -#ifndef SSIZE_MAX -#define SSIZE_MAX INTPTR_MAX -#endif - -#if !defined(MADV_DODUMP) && defined(MADV_CORE) -#define MADV_DODUMP MADV_CORE -#endif /* MADV_CORE -> MADV_DODUMP */ - -#if !defined(MADV_DONTDUMP) && defined(MADV_NOCORE) -#define MADV_DONTDUMP MADV_NOCORE -#endif /* MADV_NOCORE -> MADV_DONTDUMP */ - -#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \ - defined(i486) || defined(__i486) || defined(__i486__) || \ - defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \ - defined(__i686) || defined(__i686__) || defined(_M_IX86) || \ - defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \ - defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \ - defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__) -#ifndef __ia32__ -/* LY: define neutral __ia32__ for x86 and x86-64 archs */ -#define __ia32__ 1 -#endif /* __ia32__ */ -#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \ - defined(__amd64) || defined(_M_X64)) -/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */ -#define __amd64__ 1 -#endif /* __amd64__ */ -#endif /* all x86 */ - -#if !defined(MDBX_UNALIGNED_OK) -#if defined(_MSC_VER) -#define MDBX_UNALIGNED_OK 1 /* avoid MSVC misoptimization */ -#elif __CLANG_PREREQ(5, 0) || __GNUC_PREREQ(5, 0) -#define MDBX_UNALIGNED_OK 0 /* expecting optimization is well done */ -#elif (defined(__ia32__) || defined(__ARM_FEATURE_UNALIGNED)) && \ - !defined(__ALIGNED__) -#define MDBX_UNALIGNED_OK 1 -#else -#define MDBX_UNALIGNED_OK 0 -#endif -#endif /* MDBX_UNALIGNED_OK */ - -#if (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF -#error \ - "Sanity checking failed: Two's complement, reasonably sized integer types" -#endif - -/*----------------------------------------------------------------------------*/ -/* Compiler's includes for builtins/intrinsics */ - -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) -#include -#elif __GNUC_PREREQ(4, 4) || defined(__clang__) -#if defined(__ia32__) || defined(__e2k__) -#include -#endif /* __ia32__ */ -#if defined(__ia32__) -#include -#endif /* __ia32__ */ -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) -#include -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ - (defined(HP_IA64) || defined(__ia64)) -#include -#elif defined(__IBMC__) && defined(__powerpc) -#include -#elif defined(_AIX) -#include -#include -#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) -#include -#include -#elif defined(__MWERKS__) -/* CodeWarrior - troubles ? */ -#pragma gcc_extensions -#elif defined(__SNC__) -/* Sony PS3 - troubles ? */ -#elif defined(__hppa__) || defined(__hppa) -#include -#else -#error Unsupported C compiler, please use GNU C 4.4 or newer -#endif /* Compiler */ - -/*----------------------------------------------------------------------------*/ -/* Byteorder */ - -#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ - !defined(__ORDER_BIG_ENDIAN__) - -/* *INDENT-OFF* */ -/* clang-format off */ -#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \ - defined(HAVE_ENDIAN_H) || __has_include() -#include -#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \ - defined(HAVE_MACHINE_ENDIAN_H) || __has_include() -#include -#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include() -#include -#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \ - (__has_include() && __has_include()) -#include -#include -#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ - defined(__NETBSD__) || defined(__NetBSD__) || \ - defined(HAVE_SYS_PARAM_H) || __has_include() -#include -#endif /* OS */ -/* *INDENT-ON* */ -/* clang-format on */ - -#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) -#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN -#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN -#define __BYTE_ORDER__ __BYTE_ORDER -#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) -#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN -#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN -#define __BYTE_ORDER__ _BYTE_ORDER -#else -#define __ORDER_LITTLE_ENDIAN__ 1234 -#define __ORDER_BIG_ENDIAN__ 4321 - -#if defined(__LITTLE_ENDIAN__) || \ - (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ - defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ - defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \ - defined(_M_ARM) || defined(_M_ARM64) || defined(__e2k__) || \ - defined(__elbrus_4c__) || defined(__elbrus_8c__) || defined(__bfin__) || \ - defined(__BFIN__) || defined(__ia64__) || defined(_IA64) || \ - defined(__IA64__) || defined(__ia64) || defined(_M_IA64) || \ - defined(__itanium__) || defined(__ia32__) || defined(__CYGWIN__) || \ - defined(_WIN64) || defined(_WIN32) || defined(__TOS_WIN__) || \ - defined(__WINDOWS__) -#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ - -#elif defined(__BIG_ENDIAN__) || \ - (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \ - defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ - defined(__MIPSEB__) || defined(_MIPSEB) || defined(__MIPSEB) || \ - defined(__m68k__) || defined(M68000) || defined(__hppa__) || \ - defined(__hppa) || defined(__HPPA__) || defined(__sparc__) || \ - defined(__sparc) || defined(__370__) || defined(__THW_370__) || \ - defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__) -#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ - -#else -#error __BYTE_ORDER__ should be defined. -#endif /* Arch */ - -#endif -#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */ - -/*----------------------------------------------------------------------------*/ -/* Memory/Compiler barriers, cache coherence */ - -static __maybe_unused __inline void mdbx_compiler_barrier(void) { -#if defined(__clang__) || defined(__GNUC__) - __asm__ __volatile__("" ::: "memory"); -#elif defined(_MSC_VER) - _ReadWriteBarrier(); -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ - __memory_barrier(); - if (type > MDBX_BARRIER_COMPILER) -#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) - __mf(); -#elif defined(__i386__) || defined(__x86_64__) - _mm_mfence(); -#else -#error "Unknown target for Intel Compiler, please report to us." -#endif -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) - __compiler_barrier(); -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ - (defined(HP_IA64) || defined(__ia64)) - _Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */); -#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ - defined(__ppc64__) || defined(__powerpc64__) - __fence(); -#else -#error "Could not guess the kind of compiler, please report to us." -#endif -} - -static __maybe_unused __inline void mdbx_memory_barrier(void) { -#if __has_extension(c_atomic) || __has_extension(cxx_atomic) - __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__ATOMIC_SEQ_CST) - __atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__clang__) || defined(__GNUC__) - __sync_synchronize(); -#elif defined(_MSC_VER) - MemoryBarrier(); -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ -#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) - __mf(); -#elif defined(__i386__) || defined(__x86_64__) - _mm_mfence(); -#else -#error "Unknown target for Intel Compiler, please report to us." -#endif -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) - __machine_rw_barrier(); -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ - (defined(HP_IA64) || defined(__ia64)) - _Asm_mf(); -#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ - defined(__ppc64__) || defined(__powerpc64__) - __lwsync(); -#else -#error "Could not guess the kind of compiler, please report to us." -#endif -} - -/*----------------------------------------------------------------------------*/ -/* Cache coherence and invalidation */ - -#ifndef MDBX_CPU_WRITEBACK_IS_COHERENT -#if defined(__ia32__) || defined(__e2k__) || defined(__hppa) || \ - defined(__hppa__) -#define MDBX_CPU_WRITEBACK_IS_COHERENT 1 -#else -#define MDBX_CPU_WRITEBACK_IS_COHERENT 0 -#endif -#endif /* MDBX_CPU_WRITEBACK_IS_COHERENT */ - -#ifndef MDBX_CACHELINE_SIZE -#if defined(SYSTEM_CACHE_ALIGNMENT_SIZE) -#define MDBX_CACHELINE_SIZE SYSTEM_CACHE_ALIGNMENT_SIZE -#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) -#define MDBX_CACHELINE_SIZE 128 -#else -#define MDBX_CACHELINE_SIZE 64 -#endif -#endif /* MDBX_CACHELINE_SIZE */ - -#if MDBX_CPU_WRITEBACK_IS_COHERENT -#define mdbx_flush_noncoherent_cpu_writeback() mdbx_compiler_barrier() -#else -#define mdbx_flush_noncoherent_cpu_writeback() mdbx_memory_barrier() -#endif - -#if __has_include() -#include -#elif defined(__mips) || defined(__mips__) || defined(__mips64) || \ - defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \ - defined(__MWERKS__) || defined(__sgi) -/* MIPS should have explicit cache control */ -#include -#endif - -#ifndef MDBX_CPU_CACHE_MMAP_NONCOHERENT -#if defined(__mips) || defined(__mips__) || defined(__mips64) || \ - defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \ - defined(__MWERKS__) || defined(__sgi) -/* MIPS has cache coherency issues. */ -#define MDBX_CPU_CACHE_MMAP_NONCOHERENT 1 -#else -/* LY: assume no relevant mmap/dcache issues. */ -#define MDBX_CPU_CACHE_MMAP_NONCOHERENT 0 -#endif -#endif /* ndef MDBX_CPU_CACHE_MMAP_NONCOHERENT */ - -static __maybe_unused __inline void -mdbx_invalidate_mmap_noncoherent_cache(void *addr, size_t nbytes) { -#if MDBX_CPU_CACHE_MMAP_NONCOHERENT -#ifdef DCACHE - /* MIPS has cache coherency issues. - * Note: for any nbytes >= on-chip cache size, entire is flushed. */ - cacheflush(addr, nbytes, DCACHE); -#else -#error "Oops, cacheflush() not available" -#endif /* DCACHE */ -#else /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ - (void)addr; - (void)nbytes; -#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ -} - -/*----------------------------------------------------------------------------*/ -/* libc compatibility stuff */ - -#if (!defined(__GLIBC__) && __GLIBC_PREREQ(2, 1)) && \ - (defined(_GNU_SOURCE) || defined(_BSD_SOURCE)) -#define mdbx_asprintf asprintf -#define mdbx_vasprintf vasprintf -#else -MDBX_INTERNAL_FUNC __printf_args(2, 3) int __maybe_unused - mdbx_asprintf(char **strp, const char *fmt, ...); -MDBX_INTERNAL_FUNC int mdbx_vasprintf(char **strp, const char *fmt, va_list ap); -#endif - -/*----------------------------------------------------------------------------*/ -/* OS abstraction layer stuff */ - -/* max bytes to write in one call */ -#if defined(_WIN32) || defined(_WIN64) -#define MAX_WRITE UINT32_C(0x01000000) -#else -#define MAX_WRITE UINT32_C(0x3fff0000) -#endif - -#if defined(__linux__) || defined(__gnu_linux__) -MDBX_INTERNAL_VAR uint32_t mdbx_linux_kernel_version; -#endif /* Linux */ - -/* Get the size of a memory page for the system. - * This is the basic size that the platform's memory manager uses, and is - * fundamental to the use of memory-mapped files. */ -static __maybe_unused __inline size_t mdbx_syspagesize(void) { -#if defined(_WIN32) || defined(_WIN64) - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwPageSize; -#else - return sysconf(_SC_PAGE_SIZE); -#endif -} - -#ifndef mdbx_strdup -LIBMDBX_API char *mdbx_strdup(const char *str); -#endif - -static __maybe_unused __inline int mdbx_get_errno(void) { -#if defined(_WIN32) || defined(_WIN64) - DWORD rc = GetLastError(); -#else - int rc = errno; -#endif - return rc; -} - -#ifndef mdbx_memalign_alloc -MDBX_INTERNAL_FUNC int mdbx_memalign_alloc(size_t alignment, size_t bytes, - void **result); -#endif -#ifndef mdbx_memalign_free -MDBX_INTERNAL_FUNC void mdbx_memalign_free(void *ptr); -#endif - -MDBX_INTERNAL_FUNC int mdbx_condmutex_init(mdbx_condmutex_t *condmutex); -MDBX_INTERNAL_FUNC int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex); -MDBX_INTERNAL_FUNC int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex); -MDBX_INTERNAL_FUNC int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex); -MDBX_INTERNAL_FUNC int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex); -MDBX_INTERNAL_FUNC int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex); - -MDBX_INTERNAL_FUNC int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex); -MDBX_INTERNAL_FUNC int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex); -MDBX_INTERNAL_FUNC int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex); -MDBX_INTERNAL_FUNC int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex); - -MDBX_INTERNAL_FUNC int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, - int iovcnt, uint64_t offset, - size_t expected_written); -MDBX_INTERNAL_FUNC int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t count, - uint64_t offset); -MDBX_INTERNAL_FUNC int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, - size_t count, uint64_t offset); -MDBX_INTERNAL_FUNC int mdbx_write(mdbx_filehandle_t fd, const void *buf, - size_t count); - -MDBX_INTERNAL_FUNC int -mdbx_thread_create(mdbx_thread_t *thread, - THREAD_RESULT(THREAD_CALL *start_routine)(void *), - void *arg); -MDBX_INTERNAL_FUNC int mdbx_thread_join(mdbx_thread_t thread); - -enum mdbx_syncmode_bits { - MDBX_SYNC_DATA = 1, - MDBX_SYNC_SIZE = 2, - MDBX_SYNC_IODQ = 4 -}; - -MDBX_INTERNAL_FUNC int mdbx_filesync(mdbx_filehandle_t fd, - enum mdbx_syncmode_bits mode_bits); -MDBX_INTERNAL_FUNC int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length); -MDBX_INTERNAL_FUNC int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos); -MDBX_INTERNAL_FUNC int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length); -MDBX_INTERNAL_FUNC int mdbx_openfile(const char *pathname, int flags, - mode_t mode, mdbx_filehandle_t *fd, - bool exclusive); -MDBX_INTERNAL_FUNC int mdbx_closefile(mdbx_filehandle_t fd); -MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname); -MDBX_INTERNAL_FUNC int mdbx_is_pipe(mdbx_filehandle_t fd); - -typedef struct mdbx_mmap_param { - union { - void *address; - uint8_t *dxb; - struct MDBX_lockinfo *lck; - }; - mdbx_filehandle_t fd; - size_t limit; /* mapping length, but NOT a size of file nor DB */ - size_t current; /* mapped region size, i.e. the size of file and DB */ -#if defined(_WIN32) || defined(_WIN64) - uint64_t filesize /* in-process cache of a file size. */; -#endif -#ifdef MDBX_OSAL_SECTION - MDBX_OSAL_SECTION section; -#endif -} mdbx_mmap_t; - -MDBX_INTERNAL_FUNC int mdbx_mmap(const int flags, mdbx_mmap_t *map, - const size_t must, const size_t limit, - const bool truncate); -MDBX_INTERNAL_FUNC int mdbx_munmap(mdbx_mmap_t *map); -MDBX_INTERNAL_FUNC int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t current, - size_t wanna); -#if defined(_WIN32) || defined(_WIN64) -typedef struct { - unsigned limit, count; - HANDLE handles[31]; -} mdbx_handle_array_t; -MDBX_INTERNAL_FUNC int -mdbx_suspend_threads_before_remap(MDBX_env *env, mdbx_handle_array_t **array); -MDBX_INTERNAL_FUNC int -mdbx_resume_threads_after_remap(mdbx_handle_array_t *array); -#endif /* Windows */ -MDBX_INTERNAL_FUNC int mdbx_msync(mdbx_mmap_t *map, size_t offset, - size_t length, int async); -MDBX_INTERNAL_FUNC int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags); - -static __maybe_unused __inline uint32_t mdbx_getpid(void) { - STATIC_ASSERT(sizeof(mdbx_pid_t) <= sizeof(uint32_t)); -#if defined(_WIN32) || defined(_WIN64) - return GetCurrentProcessId(); -#else - return getpid(); -#endif -} - -static __maybe_unused __inline size_t mdbx_thread_self(void) { - STATIC_ASSERT(sizeof(mdbx_tid_t) <= sizeof(size_t)); -#if defined(_WIN32) || defined(_WIN64) - return GetCurrentThreadId(); -#else - return (size_t)pthread_self(); -#endif -} - -MDBX_INTERNAL_FUNC void __maybe_unused mdbx_osal_jitter(bool tiny); -MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); -MDBX_INTERNAL_FUNC uint64_t -mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); -MDBX_INTERNAL_FUNC uint32_t mdbx_osal_monotime_to_16dot16(uint64_t monotime); - -typedef union bin128 { - __anonymous_struct_extension__ struct { uint64_t x, y; }; - __anonymous_struct_extension__ struct { uint32_t a, b, c, d; }; -} bin128_t; - -MDBX_INTERNAL_FUNC bin128_t mdbx_osal_bootid(void); -/*----------------------------------------------------------------------------*/ -/* lck stuff */ - -#if defined(_WIN32) || defined(_WIN64) -#undef MDBX_OSAL_LOCK -#define MDBX_OSAL_LOCK_SIGN UINT32_C(0xF10C) -#else -#define MDBX_OSAL_LOCK pthread_mutex_t -#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017) -#endif /* MDBX_OSAL_LOCK */ - -/// \brief Initialization of synchronization primitives linked with MDBX_env -/// instance both in LCK-file and within the current process. -/// \param -/// global_uniqueness_flag = true - denotes that there are no other processes -/// working with DB and LCK-file. Thus the function MUST initialize -/// shared synchronization objects in memory-mapped LCK-file. -/// global_uniqueness_flag = false - denotes that at least one process is -/// already working with DB and LCK-file, including the case when DB -/// has already been opened in the current process. Thus the function -/// MUST NOT initialize shared synchronization objects in memory-mapped -/// LCK-file that are already in use. -/// \return Error code or zero on success. -MDBX_INTERNAL_FUNC int mdbx_lck_init(MDBX_env *env, - MDBX_env *inprocess_neighbor, - int global_uniqueness_flag); - -/// \brief Disconnects from shared interprocess objects and destructs -/// synchronization objects linked with MDBX_env instance -/// within the current process. -/// \param -/// inprocess_neighbor = NULL - if the current process does not have other -/// instances of MDBX_env linked with the DB being closed. -/// Thus the function MUST check for other processes working with DB or -/// LCK-file, and keep or destroy shared synchronization objects in -/// memory-mapped LCK-file depending on the result. -/// inprocess_neighbor = not-NULL - pointer to another instance of MDBX_env -/// (anyone of there is several) working with DB or LCK-file within the -/// current process. Thus the function MUST NOT try to acquire exclusive -/// lock and/or try to destruct shared synchronization objects linked with -/// DB or LCK-file. Moreover, the implementation MUST ensure correct work -/// of other instances of MDBX_env within the current process, e.g. -/// restore POSIX-fcntl locks after the closing of file descriptors. -/// \return Error code (MDBX_PANIC) or zero on success. -MDBX_INTERNAL_FUNC int mdbx_lck_destroy(MDBX_env *env, - MDBX_env *inprocess_neighbor); - -/// \brief Connects to shared interprocess locking objects and tries to acquire -/// the maximum lock level (shared if exclusive is not available) -/// Depending on implementation or/and platform (Windows) this function may -/// acquire the non-OS super-level lock (e.g. for shared synchronization -/// objects initialization), which will be downgraded to OS-exclusive or -/// shared via explicit calling of mdbx_lck_downgrade(). -/// \return -/// MDBX_RESULT_TRUE (-1) - if an exclusive lock was acquired and thus -/// the current process is the first and only after the last use of DB. -/// MDBX_RESULT_FALSE (0) - if a shared lock was acquired and thus -/// DB has already been opened and now is used by other processes. -/// Otherwise (not 0 and not -1) - error code. -MDBX_INTERNAL_FUNC int mdbx_lck_seize(MDBX_env *env); - -/// \brief Downgrades the level of initially acquired lock to -/// operational level specified by agrument. The reson for such downgrade: -/// - unblocking of other processes that are waiting for access, i.e. -/// if (env->me_flags & MDBX_EXCLUSIVE) != 0, then other processes -/// should be made aware that access is unavailable rather than -/// wait for it. -/// - freeing locks that interfere file operation (expecially for Windows) -/// (env->me_flags & MDBX_EXCLUSIVE) == 0 - downgrade to shared lock. -/// (env->me_flags & MDBX_EXCLUSIVE) != 0 - downgrade to exclusive -/// operational lock. -/// \return Error code or zero on success -MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env); - -/// \brief Locks LCK-file or/and table of readers for (de)registering. -/// \return Error code or zero on success -MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env); - -/// \brief Unlocks LCK-file or/and table of readers after (de)registering. -MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env); - -/// \brief Acquires lock for DB change (on writing transaction start) -/// Reading transactions will not be blocked. -/// Declared as LIBMDBX_API because it is used in mdbx_chk. -/// \return Error code or zero on success -LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dontwait); - -/// \brief Releases lock once DB changes is made (after writing transaction -/// has finished). -/// Declared as LIBMDBX_API because it is used in mdbx_chk. -LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env); - -/// \brief Sets alive-flag of reader presence (indicative lock) for PID of -/// the current process. The function does no more than needed for -/// the correct working of mdbx_rpid_check() in other processes. -/// \return Error code or zero on success -MDBX_INTERNAL_FUNC int mdbx_rpid_set(MDBX_env *env); - -/// \brief Resets alive-flag of reader presence (indicative lock) -/// for PID of the current process. The function does no more than needed -/// for the correct working of mdbx_rpid_check() in other processes. -/// \return Error code or zero on success -MDBX_INTERNAL_FUNC int mdbx_rpid_clear(MDBX_env *env); - -/// \brief Checks for reading process status with the given pid with help of -/// alive-flag of presence (indicative lock) or using another way. -/// \return -/// MDBX_RESULT_TRUE (-1) - if the reader process with the given PID is alive -/// and working with DB (indicative lock is present). -/// MDBX_RESULT_FALSE (0) - if the reader process with the given PID is absent -/// or not working with DB (indicative lock is not present). -/// Otherwise (not 0 and not -1) - error code. -MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid); - -#if defined(_WIN32) || defined(_WIN64) -typedef union MDBX_srwlock { - struct { - long volatile readerCount; - long volatile writerCount; - }; - RTL_SRWLOCK native; -} MDBX_srwlock; - -typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *); -MDBX_INTERNAL_VAR MDBX_srwlock_function mdbx_srwlock_Init, - mdbx_srwlock_AcquireShared, mdbx_srwlock_ReleaseShared, - mdbx_srwlock_AcquireExclusive, mdbx_srwlock_ReleaseExclusive; - -typedef BOOL(WINAPI *MDBX_GetFileInformationByHandleEx)( - _In_ HANDLE hFile, _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - _Out_ LPVOID lpFileInformation, _In_ DWORD dwBufferSize); -MDBX_INTERNAL_VAR MDBX_GetFileInformationByHandleEx - mdbx_GetFileInformationByHandleEx; - -typedef BOOL(WINAPI *MDBX_GetVolumeInformationByHandleW)( - _In_ HANDLE hFile, _Out_opt_ LPWSTR lpVolumeNameBuffer, - _In_ DWORD nVolumeNameSize, _Out_opt_ LPDWORD lpVolumeSerialNumber, - _Out_opt_ LPDWORD lpMaximumComponentLength, - _Out_opt_ LPDWORD lpFileSystemFlags, - _Out_opt_ LPWSTR lpFileSystemNameBuffer, _In_ DWORD nFileSystemNameSize); -MDBX_INTERNAL_VAR MDBX_GetVolumeInformationByHandleW - mdbx_GetVolumeInformationByHandleW; - -typedef DWORD(WINAPI *MDBX_GetFinalPathNameByHandleW)(_In_ HANDLE hFile, - _Out_ LPWSTR lpszFilePath, - _In_ DWORD cchFilePath, - _In_ DWORD dwFlags); -MDBX_INTERNAL_VAR MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW; - -typedef BOOL(WINAPI *MDBX_SetFileInformationByHandle)( - _In_ HANDLE hFile, _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - _Out_ LPVOID lpFileInformation, _In_ DWORD dwBufferSize); -MDBX_INTERNAL_VAR MDBX_SetFileInformationByHandle - mdbx_SetFileInformationByHandle; - -typedef NTSTATUS(NTAPI *MDBX_NtFsControlFile)( - IN HANDLE FileHandle, IN OUT HANDLE Event, - IN OUT PVOID /* PIO_APC_ROUTINE */ ApcRoutine, IN OUT PVOID ApcContext, - OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FsControlCode, - IN OUT PVOID InputBuffer, IN ULONG InputBufferLength, - OUT OPTIONAL PVOID OutputBuffer, IN ULONG OutputBufferLength); -MDBX_INTERNAL_VAR MDBX_NtFsControlFile mdbx_NtFsControlFile; - -typedef uint64_t(WINAPI *MDBX_GetTickCount64)(void); -MDBX_INTERNAL_VAR MDBX_GetTickCount64 mdbx_GetTickCount64; - -#if !defined(_WIN32_WINNT_WIN8) || _WIN32_WINNT < _WIN32_WINNT_WIN8 -typedef struct _WIN32_MEMORY_RANGE_ENTRY { - PVOID VirtualAddress; - SIZE_T NumberOfBytes; -} WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY; -#endif /* Windows 8.x */ - -typedef BOOL(WINAPI *MDBX_PrefetchVirtualMemory)( - HANDLE hProcess, ULONG_PTR NumberOfEntries, - PWIN32_MEMORY_RANGE_ENTRY VirtualAddresses, ULONG Flags); -MDBX_INTERNAL_VAR MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory; - -#if 0 /* LY: unused for now */ -#if !defined(_WIN32_WINNT_WIN81) || _WIN32_WINNT < _WIN32_WINNT_WIN81 -typedef enum OFFER_PRIORITY { - VmOfferPriorityVeryLow = 1, - VmOfferPriorityLow, - VmOfferPriorityBelowNormal, - VmOfferPriorityNormal -} OFFER_PRIORITY; -#endif /* Windows 8.1 */ - -typedef DWORD(WINAPI *MDBX_DiscardVirtualMemory)(PVOID VirtualAddress, - SIZE_T Size); -MDBX_INTERNAL_VAR MDBX_DiscardVirtualMemory mdbx_DiscardVirtualMemory; - -typedef DWORD(WINAPI *MDBX_ReclaimVirtualMemory)(PVOID VirtualAddress, - SIZE_T Size); -MDBX_INTERNAL_VAR MDBX_ReclaimVirtualMemory mdbx_ReclaimVirtualMemory; - -typedef DWORD(WINAPI *MDBX_OfferVirtualMemory( - PVOID VirtualAddress, - SIZE_T Size, - OFFER_PRIORITY Priority -); -MDBX_INTERNAL_VAR MDBX_OfferVirtualMemory mdbx_OfferVirtualMemory; -#endif /* unused for now */ - -#endif /* Windows */ - -/*----------------------------------------------------------------------------*/ -/* Atomics */ - -#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \ - !defined(__STDC_NO_ATOMICS__) && \ - (__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \ - !(defined(__GNUC__) || defined(__clang__))) -#include -#elif defined(__GNUC__) || defined(__clang__) -/* LY: nothing required */ -#elif defined(_MSC_VER) -#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */ -#pragma warning(disable : 4133) /* 'function': incompatible types - from \ - 'size_t' to 'LONGLONG' */ -#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \ - 'std::size_t', possible loss of data */ -#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \ - 'long', possible loss of data */ -#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange) -#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64) -#elif defined(__APPLE__) -#include -#else -#error FIXME atomic-ops -#endif - -/*----------------------------------------------------------------------------*/ - -#if defined(_MSC_VER) && _MSC_VER >= 1900 -/* LY: MSVC 2015/2017/2019 has buggy/inconsistent PRIuPTR/PRIxPTR macros - * for internal format-args checker. */ -#undef PRIuPTR -#undef PRIiPTR -#undef PRIdPTR -#undef PRIxPTR -#define PRIuPTR "Iu" -#define PRIiPTR "Ii" -#define PRIdPTR "Id" -#define PRIxPTR "Ix" -#define PRIuSIZE "zu" -#define PRIiSIZE "zi" -#define PRIdSIZE "zd" -#define PRIxSIZE "zx" -#endif /* fix PRI*PTR for _MSC_VER */ - -#ifndef PRIuSIZE -#define PRIuSIZE PRIuPTR -#define PRIiSIZE PRIiPTR -#define PRIdSIZE PRIdPTR -#define PRIxSIZE PRIxPTR -#endif /* PRI*SIZE macros for MSVC */ - -#ifdef _MSC_VER -#pragma warning(pop) -#endif diff --git a/src/contrib/db/libmdbx/src/elements/version.c.in b/src/contrib/db/libmdbx/src/elements/version.c.in deleted file mode 100644 index 2854bd5..0000000 --- a/src/contrib/db/libmdbx/src/elements/version.c.in +++ /dev/null @@ -1,46 +0,0 @@ -/* This is CMake-template for libmdbx's version.c - ******************************************************************************/ - -#include "internals.h" - -#if MDBX_VERSION_MAJOR != ${MDBX_VERSION_MAJOR} || \ - MDBX_VERSION_MINOR != ${MDBX_VERSION_MINOR} -#error "API version mismatch! Had `git fetch --tags` done?" -#endif - -static const char sourcery[] = STRINGIFY(MDBX_BUILD_SOURCERY); - -__dll_export -#ifdef __attribute_used__ - __attribute_used__ -#elif defined(__GNUC__) || __has_attribute(__used__) - __attribute__((__used__)) -#endif -#ifdef __attribute_externally_visible__ - __attribute_externally_visible__ -#elif (defined(__GNUC__) && !defined(__clang__)) || \ - __has_attribute(__externally_visible__) - __attribute__((__externally_visible__)) -#endif - const mdbx_version_info mdbx_version = { - ${MDBX_VERSION_MAJOR}, - ${MDBX_VERSION_MINOR}, - ${MDBX_VERSION_RELEASE}, - ${MDBX_VERSION_REVISION}, - {"@MDBX_GIT_TIMESTAMP@", "@MDBX_GIT_TREE@", "@MDBX_GIT_COMMIT@", - "@MDBX_GIT_DESCRIBE@"}, - sourcery}; - -__dll_export -#ifdef __attribute_used__ - __attribute_used__ -#elif defined(__GNUC__) || __has_attribute(__used__) - __attribute__((__used__)) -#endif -#ifdef __attribute_externally_visible__ - __attribute_externally_visible__ -#elif (defined(__GNUC__) && !defined(__clang__)) || \ - __has_attribute(__externally_visible__) - __attribute__((__externally_visible__)) -#endif - const char *const mdbx_sourcery_anchor = sourcery; diff --git a/src/contrib/db/libmdbx/src/man1/mdbx_chk.1 b/src/contrib/db/libmdbx/src/man1/mdbx_chk.1 deleted file mode 100644 index 84b10a1..0000000 --- a/src/contrib/db/libmdbx/src/man1/mdbx_chk.1 +++ /dev/null @@ -1,87 +0,0 @@ -.\" Copyright 2015-2019 Leonid Yuriev . -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.TH MDBX_CHK 1 "2019-09-10" "MDBX 0.x" -.SH NAME -mdbx_chk \- MDBX checking tool -.SH SYNOPSIS -.B mdbx_chk -[\c -.BR \-V ] -[\c -.BR \-v [ v [ v ]]] -[\c -.BR \-n ] -[\c -.BR \-q ] -[\c -.BR \-w ] -[\c -.BR \-d ] -[\c -.BI \-s \ subdb\fR] -[\c -.BR \-c ] -[\c -.BR \-i ] -.BR \ envpath -.SH DESCRIPTION -The -.B mdbx_chk -utility intended to check an MDBX database file. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-v -Produce verbose output, including summarize space and page usage statistics. -If \fB\-vv\fP is given, be more verbose, show summarized B-tree info -and space allocation. -If \fB\-vvv\fP is given, be more verbose, include summarized statistics -of leaf B-tree pages. -If \fB\-vvvv\fP is given, be even more verbose, show info of each page -during B-tree traversal and basic info of each GC record. -If \fB\-vvvvv\fP is given, turn maximal verbosity, display the full list -of page IDs in the GC records and size of each key-value pair of database(s). -.TP -.BR \-n -Open MDBX environment(s) which do not use subdirectories. -.TP -.BR \-q -Be quiet; do not output anything even if an error was detected. -.TP -.BR \-w -Open environment in read-write mode and lock for writing while checking. -This could be impossible if environment already used by another process(s) -in an incompatible read-write mode. This allow rollback to last steady commit -(in case environment was not closed properly) and then check transaction IDs -of meta-pages. Otherwise, without \fB\-w\fP option environment will be -opened in read-only mode. -.TP -.BR \-d -Disable page-by-page traversal of B-tree. In this case, without B-tree -traversal, it is unable to check for lost-unused pages nor for double-used -pages. -.TP -.BR \-s \ subdb -Verify and show info only for a specific subdatabase. -.TP -.BR \-c -Force using cooperative mode while opening environment, i.e. don't try to open -in exclusive/monopolistic mode. Only exclusive/monopolistic mode allow complete -check, including full check of all meta-pages and actual size of database file. -.TP -.BR \-i -Ignore wrong order errors, which will likely false-positive if custom -comparator(s) was used. -.SH DIAGNOSTICS -Exit status is zero if no errors occur. Errors result in a non-zero exit status -and a diagnostic message being written to standard error -if no quiet mode was requested. -.SH "SEE ALSO" -.BR mdbx_stat (1), -.BR mdbx_copy (1), -.BR mdbx_dump (1), -.BR mdbx_load (1) -.SH AUTHOR -Leonid Yuriev diff --git a/src/contrib/db/libmdbx/src/man1/mdbx_copy.1 b/src/contrib/db/libmdbx/src/man1/mdbx_copy.1 deleted file mode 100644 index 08717bc..0000000 --- a/src/contrib/db/libmdbx/src/man1/mdbx_copy.1 +++ /dev/null @@ -1,60 +0,0 @@ -.\" Copyright 2015-2019 Leonid Yuriev . -.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copyright 2015,2016 Peter-Service R&D LLC . -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.TH MDBX_COPY 1 "2019-09-10" "MDBX 0.x" -.SH NAME -mdbx_copy \- MDBX environment copy tool -.SH SYNOPSIS -.B mdbx_copy -[\c -.BR \-V ] -[\c -.BR \-c ] -[\c -.BR \-n ] -.B srcpath -[\c -.BR dstpath ] -.SH DESCRIPTION -The -.B mdbx_copy -utility copies an MDBX environment. The environment can -be copied regardless of whether it is currently in use. -No lockfile is created, since it gets recreated at need. - -If -.I dstpath -is specified it must be the path of an empty directory -for storing the backup. Otherwise, the backup will be -written to stdout. - -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-c -Compact while copying. Only current data pages will be copied; freed -or unused pages will be omitted from the copy. This option will -slow down the backup process as it is more CPU-intensive. -Currently it fails if the environment has suffered a page leak. -.TP -.BR \-n -Open MDBX environment(s) which do not use subdirectories. - -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. -.SH CAVEATS -This utility can trigger significant file size growth if run -in parallel with write transactions, because pages which they -free during copying cannot be reused until the copy is done. -.SH "SEE ALSO" -.BR mdbx_dump (1), -.BR mdbx_chk (1), -.BR mdbx_stat (1), -.BR mdbx_load (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/libmdbx/src/man1/mdbx_dump.1 b/src/contrib/db/libmdbx/src/man1/mdbx_dump.1 deleted file mode 100644 index 0e5ecf6..0000000 --- a/src/contrib/db/libmdbx/src/man1/mdbx_dump.1 +++ /dev/null @@ -1,80 +0,0 @@ -.\" Copyright 2015-2019 Leonid Yuriev . -.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copyright 2015,2016 Peter-Service R&D LLC . -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.TH MDBX_DUMP 1 "2019-09-10" "MDBX 0.x" -.SH NAME -mdbx_dump \- MDBX environment export tool -.SH SYNOPSIS -.B mdbx_dump -[\c -.BR \-V ] -[\c -.BI \-f \ file\fR] -[\c -.BR \-l ] -[\c -.BR \-n ] -[\c -.BR \-p ] -[\c -.BR \-a \ | -.BI \-s \ subdb\fR] -.BR \ envpath -.SH DESCRIPTION -The -.B mdbx_dump -utility reads a database and writes its contents to the -standard output using a portable flat-text format -understood by the -.BR mdbx_load (1) -utility. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-f \ file -Write to the specified file instead of to the standard output. -.TP -.BR \-l -List the databases stored in the environment. Just the -names will be listed, no data will be output. -.TP -.BR \-n -Dump an MDBX database which does not use subdirectories. -.TP -.BR \-p -If characters in either the key or data items are printing characters (as -defined by isprint(3)), output them directly. This option permits users to -use standard text editors and tools to modify the contents of databases. - -Note: different systems may have different notions about what characters -are considered printing characters, and databases dumped in this manner may -be less portable to external systems. -.TP -.BR \-a -Dump all of the subdatabases in the environment. -.TP -.BR \-s \ subdb -Dump a specific subdatabase. If no database is specified, only the main database is dumped. -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. - -Dumping and reloading databases that use user-defined comparison functions -will result in new databases that use the default comparison functions. -\fBIn this case it is quite likely that the reloaded database will be -damaged beyond repair permitting neither record storage nor retrieval.\fP - -The only available workaround is to modify the source for the -.BR mdbx_load (1) -utility to load the database using the correct comparison functions. -.SH "SEE ALSO" -.BR mdbx_load (1), -.BR mdbx_copy (1), -.BR mdbx_chk (1), -.BR mdbx_stat (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/libmdbx/src/man1/mdbx_load.1 b/src/contrib/db/libmdbx/src/man1/mdbx_load.1 deleted file mode 100644 index 01b03ef..0000000 --- a/src/contrib/db/libmdbx/src/man1/mdbx_load.1 +++ /dev/null @@ -1,89 +0,0 @@ -.\" Copyright 2015-2019 Leonid Yuriev . -.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copyright 2015,2016 Peter-Service R&D LLC . -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.TH MDBX_LOAD 1 "2019-09-10" "MDBX 0.x" -.SH NAME -mdbx_load \- MDBX environment import tool -.SH SYNOPSIS -.B mdbx_load -[\c -.BR \-V ] -[\c -.BI \-f \ file\fR] -[\c -.BR \-n ] -[\c -.BI \-s \ subdb\fR] -[\c -.BR \-N ] -[\c -.BR \-T ] -.BR \ envpath -.SH DESCRIPTION -The -.B mdbx_load -utility reads from the standard input and loads it into the -MDBX environment -.BR envpath . - -The input to -.B mdbx_load -must be in the output format specified by the -.BR mdbx_dump (1) -utility or as specified by the -.B -T -option below. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-a -Append all records in the order they appear in the input. The input is assumed to already be -in correctly sorted order and no sorting or checking for redundant values will be performed. -This option must be used to reload data that was produced by running -.B mdbx_dump -on a database that uses custom compare functions. -.TP -.BR \-f \ file -Read from the specified file instead of from the standard input. -.TP -.BR \-n -Load an MDBX database which does not use subdirectories. -.TP -.BR \-s \ subdb -Load a specific subdatabase. If no database is specified, data is loaded into the main database. -.TP -.BR \-N -Don't overwrite existing records when loading into an already existing database; just skip them. -.TP -.BR \-T -Load data from simple text files. The input must be paired lines of text, where the first -line of the pair is the key item, and the second line of the pair is its corresponding -data item. - -A simple escape mechanism, where newline and backslash (\\) characters are special, is -applied to the text input. Newline characters are interpreted as record separators. -Backslash characters in the text will be interpreted in one of two ways: If the backslash -character precedes another backslash character, the pair will be interpreted as a literal -backslash. If the backslash character precedes any other character, the two characters -following the backslash will be interpreted as a hexadecimal specification of a single -character; for example, \\0a is a newline character in the ASCII character set. - -For this reason, any backslash or newline characters that naturally occur in the text -input must be escaped to avoid misinterpretation by -.BR mdbx_load . - -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. - -.SH "SEE ALSO" -.BR mdbx_dump (1), -.BR mdbx_chk (1), -.BR mdbx_stat (1), -.BR mdbx_copy (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/libmdbx/src/man1/mdbx_stat.1 b/src/contrib/db/libmdbx/src/man1/mdbx_stat.1 deleted file mode 100644 index 424e76c..0000000 --- a/src/contrib/db/libmdbx/src/man1/mdbx_stat.1 +++ /dev/null @@ -1,69 +0,0 @@ -.\" Copyright 2015-2019 Leonid Yuriev . -.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. -.\" Copyright 2015,2016 Peter-Service R&D LLC . -.\" Copying restrictions apply. See COPYRIGHT/LICENSE. -.TH MDBX_STAT 1 "2019-09-10" "MDBX 0.x" -.SH NAME -mdbx_stat \- MDBX environment status tool -.SH SYNOPSIS -.B mdbx_stat -[\c -.BR \-V ] -[\c -.BR \-e ] -[\c -.BR \-f [ f [ f ]]] -[\c -.BR \-n ] -[\c -.BR \-r [ r ]] -[\c -.BR \-a \ | -.BI \-s \ subdb\fR] -.BR \ envpath -.SH DESCRIPTION -The -.B mdbx_stat -utility displays the status of an MDBX environment. -.SH OPTIONS -.TP -.BR \-V -Write the library version number to the standard output, and exit. -.TP -.BR \-e -Display information about the database environment. -.TP -.BR \-f -Display information about the environment freelist. -If \fB\-ff\fP is given, summarize each freelist entry. -If \fB\-fff\fP is given, display the full list of page IDs in the freelist. -.TP -.BR \-n -Display the status of an MDBX database which does not use subdirectories. -.TP -.BR \-r -Display information about the environment reader table. -Shows the process ID, thread ID, and transaction ID for each active -reader slot. The process ID and transaction ID are in decimal, the -thread ID is in hexadecimal. The transaction ID is displayed as "-" -if the reader does not currently have a read transaction open. -If \fB\-rr\fP is given, check for stale entries in the reader -table and clear them. The reader table will be printed again -after the check is performed. -.TP -.BR \-a -Display the status of all of the subdatabases in the environment. -.TP -.BR \-s \ subdb -Display the status of a specific subdatabase. -.SH DIAGNOSTICS -Exit status is zero if no errors occur. -Errors result in a non-zero exit status and -a diagnostic message being written to standard error. -.SH "SEE ALSO" -.BR mdbx_chk (1), -.BR mdbx_copy (1), -.BR mdbx_dump (1), -.BR mdbx_load (1) -.SH AUTHOR -Howard Chu of Symas Corporation diff --git a/src/contrib/db/libmdbx/src/tools/CMakeLists.txt b/src/contrib/db/libmdbx/src/tools/CMakeLists.txt deleted file mode 100644 index 01ecd7d..0000000 --- a/src/contrib/db/libmdbx/src/tools/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -set(MDBX_TOOLS mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat) - -# use, i.e. don't skip the full RPATH for the build tree -set(CMAKE_SKIP_BUILD_RPATH FALSE) - -# when building, don't use the install RPATH already (but later on when installing) -set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) - -# add the automatically determined parts of the RPATH -# which point to directories outside the build tree to the install RPATH -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - -# the RPATH to be used when installing, but only if it's not a system directory -list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) -if(isSystemDir EQUAL -1) - if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - set(CMAKE_INSTALL_RPATH "@executable_path/../lib") - else() - set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib") - endif() -endif() - -foreach(TOOL ${MDBX_TOOLS}) - if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - add_executable(${TOOL} ${TOOL}.c wingetopt.c wingetopt.h) - else() - add_executable(${TOOL} ${TOOL}.c) - endif() - - target_link_libraries(${TOOL} mdbx ${CMAKE_THREAD_LIBS_INIT}) - set_target_properties(${TOOL} PROPERTIES - C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON - INTERPROCEDURAL_OPTIMIZATION $) - - install(TARGETS ${TOOL} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT mdbx) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../man1/${TOOL}.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man1 COMPONENT mdbx) -endforeach() - -if(LIB_MATH) - target_link_libraries(mdbx_chk ${LIB_MATH}) - target_link_libraries(mdbx_stat ${LIB_MATH}) -endif() diff --git a/src/contrib/db/libmdbx/src/tools/mdbx_chk.c b/src/contrib/db/libmdbx/src/tools/mdbx_chk.c deleted file mode 100644 index cd61e44..0000000 --- a/src/contrib/db/libmdbx/src/tools/mdbx_chk.c +++ /dev/null @@ -1,1430 +0,0 @@ -/* mdbx_chk.c - memory-mapped database check tool */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#ifdef _MSC_VER -#if _MSC_VER > 1800 -#pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ -#endif /* _MSC_VER (warnings) */ - -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../elements/internals.h" - -typedef struct flagbit { - int bit; - char *name; -} flagbit; - -flagbit dbflags[] = {{MDBX_DUPSORT, "dupsort"}, - {MDBX_INTEGERKEY, "integerkey"}, - {MDBX_REVERSEKEY, "reversekey"}, - {MDBX_DUPFIXED, "dupfixed"}, - {MDBX_REVERSEDUP, "reversedup"}, - {MDBX_INTEGERDUP, "integerdup"}, - {0, NULL}}; - -#if defined(_WIN32) || defined(_WIN64) -#include "wingetopt.h" - -static volatile BOOL user_break; -static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { - (void)dwCtrlType; - user_break = true; - return true; -} - -#else /* WINDOWS */ - -static volatile sig_atomic_t user_break; -static void signal_handler(int sig) { - (void)sig; - user_break = 1; -} - -#endif /* !WINDOWS */ - -#define EXIT_INTERRUPTED (EXIT_FAILURE + 4) -#define EXIT_FAILURE_SYS (EXIT_FAILURE + 3) -#define EXIT_FAILURE_MDB (EXIT_FAILURE + 2) -#define EXIT_FAILURE_CHECK_MAJOR (EXIT_FAILURE + 1) -#define EXIT_FAILURE_CHECK_MINOR EXIT_FAILURE - -typedef struct { - const char *name; - struct { - uint64_t branch, large_count, large_volume, leaf; - uint64_t subleaf_dupsort, leaf_dupfixed, subleaf_dupfixed; - uint64_t total, empty, other; - } pages; - uint64_t payload_bytes; - uint64_t lost_bytes; -} walk_dbi_t; - -struct { - short *pagemap; - uint64_t total_payload_bytes; - uint64_t pgcount; - walk_dbi_t dbi[MAX_DBI + CORE_DBS + /* account pseudo-entry for meta */ 1]; -} walk; - -#define dbi_free walk.dbi[FREE_DBI] -#define dbi_main walk.dbi[MAIN_DBI] -#define dbi_meta walk.dbi[CORE_DBS] - -uint64_t total_unused_bytes; -int envflags = MDBX_RDONLY | MDBX_EXCLUSIVE; - -MDBX_env *env; -MDBX_txn *txn; -MDBX_envinfo envinfo; -MDBX_stat envstat; -size_t maxkeysize, userdb_count, skipped_subdb; -uint64_t reclaimable_pages, gc_pages, alloc_pages, unused_pages, backed_pages; -unsigned verbose; -bool ignore_wrong_order, quiet; -const char *only_subdb; - -struct problem { - struct problem *pr_next; - size_t count; - const char *caption; -}; - -struct problem *problems_list; -uint64_t total_problems; - -static void __printf_args(1, 2) print(const char *msg, ...) { - if (!quiet) { - va_list args; - - fflush(stderr); - va_start(args, msg); - vfprintf(stdout, msg, args); - va_end(args); - } -} - -static void __printf_args(1, 2) error(const char *msg, ...) { - total_problems++; - - if (!quiet) { - va_list args; - - fflush(NULL); - va_start(args, msg); - fputs(" ! ", stderr); - vfprintf(stderr, msg, args); - va_end(args); - fflush(NULL); - } -} - -static void pagemap_cleanup(void) { - for (size_t i = CORE_DBS + /* account pseudo-entry for meta */ 1; - i < ARRAY_LENGTH(walk.dbi); ++i) { - if (walk.dbi[i].name) { - mdbx_free((void *)walk.dbi[i].name); - walk.dbi[i].name = NULL; - } - } - - mdbx_free(walk.pagemap); - walk.pagemap = NULL; -} - -static walk_dbi_t *pagemap_lookup_dbi(const char *dbi_name, bool silent) { - static walk_dbi_t *last; - - if (dbi_name == MDBX_PGWALK_MAIN) - return &dbi_main; - if (dbi_name == MDBX_PGWALK_GC) - return &dbi_free; - if (dbi_name == MDBX_PGWALK_META) - return &dbi_meta; - - if (last && strcmp(last->name, dbi_name) == 0) - return last; - - walk_dbi_t *dbi = walk.dbi + CORE_DBS + /* account pseudo-entry for meta */ 1; - for (; dbi < ARRAY_END(walk.dbi) && dbi->name; ++dbi) { - if (strcmp(dbi->name, dbi_name) == 0) - return last = dbi; - } - - if (verbose > 0 && !silent) { - print(" - found '%s' area\n", dbi_name); - fflush(NULL); - } - - if (dbi == ARRAY_END(walk.dbi)) - return NULL; - - dbi->name = mdbx_strdup(dbi_name); - return last = dbi; -} - -static void __printf_args(4, 5) - - problem_add(const char *object, uint64_t entry_number, const char *msg, - const char *extra, ...) { - total_problems++; - - if (!quiet) { - int need_fflush = 0; - struct problem *p; - - for (p = problems_list; p; p = p->pr_next) - if (p->caption == msg) - break; - - if (!p) { - p = mdbx_calloc(1, sizeof(*p)); - p->caption = msg; - p->pr_next = problems_list; - problems_list = p; - need_fflush = 1; - } - - p->count++; - if (verbose > 1) { - print(" %s #%" PRIu64 ": %s", object, entry_number, msg); - if (extra) { - va_list args; - printf(" ("); - va_start(args, extra); - vfprintf(stdout, extra, args); - va_end(args); - printf(")"); - } - printf("\n"); - if (need_fflush) - fflush(NULL); - } - } -} - -static struct problem *problems_push(void) { - struct problem *p = problems_list; - problems_list = NULL; - return p; -} - -static size_t problems_pop(struct problem *list) { - size_t count = 0; - - if (problems_list) { - int i; - - print(" - problems: "); - for (i = 0; problems_list; ++i) { - struct problem *p = problems_list->pr_next; - count += problems_list->count; - print("%s%s (%" PRIuPTR ")", i ? ", " : "", problems_list->caption, - problems_list->count); - mdbx_free(problems_list); - problems_list = p; - } - print("\n"); - fflush(NULL); - } - - problems_list = list; - return count; -} - -static int pgvisitor(const uint64_t pgno, const unsigned pgnumber, - void *const ctx, const int deep, - const char *const dbi_name_or_tag, const size_t page_size, - const MDBX_page_type_t pagetype, const size_t nentries, - const size_t payload_bytes, const size_t header_bytes, - const size_t unused_bytes) { - (void)ctx; - if (deep > 42) { - problem_add("deep", deep, "too large", nullptr); - return MDBX_CORRUPTED /* avoid infinite loop/recursion */; - } - - if (pagetype == MDBX_page_void) - return MDBX_SUCCESS; - - walk_dbi_t *dbi = pagemap_lookup_dbi(dbi_name_or_tag, false); - if (!dbi) - return MDBX_ENOMEM; - - const size_t page_bytes = payload_bytes + header_bytes + unused_bytes; - walk.pgcount += pgnumber; - - const char *pagetype_caption; - bool branch = false; - switch (pagetype) { - default: - problem_add("page", pgno, "unknown page-type", "type %u, deep %i", - (unsigned)pagetype, deep); - pagetype_caption = "unknown"; - dbi->pages.other += pgnumber; - break; - case MDBX_page_meta: - pagetype_caption = "meta"; - dbi->pages.other += pgnumber; - break; - case MDBX_page_large: - pagetype_caption = "large"; - dbi->pages.large_volume += pgnumber; - dbi->pages.large_count += 1; - break; - case MDBX_page_branch: - pagetype_caption = "branch"; - dbi->pages.branch += pgnumber; - branch = true; - break; - case MDBX_page_leaf: - pagetype_caption = "leaf"; - dbi->pages.leaf += pgnumber; - break; - case MDBX_page_dupfixed_leaf: - pagetype_caption = "leaf-dupfixed"; - dbi->pages.leaf_dupfixed += pgnumber; - break; - case MDBX_subpage_leaf: - pagetype_caption = "subleaf-dupsort"; - dbi->pages.subleaf_dupsort += 1; - break; - case MDBX_subpage_dupfixed_leaf: - pagetype_caption = "subleaf-dupfixed"; - dbi->pages.subleaf_dupfixed += 1; - break; - } - - if (pgnumber) { - if (verbose > 3 && (!only_subdb || strcmp(only_subdb, dbi->name) == 0)) { - if (pgnumber == 1) - print(" %s-page %" PRIu64, pagetype_caption, pgno); - else - print(" %s-span %" PRIu64 "[%u]", pagetype_caption, pgno, pgnumber); - print(" of %s: header %" PRIiPTR ", payload %" PRIiPTR - ", unused %" PRIiPTR ", deep %i\n", - dbi->name, header_bytes, payload_bytes, unused_bytes, deep); - } - - bool already_used = false; - for (unsigned n = 0; n < pgnumber; ++n) { - uint64_t spanpgno = pgno + n; - if (spanpgno >= alloc_pages) - problem_add("page", spanpgno, "wrong page-no", - "%s-page: %" PRIu64 " > %" PRIu64 ", deep %i", - pagetype_caption, spanpgno, alloc_pages, deep); - else if (walk.pagemap[spanpgno]) { - walk_dbi_t *coll_dbi = &walk.dbi[walk.pagemap[spanpgno] - 1]; - problem_add("page", spanpgno, - (branch && coll_dbi == dbi) ? "loop" : "already used", - "%s-page: by %s, deep %i", pagetype_caption, coll_dbi->name, - deep); - already_used = true; - } else { - walk.pagemap[spanpgno] = (short)(dbi - walk.dbi + 1); - dbi->pages.total += 1; - } - } - - if (already_used) - return branch ? MDBX_RESULT_TRUE /* avoid infinite loop/recursion */ - : MDBX_SUCCESS; - } - - if (unused_bytes > page_size) - problem_add("page", pgno, "illegal unused-bytes", - "%s-page: %u < %" PRIuPTR " < %u", pagetype_caption, 0, - unused_bytes, envstat.ms_psize); - - if (header_bytes < (int)sizeof(long) || - (size_t)header_bytes >= envstat.ms_psize - sizeof(long)) - problem_add("page", pgno, "illegal header-length", - "%s-page: %" PRIuPTR " < %" PRIuPTR " < %" PRIuPTR, - pagetype_caption, sizeof(long), header_bytes, - envstat.ms_psize - sizeof(long)); - if (payload_bytes < 1) { - if (nentries > 1) { - problem_add("page", pgno, "zero size-of-entry", - "%s-page: payload %" PRIuPTR " bytes, %" PRIuPTR " entries", - pagetype_caption, payload_bytes, nentries); - /* if ((size_t)header_bytes + unused_bytes < page_size) { - // LY: hush a misuse error - page_bytes = page_size; - } */ - } else { - problem_add("page", pgno, "empty", - "%s-page: payload %" PRIuPTR " bytes, %" PRIuPTR - " entries, deep %i", - pagetype_caption, payload_bytes, nentries, deep); - dbi->pages.empty += 1; - } - } - - if (pgnumber) { - if (page_bytes != page_size) { - problem_add("page", pgno, "misused", - "%s-page: %" PRIuPTR " != %" PRIuPTR " (%" PRIuPTR - "h + %" PRIuPTR "p + %" PRIuPTR "u), deep %i", - pagetype_caption, page_size, page_bytes, header_bytes, - payload_bytes, unused_bytes, deep); - if (page_size > page_bytes) - dbi->lost_bytes += page_size - page_bytes; - } else { - dbi->payload_bytes += payload_bytes + header_bytes; - walk.total_payload_bytes += payload_bytes + header_bytes; - } - } - - return user_break ? MDBX_EINTR : MDBX_SUCCESS; -} - -typedef int(visitor)(const uint64_t record_number, const MDBX_val *key, - const MDBX_val *data); -static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler, - bool silent); - -static int handle_userdb(const uint64_t record_number, const MDBX_val *key, - const MDBX_val *data) { - (void)record_number; - (void)key; - (void)data; - return MDBX_SUCCESS; -} - -static int handle_freedb(const uint64_t record_number, const MDBX_val *key, - const MDBX_val *data) { - char *bad = ""; - pgno_t *iptr = data->iov_base; - - if (key->iov_len != sizeof(txnid_t)) - problem_add("entry", record_number, "wrong txn-id size", - "key-size %" PRIiPTR, key->iov_len); - else { - txnid_t txnid; - memcpy(&txnid, key->iov_base, sizeof(txnid)); - if (txnid < 1 || txnid > envinfo.mi_recent_txnid) - problem_add("entry", record_number, "wrong txn-id", "%" PRIaTXN, txnid); - else { - if (data->iov_len < sizeof(pgno_t) || data->iov_len % sizeof(pgno_t)) - problem_add("entry", txnid, "wrong idl size", "%" PRIuPTR, - data->iov_len); - size_t number = (data->iov_len >= sizeof(pgno_t)) ? *iptr++ : 0; - if (number < 1 || number > MDBX_PNL_MAX) - problem_add("entry", txnid, "wrong idl length", "%" PRIuPTR, number); - else if ((number + 1) * sizeof(pgno_t) > data->iov_len) { - problem_add("entry", txnid, "trimmed idl", - "%" PRIuSIZE " > %" PRIuSIZE " (corruption)", - (number + 1) * sizeof(pgno_t), data->iov_len); - number = data->iov_len / sizeof(pgno_t) - 1; - } else if (data->iov_len - (number + 1) * sizeof(pgno_t) >= - /* LY: allow gap upto one page. it is ok - * and better than shink-and-retry inside mdbx_update_gc() */ - envstat.ms_psize) - problem_add("entry", txnid, "extra idl space", - "%" PRIuSIZE " < %" PRIuSIZE " (minor, not a trouble)", - (number + 1) * sizeof(pgno_t), data->iov_len); - - gc_pages += number; - if (envinfo.mi_latter_reader_txnid > txnid) - reclaimable_pages += number; - - pgno_t prev = MDBX_PNL_ASCENDING ? NUM_METAS - 1 : txn->mt_next_pgno; - pgno_t span = 1; - for (unsigned i = 0; i < number; ++i) { - const pgno_t pgno = iptr[i]; - if (pgno < NUM_METAS) - problem_add("entry", txnid, "wrong idl entry", - "pgno %" PRIaPGNO " < meta-pages %u", pgno, NUM_METAS); - else if (pgno >= backed_pages) - problem_add("entry", txnid, "wrong idl entry", - "pgno %" PRIaPGNO " > backed-pages %" PRIu64, pgno, - backed_pages); - else if (pgno >= alloc_pages) - problem_add("entry", txnid, "wrong idl entry", - "pgno %" PRIaPGNO " > alloc-pages %" PRIu64, pgno, - alloc_pages - 1); - else { - if (MDBX_PNL_DISORDERED(prev, pgno)) { - bad = " [bad sequence]"; - problem_add("entry", txnid, "bad sequence", - "%" PRIaPGNO " %c [%u].%" PRIaPGNO, prev, - (prev == pgno) ? '=' : (MDBX_PNL_ASCENDING ? '>' : '<'), - i, pgno); - } - if (walk.pagemap) { - int idx = walk.pagemap[pgno]; - if (idx == 0) - walk.pagemap[pgno] = -1; - else if (idx > 0) - problem_add("page", pgno, "already used", "by %s", - walk.dbi[idx - 1].name); - else - problem_add("page", pgno, "already listed in GC", nullptr); - } - } - prev = pgno; - while (i + span < number && - iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pgno, span) - : pgno_sub(pgno, span))) - ++span; - } - if (verbose > 3 && !only_subdb) { - print(" transaction %" PRIaTXN ", %" PRIuPTR - " pages, maxspan %" PRIaPGNO "%s\n", - txnid, number, span, bad); - if (verbose > 4) { - for (unsigned i = 0; i < number; i += span) { - const pgno_t pgno = iptr[i]; - for (span = 1; - i + span < number && - iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pgno, span) - : pgno_sub(pgno, span)); - ++span) - ; - if (span > 1) { - print(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pgno, span); - } else - print(" %9" PRIaPGNO "\n", pgno); - } - } - } - } - } - - return MDBX_SUCCESS; -} - -static int handle_maindb(const uint64_t record_number, const MDBX_val *key, - const MDBX_val *data) { - char *name; - int rc; - size_t i; - - name = key->iov_base; - for (i = 0; i < key->iov_len; ++i) { - if (name[i] < ' ') - return handle_userdb(record_number, key, data); - } - - name = mdbx_malloc(key->iov_len + 1); - memcpy(name, key->iov_base, key->iov_len); - name[key->iov_len] = '\0'; - userdb_count++; - - rc = process_db(~0u, name, handle_userdb, false); - mdbx_free(name); - if (rc != MDBX_INCOMPATIBLE) - return rc; - - return handle_userdb(record_number, key, data); -} - -static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler, - bool silent) { - MDBX_cursor *mc; - MDBX_stat ms; - MDBX_val key, data; - MDBX_val prev_key, prev_data; - unsigned flags; - int rc, i; - struct problem *saved_list; - uint64_t problems_count; - - uint64_t record_count = 0, dups = 0; - uint64_t key_bytes = 0, data_bytes = 0; - - if (dbi_handle == ~0u) { - rc = mdbx_dbi_open(txn, dbi_name, 0, &dbi_handle); - if (rc) { - if (!dbi_name || - rc != - MDBX_INCOMPATIBLE) /* LY: mainDB's record is not a user's DB. */ { - error("mdbx_open '%s' failed, error %d %s\n", - dbi_name ? dbi_name : "main", rc, mdbx_strerror(rc)); - } - return rc; - } - } - - if (dbi_handle >= CORE_DBS && dbi_name && only_subdb && - strcmp(only_subdb, dbi_name) != 0) { - if (verbose) { - print("Skip processing '%s'...\n", dbi_name); - fflush(NULL); - } - skipped_subdb++; - return MDBX_SUCCESS; - } - - if (!silent && verbose) { - print("Processing '%s'...\n", dbi_name ? dbi_name : "@MAIN"); - fflush(NULL); - } - - rc = mdbx_dbi_flags(txn, dbi_handle, &flags); - if (rc) { - error("mdbx_dbi_flags failed, error %d %s\n", rc, mdbx_strerror(rc)); - return rc; - } - - rc = mdbx_dbi_stat(txn, dbi_handle, &ms, sizeof(ms)); - if (rc) { - error("mdbx_dbi_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); - return rc; - } - - if (!silent && verbose) { - print(" - dbi-id %d, flags:", dbi_handle); - if (!flags) - print(" none"); - else { - for (i = 0; dbflags[i].bit; i++) - if (flags & dbflags[i].bit) - print(" %s", dbflags[i].name); - } - print(" (0x%02X)\n", flags); - if (verbose > 1) { - print(" - page size %u, entries %" PRIu64 "\n", ms.ms_psize, - ms.ms_entries); - print(" - b-tree depth %u, pages: branch %" PRIu64 ", leaf %" PRIu64 - ", overflow %" PRIu64 "\n", - ms.ms_depth, ms.ms_branch_pages, ms.ms_leaf_pages, - ms.ms_overflow_pages); - } - } - - walk_dbi_t *dbi = (dbi_handle < CORE_DBS) - ? &walk.dbi[dbi_handle] - : pagemap_lookup_dbi(dbi_name, true); - if (!dbi) { - error("too many DBIs or out of memory\n"); - return MDBX_ENOMEM; - } - const uint64_t subtotal_pages = - ms.ms_branch_pages + ms.ms_leaf_pages + ms.ms_overflow_pages; - if (subtotal_pages != dbi->pages.total) - error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "subtotal", - subtotal_pages, dbi->pages.total); - if (ms.ms_branch_pages != dbi->pages.branch) - error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "branch", - ms.ms_branch_pages, dbi->pages.branch); - const uint64_t allleaf_pages = dbi->pages.leaf + dbi->pages.leaf_dupfixed; - if (ms.ms_leaf_pages != allleaf_pages) - error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "all-leaf", - ms.ms_leaf_pages, allleaf_pages); - if (ms.ms_overflow_pages != dbi->pages.large_volume) - error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", - "large/overlow", ms.ms_overflow_pages, dbi->pages.large_volume); - - rc = mdbx_cursor_open(txn, dbi_handle, &mc); - if (rc) { - error("mdbx_cursor_open failed, error %d %s\n", rc, mdbx_strerror(rc)); - return rc; - } - - saved_list = problems_push(); - prev_key.iov_base = NULL; - prev_key.iov_len = 0; - prev_data.iov_base = NULL; - prev_data.iov_len = 0; - rc = mdbx_cursor_get(mc, &key, &data, MDBX_FIRST); - while (rc == MDBX_SUCCESS) { - if (user_break) { - print(" - interrupted by signal\n"); - fflush(NULL); - rc = MDBX_EINTR; - goto bailout; - } - - bool bad_key = false; - if (key.iov_len > maxkeysize) { - problem_add("entry", record_count, "key length exceeds max-key-size", - "%" PRIuPTR " > %" PRIuPTR, key.iov_len, maxkeysize); - bad_key = true; - } else if ((flags & MDBX_INTEGERKEY) && key.iov_len != sizeof(uint64_t) && - key.iov_len != sizeof(uint32_t)) { - problem_add("entry", record_count, "wrong key length", - "%" PRIuPTR " != 4or8", key.iov_len); - bad_key = true; - } - - bool bad_data = false; - if ((flags & MDBX_INTEGERDUP) && data.iov_len != sizeof(uint64_t) && - data.iov_len != sizeof(uint32_t)) { - problem_add("entry", record_count, "wrong data length", - "%" PRIuPTR " != 4or8", data.iov_len); - bad_data = true; - } - - if (prev_key.iov_base && !bad_data) { - if ((flags & MDBX_DUPFIXED) && prev_data.iov_len != data.iov_len) { - problem_add("entry", record_count, "different data length", - "%" PRIuPTR " != %" PRIuPTR, prev_data.iov_len, - data.iov_len); - bad_data = true; - } - - if (!bad_key) { - int cmp = mdbx_cmp(txn, dbi_handle, &prev_key, &key); - if (cmp == 0) { - ++dups; - if ((flags & MDBX_DUPSORT) == 0) { - problem_add("entry", record_count, "duplicated entries", NULL); - if (data.iov_len == prev_data.iov_len && - memcmp(data.iov_base, prev_data.iov_base, data.iov_len) == 0) { - problem_add("entry", record_count, "complete duplicate", NULL); - } - } else if (!bad_data) { - cmp = mdbx_dcmp(txn, dbi_handle, &prev_data, &data); - if (cmp == 0) { - problem_add("entry", record_count, "complete duplicate", NULL); - } else if (cmp > 0 && !ignore_wrong_order) { - problem_add("entry", record_count, "wrong order of multi-values", - NULL); - } - } - } else if (cmp > 0 && !ignore_wrong_order) { - problem_add("entry", record_count, "wrong order of entries", NULL); - } - } - } else if (verbose) { - if (flags & MDBX_INTEGERKEY) - print(" - fixed key-size %" PRIuPTR "\n", key.iov_len); - if (flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) - print(" - fixed data-size %" PRIuPTR "\n", data.iov_len); - } - - if (handler) { - rc = handler(record_count, &key, &data); - if (MDBX_IS_ERROR(rc)) - goto bailout; - } - - record_count++; - key_bytes += key.iov_len; - data_bytes += data.iov_len; - - if (!bad_key) - prev_key = key; - if (!bad_data) - prev_data = data; - rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT); - } - if (rc != MDBX_NOTFOUND) - error("mdbx_cursor_get failed, error %d %s\n", rc, mdbx_strerror(rc)); - else - rc = 0; - - if (record_count != ms.ms_entries) - problem_add("entry", record_count, "differentent number of entries", - "%" PRIu64 " != %" PRIu64, record_count, ms.ms_entries); -bailout: - problems_count = problems_pop(saved_list); - if (!silent && verbose) { - print(" - summary: %" PRIu64 " records, %" PRIu64 " dups, %" PRIu64 - " key's bytes, %" PRIu64 " data's " - "bytes, %" PRIu64 " problems\n", - record_count, dups, key_bytes, data_bytes, problems_count); - fflush(NULL); - } - - mdbx_cursor_close(mc); - return (rc || problems_count) ? MDBX_RESULT_TRUE : MDBX_SUCCESS; -} - -static void usage(char *prog) { - fprintf(stderr, - "usage: %s dbpath [-V] [-v] [-n] [-q] [-w] [-c] [-d] [-s subdb]\n" - " -V\t\tshow version\n" - " -v\t\tmore verbose, could be used multiple times\n" - " -n\t\tNOSUBDIR mode for open\n" - " -q\t\tbe quiet\n" - " -w\t\tlock DB for writing while checking\n" - " -d\t\tdisable page-by-page traversal of B-tree\n" - " -s subdb\tprocess a specific subdatabase only\n" - " -c\t\tforce cooperative mode (don't try exclusive)\n" - " -i\t\tignore wrong order errors (for custom comparators case)\n", - prog); - exit(EXIT_INTERRUPTED); -} - -const char *meta_synctype(uint64_t sign) { - switch (sign) { - case MDBX_DATASIGN_NONE: - return "no-sync/legacy"; - case MDBX_DATASIGN_WEAK: - return "weak"; - default: - return "steady"; - } -} - -static __inline bool meta_ot(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b, - uint64_t sign_b, const bool roolback2steady) { - if (txn_a == txn_b) - return SIGN_IS_STEADY(sign_b); - - if (roolback2steady && SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b)) - return SIGN_IS_STEADY(sign_b); - - return txn_a < txn_b; -} - -static __inline bool meta_eq(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b, - uint64_t sign_b) { - if (txn_a != txn_b) - return false; - - if (SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b)) - return false; - - return true; -} - -static __inline int meta_recent(const bool roolback2steady) { - - if (meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, - envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, roolback2steady)) - return meta_ot(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, - envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, - roolback2steady) - ? 1 - : 2; - - return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, - envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, roolback2steady) - ? 2 - : 0; -} - -static __inline int meta_tail(int head) { - - if (head == 0) - return meta_ot(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, - envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true) - ? 1 - : 2; - if (head == 1) - return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, - envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true) - ? 0 - : 2; - if (head == 2) - return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, - envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, true) - ? 0 - : 1; - assert(false); - return -1; -} - -static int meta_steady(void) { return meta_recent(true); } - -static int meta_head(void) { return meta_recent(false); } - -void verbose_meta(int num, txnid_t txnid, uint64_t sign) { - print(" - meta-%d: %s %" PRIu64, num, meta_synctype(sign), txnid); - bool stay = true; - - const int steady = meta_steady(); - const int head = meta_head(); - if (num == steady && num == head) { - print(", head"); - stay = false; - } else if (num == steady) { - print(", head-steady"); - stay = false; - } else if (num == head) { - print(", head-weak"); - stay = false; - } - if (num == meta_tail(head)) { - print(", tail"); - stay = false; - } - if (stay) - print(", stay"); - - if (txnid > envinfo.mi_recent_txnid && - (envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) == MDBX_EXCLUSIVE) - print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")", - txnid - envinfo.mi_recent_txnid, txnid, envinfo.mi_recent_txnid); - print("\n"); -} - -static int check_meta_head(bool steady) { - switch (meta_recent(steady)) { - default: - assert(false); - error("unexpected internal error (%s)\n", - steady ? "meta_steady_head" : "meta_weak_head"); - __fallthrough; - case 0: - if (envinfo.mi_meta0_txnid != envinfo.mi_recent_txnid) { - print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 - ")\n", - 0, envinfo.mi_meta0_txnid, envinfo.mi_recent_txnid); - return 1; - } - break; - case 1: - if (envinfo.mi_meta1_txnid != envinfo.mi_recent_txnid) { - print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 - ")\n", - 1, envinfo.mi_meta1_txnid, envinfo.mi_recent_txnid); - return 1; - } - break; - case 2: - if (envinfo.mi_meta2_txnid != envinfo.mi_recent_txnid) { - print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 - ")\n", - 2, envinfo.mi_meta2_txnid, envinfo.mi_recent_txnid); - return 1; - } - } - return 0; -} - -static void print_size(const char *prefix, const uint64_t value, - const char *suffix) { - const char sf[] = - "KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */ - double k = 1024.0; - size_t i; - for (i = 0; sf[i + 1] && value / k > 1000.0; ++i) - k *= 1024; - print("%s%" PRIu64 " (%.2f %cb)%s", prefix, value, value / k, sf[i], suffix); -} - -int main(int argc, char *argv[]) { - int rc; - char *prog = argv[0]; - char *envname; - int problems_maindb = 0, problems_freedb = 0, problems_meta = 0; - bool dont_traversal = false; - bool locked = false; - - double elapsed; -#if defined(_WIN32) || defined(_WIN64) - uint64_t timestamp_start, timestamp_finish; - timestamp_start = GetTickCount64(); -#else - struct timespec timestamp_start, timestamp_finish; - if (clock_gettime(CLOCK_MONOTONIC, ×tamp_start)) { - rc = errno; - error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); - return EXIT_FAILURE_SYS; - } -#endif - - dbi_meta.name = "@META"; - dbi_free.name = "@GC"; - dbi_main.name = "@MAIN"; - atexit(pagemap_cleanup); - - if (argc < 2) - usage(prog); - - for (int i; (i = getopt(argc, argv, "Vvqnwcdsi:")) != EOF;) { - switch (i) { - case 'V': - printf("mdbx_chk version %d.%d.%d.%d\n" - " - source: %s %s, commit %s, tree %s\n" - " - anchor: %s\n" - " - build: %s for %s by %s\n" - " - flags: %s\n" - " - options: %s\n", - mdbx_version.major, mdbx_version.minor, mdbx_version.release, - mdbx_version.revision, mdbx_version.git.describe, - mdbx_version.git.datetime, mdbx_version.git.commit, - mdbx_version.git.tree, mdbx_sourcery_anchor, mdbx_build.datetime, - mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, - mdbx_build.options); - return EXIT_SUCCESS; - case 'v': - verbose++; - break; - case 'q': - quiet = true; - break; - case 'n': - envflags |= MDBX_NOSUBDIR; - break; - case 'w': - envflags &= ~MDBX_RDONLY; - break; - case 'c': - envflags &= ~MDBX_EXCLUSIVE; - break; - case 'd': - dont_traversal = true; - break; - case 's': - if (only_subdb && strcmp(only_subdb, optarg)) - usage(prog); - only_subdb = optarg; - break; - case 'i': - ignore_wrong_order = true; - break; - default: - usage(prog); - } - } - - if (optind != argc - 1) - usage(prog); - -#if defined(_WIN32) || defined(_WIN64) - SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); -#else -#ifdef SIGPIPE - signal(SIGPIPE, signal_handler); -#endif -#ifdef SIGHUP - signal(SIGHUP, signal_handler); -#endif - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); -#endif /* !WINDOWS */ - - envname = argv[optind]; - print("mdbx_chk %s (%s, T-%s)\nRunning for %s in 'read-%s' mode...\n", - mdbx_version.git.describe, mdbx_version.git.datetime, - mdbx_version.git.tree, envname, - (envflags & MDBX_RDONLY) ? "only" : "write"); - fflush(NULL); - - rc = mdbx_env_create(&env); - if (rc) { - error("mdbx_env_create failed, error %d %s\n", rc, mdbx_strerror(rc)); - return rc < 0 ? EXIT_FAILURE_MDB : EXIT_FAILURE_SYS; - } - - rc = mdbx_env_set_maxdbs(env, MAX_DBI); - if (rc) { - error("mdbx_env_set_maxdbs failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - rc = mdbx_env_open(env, envname, envflags, 0664); - if ((envflags & MDBX_EXCLUSIVE) && - (rc == MDBX_BUSY || -#if defined(_WIN32) || defined(_WIN64) - rc == ERROR_LOCK_VIOLATION || rc == ERROR_SHARING_VIOLATION -#else - rc == EBUSY || rc == EAGAIN -#endif - )) { - envflags &= ~MDBX_EXCLUSIVE; - rc = mdbx_env_open(env, envname, envflags, 0664); - } - - if (rc) { - error("mdbx_env_open failed, error %d %s\n", rc, mdbx_strerror(rc)); - if (rc == MDBX_WANNA_RECOVERY && (envflags & MDBX_RDONLY)) - print("Please run %s in the read-write mode (with '-w' option).\n", prog); - goto bailout; - } - if (verbose) - print(" - %s mode\n", - (envflags & MDBX_EXCLUSIVE) ? "monopolistic" : "cooperative"); - - if ((envflags & MDBX_RDONLY) == 0) { - rc = mdbx_txn_lock(env, false); - if (rc != MDBX_SUCCESS) { - error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - locked = true; - } - - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); - if (rc) { - error("mdbx_txn_begin() failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - rc = mdbx_env_get_maxkeysize(env); - if (rc < 0) { - error("mdbx_env_get_maxkeysize failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto bailout; - } - maxkeysize = rc; - - rc = mdbx_env_info_ex(env, txn, &envinfo, sizeof(envinfo)); - if (rc) { - error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - rc = mdbx_env_stat_ex(env, txn, &envstat, sizeof(envstat)); - if (rc) { - error("mdbx_env_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - mdbx_filehandle_t dxb_fd; - rc = mdbx_env_get_fd(env, &dxb_fd); - if (rc) { - error("mdbx_env_get_fd failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - uint64_t dxb_filesize = 0; -#if defined(_WIN32) || defined(_WIN64) - { - BY_HANDLE_FILE_INFORMATION info; - if (!GetFileInformationByHandle(dxb_fd, &info)) - rc = GetLastError(); - else - dxb_filesize = info.nFileSizeLow | (uint64_t)info.nFileSizeHigh << 32; - } -#else - { - struct stat st; - STATIC_ASSERT_MSG(sizeof(off_t) <= sizeof(uint64_t), - "libmdbx requires 64-bit file I/O on 64-bit systems"); - if (fstat(dxb_fd, &st)) - rc = errno; - else - dxb_filesize = st.st_size; - } -#endif - if (rc) { - error("mdbx_filesize failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - errno = 0; - const uint64_t dxbfile_pages = dxb_filesize / envinfo.mi_dxb_pagesize; - alloc_pages = txn->mt_next_pgno; - backed_pages = envinfo.mi_geo.current / envinfo.mi_dxb_pagesize; - if (backed_pages > dxbfile_pages) { - print(" ! backed-pages %" PRIu64 " > file-pages %" PRIu64 "\n", - backed_pages, dxbfile_pages); - ++problems_meta; - } - if (dxbfile_pages < NUM_METAS) - print(" ! file-pages %" PRIu64 " < %u\n", dxbfile_pages, NUM_METAS); - if (backed_pages < NUM_METAS) - print(" ! backed-pages %" PRIu64 " < %u\n", backed_pages, NUM_METAS); - if (backed_pages < NUM_METAS || dxbfile_pages < NUM_METAS) - goto bailout; - if (backed_pages > MAX_PAGENO) { - print(" ! backed-pages %" PRIu64 " > max-pages %" PRIaPGNO "\n", - backed_pages, MAX_PAGENO); - ++problems_meta; - backed_pages = MAX_PAGENO; - } - - if ((envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) != MDBX_RDONLY) { - if (backed_pages > dxbfile_pages) { - print(" ! backed-pages %" PRIu64 " > file-pages %" PRIu64 "\n", - backed_pages, dxbfile_pages); - ++problems_meta; - backed_pages = dxbfile_pages; - } - if (alloc_pages > backed_pages) { - print(" ! alloc-pages %" PRIu64 " > backed-pages %" PRIu64 "\n", - alloc_pages, backed_pages); - ++problems_meta; - alloc_pages = backed_pages; - } - } else { - /* LY: DB may be shrinked by writer downto the allocated pages. */ - if (alloc_pages > backed_pages) { - print(" ! alloc-pages %" PRIu64 " > backed-pages %" PRIu64 "\n", - alloc_pages, backed_pages); - ++problems_meta; - alloc_pages = backed_pages; - } - if (alloc_pages > dxbfile_pages) { - print(" ! alloc-pages %" PRIu64 " > file-pages %" PRIu64 "\n", - alloc_pages, dxbfile_pages); - ++problems_meta; - alloc_pages = dxbfile_pages; - } - if (backed_pages > dxbfile_pages) - backed_pages = dxbfile_pages; - } - - if (verbose) { - print(" - pagesize %u (%u system), max keysize %" PRIuPTR - ", max readers %u\n", - envinfo.mi_dxb_pagesize, envinfo.mi_sys_pagesize, maxkeysize, - envinfo.mi_maxreaders); - print_size(" - mapsize ", envinfo.mi_mapsize, "\n"); - if (envinfo.mi_geo.lower == envinfo.mi_geo.upper) - print_size(" - fixed datafile: ", envinfo.mi_geo.current, ""); - else { - print_size(" - dynamic datafile: ", envinfo.mi_geo.lower, ""); - print_size(" .. ", envinfo.mi_geo.upper, ", "); - print_size("+", envinfo.mi_geo.grow, ", "); - print_size("-", envinfo.mi_geo.shrink, "\n"); - print_size(" - current datafile: ", envinfo.mi_geo.current, ""); - } - printf(", %" PRIu64 " pages\n", - envinfo.mi_geo.current / envinfo.mi_dxb_pagesize); - print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64 - ", lag %" PRIi64 "\n", - envinfo.mi_recent_txnid, envinfo.mi_latter_reader_txnid, - envinfo.mi_recent_txnid - envinfo.mi_latter_reader_txnid); - - verbose_meta(0, envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign); - verbose_meta(1, envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign); - verbose_meta(2, envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign); - } - - if (verbose) - print(" - performs check for meta-pages clashes\n"); - if (meta_eq(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, - envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign)) { - print(" ! meta-%d and meta-%d are clashed\n", 0, 1); - ++problems_meta; - } - if (meta_eq(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, - envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign)) { - print(" ! meta-%d and meta-%d are clashed\n", 1, 2); - ++problems_meta; - } - if (meta_eq(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, - envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign)) { - print(" ! meta-%d and meta-%d are clashed\n", 2, 0); - ++problems_meta; - } - - if (envflags & MDBX_EXCLUSIVE) { - if (verbose) - print(" - performs full check recent-txn-id with meta-pages\n"); - problems_meta += check_meta_head(true); - } else if (locked) { - if (verbose) - print(" - performs lite check recent-txn-id with meta-pages (not a " - "monopolistic mode)\n"); - problems_meta += check_meta_head(false); - } else if (verbose) { - print(" - skip check recent-txn-id with meta-pages (monopolistic or " - "read-write mode only)\n"); - } - - if (!dont_traversal) { - struct problem *saved_list; - size_t traversal_problems; - uint64_t empty_pages, lost_bytes; - - print("Traversal b-tree by txn#%" PRIaTXN "...\n", txn->mt_txnid); - fflush(NULL); - walk.pagemap = mdbx_calloc((size_t)backed_pages, sizeof(*walk.pagemap)); - if (!walk.pagemap) { - rc = errno ? errno : MDBX_ENOMEM; - error("calloc failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto bailout; - } - - saved_list = problems_push(); - rc = mdbx_env_pgwalk(txn, pgvisitor, NULL); - traversal_problems = problems_pop(saved_list); - - if (rc) { - if (rc == MDBX_EINTR && user_break) { - print(" - interrupted by signal\n"); - fflush(NULL); - } else { - error("mdbx_env_pgwalk failed, error %d %s\n", rc, mdbx_strerror(rc)); - } - goto bailout; - } - - for (uint64_t n = 0; n < alloc_pages; ++n) - if (!walk.pagemap[n]) - unused_pages += 1; - - empty_pages = lost_bytes = 0; - for (walk_dbi_t *dbi = &dbi_main; dbi < ARRAY_END(walk.dbi) && dbi->name; - ++dbi) { - empty_pages += dbi->pages.empty; - lost_bytes += dbi->lost_bytes; - } - - if (verbose) { - uint64_t total_page_bytes = walk.pgcount * envstat.ms_psize; - print(" - pages: total %" PRIu64 ", unused %" PRIu64 "\n", walk.pgcount, - unused_pages); - if (verbose > 1) { - for (walk_dbi_t *dbi = walk.dbi; dbi < ARRAY_END(walk.dbi) && dbi->name; - ++dbi) { - print(" %s: subtotal %" PRIu64, dbi->name, dbi->pages.total); - if (dbi->pages.other && dbi->pages.other != dbi->pages.total) - print(", other %" PRIu64, dbi->pages.other); - if (dbi->pages.branch) - print(", branch %" PRIu64, dbi->pages.branch); - if (dbi->pages.large_count) - print(", large %" PRIu64, dbi->pages.large_count); - uint64_t all_leaf = dbi->pages.leaf + dbi->pages.leaf_dupfixed; - if (all_leaf) { - print(", leaf %" PRIu64, all_leaf); - if (verbose > 2 && - (dbi->pages.leaf_dupfixed | dbi->pages.subleaf_dupsort | - dbi->pages.subleaf_dupsort)) - print(" (usual %" PRIu64 ", sub-dupsort %" PRIu64 - ", dupfixed %" PRIu64 ", sub-dupfixed %" PRIu64 ")", - dbi->pages.leaf, dbi->pages.subleaf_dupsort, - dbi->pages.leaf_dupfixed, dbi->pages.subleaf_dupfixed); - } - print("\n"); - } - } - - if (verbose > 1) - print(" - usage: total %" PRIu64 " bytes, payload %" PRIu64 - " (%.1f%%), unused " - "%" PRIu64 " (%.1f%%)\n", - total_page_bytes, walk.total_payload_bytes, - walk.total_payload_bytes * 100.0 / total_page_bytes, - total_page_bytes - walk.total_payload_bytes, - (total_page_bytes - walk.total_payload_bytes) * 100.0 / - total_page_bytes); - if (verbose > 2) { - for (walk_dbi_t *dbi = walk.dbi; dbi < ARRAY_END(walk.dbi) && dbi->name; - ++dbi) - if (dbi->pages.total) { - uint64_t dbi_bytes = dbi->pages.total * envstat.ms_psize; - print(" %s: subtotal %" PRIu64 " bytes (%.1f%%)," - " payload %" PRIu64 " (%.1f%%), unused %" PRIu64 " (%.1f%%)", - dbi->name, dbi_bytes, dbi_bytes * 100.0 / total_page_bytes, - dbi->payload_bytes, dbi->payload_bytes * 100.0 / dbi_bytes, - dbi_bytes - dbi->payload_bytes, - (dbi_bytes - dbi->payload_bytes) * 100.0 / dbi_bytes); - if (dbi->pages.empty) - print(", %" PRIu64 " empty pages", dbi->pages.empty); - if (dbi->lost_bytes) - print(", %" PRIu64 " bytes lost", dbi->lost_bytes); - print("\n"); - } else - print(" %s: empty\n", dbi->name); - } - print(" - summary: average fill %.1f%%", - walk.total_payload_bytes * 100.0 / total_page_bytes); - if (empty_pages) - print(", %" PRIu64 " empty pages", empty_pages); - if (lost_bytes) - print(", %" PRIu64 " bytes lost", lost_bytes); - print(", %" PRIuPTR " problems\n", traversal_problems); - } - } else if (verbose) { - print("Skipping b-tree walk...\n"); - fflush(NULL); - } - - if (!verbose) - print("Iterating DBIs...\n"); - problems_maindb = process_db(~0u, /* MAIN_DBI */ NULL, NULL, false); - problems_freedb = process_db(FREE_DBI, "@GC", handle_freedb, false); - - if (verbose) { - uint64_t value = envinfo.mi_mapsize / envstat.ms_psize; - double percent = value / 100.0; - print(" - space: %" PRIu64 " total pages", value); - print(", backed %" PRIu64 " (%.1f%%)", backed_pages, - backed_pages / percent); - print(", allocated %" PRIu64 " (%.1f%%)", alloc_pages, - alloc_pages / percent); - - if (verbose > 1) { - value = envinfo.mi_mapsize / envstat.ms_psize - alloc_pages; - print(", remained %" PRIu64 " (%.1f%%)", value, value / percent); - - value = alloc_pages - gc_pages; - print(", used %" PRIu64 " (%.1f%%)", value, value / percent); - - print(", gc %" PRIu64 " (%.1f%%)", gc_pages, gc_pages / percent); - - value = gc_pages - reclaimable_pages; - print(", detained %" PRIu64 " (%.1f%%)", value, value / percent); - - print(", reclaimable %" PRIu64 " (%.1f%%)", reclaimable_pages, - reclaimable_pages / percent); - } - - value = - envinfo.mi_mapsize / envstat.ms_psize - alloc_pages + reclaimable_pages; - print(", available %" PRIu64 " (%.1f%%)\n", value, value / percent); - } - - if (problems_maindb == 0 && problems_freedb == 0) { - if (!dont_traversal && - (envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) != MDBX_RDONLY) { - if (walk.pgcount != alloc_pages - gc_pages) { - error("used pages mismatch (%" PRIu64 "(walked) != %" PRIu64 - "(allocated - GC))\n", - walk.pgcount, alloc_pages - gc_pages); - } - if (unused_pages != gc_pages) { - error("gc pages mismatch (%" PRIu64 "(walked) != %" PRIu64 "(GC))\n", - unused_pages, gc_pages); - } - } else if (verbose) { - print(" - skip check used and gc pages (btree-traversal with " - "monopolistic or read-write mode only)\n"); - } - - if (!process_db(MAIN_DBI, NULL, handle_maindb, true)) { - if (!userdb_count && verbose) - print(" - does not contain multiple databases\n"); - } - } - -bailout: - if (txn) - mdbx_txn_abort(txn); - if (locked) - mdbx_txn_unlock(env); - if (env) - mdbx_env_close(env); - fflush(NULL); - if (rc) { - if (rc < 0) - return (user_break) ? EXIT_INTERRUPTED : EXIT_FAILURE_SYS; - return EXIT_FAILURE_MDB; - } - -#if defined(_WIN32) || defined(_WIN64) - timestamp_finish = GetTickCount64(); - elapsed = (timestamp_finish - timestamp_start) * 1e-3; -#else - if (clock_gettime(CLOCK_MONOTONIC, ×tamp_finish)) { - rc = errno; - error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); - return EXIT_FAILURE_SYS; - } - elapsed = timestamp_finish.tv_sec - timestamp_start.tv_sec + - (timestamp_finish.tv_nsec - timestamp_start.tv_nsec) * 1e-9; -#endif /* !WINDOWS */ - - total_problems += problems_meta; - if (total_problems || problems_maindb || problems_freedb) { - print("Total %" PRIu64 " error%s detected, elapsed %.3f seconds.\n", - total_problems, (total_problems > 1) ? "s are" : " is", elapsed); - if (problems_meta || problems_maindb || problems_freedb) - return EXIT_FAILURE_CHECK_MAJOR; - return EXIT_FAILURE_CHECK_MINOR; - } - print("No error is detected, elapsed %.3f seconds\n", elapsed); - return EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/src/tools/mdbx_copy.c b/src/contrib/db/libmdbx/src/tools/mdbx_copy.c deleted file mode 100644 index a58fd74..0000000 --- a/src/contrib/db/libmdbx/src/tools/mdbx_copy.c +++ /dev/null @@ -1,130 +0,0 @@ -/* mdbx_copy.c - memory-mapped database backup tool */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#ifdef _MSC_VER -#if _MSC_VER > 1800 -#pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ -#endif /* _MSC_VER (warnings) */ - -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../elements/internals.h" - -#if defined(_WIN32) || defined(_WIN64) -#include "wingetopt.h" - -static volatile BOOL user_break; -static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { - (void)dwCtrlType; - user_break = true; - return true; -} - -#else /* WINDOWS */ - -static volatile sig_atomic_t user_break; -static void signal_handler(int sig) { - (void)sig; - user_break = 1; -} - -#endif /* !WINDOWS */ - -int main(int argc, char *argv[]) { - int rc; - MDBX_env *env = NULL; - const char *progname = argv[0], *act; - unsigned flags = MDBX_RDONLY; - unsigned cpflags = 0; - bool quiet = false; - - for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) { - if (argv[1][1] == 'n' && argv[1][2] == '\0') - flags |= MDBX_NOSUBDIR; - else if (argv[1][1] == 'c' && argv[1][2] == '\0') - cpflags |= MDBX_CP_COMPACT; - else if (argv[1][1] == 'q' && argv[1][2] == '\0') - quiet = true; - else if (argv[1][1] == 'V' && argv[1][2] == '\0') { - printf("mdbx_copy version %d.%d.%d.%d\n" - " - source: %s %s, commit %s, tree %s\n" - " - anchor: %s\n" - " - build: %s for %s by %s\n" - " - flags: %s\n" - " - options: %s\n", - mdbx_version.major, mdbx_version.minor, mdbx_version.release, - mdbx_version.revision, mdbx_version.git.describe, - mdbx_version.git.datetime, mdbx_version.git.commit, - mdbx_version.git.tree, mdbx_sourcery_anchor, mdbx_build.datetime, - mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, - mdbx_build.options); - return EXIT_SUCCESS; - } else - argc = 0; - } - - if (argc < 2 || argc > 3) { - fprintf(stderr, "usage: %s [-V] [-q] [-c] [-n] srcpath [dstpath]\n", - progname); - exit(EXIT_FAILURE); - } - -#if defined(_WIN32) || defined(_WIN64) - SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); -#else -#ifdef SIGPIPE - signal(SIGPIPE, signal_handler); -#endif -#ifdef SIGHUP - signal(SIGHUP, signal_handler); -#endif - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); -#endif /* !WINDOWS */ - - if (!quiet) { - fprintf((argc == 2) ? stderr : stdout, - "mdbx_copy %s (%s, T-%s)\nRunning for copy %s to %s...\n", - mdbx_version.git.describe, mdbx_version.git.datetime, - mdbx_version.git.tree, argv[1], (argc == 2) ? "stdout" : argv[2]); - fflush(NULL); - } - - act = "opening environment"; - rc = mdbx_env_create(&env); - if (rc == MDBX_SUCCESS) { - rc = mdbx_env_open(env, argv[1], flags, 0640); - } - if (rc == MDBX_SUCCESS) { - act = "copying"; - if (argc == 2) { - mdbx_filehandle_t fd; -#if defined(_WIN32) || defined(_WIN64) - fd = GetStdHandle(STD_OUTPUT_HANDLE); -#else - fd = fileno(stdout); -#endif - rc = mdbx_env_copy2fd(env, fd, cpflags); - } else - rc = mdbx_env_copy(env, argv[2], cpflags); - } - if (rc) - fprintf(stderr, "%s: %s failed, error %d (%s)\n", progname, act, rc, - mdbx_strerror(rc)); - mdbx_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/src/tools/mdbx_dump.c b/src/contrib/db/libmdbx/src/tools/mdbx_dump.c deleted file mode 100644 index 20cd376..0000000 --- a/src/contrib/db/libmdbx/src/tools/mdbx_dump.c +++ /dev/null @@ -1,352 +0,0 @@ -/* mdbx_dump.c - memory-mapped database dump tool */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#ifdef _MSC_VER -#if _MSC_VER > 1800 -#pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ -#endif /* _MSC_VER (warnings) */ - -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../elements/internals.h" - -#include - -#define PRINT 1 -static int mode; - -typedef struct flagbit { - int bit; - char *name; -} flagbit; - -flagbit dbflags[] = {{MDBX_REVERSEKEY, "reversekey"}, - {MDBX_DUPSORT, "dupsort"}, - {MDBX_INTEGERKEY, "integerkey"}, - {MDBX_DUPFIXED, "dupfixed"}, - {MDBX_INTEGERDUP, "integerdup"}, - {MDBX_REVERSEDUP, "reversedup"}, - {0, NULL}}; - -#if defined(_WIN32) || defined(_WIN64) -#include "wingetopt.h" - -static volatile BOOL user_break; -static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { - (void)dwCtrlType; - user_break = true; - return true; -} - -#else /* WINDOWS */ - -static volatile sig_atomic_t user_break; -static void signal_handler(int sig) { - (void)sig; - user_break = 1; -} - -#endif /* !WINDOWS */ - -static const char hexc[] = "0123456789abcdef"; - -static void dumpbyte(unsigned char c) { - putchar(hexc[c >> 4]); - putchar(hexc[c & 0xf]); -} - -static void text(MDBX_val *v) { - unsigned char *c, *end; - - putchar(' '); - c = v->iov_base; - end = c + v->iov_len; - while (c < end) { - if (isprint(*c) && *c != '\\') { - putchar(*c); - } else { - putchar('\\'); - dumpbyte(*c); - } - c++; - } - putchar('\n'); -} - -static void dumpval(MDBX_val *v) { - unsigned char *c, *end; - - putchar(' '); - c = v->iov_base; - end = c + v->iov_len; - while (c < end) { - dumpbyte(*c++); - } - putchar('\n'); -} - -/* Dump in BDB-compatible format */ -static int dumpit(MDBX_txn *txn, MDBX_dbi dbi, char *name) { - MDBX_cursor *mc; - MDBX_stat ms; - MDBX_val key, data; - MDBX_envinfo info; - unsigned int flags; - int rc, i; - - rc = mdbx_dbi_flags(txn, dbi, &flags); - if (rc) - return rc; - - rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms)); - if (rc) - return rc; - - rc = mdbx_env_info(mdbx_txn_env(txn), &info, sizeof(info)); - if (rc) - return rc; - - printf("VERSION=3\n"); - printf("format=%s\n", mode & PRINT ? "print" : "bytevalue"); - if (name) - printf("database=%s\n", name); - printf("type=btree\n"); - printf("mapsize=%" PRIu64 "\n", info.mi_mapsize); - printf("maxreaders=%u\n", info.mi_maxreaders); - - for (i = 0; dbflags[i].bit; i++) - if (flags & dbflags[i].bit) - printf("%s=1\n", dbflags[i].name); - - printf("db_pagesize=%d\n", ms.ms_psize); - printf("HEADER=END\n"); - - rc = mdbx_cursor_open(txn, dbi, &mc); - if (rc) - return rc; - - while ((rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) { - if (user_break) { - rc = MDBX_EINTR; - break; - } - if (mode & PRINT) { - text(&key); - text(&data); - } else { - dumpval(&key); - dumpval(&data); - } - } - printf("DATA=END\n"); - if (rc == MDBX_NOTFOUND) - rc = MDBX_SUCCESS; - - return rc; -} - -static void usage(char *prog) { - fprintf(stderr, - "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", - prog); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - int i, rc; - MDBX_env *env; - MDBX_txn *txn; - MDBX_dbi dbi; - char *prog = argv[0]; - char *envname; - char *subname = NULL; - int alldbs = 0, envflags = 0, list = 0; - - if (argc < 2) - usage(prog); - - /* -a: dump main DB and all subDBs - * -s: dump only the named subDB - * -n: use NOSUBDIR flag on env_open - * -p: use printable characters - * -f: write to file instead of stdout - * -V: print version and exit - * (default) dump only the main DB - */ - while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) { - switch (i) { - case 'V': - printf("mdbx_dump version %d.%d.%d.%d\n" - " - source: %s %s, commit %s, tree %s\n" - " - anchor: %s\n" - " - build: %s for %s by %s\n" - " - flags: %s\n" - " - options: %s\n", - mdbx_version.major, mdbx_version.minor, mdbx_version.release, - mdbx_version.revision, mdbx_version.git.describe, - mdbx_version.git.datetime, mdbx_version.git.commit, - mdbx_version.git.tree, mdbx_sourcery_anchor, mdbx_build.datetime, - mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, - mdbx_build.options); - return EXIT_SUCCESS; - case 'l': - list = 1; - /*FALLTHROUGH*/; - __fallthrough; - case 'a': - if (subname) - usage(prog); - alldbs++; - break; - case 'f': - if (freopen(optarg, "w", stdout) == NULL) { - fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, - mdbx_strerror(errno)); - exit(EXIT_FAILURE); - } - break; - case 'n': - envflags |= MDBX_NOSUBDIR; - break; - case 'p': - mode |= PRINT; - break; - case 's': - if (alldbs) - usage(prog); - subname = optarg; - break; - default: - usage(prog); - } - } - - if (optind != argc - 1) - usage(prog); - -#if defined(_WIN32) || defined(_WIN64) - SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); -#else -#ifdef SIGPIPE - signal(SIGPIPE, signal_handler); -#endif -#ifdef SIGHUP - signal(SIGHUP, signal_handler); -#endif - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); -#endif /* !WINDOWS */ - - envname = argv[optind]; - printf("mdbx_dump %s (%s, T-%s)\nRunning for %s...\n", - mdbx_version.git.describe, mdbx_version.git.datetime, - mdbx_version.git.tree, envname); - fflush(NULL); - - rc = mdbx_env_create(&env); - if (rc) { - fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, - mdbx_strerror(rc)); - return EXIT_FAILURE; - } - - if (alldbs || subname) { - mdbx_env_set_maxdbs(env, 2); - } - - rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664); - if (rc) { - fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); - if (rc) { - fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - rc = mdbx_dbi_open(txn, subname, 0, &dbi); - if (rc) { - fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto txn_abort; - } - - if (alldbs) { - MDBX_cursor *cursor; - MDBX_val key; - int count = 0; - - rc = mdbx_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) { - if (user_break) { - rc = MDBX_EINTR; - break; - } - char *str; - MDBX_dbi db2; - if (memchr(key.iov_base, '\0', key.iov_len)) - continue; - count++; - str = mdbx_malloc(key.iov_len + 1); - memcpy(str, key.iov_base, key.iov_len); - str[key.iov_len] = '\0'; - rc = mdbx_dbi_open(txn, str, 0, &db2); - if (rc == MDBX_SUCCESS) { - if (list) { - printf("%s\n", str); - list++; - } else { - rc = dumpit(txn, db2, str); - if (rc) - break; - } - mdbx_dbi_close(env, db2); - } - mdbx_free(str); - if (rc) - continue; - } - mdbx_cursor_close(cursor); - if (!count) { - fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, - envname); - rc = MDBX_NOTFOUND; - } else if (rc == MDBX_INCOMPATIBLE) { - /* LY: the record it not a named sub-db. */ - rc = MDBX_SUCCESS; - } - } else { - rc = dumpit(txn, dbi, subname); - } - if (rc && rc != MDBX_NOTFOUND) - fprintf(stderr, "%s: %s: %s\n", prog, envname, mdbx_strerror(rc)); - - mdbx_dbi_close(env, dbi); -txn_abort: - mdbx_txn_abort(txn); -env_close: - mdbx_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/src/tools/mdbx_load.c b/src/contrib/db/libmdbx/src/tools/mdbx_load.c deleted file mode 100644 index 00bfa87..0000000 --- a/src/contrib/db/libmdbx/src/tools/mdbx_load.c +++ /dev/null @@ -1,567 +0,0 @@ -/* mdbx_load.c - memory-mapped database load tool */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#ifdef _MSC_VER -#if _MSC_VER > 1800 -#pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ -#endif /* _MSC_VER (warnings) */ - -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../elements/internals.h" - -#include - -#if defined(_WIN32) || defined(_WIN64) -#include "wingetopt.h" - -static volatile BOOL user_break; -static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { - (void)dwCtrlType; - user_break = true; - return true; -} - -#else /* WINDOWS */ - -static volatile sig_atomic_t user_break; -static void signal_handler(int sig) { - (void)sig; - user_break = 1; -} - -#endif /* !WINDOWS */ - -#define PRINT 1 -#define NOHDR 2 -static int mode; - -static char *subname = NULL; -static size_t lineno; -static int version; - -static int dbi_flags; -static char *prog; -static int Eof; - -static MDBX_envinfo envinfo; -static MDBX_val kbuf, dbuf; -static MDBX_val k0buf; - -#define STRLENOF(s) (sizeof(s) - 1) - -typedef struct flagbit { - int bit; - char *name; - int len; -} flagbit; - -#define S(s) s, STRLENOF(s) - -flagbit dbflags[] = {{MDBX_REVERSEKEY, S("reversekey")}, - {MDBX_DUPSORT, S("dupsort")}, - {MDBX_INTEGERKEY, S("integerkey")}, - {MDBX_DUPFIXED, S("dupfixed")}, - {MDBX_INTEGERDUP, S("integerdup")}, - {MDBX_REVERSEDUP, S("reversedup")}, - {0, NULL, 0}}; - -static void readhdr(void) { - char *ptr; - - dbi_flags = 0; - while (fgets(dbuf.iov_base, (int)dbuf.iov_len, stdin) != NULL) { - lineno++; - if (!strncmp(dbuf.iov_base, "db_pagesize=", STRLENOF("db_pagesize=")) || - !strncmp(dbuf.iov_base, "duplicates=", STRLENOF("duplicates="))) { - /* LY: silently ignore information fields. */ - continue; - } else if (!strncmp(dbuf.iov_base, "VERSION=", STRLENOF("VERSION="))) { - version = atoi((char *)dbuf.iov_base + STRLENOF("VERSION=")); - if (version > 3) { - fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported VERSION %d\n", - prog, lineno, version); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.iov_base, "HEADER=END", STRLENOF("HEADER=END"))) { - break; - } else if (!strncmp(dbuf.iov_base, "format=", STRLENOF("format="))) { - if (!strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "print", - STRLENOF("print"))) - mode |= PRINT; - else if (strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "bytevalue", - STRLENOF("bytevalue"))) { - fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported FORMAT %s\n", prog, - lineno, (char *)dbuf.iov_base + STRLENOF("FORMAT=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.iov_base, "database=", STRLENOF("database="))) { - ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); - if (ptr) - *ptr = '\0'; - if (subname) - mdbx_free(subname); - subname = mdbx_strdup((char *)dbuf.iov_base + STRLENOF("database=")); - } else if (!strncmp(dbuf.iov_base, "type=", STRLENOF("type="))) { - if (strncmp((char *)dbuf.iov_base + STRLENOF("type="), "btree", - STRLENOF("btree"))) { - fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported type %s\n", prog, - lineno, (char *)dbuf.iov_base + STRLENOF("type=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.iov_base, "mapaddr=", STRLENOF("mapaddr="))) { - int i; - ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); - if (ptr) - *ptr = '\0'; - void *unused; - i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p", &unused); - if (i != 1) { - fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapaddr %s\n", prog, - lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.iov_base, "mapsize=", STRLENOF("mapsize="))) { - int i; - ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); - if (ptr) - *ptr = '\0'; - i = sscanf((char *)dbuf.iov_base + STRLENOF("mapsize="), "%" PRIu64, - &envinfo.mi_mapsize); - if (i != 1) { - fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapsize %s\n", prog, - lineno, (char *)dbuf.iov_base + STRLENOF("mapsize=")); - exit(EXIT_FAILURE); - } - } else if (!strncmp(dbuf.iov_base, - "maxreaders=", STRLENOF("maxreaders="))) { - int i; - ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); - if (ptr) - *ptr = '\0'; - i = sscanf((char *)dbuf.iov_base + STRLENOF("maxreaders="), "%u", - &envinfo.mi_maxreaders); - if (i != 1) { - fprintf(stderr, "%s: line %" PRIiSIZE ": invalid maxreaders %s\n", prog, - lineno, (char *)dbuf.iov_base + STRLENOF("maxreaders=")); - exit(EXIT_FAILURE); - } - } else { - int i; - for (i = 0; dbflags[i].bit; i++) { - if (!strncmp(dbuf.iov_base, dbflags[i].name, dbflags[i].len) && - ((char *)dbuf.iov_base)[dbflags[i].len] == '=') { - if (((char *)dbuf.iov_base)[dbflags[i].len + 1] == '1') - dbi_flags |= dbflags[i].bit; - break; - } - } - if (!dbflags[i].bit) { - ptr = memchr(dbuf.iov_base, '=', dbuf.iov_len); - if (!ptr) { - fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected format\n", prog, - lineno); - exit(EXIT_FAILURE); - } else { - *ptr = '\0'; - fprintf(stderr, - "%s: line %" PRIiSIZE ": unrecognized keyword ignored: %s\n", - prog, lineno, (char *)dbuf.iov_base); - } - } - } - } -} - -static void badend(void) { - fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected end of input\n", prog, - lineno); -} - -static int unhex(unsigned char *c2) { - int x, c; - x = *c2++ & 0x4f; - if (x & 0x40) - x -= 55; - c = x << 4; - x = *c2 & 0x4f; - if (x & 0x40) - x -= 55; - c |= x; - return c; -} - -static int readline(MDBX_val *out, MDBX_val *buf) { - unsigned char *c1, *c2, *end; - size_t len, l2; - int c; - - if (!(mode & NOHDR)) { - c = fgetc(stdin); - if (c == EOF) { - Eof = 1; - return EOF; - } - if (c != ' ') { - lineno++; - if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) { - badend: - Eof = 1; - badend(); - return EOF; - } - if (c == 'D' && !strncmp(buf->iov_base, "ATA=END", STRLENOF("ATA=END"))) - return EOF; - goto badend; - } - } - if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) { - Eof = 1; - return EOF; - } - lineno++; - - c1 = buf->iov_base; - len = strlen((char *)c1); - l2 = len; - - /* Is buffer too short? */ - while (c1[len - 1] != '\n') { - buf->iov_base = mdbx_realloc(buf->iov_base, buf->iov_len * 2); - if (!buf->iov_base) { - Eof = 1; - fprintf(stderr, "%s: line %" PRIiSIZE ": out of memory, line too long\n", - prog, lineno); - return EOF; - } - c1 = buf->iov_base; - c1 += l2; - if (fgets((char *)c1, (int)buf->iov_len + 1, stdin) == NULL) { - Eof = 1; - badend(); - return EOF; - } - buf->iov_len *= 2; - len = strlen((char *)c1); - l2 += len; - } - c1 = c2 = buf->iov_base; - len = l2; - c1[--len] = '\0'; - end = c1 + len; - - if (mode & PRINT) { - while (c2 < end) { - if (unlikely(*c2 == '\\')) { - if (c2[1] == '\\') { - *c1++ = '\\'; - } else { - if (c2 + 3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) { - Eof = 1; - badend(); - return EOF; - } - *c1++ = (char)unhex(++c2); - } - c2 += 2; - } else { - /* copies are redundant when no escapes were used */ - *c1++ = *c2++; - } - } - } else { - /* odd length not allowed */ - if (len & 1) { - Eof = 1; - badend(); - return EOF; - } - while (c2 < end) { - if (!isxdigit(*c2) || !isxdigit(c2[1])) { - Eof = 1; - badend(); - return EOF; - } - *c1++ = (char)unhex(c2); - c2 += 2; - } - } - c2 = out->iov_base = buf->iov_base; - out->iov_len = c1 - c2; - - return 0; -} - -static void usage(void) { - fprintf(stderr, - "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", - prog); - exit(EXIT_FAILURE); -} - -static int anyway_greater(const MDBX_val *a, const MDBX_val *b) { - (void)a; - (void)b; - return 1; -} - -int main(int argc, char *argv[]) { - int i, rc; - MDBX_env *env = NULL; - MDBX_txn *txn = NULL; - MDBX_cursor *mc = NULL; - MDBX_dbi dbi; - char *envname = NULL; - int envflags = MDBX_UTTERLY_NOSYNC, putflags = 0; - int append = 0; - MDBX_val prevk; - - prog = argv[0]; - if (argc < 2) - usage(); - - /* -a: append records in input order - * -f: load file instead of stdin - * -n: use NOSUBDIR flag on env_open - * -s: load into named subDB - * -N: use NOOVERWRITE on puts - * -T: read plaintext - * -V: print version and exit - */ - while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) { - switch (i) { - case 'V': - printf("mdbx_load version %d.%d.%d.%d\n" - " - source: %s %s, commit %s, tree %s\n" - " - anchor: %s\n" - " - build: %s for %s by %s\n" - " - flags: %s\n" - " - options: %s\n", - mdbx_version.major, mdbx_version.minor, mdbx_version.release, - mdbx_version.revision, mdbx_version.git.describe, - mdbx_version.git.datetime, mdbx_version.git.commit, - mdbx_version.git.tree, mdbx_sourcery_anchor, mdbx_build.datetime, - mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, - mdbx_build.options); - return EXIT_SUCCESS; - case 'a': - append = 1; - break; - case 'f': - if (freopen(optarg, "r", stdin) == NULL) { - fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, - mdbx_strerror(errno)); - exit(EXIT_FAILURE); - } - break; - case 'n': - envflags |= MDBX_NOSUBDIR; - break; - case 's': - subname = mdbx_strdup(optarg); - break; - case 'N': - putflags = MDBX_NOOVERWRITE | MDBX_NODUPDATA; - break; - case 'T': - mode |= NOHDR | PRINT; - break; - default: - usage(); - } - } - - if (optind != argc - 1) - usage(); - -#if defined(_WIN32) || defined(_WIN64) - SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); -#else -#ifdef SIGPIPE - signal(SIGPIPE, signal_handler); -#endif -#ifdef SIGHUP - signal(SIGHUP, signal_handler); -#endif - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); -#endif /* !WINDOWS */ - - envname = argv[optind]; - printf("mdbx_load %s (%s, T-%s)\nRunning for %s...\n", - mdbx_version.git.describe, mdbx_version.git.datetime, - mdbx_version.git.tree, envname); - fflush(NULL); - - dbuf.iov_len = 4096; - dbuf.iov_base = mdbx_malloc(dbuf.iov_len); - - /* read first header for mapsize= */ - if (!(mode & NOHDR)) - readhdr(); - - rc = mdbx_env_create(&env); - if (rc) { - fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, - mdbx_strerror(rc)); - return EXIT_FAILURE; - } - - mdbx_env_set_maxdbs(env, 2); - - if (envinfo.mi_maxreaders) - mdbx_env_set_maxreaders(env, envinfo.mi_maxreaders); - - if (envinfo.mi_mapsize) { - if (envinfo.mi_mapsize > SIZE_MAX) { - fprintf(stderr, "mdbx_env_set_mapsize failed, error %d %s\n", rc, - mdbx_strerror(MDBX_TOO_LARGE)); - return EXIT_FAILURE; - } - mdbx_env_set_mapsize(env, (size_t)envinfo.mi_mapsize); - } - -#ifdef MDBX_FIXEDMAP - if (info.mi_mapaddr) - envflags |= MDBX_FIXEDMAP; -#endif - - rc = mdbx_env_open(env, envname, envflags, 0664); - if (rc) { - fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - kbuf.iov_len = mdbx_env_get_maxkeysize(env); - if (kbuf.iov_len >= SIZE_MAX / 4) { - fprintf(stderr, "mdbx_env_get_maxkeysize failed, returns %zu\n", - kbuf.iov_len); - goto env_close; - } - kbuf.iov_len = (kbuf.iov_len + 1) * 2; - kbuf.iov_base = malloc(kbuf.iov_len * 2); - k0buf.iov_len = kbuf.iov_len; - k0buf.iov_base = (char *)kbuf.iov_base + kbuf.iov_len; - prevk.iov_base = k0buf.iov_base; - - while (!Eof) { - if (user_break) { - rc = MDBX_EINTR; - break; - } - - rc = mdbx_txn_begin(env, NULL, 0, &txn); - if (rc) { - fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - rc = mdbx_dbi_open_ex(txn, subname, dbi_flags | MDBX_CREATE, &dbi, - append ? anyway_greater : NULL, - append ? anyway_greater : NULL); - if (rc) { - fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto txn_abort; - } - - rc = mdbx_cursor_open(txn, dbi, &mc); - if (rc) { - fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - - int batch = 0; - prevk.iov_len = 0; - while (1) { - MDBX_val key; - rc = readline(&key, &kbuf); - if (rc) /* rc == EOF */ - break; - - MDBX_val data; - rc = readline(&data, &dbuf); - if (rc) { - fprintf(stderr, "%s: line %" PRIiSIZE ": failed to read key value\n", - prog, lineno); - goto txn_abort; - } - - int appflag = 0; - if (append) { - appflag = MDBX_APPEND; - if (dbi_flags & MDBX_DUPSORT) { - if (prevk.iov_len == key.iov_len && - memcmp(prevk.iov_base, key.iov_base, key.iov_len) == 0) - appflag = MDBX_APPEND | MDBX_APPENDDUP; - else - memcpy(prevk.iov_base, key.iov_base, prevk.iov_len = key.iov_len); - } - } - rc = mdbx_cursor_put(mc, &key, &data, putflags | appflag); - if (rc == MDBX_KEYEXIST && putflags) - continue; - if (rc) { - fprintf(stderr, "mdbx_cursor_put failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - batch++; - if (batch == 100) { - rc = mdbx_txn_commit(txn); - if (rc) { - fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, - lineno, mdbx_strerror(rc)); - goto env_close; - } - rc = mdbx_txn_begin(env, NULL, 0, &txn); - if (rc) { - fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - rc = mdbx_cursor_open(txn, dbi, &mc); - if (rc) { - fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - batch = 0; - } - } - rc = mdbx_txn_commit(txn); - txn = NULL; - if (rc) { - fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, lineno, - mdbx_strerror(rc)); - goto env_close; - } - mdbx_dbi_close(env, dbi); - - /* try read next header */ - if (!(mode & NOHDR)) - readhdr(); - } - -txn_abort: - mdbx_txn_abort(txn); -env_close: - mdbx_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/src/tools/mdbx_stat.c b/src/contrib/db/libmdbx/src/tools/mdbx_stat.c deleted file mode 100644 index 04c1fb9..0000000 --- a/src/contrib/db/libmdbx/src/tools/mdbx_stat.c +++ /dev/null @@ -1,436 +0,0 @@ -/* mdbx_stat.c - memory-mapped database status tool */ - -/* - * Copyright 2015-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . */ - -#ifdef _MSC_VER -#if _MSC_VER > 1800 -#pragma warning(disable : 4464) /* relative include path contains '..' */ -#endif -#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ -#endif /* _MSC_VER (warnings) */ - -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../elements/internals.h" - -#if defined(_WIN32) || defined(_WIN64) -#include "wingetopt.h" - -static volatile BOOL user_break; -static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { - (void)dwCtrlType; - user_break = true; - return true; -} - -#else /* WINDOWS */ - -static volatile sig_atomic_t user_break; -static void signal_handler(int sig) { - (void)sig; - user_break = 1; -} - -#endif /* !WINDOWS */ - -static void prstat(MDBX_stat *ms) { - printf(" Pagesize: %u\n", ms->ms_psize); - printf(" Tree depth: %u\n", ms->ms_depth); - printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages); - printf(" Leaf pages: %" PRIu64 "\n", ms->ms_leaf_pages); - printf(" Overflow pages: %" PRIu64 "\n", ms->ms_overflow_pages); - printf(" Entries: %" PRIu64 "\n", ms->ms_entries); -} - -static void usage(char *prog) { - fprintf(stderr, - "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", - prog); - exit(EXIT_FAILURE); -} - -static int reader_list_func(void *ctx, int num, int slot, mdbx_pid_t pid, - mdbx_tid_t thread, uint64_t txnid, uint64_t lag, - size_t bytes_used, size_t bytes_retained) { - (void)ctx; - if (num == 1) - printf("Reader Table Status\n" - " #\tslot\t%6s %*s %20s %10s %13s %13s\n", - "pid", (int)sizeof(size_t) * 2, "thread", "txnid", "lag", "used", - "retained"); - - printf(" %3d)\t[%d]\t%6" PRIdSIZE " %*" PRIxSIZE, num, slot, (size_t)pid, - (int)sizeof(size_t) * 2, (size_t)thread); - if (txnid) - printf(" %20" PRIu64 " %10" PRIu64 " %12.1fM %12.1fM\n", txnid, lag, - bytes_used / 1048576.0, bytes_retained / 1048576.0); - else - printf(" %20s %10s %13s %13s\n", "-", "0", "0", "0"); - - return user_break ? MDBX_RESULT_TRUE : MDBX_RESULT_FALSE; -} - -int main(int argc, char *argv[]) { - int o, rc; - MDBX_env *env; - MDBX_txn *txn; - MDBX_dbi dbi; - MDBX_stat mst; - MDBX_envinfo mei; - char *prog = argv[0]; - char *envname; - char *subname = NULL; - int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; - - if (argc < 2) - usage(prog); - - /* -a: print stat of main DB and all subDBs - * -s: print stat of only the named subDB - * -e: print env info - * -f: print freelist info - * -r: print reader info - * -n: use NOSUBDIR flag on env_open - * -V: print version and exit - * (default) print stat of only the main DB - */ - while ((o = getopt(argc, argv, "Vaefnrs:")) != EOF) { - switch (o) { - case 'V': - printf("mdbx_stat version %d.%d.%d.%d\n" - " - source: %s %s, commit %s, tree %s\n" - " - anchor: %s\n" - " - build: %s for %s by %s\n" - " - flags: %s\n" - " - options: %s\n", - mdbx_version.major, mdbx_version.minor, mdbx_version.release, - mdbx_version.revision, mdbx_version.git.describe, - mdbx_version.git.datetime, mdbx_version.git.commit, - mdbx_version.git.tree, mdbx_sourcery_anchor, mdbx_build.datetime, - mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, - mdbx_build.options); - return EXIT_SUCCESS; - case 'a': - if (subname) - usage(prog); - alldbs++; - break; - case 'e': - envinfo++; - break; - case 'f': - freinfo++; - break; - case 'n': - envflags |= MDBX_NOSUBDIR; - break; - case 'r': - rdrinfo++; - break; - case 's': - if (alldbs) - usage(prog); - subname = optarg; - break; - default: - usage(prog); - } - } - - if (optind != argc - 1) - usage(prog); - -#if defined(_WIN32) || defined(_WIN64) - SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); -#else -#ifdef SIGPIPE - signal(SIGPIPE, signal_handler); -#endif -#ifdef SIGHUP - signal(SIGHUP, signal_handler); -#endif - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); -#endif /* !WINDOWS */ - - envname = argv[optind]; - envname = argv[optind]; - printf("mdbx_stat %s (%s, T-%s)\nRunning for %s...\n", - mdbx_version.git.describe, mdbx_version.git.datetime, - mdbx_version.git.tree, envname); - fflush(NULL); - - rc = mdbx_env_create(&env); - if (rc) { - fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, - mdbx_strerror(rc)); - return EXIT_FAILURE; - } - - if (alldbs || subname) - mdbx_env_set_maxdbs(env, 4); - - rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664); - if (rc) { - fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - if (envinfo || freinfo) { - (void)mdbx_env_info(env, &mei, sizeof(mei)); - } else { - /* LY: zap warnings from gcc */ - memset(&mei, 0, sizeof(mei)); - } - - if (envinfo) { - (void)mdbx_env_stat(env, &mst, sizeof(mst)); - printf("Environment Info\n"); - printf(" Pagesize: %u\n", mst.ms_psize); - if (mei.mi_geo.lower != mei.mi_geo.upper) { - printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64 - "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64 - "/-%" PRIu64 ")\n", - mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow, - mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize, - mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize, - mei.mi_geo.shrink / mst.ms_psize); - printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", - mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); - } else { - printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", - mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); - } - printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n", - mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize); - printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1); - printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid); - printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n", - mei.mi_latter_reader_txnid, - mei.mi_latter_reader_txnid - mei.mi_recent_txnid); - printf(" Max readers: %u\n", mei.mi_maxreaders); - printf(" Number of readers used: %u\n", mei.mi_numreaders); - } else { - /* LY: zap warnings from gcc */ - memset(&mst, 0, sizeof(mst)); - } - - if (rdrinfo) { - rc = mdbx_reader_list(env, reader_list_func, nullptr); - if (rc == MDBX_RESULT_TRUE) - printf("Reader Table is empty\n"); - else if (rc == MDBX_SUCCESS && rdrinfo > 1) { - int dead; - rc = mdbx_reader_check(env, &dead); - if (rc == MDBX_RESULT_TRUE) { - printf(" %d stale readers cleared.\n", dead); - rc = mdbx_reader_list(env, reader_list_func, nullptr); - if (rc == MDBX_RESULT_TRUE) - printf(" Now Reader Table is empty\n"); - } else - printf(" No stale readers.\n"); - } - if (MDBX_IS_ERROR(rc)) { - fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - if (!(subname || alldbs || freinfo)) - goto env_close; - } - - rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); - if (rc) { - fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto env_close; - } - - if (freinfo) { - MDBX_cursor *cursor; - MDBX_val key, data; - pgno_t pages = 0, *iptr; - pgno_t reclaimable = 0; - - printf("Freelist Status\n"); - dbi = 0; - rc = mdbx_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); - if (rc) { - fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - prstat(&mst); - while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == - MDBX_SUCCESS) { - if (user_break) { - rc = MDBX_EINTR; - break; - } - iptr = data.iov_base; - const pgno_t number = *iptr++; - - pages += number; - if (envinfo && mei.mi_latter_reader_txnid > *(size_t *)key.iov_base) - reclaimable += number; - - if (freinfo > 1) { - char *bad = ""; - pgno_t prev = - MDBX_PNL_ASCENDING ? NUM_METAS - 1 : (pgno_t)mei.mi_last_pgno + 1; - pgno_t span = 1; - for (unsigned i = 0; i < number; ++i) { - pgno_t pg = iptr[i]; - if (MDBX_PNL_DISORDERED(prev, pg)) - bad = " [bad sequence]"; - prev = pg; - while (i + span < number && - iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span) - : pgno_sub(pg, span))) - ++span; - } - printf(" Transaction %" PRIaTXN ", %" PRIaPGNO - " pages, maxspan %" PRIaPGNO "%s\n", - *(txnid_t *)key.iov_base, number, span, bad); - if (freinfo > 2) { - for (unsigned i = 0; i < number; i += span) { - const pgno_t pg = iptr[i]; - for (span = 1; - i + span < number && - iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span) - : pgno_sub(pg, span)); - ++span) - ; - if (span > 1) - printf(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pg, span); - else - printf(" %9" PRIaPGNO "\n", pg); - } - } - } - } - mdbx_cursor_close(cursor); - - switch (rc) { - case MDBX_SUCCESS: - case MDBX_NOTFOUND: - break; - case MDBX_EINTR: - fprintf(stderr, "Interrupted by signal/user\n"); - goto txn_abort; - default: - fprintf(stderr, "mdbx_cursor_get failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - - if (envinfo) { - uint64_t value = mei.mi_mapsize / mst.ms_psize; - double percent = value / 100.0; - printf("Page Allocation Info\n"); - printf(" Max pages: %" PRIu64 " 100%%\n", value); - - value = mei.mi_last_pgno + 1; - printf(" Pages used: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1); - printf(" Remained: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = mei.mi_last_pgno + 1 - pages; - printf(" Used now: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = pages; - printf(" Unallocated: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = pages - reclaimable; - printf(" Detained: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = reclaimable; - printf(" Reclaimable: %" PRIu64 " %.1f%%\n", value, value / percent); - - value = - mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1) + reclaimable; - printf(" Available: %" PRIu64 " %.1f%%\n", value, value / percent); - } else - printf(" Free pages: %" PRIaPGNO "\n", pages); - } - - rc = mdbx_dbi_open(txn, subname, 0, &dbi); - if (rc) { - fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); - goto txn_abort; - } - - rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); - if (rc) { - fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - printf("Status of %s\n", subname ? subname : "Main DB"); - prstat(&mst); - - if (alldbs) { - MDBX_cursor *cursor; - MDBX_val key; - - rc = mdbx_cursor_open(txn, dbi, &cursor); - if (rc) { - fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) { - char *str; - MDBX_dbi db2; - if (memchr(key.iov_base, '\0', key.iov_len)) - continue; - str = mdbx_malloc(key.iov_len + 1); - memcpy(str, key.iov_base, key.iov_len); - str[key.iov_len] = '\0'; - rc = mdbx_dbi_open(txn, str, 0, &db2); - if (rc == MDBX_SUCCESS) - printf("Status of %s\n", str); - mdbx_free(str); - if (rc) - continue; - rc = mdbx_dbi_stat(txn, db2, &mst, sizeof(mst)); - if (rc) { - fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, - mdbx_strerror(rc)); - goto txn_abort; - } - prstat(&mst); - mdbx_dbi_close(env, db2); - } - mdbx_cursor_close(cursor); - } - - if (rc == MDBX_NOTFOUND) - rc = MDBX_SUCCESS; - - mdbx_dbi_close(env, dbi); -txn_abort: - mdbx_txn_abort(txn); -env_close: - mdbx_env_close(env); - - return rc ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/src/tools/wingetopt.c b/src/contrib/db/libmdbx/src/tools/wingetopt.c deleted file mode 100644 index 7feb223..0000000 --- a/src/contrib/db/libmdbx/src/tools/wingetopt.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * POSIX getopt for Windows - * - * AT&T Public License - * - * Code given out at the 1985 UNIFORUM conference in Dallas. - */ - -/*----------------------------------------------------------------------------*/ -/* Microsoft compiler generates a lot of warning for self includes... */ - -#ifdef _MSC_VER -#pragma warning(push, 1) -#pragma warning(disable : 4548) /* expression before comma has no effect; \ - expected expression with side - effect */ -#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ - * semantics are not enabled. Specify /EHsc */ -#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ - * mode specified; termination on exception is \ - * not guaranteed. Specify /EHsc */ -#if !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif -#endif /* _MSC_VER (warnings) */ - -#include "wingetopt.h" -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif -/*----------------------------------------------------------------------------*/ - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef EOF -#define EOF (-1) -#endif - -#define ERR(s, c) \ - if (opterr) { \ - fputs(argv[0], stderr); \ - fputs(s, stderr); \ - fputc(c, stderr); \ - } - -int opterr = 1; -int optind = 1; -int optopt; -char *optarg; - -int getopt(int argc, char *const argv[], const char *opts) { - static int sp = 1; - int c; - const char *cp; - - if (sp == 1) { - if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') - return EOF; - else if (strcmp(argv[optind], "--") == 0) { - optind++; - return EOF; - } - } - optopt = c = argv[optind][sp]; - if (c == ':' || (cp = strchr(opts, c)) == NULL) { - ERR(": illegal option -- ", c); - if (argv[optind][++sp] == '\0') { - optind++; - sp = 1; - } - return '?'; - } - if (*++cp == ':') { - if (argv[optind][sp + 1] != '\0') - optarg = &argv[optind++][sp + 1]; - else if (++optind >= argc) { - ERR(": option requires an argument -- ", c); - sp = 1; - return '?'; - } else - optarg = argv[optind++]; - sp = 1; - } else { - if (argv[optind][++sp] == '\0') { - sp = 1; - optind++; - } - optarg = NULL; - } - return c; -} diff --git a/src/contrib/db/libmdbx/src/tools/wingetopt.h b/src/contrib/db/libmdbx/src/tools/wingetopt.h deleted file mode 100644 index d328e38..0000000 --- a/src/contrib/db/libmdbx/src/tools/wingetopt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * POSIX getopt for Windows - * - * AT&T Public License - * - * Code given out at the 1985 UNIFORUM conference in Dallas. - */ - -#ifndef _WINGETOPT_H_ -#define _WINGETOPT_H_ - -/* Bit of madness for Windows console */ -#define mdbx_strerror mdbx_strerror_ANSI2OEM -#define mdbx_strerror_r mdbx_strerror_r_ANSI2OEM - -#ifdef __cplusplus -extern "C" { -#endif - -extern int opterr; -extern int optind; -extern int optopt; -extern char *optarg; -int getopt(int argc, char *const argv[], const char *optstring); - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H_ */ diff --git a/src/contrib/db/libmdbx/test/CMakeLists.txt b/src/contrib/db/libmdbx/test/CMakeLists.txt deleted file mode 100644 index 0cc2218..0000000 --- a/src/contrib/db/libmdbx/test/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - set(TEST_OSAL windows) -else() - set(TEST_OSAL unix) -endif() - -add_executable(mdbx_test - base.h - cases.cc - chrono.cc - chrono.h - config.cc - config.h - copy.cc - dead.cc - hill.cc - jitter.cc - keygen.cc - keygen.h - log.cc - log.h - main.cc - osal.h - osal-${TEST_OSAL}.cc - test.cc - test.h - try.cc - utils.cc - utils.h - append.cc - ttl.cc - nested.cc - ) - -set_target_properties(mdbx_test PROPERTIES - INTERPROCEDURAL_OPTIMIZATION $ - CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON) - -if(CC_HAS_FASTMATH) - target_compile_options(mdbx_test PRIVATE "-ffast-math") -endif() -if(CC_HAS_VISIBILITY AND (LTO_ENABLED OR INTERPROCEDURAL_OPTIMIZATION)) - set_target_properties(mdbx_test PROPERTIES LINK_FLAGS "-fvisibility=hidden") -endif() - -target_link_libraries(mdbx_test mdbx ${LIB_MATH} ${CMAKE_THREAD_LIBS_INIT}) -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - target_link_libraries(mdbx_test winmm.lib) -endif() - -if(UNIX AND NOT SUBPROJECT) - add_subdirectory(pcrf) -endif() diff --git a/src/contrib/db/libmdbx/test/append.cc b/src/contrib/db/libmdbx/test/append.cc deleted file mode 100644 index 9f567c7..0000000 --- a/src/contrib/db/libmdbx/test/append.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -bool testcase_append::run() { - int err = db_open__begin__table_create_open_clean(dbi); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("append: bailout-prepare due '%s'", mdbx_strerror(err)); - return true; - } - - keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); - /* LY: теÑÑ‚ Ð½Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† в append-режиме, - * при котором запиÑи добавлÑÑŽÑ‚ÑÑ Ñтрого в конец (в порÑдке Ñортировки) */ - const unsigned flags = (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_APPEND | MDBX_APPENDDUP - : MDBX_APPEND; - keyvalue_maker.make_ordered(); - - key = keygen::alloc(config.params.keylen_max); - data = keygen::alloc(config.params.datalen_max); - keygen::buffer last_key = keygen::alloc(config.params.keylen_max); - keygen::buffer last_data = keygen::alloc(config.params.datalen_max); - last_key->value.iov_base = last_key->bytes; - last_key->value.iov_len = 0; - last_data->value.iov_base = last_data->bytes; - last_data->value.iov_len = 0; - - simple_checksum inserted_checksum; - uint64_t inserted_number = 0; - uint64_t serial_count = 0; - - unsigned txn_nops = 0; - uint64_t commited_inserted_number = inserted_number; - simple_checksum commited_inserted_checksum = inserted_checksum; - while (should_continue()) { - const keygen::serial_t serial = serial_count; - if (!keyvalue_maker.increment(serial_count, 1)) { - // дошли до границы проÑтранÑтва ключей - break; - } - - log_trace("append: append-a %" PRIu64, serial); - generate_pair(serial, key, data); - int cmp = inserted_number ? mdbx_cmp(txn_guard.get(), dbi, &key->value, - &last_key->value) - : 1; - if (cmp == 0 && (config.params.table_flags & MDBX_DUPSORT)) - cmp = mdbx_dcmp(txn_guard.get(), dbi, &data->value, &last_data->value); - - err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value, flags); - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("append: bailout-insert due '%s'", mdbx_strerror(err)); - txn_end(true); - inserted_number = commited_inserted_number; - inserted_checksum = commited_inserted_checksum; - break; - } - - if (cmp > 0) { - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_put(appenda-a)", err); - - memcpy(last_key->value.iov_base, key->value.iov_base, - last_key->value.iov_len = key->value.iov_len); - memcpy(last_data->value.iov_base, data->value.iov_base, - last_data->value.iov_len = data->value.iov_len); - ++inserted_number; - inserted_checksum.push((uint32_t)inserted_number, key->value); - inserted_checksum.push(10639, data->value); - } else { - if (unlikely(err != MDBX_EKEYMISMATCH)) - failure_perror("mdbx_put(appenda-a) != MDBX_EKEYMISMATCH", err); - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("append: bailout-commit due '%s'", mdbx_strerror(err)); - inserted_number = commited_inserted_number; - inserted_checksum = commited_inserted_checksum; - break; - } - commited_inserted_number = inserted_number; - commited_inserted_checksum = inserted_checksum; - txn_nops = 0; - } - - report(1); - } - - if (txn_guard) { - err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("append: bailout-commit due '%s'", mdbx_strerror(err)); - inserted_number = commited_inserted_number; - inserted_checksum = commited_inserted_checksum; - } - } - //---------------------------------------------------------------------------- - txn_begin(true); - cursor_open(dbi); - - MDBX_val check_key, check_data; - err = - mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, MDBX_FIRST); - if (likely(inserted_number)) { - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_cursor_get(MDBX_FIRST)", err); - } - - simple_checksum read_checksum; - uint64_t read_count = 0; - while (err == MDBX_SUCCESS) { - ++read_count; - read_checksum.push((uint32_t)read_count, check_key); - read_checksum.push(10639, check_data); - - err = - mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, MDBX_NEXT); - } - - if (unlikely(err != MDBX_NOTFOUND)) - failure_perror("mdbx_cursor_get(MDBX_NEXT) != EOF", err); - - if (unlikely(read_count != inserted_number)) - failure("read_count(%" PRIu64 ") != inserted_number(%" PRIu64 ")", - read_count, inserted_number); - - if (unlikely(read_checksum.value != inserted_checksum.value)) - failure("read_checksum(0x%016" PRIu64 ") " - "!= inserted_checksum(0x%016" PRIu64 ")", - read_checksum.value, inserted_checksum.value); - - cursor_close(); - txn_end(true); - //---------------------------------------------------------------------------- - - if (dbi) { - if (config.params.drop_table && !mode_readonly()) { - txn_begin(false); - db_table_drop(dbi); - err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("append: bailout-clean due '%s'", mdbx_strerror(err)); - return true; - } - } else - db_table_close(dbi); - } - return true; -} diff --git a/src/contrib/db/libmdbx/test/base.h b/src/contrib/db/libmdbx/test/base.h deleted file mode 100644 index 0494281..0000000 --- a/src/contrib/db/libmdbx/test/base.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#pragma warning(push, 1) -#pragma warning(disable : 4548) /* expression before comma has no effect; \ - expected expression with side - effect */ -#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ - semantics are not enabled. Specify /EHsc */ -#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ - mode specified; termination on exception \ - is not guaranteed. Specify /EHsc */ -#endif /* _MSC_VER (warnings) */ - -/* If you wish to build your application for a previous Windows platform, - * include WinSDKVer.h and set the _WIN32_WINNT macro to the platform you - * wish to support before including SDKDDKVer.h. - * - * TODO: #define _WIN32_WINNT WIN32_MUSTDIE */ -#include -#endif /* WINDOWS */ - -#ifdef __APPLE__ -#define _DARWIN_C_SOURCE -#endif - -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -#ifdef _BSD_SOURCE -#include -#endif - -#include -#include -#include // for PRId64, PRIu64 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MDBX_INTERNAL_FUNC -#define MDBX_INTERNAL_VAR extern -#define MDBX_TOOLS /* Avoid using internal mdbx_assert() */ -#include "../mdbx.h" -#include "../src/elements/defs.h" -#include "../src/elements/osal.h" - -#if !defined(__thread) && (defined(_MSC_VER) || defined(__DMC__)) -#define __thread __declspec(thread) -#endif /* __thread */ - -#ifdef _MSC_VER -#pragma warning(pop) -#pragma warning(disable : 4201) /* nonstandard extension used : \ - nameless struct / union */ -#pragma warning(disable : 4127) /* conditional expression is constant */ -#if _MSC_VER < 1900 -#pragma warning(disable : 4510) /* default constructor could \ - not be generated */ -#pragma warning(disable : 4512) /* assignment operator could \ - not be generated */ -#pragma warning(disable : 4610) /* user-defined constructor required */ -#ifndef snprintf -#define snprintf(buffer, buffer_size, format, ...) \ - _snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__) -#endif -#ifndef vsnprintf -#define vsnprintf(buffer, buffer_size, format, args) \ - _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args) -#endif -#pragma warning(disable : 4996) /* 'vsnprintf': This function or variable \ - may be unsafe */ -#endif -#endif /* _MSC_VER */ diff --git a/src/contrib/db/libmdbx/test/cases.cc b/src/contrib/db/libmdbx/test/cases.cc deleted file mode 100644 index df6d402..0000000 --- a/src/contrib/db/libmdbx/test/cases.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -void configure_actor(unsigned &last_space_id, const actor_testcase testcase, - const char *space_id_cstr, const actor_params ¶ms) { - unsigned wait4id = 0; - - if (params.waitfor_nops) { - for (auto i = global::actors.rbegin(); i != global::actors.rend(); ++i) { - if (i->is_waitable(params.waitfor_nops)) { - if (i->signal_nops && i->signal_nops != params.waitfor_nops) - failure("Previous waitable actor (id=%u) already linked on %u-ops\n", - i->actor_id, i->signal_nops); - wait4id = i->actor_id; - i->signal_nops = params.waitfor_nops; - break; - } - } - if (!wait4id) - failure("No previous waitable actor for %u-ops\n", params.waitfor_nops); - } - - unsigned space_id = 0; - if (!space_id_cstr || strcmp(space_id_cstr, "auto") == 0) - space_id = last_space_id + 1; - else { - char *end = nullptr; - errno = 0; - space_id = strtoul(space_id_cstr, &end, 0); - if (errno) - failure_perror("Expects an integer value for space-id\n", errno); - if (end && *end) - failure("The '%s' is unexpected for space-id\n", end); - } - - if (space_id > ACTOR_ID_MAX) - failure("Invalid space-id %u\n", space_id); - last_space_id = space_id; - - log_trace("configure_actor: space %u for %s", space_id, - testcase2str(testcase)); - global::actors.emplace_back( - actor_config(testcase, params, space_id, wait4id)); - global::databases.insert(params.pathname_db); -} - -void testcase_setup(const char *casename, actor_params ¶ms, - unsigned &last_space_id) { - if (strcmp(casename, "basic") == 0) { - log_notice(">>> testcase_setup(%s)", casename); - configure_actor(last_space_id, ac_nested, nullptr, params); - configure_actor(last_space_id, ac_hill, nullptr, params); - configure_actor(last_space_id, ac_ttl, nullptr, params); - configure_actor(last_space_id, ac_copy, nullptr, params); - configure_actor(last_space_id, ac_append, nullptr, params); - configure_actor(last_space_id, ac_jitter, nullptr, params); - configure_actor(last_space_id, ac_try, nullptr, params); - configure_actor(last_space_id, ac_jitter, nullptr, params); - configure_actor(last_space_id, ac_try, nullptr, params); - log_notice("<<< testcase_setup(%s): done", casename); - } else { - failure("unknown testcase `%s`", casename); - } -} - -void keycase_setup(const char *casename, actor_params ¶ms) { - if (strcmp(casename, "random") == 0 || strcmp(casename, "prng") == 0) { - log_notice(">>> keycase_setup(%s)", casename); - params.keygen.keycase = kc_random; - // TODO - log_notice("<<< keycase_setup(%s): done", casename); - } else if (strcmp(casename, "dashes") == 0 || - strcmp(casename, "aside") == 0) { - log_notice(">>> keycase_setup(%s)", casename); - params.keygen.keycase = kc_dashes; - // TODO - log_notice("<<< keycase_setup(%s): done", casename); - } else if (strcmp(casename, "custom") == 0) { - log_notice("=== keycase_setup(%s): skip", casename); - params.keygen.keycase = kc_custom; - } else { - failure("unknown keycase `%s`", casename); - } -} - -/* TODO */ diff --git a/src/contrib/db/libmdbx/test/chrono.cc b/src/contrib/db/libmdbx/test/chrono.cc deleted file mode 100644 index 315d379..0000000 --- a/src/contrib/db/libmdbx/test/chrono.cc +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -namespace chrono { - -#ifndef NSEC_PER_SEC -#define NSEC_PER_SEC 1000000000u -#endif /* NSEC_PER_SEC */ - -uint32_t ns2fractional(uint32_t ns) { - assert(ns < NSEC_PER_SEC); - /* LY: здеÑÑŒ и далее иÑпользуетÑÑ "длинное деление", которое - * Ð´Ð»Ñ ÑÑноÑти кода оÑтавлено как еÑть (без ручной оптимизации). Так как - * GCC, Clang и даже MSVC Ñами давно умеют конвертировать деление на - * конÑтанту в быÑтрую reciprocal-форму. */ - return ((uint64_t)ns << 32) / NSEC_PER_SEC; -} - -uint32_t fractional2ns(uint32_t fractional) { - return (fractional * (uint64_t)NSEC_PER_SEC) >> 32; -} - -#ifndef USEC_PER_SEC -#define USEC_PER_SEC 1000000u -#endif /* USEC_PER_SEC */ -uint32_t us2fractional(uint32_t us) { - assert(us < USEC_PER_SEC); - return ((uint64_t)us << 32) / USEC_PER_SEC; -} - -uint32_t fractional2us(uint32_t fractional) { - return (fractional * (uint64_t)USEC_PER_SEC) >> 32; -} - -#ifndef MSEC_PER_SEC -#define MSEC_PER_SEC 1000u -#endif /* MSEC_PER_SEC */ -uint32_t ms2fractional(uint32_t ms) { - assert(ms < MSEC_PER_SEC); - return ((uint64_t)ms << 32) / MSEC_PER_SEC; -} - -uint32_t fractional2ms(uint32_t fractional) { - return (fractional * (uint64_t)MSEC_PER_SEC) >> 32; -} - -time from_ns(uint64_t ns) { - time result; - result.fixedpoint = ((ns / NSEC_PER_SEC) << 32) | - ns2fractional((uint32_t)(ns % NSEC_PER_SEC)); - return result; -} - -time from_us(uint64_t us) { - time result; - result.fixedpoint = ((us / USEC_PER_SEC) << 32) | - us2fractional((uint32_t)(us % USEC_PER_SEC)); - return result; -} - -time from_ms(uint64_t ms) { - time result; - result.fixedpoint = ((ms / MSEC_PER_SEC) << 32) | - ms2fractional((uint32_t)(ms % MSEC_PER_SEC)); - return result; -} - -time now_realtime() { -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - static void(WINAPI * query_time)(LPFILETIME); - if (!query_time) { - query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress( - GetModuleHandle(TEXT("kernel32.dll")), - "GetSystemTimePreciseAsFileTime"); - if (!query_time) - query_time = GetSystemTimeAsFileTime; - } - - FILETIME filetime; - query_time(&filetime); - uint64_t ns100 = - (uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime; - return from_ns((ns100 - UINT64_C(116444736000000000)) * 100u); -#else - struct timespec ts; - if (unlikely(clock_gettime(CLOCK_REALTIME, &ts))) - failure_perror("clock_gettime(CLOCK_REALTIME", errno); - - return from_timespec(ts); -#endif -} - -time now_motonic() { -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - static uint64_t reciprocal; - static LARGE_INTEGER Frequency; - if (reciprocal == 0) { - if (!QueryPerformanceFrequency(&Frequency)) - failure_perror("QueryPerformanceFrequency()", GetLastError()); - reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) / - Frequency.QuadPart); - assert(reciprocal); - } - - LARGE_INTEGER Counter; - if (!QueryPerformanceCounter(&Counter)) - failure_perror("QueryPerformanceCounter()", GetLastError()); - - time result; - result.fixedpoint = (Counter.QuadPart / Frequency.QuadPart) << 32; - uint64_t mod = Counter.QuadPart % Frequency.QuadPart; - result.fixedpoint += (mod * reciprocal) >> 16; - return result; -#else - struct timespec ts; - if (unlikely(clock_gettime(CLOCK_MONOTONIC, &ts))) - failure_perror("clock_gettime(CLOCK_MONOTONIC)", errno); - - return from_timespec(ts); -#endif -} - -} /* namespace chrono */ diff --git a/src/contrib/db/libmdbx/test/chrono.h b/src/contrib/db/libmdbx/test/chrono.h deleted file mode 100644 index 07cdef6..0000000 --- a/src/contrib/db/libmdbx/test/chrono.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" -#include "utils.h" - -namespace chrono { - -#pragma pack(push, 1) - -typedef union time { - uint64_t fixedpoint; - __anonymous_struct_extension__ struct { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint32_t fractional; - union { - uint32_t utc; - uint32_t integer; - }; -#else - union { - uint32_t utc; - uint32_t integer; - }; - uint32_t fractional; -#endif - }; - - void reset() { fixedpoint = 0; } - uint32_t seconds() const { return utc; } -} time; - -#pragma pack(pop) - -uint32_t ns2fractional(uint32_t); -uint32_t fractional2ns(uint32_t); -uint32_t us2fractional(uint32_t); -uint32_t fractional2us(uint32_t); -uint32_t ms2fractional(uint32_t); -uint32_t fractional2ms(uint32_t); - -time from_ns(uint64_t us); -time from_us(uint64_t ns); -time from_ms(uint64_t ms); - -inline time from_seconds(uint64_t seconds) { - assert(seconds < UINT32_MAX); - time result; - result.fixedpoint = seconds << 32; - return result; -} - -inline time from_utc(time_t utc) { - assert(utc >= 0); - return from_seconds((uint64_t)utc); -} - -inline time infinite() { - time result; - result.fixedpoint = UINT64_MAX; - return result; -} - -#if defined(HAVE_TIMESPEC_TV_NSEC) || defined(__timespec_defined) || \ - defined(CLOCK_REALTIME) -inline time from_timespec(const struct timespec &ts) { - time result; - result.fixedpoint = - ((uint64_t)ts.tv_sec << 32) | ns2fractional((uint32_t)ts.tv_nsec); - return result; -} -#endif /* HAVE_TIMESPEC_TV_NSEC */ - -#if defined(HAVE_TIMEVAL_TV_USEC) || defined(_STRUCT_TIMEVAL) -inline time from_timeval(const struct timeval &tv) { - time result; - result.fixedpoint = - ((uint64_t)tv.tv_sec << 32) | us2fractional((uint32_t)tv.tv_usec); - return result; -} -#endif /* HAVE_TIMEVAL_TV_USEC */ - -time now_realtime(); -time now_motonic(); - -} /* namespace chrono */ diff --git a/src/contrib/db/libmdbx/test/config.cc b/src/contrib/db/libmdbx/test/config.cc deleted file mode 100644 index e900d4a..0000000 --- a/src/contrib/db/libmdbx/test/config.cc +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -#if defined(_MSC_VER) && !defined(strcasecmp) -#define strcasecmp(str, len) _stricmp(str, len) -#endif /* _MSC_VER && strcasecmp() */ - -namespace config { - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - const char **value, const char *default_value) { - assert(narg < argc); - const char *current = argv[narg]; - const size_t optlen = strlen(option); - - if (strncmp(current, "--", 2) || strncmp(current + 2, option, optlen)) - return false; - - if (!value) { - if (current[optlen + 2] == '=') - failure("Option '--%s' doen't accept any value\n", option); - return true; - } - - *value = nullptr; - if (current[optlen + 2] == '=') { - *value = ¤t[optlen + 3]; - return true; - } - - if (narg + 1 < argc && strncmp("--", argv[narg + 1], 2) != 0) { - *value = argv[narg + 1]; - if (strcmp(*value, "default") == 0) { - if (!default_value) - failure("Option '--%s' doen't accept default value\n", option); - *value = default_value; - } - ++narg; - return true; - } - - if (default_value) { - *value = default_value; - return true; - } - - failure("No value given for '--%s' option\n", option); -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - std::string &value, bool allow_empty) { - return parse_option(argc, argv, narg, option, value, allow_empty, - allow_empty ? "" : nullptr); -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - std::string &value, bool allow_empty, - const char *default_value) { - const char *value_cstr; - if (!parse_option(argc, argv, narg, option, &value_cstr, default_value)) - return false; - - if (!allow_empty && strlen(value_cstr) == 0) - failure("Value for option '--%s' could't be empty\n", option); - - value = value_cstr; - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - unsigned &mask, const option_verb *verbs) { - const char *list; - if (!parse_option(argc, argv, narg, option, &list)) - return false; - - unsigned clear = 0; - while (*list) { - if (*list == ',' || *list == ' ' || *list == '\t') { - ++list; - continue; - } - - const char *const comma = strchr(list, ','); - const bool strikethrough = *list == '-' || *list == '~'; - if (strikethrough || *list == '+') - ++list; - else - mask = clear; - const size_t len = (comma) ? comma - list : strlen(list); - const option_verb *scan = verbs; - - while (true) { - if (!scan->verb) - failure("Unknown verb '%.*s', for option '==%s'\n", (int)len, list, - option); - if (strlen(scan->verb) == len && strncmp(list, scan->verb, len) == 0) { - mask = strikethrough ? mask & ~scan->mask : mask | scan->mask; - clear = strikethrough ? clear & ~scan->mask : clear | scan->mask; - list += len; - break; - } - ++scan; - } - } - - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - uint64_t &value, const scale_mode scale, - const uint64_t minval, const uint64_t maxval, - const uint64_t default_value) { - - const char *value_cstr; - if (!parse_option(argc, argv, narg, option, &value_cstr)) - return false; - - if (default_value && strcmp(value_cstr, "default") == 0) { - value = default_value; - return true; - } - - if (strcmp(value_cstr, "min") == 0 || strcmp(value_cstr, "minimal") == 0) { - value = minval; - return true; - } - - if (strcmp(value_cstr, "max") == 0 || strcmp(value_cstr, "maximal") == 0) { - value = maxval; - return true; - } - - char *suffix = nullptr; - errno = 0; - unsigned long long raw = strtoull(value_cstr, &suffix, 0); - if ((suffix && *suffix) || errno) { - suffix = nullptr; - errno = 0; - raw = strtoull(value_cstr, &suffix, 10); - } - if (errno) - failure("Option '--%s' expects a numeric value (%s)\n", option, - test_strerror(errno)); - - uint64_t multipler = 1; - if (suffix && *suffix) { - if (scale == no_scale) - failure("Option '--%s' doen't accepts suffixes, so '%s' is unexpected\n", - option, suffix); - if (strcmp(suffix, "K") == 0 || strcasecmp(suffix, "Kilo") == 0) - multipler = (scale == decimal) ? UINT64_C(1000) : UINT64_C(1024); - else if (strcmp(suffix, "M") == 0 || strcasecmp(suffix, "Mega") == 0) - multipler = - (scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024; - else if (strcmp(suffix, "G") == 0 || strcasecmp(suffix, "Giga") == 0) - multipler = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 - : UINT64_C(1024) * 1024 * 1024; - else if (strcmp(suffix, "T") == 0 || strcasecmp(suffix, "Tera") == 0) - multipler = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 * 1000 - : UINT64_C(1024) * 1024 * 1024 * 1024; - else if (scale == duration && - (strcmp(suffix, "s") == 0 || strcasecmp(suffix, "Seconds") == 0)) - multipler = 1; - else if (scale == duration && - (strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0)) - multipler = 60; - else if (scale == duration && - (strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0)) - multipler = 3600; - else if (scale == duration && - (strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0)) - multipler = 3600 * 24; - else - failure( - "Option '--%s' expects a numeric value with Kilo/Mega/Giga/Tera %s" - "suffixes, but '%s' is unexpected\n", - option, (scale == duration) ? "or Seconds/Minutes/Hours/Days " : "", - suffix); - } - - if (raw >= UINT64_MAX / multipler) - failure("The value for option '--%s' is too huge\n", option); - - value = raw * multipler; - if (maxval && value > maxval) - failure("The maximal value for option '--%s' is %" PRIu64 "\n", option, - maxval); - if (value < minval) - failure("The minimal value for option '--%s' is %" PRIu64 "\n", option, - minval); - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - unsigned &value, const scale_mode scale, - const unsigned minval, const unsigned maxval, - const unsigned default_value) { - - uint64_t huge; - if (!parse_option(argc, argv, narg, option, huge, scale, minval, maxval, - default_value)) - return false; - value = (unsigned)huge; - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - uint8_t &value, const uint8_t minval, const uint8_t maxval, - const uint8_t default_value) { - - uint64_t huge; - if (!parse_option(argc, argv, narg, option, huge, no_scale, minval, maxval, - default_value)) - return false; - value = (uint8_t)huge; - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - int64_t &value, const int64_t minval, const int64_t maxval, - const int64_t default_value) { - uint64_t proxy = (uint64_t)value; - if (parse_option(argc, argv, narg, option, proxy, config::binary, - (uint64_t)minval, (uint64_t)maxval, - (uint64_t)default_value)) { - value = (int64_t)proxy; - return true; - } - return false; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - int32_t &value, const int32_t minval, const int32_t maxval, - const int32_t default_value) { - uint64_t proxy = (uint64_t)value; - if (parse_option(argc, argv, narg, option, proxy, config::binary, - (uint64_t)minval, (uint64_t)maxval, - (uint64_t)default_value)) { - value = (int32_t)proxy; - return true; - } - return false; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - bool &value) { - const char *value_cstr = nullptr; - if (!parse_option(argc, argv, narg, option, &value_cstr, "yes")) { - const char *current = argv[narg]; - if (strncmp(current, "--no-", 5) == 0 && strcmp(current + 5, option) == 0) { - value = false; - return true; - } - if (strncmp(current, "--dont-", 7) == 0 && - strcmp(current + 7, option) == 0) { - value = false; - return true; - } - return false; - } - - if (!value_cstr) { - value = true; - return true; - } - - if (strcasecmp(value_cstr, "yes") == 0 || strcasecmp(value_cstr, "1") == 0) { - value = true; - return true; - } - - if (strcasecmp(value_cstr, "no") == 0 || strcasecmp(value_cstr, "0") == 0) { - value = false; - return true; - } - - failure( - "Option '--%s' expects a 'boolean' value Yes/No, so '%s' is unexpected\n", - option, value_cstr); -} - -//----------------------------------------------------------------------------- - -const struct option_verb mode_bits[] = { - {"rdonly", MDBX_RDONLY}, {"mapasync", MDBX_MAPASYNC}, - {"utterly", MDBX_UTTERLY_NOSYNC}, {"nosubdir", MDBX_NOSUBDIR}, - {"nosync", MDBX_NOSYNC}, {"nometasync", MDBX_NOMETASYNC}, - {"writemap", MDBX_WRITEMAP}, {"notls", MDBX_NOTLS}, - {"nordahead", MDBX_NORDAHEAD}, {"nomeminit", MDBX_NOMEMINIT}, - {"coalesce", MDBX_COALESCE}, {"lifo", MDBX_LIFORECLAIM}, - {"perturb", MDBX_PAGEPERTURB}, {nullptr, 0}}; - -const struct option_verb table_bits[] = { - {"key.reverse", MDBX_REVERSEKEY}, - {"key.integer", MDBX_INTEGERKEY}, - {"data.integer", MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT}, - {"data.fixed", MDBX_DUPFIXED | MDBX_DUPSORT}, - {"data.reverse", MDBX_REVERSEDUP | MDBX_DUPSORT}, - {"data.dups", MDBX_DUPSORT}, - {nullptr, 0}}; - -static void dump_verbs(const char *caption, size_t bits, - const struct option_verb *verbs) { - log_verbose("%s: 0x%" PRIx64 " = ", caption, (uint64_t)bits); - - const char *comma = ""; - while (verbs->mask && bits) { - if ((bits & verbs->mask) == verbs->mask) { - logging::feed("%s%s", comma, verbs->verb); - bits -= verbs->mask; - comma = ", "; - } - ++verbs; - } - - logging::feed("%s\n", (*comma == '\0') ? "none" : ""); -} - -static void dump_duration(const char *caption, unsigned duration) { - log_verbose("%s: ", caption); - if (duration) { - if (duration > 24 * 3600) - logging::feed("%u_", duration / (24 * 3600)); - if (duration > 3600) - logging::feed("%02u:", (duration % (24 * 3600)) / 3600); - logging::feed("%02u:%02u", (duration % 3600) / 60, duration % 60); - } else { - logging::feed("INFINITE"); - } - logging::feed("\n"); -} - -void dump(const char *title) { - logging::local_suffix indent(title); - - for (auto i = global::actors.begin(); i != global::actors.end(); ++i) { - log_verbose("#%u, testcase %s, space_id/table %u\n", i->actor_id, - testcase2str(i->testcase), i->space_id); - indent.push(); - - if (i->params.loglevel) { - log_verbose("log: level %u, %s\n", i->params.loglevel, - i->params.pathname_log.empty() - ? "console" - : i->params.pathname_log.c_str()); - } - - log_verbose("database: %s, size %" PRIuPTR "[%" PRIiPTR "..%" PRIiPTR - ", %i %i, %i]\n", - i->params.pathname_db.c_str(), i->params.size_now, - i->params.size_lower, i->params.size_upper, - i->params.shrink_threshold, i->params.growth_step, - i->params.pagesize); - - dump_verbs("mode", i->params.mode_flags, mode_bits); - dump_verbs("table", i->params.table_flags, table_bits); - - if (i->params.test_nops) - log_verbose("iterations/records %u\n", i->params.test_nops); - else - dump_duration("duration", i->params.test_duration); - - if (i->params.nrepeat) - log_verbose("repeat %u\n", i->params.nrepeat); - else - log_verbose("repeat ETERNALLY\n"); - - log_verbose("threads %u\n", i->params.nthreads); - - log_verbose( - "keygen.params: case %s, width %u, mesh %u, rotate %u, offset %" PRIu64 - ", split %u/%u\n", - keygencase2str(i->params.keygen.keycase), i->params.keygen.width, - i->params.keygen.mesh, i->params.keygen.rotate, i->params.keygen.offset, - i->params.keygen.split, - i->params.keygen.width - i->params.keygen.split); - log_verbose("keygen.seed: %u\n", i->params.keygen.seed); - log_verbose("key: minlen %u, maxlen %u\n", i->params.keylen_min, - i->params.keylen_max); - log_verbose("data: minlen %u, maxlen %u\n", i->params.datalen_min, - i->params.datalen_max); - - log_verbose("batch: read %u, write %u\n", i->params.batch_read, - i->params.batch_write); - - if (i->params.waitfor_nops) - log_verbose("wait: actor %u for %u ops\n", i->wait4id, - i->params.waitfor_nops); - else if (i->params.delaystart) - dump_duration("delay", i->params.delaystart); - else - log_verbose("no-delay\n"); - - if (i->params.inject_writefaultn) - log_verbose("inject-writefault on %u ops\n", - i->params.inject_writefaultn); - else - log_verbose("no-inject-writefault\n"); - - log_verbose("limits: readers %u, tables %u\n", i->params.max_readers, - i->params.max_tables); - - log_verbose("drop table: %s\n", i->params.drop_table ? "Yes" : "No"); - log_verbose("ignore MDBX_MAP_FULL error: %s\n", - i->params.ignore_dbfull ? "Yes" : "No"); - log_verbose("verifying by speculum: %s\n", - i->params.speculum ? "Yes" : "No"); - - indent.pop(); - } - - dump_duration("timeout", global::config::timeout_duration_seconds); - log_verbose("cleanup: before %s, after %s\n", - global::config::cleanup_before ? "Yes" : "No", - global::config::cleanup_after ? "Yes" : "No"); - - log_verbose("failfast: %s\n", global::config::failfast ? "Yes" : "No"); - log_verbose("progress indicator: %s\n", - global::config::progress_indicator ? "Yes" : "No"); - log_verbose("console mode: %s\n", - global::config::console_mode ? "Yes" : "No"); -} - -} /* namespace config */ - -//----------------------------------------------------------------------------- - -using namespace config; - -actor_config::actor_config(actor_testcase testcase, const actor_params ¶ms, - unsigned space_id, unsigned wait4id) - : params(params) { - this->space_id = space_id; - this->actor_id = 1 + (unsigned)global::actors.size(); - this->testcase = testcase; - this->wait4id = wait4id; - signal_nops = 0; -} - -const std::string actor_config::serialize(const char *prefix) const { - simple_checksum checksum; - - std::string result; - if (prefix) - result.append(prefix); - - checksum.push(params.pathname_db); - result.append(params.pathname_db); - result.push_back('|'); - - checksum.push(params.pathname_log); - result.append(params.pathname_log); - result.push_back('|'); - - static_assert(std::is_pod::value, - "actor_params_pod should by POD"); - result.append(data2hex(static_cast(¶ms), - sizeof(actor_params_pod), checksum)); - result.push_back('|'); - - static_assert(std::is_pod::value, - "actor_config_pod should by POD"); - result.append(data2hex(static_cast(this), - sizeof(actor_config_pod), checksum)); - result.push_back('|'); - result.push_back(global::config::progress_indicator ? 'Y' : 'N'); - checksum.push(global::config::progress_indicator); - result.push_back(global::config::console_mode ? 'Y' : 'N'); - checksum.push(global::config::console_mode); - result.push_back('|'); - - result.append(osal_serialize(checksum)); - result.push_back('|'); - - result.append(std::to_string(checksum.value)); - return result; -} - -bool actor_config::deserialize(const char *str, actor_config &config) { - simple_checksum checksum; - - TRACE(">> actor_config::deserialize: %s\n", str); - - const char *slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-1\n"); - return false; - } - config.params.pathname_db.assign(str, slash - str); - checksum.push(config.params.pathname_db); - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-2\n"); - return false; - } - config.params.pathname_log.assign(str, slash - str); - checksum.push(config.params.pathname_log); - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-3\n"); - return false; - } - static_assert(std::is_pod::value, - "actor_params_pod should by POD"); - if (!hex2data(str, slash, static_cast(&config.params), - sizeof(actor_params_pod), checksum)) { - TRACE("<< actor_config::deserialize: actor_params_pod(%.*s)\n", - (int)(slash - str), str); - return false; - } - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-4\n"); - return false; - } - static_assert(std::is_pod::value, - "actor_config_pod should by POD"); - if (!hex2data(str, slash, static_cast(&config), - sizeof(actor_config_pod), checksum)) { - TRACE("<< actor_config::deserialize: actor_config_pod(%.*s)\n", - (int)(slash - str), str); - return false; - } - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-5\n"); - return false; - } - if ((str[0] == 'Y' || str[0] == 'N') && (str[1] == 'Y' || str[1] == 'N')) { - global::config::progress_indicator = str[0] == 'Y'; - checksum.push(global::config::progress_indicator); - global::config::console_mode = str[1] == 'Y'; - checksum.push(global::config::console_mode); - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-6\n"); - return false; - } - } - - if (!config.osal_deserialize(str, slash, checksum)) { - TRACE("<< actor_config::deserialize: osal\n"); - return false; - } - str = slash + 1; - - uint64_t verify = std::stoull(std::string(str)); - if (checksum.value != verify) { - TRACE("<< actor_config::deserialize: checksum mismatch\n"); - return false; - } - - TRACE("<< actor_config::deserialize: OK\n"); - return true; -} - -unsigned actor_params::mdbx_keylen_min() const { - return (table_flags & MDBX_INTEGERKEY) ? 4 : 0; -} - -unsigned actor_params::mdbx_keylen_max() const { - return (table_flags & MDBX_INTEGERKEY) - ? 8 - : std::min((unsigned)mdbx_limits_keysize_max(pagesize), - (unsigned)UINT16_MAX); -} - -unsigned actor_params::mdbx_datalen_min() const { - return (table_flags & MDBX_INTEGERDUP) ? 4 : 0; -} - -unsigned actor_params::mdbx_datalen_max() const { - return (table_flags & MDBX_INTEGERDUP) - ? 8 - : std::min((table_flags & MDBX_DUPSORT) - ? (unsigned)mdbx_limits_keysize_max(pagesize) - : (unsigned)MDBX_MAXDATASIZE, - (unsigned)UINT16_MAX); -} diff --git a/src/contrib/db/libmdbx/test/config.h b/src/contrib/db/libmdbx/test/config.h deleted file mode 100644 index 3703d3f..0000000 --- a/src/contrib/db/libmdbx/test/config.h +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" -#include "log.h" -#include "utils.h" - -#define ACTOR_ID_MAX INT16_MAX - -enum actor_testcase { - ac_none, - ac_hill, - ac_deadread, - ac_deadwrite, - ac_jitter, - ac_try, - ac_copy, - ac_append, - ac_ttl, - ac_nested -}; - -enum actor_status { - as_unknown, - as_debuging, - as_running, - as_successful, - as_killed, - as_failed, - as_coredump, -}; - -const char *testcase2str(const actor_testcase); -const char *status2str(actor_status status); - -enum keygen_case { - kc_random, /* [ 6.. 2.. 7.. 4.. 0.. 1.. 5.. 3.. ] */ - kc_dashes, /* [ 0123.. 4567.. ] */ - kc_custom, - /* TODO: more cases */ -}; - -const char *keygencase2str(const keygen_case); - -//----------------------------------------------------------------------------- - -namespace config { - -enum scale_mode { no_scale, decimal, binary, duration }; - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - const char **value, const char *default_value = nullptr); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - std::string &value, bool allow_empty = false); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - std::string &value, bool allow_empty, - const char *default_value); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - bool &value); - -struct option_verb { - const char *const verb; - unsigned mask; -}; - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - unsigned &mask, const option_verb *verbs); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - uint64_t &value, const scale_mode scale, - const uint64_t minval = 0, const uint64_t maxval = INT64_MAX, - const uint64_t default_value = 0); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - unsigned &value, const scale_mode scale, - const unsigned minval = 0, const unsigned maxval = INT32_MAX, - const unsigned default_value = 0); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - uint8_t &value, const uint8_t minval = 0, - const uint8_t maxval = 255, const uint8_t default_value = 0); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - int64_t &value, const int64_t minval, const int64_t maxval, - const int64_t default_value = -1); - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - int32_t &value, const int32_t minval, const int32_t maxval, - const int32_t default_value = -1); - -inline bool parse_option_intptr(int argc, char *const argv[], int &narg, - const char *option, intptr_t &value, - const intptr_t minval, const intptr_t maxval, - const intptr_t default_value = -1) { - static_assert(sizeof(intptr_t) == 4 || sizeof(intptr_t) == 8, "WTF?"); - if (sizeof(intptr_t) == 8) - return parse_option(argc, argv, narg, option, - *reinterpret_cast(&value), int64_t(minval), - int64_t(maxval), int64_t(default_value)); - else - return parse_option(argc, argv, narg, option, - *reinterpret_cast(&value), int32_t(minval), - int32_t(maxval), int32_t(default_value)); -} - -//----------------------------------------------------------------------------- - -#pragma pack(push, 1) - -struct keygen_params_pod { - /* Параметры генератора пар key-value. - * - * Ключи и Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð³ÐµÐ½ÐµÑ€Ð¸Ñ€ÑƒÑŽÑ‚ÑÑ Ð¿Ð¾ задаваемым параметрам на оÑнове "плоÑкой" - * иÑходной координаты. При Ñтом, в общем Ñлучае, в процеÑÑе теÑтов иÑÑ…Ð¾Ð´Ð½Ð°Ñ - * координата поÑледовательно итерируетÑÑ Ð² заданном диапазоне, а необходимые - * паттерны/поÑледовательноÑти/узоры получаютÑÑ Ð·Ð° Ñчет Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ - * иÑходной координаты, ÑоглаÑно опиÑанным ниже параметрам. - * - * Стоит отметить, что порÑдок опиÑÐ°Ð½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² Ð´Ð»Ñ ÑƒÐ´Ð¾Ð±Ñтва Ñовпадает Ñ - * порÑдком их иÑпользованиÑ, Ñ‚.е. Ñ Ð¿Ð¾Ñ€Ñдком ÑоответÑтвующих преобразований. - * - * Второе важное замечание каÑаетÑÑ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ð¹ одновременной координированной - * генерации паттеров как Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡ÐµÐ¹, так и Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹. Суть в том, что - * Ñ‚Ð°ÐºÐ°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñть не нужна по Ñледующим причинам: - * - libmdbx поддерживает два ÑущеÑтвенно различающихÑÑ Ð²Ð¸Ð´Ð° таблиц, - * "уникальные" (без дубликатов и без multi-value), и так называемые - * "Ñ Ð´ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ‚Ð°Ð¼Ð¸" (c multi-value). - * - Ð”Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† "без дубликатов" только размер ÑвÑзанных к ключами значений - * (данных) оказывает влиÑÐ½Ð¸Ñ Ð½Ð° работу движка, непоÑредÑтвенно Ñодержимое - * данных не анализируетÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼ и не оказывает влиÑÐ½Ð¸Ñ Ð½Ð° его работу. - * - Ð”Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† "Ñ Ð´ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ‚Ð°Ð¼Ð¸", при наличии более одного Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ - * некоторого ключа, формируетÑÑ Ð´Ð¾Ñ‡ÐµÑ€Ð½ÐµÐµ btree-поддерево. Это дерево - * формируетÑÑ Ð² отдельном "куÑте" Ñтраниц и обÑлуживаетÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимо - * от Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкого ключа. - * - Таким образом, паттерн генерации значений имеет ÑмыÑл только Ð´Ð»Ñ - * таблиц "Ñ Ð´ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ‚Ð°Ð¼Ð¸" и только в контекÑте одного Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð°. - * Иначе говорÑ, нет ÑмыÑла в Ñо-координации генерации паттернов Ð´Ð»Ñ - * ключей и значений. Более того, генерацию значений вÑегда необходимо - * раÑÑматривать в контекÑте ÑвÑзки Ñ Ð¾Ð´Ð½Ð¸Ð¼ значением ключа. - * - Тем не менее, во вÑех ÑлучаÑÑ… доÑтаточно важным ÑвлÑетÑÑ Ñ€Ð°Ð²Ð½Ð¾Ð¼ÐµÑ€Ð½Ð°Ñ - * вÑех возможных Ñочетаний длин ключей и данных. - * - * width: - * БольшинÑтво теÑтов предполагают Ñоздание или итерирование некоторого - * количеÑтва запиÑей. При Ñтом требуетÑÑ Ð¸Ñ‚ÐµÑ€Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ðµ или Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ - * значений и ключей из некоторого ограниченного проÑтранÑтва вариантов. - * - * Параметр width задает такую ширину проÑтранÑтва вариантов в битах. - * Таким образом мощноÑть проÑтранÑтва вариантов (пока) вÑегда равна - * Ñтепени двойки. Это ограничение можно ÑнÑть, но ценой ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ - * вычиÑлительной ÑложноÑти, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¿Ð¾Ñ‚ÐµÑ€ÑŽ проÑтоты и прозрачноÑти. - * - * С другой Ñтороны, не-битовый width может быть полезен: - * - Позволит генерировать ключи/Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² точно задаваемом диапазоне. - * Ðапример, перебрать в пÑевдо-Ñлучайном порÑдке 10001 значение. - * - Позволит поровну разделÑть заданное проÑтранÑтво (диапазон) - * ключей/значений между количеÑтвом потоков некратным Ñтепени двойки. - * - * mesh и seed: - * ПозволÑÑŽÑ‚ получить пÑевдо-Ñлучайные поÑледовательноÑти ключей/значений. - * Параметр mesh задает Ñколько младших бит иÑходной плоÑкой координаты - * будет "перемешано" (инъективно отображено), а параметр seed позволÑет - * выбрать конкретный вариант "перемешиваниÑ". - * - * Перемешивание выполнÑетÑÑ Ð¿Ñ€Ð¸ ненулевом значении mesh. Перемешивание - * реализуетÑÑ Ð¿Ð¾ÑредÑтвом Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð²ÑƒÑ… инъективных функций Ð´Ð»Ñ - * заданного количеÑтва бит: - * - применÑетÑÑ Ð¿ÐµÑ€Ð²Ð°Ñ Ð¸Ð½ÑŠÐµÐºÑ‚Ð¸Ð²Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ; - * - к результату добавлÑетÑÑ salt полученный из seed; - * - применÑетÑÑ Ð²Ñ‚Ð¾Ñ€Ð°Ñ Ð¸Ð½ÑŠÐµÐºÑ‚Ð¸Ð²Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ; - * - * Следует отметить, что mesh умышленно позволÑет перемешать только младшую - * чаÑть, что при ненулевом значении split (Ñм далее) не позволÑет получать - * пÑевдо-Ñлучайные значений ключей без пÑевдо-ÑлучайноÑти в значениÑÑ…. - * - * Такое ограничение ÑоответÑтвуют внутренней алгоритмике libmdbx. Проще - * говорÑ, мы можем проверить движок пÑевдо-Ñлучайной поÑледовательноÑтью - * ключей на таблицах без дубликатов (без multi-value), а затем проверить - * корректноÑть работу пÑевдо-Ñлучайной поÑледовательноÑтью значений на - * таблицах Ñ Ð´ÑƒÐ±Ð»Ð¸ÐºÐ°Ñ‚Ð°Ð¼Ð¸ (Ñ multi-value), опционально добавлÑÑ - * пÑевдо-ÑлучайноÑти к поÑледовательноÑти ключей. Однако, нет ÑмыÑла - * генерировать пÑевдо-Ñлучайные ключи, одновременно Ñ Ñ„Ð¾Ñ€Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ¼ - * какого-либо паттерна в значениÑÑ…, так как Ñодержимое в данных либо - * не будет иметь Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ (Ð´Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† без дубликатов), либо будет - * обрабатыватьÑÑ Ð² отдельных btree-поддеревьÑÑ…. - * - * rotate и offset: - * Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ ÑлиÑÐ½Ð¸Ñ Ð¸ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñтраниц внутри движка требуютÑÑ - * Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ ÐºÐ»ÑŽÑ‡ÐµÐ¹/значений в виде не-Ñмежных поÑледовательноÑтей, как-бы - * в виде "пунктира", который поÑтепенно заполнÑет веÑÑŒ заданных диапазон. - * - * Параметры позволÑÑŽÑ‚ генерировать такой "пунктир". СоответÑтвенно rotate - * задает цикличеÑкий Ñдвиг вправо, а offset задает Ñмещение, точнее Ð³Ð¾Ð²Ð¾Ñ€Ñ - * Ñложение по модулю внутри диапазона заданного поÑредÑтвом width. - * - * Ðапример, при rotate равном 1 (цикличеÑкий Ñдвиг вправо на 1 бит), - * четные и нечетные иÑходные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑложатÑÑ Ð² две линейные - * поÑледовательноÑти, которые поÑтепенно закроют Ñтаршую и младшую - * половины диапазона. - * - * split: - * Ð”Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† без дубликатов (без multi-value ключей) фактичеÑки требуетÑÑ - * Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ ключей, а данные могут быть поÑтоÑнным. Ðо Ð´Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ† Ñ - * дубликатами (Ñ multi-value ключами) также требуетÑÑ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹. - * - * Ðенулевое значение параметра split фактичеÑки включает генерацию значений, - * при Ñтом значение split определÑет Ñколько бит иÑходного абÑтрактного - * номера будет отрезано Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ð¸ значениÑ. - */ - - uint8_t width; - uint8_t mesh; - uint8_t rotate; - uint8_t split; - uint32_t seed; - uint64_t offset; - keygen_case keycase; -}; - -struct actor_params_pod { - unsigned mode_flags; - unsigned table_flags; - intptr_t size_lower; - intptr_t size_now; - intptr_t size_upper; - int shrink_threshold; - int growth_step; - int pagesize; - - unsigned test_duration; - unsigned test_nops; - unsigned nrepeat; - unsigned nthreads; - - unsigned keylen_min, keylen_max; - unsigned datalen_min, datalen_max; - - unsigned batch_read; - unsigned batch_write; - - unsigned delaystart; - unsigned waitfor_nops; - unsigned inject_writefaultn; - - unsigned max_readers; - unsigned max_tables; - keygen_params_pod keygen; - - uint8_t loglevel; - bool drop_table; - bool ignore_dbfull; - bool speculum; -}; - -struct actor_config_pod { - unsigned actor_id, space_id; - actor_testcase testcase; - unsigned wait4id; - unsigned signal_nops; -}; - -#pragma pack(pop) - -extern const struct option_verb mode_bits[]; -extern const struct option_verb table_bits[]; -void dump(const char *title = "config-dump: "); - -} /* namespace config */ - -struct actor_params : public config::actor_params_pod { - std::string pathname_log; - std::string pathname_db; - void set_defaults(const std::string &tmpdir); - - unsigned mdbx_keylen_min() const; - unsigned mdbx_keylen_max() const; - unsigned mdbx_datalen_min() const; - unsigned mdbx_datalen_max() const; -}; - -struct actor_config : public config::actor_config_pod { - actor_params params; - - bool wanna_event4signalling() const { return true /* TODO ? */; } - - actor_config(actor_testcase testcase, const actor_params ¶ms, - unsigned space_id, unsigned wait4id); - - actor_config(const char *str) { - if (!deserialize(str, *this)) - failure("Invalid internal parameter '%s'\n", str); - } - - const std::string osal_serialize(simple_checksum &) const; - bool osal_deserialize(const char *str, const char *end, simple_checksum &); - - const std::string serialize(const char *prefix) const; - static bool deserialize(const char *str, actor_config &config); - - bool is_waitable(size_t nops) const { - switch (testcase) { - case ac_hill: - if (!params.test_nops || params.test_nops >= nops) - return true; - __fallthrough; - default: - return false; - } - } -}; diff --git a/src/contrib/db/libmdbx/test/copy.cc b/src/contrib/db/libmdbx/test/copy.cc deleted file mode 100644 index ff53153..0000000 --- a/src/contrib/db/libmdbx/test/copy.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include "test.h" - -void testcase_copy::copy_db(const bool with_compaction) { - int err = osal_removefile(copy_pathname); - if (err != MDBX_SUCCESS && err != MDBX_ENOFILE) - failure_perror("mdbx_removefile()", err); - - err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(), - with_compaction ? MDBX_CP_COMPACT : 0); - if (unlikely(err != MDBX_SUCCESS)) - failure_perror(with_compaction ? "mdbx_env_copy(MDBX_CP_COMPACT)" - : "mdbx_env_copy(MDBX_CP_ASIS)", - err); -} - -bool testcase_copy::run() { - jitter_delay(); - db_open(); - assert(!txn_guard); - const bool order = flipcoin(); - jitter_delay(); - copy_db(order); - jitter_delay(); - copy_db(!order); - return true; -} diff --git a/src/contrib/db/libmdbx/test/darwin/LICENSE b/src/contrib/db/libmdbx/test/darwin/LICENSE deleted file mode 100644 index 6a0dd30..0000000 --- a/src/contrib/db/libmdbx/test/darwin/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2015, Aleksey Demakov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/contrib/db/libmdbx/test/darwin/README.md b/src/contrib/db/libmdbx/test/darwin/README.md deleted file mode 100644 index a6a8fd1..0000000 --- a/src/contrib/db/libmdbx/test/darwin/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# DarwinPthreadBarrier - -A pthread_barrier_t implementation for Mac OS/X - -There is no pthread_barrier_t in Mac OS/X pthreads. This project fixes -this omission by providing a simple-minded barrier implementation based -on a pair of pthread_mutex_t and pthread_cond_t. - diff --git a/src/contrib/db/libmdbx/test/darwin/pthread_barrier.c b/src/contrib/db/libmdbx/test/darwin/pthread_barrier.c deleted file mode 100644 index 054aa00..0000000 --- a/src/contrib/db/libmdbx/test/darwin/pthread_barrier.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2015, Aleksey Demakov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "pthread_barrier.h" - -#include - -#ifdef __APPLE__ - -int pthread_barrierattr_init(pthread_barrierattr_t *attr) { - memset(attr, 0, sizeof(pthread_barrierattr_t)); - int m = pthread_mutexattr_init(&attr->mattr); - int c = pthread_condattr_init(&attr->cattr); - return m ? m : c; -} - -int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) { - int c = pthread_condattr_destroy(&attr->cattr); - int m = pthread_mutexattr_destroy(&attr->mattr); - return m ? m : c; -} - -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, - int *__restrict pshared) { - return pthread_condattr_getpshared(&attr->cattr, pshared); -} - -int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) { - int m = pthread_mutexattr_setpshared(&attr->mattr, pshared); - int c = pthread_condattr_setpshared(&attr->cattr, pshared); - return m ? m : c; -} - -int pthread_barrier_init(pthread_barrier_t *__restrict barrier, - const pthread_barrierattr_t *__restrict attr, - unsigned count) { - if (count == 0) - return errno = EINVAL; - - int rc = pthread_mutex_init(&barrier->mutex, attr ? &attr->mattr : 0); - if (rc) - return rc; - - rc = pthread_cond_init(&barrier->cond, attr ? &attr->cattr : 0); - if (rc) { - int errno_save = errno; - pthread_mutex_destroy(&barrier->mutex); - errno = errno_save; - return rc; - } - - barrier->limit = count; - barrier->count = 0; - barrier->phase = 0; - return 0; -} - -int pthread_barrier_destroy(pthread_barrier_t *barrier) { - pthread_mutex_destroy(&barrier->mutex); - pthread_cond_destroy(&barrier->cond); - return 0; -} - -int pthread_barrier_wait(pthread_barrier_t *barrier) { - int rc = pthread_mutex_lock(&barrier->mutex); - if (rc) - return rc; - - barrier->count++; - if (barrier->count >= barrier->limit) { - barrier->phase++; - barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; - } else { - unsigned phase = barrier->phase; - do - pthread_cond_wait(&barrier->cond, &barrier->mutex); - while (phase == barrier->phase); - pthread_mutex_unlock(&barrier->mutex); - return 0; - } -} - -#endif /* __APPLE__ */ diff --git a/src/contrib/db/libmdbx/test/darwin/pthread_barrier.h b/src/contrib/db/libmdbx/test/darwin/pthread_barrier.h deleted file mode 100644 index efa9b9b..0000000 --- a/src/contrib/db/libmdbx/test/darwin/pthread_barrier.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2015, Aleksey Demakov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PTHREAD_BARRIER_H -#define PTHREAD_BARRIER_H - -#include - -#ifdef __APPLE__ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(PTHREAD_BARRIER_SERIAL_THREAD) -#define PTHREAD_BARRIER_SERIAL_THREAD (1) -#endif - -#if !defined(PTHREAD_PROCESS_PRIVATE) -#define PTHREAD_PROCESS_PRIVATE (42) -#endif -#if !defined(PTHREAD_PROCESS_SHARED) -#define PTHREAD_PROCESS_SHARED (43) -#endif - -typedef struct { - pthread_mutexattr_t mattr; - pthread_condattr_t cattr; -} pthread_barrierattr_t; - -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - unsigned int limit; - unsigned int count; - unsigned int phase; -} pthread_barrier_t; - -int pthread_barrierattr_init(pthread_barrierattr_t *attr); -int pthread_barrierattr_destroy(pthread_barrierattr_t *attr); - -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, - int *__restrict pshared); -int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared); - -int pthread_barrier_init(pthread_barrier_t *__restrict barrier, - const pthread_barrierattr_t *__restrict attr, - unsigned int count); -int pthread_barrier_destroy(pthread_barrier_t *barrier); - -int pthread_barrier_wait(pthread_barrier_t *barrier); - -#ifdef __cplusplus -} -#endif - -#endif /* __APPLE__ */ - -#endif /* PTHREAD_BARRIER_H */ diff --git a/src/contrib/db/libmdbx/test/dead.cc b/src/contrib/db/libmdbx/test/dead.cc deleted file mode 100644 index 8f83bbe..0000000 --- a/src/contrib/db/libmdbx/test/dead.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -bool testcase_deadread::run() { - db_open(); - txn_begin(true); - cursor_guard.reset(); - txn_guard.reset(); - db_guard.reset(); - return true; -} - -//----------------------------------------------------------------------------- - -bool testcase_deadwrite::run() { - db_open(); - txn_begin(false); - cursor_guard.reset(); - txn_guard.reset(); - db_guard.reset(); - return true; -} diff --git a/src/contrib/db/libmdbx/test/hill.cc b/src/contrib/db/libmdbx/test/hill.cc deleted file mode 100644 index 9d98909..0000000 --- a/src/contrib/db/libmdbx/test/hill.cc +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -bool testcase_hill::run() { - int err = db_open__begin__table_create_open_clean(dbi); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("hill: bailout-prepare due '%s'", mdbx_strerror(err)); - return false; - } - speculum.clear(); - speculum_commited.clear(); - - /* LY: теÑÑ‚ "холмиком": - * - Ñначала наполнÑем таблицу цикличеÑкими CRUD-манипулÑциÑми, - * которые в каждом цикле делают неÑколько операций, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ðµ, - * но в результате добавлÑÑŽÑ‚ запиÑи. - * - затем очищаем таблицу также CRUD-манипулÑциÑми, но уже Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ - * пропорцией удалений. - * - * При Ñтом очень многое завиÑит от порÑдка перебора ключей: - * - (пÑевдо)Ñлучайное раÑпределение требуетÑÑ Ð»Ð¸ÑˆÑŒ Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñ‚Ñ‹ картины, - * но в целом не покрывает важных кейÑов. - * - кроме (пÑевдо)Ñлучайного перебора требуетÑÑ Ð¿Ð¾Ñледовательное - * итерирование ключей интервалами различной ширины, Ñ Ñ‚ÐµÐ¼ чтобы - * проверить различные варианты как разделениÑ, так и ÑлиÑÐ½Ð¸Ñ Ñтраниц - * внутри движка. - * - при не-уникальных ключах (MDBX_DUPSORT Ñ Ð¿Ð¾Ð´Ð²Ð°Ñ€Ð¸Ð°Ð½Ñ‚Ð°Ð¼Ð¸), Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ - * повтора внутри движка формируетÑÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ðµ btree-дерево, - * ÑоответÑтвенно требуетÑÑ Ñоблюдение аналогичных принципов - * Ð¸Ñ‚ÐµÑ€Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹. - */ - - /* TODO: работа в неÑколько потоков */ - keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); - - keygen::buffer a_key = keygen::alloc(config.params.keylen_max); - keygen::buffer a_data_0 = keygen::alloc(config.params.datalen_max); - keygen::buffer a_data_1 = keygen::alloc(config.params.datalen_max); - keygen::buffer b_key = keygen::alloc(config.params.keylen_max); - keygen::buffer b_data = keygen::alloc(config.params.datalen_max); - - const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_NODUPDATA - : MDBX_NODUPDATA | MDBX_NOOVERWRITE; - const unsigned update_flags = - (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_CURRENT | MDBX_NODUPDATA | MDBX_NOOVERWRITE - : MDBX_NODUPDATA; - - uint64_t serial_count = 0; - uint64_t commited_serial = serial_count; - unsigned txn_nops = 0; - - bool rc = false; - while (should_continue()) { - const keygen::serial_t a_serial = serial_count; - if (unlikely(!keyvalue_maker.increment(serial_count, 1))) { - log_notice("uphill: unexpected key-space overflow"); - break; - } - - const keygen::serial_t b_serial = serial_count; - assert(b_serial > a_serial); - - // Ñоздаем первую запиÑÑŒ из пары - const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); - log_trace("uphill: insert-a (age %" PRIu64 ") %" PRIu64, age_shift, - a_serial); - generate_pair(a_serial, a_key, a_data_1, age_shift); - - err = insert(a_key, a_data_1, insert_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("uphill: bailout at insert-a due '%s'", mdbx_strerror(err)); - txn_restart(true, false); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - failure_perror("mdbx_put(insert-a.1)", err); - } - if (!speculum_verify()) { - log_notice("uphill: bailout after insert-a, before commit"); - goto bailout; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - commited_serial = a_serial; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("uphill: bailout after insert-a, after commit"); - goto bailout; - } - } - - // Ñоздаем вторую запиÑÑŒ из пары - log_trace("uphill: insert-b %" PRIu64, b_serial); - generate_pair(b_serial, b_key, b_data, 0); - err = insert(b_key, b_data, insert_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("uphill: bailout at insert-b due '%s'", mdbx_strerror(err)); - txn_restart(true, false); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - failure_perror("mdbx_put(insert-b)", err); - } - if (!speculum_verify()) { - log_notice("uphill: bailout after insert-b, before commit"); - goto bailout; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - commited_serial = a_serial; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("uphill: bailout after insert-b, after commit"); - goto bailout; - } - } - - // обновлÑем данные в первой запиÑи - log_trace("uphill: update-a (age %" PRIu64 "->0) %" PRIu64, age_shift, - a_serial); - generate_pair(a_serial, a_key, a_data_0, 0); - checkdata("uphill: update-a", dbi, a_key->value, a_data_1->value); - err = replace(a_key, a_data_0, a_data_1, update_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("uphill: bailout at update-a due '%s'", mdbx_strerror(err)); - txn_restart(true, false); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - failure_perror("mdbx_replace(update-a: 1->0)", err); - } - if (!speculum_verify()) { - log_notice("uphill: bailout after update-a, before commit"); - goto bailout; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - commited_serial = a_serial; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("uphill: bailout after update-a, after commit"); - goto bailout; - } - } - - // удалÑем вторую запиÑÑŒ - log_trace("uphill: delete-b %" PRIu64, b_serial); - checkdata("uphill: delete-b", dbi, b_key->value, b_data->value); - err = remove(b_key, b_data); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("uphill: bailout at delete-b due '%s'", mdbx_strerror(err)); - txn_restart(true, false); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - failure_perror("mdbx_del(b)", err); - } - if (!speculum_verify()) { - log_notice("uphill: bailout after delete-b, before commit"); - goto bailout; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); - serial_count = commited_serial; - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - commited_serial = a_serial; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("uphill: bailout after delete-b, after commit"); - goto bailout; - } - } - - report(1); - if (!keyvalue_maker.increment(serial_count, 1)) { - // дошли до границы проÑтранÑтва ключей - serial_count = a_serial; - goto overflow; - } - } - - while (serial_count > 1) { - if (unlikely(!keyvalue_maker.increment(serial_count, -2))) - failure("downhill: unexpected key-space underflow"); - - overflow: - const keygen::serial_t a_serial = serial_count; - const keygen::serial_t b_serial = a_serial + 1; - assert(b_serial > a_serial); - - // обновлÑем первую запиÑÑŒ из пары - const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); - log_trace("downhill: update-a (age 0->%" PRIu64 ") %" PRIu64, age_shift, - a_serial); - generate_pair(a_serial, a_key, a_data_0, 0); - generate_pair(a_serial, a_key, a_data_1, age_shift); - checkdata("downhill: update-a", dbi, a_key->value, a_data_0->value); - err = replace(a_key, a_data_1, a_data_0, update_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("downhill: bailout at update-a due '%s'", - mdbx_strerror(err)); - txn_end(true); - speculum = speculum_commited; - break; - } - failure_perror("mdbx_put(update-a: 0->1)", err); - } - if (!speculum_verify()) { - log_notice("downhill: bailout after update-a, before commit"); - break; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("downhill: bailout after update-a, after commit"); - break; - } - } - - // Ñоздаем вторую запиÑÑŒ из пары - log_trace("downhill: insert-b %" PRIu64, b_serial); - generate_pair(b_serial, b_key, b_data, 0); - err = insert(b_key, b_data, insert_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("downhill: bailout at insert-a due '%s'", - mdbx_strerror(err)); - txn_end(true); - speculum = speculum_commited; - break; - } - failure_perror("mdbx_put(insert-b)", err); - } - if (!speculum_verify()) { - log_notice("downhill: bailout after insert-b, before commit"); - break; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("downhill: bailout after insert-b, after commit"); - break; - } - } - - // удалÑем первую запиÑÑŒ - log_trace("downhill: delete-a (age %" PRIu64 ") %" PRIu64, age_shift, - a_serial); - checkdata("downhill: delete-a", dbi, a_key->value, a_data_1->value); - err = remove(a_key, a_data_1); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("downhill: bailout at delete-a due '%s'", - mdbx_strerror(err)); - txn_end(true); - speculum = speculum_commited; - break; - } - failure_perror("mdbx_del(a)", err); - } - if (!speculum_verify()) { - log_notice("downhill: bailout after delete-a, before commit"); - break; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("downhill: bailout after delete-a, after commit"); - break; - } - } - - // удалÑем вторую запиÑÑŒ - log_trace("downhill: delete-b %" PRIu64, b_serial); - checkdata("downhill: delete-b", dbi, b_key->value, b_data->value); - err = remove(b_key, b_data); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("downhill: bailout at delete-b due '%s'", - mdbx_strerror(err)); - txn_end(true); - speculum = speculum_commited; - break; - } - failure_perror("mdbx_del(b)", err); - } - if (!speculum_verify()) { - log_notice("downhill: bailout after delete-b, before commit"); - break; - } - - if (++txn_nops >= config.params.batch_write) { - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); - speculum = speculum_commited; - break; - } - speculum_commited = speculum; - txn_nops = 0; - if (!speculum_verify()) { - log_notice("downhill: bailout after delete-b, after commit"); - goto bailout; - } - } - - report(1); - } - - rc = speculum_verify(); -bailout: - if (txn_guard) { - err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) - log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); - } - - if (dbi) { - if (config.params.drop_table && !mode_readonly()) { - txn_begin(false); - db_table_drop(dbi); - err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("hill: bailout-clean due '%s'", mdbx_strerror(err)); - return rc; - } - } else - db_table_close(dbi); - } - return rc; -} diff --git a/src/contrib/db/libmdbx/test/jitter.cc b/src/contrib/db/libmdbx/test/jitter.cc deleted file mode 100644 index 38caf33..0000000 --- a/src/contrib/db/libmdbx/test/jitter.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -bool testcase_jitter::run() { - while (should_continue()) { - jitter_delay(); - db_open(); - - if (flipcoin()) { - jitter_delay(); - txn_begin(true); - fetch_canary(); - jitter_delay(); - txn_end(flipcoin()); - } - - jitter_delay(); - txn_begin(mode_readonly()); - jitter_delay(); - if (!mode_readonly()) { - fetch_canary(); - update_canary(1); - /* TODO: - * - db_setsize() - * ... - */ - } - txn_end(flipcoin()); - - if (flipcoin()) { - jitter_delay(); - txn_begin(true); - jitter_delay(); - txn_end(flipcoin()); - } - - jitter_delay(); - db_close(); - - /* just 'align' nops with other tests with batching */ - const auto batching = - std::max(config.params.batch_read, config.params.batch_write); - report(std::max(1u, batching / 2)); - } - return true; -} diff --git a/src/contrib/db/libmdbx/test/keygen.cc b/src/contrib/db/libmdbx/test/keygen.cc deleted file mode 100644 index e156142..0000000 --- a/src/contrib/db/libmdbx/test/keygen.cc +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -namespace keygen { - -static inline __pure_function serial_t mask(unsigned bits) { - assert(bits > 0 && bits <= serial_maxwith); - return serial_allones >> (serial_maxwith - bits); -} - -/* LY: https://en.wikipedia.org/wiki/Injective_function */ -serial_t injective(const serial_t serial, - const unsigned bits /* at least serial_minwith (8) */, - const serial_t salt) { - assert(bits > serial_minwith && bits <= serial_maxwith); - - /* LY: All these "magic" prime numbers were found - * and verified with a bit of brute force. */ - - static const uint64_t m[64 - serial_minwith + 1] = { - /* 8 - 24 */ - 113, 157, 397, 653, 1753, 5641, 9697, 23873, 25693, 80833, 105953, 316937, - 309277, 834497, 1499933, 4373441, 10184137, - /* 25 - 64 */ - 10184137, 17279209, 33990377, 67295161, 284404553, 1075238767, 6346721573, - 6924051577, 19204053433, 45840188887, 53625693977, 73447827913, - 141638870249, 745683604649, 1283334050489, 1100828289853, 2201656586197, - 5871903036137, 11238507001417, 45264020802263, 105008404482889, - 81921776907059, 199987980256399, 307207457507641, 946769023178273, - 2420886491930041, 3601632139991929, 11984491914483833, 21805846439714153, - 23171543400565993, 53353226456762893, 155627817337932409, - 227827205384840249, 816509268558278821, 576933057762605689, - 2623957345935638441, 5048241705479929949, 4634245581946485653, - 4613509448041658233, 4952535426879925961}; - static const uint8_t s[64 - serial_minwith + 1] = { - /* 8 - 24 */ - 2, 3, 4, 4, 2, 4, 3, 3, 7, 3, 3, 4, 8, 3, 10, 3, 11, - /* 25 - 64 */ - 11, 9, 9, 9, 11, 10, 5, 14, 11, 16, 14, 12, 13, 16, 19, 10, 10, 21, 7, 20, - 10, 14, 22, 19, 3, 21, 18, 19, 26, 24, 2, 21, 25, 29, 24, 10, 11, 14, 20, - 19}; - - const auto mult = m[bits - 8]; - const auto shift = s[bits - 8]; - serial_t result = serial * mult; - if (salt) { - const unsigned left = bits / 2; - const unsigned right = bits - left; - result = (result << left) | ((result & mask(bits)) >> right); - result = (result ^ salt) * mult; - } - - result ^= result << shift; - result &= mask(bits); - log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64 - " => %" PRIu64 "/%u", - serial, bits, mult, shift, salt, result, bits); - return result; -} - -void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, - serial_t value_age) { - assert(mapping.width >= serial_minwith && mapping.width <= serial_maxwith); - assert(mapping.split <= mapping.width); - assert(mapping.mesh <= mapping.width); - assert(mapping.rotate <= mapping.width); - assert(mapping.offset <= mask(mapping.width)); - assert(!(key_essentials.flags & - ~(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))); - assert(!(value_essentials.flags & ~(MDBX_INTEGERDUP | MDBX_REVERSEDUP))); - - log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial, - value_age); - - if (mapping.mesh >= serial_minwith) { - serial = - (serial & ~mask(mapping.mesh)) | injective(serial, mapping.mesh, salt); - log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial); - } - - if (mapping.rotate) { - const unsigned right = mapping.rotate; - const unsigned left = mapping.width - right; - serial = (serial << left) | ((serial & mask(mapping.width)) >> right); - log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64, - mapping.rotate, serial, serial); - } - - if (mapping.offset) { - serial = (serial + mapping.offset) & mask(mapping.width); - log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset, - serial); - } - if (base) { - serial += base; - log_trace("keygen-pair: base@%" PRIu64 " => %" PRIu64, base, serial); - } - - serial_t key_serial = serial; - serial_t value_serial = value_age << mapping.split; - if (mapping.split) { - if (key_essentials.flags & MDBX_DUPSORT) { - key_serial >>= mapping.split; - value_serial += serial & mask(mapping.split); - } else { - /* Без MDBX_DUPSORT требуетÑÑ ÑƒÐ½Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾Ñть ключей, а Ð´Ð»Ñ Ñтого Ð½ÐµÐ»ÑŒÐ·Ñ - * отбраÑывать какие-либо биты serial поÑле инъективного преобразованиÑ. - * ПоÑтому key_serial не трогаем, а в value_serial нелинейно вмешиваем - * запрошенное количеÑтво бит из serial */ - value_serial += - (serial ^ (serial >> mapping.split)) & mask(mapping.split); - } - - value_serial |= value_age << mapping.split; - log_trace("keygen-pair: split@%u => k%" PRIu64 ", v%" PRIu64, mapping.split, - key_serial, value_serial); - } - - log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial, - value_serial); - mk(key_serial, key_essentials, *key); - mk(value_serial, value_essentials, *value); - - if (log_enabled(logging::trace)) { - char dump_key[128], dump_value[128]; - log_trace("keygen-pair: key %s, value %s", - mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)), - mdbx_dump_val(&value->value, dump_value, sizeof(dump_value))); - } -} - -void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, - unsigned thread_number) { - key_essentials.flags = - actor.table_flags & (MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT); - assert(actor.keylen_min <= UINT8_MAX); - key_essentials.minlen = (uint8_t)actor.keylen_min; - assert(actor.keylen_max <= UINT16_MAX); - key_essentials.maxlen = (uint16_t)actor.keylen_max; - - value_essentials.flags = - actor.table_flags & (MDBX_INTEGERDUP | MDBX_REVERSEDUP); - assert(actor.datalen_min <= UINT8_MAX); - value_essentials.minlen = (uint8_t)actor.datalen_min; - assert(actor.datalen_max <= UINT16_MAX); - value_essentials.maxlen = (uint16_t)actor.datalen_max; - - assert(thread_number < 2); - (void)thread_number; - mapping = actor.keygen; - salt = (actor.keygen.seed + actor_id) * UINT64_C(14653293970879851569); - - // FIXME: TODO - base = 0; -} - -void maker::make_ordered() { - mapping.mesh = 0; - mapping.rotate = 0; -} - -bool maker::is_unordered() const { - return (mapping.mesh >= serial_minwith || mapping.rotate) != 0; -} - -bool maker::increment(serial_t &serial, int delta) const { - if (serial > mask(mapping.width)) { - log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial, - mask(mapping.width)); - return false; - } - - serial_t target = serial + (int64_t)delta; - if (target > mask(mapping.width) || - ((delta > 0) ? target < serial : target > serial)) { - log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow", - serial, delta, target); - return false; - } - - log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", continue", serial, - delta, target); - serial = target; - return true; -} - -//----------------------------------------------------------------------------- - -static size_t length(serial_t serial) { - size_t n = 0; - if (serial > UINT32_MAX) { - n = 4; - serial >>= 32; - } - if (serial > UINT16_MAX) { - n += 2; - serial >>= 16; - } - if (serial > UINT8_MAX) { - n += 1; - serial >>= 8; - } - return (serial > 0) ? n + 1 : n; -} - -buffer alloc(size_t limit) { - result *ptr = (result *)malloc(sizeof(result) + limit); - if (unlikely(ptr == nullptr)) - failure_perror("malloc(keyvalue_buffer)", errno); - ptr->value.iov_base = ptr->bytes; - ptr->value.iov_len = 0; - ptr->limit = limit; - return buffer(ptr); -} - -void __hot maker::mk(const serial_t serial, const essentials ¶ms, - result &out) { - assert(out.limit >= params.maxlen); - assert(params.maxlen >= params.minlen); - assert(params.maxlen >= length(serial)); - - out.value.iov_base = out.bytes; - out.value.iov_len = - (params.maxlen > params.minlen) - ? params.minlen + serial % (params.maxlen - params.minlen) - : params.minlen; - - if (params.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) { - assert(params.maxlen == params.minlen); - assert(params.minlen == 4 || params.minlen == 8); - if (is_byteorder_le() || params.minlen == 8) - out.u64 = serial; - else - out.u32 = (uint32_t)serial; - } else if (params.flags & (MDBX_REVERSEKEY | MDBX_REVERSEDUP)) { - if (out.value.iov_len > 8) { - memset(out.bytes, '\0', out.value.iov_len - 8); - unaligned::store(out.bytes + out.value.iov_len - 8, htobe64(serial)); - } else { - out.u64 = htobe64(serial); - if (out.value.iov_len < 8) { - out.value.iov_len = std::max(length(serial), out.value.iov_len); - out.value.iov_base = out.bytes + 8 - out.value.iov_len; - } - } - } else { - out.u64 = htole64(serial); - if (out.value.iov_len > 8) - memset(out.bytes + 8, '\0', out.value.iov_len - 8); - else - out.value.iov_len = std::max(length(serial), out.value.iov_len); - } - - assert(out.value.iov_len >= params.minlen); - assert(out.value.iov_len <= params.maxlen); - assert(out.value.iov_len >= length(serial)); - assert(out.value.iov_base >= out.bytes); - assert((uint8_t *)out.value.iov_base + out.value.iov_len <= - out.bytes + out.limit); -} - -} /* namespace keygen */ diff --git a/src/contrib/db/libmdbx/test/keygen.h b/src/contrib/db/libmdbx/test/keygen.h deleted file mode 100644 index 0403ab8..0000000 --- a/src/contrib/db/libmdbx/test/keygen.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" -#include "config.h" -#include "log.h" -#include "utils.h" - -namespace keygen { - -/* Под "генерацией ключей" здеÑÑŒ понимаетÑÑ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¾Ð±Ð¾Ð¸Ñ… значений Ð´Ð»Ñ - * пар key-value, Ñ‚.е. не только ключей, но и аÑÑоциированных Ñ Ð½Ð¸Ð¼Ð¸ данных. - */ - -/* Генерацию ключей Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð½ÐµÑти к проÑтым задачам, так как Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ - * примерно Ñледующие: - * - Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ€Ð°Ð·Ð½Ð¾Ð³Ð¾ количеÑтва уникальных ключей различной длины - * в задаваемом диапазоне; - * - возможноÑть выбора как пÑевдо-Ñлучайного порÑдка ключей, - * так и по некоторым ÑпецифичеÑким законам (ограниченными упорÑдоченными - * поÑледовательноÑÑ‚Ñми, в шахматном порÑдке по граница диапазона и Ñ‚.д.); - * - возможноÑть генерации дубликатов Ñ Ð·Ð°Ð´Ð°Ð²Ð°ÐµÐ¼Ñ‹Ð¼ законом раÑпределениÑ; - * - возможноÑть генерации непереÑекающимиÑÑ ÐºÐ»Ð°Ñтерами Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð»Ð»ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ - * иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² неÑкольких потоках; - * - иÑпользовать минимум реÑурÑов, как CPU, так и RAM, в том чиÑле - * Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ cache pollution и ram bandwidth. - * - * При Ñтом заведомо извеÑтно, что Ð´Ð»Ñ MDBX не имеет значениÑ: - * - иÑпользуемый алфавит (Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð²); - * - чаÑтотное раÑпределение по алфавиту; - * - абÑолютное значение ключей или разноÑть между отдельными значениÑми; - * - * СоответÑтвенно, в общих чертах, Ñхема генерации ÑледующаÑ: - * - вводитÑÑ Ð¿Ð»Ð¾ÑÐºÐ°Ñ Ð¾Ð´Ð½Ð¾Ð¼ÐµÑ€Ð½Ð°Ñ "координата" serial (uint64_t); - * - Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ ÑпецифичеÑких паттернов (поÑледовательноÑтей) - * реализуетÑÑ Ð¿Ð¾ÑредÑтвом ÑоответÑтвующих преобразований "координат", при - * Ñтом вÑе подобные Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÑÑŽÑ‚ÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ над "координатой"; - * - Ð¸Ñ‚Ð¾Ð³Ð¾Ð²Ð°Ñ "координата" преобразуетÑÑ Ð² 8-байтное Ñуррогатное значение - * ключа; - * - Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÐºÐ»ÑŽÑ‡ÐµÐ¹ длиной МЕÐЕЕ 8 байт Ñуррогат может уÑекатьÑÑ - * до ненулевых байт, в том чиÑле до нулевой длины; - * - Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÐºÐ»ÑŽÑ‡ÐµÐ¹ длиной БОЛЕЕ 8 байт Ñуррогат дополнÑетÑÑ - * нулÑми или пÑевдоÑлучайной поÑледовательноÑтью; - * - * Механизм генерации паттернов: - * - реализованный механизм ÑвлÑетÑÑ ÐºÐ¾Ð¼Ð¿Ñ€Ð¾Ð¼Ð¸ÑÑом между ÑкороÑтью/проÑтотой - * и гибкоÑтью, необходимой Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ÑледовательноÑтей, которых - * будет доÑтаточно Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ Ñценариев Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸ ÑлиÑÐ½Ð¸Ñ Ñтраниц - * Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ внутри mdbx; - * - пÑевдо-Ñлучайные паттерны реализуютÑÑ Ð¿Ð¾ÑредÑтвом набора инъективных - * отображающих функций; - * - не-пÑевдо-Ñлучайные паттерны реализуютÑÑ Ð¿Ð¾ÑредÑтвом параметризируемого - * трех-Ñтапного преобразованиÑ: - * 1) Ñмещение (Ñложение) по модулю; - * 2) цикличеÑкий Ñдвиг; - * 3) добавление абÑолютного ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ (базы); - */ - -typedef uint64_t serial_t; - -enum : serial_t { - serial_minwith = 8, - serial_maxwith = sizeof(serial_t) * 8, - serial_allones = ~(serial_t)0u -}; - -struct result { - MDBX_val value; - size_t limit; - union { - uint8_t bytes[sizeof(uint64_t)]; - uint32_t u32; - uint64_t u64; - }; - - std::string as_string() const { - return std::string((const char *)value.iov_base, value.iov_len); - } -}; - -//----------------------------------------------------------------------------- - -struct buffer_deleter /* : public std::unary_function */ { - void operator()(result *buffer) const { free(buffer); } -}; - -typedef std::unique_ptr buffer; - -buffer alloc(size_t limit); - -class maker { - config::keygen_params_pod mapping; - serial_t base; - serial_t salt; - - struct essentials { - uint8_t minlen; - uint8_t flags; - uint16_t maxlen; - } key_essentials, value_essentials; - - static void mk(const serial_t serial, const essentials ¶ms, result &out); - -public: - maker() { memset(this, 0, sizeof(*this)); } - - void pair(serial_t serial, const buffer &key, buffer &value, - serial_t value_age); - void setup(const config::actor_params_pod &actor, unsigned actor_id, - unsigned thread_number); - void make_ordered(); - bool is_unordered() const; - - bool increment(serial_t &serial, int delta) const; -}; - -} /* namespace keygen */ diff --git a/src/contrib/db/libmdbx/test/log.cc b/src/contrib/db/libmdbx/test/log.cc deleted file mode 100644 index 57139ea..0000000 --- a/src/contrib/db/libmdbx/test/log.cc +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -static void fflushall() { fflush(nullptr); } - -void failure(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - fflushall(); - logging::output_nocheckloglevel_ap(logging::failure, fmt, ap); - va_end(ap); - fflushall(); - exit(EXIT_FAILURE); -} - -const char *test_strerror(int errnum) { - static __thread char buf[1024]; - return mdbx_strerror_r(errnum, buf, sizeof(buf)); -} - -void __noreturn failure_perror(const char *what, int errnum) { - failure("%s failed: %s (%d)\n", what, test_strerror(errnum), errnum); -} - -//----------------------------------------------------------------------------- - -static void mdbx_logger(int priority, const char *function, int line, - const char *msg, va_list args) { - if (!function) - function = "unknown"; - - if (priority == MDBX_LOG_FATAL) - log_error("mdbx: fatal failure: %s, %d", function, line); - - logging::output_nocheckloglevel( - logging::loglevel(priority), - strncmp(function, "mdbx_", 5) == 0 ? "%s: " : "mdbx %s: ", function); - logging::feed_ap(msg, args); -} - -namespace logging { - -static std::string prefix; -static std::string suffix; -static loglevel level; -static FILE *last; - -void setlevel(loglevel priority) { - level = priority; - int rc = mdbx_setup_debug(priority, - MDBX_DBG_ASSERT | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | - MDBX_DBG_DUMP, - mdbx_logger); - log_trace("set mdbx debug-opts: 0x%02x", rc); -} - -void setup(loglevel priority, const std::string &_prefix) { - setlevel(priority); - prefix = _prefix; -} - -void setup(const std::string &_prefix) { prefix = _prefix; } - -const char *level2str(const loglevel alevel) { - switch (alevel) { - default: - return "invalid/unknown"; - case extra: - return "extra"; - case trace: - return "trace"; - case debug: - return "debug"; - case verbose: - return "verbose"; - case notice: - return "notice"; - case warning: - return "warning"; - case error: - return "error"; - case failure: - return "failure"; - } -} - -bool output(const loglevel priority, const char *format, ...) { - if (lower(priority, level)) - return false; - - va_list ap; - va_start(ap, format); - output_nocheckloglevel_ap(priority, format, ap); - va_end(ap); - return true; -} - -void output_nocheckloglevel_ap(const logging::loglevel priority, - const char *format, va_list ap) { - if (last) { - putc('\n', last); - fflush(last); - if (last == stderr) { - putc('\n', stdout); - fflush(stdout); - } - last = nullptr; - } - - chrono::time now = chrono::now_realtime(); - struct tm tm; -#ifdef _MSC_VER - int rc = _localtime32_s(&tm, (const __time32_t *)&now.utc); -#else - time_t time = now.utc; - int rc = localtime_r(&time, &tm) ? MDBX_SUCCESS : errno; -#endif - if (rc != MDBX_SUCCESS) - failure_perror("localtime_r()", rc); - - last = stdout; - fprintf(last, - "[ %02d%02d%02d-%02d:%02d:%02d.%06d_%05u %-10s %.4s ] %s" /* TODO */, - tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, - tm.tm_sec, chrono::fractional2us(now.fractional), osal_getpid(), - prefix.c_str(), level2str(priority), suffix.c_str()); - - va_list ones; - memset(&ones, 0, sizeof(ones)) /* zap MSVC and other stupid compilers */; - if (same_or_higher(priority, error)) - va_copy(ones, ap); - vfprintf(last, format, ap); - - size_t len = strlen(format); - char end = len ? format[len - 1] : '\0'; - - switch (end) { - default: - putc('\n', last); - // fall through - case '\n': - fflush(last); - last = nullptr; - // fall through - case ' ': - case '_': - case ':': - case '|': - case ',': - case '\t': - case '\b': - case '\r': - case '\0': - break; - } - - if (same_or_higher(priority, error)) { - if (last != stderr) { - fprintf(stderr, "[ %05u %-10s %.4s ] %s", osal_getpid(), prefix.c_str(), - level2str(priority), suffix.c_str()); - vfprintf(stderr, format, ones); - if (end == '\n') - fflush(stderr); - else - last = stderr; - } - va_end(ones); - } -} - -bool feed_ap(const char *format, va_list ap) { - if (!last) - return false; - - if (last == stderr) { - va_list ones; - va_copy(ones, ap); - vfprintf(stdout, format, ones); - va_end(ones); - } - vfprintf(last, format, ap); - size_t len = strlen(format); - if (len && format[len - 1] == '\n') { - fflush(last); - if (last == stderr) - fflush(stdout); - last = nullptr; - } - return true; -} - -bool feed(const char *format, ...) { - if (!last) - return false; - - va_list ap; - va_start(ap, format); - feed_ap(format, ap); - va_end(ap); - return true; -} - -local_suffix::local_suffix(const char *c_str) - : trim_pos(suffix.size()), indent(0) { - suffix.append(c_str); -} - -local_suffix::local_suffix(const std::string &str) - : trim_pos(suffix.size()), indent(0) { - suffix.append(str); -} - -void local_suffix::push() { - indent += 1; - suffix.push_back('\t'); -} - -void local_suffix::pop() { - assert(indent > 0); - if (indent > 0) { - indent -= 1; - suffix.pop_back(); - } -} - -local_suffix::~local_suffix() { suffix.erase(trim_pos); } - -void progress_canary(bool active) { - static chrono::time progress_timestamp; - chrono::time now = chrono::now_motonic(); - - if (now.fixedpoint - progress_timestamp.fixedpoint < - chrono::from_ms(42).fixedpoint) - return; - - if (osal_progress_push(active)) { - progress_timestamp = now; - return; - } - - if (progress_timestamp.fixedpoint == 0) { - putc('>', stderr); - progress_timestamp = now; - } else if (global::config::console_mode) { - if (active) { - static int last_point = -1; - int point = (now.fixedpoint >> 29) & 3; - if (point != last_point) { - progress_timestamp = now; - fprintf(stderr, "%c\b", "-\\|/"[last_point = point]); - } - } else if (now.fixedpoint - progress_timestamp.fixedpoint > - chrono::from_seconds(2).fixedpoint) { - progress_timestamp = now; - fprintf(stderr, "%c\b", "@*"[now.utc & 1]); - } - } else { - static int count; - if (active && now.fixedpoint - progress_timestamp.fixedpoint > - chrono::from_seconds(1).fixedpoint) { - putc('.', stderr); - progress_timestamp = now; - ++count; - } else if (now.fixedpoint - progress_timestamp.fixedpoint > - chrono::from_seconds(5).fixedpoint) { - putc("@*"[now.utc & 1], stderr); - progress_timestamp = now; - ++count; - } - if (count == 60) { - count = 0; - putc('\n', stderr); - } - } - fflush(stderr); -} - -} // namespace logging - -void log_extra(const char *msg, ...) { - if (logging::same_or_higher(logging::extra, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::extra, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_trace(const char *msg, ...) { - if (logging::same_or_higher(logging::trace, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::trace, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_debug(const char *msg, ...) { - if (logging::same_or_higher(logging::debug, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::debug, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_verbose(const char *msg, ...) { - if (logging::same_or_higher(logging::verbose, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::verbose, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_notice(const char *msg, ...) { - if (logging::same_or_higher(logging::notice, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::notice, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_warning(const char *msg, ...) { - if (logging::same_or_higher(logging::warning, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::warning, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_error(const char *msg, ...) { - if (logging::same_or_higher(logging::error, logging::level)) { - va_list ap; - va_start(ap, msg); - logging::output_nocheckloglevel_ap(logging::error, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_trouble(const char *where, const char *what, int errnum) { - log_error("%s: %s %s", where, what, test_strerror(errnum)); -} - -bool log_enabled(const logging::loglevel priority) { - return logging::same_or_higher(priority, logging::level); -} - -void log_flush(void) { fflushall(); } diff --git a/src/contrib/db/libmdbx/test/log.h b/src/contrib/db/libmdbx/test/log.h deleted file mode 100644 index bb8f997..0000000 --- a/src/contrib/db/libmdbx/test/log.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" -#include "chrono.h" - -void __noreturn usage(void); -void __noreturn __printf_args(1, 2) failure(const char *fmt, ...); -void __noreturn failure_perror(const char *what, int errnum); -const char *test_strerror(int errnum); - -namespace logging { - -enum loglevel { - extra = MDBX_LOG_EXTRA, - trace = MDBX_LOG_TRACE, - debug = MDBX_LOG_DEBUG, - verbose = MDBX_LOG_VERBOSE, - notice = MDBX_LOG_NOTICE, - warning = MDBX_LOG_WARN, - error = MDBX_LOG_ERROR, - failure = MDBX_LOG_FATAL -}; - -inline bool lower(loglevel left, loglevel right) { - static_assert(MDBX_LOG_EXTRA > MDBX_LOG_FATAL, "WTF?"); - return left > right; -} - -inline bool same_or_higher(loglevel left, loglevel right) { - return left <= right; -} - -const char *level2str(const loglevel level); -void setup(loglevel priority, const std::string &prefix); -void setup(const std::string &prefix); -void setlevel(loglevel priority); - -void output_nocheckloglevel_ap(const loglevel priority, const char *format, - va_list ap); -bool __printf_args(2, 3) - output(const loglevel priority, const char *format, ...); -bool feed_ap(const char *format, va_list ap); -bool __printf_args(1, 2) feed(const char *format, ...); - -void inline __printf_args(2, 3) - output_nocheckloglevel(const loglevel priority, const char *format, ...) { - va_list ap; - va_start(ap, format); - output_nocheckloglevel_ap(priority, format, ap); - va_end(ap); -} - -void progress_canary(bool active); - -class local_suffix { -protected: - size_t trim_pos; - int indent; - -public: - local_suffix(const local_suffix &) = delete; - local_suffix(const local_suffix &&) = delete; - const local_suffix &operator=(const local_suffix &) = delete; - - local_suffix(const char *c_str); - local_suffix(const std::string &str); - void push(); - void pop(); - ~local_suffix(); -}; - -} // namespace logging - -void __printf_args(1, 2) log_extra(const char *msg, ...); -void __printf_args(1, 2) log_trace(const char *msg, ...); -void __printf_args(1, 2) log_debug(const char *msg, ...); -void __printf_args(1, 2) log_verbose(const char *msg, ...); -void __printf_args(1, 2) log_notice(const char *msg, ...); -void __printf_args(1, 2) log_warning(const char *msg, ...); -void __printf_args(1, 2) log_error(const char *msg, ...); - -void log_trouble(const char *where, const char *what, int errnum); -void log_flush(void); -bool log_enabled(const logging::loglevel priority); - -#ifdef _DEBUG -#define TRACE(...) log_trace(__VA_ARGS__) -#else -#define TRACE(...) __noop(__VA_ARGS__) -#endif diff --git a/src/contrib/db/libmdbx/test/long_stochastic.sh b/src/contrib/db/libmdbx/test/long_stochastic.sh deleted file mode 100644 index 7b9f90f..0000000 --- a/src/contrib/db/libmdbx/test/long_stochastic.sh +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/env bash -if ! which make cc c++ tee lz4 >/dev/null; then - echo "Please install the following prerequisites: make cc c++ tee lz4" >&2 - exit 1 -fi - -set -euo pipefail - -UNAME="$(uname -s 2>/dev/null || echo Unknown)" - -## NOTE: Valgrind could produce some false-positive warnings -## in multi-process environment with shared memory. -## For instance, when the process "A" explicitly marks a memory -## region as "undefined", the process "B" fill it, -## and after this process "A" read such region, etc. -#VALGRIND="valgrind --trace-children=yes --log-file=valgrind-%p.log --leak-check=full --track-origins=yes --error-exitcode=42 --suppressions=test/valgrind_suppress.txt" - -############################################################################### -# 1. clean data from prev runs and examine available RAM - -if [[ -v VALGRIND && ! -z "$VALGRIND" ]]; then - rm -f valgrind-*.log -else - VALGRIND=time -fi - -WANNA_MOUNT=0 -case ${UNAME} in - Linux) - MAKE=make - if [[ ! -v TESTDB_DIR || -z "$TESTDB_DIR" ]]; then - for old_test_dir in $(ls -d /dev/shm/mdbx-test.[0-9]*); do - rm -rf $old_test_dir - done - TESTDB_DIR="/dev/shm/mdbx-test.$$" - fi - mkdir -p $TESTDB_DIR && rm -f $TESTDB_DIR/* - - if LC_ALL=C free | grep -q -i available; then - ram_avail_mb=$(($(LC_ALL=C free | grep -i Mem: | tr -s [:blank:] ' ' | cut -d ' ' -f 7) / 1024)) - else - ram_avail_mb=$(($(LC_ALL=C free | grep -i Mem: | tr -s [:blank:] ' ' | cut -d ' ' -f 4) / 1024)) - fi - ;; - - FreeBSD) - MAKE=gmake - if [[ ! -v TESTDB_DIR || -z "$TESTDB_DIR" ]]; then - for old_test_dir in $(ls -d /tmp/mdbx-test.[0-9]*); do - umount $old_test_dir && rm -r $old_test_dir - done - TESTDB_DIR="/tmp/mdbx-test.$$" - rm -rf $TESTDB_DIR && mkdir -p $TESTDB_DIR - WANNA_MOUNT=1 - else - mkdir -p $TESTDB_DIR && rm -f $TESTDB_DIR/* - fi - - ram_avail_mb=$(($(LC_ALL=C vmstat -s | grep -ie '[0-9] pages free$' | cut -d p -f 1) * ($(LC_ALL=C vmstat -s | grep -ie '[0-9] bytes per page$' | cut -d b -f 1) / 1024) / 1024)) - ;; - - Darwin) - MAKE=make - if [[ ! -v TESTDB_DIR || -z "$TESTDB_DIR" ]]; then - for vol in $(ls -d /Volumes/mdx[0-9]*[0-9]tst); do - disk=$(mount | grep $vol | cut -d ' ' -f 1) - echo "umount: volume $vol disk $disk" - hdiutil unmount $vol -force - hdiutil detach $disk - done - TESTDB_DIR="/Volumes/mdx$$tst" - WANNA_MOUNT=1 - else - mkdir -p $TESTDB_DIR && rm -f $TESTDB_DIR/* - fi - - pagesize=$(($(LC_ALL=C vm_stat | grep -o 'page size of [0-9]\+ bytes' | cut -d' ' -f 4) / 1024)) - freepages=$(LC_ALL=C vm_stat | grep '^Pages free:' | grep -o '[0-9]\+\.$' | cut -d'.' -f 1) - ram_avail_mb=$((pagesize * freepages / 1024)) - echo "pagesize ${pagesize}K, freepages ${freepages}, ram_avail_mb ${ram_avail_mb}" - - ;; - - *) - echo "FIXME: ${UNAME} not supported by this script" - exit 2 - ;; -esac - -############################################################################### -# 2. estimate reasonable RAM space for test-db - -echo "=== ${ram_avail_mb}M RAM available" -ram_reserve4logs_mb=1234 -if [ $ram_avail_mb -lt $ram_reserve4logs_mb ]; then - echo "=== At least ${ram_reserve4logs_mb}Mb RAM required" - exit 3 -fi - -# -# Ð’ режимах отличных от MDBX_WRITEMAP Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð¾ запиÑи в файл -# будут накапливатьÑÑ Ð² памÑти, что может потребовать Ñвободной -# памÑти размером Ñ Ð‘Ð”. Кроме Ñтого, в теÑÑ‚ входит Ñценарий -# ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð‘Ð” на ходу. ПоÑтому БД не может быть больше 1/3 -# от доÑтупной памÑти. Однако, Ñледует учеÑть что malloc() будет -# не Ñразу возвращать выделенную памÑть ÑиÑтеме, а также -# предуÑмотреть меÑта Ð´Ð»Ñ Ð»Ð¾Ð³Ð¾Ð². -# -# In non-MDBX_WRITEMAP modes, updates (dirty pages) will -# accumulate in memory before writing to the disk, which may -# require a free memory up to the size of a whole database. In -# addition, the test includes a script create a copy of the -# database on the go. Therefore, the database cannot be more 1/3 -# of available memory. Moreover, should be taken into account -# that malloc() will not return the allocated memory to the -# system immediately, as well some space is required for logs. -# -db_size_mb=$(((ram_avail_mb - ram_reserve4logs_mb) / 4)) -if [ $db_size_mb -gt 3072 ]; then - db_size_mb=3072 -fi -echo "=== use ${db_size_mb}M for DB" - -############################################################################### -# 3. Create test-directory in ramfs/tmpfs, i.e. create/format/mount if required -case ${UNAME} in - Linux) - ;; - - FreeBSD) - if [[ WANNA_MOUNT ]]; then - mount -t tmpfs tmpfs $TESTDB_DIR - fi - ;; - - Darwin) - if [[ WANNA_MOUNT ]]; then - ramdisk_size_mb=$((42 + db_size_mb * 2 + ram_reserve4logs_mb)) - number_of_sectors=$((ramdisk_size_mb * 2048)) - ramdev=$(hdiutil attach -nomount ram://${number_of_sectors}) - diskutil erasevolume ExFAT "mdx$$tst" ${ramdev} - fi - ;; - - *) - echo "FIXME: ${UNAME} not supported by this script" - exit 2 - ;; -esac - -############################################################################### -# 4. Run basic test, i.e. `make check` - -${MAKE} TEST_DB=${TESTDB_DIR}/smoke.db TEST_LOG=${TESTDB_DIR}/smoke.log check -rm -f ${TESTDB_DIR}/* - -############################################################################### -# 5. run stochastic iterations - -function rep9 { printf "%*s" $1 '' | tr ' ' '9'; } -function join { local IFS="$1"; shift; echo "$*"; } -function bit2option { local -n arr=$1; (( ($2&(1<<$3)) != 0 )) && echo -n '+' || echo -n '-'; echo "${arr[$3]}"; } - -options=(writemap coalesce lifo) - -function bits2list { - local -n arr=$1 - local i - local list=() - for ((i=0; i<${#arr[@]}; ++i)) do - list[$i]=$(bit2option $1 $2 $i) - done - join , "${list[@]}" -} - -function probe { - echo "=============================================== $(date)" - echo "${caption}: $*" - rm -f ${TESTDB_DIR}/* \ - && ${VALGRIND} ./mdbx_test --ignore-dbfull --repeat=42 --pathname=${TESTDB_DIR}/long.db "$@" | lz4 > ${TESTDB_DIR}/long.log.lz4 \ - && ${VALGRIND} ./mdbx_chk -nvvv ${TESTDB_DIR}/long.db | tee ${TESTDB_DIR}/long-chk.log \ - && ([ ! -e ${TESTDB_DIR}/long.db-copy ] || ${VALGRIND} ./mdbx_chk -nvvv ${TESTDB_DIR}/long.db-copy | tee ${TESTDB_DIR}/long-chk-copy.log) \ - || (echo "FAILED"; exit 1) -} - -#------------------------------------------------------------------------------ - -count=0 -for nops in $(seq 2 6); do - for ((wbatch=nops-1; wbatch > 0; --wbatch)); do - loops=$(((111 >> nops) / nops + 3)) - for ((rep=0; rep++ < loops; )); do - for ((bits=2**${#options[@]}; --bits >= 0; )); do - seed=$(($(date +%s) + RANDOM)) - caption="Probe #$((++count)) int-key,w/o-dups, repeat ${rep} of ${loops}" probe \ - --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,-data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=1111 \ - --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ - --keygen.seed=${seed} basic - caption="Probe #$((++count)) int-key,with-dups, repeat ${rep} of ${loops}" probe \ - --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,+data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ - --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ - --keygen.seed=${seed} basic - caption="Probe #$((++count)) int-key,int-data, repeat ${rep} of ${loops}" probe \ - --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,+data.integer --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ - --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ - --keygen.seed=${seed} basic - caption="Probe #$((++count)) w/o-dups, repeat ${rep} of ${loops}" probe \ - --pagesize=min --size-upper=${db_size_mb}M --table=-data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=1111 \ - --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ - --keygen.seed=${seed} basic - caption="Probe #$((++count)) with-dups, repeat ${rep} of ${loops}" probe \ - --pagesize=min --size-upper=${db_size_mb}M --table=+data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ - --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ - --keygen.seed=${seed} basic - done - done - done -done - -echo "=== ALL DONE ====================== $(date)" diff --git a/src/contrib/db/libmdbx/test/main.cc b/src/contrib/db/libmdbx/test/main.cc deleted file mode 100644 index fe5243e..0000000 --- a/src/contrib/db/libmdbx/test/main.cc +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -#if !(defined(_WIN32) || defined(_WIN64)) -#include -#include -#endif /* !Windows */ - -void __noreturn usage(void) { - puts( - "usage:\n" - " --help or -h Show this text\n" - "Common parameters:\n" - " --pathname=... Path and/or name of database files\n" - " --repeat=N Set repeat counter\n" - " --threads=N Number of thread (unsunpported for now)\n" - " --timeout=N[s|m|h|d] Set timeout in seconds/minutes/hours/days\n" - " --failfast[=YES/no] Lill all actors on first failure/error\n" - " --max-readers=N See mdbx_env_set_maxreaders() description\n" - " --max-tables=N Se mdbx_env_set_maxdbs() description\n" - " --dump-config[=YES/no] Dump entire test config before run\n" - " --progress[=YES/no] Enable/disable progress `canary`\n" - " --console[=yes/no] Enable/disable console-like output\n" - " --cleanup-before[=YES/no] Cleanup/remove and re-create database\n" - " --cleanup-after[=YES/no] Cleanup/remove database after completion\n" - "Database size control:\n" - " --pagesize=... Database page size: min, max, 256..65536\n" - " --size-lower=N[K|M|G|T] Lower-bound of size in Kb/Mb/Gb/Tb\n" - " --size-upper Upper-bound of size in Kb/Mb/Gb/Tb\n" - " --size Initial size in Kb/Mb/Gb/Tb\n" - " --shrink-threshold Shrink threshold in Kb/Mb/Gb/Tb\n" - " --growth-step Grow step in Kb/Mb/Gb/Tb\n" - "Predefined complext scenarios/cases:\n" - " --case=... Only `basic` scenario implemented for now\n" - " basic == Simultaneous multi-process execution\n" - " of test-actors: nested,hill,ttl,copy,append,jitter,try\n" - "Test actors:\n" - " --hill Fill-up and empty-down\n" - " by CRUD-operation quads\n" - " --ttl Stochastic time-to-live simulation\n" - " --nested Nested transactionÑ‹\n" - " with stochastic-size bellows\n" - " --jitter Jitter/delays simulation\n" - " --try Try write-transaction, no more\n" - " --copy Online copy/backup\n" - " --append Append-mode insertions\n" - " --dead.reader Dead-reader simulator\n" - " --dead.writer Dead-writer simulator\n" - "Actor options:\n" - " --batch.read=N Read-operations batch size\n" - " --batch.write=N Write-operations batch size\n" - " --delay=N | --no-delay (no)Delay test-actor before start\n" - " --wait4ops=N | --no-wait4ops (no)Wait for previous test-actor\n" - " completes # ops before start\n" - " --duration=N[s|m|h|d] Define running duration\n" - " --nops=N[K|M|G|T] Define number of operations/steps\n" - " --inject-writefault[=yes|NO] TBD (see the source code)\n" - " --drop[=yes|NO] Drop key-value space/table on " - "completion\n" - " --ignore-dbfull[=yes|NO] Ignore MDBX_MAP_FULL error\n" - " --speculum[=yes|NO] Use internal `speculum` to check " - "dataset\n" - "Keys and Value:\n" - " --keygen.min=N Minimal keys length\n" - " --keygen.max=N Miximal keys length\n" - " --datalen.min=N Minimal data length\n" - " --datalen.max=N Miximal data length\n" - " --keygen.width=N TBD (see the source code)\n" - " --keygen.mesh=N TBD (see the source code)\n" - " --keygen.seed=N TBD (see the source code)\n" - " --keygen.split=N TBD (see the source code)\n" - " --keygen.rotate=N TBD (see the source code)\n" - " --keygen.offset=N TBD (see the source code)\n" - " --keygen.case=random Generator case (only `random` for now)\n" - "Database operation mode:\n" - " --mode={[+-]FLAG}[,[+-]FLAG]...\n" - " nosubdir == MDBX_NOSUBDIR\n" - " rdonly == MDBX_RDONLY\n" - " nometasync == MDBX_NOMETASYNC\n" - " lifo == MDBX_LIFORECLAIM\n" - " coalesce == MDBX_COALESCE\n" - " nosync == MDBX_NOSYNC\n" - " writemap == MDBX_WRITEMAP\n" - " mapasync == MDBX_MAPASYNC\n" - " utterly == MDBX_UTTERLY_NOSYNC\n" - " perturb == MDBX_PAGEPERTURB\n" - " notls == MDBX_NOTLS\n" - " nordahead == MDBX_NORDAHEAD\n" - " nomeminit == MDBX_NOMEMINIT\n" - "Key-value space/table options:\n" - " --table={[+-]FLAG}[,[+-]FLAG]...\n" - " key.reverse == MDBX_REVERSEKEY\n" - " key.integer == MDBX_INTEGERKEY\n" - " data.dups == MDBX_DUPSORT\n" - " data.integer == MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT\n" - " data.fixed == MDBX_DUPFIXED | MDBX_DUPSORT\n" - " data.reverse == MDBX_REVERSEDUP | MDBX_DUPSORT\n"); - exit(EXIT_FAILURE); -} - -//----------------------------------------------------------------------------- - -void actor_params::set_defaults(const std::string &tmpdir) { - pathname_log = ""; - loglevel = -#if defined(NDEBUG) || defined(_WIN32) || defined(_WIN64) - logging::verbose; -#else - logging::trace; -#endif - - pathname_db = tmpdir + "mdbx-test.db"; - mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOMEMINIT | - MDBX_COALESCE | MDBX_LIFORECLAIM; - table_flags = MDBX_DUPSORT; - - size_lower = -1; - size_now = - intptr_t(1024) * 1024 * ((table_flags & MDBX_DUPSORT) ? 256 : 1024); - size_upper = -1; - shrink_threshold = -1; - growth_step = -1; - pagesize = -1; - - keygen.seed = 1; - keygen.keycase = kc_random; - keygen.width = (table_flags & MDBX_DUPSORT) ? 32 : 64; - keygen.mesh = keygen.width; - keygen.split = keygen.width / 2; - keygen.rotate = 3; - keygen.offset = 41; - - test_duration = 0; - test_nops = 1000; - nrepeat = 1; - nthreads = 1; - - keylen_min = mdbx_keylen_min(); - keylen_max = mdbx_keylen_max(); - datalen_min = mdbx_datalen_min(); - datalen_max = std::min(mdbx_datalen_max(), 256u * 1024 + 42); - - batch_read = 42; - batch_write = 42; - - delaystart = 0; - waitfor_nops = 0; - inject_writefaultn = 0; - - drop_table = false; - ignore_dbfull = false; - speculum = false; - - max_readers = 42; - max_tables = 42; - - global::config::timeout_duration_seconds = 0 /* infinite */; - global::config::dump_config = true; - global::config::cleanup_before = true; - global::config::cleanup_after = true; - global::config::failfast = true; - global::config::progress_indicator = true; - global::config::console_mode = osal_istty(STDERR_FILENO); -} - -namespace global { - -std::vector actors; -std::unordered_map events; -std::unordered_map pid2actor; -std::set databases; -unsigned nactors; -chrono::time start_motonic; -chrono::time deadline_motonic; -bool singlemode; - -namespace config { -unsigned timeout_duration_seconds; -bool dump_config; -bool cleanup_before; -bool cleanup_after; -bool failfast; -bool progress_indicator; -bool console_mode; -} /* namespace config */ - -} /* namespace global */ - -//----------------------------------------------------------------------------- - -const char global::thunk_param_prefix[] = "--execute="; - -std::string thunk_param(const actor_config &config) { - return config.serialize(global::thunk_param_prefix); -} - -void cleanup() { - log_trace(">> cleanup"); - /* TODO: remove each database */ - log_trace("<< cleanup"); -} - -int main(int argc, char *const argv[]) { - -#ifdef _DEBUG - log_trace("#argc = %d", argc); - for (int i = 0; i < argc; ++i) - log_trace("#argv[%d] = %s", i, argv[i]); -#endif /* _DEBUG */ - - if (argc < 2) - failure("No parameters given. Try --help\n"); - - if (argc == 2 && strncmp(argv[1], global::thunk_param_prefix, - strlen(global::thunk_param_prefix)) == 0) - return test_execute( - actor_config(argv[1] + strlen(global::thunk_param_prefix))) - ? EXIT_SUCCESS - : EXIT_FAILURE; - - if (argc == 2 && - (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) - usage(); - - actor_params params; - params.set_defaults(osal_tempdir()); - global::config::dump_config = true; - logging::setup((logging::loglevel)params.loglevel, "main"); - unsigned last_space_id = 0; - - for (int narg = 1; narg < argc; ++narg) { - const char *value = nullptr; - - if (config::parse_option(argc, argv, narg, "case", &value)) { - testcase_setup(value, params, last_space_id); - continue; - } - if (config::parse_option(argc, argv, narg, "pathname", params.pathname_db)) - continue; - if (config::parse_option(argc, argv, narg, "mode", params.mode_flags, - config::mode_bits)) - continue; - if (config::parse_option(argc, argv, narg, "table", params.table_flags, - config::table_bits)) { - if ((params.table_flags & MDBX_DUPFIXED) == 0) - params.table_flags &= ~MDBX_INTEGERDUP; - if ((params.table_flags & MDBX_DUPSORT) == 0) - params.table_flags &= - ~(MDBX_DUPFIXED | MDBX_REVERSEDUP | MDBX_INTEGERDUP); - continue; - } - - if (config::parse_option(argc, argv, narg, "pagesize", params.pagesize, - int(mdbx_limits_pgsize_min()), - int(mdbx_limits_pgsize_max()))) { - const unsigned keylen_max = params.mdbx_keylen_max(); - if (params.keylen_min > keylen_max) - params.keylen_min = keylen_max; - if (params.keylen_max > keylen_max) - params.keylen_max = keylen_max; - const unsigned datalen_max = params.mdbx_datalen_max(); - if (params.datalen_min > datalen_max) - params.datalen_min = datalen_max; - if (params.datalen_max > datalen_max) - params.datalen_max = datalen_max; - continue; - } - if (config::parse_option(argc, argv, narg, "repeat", params.nrepeat, - config::no_scale)) - continue; - if (config::parse_option(argc, argv, narg, "threads", params.nthreads, - config::no_scale, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "timeout", - global::config::timeout_duration_seconds, - config::duration, 1)) - continue; - - if (config::parse_option_intptr(argc, argv, narg, "size-lower", - params.size_lower, - mdbx_limits_dbsize_min(params.pagesize), - mdbx_limits_dbsize_max(params.pagesize))) - continue; - if (config::parse_option_intptr(argc, argv, narg, "size-upper", - params.size_upper, - mdbx_limits_dbsize_min(params.pagesize), - mdbx_limits_dbsize_max(params.pagesize))) - continue; - if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now, - mdbx_limits_dbsize_min(params.pagesize), - mdbx_limits_dbsize_max(params.pagesize))) - continue; - if (config::parse_option( - argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0, - (int)std::min((intptr_t)INT_MAX, - mdbx_limits_dbsize_max(params.pagesize) - - mdbx_limits_dbsize_min(params.pagesize)))) - continue; - if (config::parse_option( - argc, argv, narg, "growth-step", params.growth_step, 0, - (int)std::min((intptr_t)INT_MAX, - mdbx_limits_dbsize_max(params.pagesize) - - mdbx_limits_dbsize_min(params.pagesize)))) - continue; - - if (config::parse_option(argc, argv, narg, "keygen.width", - params.keygen.width, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.mesh", - params.keygen.mesh, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.seed", - params.keygen.seed, config::no_scale)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.split", - params.keygen.split, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.rotate", - params.keygen.rotate, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.offset", - params.keygen.offset, config::binary)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.case", &value)) { - keycase_setup(value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "keylen.min", params.keylen_min, - config::no_scale, params.mdbx_keylen_min(), - params.mdbx_keylen_max())) { - if ((params.table_flags & MDBX_INTEGERKEY) || - params.keylen_max < params.keylen_min) - params.keylen_max = params.keylen_min; - continue; - } - if (config::parse_option(argc, argv, narg, "keylen.max", params.keylen_max, - config::no_scale, params.mdbx_keylen_min(), - params.mdbx_keylen_max())) { - if ((params.table_flags & MDBX_INTEGERKEY) || - params.keylen_min > params.keylen_max) - params.keylen_min = params.keylen_max; - continue; - } - if (config::parse_option(argc, argv, narg, "datalen.min", - params.datalen_min, config::no_scale, - params.mdbx_datalen_min(), - params.mdbx_datalen_max())) { - if ((params.table_flags & MDBX_DUPFIXED) || - params.datalen_max < params.datalen_min) - params.datalen_max = params.datalen_min; - continue; - } - if (config::parse_option(argc, argv, narg, "datalen.max", - params.datalen_max, config::no_scale, - params.mdbx_datalen_min(), - params.mdbx_datalen_max())) { - if ((params.table_flags & MDBX_DUPFIXED) || - params.datalen_min > params.datalen_max) - params.datalen_min = params.datalen_max; - continue; - } - if (config::parse_option(argc, argv, narg, "batch.read", params.batch_read, - config::no_scale, 1)) - continue; - if (config::parse_option(argc, argv, narg, "batch.write", - params.batch_write, config::no_scale, 1)) - continue; - if (config::parse_option(argc, argv, narg, "delay", params.delaystart, - config::duration)) - continue; - if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops, - config::decimal)) - continue; - if (config::parse_option(argc, argv, narg, "inject-writefault", - params.inject_writefaultn, config::decimal)) - continue; - if (config::parse_option(argc, argv, narg, "drop", params.drop_table)) - continue; - if (config::parse_option(argc, argv, narg, "ignore-dbfull", - params.ignore_dbfull)) - continue; - if (config::parse_option(argc, argv, narg, "speculum", params.speculum)) - continue; - if (config::parse_option(argc, argv, narg, "dump-config", - global::config::dump_config)) - continue; - if (config::parse_option(argc, argv, narg, "cleanup-before", - global::config::cleanup_before)) - continue; - if (config::parse_option(argc, argv, narg, "cleanup-after", - global::config::cleanup_after)) - continue; - if (config::parse_option(argc, argv, narg, "max-readers", - params.max_readers, config::no_scale, 1, 255)) - continue; - if (config::parse_option(argc, argv, narg, "max-tables", params.max_tables, - config::no_scale, 1, INT16_MAX)) - continue; - - if (config::parse_option(argc, argv, narg, "no-delay", nullptr)) { - params.delaystart = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "no-wait4ops", nullptr)) { - params.waitfor_nops = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "duration", params.test_duration, - config::duration, 1)) { - params.test_nops = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "nops", params.test_nops, - config::decimal, 1)) { - params.test_duration = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "hill", &value, "auto")) { - configure_actor(last_space_id, ac_hill, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "jitter", nullptr)) { - configure_actor(last_space_id, ac_jitter, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "dead.reader", nullptr)) { - configure_actor(last_space_id, ac_deadread, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "dead.writer", nullptr)) { - configure_actor(last_space_id, ac_deadwrite, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "try", nullptr)) { - configure_actor(last_space_id, ac_try, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "copy", nullptr)) { - configure_actor(last_space_id, ac_copy, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "append", nullptr)) { - configure_actor(last_space_id, ac_append, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "ttl", nullptr)) { - configure_actor(last_space_id, ac_ttl, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "nested", nullptr)) { - configure_actor(last_space_id, ac_nested, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "failfast", - global::config::failfast)) - continue; - if (config::parse_option(argc, argv, narg, "progress", - global::config::progress_indicator)) - continue; - if (config::parse_option(argc, argv, narg, "console", - global::config::console_mode)) - continue; - - if (*argv[narg] != '-') - testcase_setup(argv[narg], params, last_space_id); - else - failure("Unknown option '%s'. Try --help\n", argv[narg]); - } - - if (global::config::dump_config) - config::dump(); - - //-------------------------------------------------------------------------- - - if (global::actors.empty()) { - log_notice("no testcase(s) configured, exiting"); - return EXIT_SUCCESS; - } - - bool failed = false; - global::start_motonic = chrono::now_motonic(); - global::deadline_motonic.fixedpoint = - (global::config::timeout_duration_seconds == 0) - ? chrono::infinite().fixedpoint - : global::start_motonic.fixedpoint + - chrono::from_seconds(global::config::timeout_duration_seconds) - .fixedpoint; - - if (global::config::cleanup_before) - cleanup(); - - log_trace(">> probe entropy_ticks()"); - entropy_ticks(); - log_trace("<< probe entropy_ticks()"); - - if (global::actors.size() == 1) { - logging::setup("main"); - global::singlemode = true; - if (!test_execute(global::actors.front())) - failed = true; - } else { - logging::setup("overlord"); - - log_trace("=== preparing..."); - log_trace(">> osal_setup"); - osal_setup(global::actors); - log_trace("<< osal_setup"); - - for (auto &a : global::actors) { - mdbx_pid_t pid; - log_trace(">> actor_start"); - int rc = osal_actor_start(a, pid); - log_trace("<< actor_start"); - if (rc) { - log_trace(">> killall_actors: (%s)", "start failed"); - osal_killall_actors(); - log_trace("<< killall_actors"); - failure("Failed to start actor #%u (%s)\n", a.actor_id, - test_strerror(rc)); - } - global::pid2actor[pid] = &a; - } - - log_trace("=== ready to start..."); - atexit(osal_killall_actors); - log_trace(">> wait4barrier"); - osal_wait4barrier(); - log_trace("<< wait4barrier"); - - size_t left = global::actors.size(); - log_trace("=== polling..."); - while (left > 0) { - unsigned timeout_seconds_left = INT_MAX; - chrono::time now_motonic = chrono::now_motonic(); - if (now_motonic.fixedpoint >= global::deadline_motonic.fixedpoint) - timeout_seconds_left = 0; - else { - chrono::time left_motonic; - left_motonic.fixedpoint = - global::deadline_motonic.fixedpoint - now_motonic.fixedpoint; - timeout_seconds_left = left_motonic.seconds(); - } - - mdbx_pid_t pid; - int rc = osal_actor_poll(pid, timeout_seconds_left); - if (rc) - failure("Poll error: %s (%d)\n", test_strerror(rc), rc); - - if (pid) { - actor_status status = osal_actor_info(pid); - actor_config *actor = global::pid2actor.at(pid); - if (!actor) - continue; - - log_verbose("actor #%u, id %d, pid %u: %s\n", actor->actor_id, - actor->space_id, pid, status2str(status)); - if (status > as_running) { - left -= 1; - if (status != as_successful) { - if (global::config::failfast && !failed) { - log_trace(">> killall_actors: (%s)", "failfast"); - osal_killall_actors(); - log_trace("<< killall_actors"); - } - failed = true; - } - } - } else { - if (timeout_seconds_left == 0) - failure("Timeout\n"); - } - } - log_trace("=== done..."); - } - - log_notice("RESULT: %s\n", failed ? "Failed" : "Successful"); - if (global::config::cleanup_before) { - if (failed) - log_verbose("skip cleanup"); - else - cleanup(); - } - -#if !(defined(_WIN32) || defined(_WIN64)) - struct rusage spent; - if (getrusage(RUSAGE_CHILDREN, &spent) == 0) { - log_notice("%6s: user %f, system %f", "CPU", - spent.ru_utime.tv_sec + spent.ru_utime.tv_usec * 1e-6, - spent.ru_stime.tv_sec + spent.ru_stime.tv_usec * 1e-6); -#if defined(__linux__) || defined(__gnu_linux__) || defined(__FreeBSD__) || \ - defined(__NetBSD__) || defined(__OpenBSD__) || defined(__BSD__) || \ - defined(__NETBSD__) || defined(__bsdi__) || defined(__DragonFly__) || \ - defined(__APPLE__) || defined(__MACH__) - log_notice("%6s: read %ld, write %ld", "IOPs", spent.ru_inblock, - spent.ru_oublock); - log_notice("%6s: %ld Kb", "RAM", spent.ru_maxrss); - log_notice("%6s: reclaims %ld, faults %ld, swaps %ld", "Paging", - spent.ru_minflt, spent.ru_majflt, spent.ru_nswap); -#endif /* Linux */ - } -#endif /* !Windows */ - - return failed ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/test/nested.cc b/src/contrib/db/libmdbx/test/nested.cc deleted file mode 100644 index e02fe8b..0000000 --- a/src/contrib/db/libmdbx/test/nested.cc +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" -#include - -bool testcase_nested::setup() { - if (!inherited::setup()) - return false; - int err = db_open__begin__table_create_open_clean(dbi); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("nested: bailout-prepare due '%s'", mdbx_strerror(err)); - return false; - } - - keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); - key = keygen::alloc(config.params.keylen_max); - data = keygen::alloc(config.params.datalen_max); - serial = 0; - fifo.clear(); - speculum.clear(); - assert(stack.empty()); - stack.emplace(nullptr, serial, fifo, speculum); - return true; -} - -bool testcase_nested::teardown() { - while (!stack.empty()) - pop_txn(true); - - bool ok = true; - if (dbi) { - if (config.params.drop_table && !mode_readonly()) { - txn_begin(false); - db_table_drop(dbi); - int err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("nested: bailout-clean due '%s'", mdbx_strerror(err)); - ok = false; - } - } else - db_table_close(dbi); - dbi = 0; - } - return inherited::teardown() && ok; -} - -static unsigned edge2window(uint64_t edge, unsigned window_max) { - const double rnd = u64_to_double1(bleach64(edge)); - const unsigned window = window_max - std::lrint(std::pow(window_max, rnd)); - return window; -} - -static unsigned edge2count(uint64_t edge, unsigned count_max) { - const double rnd = u64_to_double1(prng64_map1_white(edge)); - const unsigned count = std::lrint(std::pow(count_max, rnd)); - return count; -} - -void testcase_nested::push_txn() { - MDBX_txn *txn; - int err = mdbx_txn_begin( - db_guard.get(), txn_guard.get(), - prng32() & (MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC), &txn); - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_txn_begin(nested)", err); -#if __cplusplus >= 201703L - stack.emplace(txn, serial, fifo, speculum); -#else - stack.push(std::make_tuple(scoped_txn_guard(txn), serial, fifo, speculum)); -#endif - std::swap(txn_guard, std::get<0>(stack.top())); - log_verbose("begin level#%zu txn, serial %" PRIu64, stack.size(), serial); -} - -bool testcase_nested::pop_txn(bool abort) { - assert(txn_guard && !stack.empty()); - bool should_continue = true; - MDBX_txn *txn = txn_guard.release(); - bool commited = false; - if (abort) { - log_verbose("abort level#%zu txn, undo serial %" PRIu64 " <- %" PRIu64, - stack.size(), serial, std::get<1>(stack.top())); - int err = mdbx_txn_abort(txn); - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_txn_abort()", err); - } else { - log_verbose("commit level#%zu txn, nested serial %" PRIu64 " -> %" PRIu64, - stack.size(), serial, std::get<1>(stack.top())); - int err = mdbx_txn_commit(txn); - if (likely(err == MDBX_SUCCESS)) - commited = true; - else { - should_continue = false; - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - err = mdbx_txn_abort(txn); - if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH && - err != MDBX_BAD_TXN)) - failure_perror("mdbx_txn_abort()", err); - } else - failure_perror("mdbx_txn_commit()", err); - } - } - - std::swap(txn_guard, std::get<0>(stack.top())); - if (!commited) { - serial = std::get<1>(stack.top()); - std::swap(fifo, std::get<2>(stack.top())); - std::swap(speculum, std::get<3>(stack.top())); - } - stack.pop(); - return should_continue; -} - -bool testcase_nested::stochastic_breakable_restart_with_nested( - bool force_restart) { - log_trace(">> stochastic_breakable_restart_with_nested%s", - force_restart ? ": force_restart" : ""); - - if (force_restart) - while (txn_guard) - pop_txn(true); - - bool should_continue = true; - while (!stack.empty() && - (flipcoin() || txn_underutilization_x256(txn_guard.get()) < 42)) - should_continue &= pop_txn(); - - if (should_continue) - while (stack.empty() || - (is_nested_txn_available() && flipcoin() && stack.size() < 5)) - push_txn(); - - log_trace("<< stochastic_breakable_restart_with_nested: should_continue=%s", - should_continue ? "yes" : "no"); - return should_continue; -} - -bool testcase_nested::trim_tail(unsigned window_width) { - if (window_width) { - while (fifo.size() > window_width) { - uint64_t tail_serial = fifo.back().first; - const unsigned tail_count = fifo.back().second; - log_trace("nested: pop-tail (serial %" PRIu64 ", count %u)", tail_serial, - tail_count); - fifo.pop_back(); - for (unsigned n = 0; n < tail_count; ++n) { - log_trace("nested: remove-tail %" PRIu64, tail_serial); - generate_pair(tail_serial); - int err = remove(key, data); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("nested: tail-bailout due '%s'", mdbx_strerror(err)); - return false; - } - failure_perror("mdbx_del(tail)", err); - } - if (unlikely(!keyvalue_maker.increment(tail_serial, 1))) - failure("nested: unexpected key-space overflow on the tail"); - } - } - } else { - log_trace("nested: purge state"); - db_table_clear(dbi, txn_guard.get()); - fifo.clear(); - speculum.clear(); - } - return true; -} - -bool testcase_nested::grow_head(unsigned head_count) { - const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_NODUPDATA - : MDBX_NODUPDATA | MDBX_NOOVERWRITE; -retry: - fifo.push_front(std::make_pair(serial, head_count)); - for (unsigned n = 0; n < head_count; ++n) { - log_trace("nested: insert-head %" PRIu64, serial); - generate_pair(serial); - int err = insert(key, data, insert_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("nested: head-insert skip due '%s'", mdbx_strerror(err)); - head_count = n; - stochastic_breakable_restart_with_nested(true); - goto retry; - } - failure_perror("mdbx_put(head)", err); - } - - if (unlikely(!keyvalue_maker.increment(serial, 1))) { - log_notice("nested: unexpected key-space overflow"); - return false; - } - } - - return true; -} - -bool testcase_nested::run() { - /* LY: теÑÑ‚ "ÑмулÑцией time-to-live" Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ‹Ð¼Ð¸ транзакциÑми: - * - организуетÑÑ "ÑкользÑщее окно", которое каждую транзакцию ÑдвигаетÑÑ - * вперед вдоль чиÑловой оÑи. - * - по переднему краю "ÑкользÑщего окна" запиÑи добавлÑÑŽÑ‚ÑÑ Ð² таблицу, - * а по заднему удалÑÑŽÑ‚ÑÑ. - * - количеÑтво добавлÑемых/удалÑемых запиÑей пÑевдоÑлучайно завиÑит - * от номера транзакции, но Ñ ÑкÑпоненциальным раÑпределением. - * - размер "ÑкользÑщего окна" также пÑевдоÑлучайно завиÑит от номера - * транзакции Ñ "отрицательным" ÑкÑпоненциальным раÑпределением - * MAX_WIDTH - exp(rnd(N)), при уменьшении окна ÑдвигаетÑÑ Ð·Ð°Ð´Ð½Ð¸Ð¹ - * край и удалÑÑŽÑ‚ÑÑ Ð·Ð°Ð¿Ð¸Ñи позади него. - * - групповое добавление данных в начало окна и групповое уделение в конце, - * в половине Ñлучаев выполнÑÑŽÑ‚ÑÑ Ð²Ð¾ вложенных транзакциÑÑ…. - * - половина запуÑкаемых вложенных транзакций отменÑетÑÑ, поÑледуюим - * повтором групповой операции. - * - * Таким образом имитируетÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ таблицы Ñ TTL: запиÑи ÑтохаÑтичеÑки - * добавлÑÑŽÑ‚ÑÑ Ð¸ удалÑÑŽÑ‚ÑÑ, но изредка проиÑходÑÑ‚ маÑÑивные удалениÑ. */ - - /* LY: Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ иÑпользуем подходÑщие параметры, которые не имеют - * здеÑÑŒ ÑмыÑла в первоначальном значении. */ - const unsigned window_max_lower = 333; - const unsigned count_max_lower = 333; - - const unsigned window_max = (config.params.batch_read > window_max_lower) - ? config.params.batch_read - : window_max_lower; - const unsigned count_max = (config.params.batch_write > count_max_lower) - ? config.params.batch_write - : count_max_lower; - log_verbose("nested: using `batch_read` value %u for window_max", window_max); - log_verbose("nested: using `batch_write` value %u for count_max", count_max); - - uint64_t seed = - prng64_map2_white(config.params.keygen.seed) + config.actor_id; - - while (should_continue()) { - const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */; - const unsigned window_width = - flipcoin_x4() ? 0 : edge2window(salt, window_max); - const unsigned head_count = edge2count(salt, count_max); - log_debug("nested: step #%zu (serial %" PRIu64 - ", window %u, count %u) salt %" PRIu64, - nops_completed, serial, window_width, head_count, salt); - - if (!trim_tail(window_width)) - return false; - if (!stochastic_breakable_restart_with_nested()) { - log_notice("nested: bailout at commit/restart after tail-trim"); - return false; - } - if (!speculum_verify()) { - log_notice("nested: bailout after tail-trim"); - return false; - } - - if (!grow_head(head_count)) - return false; - if (!stochastic_breakable_restart_with_nested()) - log_notice("nested: skip commit/restart after head-grow"); - if (!speculum_verify()) { - log_notice("nested: bailout after head-grow"); - return false; - } - - report(1); - } - - while (!stack.empty()) - pop_txn(false); - - return speculum_verify(); -} diff --git a/src/contrib/db/libmdbx/test/osal-unix.cc b/src/contrib/db/libmdbx/test/osal-unix.cc deleted file mode 100644 index d954cea..0000000 --- a/src/contrib/db/libmdbx/test/osal-unix.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -#include -#include -#include -#include -#include -#include - -#ifdef __APPLE__ -#include "darwin/pthread_barrier.c" -#endif - -struct shared_t { - pthread_barrier_t barrier; - pthread_mutex_t mutex; - size_t conds_size; - pthread_cond_t conds[1]; -}; - -static shared_t *shared; - -void osal_wait4barrier(void) { - assert(shared != nullptr && shared != MAP_FAILED); - int rc = pthread_barrier_wait(&shared->barrier); - if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { - failure_perror("pthread_barrier_wait(shared)", rc); - } -} - -void osal_setup(const std::vector &actors) { - assert(shared == nullptr); - - pthread_mutexattr_t mutexattr; - int rc = pthread_mutexattr_init(&mutexattr); - if (rc) - failure_perror("pthread_mutexattr_init()", rc); - rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_mutexattr_setpshared()", rc); - - pthread_barrierattr_t barrierattr; - rc = pthread_barrierattr_init(&barrierattr); - if (rc) - failure_perror("pthread_barrierattr_init()", rc); - rc = pthread_barrierattr_setpshared(&barrierattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_barrierattr_setpshared()", rc); - - pthread_condattr_t condattr; - rc = pthread_condattr_init(&condattr); - if (rc) - failure_perror("pthread_condattr_init()", rc); - rc = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_condattr_setpshared()", rc); - - shared = (shared_t *)mmap( - nullptr, sizeof(shared_t) + actors.size() * sizeof(pthread_cond_t), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (MAP_FAILED == (void *)shared) - failure_perror("mmap(shared_conds)", errno); - - rc = pthread_mutex_init(&shared->mutex, &mutexattr); - if (rc) - failure_perror("pthread_mutex_init(shared)", rc); - - rc = pthread_barrier_init(&shared->barrier, &barrierattr, actors.size() + 1); - if (rc) - failure_perror("pthread_barrier_init(shared)", rc); - - const size_t n = actors.size() + 1; - for (size_t i = 0; i < n; ++i) { - pthread_cond_t *event = &shared->conds[i]; - rc = pthread_cond_init(event, &condattr); - if (rc) - failure_perror("pthread_cond_init(shared)", rc); - log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i, - __Wpedantic_format_voidptr(event)); - } - shared->conds_size = actors.size() + 1; - - pthread_barrierattr_destroy(&barrierattr); - pthread_condattr_destroy(&condattr); - pthread_mutexattr_destroy(&mutexattr); -} - -void osal_broadcast(unsigned id) { - assert(shared != nullptr && shared != MAP_FAILED); - log_trace("osal_broadcast: event %u", id); - if (id >= shared->conds_size) - failure("osal_broadcast: id > limit"); - int rc = pthread_cond_broadcast(shared->conds + id); - if (rc) - failure_perror("sem_post(shared)", rc); -} - -int osal_waitfor(unsigned id) { - assert(shared != nullptr && shared != MAP_FAILED); - - log_trace("osal_waitfor: event %u", id); - if (id >= shared->conds_size) - failure("osal_waitfor: id > limit"); - - int rc = pthread_mutex_lock(&shared->mutex); - if (rc != 0) - failure_perror("pthread_mutex_lock(shared)", rc); - - rc = pthread_cond_wait(shared->conds + id, &shared->mutex); - if (rc && rc != EINTR) - failure_perror("pthread_cond_wait(shared)", rc); - - rc = pthread_mutex_unlock(&shared->mutex); - if (rc != 0) - failure_perror("pthread_mutex_unlock(shared)", rc); - - return (rc == 0) ? true : false; -} - -//----------------------------------------------------------------------------- - -const std::string -actor_config::osal_serialize(simple_checksum &checksum) const { - (void)checksum; - /* not used in workload, but just for testing */ - return "unix.fork"; -} - -bool actor_config::osal_deserialize(const char *str, const char *end, - simple_checksum &checksum) { - (void)checksum; - /* not used in workload, but just for testing */ - return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end; -} - -//----------------------------------------------------------------------------- - -static pid_t overlord_pid; - -static volatile sig_atomic_t sigusr1_head, sigusr2_head; -static void handler_SIGUSR(int signum) { - switch (signum) { - case SIGUSR1: - sigusr1_head += 1; - return; - case SIGUSR2: - sigusr2_head += 1; - return; - default: - abort(); - } -} - -bool osal_progress_push(bool active) { - if (overlord_pid) { - if (kill(overlord_pid, active ? SIGUSR1 : SIGUSR2)) - failure_perror("osal_progress_push: kill(overload)", errno); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -static std::unordered_map childs; - -static volatile sig_atomic_t sigalarm_head; -static void handler_SIGCHLD(int signum) { - if (signum == SIGALRM) - sigalarm_head += 1; -} - -mdbx_pid_t osal_getpid(void) { return getpid(); } - -int osal_delay(unsigned seconds) { return sleep(seconds) ? errno : 0; } - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { - if (childs.empty()) { - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = handler_SIGCHLD; - sigaction(SIGCHLD, &act, nullptr); - sigaction(SIGALRM, &act, nullptr); - act.sa_handler = handler_SIGUSR; - sigaction(SIGUSR1, &act, nullptr); - sigaction(SIGUSR2, &act, nullptr); - - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - sigaddset(&mask, SIGUSR1); - sigaddset(&mask, SIGUSR2); - sigprocmask(SIG_UNBLOCK, &mask, nullptr); - } - - pid = fork(); - - if (pid == 0) { - overlord_pid = getppid(); - const bool result = test_execute(config); - exit(result ? EXIT_SUCCESS : EXIT_FAILURE); - } - - if (pid < 0) - return errno; - - log_trace("osal_actor_start: fork pid %i for %u", pid, config.actor_id); - childs[pid] = as_running; - return 0; -} - -actor_status osal_actor_info(const mdbx_pid_t pid) { return childs.at(pid); } - -void osal_killall_actors(void) { - for (auto &pair : childs) { - kill(pair.first, SIGKILL); - pair.second = as_killed; - } -} - -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { - static sig_atomic_t sigalarm_tail; - alarm(0) /* cancel prev timeout */; - sigalarm_tail = sigalarm_head /* reset timeout flag */; - - int options = WNOHANG; - if (timeout) { - alarm((timeout > INT_MAX) ? INT_MAX : timeout); - options = 0; - } - -#ifdef WUNTRACED - options |= WUNTRACED; -#endif -#ifdef WCONTINUED - options |= WCONTINUED; -#endif - - while (sigalarm_tail == sigalarm_head) { - int status; - pid = waitpid(0, &status, options); - - if (pid > 0) { - if (WIFEXITED(status)) - childs[pid] = - (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed; - else if (WCOREDUMP(status)) - childs[pid] = as_coredump; - else if (WIFSIGNALED(status)) - childs[pid] = as_killed; - else if (WIFSTOPPED(status)) - childs[pid] = as_debuging; - else if (WIFCONTINUED(status)) - childs[pid] = as_running; - else { - assert(false); - } - return 0; - } - - static sig_atomic_t sigusr1_tail, sigusr2_tail; - if (sigusr1_tail != sigusr1_head) { - sigusr1_tail = sigusr1_head; - logging::progress_canary(true); - if (pid < 0 && errno == EINTR) - continue; - } - if (sigusr2_tail != sigusr2_head) { - sigusr2_tail = sigusr2_head; - logging::progress_canary(false); - if (pid < 0 && errno == EINTR) - continue; - } - - if (pid == 0) - break; - - int err = errno; - if (err != EINTR) - return err; - } - return 0 /* timeout */; -} - -void osal_yield(void) { - if (sched_yield()) - failure_perror("sched_yield()", errno); -} - -void osal_udelay(unsigned us) { - chrono::time until, now = chrono::now_motonic(); - until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; - struct timespec ts; - - static unsigned threshold_us; - if (threshold_us == 0) { - if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) { - int rc = errno; - failure_perror("clock_getres(CLOCK_PROCESS_CPUTIME_ID)", rc); - } - chrono::time threshold = chrono::from_timespec(ts); - assert(threshold.seconds() == 0); - - threshold_us = chrono::fractional2us(threshold.fractional); - if (threshold_us < 1000) - threshold_us = 1000; - } - - ts.tv_sec = ts.tv_nsec = 0; - if (us > threshold_us) { - ts.tv_sec = us / 1000000u; - ts.tv_nsec = (us % 1000000u) * 1000u; - } - - do { - if (us > threshold_us) { - if (nanosleep(&ts, &ts)) { - int rc = errno; - /* if (rc == EINTR) { ... } ? */ - failure_perror("usleep()", rc); - } - us = ts.tv_sec * 1000000u + ts.tv_nsec / 1000u; - } - cpu_relax(); - - now = chrono::now_motonic(); - } while (until.fixedpoint > now.fixedpoint); -} - -bool osal_istty(int fd) { return isatty(fd) == 1; } - -std::string osal_tempdir(void) { - const char *tempdir = getenv("TMPDIR"); - if (!tempdir) - tempdir = getenv("TMP"); - if (!tempdir) - tempdir = getenv("TEMPDIR"); - if (!tempdir) - tempdir = getenv("TEMP"); - if (tempdir) { - std::string dir(tempdir); - if (!dir.empty() && dir.at(dir.length() - 1) != '/') - dir.append("/"); - return dir; - } - if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0) - return "/dev/shm/"; - return ""; -} - -int osal_removefile(const std::string &pathname) { - return unlink(pathname.c_str()) ? errno : MDBX_SUCCESS; -} diff --git a/src/contrib/db/libmdbx/test/osal-windows.cc b/src/contrib/db/libmdbx/test/osal-windows.cc deleted file mode 100644 index 0b158c0..0000000 --- a/src/contrib/db/libmdbx/test/osal-windows.cc +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -static std::unordered_map events; -static HANDLE hBarrierSemaphore, hBarrierEvent; -static HANDLE hProgressActiveEvent, hProgressPassiveEvent; - -static int waitstatus2errcode(DWORD result) { - switch (result) { - case WAIT_OBJECT_0: - return MDBX_SUCCESS; - case WAIT_FAILED: - return GetLastError(); - case WAIT_ABANDONED: - return ERROR_ABANDONED_WAIT_0; - case WAIT_IO_COMPLETION: - return ERROR_USER_APC; - case WAIT_TIMEOUT: - return ERROR_TIMEOUT; - default: - return ERROR_UNHANDLED_ERROR; - } -} - -void osal_wait4barrier(void) { - DWORD rc = WaitForSingleObject(hBarrierSemaphore, 0); - switch (rc) { - default: - failure_perror("WaitForSingleObject(BarrierSemaphore)", - waitstatus2errcode(rc)); - case WAIT_OBJECT_0: - rc = WaitForSingleObject(hBarrierEvent, INFINITE); - if (rc != WAIT_OBJECT_0) - failure_perror("WaitForSingleObject(BarrierEvent)", - waitstatus2errcode(rc)); - break; - case WAIT_TIMEOUT: - if (!SetEvent(hBarrierEvent)) - failure_perror("SetEvent(BarrierEvent)", GetLastError()); - break; - } -} - -static HANDLE make_inheritable(HANDLE hHandle) { - assert(hHandle != NULL && hHandle != INVALID_HANDLE_VALUE); - if (!DuplicateHandle(GetCurrentProcess(), hHandle, GetCurrentProcess(), - &hHandle, 0, TRUE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) - failure_perror("DuplicateHandle()", GetLastError()); - return hHandle; -} - -void osal_setup(const std::vector &actors) { - assert(events.empty()); - const size_t n = actors.size() + 1; - events.reserve(n); - - for (unsigned i = 0; i < n; ++i) { - HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!hEvent) - failure_perror("CreateEvent()", GetLastError()); - hEvent = make_inheritable(hEvent); - log_trace("osal_setup: event %" PRIuPTR " -> %p", i, hEvent); - events[i] = hEvent; - } - - hBarrierSemaphore = CreateSemaphore(NULL, 0, (LONG)actors.size(), NULL); - if (!hBarrierSemaphore) - failure_perror("CreateSemaphore(BarrierSemaphore)", GetLastError()); - hBarrierSemaphore = make_inheritable(hBarrierSemaphore); - - hBarrierEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!hBarrierEvent) - failure_perror("CreateEvent(BarrierEvent)", GetLastError()); - hBarrierEvent = make_inheritable(hBarrierEvent); - - hProgressActiveEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!hProgressActiveEvent) - failure_perror("CreateEvent(ProgressActiveEvent)", GetLastError()); - hProgressActiveEvent = make_inheritable(hProgressActiveEvent); - - hProgressPassiveEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!hProgressPassiveEvent) - failure_perror("CreateEvent(ProgressPassiveEvent)", GetLastError()); - hProgressPassiveEvent = make_inheritable(hProgressPassiveEvent); -} - -void osal_broadcast(unsigned id) { - log_trace("osal_broadcast: event %u", id); - if (!SetEvent(events.at(id))) - failure_perror("SetEvent()", GetLastError()); -} - -int osal_waitfor(unsigned id) { - log_trace("osal_waitfor: event %u", id); - DWORD rc = WaitForSingleObject(events.at(id), INFINITE); - return waitstatus2errcode(rc); -} - -mdbx_pid_t osal_getpid(void) { return GetCurrentProcessId(); } - -int osal_delay(unsigned seconds) { - Sleep(seconds * 1000u); - return 0; -} - -//----------------------------------------------------------------------------- - -const std::string -actor_config::osal_serialize(simple_checksum &checksum) const { - checksum.push(hBarrierSemaphore); - checksum.push(hBarrierEvent); - checksum.push(hProgressActiveEvent); - checksum.push(hProgressPassiveEvent); - - HANDLE hWait = INVALID_HANDLE_VALUE; - if (wait4id) { - hWait = events.at(wait4id); - checksum.push(hWait); - } - - HANDLE hSignal = INVALID_HANDLE_VALUE; - if (wanna_event4signalling()) { - hSignal = events.at(actor_id); - checksum.push(hSignal); - } - - return format("%p.%p.%p.%p.%p.%p", hBarrierSemaphore, hBarrierEvent, hWait, - hSignal, hProgressActiveEvent, hProgressPassiveEvent); -} - -bool actor_config::osal_deserialize(const char *str, const char *end, - simple_checksum &checksum) { - - std::string copy(str, end - str); - TRACE(">> osal_deserialize(%s)\n", copy.c_str()); - - assert(hBarrierSemaphore == 0); - assert(hBarrierEvent == 0); - assert(hProgressActiveEvent == 0); - assert(hProgressPassiveEvent == 0); - assert(events.empty()); - - HANDLE hWait, hSignal; - if (sscanf_s(copy.c_str(), "%p.%p.%p.%p.%p.%p", &hBarrierSemaphore, - &hBarrierEvent, &hWait, &hSignal, &hProgressActiveEvent, - &hProgressPassiveEvent) != 6) { - TRACE("<< osal_deserialize: failed\n"); - return false; - } - - checksum.push(hBarrierSemaphore); - checksum.push(hBarrierEvent); - checksum.push(hProgressActiveEvent); - checksum.push(hProgressPassiveEvent); - - if (wait4id) { - checksum.push(hWait); - events[wait4id] = hWait; - } - - if (wanna_event4signalling()) { - checksum.push(hSignal); - events[actor_id] = hSignal; - } - - TRACE("<< osal_deserialize: OK\n"); - return true; -} - -//----------------------------------------------------------------------------- - -typedef std::pair child; -static std::unordered_map childs; - -bool osal_progress_push(bool active) { - if (childs.empty()) { - if (!SetEvent(active ? hProgressActiveEvent : hProgressPassiveEvent)) - failure_perror("osal_progress_push: SetEvent(overlord.progress)", - GetLastError()); - return true; - } - - return false; -} - -static void ArgvQuote(std::string &CommandLine, const std::string &Argument, - bool Force = false) - -/*++ - -https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ - -Routine Description: - - This routine appends the given argument to a command line such - that CommandLineToArgvW will return the argument string unchanged. - Arguments in a command line should be separated by spaces; this - function does not add these spaces. - -Arguments: - - Argument - Supplies the argument to encode. - - CommandLine - Supplies the command line to which we append the encoded -argument string. - - Force - Supplies an indication of whether we should quote - the argument even if it does not contain any characters that would - ordinarily require quoting. - -Return Value: - - None. - -Environment: - - Arbitrary. - ---*/ - -{ - // - // Unless we're told otherwise, don't quote unless we actually - // need to do so --- hopefully avoid problems if programs won't - // parse quotes properly - // - - if (Force == false && Argument.empty() == false && - Argument.find_first_of(" \t\n\v\"") == Argument.npos) { - CommandLine.append(Argument); - } else { - CommandLine.push_back('"'); - - for (auto It = Argument.begin();; ++It) { - unsigned NumberBackslashes = 0; - - while (It != Argument.end() && *It == '\\') { - ++It; - ++NumberBackslashes; - } - - if (It == Argument.end()) { - // - // Escape all backslashes, but let the terminating - // double quotation mark we add below be interpreted - // as a metacharacter. - // - CommandLine.append(NumberBackslashes * 2, '\\'); - break; - } else if (*It == L'"') { - // - // Escape all backslashes and the following - // double quotation mark. - // - CommandLine.append(NumberBackslashes * 2 + 1, '\\'); - CommandLine.push_back(*It); - } else { - // - // Backslashes aren't special here. - // - CommandLine.append(NumberBackslashes, '\\'); - CommandLine.push_back(*It); - } - } - - CommandLine.push_back('"'); - } -} - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { - if (childs.size() == MAXIMUM_WAIT_OBJECTS) - failure("Could't manage more that %u actors on Windows\n", - MAXIMUM_WAIT_OBJECTS); - - _flushall(); - - STARTUPINFOA StartupInfo; - GetStartupInfoA(&StartupInfo); - - char exename[_MAX_PATH + 1]; - DWORD exename_size = sizeof(exename); - if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, exename, - &exename_size)) - failure_perror("QueryFullProcessImageName()", GetLastError()); - - if (exename[1] != ':') { - exename_size = GetModuleFileName(NULL, exename, sizeof(exename)); - if (exename_size >= sizeof(exename)) - return ERROR_BAD_LENGTH; - } - - std::string cmdline = "$ "; - ArgvQuote(cmdline, thunk_param(config)); - - if (cmdline.size() >= 32767) - return ERROR_BAD_LENGTH; - - PROCESS_INFORMATION ProcessInformation; - if (!CreateProcessA(exename, const_cast(cmdline.c_str()), - NULL, // Retuned process handle is not inheritable. - NULL, // Retuned thread handle is not inheritable. - TRUE, // Child inherits all inheritable handles. - NORMAL_PRIORITY_CLASS | INHERIT_PARENT_AFFINITY, - NULL, // Inherit the parent's environment. - NULL, // Inherit the parent's current directory. - &StartupInfo, &ProcessInformation)) - failure_perror(exename, GetLastError()); - - CloseHandle(ProcessInformation.hThread); - pid = ProcessInformation.dwProcessId; - childs[pid] = std::make_pair(ProcessInformation.hProcess, as_running); - return 0; -} - -actor_status osal_actor_info(const mdbx_pid_t pid) { - actor_status status = childs.at(pid).second; - if (status > as_running) - return status; - - DWORD ExitCode; - if (!GetExitCodeProcess(childs.at(pid).first, &ExitCode)) - failure_perror("GetExitCodeProcess()", GetLastError()); - - switch (ExitCode) { - case STILL_ACTIVE: - return as_running; - case EXIT_SUCCESS: - status = as_successful; - break; - case EXCEPTION_BREAKPOINT: - case EXCEPTION_SINGLE_STEP: - status = as_debuging; - break; - case STATUS_CONTROL_C_EXIT: - status = as_killed; - break; - case EXCEPTION_ACCESS_VIOLATION: - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - case EXCEPTION_DATATYPE_MISALIGNMENT: - case EXCEPTION_STACK_OVERFLOW: - case EXCEPTION_INVALID_DISPOSITION: - case EXCEPTION_ILLEGAL_INSTRUCTION: - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - status = as_coredump; - break; - default: - status = as_failed; - break; - } - - childs.at(pid).second = status; - return status; -} - -void osal_killall_actors(void) { - for (auto &pair : childs) - TerminateProcess(pair.second.first, STATUS_CONTROL_C_EXIT); -} - -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { - std::vector handles; - handles.reserve(childs.size() + 2); - handles.push_back(hProgressActiveEvent); - handles.push_back(hProgressPassiveEvent); - for (const auto &pair : childs) - if (pair.second.second <= as_running) - handles.push_back(pair.second.first); - - while (true) { - DWORD rc = - MsgWaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0], - (timeout > 60) ? 60 * 1000 : timeout * 1000, - QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0); - - if (rc == WAIT_OBJECT_0) { - logging::progress_canary(true); - continue; - } - if (rc == WAIT_OBJECT_0 + 1) { - logging::progress_canary(false); - continue; - } - - if (rc >= WAIT_OBJECT_0 + 2 && rc < WAIT_OBJECT_0 + handles.size()) { - pid = 0; - for (const auto &pair : childs) - if (pair.second.first == handles[rc - WAIT_OBJECT_0]) { - pid = pair.first; - break; - } - return 0; - } - - if (rc == WAIT_TIMEOUT) { - pid = 0; - return 0; - } - - return waitstatus2errcode(rc); - } -} - -void osal_yield(void) { SwitchToThread(); } - -void osal_udelay(unsigned us) { - chrono::time until, now = chrono::now_motonic(); - until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; - - static unsigned threshold_us; - if (threshold_us == 0) { -#if 1 - unsigned timeslice_ms = 1; - while (timeBeginPeriod(timeslice_ms) == TIMERR_NOCANDO) - ++timeslice_ms; - threshold_us = timeslice_ms * 1500u; -#else - ULONGLONG InterruptTimePrecise_100ns; - QueryInterruptTimePrecise(&InterruptTimePrecise_100ns); - threshold_us = InterruptTimePrecise_100ns / 5; -#endif - assert(threshold_us > 0); - } - - do { - if (us > threshold_us && us > 1000) { - DWORD rc = SleepEx(us / 1000, TRUE); - if (rc) - failure_perror("SleepEx()", waitstatus2errcode(rc)); - us = 0; - } - - YieldProcessor(); - now = chrono::now_motonic(); - } while (now.fixedpoint < until.fixedpoint); -} - -bool osal_istty(int fd) { return _isatty(fd) != 0; } - -std::string osal_tempdir(void) { - char buf[MAX_PATH + 1]; - DWORD len = GetTempPathA(sizeof(buf), buf); - return std::string(buf, len); -} - -int osal_removefile(const std::string &pathname) { - return DeleteFileA(pathname.c_str()) ? MDBX_SUCCESS : GetLastError(); -} diff --git a/src/contrib/db/libmdbx/test/osal.h b/src/contrib/db/libmdbx/test/osal.h deleted file mode 100644 index 6d0e1c4..0000000 --- a/src/contrib/db/libmdbx/test/osal.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" - -void osal_setup(const std::vector &actors); -void osal_broadcast(unsigned id); -int osal_waitfor(unsigned id); - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid); -actor_status osal_actor_info(const mdbx_pid_t pid); -void osal_killall_actors(void); -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout); -void osal_wait4barrier(void); - -bool osal_progress_push(bool active); - -mdbx_pid_t osal_getpid(void); -int osal_delay(unsigned seconds); -void osal_udelay(unsigned us); -void osal_yield(void); -bool osal_istty(int fd); -std::string osal_tempdir(void); -int osal_removefile(const std::string &pathname); - -#ifdef _MSC_VER -#ifndef STDIN_FILENO -#define STDIN_FILENO _fileno(stdin) -#endif -#ifndef STDOUT_FILENO -#define STDOUT_FILENO _fileno(stdout) -#endif -#ifndef STDERR_FILENO -#define STDERR_FILENO _fileno(stderr) -#endif -#endif /* _MSC_VER */ diff --git a/src/contrib/db/libmdbx/test/pcrf/CMakeLists.txt b/src/contrib/db/libmdbx/test/pcrf/CMakeLists.txt deleted file mode 100644 index 8bd3e3d..0000000 --- a/src/contrib/db/libmdbx/test/pcrf/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(TARGET pcrf_test) -add_executable(${TARGET} pcrf_test.c) -target_include_directories(${TARGET} PRIVATE "${PROJECT_SOURCE_DIR}") -target_link_libraries(${TARGET} mdbx) - diff --git a/src/contrib/db/libmdbx/test/pcrf/README.md b/src/contrib/db/libmdbx/test/pcrf/README.md deleted file mode 100644 index b2c9b5c..0000000 --- a/src/contrib/db/libmdbx/test/pcrf/README.md +++ /dev/null @@ -1,2 +0,0 @@ -PCRF Session DB emulation test - diff --git a/src/contrib/db/libmdbx/test/pcrf/pcrf_test.c b/src/contrib/db/libmdbx/test/pcrf/pcrf_test.c deleted file mode 100644 index 90e0e28..0000000 --- a/src/contrib/db/libmdbx/test/pcrf/pcrf_test.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright 2016-2019 Leonid Yuriev . - * Copyright 2015 Vladimir Romanov - * , Yota Lab. - * - * This file is part of libmdbx. - * - * ReOpenMDBX is free software; you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * ReOpenMDBX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include "mdbx.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#define IP_PRINTF_ARG_HOST(addr) \ - (int)((addr) >> 24), (int)((addr) >> 16 & 0xff), (int)((addr) >> 8 & 0xff), \ - (int)((addr)&0xff) - -char opt_db_path[PATH_MAX] = "./mdbx_bench2"; -static MDBX_env *env; -#define REC_COUNT 10240000 -int64_t ids[REC_COUNT * 10]; -int32_t ids_count = 0; - -int64_t mdbx_add_count = 0; -int64_t mdbx_del_count = 0; -uint64_t mdbx_add_time = 0; -uint64_t mdbx_del_time = 0; -int64_t obj_id = 0; -int64_t mdbx_data_size = 0; -int64_t mdbx_key_size = 0; - -typedef struct { - char session_id1[100]; - char session_id2[100]; - char ip[20]; - uint8_t fill[100]; -} session_data_t; - -typedef struct { - int64_t obj_id; - int8_t event_type; -} __attribute__((__packed__)) event_data_t; - -static void add_id_to_pool(int64_t id) { - ids[ids_count] = id; - ids_count++; -} - -static inline int64_t getClockUs(void) { - struct timespec val; -#ifdef CYGWIN - clock_gettime(CLOCK_REALTIME, &val); -#else - clock_gettime(CLOCK_MONOTONIC, &val); -#endif - return val.tv_sec * ((int64_t)1000000) + val.tv_nsec / 1000; -} - -static int64_t get_id_from_pool() { - if (ids_count == 0) { - return -1; - } - int32_t index = rand() % ids_count; - int64_t id = ids[index]; - ids[index] = ids[ids_count - 1]; - ids_count--; - return id; -} - -#define MDBX_CHECK(x) \ - do { \ - const int rc = (x); \ - if (rc != MDBX_SUCCESS) { \ - printf("Error [%d] %s in %s at %s:%d\n", rc, mdbx_strerror(rc), #x, \ - __FILE__, __LINE__); \ - exit(EXIT_FAILURE); \ - } \ - } while (0) - -static void db_connect() { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - - MDBX_CHECK(mdbx_env_create(&env)); - MDBX_CHECK( - mdbx_env_set_mapsize(env, REC_COUNT * sizeof(session_data_t) * 10)); - MDBX_CHECK(mdbx_env_set_maxdbs(env, 30)); - MDBX_CHECK(mdbx_env_open(env, opt_db_path, - MDBX_CREATE | MDBX_WRITEMAP | MDBX_MAPASYNC | - MDBX_NOSYNC | MDBX_LIFORECLAIM, - 0664)); - MDBX_txn *txn; - - // transaction init - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - // open database in read-write mode - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); - MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); - MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); - // transaction commit - MDBX_CHECK(mdbx_txn_commit(txn)); - printf("Connection open\n"); -} - -static void create_record(uint64_t record_id) { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - event_data_t event; - MDBX_txn *txn; - session_data_t data; - // transaction init - snprintf(data.session_id1, sizeof(data.session_id1), - "prefix%02u_%02u.fill.fill.fill.fill.fill.fill;%" PRIu64, - (unsigned)(record_id % 3) + 1, (unsigned)(record_id % 9) + 1, - record_id); - snprintf(data.session_id2, sizeof(data.session_id2), - "dprefix%" PRIu64 ";%" PRIu64 ".fill.fill.;suffix", record_id, - (record_id + UINT64_C(1442695040888963407)) % - UINT64_C(6364136223846793005)); - snprintf(data.ip, sizeof(data.ip), "%d.%d.%d.%d", - IP_PRINTF_ARG_HOST(record_id & 0xFFFFFFFF)); - event.obj_id = record_id; - event.event_type = 1; - - MDBX_val _session_id1_rec = {data.session_id1, strlen(data.session_id1)}; - MDBX_val _session_id2_rec = {data.session_id2, strlen(data.session_id2)}; - MDBX_val _ip_rec = {data.ip, strlen(data.ip)}; - MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)}; - MDBX_val _data_rec = {&data, offsetof(session_data_t, fill) + - (rand() % sizeof(data.fill))}; - MDBX_val _event_rec = {&event, sizeof(event)}; - - uint64_t start = getClockUs(); - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); - MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); - MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); - MDBX_CHECK(mdbx_put(txn, dbi_session, &_obj_id_rec, &_data_rec, - MDBX_NOOVERWRITE | MDBX_NODUPDATA)); - MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id1_rec, &_obj_id_rec, - MDBX_NOOVERWRITE | MDBX_NODUPDATA)); - MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id2_rec, &_obj_id_rec, - MDBX_NOOVERWRITE | MDBX_NODUPDATA)); - MDBX_CHECK(mdbx_put(txn, dbi_ip, &_ip_rec, &_obj_id_rec, 0)); - MDBX_CHECK(mdbx_put(txn, dbi_event, &_event_rec, &_obj_id_rec, 0)); - MDBX_CHECK(mdbx_txn_commit(txn)); - - mdbx_data_size += (_data_rec.iov_len + _obj_id_rec.iov_len * 4); - mdbx_key_size += - (_obj_id_rec.iov_len + _session_id1_rec.iov_len + - _session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len); - - // transaction commit - mdbx_add_count++; - mdbx_add_time += (getClockUs() - start); -} - -static void delete_record(int64_t record_id) { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - event_data_t event; - MDBX_txn *txn; - - // transaction init - uint64_t start = getClockUs(); - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - // open database in read-write mode - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); - MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); - MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); - // put data - MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)}; - MDBX_val _data_rec; - // get data - MDBX_CHECK(mdbx_get(txn, dbi_session, &_obj_id_rec, &_data_rec)); - session_data_t *data = (session_data_t *)_data_rec.iov_base; - - MDBX_val _session_id1_rec = {data->session_id1, strlen(data->session_id1)}; - MDBX_val _session_id2_rec = {data->session_id2, strlen(data->session_id2)}; - MDBX_val _ip_rec = {data->ip, strlen(data->ip)}; - MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id1_rec, NULL)); - MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id2_rec, NULL)); - MDBX_CHECK(mdbx_del(txn, dbi_ip, &_ip_rec, NULL)); - event.obj_id = record_id; - event.event_type = 1; - MDBX_val _event_rec = {&event, sizeof(event)}; - MDBX_CHECK(mdbx_del(txn, dbi_event, &_event_rec, NULL)); - MDBX_CHECK(mdbx_del(txn, dbi_session, &_obj_id_rec, NULL)); - - mdbx_data_size -= (_data_rec.iov_len + _obj_id_rec.iov_len * 4); - mdbx_key_size -= - (_obj_id_rec.iov_len + _session_id1_rec.iov_len + - _session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len); - - // transaction commit - MDBX_CHECK(mdbx_txn_commit(txn)); - mdbx_del_count++; - mdbx_del_time += (getClockUs() - start); -} - -static void db_disconnect() { - mdbx_env_close(env); - printf("Connection closed\n"); -} - -static void get_db_stat(const char *db, int64_t *ms_branch_pages, - int64_t *ms_leaf_pages) { - MDBX_txn *txn; - MDBX_stat stat; - MDBX_dbi dbi; - - MDBX_CHECK(mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn)); - MDBX_CHECK(mdbx_dbi_open(txn, db, MDBX_CREATE, &dbi)); - MDBX_CHECK(mdbx_dbi_stat(txn, dbi, &stat, sizeof(stat))); - mdbx_txn_abort(txn); - printf("%15s | %15" PRIu64 " | %5u | %10" PRIu64 " | %10" PRIu64 - " | %11" PRIu64 " |\n", - db, stat.ms_branch_pages, stat.ms_depth, stat.ms_entries, - stat.ms_leaf_pages, stat.ms_overflow_pages); - (*ms_branch_pages) += stat.ms_branch_pages; - (*ms_leaf_pages) += stat.ms_leaf_pages; -} - -static void periodic_stat(void) { - int64_t ms_branch_pages = 0; - int64_t ms_leaf_pages = 0; - MDBX_stat mst; - MDBX_envinfo mei; - MDBX_CHECK(mdbx_env_stat(env, &mst, sizeof(mst))); - MDBX_CHECK(mdbx_env_info(env, &mei, sizeof(mei))); - printf("Environment Info\n"); - printf(" Pagesize: %u\n", mst.ms_psize); - if (mei.mi_geo.lower != mei.mi_geo.upper) { - printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64 - "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64 - "/-%" PRIu64 ")\n", - mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow, - mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize, - mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize, - mei.mi_geo.shrink / mst.ms_psize); - printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", - mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); - } else { - printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", - mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); - } - printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n", - mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize); - printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1); - printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid); - printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n", - mei.mi_latter_reader_txnid, - mei.mi_latter_reader_txnid - mei.mi_recent_txnid); - printf(" Max readers: %u\n", mei.mi_maxreaders); - printf(" Number of readers used: %u\n", mei.mi_numreaders); - - printf(" Name | ms_branch_pages | depth | entries | leaf_pages " - "| overf_pages |\n"); - get_db_stat("session", &ms_branch_pages, &ms_leaf_pages); - get_db_stat("session_id", &ms_branch_pages, &ms_leaf_pages); - get_db_stat("event", &ms_branch_pages, &ms_leaf_pages); - get_db_stat("ip", &ms_branch_pages, &ms_leaf_pages); - printf("%15s | %15" PRIu64 " | %5s | %10s | %10" PRIu64 " | %11s |\n", "", - ms_branch_pages, "", "", ms_leaf_pages, ""); - - static int64_t prev_add_count; - static int64_t prev_del_count; - static uint64_t prev_add_time; - static uint64_t prev_del_time; - static int64_t t = -1; - if (t > 0) { - int64_t delta = (getClockUs() - t); - printf("CPS: add %" PRIu64 ", delete %" PRIu64 - ", items processed - %" PRIu64 "K data=%" PRIu64 "K key=%" PRIu64 - "K\n", - (mdbx_add_count - prev_add_count) * 1000000 / delta, - (mdbx_del_count - prev_del_count) * 1000000 / delta, obj_id / 1024, - mdbx_data_size / 1024, mdbx_key_size / 1024); - printf("usage data=%" PRIu64 "%%", - ((mdbx_data_size + mdbx_key_size) * 100) / - ((ms_leaf_pages + ms_branch_pages) * 4096)); - if (prev_add_time != mdbx_add_time) { - printf(" Add : %" PRIu64 " c/s", (mdbx_add_count - prev_add_count) * - 1000000 / - (mdbx_add_time - prev_add_time)); - } - if (prev_del_time != mdbx_del_time) { - printf(" Del : %" PRIu64 " c/s", (mdbx_del_count - prev_del_count) * - 1000000 / - (mdbx_del_time - prev_del_time)); - } - if (mdbx_add_time) { - printf(" tAdd : %" PRIu64 " c/s", - mdbx_add_count * 1000000 / mdbx_add_time); - } - if (mdbx_del_time) { - printf(" tDel : %" PRIu64 " c/s", - mdbx_del_count * 1000000 / mdbx_del_time); - } - puts(""); - } - t = getClockUs(); - prev_add_count = mdbx_add_count; - prev_del_count = mdbx_del_count; - prev_add_time = mdbx_add_time; - prev_del_time = mdbx_del_time; -} - -// static void periodic_add_rec() { -// for (int i = 0; i < 10240; i++) { -// if (ids_count <= REC_COUNT) { -// int64_t id = obj_id++; -// create_record(id); -// add_id_to_pool(id); -// } -// if (ids_count > REC_COUNT) { -// int64_t id = get_id_from_pool(); -// delete_record(id); -// } -// } -// periodic_stat(); -//} - -int main(int argc, char **argv) { - (void)argc; - (void)argv; - - char filename[PATH_MAX]; - int i; - - mkdir(opt_db_path, 0775); - - strcpy(filename, opt_db_path); - strcat(filename, "/mdbx.dat"); - remove(filename); - - strcpy(filename, opt_db_path); - strcat(filename, "/mdbx.lck"); - remove(filename); - - puts("Open DB..."); - db_connect(); - puts("Create data..."); - int64_t t = getClockUs(); - for (i = 0; i < REC_COUNT; i++) { - int64_t id = obj_id++; - create_record(id); - add_id_to_pool(id); - if (i % 1000 == 0) { - int64_t now = getClockUs(); - if ((now - t) > 1000000L) { - periodic_stat(); - t = now; - } - } - } - periodic_stat(); - while (1) { - int i; - for (i = 0; i < 1000; i++) { - int64_t id = obj_id++; - create_record(id); - add_id_to_pool(id); - id = get_id_from_pool(); - delete_record(id); - } - // for (i = 0; i < 50; i++) { - // int64_t id = obj_id++; - // create_record(id); - // add_id_to_pool(id); - // } - // int64_t id = obj_id++; - // create_record(id); - // add_id_to_pool(id); - int64_t now = getClockUs(); - if ((now - t) > 10000000L) { - periodic_stat(); - t = now; - } - } - db_disconnect(); - return 0; -} diff --git a/src/contrib/db/libmdbx/test/test.cc b/src/contrib/db/libmdbx/test/test.cc deleted file mode 100644 index 806e0b3..0000000 --- a/src/contrib/db/libmdbx/test/test.cc +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" - -const char *testcase2str(const actor_testcase testcase) { - switch (testcase) { - default: - assert(false); - return "?!"; - case ac_none: - return "none"; - case ac_hill: - return "hill"; - case ac_deadread: - return "deadread"; - case ac_deadwrite: - return "deadwrite"; - case ac_jitter: - return "jitter"; - case ac_try: - return "try"; - case ac_copy: - return "copy"; - case ac_append: - return "append"; - case ac_ttl: - return "ttl"; - case ac_nested: - return "nested"; - } -} - -const char *status2str(actor_status status) { - switch (status) { - default: - assert(false); - return "?!"; - case as_debuging: - return "debuging"; - case as_running: - return "running"; - case as_successful: - return "successful"; - case as_killed: - return "killed"; - case as_failed: - return "failed"; - case as_coredump: - return "coredump"; - } -} - -const char *keygencase2str(const keygen_case keycase) { - switch (keycase) { - default: - assert(false); - return "?!"; - case kc_random: - return "random"; - case kc_dashes: - return "dashes"; - case kc_custom: - return "custom"; - } -} - -//----------------------------------------------------------------------------- - -int testcase::oom_callback(MDBX_env *env, mdbx_pid_t pid, mdbx_tid_t tid, - uint64_t txn, unsigned gap, size_t space, - int retry) { - - testcase *self = (testcase *)mdbx_env_get_userctx(env); - - if (retry == 0) - log_notice("oom_callback: waitfor pid %u, thread %" PRIuPTR - ", txn #%" PRIu64 ", gap %d, scape %zu", - pid, (size_t)tid, txn, gap, space); - - if (self->should_continue(true)) { - osal_yield(); - if (retry > 0) - osal_udelay(retry * 100); - return 0 /* always retry */; - } - - return -1; -} - -void testcase::db_prepare() { - log_trace(">> db_prepare"); - assert(!db_guard); - - MDBX_env *env = nullptr; - int rc = mdbx_env_create(&env); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_create()", rc); - - assert(env != nullptr); - db_guard.reset(env); - - rc = mdbx_env_set_userctx(env, this); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_userctx()", rc); - - rc = mdbx_env_set_maxreaders(env, config.params.max_readers); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_maxreaders()", rc); - - rc = mdbx_env_set_maxdbs(env, config.params.max_tables); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_maxdbs()", rc); - - rc = mdbx_env_set_oomfunc(env, testcase::oom_callback); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_oomfunc()", rc); - - rc = mdbx_env_set_geometry( - env, config.params.size_lower, config.params.size_now, - config.params.size_upper, config.params.growth_step, - config.params.shrink_threshold, config.params.pagesize); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_mapsize()", rc); - - log_trace("<< db_prepare"); -} - -void testcase::db_open() { - log_trace(">> db_open"); - - if (!db_guard) - db_prepare(); - - jitter_delay(true); - int rc = mdbx_env_open(db_guard.get(), config.params.pathname_db.c_str(), - (unsigned)config.params.mode_flags, 0640); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_open()", rc); - - log_trace("<< db_open"); -} - -void testcase::db_close() { - log_trace(">> db_close"); - cursor_guard.reset(); - txn_guard.reset(); - db_guard.reset(); - log_trace("<< db_close"); -} - -void testcase::txn_begin(bool readonly, unsigned flags) { - assert((flags & MDBX_RDONLY) == 0); - log_trace(">> txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", - flags); - assert(!txn_guard); - - MDBX_txn *txn = nullptr; - int rc = mdbx_txn_begin(db_guard.get(), nullptr, - readonly ? flags | MDBX_RDONLY : flags, &txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_begin()", rc); - txn_guard.reset(txn); - - log_trace("<< txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", - flags); -} - -int testcase::breakable_commit() { - int rc = MDBX_SUCCESS; - log_trace(">> txn_commit"); - assert(txn_guard); - - MDBX_txn *txn = txn_guard.release(); - txn_inject_writefault(txn); - int err = mdbx_txn_commit(txn); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - rc = err; - err = mdbx_txn_abort(txn); - if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH && - err != MDBX_BAD_TXN)) - failure_perror("mdbx_txn_abort()", err); - } else - failure_perror("mdbx_txn_commit()", err); - } - - log_trace("<< txn_commit: %s", rc ? "failed" : "Ok"); - return rc; -} - -unsigned testcase::txn_underutilization_x256(MDBX_txn *txn) const { - if (txn) { - MDBX_txn_info info; - int err = mdbx_txn_info(txn, &info, false); - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_txn_info()", err); - const size_t left = size_t(info.txn_space_leftover); - const size_t total = - size_t(info.txn_space_leftover) + size_t(info.txn_space_dirty); - return (unsigned)(left / (total >> 8)); - } - return 0; -} - -void testcase::txn_end(bool abort) { - log_trace(">> txn_end(%s)", abort ? "abort" : "commit"); - assert(txn_guard); - - MDBX_txn *txn = txn_guard.release(); - if (abort) { - int err = mdbx_txn_abort(txn); - if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH && - err != MDBX_BAD_TXN)) - failure_perror("mdbx_txn_abort()", err); - } else { - txn_inject_writefault(txn); - int err = mdbx_txn_commit(txn); - if (unlikely(err != MDBX_SUCCESS)) - failure_perror("mdbx_txn_commit()", err); - } - - log_trace("<< txn_end(%s)", abort ? "abort" : "commit"); -} - -void testcase::cursor_open(MDBX_dbi handle) { - log_trace(">> cursor_open(%u)", handle); - assert(!cursor_guard); - assert(txn_guard); - - MDBX_cursor *cursor = nullptr; - int rc = mdbx_cursor_open(txn_guard.get(), handle, &cursor); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_cursor_open()", rc); - cursor_guard.reset(cursor); - - log_trace("<< cursor_open(%u)", handle); -} - -void testcase::cursor_close() { - log_trace(">> cursor_close()"); - assert(cursor_guard); - MDBX_cursor *cursor = cursor_guard.release(); - mdbx_cursor_close(cursor); - log_trace("<< cursor_close()"); -} - -int testcase::breakable_restart() { - int rc = MDBX_SUCCESS; - if (txn_guard) - rc = breakable_commit(); - if (cursor_guard) - cursor_close(); - txn_begin(false, 0); - return rc; -} - -void testcase::txn_restart(bool abort, bool readonly, unsigned flags) { - if (txn_guard) - txn_end(abort); - if (cursor_guard) - cursor_close(); - txn_begin(readonly, flags); -} - -void testcase::txn_inject_writefault(void) { - if (txn_guard) - txn_inject_writefault(txn_guard.get()); -} - -void testcase::txn_inject_writefault(MDBX_txn *txn) { - if (config.params.inject_writefaultn && txn) { - if (config.params.inject_writefaultn <= nops_completed && - (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) { - log_verbose( - "== txn_inject_writefault(): got %u nops or more, inject FAULT", - config.params.inject_writefaultn); - log_flush(); -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - TerminateProcess(GetCurrentProcess(), 42); -#else - raise(SIGKILL); -#endif - } - } -} - -bool testcase::wait4start() { - if (config.wait4id) { - log_trace(">> wait4start(%u)", config.wait4id); - assert(!global::singlemode); - int rc = osal_waitfor(config.wait4id); - if (rc) { - log_trace("<< wait4start(%u), failed %s", config.wait4id, - test_strerror(rc)); - return false; - } - } else { - log_trace("== skip wait4start: not needed"); - } - - if (config.params.delaystart) { - int rc = osal_delay(config.params.delaystart); - if (rc) { - log_trace("<< delay(%u), failed %s", config.params.delaystart, - test_strerror(rc)); - return false; - } - } else { - log_trace("== skip delay: not needed"); - } - - return true; -} - -void testcase::kick_progress(bool active) const { - if (!global::config::progress_indicator) - return; - logging::progress_canary(active); -} - -void testcase::report(size_t nops_done) { - assert(nops_done > 0); - if (!nops_done) - return; - - nops_completed += nops_done; - log_debug("== complete +%" PRIuPTR " iteration, total %" PRIuPTR " done", - nops_done, nops_completed); - - kick_progress(true); - - if (config.signal_nops && !signalled && - config.signal_nops <= nops_completed) { - log_trace(">> signal(n-ops %" PRIuPTR ")", nops_completed); - if (!global::singlemode) - osal_broadcast(config.actor_id); - signalled = true; - log_trace("<< signal(n-ops %" PRIuPTR ")", nops_completed); - } -} - -void testcase::signal() { - if (!signalled) { - log_trace(">> signal(forced)"); - if (!global::singlemode) - osal_broadcast(config.actor_id); - signalled = true; - log_trace("<< signal(forced)"); - } -} - -bool testcase::setup() { - db_prepare(); - if (!wait4start()) - return false; - - start_timestamp = chrono::now_motonic(); - nops_completed = 0; - return true; -} - -bool testcase::teardown() { - log_trace(">> testcase::teardown"); - signal(); - db_close(); - log_trace("<< testcase::teardown"); - return true; -} - -bool testcase::should_continue(bool check_timeout_only) const { - bool result = true; - - if (config.params.test_duration) { - chrono::time since; - since.fixedpoint = - chrono::now_motonic().fixedpoint - start_timestamp.fixedpoint; - if (since.seconds() >= config.params.test_duration) - result = false; - } - - if (!check_timeout_only && config.params.test_nops && - nops_completed >= config.params.test_nops) - result = false; - - if (result) - kick_progress(false); - - return result; -} - -void testcase::fetch_canary() { - mdbx_canary canary_now; - log_trace(">> fetch_canary"); - - int rc = mdbx_canary_get(txn_guard.get(), &canary_now); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_canary_get()", rc); - - if (canary_now.v < last.canary.v) - failure("fetch_canary: %" PRIu64 "(canary-now.v) < %" PRIu64 - "(canary-last.v)", - canary_now.v, last.canary.v); - if (canary_now.y < last.canary.y) - failure("fetch_canary: %" PRIu64 "(canary-now.y) < %" PRIu64 - "(canary-last.y)", - canary_now.y, last.canary.y); - - last.canary = canary_now; - log_trace("<< fetch_canary: db-sequence %" PRIu64 - ", db-sequence.txnid %" PRIu64, - last.canary.y, last.canary.v); -} - -void testcase::update_canary(uint64_t increment) { - mdbx_canary canary_now = last.canary; - - log_trace(">> update_canary: sequence %" PRIu64 " += %" PRIu64, canary_now.y, - increment); - canary_now.y += increment; - - int rc = mdbx_canary_put(txn_guard.get(), &canary_now); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_canary_put()", rc); - - log_trace("<< update_canary: sequence = %" PRIu64, canary_now.y); -} - -int testcase::db_open__begin__table_create_open_clean(MDBX_dbi &handle) { - db_open(); - - int err, retry_left = 42; - for (;;) { - txn_begin(false); - handle = db_table_open(true); - db_table_clear(handle); - err = breakable_commit(); - if (likely(err == MDBX_SUCCESS)) { - txn_begin(false); - return MDBX_SUCCESS; - } - if (--retry_left == 0) - break; - jitter_delay(true); - } - log_notice("db_begin_table_create_open_clean: bailout due '%s'", - mdbx_strerror(err)); - return err; -} - -MDBX_dbi testcase::db_table_open(bool create) { - log_trace(">> testcase::db_table_create"); - - char tablename_buf[16]; - const char *tablename = nullptr; - if (config.space_id) { - int rc = snprintf(tablename_buf, sizeof(tablename_buf), "TBL%04u", - config.space_id); - if (rc < 4 || rc >= (int)sizeof(tablename_buf) - 1) - failure("snprintf(tablename): %d", rc); - tablename = tablename_buf; - } - log_debug("use %s table", tablename ? tablename : "MAINDB"); - - MDBX_dbi handle = 0; - int rc = mdbx_dbi_open(txn_guard.get(), tablename, - (create ? MDBX_CREATE : 0) | config.params.table_flags, - &handle); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_dbi_open()", rc); - - log_trace("<< testcase::db_table_create, handle %u", handle); - return handle; -} - -void testcase::db_table_drop(MDBX_dbi handle) { - log_trace(">> testcase::db_table_drop, handle %u", handle); - - if (config.params.drop_table) { - int rc = mdbx_drop(txn_guard.get(), handle, true); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_drop(delete=true)", rc); - log_trace("<< testcase::db_table_drop"); - } else { - log_trace("<< testcase::db_table_drop: not needed"); - } -} - -void testcase::db_table_clear(MDBX_dbi handle, MDBX_txn *txn) { - log_trace(">> testcase::db_table_clear, handle %u", handle); - int rc = mdbx_drop(txn ? txn : txn_guard.get(), handle, false); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_drop(delete=false)", rc); - log_trace("<< testcase::db_table_clear"); -} - -void testcase::db_table_close(MDBX_dbi handle) { - log_trace(">> testcase::db_table_close, handle %u", handle); - assert(!txn_guard); - int rc = mdbx_dbi_close(db_guard.get(), handle); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_dbi_close()", rc); - log_trace("<< testcase::db_table_close"); -} - -void testcase::checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check, - MDBX_val expected_valued) { - MDBX_val actual_value = expected_valued; - int rc = mdbx_get_nearest(txn_guard.get(), handle, &key2check, &actual_value); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror(step, rc); - if (!is_samedata(&actual_value, &expected_valued)) - failure("%s data mismatch", step); -} - -//----------------------------------------------------------------------------- - -bool test_execute(const actor_config &config_const) { - const mdbx_pid_t pid = osal_getpid(); - actor_config config = config_const; - - if (global::singlemode) { - logging::setup(format("single_%s", testcase2str(config.testcase))); - } else { - logging::setup((logging::loglevel)config.params.loglevel, - format("child_%u.%u", config.actor_id, config.space_id)); - log_trace(">> wait4barrier"); - osal_wait4barrier(); - log_trace("<< wait4barrier"); - } - - try { - std::unique_ptr test; - switch (config.testcase) { - case ac_hill: - test.reset(new testcase_hill(config, pid)); - break; - case ac_deadread: - test.reset(new testcase_deadread(config, pid)); - break; - case ac_deadwrite: - test.reset(new testcase_deadwrite(config, pid)); - break; - case ac_jitter: - test.reset(new testcase_jitter(config, pid)); - break; - case ac_try: - test.reset(new testcase_try(config, pid)); - break; - case ac_copy: - test.reset(new testcase_copy(config, pid)); - break; - case ac_append: - test.reset(new testcase_append(config, pid)); - break; - case ac_ttl: - test.reset(new testcase_ttl(config, pid)); - break; - case ac_nested: - test.reset(new testcase_nested(config, pid)); - break; - default: - test.reset(new testcase(config, pid)); - break; - } - - size_t iter = 0; - do { - iter++; - if (!test->setup()) { - log_notice("test setup failed"); - return false; - } - if (!test->run()) { - log_notice("test failed"); - return false; - } - if (!test->teardown()) { - log_notice("test teardown failed"); - return false; - } - - if (config.params.nrepeat == 1) - log_verbose("test successed"); - else { - if (config.params.nrepeat) - log_verbose("test successed (iteration %zi of %zi)", iter, - size_t(config.params.nrepeat)); - else - log_verbose("test successed (iteration %zi)", iter); - config.params.keygen.seed += INT32_C(0xA4F4D37B); - } - - } while (config.params.nrepeat == 0 || iter < config.params.nrepeat); - return true; - } catch (const std::exception &pipets) { - failure("***** Exception: %s *****", pipets.what()); - return false; - } -} - -//----------------------------------------------------------------------------- - -int testcase::insert(const keygen::buffer &akey, const keygen::buffer &adata, - unsigned flags) { - int err = mdbx_put(txn_guard.get(), dbi, &akey->value, &adata->value, flags); - if (err == MDBX_SUCCESS && config.params.speculum) { - const auto S_key = S(akey); - const auto S_data = S(adata); - const bool inserted = speculum.emplace(S_key, S_data).second; - assert(inserted); - (void)inserted; - } - return err; -} - -int testcase::replace(const keygen::buffer &akey, - const keygen::buffer &new_data, - const keygen::buffer &old_data, unsigned flags) { - if (config.params.speculum) { - const auto S_key = S(akey); - const auto S_old = S(old_data); - const auto S_new = S(new_data); - const auto removed = speculum.erase(SET::key_type(S_key, S_old)); - assert(removed == 1); - (void)removed; - const bool inserted = speculum.emplace(S_key, S_new).second; - assert(inserted); - (void)inserted; - } - return mdbx_replace(txn_guard.get(), dbi, &akey->value, &new_data->value, - &old_data->value, flags); -} - -int testcase::remove(const keygen::buffer &akey, const keygen::buffer &adata) { - if (config.params.speculum) { - const auto S_key = S(akey); - const auto S_data = S(adata); - const auto removed = speculum.erase(SET::key_type(S_key, S_data)); - assert(removed == 1); - (void)removed; - } - return mdbx_del(txn_guard.get(), dbi, &akey->value, &adata->value); -} - -bool testcase::speculum_verify() const { - if (!config.params.speculum) - return true; - - char dump_key[128], dump_value[128]; - char dump_mkey[128], dump_mvalue[128]; - - MDBX_cursor *cursor; - int err = mdbx_cursor_open(txn_guard.get(), dbi, &cursor); - if (err != MDBX_SUCCESS) - failure_perror("mdbx_cursor_open()", err); - - bool rc = true; - MDBX_val akey, avalue; - MDBX_val mkey, mvalue; - err = mdbx_cursor_get(cursor, &akey, &avalue, MDBX_FIRST); - - assert(std::is_sorted(speculum.cbegin(), speculum.cend(), ItemCompare(this))); - auto it = speculum.cbegin(); - while (true) { - if (err != MDBX_SUCCESS) { - akey.iov_len = avalue.iov_len = 0; - akey.iov_base = avalue.iov_base = nullptr; - } - const auto S_key = S(akey); - const auto S_data = S(avalue); - if (it != speculum.cend()) { - mkey.iov_base = (void *)it->first.c_str(); - mkey.iov_len = it->first.size(); - mvalue.iov_base = (void *)it->second.c_str(); - mvalue.iov_len = it->second.size(); - } - if (err == MDBX_SUCCESS && it != speculum.cend() && S_key == it->first && - S_data == it->second) { - ++it; - err = mdbx_cursor_get(cursor, &akey, &avalue, MDBX_NEXT); - } else if (err == MDBX_SUCCESS && - (it == speculum.cend() || S_key < it->first || - (S_key == it->first && S_data < it->second))) { - if (it != speculum.cend()) { - log_error("extra pair: db{%s, %s} < mi{%s, %s}", - mdbx_dump_val(&akey, dump_key, sizeof(dump_key)), - mdbx_dump_val(&avalue, dump_value, sizeof(dump_value)), - mdbx_dump_val(&mkey, dump_mkey, sizeof(dump_mkey)), - mdbx_dump_val(&mvalue, dump_mvalue, sizeof(dump_mvalue))); - } else { - log_error("extra pair: db{%s, %s} < mi.END", - mdbx_dump_val(&akey, dump_key, sizeof(dump_key)), - mdbx_dump_val(&avalue, dump_value, sizeof(dump_value))); - } - err = mdbx_cursor_get(cursor, &akey, &avalue, MDBX_NEXT); - rc = false; - } else if (it != speculum.cend() && - (err == MDBX_NOTFOUND || S_key > it->first || - (S_key == it->first && S_data > it->second))) { - if (err == MDBX_NOTFOUND) { - log_error("lost pair: db.END > mi{%s, %s}", - mdbx_dump_val(&mkey, dump_mkey, sizeof(dump_mkey)), - mdbx_dump_val(&mvalue, dump_mvalue, sizeof(dump_mvalue))); - } else { - log_error("lost pair: db{%s, %s} > mi{%s, %s}", - mdbx_dump_val(&akey, dump_key, sizeof(dump_key)), - mdbx_dump_val(&avalue, dump_value, sizeof(dump_value)), - mdbx_dump_val(&mkey, dump_mkey, sizeof(dump_mkey)), - mdbx_dump_val(&mvalue, dump_mvalue, sizeof(dump_mvalue))); - } - ++it; - rc = false; - } else if (err == MDBX_NOTFOUND && it == speculum.cend()) { - break; - } else if (err != MDBX_SUCCESS) { - failure_perror("mdbx_cursor_get()", err); - } else { - assert(!"WTF?"); - } - } - - mdbx_cursor_close(cursor); - return rc; -} diff --git a/src/contrib/db/libmdbx/test/test.h b/src/contrib/db/libmdbx/test/test.h deleted file mode 100644 index 178100e..0000000 --- a/src/contrib/db/libmdbx/test/test.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once - -#include "base.h" -#include "chrono.h" -#include "config.h" -#include "keygen.h" -#include "log.h" -#include "osal.h" -#include "utils.h" - -#include -#include -#include -#include - -#ifndef HAVE_cxx17_std_string_view -#if __cplusplus >= 201703L && __has_include() -#include -#define HAVE_cxx17_std_string_view 1 -#else -#define HAVE_cxx17_std_string_view 0 -#endif -#endif /* HAVE_cxx17_std_string_view */ - -#if HAVE_cxx17_std_string_view -#include -#endif - -bool test_execute(const actor_config &config); -std::string thunk_param(const actor_config &config); -void testcase_setup(const char *casename, actor_params ¶ms, - unsigned &last_space_id); -void configure_actor(unsigned &last_space_id, const actor_testcase testcase, - const char *space_id_cstr, const actor_params ¶ms); -void keycase_setup(const char *casename, actor_params ¶ms); - -namespace global { - -extern const char thunk_param_prefix[]; -extern std::vector actors; -extern std::unordered_map events; -extern std::unordered_map pid2actor; -extern std::set databases; -extern unsigned nactors; -extern chrono::time start_motonic; -extern chrono::time deadline_motonic; -extern bool singlemode; - -namespace config { -extern unsigned timeout_duration_seconds; -extern bool dump_config; -extern bool cleanup_before; -extern bool cleanup_after; -extern bool failfast; -extern bool progress_indicator; -extern bool console_mode; -} /* namespace config */ - -} /* namespace global */ - -//----------------------------------------------------------------------------- - -struct db_deleter /* : public std::unary_function */ { - void operator()(MDBX_env *env) const { mdbx_env_close(env); } -}; - -struct txn_deleter /* : public std::unary_function */ { - void operator()(MDBX_txn *txn) const { - int rc = mdbx_txn_abort(txn); - if (rc) - log_trouble(__func__, "mdbx_txn_abort()", rc); - } -}; - -struct cursor_deleter /* : public std::unary_function */ { - void operator()(MDBX_cursor *cursor) const { mdbx_cursor_close(cursor); } -}; - -typedef std::unique_ptr scoped_db_guard; -typedef std::unique_ptr scoped_txn_guard; -typedef std::unique_ptr scoped_cursor_guard; - -//----------------------------------------------------------------------------- - -class testcase { -protected: -#if HAVE_cxx17_std_string_view - using data_view = std::string_view; -#else - using data_view = std::string; -#endif - static inline data_view S(const MDBX_val &v) { - return data_view(static_cast(v.iov_base), v.iov_len); - } - static inline data_view S(const keygen::buffer &b) { return S(b->value); } - - using Item = std::pair; - struct ItemCompare { - const testcase *context; - ItemCompare(const testcase *owner) : context(owner) {} - - bool operator()(const Item &a, const Item &b) const { - MDBX_val va, vb; - va.iov_base = (void *)a.first.data(); - va.iov_len = a.first.size(); - vb.iov_base = (void *)b.first.data(); - vb.iov_len = b.first.size(); - int cmp = mdbx_cmp(context->txn_guard.get(), context->dbi, &va, &vb); - if (cmp == 0 && - (context->config.params.table_flags & MDBX_DUPSORT) != 0) { - va.iov_base = (void *)a.second.data(); - va.iov_len = a.second.size(); - vb.iov_base = (void *)b.second.data(); - vb.iov_len = b.second.size(); - cmp = mdbx_dcmp(context->txn_guard.get(), context->dbi, &va, &vb); - } - return cmp < 0; - } - }; - using SET = std::set; - - const actor_config &config; - const mdbx_pid_t pid; - - MDBX_dbi dbi; - scoped_db_guard db_guard; - scoped_txn_guard txn_guard; - scoped_cursor_guard cursor_guard; - bool signalled; - - size_t nops_completed; - chrono::time start_timestamp; - keygen::buffer key; - keygen::buffer data; - keygen::maker keyvalue_maker; - - struct { - mdbx_canary canary; - } last; - - SET speculum; - bool speculum_verify() const; - int insert(const keygen::buffer &akey, const keygen::buffer &adata, - unsigned flags); - int replace(const keygen::buffer &akey, const keygen::buffer &new_value, - const keygen::buffer &old_value, unsigned flags); - int remove(const keygen::buffer &akey, const keygen::buffer &adata); - - static int oom_callback(MDBX_env *env, mdbx_pid_t pid, mdbx_tid_t tid, - uint64_t txn, unsigned gap, size_t space, int retry); - - bool is_nested_txn_available() const { - return (config.params.mode_flags & MDBX_WRITEMAP) == 0; - } - void kick_progress(bool active) const; - void db_prepare(); - void db_open(); - void db_close(); - void txn_begin(bool readonly, unsigned flags = 0); - int breakable_commit(); - void txn_end(bool abort); - int breakable_restart(); - void txn_restart(bool abort, bool readonly, unsigned flags = 0); - void cursor_open(MDBX_dbi handle); - void cursor_close(); - void txn_inject_writefault(void); - void txn_inject_writefault(MDBX_txn *txn); - void fetch_canary(); - void update_canary(uint64_t increment); - void checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check, - MDBX_val expected_valued); - unsigned txn_underutilization_x256(MDBX_txn *txn) const; - - MDBX_dbi db_table_open(bool create); - void db_table_drop(MDBX_dbi handle); - void db_table_clear(MDBX_dbi handle, MDBX_txn *txn = nullptr); - void db_table_close(MDBX_dbi handle); - int db_open__begin__table_create_open_clean(MDBX_dbi &handle); - - bool wait4start(); - void report(size_t nops_done); - void signal(); - bool should_continue(bool check_timeout_only = false) const; - - void generate_pair(const keygen::serial_t serial, keygen::buffer &out_key, - keygen::buffer &out_value, keygen::serial_t data_age = 0) { - keyvalue_maker.pair(serial, out_key, out_value, data_age); - } - - void generate_pair(const keygen::serial_t serial, - keygen::serial_t data_age = 0) { - generate_pair(serial, key, data, data_age); - } - - bool mode_readonly() const { - return (config.params.mode_flags & MDBX_RDONLY) ? true : false; - } - -public: - testcase(const actor_config &config, const mdbx_pid_t pid) - : config(config), pid(pid), signalled(false), nops_completed(0), - speculum(ItemCompare(this)) { - start_timestamp.reset(); - memset(&last, 0, sizeof(last)); - } - - virtual bool setup(); - virtual bool run() { return true; } - virtual bool teardown(); - virtual ~testcase() {} -}; - -class testcase_ttl : public testcase { -public: - testcase_ttl(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_hill : public testcase { - using inherited = testcase; - SET speculum_commited; - -public: - testcase_hill(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid), speculum_commited(ItemCompare(this)) {} - bool run() override; -}; - -class testcase_append : public testcase { -public: - testcase_append(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_deadread : public testcase { -public: - testcase_deadread(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_deadwrite : public testcase { -public: - testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_jitter : public testcase { -public: - testcase_jitter(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_try : public testcase { -public: - testcase_try(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool run() override; -}; - -class testcase_copy : public testcase { - const std::string copy_pathname; - void copy_db(const bool with_compaction); - -public: - testcase_copy(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid), - copy_pathname(config.params.pathname_db + "-copy") {} - bool run() override; -}; - -class testcase_nested : public testcase { - using inherited = testcase; - using FIFO = std::deque>; - - uint64_t serial; - FIFO fifo; - std::stack> stack; - - bool trim_tail(unsigned window_width); - bool grow_head(unsigned head_count); - bool pop_txn(bool abort); - bool pop_txn() { - return pop_txn(inherited::is_nested_txn_available() ? flipcoin_x3() - : flipcoin_x2()); - } - void push_txn(); - bool stochastic_breakable_restart_with_nested(bool force_restart = false); - -public: - testcase_nested(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup() override; - bool run() override; - bool teardown() override; -}; diff --git a/src/contrib/db/libmdbx/test/try.cc b/src/contrib/db/libmdbx/test/try.cc deleted file mode 100644 index adb0113..0000000 --- a/src/contrib/db/libmdbx/test/try.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include "test.h" - -bool testcase_try::run() { - db_open(); - assert(!txn_guard); - - MDBX_txn *txn = nullptr; - MDBX_txn *txn2 = nullptr; - int rc = mdbx_txn_begin(db_guard.get(), nullptr, 0, &txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); - else { - rc = mdbx_txn_begin(db_guard.get(), nullptr, MDBX_TRYTXN, &txn2); - if (unlikely(rc != MDBX_BUSY)) - failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); - } - - txn_guard.reset(txn); - return true; -} diff --git a/src/contrib/db/libmdbx/test/ttl.cc b/src/contrib/db/libmdbx/test/ttl.cc deleted file mode 100644 index 782a8b4..0000000 --- a/src/contrib/db/libmdbx/test/ttl.cc +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" -#include -#include - -static unsigned edge2window(uint64_t edge, unsigned window_max) { - const double rnd = u64_to_double1(bleach64(edge)); - const unsigned window = window_max - std::lrint(std::pow(window_max, rnd)); - return window; -} - -static unsigned edge2count(uint64_t edge, unsigned count_max) { - const double rnd = u64_to_double1(prng64_map1_white(edge)); - const unsigned count = std::lrint(std::pow(count_max, rnd)); - return count; -} - -bool testcase_ttl::run() { - int err = db_open__begin__table_create_open_clean(dbi); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("ttl: bailout-prepare due '%s'", mdbx_strerror(err)); - return false; - } - - /* LY: теÑÑ‚ "ÑмулÑцией time-to-live": - * - организуетÑÑ "ÑкользÑщее окно", которое двигаетÑÑ Ð²Ð¿ÐµÑ€ÐµÐ´ вдоль - * чиÑловой оÑи каждую транзакцию. - * - по переднему краю "ÑкользÑщего окна" запиÑи добавлÑÑŽÑ‚ÑÑ Ð² таблицу, - * а по заднему удалÑÑŽÑ‚ÑÑ. - * - количеÑтво добавлÑемых/удалÑемых запиÑей пÑевдоÑлучайно завиÑит - * от номера транзакции, но Ñ ÑкÑпоненциальным раÑпределением. - * - размер "ÑкользÑщего окна" также пÑевдоÑлучайно завиÑит от номера - * транзакции Ñ "отрицательным" ÑкÑпоненциальным раÑпределением - * MAX_WIDTH - exp(rnd(N)), при уменьшении окна ÑдвигаетÑÑ Ð·Ð°Ð´Ð½Ð¸Ð¹ - * край и удалÑÑŽÑ‚ÑÑ Ð·Ð°Ð¿Ð¸Ñи позади него. - * - * Таким образом имитируетÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ таблицы Ñ TTL: запиÑи ÑтохаÑтичеÑки - * добавлÑÑŽÑ‚ÑÑ Ð¸ удалÑÑŽÑ‚ÑÑ, но изредка проиÑходÑÑ‚ маÑÑивные удалениÑ. - */ - - /* LY: Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ иÑпользуем подходÑщие параметры, которые не имеют - * здеÑÑŒ ÑмыÑла в первоначальном значении. */ - const unsigned window_max_lower = 333; - const unsigned count_max_lower = 333; - - const unsigned window_max = (config.params.batch_read > window_max_lower) - ? config.params.batch_read - : window_max_lower; - const unsigned count_max = (config.params.batch_write > count_max_lower) - ? config.params.batch_write - : count_max_lower; - log_verbose("ttl: using `batch_read` value %u for window_max", window_max); - log_verbose("ttl: using `batch_write` value %u for count_max", count_max); - - uint64_t seed = - prng64_map2_white(config.params.keygen.seed) + config.actor_id; - keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); - key = keygen::alloc(config.params.keylen_max); - data = keygen::alloc(config.params.datalen_max); - const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_NODUPDATA - : MDBX_NODUPDATA | MDBX_NOOVERWRITE; - - std::deque> fifo; - uint64_t serial = 0; - bool rc = false; - while (should_continue()) { - const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */; - - const unsigned window_width = - flipcoin_x4() ? 0 : edge2window(salt, window_max); - unsigned head_count = edge2count(salt, count_max); - log_debug("ttl: step #%zu (serial %" PRIu64 - ", window %u, count %u) salt %" PRIu64, - nops_completed, serial, window_width, head_count, salt); - - if (window_width) { - while (fifo.size() > window_width) { - uint64_t tail_serial = fifo.back().first; - const unsigned tail_count = fifo.back().second; - log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial, - tail_count); - fifo.pop_back(); - for (unsigned n = 0; n < tail_count; ++n) { - log_trace("ttl: remove-tail %" PRIu64, tail_serial); - generate_pair(tail_serial); - err = mdbx_del(txn_guard.get(), dbi, &key->value, &data->value); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("ttl: tail-bailout due '%s'", mdbx_strerror(err)); - goto bailout; - } - failure_perror("mdbx_del(tail)", err); - } - if (unlikely(!keyvalue_maker.increment(tail_serial, 1))) - failure("ttl: unexpected key-space overflow on the tail"); - } - } - } else { - log_trace("ttl: purge state"); - db_table_clear(dbi); - fifo.clear(); - } - - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("ttl: bailout at commit due '%s'", mdbx_strerror(err)); - break; - } - fifo.push_front(std::make_pair(serial, head_count)); - retry: - for (unsigned n = 0; n < head_count; ++n) { - log_trace("ttl: insert-head %" PRIu64, serial); - generate_pair(serial); - err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value, - insert_flags); - if (unlikely(err != MDBX_SUCCESS)) { - if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { - log_notice("ttl: head-insert skip due '%s'", mdbx_strerror(err)); - txn_restart(true, false); - serial = fifo.front().first; - fifo.front().second = head_count = n; - goto retry; - } - failure_perror("mdbx_put(head)", err); - } - - if (unlikely(!keyvalue_maker.increment(serial, 1))) { - log_notice("ttl: unexpected key-space overflow"); - goto bailout; - } - } - err = breakable_restart(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("ttl: head-commit skip due '%s'", mdbx_strerror(err)); - serial = fifo.front().first; - fifo.pop_front(); - } - - report(1); - rc = true; - } - -bailout: - txn_end(true); - if (dbi) { - if (config.params.drop_table && !mode_readonly()) { - txn_begin(false); - db_table_drop(dbi); - err = breakable_commit(); - if (unlikely(err != MDBX_SUCCESS)) { - log_notice("ttl: bailout-clean due '%s'", mdbx_strerror(err)); - return false; - } - } else - db_table_close(dbi); - } - return rc; -} diff --git a/src/contrib/db/libmdbx/test/utils.cc b/src/contrib/db/libmdbx/test/utils.cc deleted file mode 100644 index 311cf54..0000000 --- a/src/contrib/db/libmdbx/test/utils.cc +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#include "test.h" -#include -#if defined(HAVE_IEEE754_H) || __has_include() -#include -#endif -#if defined(__APPLE__) || defined(__MACH__) -#include -#endif /* defined(__APPLE__) || defined(__MACH__) */ - -std::string format(const char *fmt, ...) { - va_list ap, ones; - va_start(ap, fmt); - va_copy(ones, ap); -#ifdef _MSC_VER - int needed = _vscprintf(fmt, ap); -#else - int needed = vsnprintf(nullptr, 0, fmt, ap); -#endif - assert(needed >= 0); - va_end(ap); - std::string result; - result.reserve((size_t)needed + 1); - result.resize((size_t)needed, '\0'); - int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones); - assert(actual == needed); - (void)actual; - va_end(ones); - return result; -} - -std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) { - std::string result; - if (bytes > 0) { - const uint8_t *data = (const uint8_t *)ptr; - checksum.push(data, bytes); - result.reserve(bytes * 2); - const uint8_t *const end = data + bytes; - do { - char h = *data >> 4; - char l = *data & 15; - result.push_back((l < 10) ? l + '0' : l - 10 + 'a'); - result.push_back((h < 10) ? h + '0' : h - 10 + 'a'); - } while (++data < end); - } - assert(result.size() == bytes * 2); - return result; -} - -bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, - size_t bytes, simple_checksum &checksum) { - if (bytes * 2 != (size_t)(hex_end - hex_begin)) - return false; - - uint8_t *data = (uint8_t *)ptr; - for (const char *hex = hex_begin; hex != hex_end; hex += 2, ++data) { - unsigned l = hex[0], h = hex[1]; - - if (l >= '0' && l <= '9') - l = l - '0'; - else if (l >= 'A' && l <= 'F') - l = l - 'A' + 10; - else if (l >= 'a' && l <= 'f') - l = l - 'a' + 10; - else - return false; - - if (h >= '0' && h <= '9') - h = h - '0'; - else if (h >= 'A' && h <= 'F') - h = h - 'A' + 10; - else if (h >= 'a' && h <= 'f') - h = h - 'a' + 10; - else - return false; - - uint32_t c = l + (h << 4); - checksum.push(c); - *data = (uint8_t)c; - } - return true; -} - -bool is_samedata(const MDBX_val *a, const MDBX_val *b) { - return a->iov_len == b->iov_len && - memcmp(a->iov_base, b->iov_base, a->iov_len) == 0; -} - -//----------------------------------------------------------------------------- - -/* TODO: replace my 'libmera' from t1ha. */ -uint64_t entropy_ticks(void) { -#if defined(EMSCRIPTEN) - return (uint64_t)emscripten_get_now(); -#endif /* EMSCRIPTEN */ - -#if defined(__APPLE__) || defined(__MACH__) - return mach_absolute_time(); -#endif /* defined(__APPLE__) || defined(__MACH__) */ - -#if defined(__sun__) || defined(__sun) - return gethrtime(); -#endif /* __sun__ */ - -#if defined(__GNUC__) || defined(__clang__) - -#if defined(__ia64__) - uint64_t ticks; - __asm __volatile("mov %0=ar.itc" : "=r"(ticks)); - return ticks; -#elif defined(__hppa__) - uint64_t ticks; - __asm __volatile("mfctl 16, %0" : "=r"(ticks)); - return ticks; -#elif defined(__s390__) - uint64_t ticks; - __asm __volatile("stck 0(%0)" : : "a"(&(ticks)) : "memory", "cc"); - return ticks; -#elif defined(__alpha__) - uint64_t ticks; - __asm __volatile("rpcc %0" : "=r"(ticks)); - return ticks; -#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \ - defined(__sparc64) || defined(__sparc_v8plus__) || \ - defined(__sparc_v8plus) || defined(__sparc_v8plusa__) || \ - defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9) - - union { - uint64_t u64; - struct { -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - uint32_t h, l; -#else - uint32_t l, h; -#endif - } u32; - } cycles; - -#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || \ - defined(__sparc_v9__) || defined(__sparc_v8plus) || \ - defined(__sparc_v8plusa) || defined(__sparc_v9) - -#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || \ - defined(__sparc64__) || defined(__sparc64) - __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64)); -#else - __asm __volatile("rd %%tick, %1; srlx %1, 32, %0" - : "=r"(cycles.u32.h), "=r"(cycles.u32.l)); -#endif /* __sparc64__ */ - -#else - __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0" - : "=r"(cycles.u64) - : - : "%g1"); -#endif /* __sparc8plus__ || __sparc_v9__ */ - return cycles.u64; - -#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) || \ - defined(__powerpc64)) - uint64_t ticks; - __asm __volatile("mfspr %0, 268" : "=r"(ticks)); - return ticks; -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) || \ - defined(__ppc)) -#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul - uint64_t ticks; - __asm __volatile("mftb %0" : "=r"(ticks)); - *now = ticks; -#else - uint64_t ticks; - uint32_t low, high_before, high_after; - __asm __volatile("mftbu %0; mftb %1; mftbu %2" - : "=r"(high_before), "=r"(low), "=r"(high_after)); - ticks = (uint64_t)high_after << 32; - ticks |= low & /* zeroes if high part has changed */ - ~(high_before - high_after); -#endif -#elif (defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7)) && \ - !defined(MDBX_SAFE4QEMU) - uint64_t virtual_timer; - __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer)); - return virtual_timer; -#elif (defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8) || \ - defined(_M_ARM) - static uint32_t pmcntenset = 0x00425B00; - if (unlikely(pmcntenset == 0x00425B00)) { - uint32_t pmuseren; -#ifdef _M_ARM - pmuseren = _MoveFromCoprocessor(15, 0, 9, 14, 0); -#else - __asm("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren)); -#endif - if (1 & pmuseren /* Is it allowed for user mode code? */) { -#ifdef _M_ARM - pmcntenset = _MoveFromCoprocessor(15, 0, 9, 12, 1); -#else - __asm("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset)); -#endif - } else - pmcntenset = 0; - } - if (pmcntenset & 0x80000000ul /* Is it counting? */) { -#ifdef _M_ARM - return __rdpmccntr64(); -#else - uint32_t pmccntr; - __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); - return pmccntr; -#endif - } -#elif defined(__mips__) || defined(__mips) || defined(_R4000) - unsigned count; - __asm __volatile("rdhwr %0, $2" : "=r"(count)); - return count; -#endif /* arch selector */ -#endif /* __GNUC__ || __clang__ */ - -#if defined(__e2k__) || defined(__ia32__) - return __rdtsc(); -#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - LARGE_INTEGER PerformanceCount; - if (QueryPerformanceCounter(&PerformanceCount)) - return PerformanceCount.QuadPart; - return GetTickCount64(); -#else - struct timespec ts; -#if defined(CLOCK_MONOTONIC_COARSE) - clockid_t clk_id = CLOCK_MONOTONIC_COARSE; -#elif defined(CLOCK_MONOTONIC_RAW) - clockid_t clk_id = CLOCK_MONOTONIC_RAW; -#else - clockid_t clk_id = CLOCK_MONOTONIC; -#endif - int rc = clock_gettime(clk_id, &ts); - if (unlikely(rc)) - failure_perror("clock_gettime()", rc); - - return (((uint64_t)ts.tv_sec) << 32) + ts.tv_nsec; -#endif -} - -//----------------------------------------------------------------------------- - -uint64_t prng64_white(uint64_t &state) { - state = prng64_map2_careless(state); - return bleach64(state); -} - -uint32_t prng32(uint64_t &state) { - return (uint32_t)(prng64_careless(state) >> 32); -} - -void prng_fill(uint64_t &state, void *ptr, size_t bytes) { - while (bytes >= 4) { - *((uint32_t *)ptr) = prng32(state); - ptr = (uint32_t *)ptr + 1; - bytes -= 4; - } - - switch (bytes & 3) { - case 3: { - uint32_t u32 = prng32(state); - memcpy(ptr, &u32, 3); - } break; - case 2: - *((uint16_t *)ptr) = (uint16_t)prng32(state); - break; - case 1: - *((uint8_t *)ptr) = (uint8_t)prng32(state); - break; - case 0: - break; - } -} - -static __thread uint64_t prng_state; - -void prng_seed(uint64_t seed) { prng_state = bleach64(seed); } - -uint32_t prng32(void) { return prng32(prng_state); } - -uint64_t prng64(void) { return prng64_white(prng_state); } - -void prng_fill(void *ptr, size_t bytes) { prng_fill(prng_state, ptr, bytes); } - -uint64_t entropy_white() { return bleach64(entropy_ticks()); } - -double double_from_lower(uint64_t salt) { -#ifdef IEEE754_DOUBLE_BIAS - ieee754_double r; - r.ieee.negative = 0; - r.ieee.exponent = IEEE754_DOUBLE_BIAS; - r.ieee.mantissa0 = (unsigned)(salt >> 32); - r.ieee.mantissa1 = (unsigned)salt; - return r.d; -#else - const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; - const double scale = 1.0 / (double)top; - return (salt & top) * scale; -#endif -} - -double double_from_upper(uint64_t salt) { -#ifdef IEEE754_DOUBLE_BIAS - ieee754_double r; - r.ieee.negative = 0; - r.ieee.exponent = IEEE754_DOUBLE_BIAS; - salt >>= 64 - DBL_MANT_DIG; - r.ieee.mantissa0 = (unsigned)(salt >> 32); - r.ieee.mantissa1 = (unsigned)salt; - return r.d; -#else - const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; - const double scale = 1.0 / (double)top; - return (salt >> (64 - DBL_MANT_DIG)) * scale; -#endif -} - -bool flipcoin() { return bleach32((uint32_t)entropy_ticks()) & 1; } -bool flipcoin_x2() { return (bleach32((uint32_t)entropy_ticks()) & 3) == 0; } -bool flipcoin_x3() { return (bleach32((uint32_t)entropy_ticks()) & 7) == 0; } -bool flipcoin_x4() { return (bleach32((uint32_t)entropy_ticks()) & 15) == 0; } - -bool jitter(unsigned probability_percent) { - const uint32_t top = UINT32_MAX - UINT32_MAX % 100; - uint32_t dice, edge = (top) / 100 * probability_percent; - do - dice = bleach32((uint32_t)entropy_ticks()); - while (dice >= top); - return dice < edge; -} - -void jitter_delay(bool extra) { - unsigned dice = entropy_white() & 3; - if (dice == 0) { - log_trace("== jitter.no-delay"); - } else { - log_trace(">> jitter.delay: dice %u", dice); - do { - cpu_relax(); - memory_barrier(); - cpu_relax(); - if (dice > 1) { - osal_yield(); - cpu_relax(); - if (dice > 2) { - unsigned us = entropy_white() & - (extra ? 0xffff /* 656 ms */ : 0x3ff /* 1 ms */); - log_trace("== jitter.delay: %0.6f", us / 1000000.0); - osal_udelay(us); - } - } - } while (flipcoin()); - log_trace("<< jitter.delay: dice %u", dice); - } -} diff --git a/src/contrib/db/libmdbx/test/utils.h b/src/contrib/db/libmdbx/test/utils.h deleted file mode 100644 index 2a5a54d..0000000 --- a/src/contrib/db/libmdbx/test/utils.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2017-2019 Leonid Yuriev - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * . - */ - -#pragma once -#include "base.h" - -#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ - !defined(__ORDER_BIG_ENDIAN__) -#error __BYTE_ORDER__ should be defined. -#endif - -#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \ - __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ -#error Unsupported byte order. -#endif - -#if __GNUC_PREREQ(4, 4) || defined(__clang__) -#ifndef bswap64 -#define bswap64(v) __builtin_bswap64(v) -#endif -#ifndef bswap32 -#define bswap32(v) __builtin_bswap32(v) -#endif -#if (__GNUC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16)) && \ - !defined(bswap16) -#define bswap16(v) __builtin_bswap16(v) -#endif - -#elif defined(_MSC_VER) - -#if _MSC_FULL_VER < 190024215 -#pragma message( \ - "It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.") -#endif - -#define bswap64(v) _byteswap_uint64(v) -#define bswap32(v) _byteswap_ulong(v) -#define bswap16(v) _byteswap_ushort(v) -#define rot64(v, s) _rotr64(v, s) -#define rot32(v, s) _rotr(v, s) - -#if defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64) -#pragma intrinsic(_umul128) -#define mul_64x64_128(a, b, ph) _umul128(a, b, ph) -#pragma intrinsic(__umulh) -#define mul_64x64_high(a, b) __umulh(a, b) -#endif - -#if defined(_M_IX86) -#pragma intrinsic(__emulu) -#define mul_32x32_64(a, b) __emulu(a, b) -#elif defined(_M_ARM) -#define mul_32x32_64(a, b) _arm_umull(a, b) -#endif - -#endif /* compiler */ - -#ifndef bswap64 -#ifdef __bswap_64 -#define bswap64(v) __bswap_64(v) -#else -static __inline uint64_t bswap64(uint64_t v) { - return v << 56 | v >> 56 | ((v << 40) & UINT64_C(0x00ff000000000000)) | - ((v << 24) & UINT64_C(0x0000ff0000000000)) | - ((v << 8) & UINT64_C(0x000000ff00000000)) | - ((v >> 8) & UINT64_C(0x00000000ff0000000)) | - ((v >> 24) & UINT64_C(0x0000000000ff0000)) | - ((v >> 40) & UINT64_C(0x000000000000ff00)); -} -#endif -#endif /* bswap64 */ - -#ifndef bswap32 -#ifdef __bswap_32 -#define bswap32(v) __bswap_32(v) -#else -static __inline uint32_t bswap32(uint32_t v) { - return v << 24 | v >> 24 | ((v << 8) & UINT32_C(0x00ff0000)) | - ((v >> 8) & UINT32_C(0x0000ff00)); -} -#endif -#endif /* bswap32 */ - -#ifndef bswap16 -#ifdef __bswap_16 -#define bswap16(v) __bswap_16(v) -#else -static __inline uint16_t bswap16(uint16_t v) { return v << 8 | v >> 8; } -#endif -#endif /* bswap16 */ - -#define is_byteorder_le() (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define is_byteorder_be() (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - -#ifndef htole16 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe16(v) bswap16(v) -#define htole16(v) (v) -#define be16toh(v) bswap16(v) -#define le16toh(v) (v) -#else -#define htobe16(v) (v) -#define htole16(v) bswap16(v) -#define be16toh(v) (v) -#define le16toh(v) bswap16(v) -#endif -#endif /* htole16 */ - -#ifndef htole32 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe32(v) bswap32(v) -#define htole32(v) (v) -#define be32toh(v) bswap32(v) -#define le32toh(v) (v) -#else -#define htobe32(v) (v) -#define htole32(v) bswap32(v) -#define be32toh(v) (v) -#define le32toh(v) bswap32(v) -#endif -#endif /* htole32 */ - -#ifndef htole64 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe64(v) bswap64(v) -#define htole64(v) (v) -#define be64toh(v) bswap64(v) -#define le64toh(v) (v) -#else -#define htobe64(v) (v) -#define htole64(v) bswap_64(v) -#define be64toh(v) (v) -#define le64toh(v) bswap_64(v) -#endif -#endif /* htole64 */ - -namespace unaligned { - -template static __inline T load(const void *ptr) { -#if defined(_MSC_VER) && \ - (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) - return *(const T __unaligned *)ptr; -#elif MDBX_UNALIGNED_OK - return *(const T *)ptr; -#else - T local; -#if defined(__GNUC__) || defined(__clang__) - __builtin_memcpy(&local, (const T *)ptr, sizeof(T)); -#else - memcpy(&local, (const T *)ptr, sizeof(T)); -#endif /* __GNUC__ || __clang__ */ - return local; -#endif /* MDBX_UNALIGNED_OK */ -} - -template static __inline void store(void *ptr, const T &value) { -#if defined(_MSC_VER) && \ - (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) - *((T __unaligned *)ptr) = value; -#elif MDBX_UNALIGNED_OK - *(volatile T *)ptr = value; -#else -#if defined(__GNUC__) || defined(__clang__) - __builtin_memcpy(ptr, &value, sizeof(T)); -#else - memcpy(ptr, &value, sizeof(T)); -#endif /* __GNUC__ || __clang__ */ -#endif /* MDBX_UNALIGNED_OK */ -} - -} /* namespace unaligned */ - -//----------------------------------------------------------------------------- - -#ifndef rot64 -static __inline uint64_t rot64(uint64_t v, unsigned s) { - return (v >> s) | (v << (64 - s)); -} -#endif /* rot64 */ - -static __inline bool is_power2(size_t x) { return (x & (x - 1)) == 0; } - -#undef roundup2 -static __inline size_t roundup2(size_t value, size_t granularity) { - assert(is_power2(granularity)); - return (value + granularity - 1) & ~(granularity - 1); -} - -//----------------------------------------------------------------------------- - -static __inline void memory_barrier(void) { -#if __has_extension(c_atomic) || __has_extension(cxx_atomic) - __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__ATOMIC_SEQ_CST) - __atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__clang__) || defined(__GNUC__) - __sync_synchronize(); -#elif defined(_MSC_VER) - MemoryBarrier(); -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ -#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) - __mf(); -#elif defined(__ia32__) - _mm_mfence(); -#else -#error "Unknown target for Intel Compiler, please report to us." -#endif -#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) - __machine_rw_barrier(); -#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ - (defined(HP_IA64) || defined(__ia64)) - _Asm_mf(); -#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ - defined(__ppc64__) || defined(__powerpc64__) - __lwsync(); -#else -#error "Could not guess the kind of compiler, please report to us." -#endif -} - -static __inline void cpu_relax() { -#if defined(__ia32__) - _mm_pause(); -#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \ - defined(YieldProcessor) - YieldProcessor(); -#else -/* nope */ -#endif -} - -//----------------------------------------------------------------------------- - -struct simple_checksum { - uint64_t value; - - simple_checksum() : value(0) {} - - void push(const uint32_t &data) { - value += data * UINT64_C(9386433910765580089) + 1; - value ^= value >> 41; - value *= UINT64_C(0xBD9CACC22C6E9571); - } - - void push(const uint64_t &data) { - push((uint32_t)data); - push((uint32_t)(data >> 32)); - } - - void push(const bool data) { - push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E)); - } - - void push(const void *ptr, size_t bytes) { - const uint8_t *data = (const uint8_t *)ptr; - for (size_t i = 0; i < bytes; ++i) - push((uint32_t)data[i]); - } - - void push(const double &data) { push(&data, sizeof(double)); } - void push(const char *cstr) { push(cstr, strlen(cstr)); } - void push(const std::string &str) { push(str.data(), str.size()); } - - void push(unsigned salt, const MDBX_val &val) { - push(unsigned(val.iov_len)); - push(salt); - push(val.iov_base, val.iov_len); - } - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - void push(const HANDLE &handle) { push(&handle, sizeof(handle)); } -#endif /* _WINDOWS */ -}; - -std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum); -bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, - size_t bytes, simple_checksum &checksum); -bool is_samedata(const MDBX_val *a, const MDBX_val *b); -std::string format(const char *fmt, ...); - -uint64_t entropy_ticks(void); -uint64_t entropy_white(void); -static inline uint64_t bleach64(uint64_t v) { - // Tommy Ettinger, https://www.blogger.com/profile/04953541827437796598 - // http://mostlymangling.blogspot.com/2019/01/better-stronger-mixer-and-test-procedure.html - v ^= rot64(v, 25) ^ rot64(v, 50); - v *= UINT64_C(0xA24BAED4963EE407); - v ^= rot64(v, 24) ^ rot64(v, 49); - v *= UINT64_C(0x9FB21C651E98DF25); - return v ^ v >> 28; -} - -static inline uint32_t bleach32(uint32_t x) { - // https://github.com/skeeto/hash-prospector - // exact bias: 0.17353355999581582 - x ^= x >> 16; - x *= UINT32_C(0x7feb352d); - x ^= 0x3027C563 ^ (x >> 15); - x *= UINT32_C(0x846ca68b); - x ^= x >> 16; - return x; -} - -static inline uint64_t prng64_map1_careless(uint64_t state) { - return state * UINT64_C(6364136223846793005) + 1; -} - -static inline uint64_t prng64_map2_careless(uint64_t state) { - return (state + UINT64_C(1442695040888963407)) * - UINT64_C(6364136223846793005); -} - -static inline uint64_t prng64_map1_white(uint64_t state) { - return bleach64(prng64_map1_careless(state)); -} - -static inline uint64_t prng64_map2_white(uint64_t state) { - return bleach64(prng64_map2_careless(state)); -} - -static inline uint64_t prng64_careless(uint64_t &state) { - state = prng64_map1_careless(state); - return state; -} - -static inline double u64_to_double1(uint64_t v) { - union { - uint64_t u64; - double d; - } casting; - - casting.u64 = UINT64_C(0x3ff) << 52 | (v >> 12); - assert(casting.d >= 1.0 && casting.d < 2.0); - return casting.d - 1.0; -} - -uint64_t prng64_white(uint64_t &state); -uint32_t prng32(uint64_t &state); -void prng_fill(uint64_t &state, void *ptr, size_t bytes); - -void prng_seed(uint64_t seed); -uint32_t prng32(void); -uint64_t prng64(void); -void prng_fill(void *ptr, size_t bytes); - -bool flipcoin(); -bool flipcoin_x2(); -bool flipcoin_x3(); -bool flipcoin_x4(); -bool jitter(unsigned probability_percent); -void jitter_delay(bool extra = false); diff --git a/src/contrib/db/libmdbx/test/valgrind_suppress.txt b/src/contrib/db/libmdbx/test/valgrind_suppress.txt deleted file mode 100644 index 98309ce..0000000 --- a/src/contrib/db/libmdbx/test/valgrind_suppress.txt +++ /dev/null @@ -1,24 +0,0 @@ -{ - msync-whole-mmap-1 - Memcheck:Param - msync(start) - fun:msync - ... - fun:mdbx_sync_locked -} -{ - msync-whole-mmap-2 - Memcheck:Param - msync(start) - fun:msync - ... - fun:mdbx_env_sync_ex -} -{ - pwrite-page-flush - Memcheck:Param - pwritev(vector[...]) - fun:pwritev - ... - fun:mdbx_page_flush -} diff --git a/src/contrib/eos_portable_archive/.DS_Store b/src/contrib/eos_portable_archive/.DS_Store deleted file mode 100644 index 95a90edd0612cb38baaddf247d824cf679e1a6c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKU5nE|6ur|{O(n6eGKct2Nn%HV`tUnQoO*=(9h= zkJbMn`s5GLpW;(J^RY`m)>kbu7w(*!nR_P5xy?+6h*)FTxk=;^kpq`lDx*2Wl#7CgE!YtlP@+3;qM7(ia z*LB>sw>ci)zPnTPw`x0+sz1KBU90-rTel_?@7Qs!UcYny@w5Kq?Ys9MJ|2Ji{N<~9 zVPaT9m0dD;0^blAIgWxsmh!BN9+|x%ms*G)qZGL+L4Nf(x zr2~yR0su?sR)$!fB_zi;ST{J;h!GgmRG_9ZbHrepj(*?d)eTNHYC17<_+aMF%$!h| zx;y6gRXVY{M%!8itOAP)6!oPi_y31~KL0P0?3Go(D)3(^z)H=a*}yBAy>;c~/boost/filesystem /boost/program_options - */ -/****************************************************************************/ - -#pragma warning( disable:4217 4127 4310 4244 4800 4267 ) - -// text_archive test header -// include output archive header -#include "portable_oarchive.hpp" -// set name of test output archive -typedef eos::polymorphic_portable_oarchive test_oarchive; -// set name of test output stream -typedef std::ofstream test_ostream; - -// repeat the above for input archive -#include "portable_iarchive.hpp" -typedef eos::polymorphic_portable_iarchive test_iarchive; -typedef std::ifstream test_istream; - -// define open mode for streams -// binary archives should use std::ios_base::binary -#define TEST_STREAM_FLAGS std::ios_base::binary diff --git a/src/contrib/eos_portable_archive/eos/portable_archive.hpp b/src/contrib/eos_portable_archive/eos/portable_archive.hpp deleted file mode 100644 index f7f9331..0000000 --- a/src/contrib/eos_portable_archive/eos/portable_archive.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/*****************************************************************************/ -/** - * \file portable_archive.hpp - * \brief Needed for unit tests on portable archives. - * \author christian.pfligersdorffer@gmx.at - * - * Header for testing portable archives with all of the serialization tests. - * Before use copy all hpp files from this directory to your boost folder - * boost_.../libs/serialization/test and run from there a visual studio - * prompt with b2 oder bjam -sBOOST_ARCHIVE_LIST=portable_archive.hpp - * - * \note Since portable archives version 5.0 we depend on program_options! - * Edit libs/serialization/test/Jamfile.v2 and change the requirements to - * : requirements /boost/filesystem /boost/program_options - */ -/****************************************************************************/ -#if defined(_MSC_VER) -#pragma warning( disable:4217 4127 4310 4244 4800 4267 ) -#endif - -// text_archive test header -// include output archive header -#include "portable_oarchive.hpp" -// set name of test output archive -typedef eos::portable_oarchive test_oarchive; -// set name of test output stream -typedef std::ofstream test_ostream; - -// repeat the above for input archive -#include "portable_iarchive.hpp" -typedef eos::portable_iarchive test_iarchive; -typedef std::ifstream test_istream; - -// define open mode for streams -// binary archives should use std::ios_base::binary -#define TEST_STREAM_FLAGS std::ios_base::binary diff --git a/src/contrib/eos_portable_archive/eos/portable_archive_exception.hpp b/src/contrib/eos_portable_archive/eos/portable_archive_exception.hpp deleted file mode 100644 index 5af9c80..0000000 --- a/src/contrib/eos_portable_archive/eos/portable_archive_exception.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/*****************************************************************************/ -/** - * \file portable_archive_exception.hpp - * \brief Provides error handling and constants. - * \author christian.pfligersdorffer@gmx.at - * - * Portable archive exceptions derive from the boost archive exceptions - * and add failure causes specific to the portable binary usecase. - * - * Additionally this header serves as common include for important - * constants or typedefs. - */ -/****************************************************************************/ - -#pragma once - -#include -#include -#include - -namespace eos { - - // this value is written to the top of the stream - const signed char magic_byte = 'e' | 'o' | 's'; - - // flag for fp serialization - const unsigned no_infnan = 64; - - // integral type for the archive version - #if BOOST_VERSION < 104400 - typedef boost::archive::version_type archive_version_type; - #else - typedef boost::archive::library_version_type archive_version_type; - #endif - - // version of the linked boost archive library - const archive_version_type archive_version( - - 100 // explicitly fix archive version to make it independent from Boost version - - //#if BOOST_VERSION < 103700 - // boost::archive::ARCHIVE_VERSION() - //#else - // boost::archive::BOOST_ARCHIVE_VERSION() - //#endif - ); - - /** - * \brief Exception being thrown when serialization cannot proceed. - * - * There are several situations in which the portable archives may fail and - * hence throw an exception: - * -# deserialization of an integer value that exceeds the range of the type - * -# (de)serialization of inf/nan through an archive with no_infnan flag set - * -# deserialization of a denormalized value without the floating point type - * supporting denormalized numbers - * - * Note that this exception will also be thrown if you mixed up your stream - * position and accidentially interpret some value for size data (in this case - * the reported size will be totally amiss most of the time). - */ - class portable_archive_exception : public boost::archive::archive_exception - { - std::string msg; - - public: - //! type size is not large enough for deserialized number - portable_archive_exception(signed char invalid_size) - : boost::archive::archive_exception(other_exception) - , msg("requested integer size exceeds type size: ") - { - msg += boost::lexical_cast(invalid_size); - } - - //! negative number in unsigned type - portable_archive_exception() - : boost::archive::archive_exception(other_exception) - , msg("cannot read a negative number into an unsigned type") - { - } - - //! serialization of inf, nan and denormals - template - portable_archive_exception(const T& abnormal) - : boost::archive::archive_exception(other_exception) - , msg("serialization of illegal floating point value: ") - { - msg += boost::lexical_cast(abnormal); - } - - //! override the base class function with our message - const char* what() const throw() { return msg.c_str(); } - ~portable_archive_exception() throw() {} - }; - -} // namespace eos diff --git a/src/contrib/eos_portable_archive/eos/portable_iarchive.hpp b/src/contrib/eos_portable_archive/eos/portable_iarchive.hpp deleted file mode 100644 index cd087f3..0000000 --- a/src/contrib/eos_portable_archive/eos/portable_iarchive.hpp +++ /dev/null @@ -1,501 +0,0 @@ -/*****************************************************************************/ -/** - * \file portable_iarchive.hpp - * \brief Provides an archive to read from portable binary files. - * \author christian.pfligersdorffer@gmx.at - * \version 5.1 - * - * This pair of archives brings the advantages of binary streams to the cross - * platform boost::serialization user. While being almost as fast as the native - * binary archive it allows its files to be exchanged between cpu architectures - * using different byte order (endianness). Speaking of speed: in serializing - * numbers the (portable) binary approach is approximately ten times faster than - * the ascii implementation (that is inherently portable)! - * - * Based on the portable archive example by Robert Ramey this implementation - * uses Beman Dawes endian library and fp_utilities from Johan Rade, both being - * in boost since 1.36. Prior to that you need to add them both (header only) - * to your boost directory before you're able to use the archives provided. - * Our archives have been tested successfully for boost versions 1.33 to 1.49! - * - * \note Correct behaviour has so far been confirmed using PowerPC-32, x86-32 - * and x86-64 platforms featuring different byte order. So there is a good - * chance it will instantly work for your specific setup. If you encounter - * problems or have suggestions please contact the author. - * - * \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to - * ecotax for pointing to the issue with shared_ptr_helper. - * - * \note Version 5.0 is now compatible with boost up to version 1.49 and enables - * serialization of std::wstring by converting it to/from utf8 (thanks to - * Arash Abghari for this suggestion). With that all unit tests from the - * serialization library pass again with the notable exception of user - * defined primitive types. Those are not supported and as a result any - * user defined type to be used with the portable archives are required - * to be at least object_serializable. - * - * \note Version 4.2 maintains compatibility with the latest boost 1.45 and adds - * serialization of special floating point values inf and NaN as proposed - * by Francois Mauger. - * - * \note Version 4.1 makes the archives work together with boost 1.40 and 1.41. - * Thanks to Francois Mauger for his suggestions. - * - * \note Version 4 removes one level of the inheritance hierarchy and directly - * builds upon binary primitive and basic binary archive, thereby fixing - * the last open issue regarding array serialization. Thanks to Robert - * Ramey for the hint. - * - * \note A few fixes introduced in version 3.1 let the archives pass all of the - * serialization tests. Thanks to Sergey Morozov for running the tests. - * Wouter Bijlsma pointed out where to find the fp_utilities and endian - * libraries headers inside the boost distribution. I would never have - * found them so thank him it works out of the box since boost 1.36. - * - * \note With Version 3.0 the archives have been made portable across different - * boost versions. For that purpose a header is added to the data that - * supplies the underlying serialization library version. Backwards - * compatibility is maintained by assuming library version boost 1.33 if - * the iarchive is created using the no_header flag. Whether a header is - * present or not can be guessed by peeking into the stream: the header's - * first byte is the magic number 127 coinciding with 'e'|'o'|'s' :-) - * - * \note Version 2.1 removes several compiler warnings and enhances floating - * point diagnostics to inform the user if some preconditions are violated - * on his platform. We do not strive for the universally portable solution - * in binary floating point serialization as desired by some boost users. - * Instead we support only the most widely used IEEE 754 format and try to - * detect when requirements are not met and hence our approach must fail. - * Contributions we made by Johan Rade and Ákos Maróy. - * - * \note Version 2.0 fixes a serious bug that effectively transformed most - * of negative integral values into positive values! For example the two - * numbers -12 and 234 were stored in the same 8-bit pattern and later - * always restored to 234. This was fixed in this version in a way that - * does not change the interpretation of existing archives that did work - * because there were no negative numbers. The other way round archives - * created by version 2.0 and containing negative numbers will raise an - * integer type size exception when reading it with version 1.0. Thanks - * to Markus Frohnmaier for testing the archives and finding the bug. - * - * \copyright The boost software license applies. - */ -/*****************************************************************************/ - -#pragma once - -#include - -// basic headers -#include -#include -#include -#include - -#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 -#include -#endif - -// funny polymorphics -#if BOOST_VERSION < 103500 -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_impl - -#elif BOOST_VERSION < 103600 -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_dispatch - -#else -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_iarchive_route -#endif - -// endian and fpclassify -#if BOOST_VERSION < 103600 -#include -#include -#elif BOOST_VERSION < 104800 -#include -// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math -#elif BOOST_VERSION < 106900 -#include -#include -#elif BOOST_VERSION >= 106900 -# define BOOST_MATH_DISABLE_STD_FPCLASSIFY -# include -# include -#else -# include -# include -#endif -// namespace alias -#if BOOST_VERSION < 103800 -namespace fp = boost::math; -#elif BOOST_VERSION >= 106900 -namespace fp = boost::math; -#else -namespace fp = boost::spirit::math; -#endif - -// namespace alias endian -#if BOOST_VERSION < 104800 -namespace endian = boost::detail; -#elif BOOST_VERSION >= 106900 -namespace endian = boost::endian; -#else -namespace endian = boost::spirit::detail; -#endif - -#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING -// used for wstring to utf8 conversion -#include -#include -#endif - -// generic type traits for numeric types -#include -#include -#include -#include - -#include "portable_archive_exception.hpp" - -// hint from Johan Rade: on VMS there is still support for -// the VAX floating point format and this macro detects it -#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT -#error "VAX floating point format is not supported!" -#endif - -namespace eos { - - // forward declaration - class portable_iarchive; - - typedef boost::archive::basic_binary_iprimitive< - portable_iarchive - #if BOOST_VERSION < 103400 - , std::istream - #else - , std::istream::char_type - , std::istream::traits_type - #endif - > portable_iprimitive; - - /** - * \brief Portable binary input archive using little endian format. - * - * This archive addresses integer size, endianness and floating point types so - * that data can be transferred across different systems. There may still be - * constraints as to what systems are compatible and the user will have to take - * care that e.g. a very large int being saved on a 64 bit machine will result - * in a portable_archive_exception if loaded into an int on a 32 bit system. - * A possible workaround to this would be to use fixed types like - * boost::uint64_t in your serialization structures. - * - * \note The class is based on the portable binary example by Robert Ramey and - * uses Beman Dawes endian library plus fp_utilities by Johan Rade. - */ - class portable_iarchive : public portable_iprimitive - - // the example derives from common_oarchive but that lacks the - // load_override functions so we chose to stay one level higher - , public boost::archive::basic_binary_iarchive - - #if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 - // mix-in helper class for serializing shared_ptr - , public boost::archive::detail::shared_ptr_helper - #endif - { - // only needed for Robert's hack in basic_binary_iarchive::init - friend class boost::archive::basic_binary_iarchive; - - // workaround for gcc: use a dummy struct - // as additional argument type for overloading - template struct dummy { dummy(int) {}}; - - // loads directly from stream - inline signed char load_signed_char() - { - signed char c; - portable_iprimitive::load(c); - return c; - } - - // archive initialization - void init(unsigned flags) - { - using namespace boost::archive; - archive_version_type input_library_version(3); - - // it is vital to have version information! - // if we don't have any we assume boost 1.33 - if (flags & no_header) - set_library_version(input_library_version); - - // extract and check the magic eos byte - else if (load_signed_char() != magic_byte) - throw archive_exception(archive_exception::invalid_signature); - - else - { - // extract version information - operator>>(input_library_version); - - // throw if file version is newer than we are - if (input_library_version > archive_version) - throw archive_exception(archive_exception::unsupported_version); - - // else set the library version accordingly - else set_library_version(input_library_version); - } - } - - public: - /** - * \brief Constructor on a stream using ios::binary mode! - * - * We cannot call basic_binary_iprimitive::init which tries to detect - * if the binary archive stems from a different platform by examining - * type sizes. - * - * We could have called basic_binary_iarchive::init which would create - * the boost::serialization standard archive header containing also the - * library version. Due to efficiency we stick with our own. - */ - portable_iarchive(std::istream& is, unsigned flags = 0) - #if BOOST_VERSION < 103400 - : portable_iprimitive(is, flags & boost::archive::no_codecvt) - #else - : portable_iprimitive(*is.rdbuf(), flags & boost::archive::no_codecvt) - #endif - , boost::archive::basic_binary_iarchive(flags) - { - init(flags); - } - - #if BOOST_VERSION >= 103400 - portable_iarchive(std::streambuf& sb, unsigned flags = 0) - : portable_iprimitive(sb, flags & boost::archive::no_codecvt) - , boost::archive::basic_binary_iarchive(flags) - { - init(flags); - } - #endif - - //! Load narrow strings. - void load(std::string& s) - { - portable_iprimitive::load(s); - } - - #ifndef BOOST_NO_STD_WSTRING - /** - * \brief Load wide strings. - * - * This is rather tricky to get right for true portability as there - * are so many different character encodings around. However, wide - * strings that are encoded in one of the Unicode schemes only need - * to be _transcoded_ which is a lot easier actually. - * - * We generate the output string to be encoded in the system's native - * format, ie. UTF-16 on Windows and UTF-32 on Linux machines. Don't - * know about Mac here so I can't really say about that. - */ - void load(std::wstring& s) - { - std::string utf8; - load(utf8); - s = boost::from_utf8(utf8); - } - #endif - - /** - * \brief Loading bool type. - * - * Byte pattern is same as with integer types, so this function - * is somewhat redundant but treating bool as integer generates - * a lot of compiler warnings. - * - * \note If you cannot compile your application and it says something - * about load(bool) cannot convert your type A& into bool& then you - * should check your BOOST_CLASS_IMPLEMENTATION setting for A, as - * portable_archive is not able to handle custom primitive types in - * a general manner. - */ - void load(bool& b) - { - switch (signed char c = load_signed_char()) - { - case 0: b = false; break; - case 1: b = load_signed_char(); break; - default: throw portable_archive_exception(c); - } - } - - /** - * \brief Load integer types. - * - * First we load the size information ie. the number of bytes that - * hold the actual data. Then we retrieve the data and transform it - * to the original value by using load_little_endian. - */ - template - typename boost::enable_if >::type - load(T & t, dummy<2> = 0) - { - // get the number of bytes in the stream - if (signed char size = load_signed_char()) - { - // check for negative value in unsigned type - if (size < 0 && boost::is_unsigned::value) - throw portable_archive_exception(); - - // check that our type T is large enough - else if ((unsigned) abs(size) > sizeof(T)) - throw portable_archive_exception(size); - - // reconstruct the value - T temp = size < 0 ? -1 : 0; - load_binary(&temp, abs(size)); - - // load the value from little endian - it is then converted - // to the target type T and fits it because size <= sizeof(T) -#if BOOST_VERSION >= 106900 - t = endian::little_to_native(temp); -#else - t = endian::load_little_endian(&temp); -#endif - } - - else t = 0; // zero optimization - } - - /** - * \brief Load floating point types. - * - * We simply rely on fp_traits to set the bit pattern from the (unsigned) - * integral type that was stored in the stream. Francois Mauger provided - * standardized behaviour for special values like inf and NaN, that need to - * be serialized in his application. - * - * \note by Johan Rade (author of the floating point utilities library): - * Be warned that the math::detail::fp_traits::type::get_bits() function - * is *not* guaranteed to give you all bits of the floating point number. It - * will give you all bits if and only if there is an integer type that has - * the same size as the floating point you are copying from. It will not - * give you all bits for double if there is no uint64_t. It will not give - * you all bits for long double if sizeof(long double) > 8 or there is no - * uint64_t. - * - * The member fp_traits::type::coverage will tell you whether all bits - * are copied. This is a typedef for either math::detail::all_bits or - * math::detail::not_all_bits. - * - * If the function does not copy all bits, then it will copy the most - * significant bits. So if you serialize and deserialize the way you - * describe, and fp_traits::type::coverage is math::detail::not_all_bits, - * then your floating point numbers will be truncated. This will introduce - * small rounding off errors. - */ - template - typename boost::enable_if >::type - load(T & t, dummy<3> = 0) - { - typedef typename fp::detail::fp_traits::type traits; - - // if you end here there are three possibilities: - // 1. you're serializing a long double which is not portable - // 2. you're serializing a double but have no 64 bit integer - // 3. your machine is using an unknown floating point format - // after reading the note above you still might decide to - // deactivate this static assert and try if it works out. - typename traits::bits bits; - BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); - - load(bits); - traits::set_bits(t, bits); - - // if the no_infnan flag is set we must throw here - if (get_flags() & no_infnan && !fp::isfinite(t)) - throw portable_archive_exception(t); - - // if you end here your floating point type does not support - // denormalized numbers. this might be the case even though - // your type conforms to IEC 559 (and thus to IEEE 754) - if (std::numeric_limits::has_denorm == std::denorm_absent - && fp::fpclassify(t) == (int) FP_SUBNORMAL) // GCC4 - throw portable_archive_exception(t); - } - - // in boost 1.44 version_type was splitted into library_version_type and - // item_version_type, plus a whole bunch of additional strong typedefs. - template - typename boost::disable_if >::type - load(T& t, dummy<4> = 0) - { - // we provide a generic load routine for all types that feature - // conversion operators into an unsigned integer value like those - // created through BOOST_STRONG_TYPEDEF(X, some unsigned int) like - // library_version_type, collection_size_type, item_version_type, - // class_id_type, object_id_type, version_type and tracking_type - load((typename boost::uint_t::least&)(t)); - } - }; - - // polymorphic portable binary iarchive typedef - typedef POLYMORPHIC(portable_iarchive) polymorphic_portable_iarchive; - #undef POLYMORPHIC - -} // namespace eos - -// this is required by export which registers all of your -// classes with all the inbuilt archives plus our archive. -#if BOOST_VERSION < 103500 -#define BOOST_ARCHIVE_CUSTOM_IARCHIVE_TYPES eos::portable_iarchive -#else -BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::portable_iarchive) -BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::polymorphic_portable_iarchive) -#endif - -// if you include this header multiple times and your compiler is picky -// about multiple template instantiations (eg. gcc is) then you need to -// define NO_EXPLICIT_TEMPLATE_INSTANTIATION before every include but one -// or you move the instantiation section into an implementation file -#ifndef NO_EXPLICIT_TEMPLATE_INSTANTIATION - -#include -#include - -#if BOOST_VERSION < 104000 -#include -#elif !defined BOOST_ARCHIVE_SERIALIZER_INCLUDED -#include -#define BOOST_ARCHIVE_SERIALIZER_INCLUDED -#endif - -namespace boost { namespace archive { - - // explicitly instantiate for this type of binary stream - template class basic_binary_iarchive; - - template class basic_binary_iprimitive< - eos::portable_iarchive - #if BOOST_VERSION < 103400 - , std::istream - #else - , std::istream::char_type - , std::istream::traits_type - #endif - >; - -#if BOOST_VERSION < 104000 - template class detail::archive_pointer_iserializer; -#else - template class detail::archive_serializer_map; - //template class detail::archive_serializer_map; -#endif - -} } // namespace boost::archive - -#endif diff --git a/src/contrib/eos_portable_archive/eos/portable_oarchive.hpp b/src/contrib/eos_portable_archive/eos/portable_oarchive.hpp deleted file mode 100644 index fce2bd2..0000000 --- a/src/contrib/eos_portable_archive/eos/portable_oarchive.hpp +++ /dev/null @@ -1,488 +0,0 @@ -/*****************************************************************************/ -/** - * \file portable_oarchive.hpp - * \brief Provides an archive to create portable binary files. - * \author christian.pfligersdorffer@gmx.at - * \version 5.1 - * - * This pair of archives brings the advantages of binary streams to the cross - * platform boost::serialization user. While being almost as fast as the native - * binary archive it allows its files to be exchanged between cpu architectures - * using different byte order (endianness). Speaking of speed: in serializing - * numbers the (portable) binary approach is approximately ten times faster than - * the ascii implementation (that is inherently portable)! - * - * Based on the portable archive example by Robert Ramey this implementation - * uses Beman Dawes endian library and fp_utilities from Johan Rade, both being - * in boost since 1.36. Prior to that you need to add them both (header only) - * to your boost directory before you're able to use the archives provided. - * Our archives have been tested successfully for boost versions 1.33 to 1.49! - * - * \note Correct behaviour has so far been confirmed using PowerPC-32, x86-32 - * and x86-64 platforms featuring different byte order. So there is a good - * chance it will instantly work for your specific setup. If you encounter - * problems or have suggestions please contact the author. - * - * \note Version 5.1 is now compatible with boost up to version 1.59. Thanks to - * ecotax for pointing to the issue with shared_ptr_helper. - * - * \note Version 5.0 is now compatible with boost up to version 1.49 and enables - * serialization of std::wstring by converting it to/from utf8 (thanks to - * Arash Abghari for this suggestion). With that all unit tests from the - * serialization library pass again with the notable exception of user - * defined primitive types. Those are not supported and as a result any - * user defined type to be used with the portable archives are required - * to be at least object_serializable. - * - * \note Oliver Putz pointed out that -0.0 was not serialized correctly, so - * version 4.3 provides a fix for that. Thanks Ollie! - * - * \note Version 4.2 maintains compatibility with the latest boost 1.45 and adds - * serialization of special floating point values inf and NaN as proposed - * by Francois Mauger. - * - * \note Version 4.1 makes the archives work together with boost 1.40 and 1.41. - * Thanks to Francois Mauger for his suggestions. - * - * \note Version 4 removes one level of the inheritance hierarchy and directly - * builds upon binary primitive and basic binary archive, thereby fixing - * the last open issue regarding array serialization. Thanks to Robert - * Ramey for the hint. - * - * \note A few fixes introduced in version 3.1 let the archives pass all of the - * serialization tests. Thanks to Sergey Morozov for running the tests. - * Wouter Bijlsma pointed out where to find the fp_utilities and endian - * libraries headers inside the boost distribution. I would never have - * found them so thank him it works out of the box since boost 1.36. - * - * \note With Version 3.0 the archives have been made portable across different - * boost versions. For that purpose a header is added to the data that - * supplies the underlying serialization library version. Backwards - * compatibility is maintained by assuming library version boost 1.33 if - * the iarchive is created using the no_header flag. Whether a header is - * present or not can be guessed by peeking into the stream: the header's - * first byte is the magic number 127 coinciding with 'e'|'o'|'s' :-) - * - * \note Version 2.1 removes several compiler warnings and enhances floating - * point diagnostics to inform the user if some preconditions are violated - * on his platform. We do not strive for the universally portable solution - * in binary floating point serialization as desired by some boost users. - * Instead we support only the most widely used IEEE 754 format and try to - * detect when requirements are not met and hence our approach must fail. - * Contributions we made by Johan Rade and Ákos Maróy. - * - * \note Version 2.0 fixes a serious bug that effectively transformed most - * of negative integral values into positive values! For example the two - * numbers -12 and 234 were stored in the same 8-bit pattern and later - * always restored to 234. This was fixed in this version in a way that - * does not change the interpretation of existing archives that did work - * because there were no negative numbers. The other way round archives - * created by version 2.0 and containing negative numbers will raise an - * integer type size exception when reading it with version 1.0. Thanks - * to Markus Frohnmaier for testing the archives and finding the bug. - * - * \copyright The boost software license applies. - */ -/*****************************************************************************/ - -#pragma once - -#include - -// basic headers -#include -#include -#include -#include - -#if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 -#include -#endif - -// funny polymorphics -#if BOOST_VERSION < 103500 -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_impl - -#elif BOOST_VERSION < 103600 -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_dispatch - -#else -#include -#define POLYMORPHIC(T) boost::archive::detail::polymorphic_oarchive_route -#endif - -// endian and fpclassify -#if BOOST_VERSION < 103600 -#include -#include -#elif BOOST_VERSION < 104800 -#include -// Boost 1.69 (Spirit.X2/X3) has dropped their own FP routines in favor of boost::math -#elif BOOST_VERSION < 106900 -#include -#include -#elif BOOST_VERSION >= 106900 -#define BOOST_MATH_DISABLE_STD_FPCLASSIFY -#include -#include -#else -#include -#include -#endif - -// namespace alias fp_classify -#if BOOST_VERSION < 103800 -namespace fp = boost::math; -#elif BOOST_VERSION >= 106900 -namespace fp = boost::math; -#else -namespace fp = boost::spirit::math; -#endif - -// namespace alias endian -#if BOOST_VERSION < 104800 -namespace endian = boost::detail; -#elif BOOST_VERSION >= 106900 -namespace endian = boost::endian; -#else -namespace endian = boost::spirit::detail; -#endif - -#if BOOST_VERSION >= 104500 && !defined BOOST_NO_STD_WSTRING -// used for wstring to utf8 conversion -#include -#include -#endif - -// generic type traits for numeric types -#include -#include -#include -#include - -#include "portable_archive_exception.hpp" - -// hint from Johan Rade: on VMS there is still support for -// the VAX floating point format and this macro detects it -#if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT -#error "VAX floating point format is not supported!" -#endif - -namespace eos { - - // forward declaration - class portable_oarchive; - - typedef boost::archive::basic_binary_oprimitive< - portable_oarchive - #if BOOST_VERSION < 103400 - , std::ostream - #else - , std::ostream::char_type - , std::ostream::traits_type - #endif - > portable_oprimitive; - - /** - * \brief Portable binary output archive using little endian format. - * - * This archive addresses integer size, endianness and floating point types so - * that data can be transferred across different systems. The archive consists - * primarily of three different save implementations for integral types, - * floating point types and string types. Those functions are templates and use - * enable_if to be correctly selected for overloading. - * - * \note The class is based on the portable binary example by Robert Ramey and - * uses Beman Dawes endian library plus fp_utilities by Johan Rade. - */ - class portable_oarchive : public portable_oprimitive - - // the example derives from common_oarchive but that lacks the - // save_override functions so we chose to stay one level higher - , public boost::archive::basic_binary_oarchive - - #if BOOST_VERSION >= 103500 && BOOST_VERSION < 105600 - // mix-in helper class for serializing shared_ptr - , public boost::archive::detail::shared_ptr_helper - #endif - { - // workaround for gcc: use a dummy struct - // as additional argument type for overloading - template struct dummy { dummy(int) {}}; - - // stores a signed char directly to stream - inline void save_signed_char(const signed char& c) - { - portable_oprimitive::save(c); - } - - // archive initialization - void init(unsigned flags) - { - // it is vital to have version information if the archive is - // to be parsed with a newer version of boost::serialization - // therefor we create a header, no header means boost 1.33 - if (flags & boost::archive::no_header) - BOOST_ASSERT(archive_version == 3); - else - { - // write our minimalistic header (magic byte plus version) - // the boost archives write a string instead - by calling - // boost::archive::basic_binary_oarchive::init() - save_signed_char(magic_byte); - - // write current version -// save(archive_version); - operator<<(archive_version); - } - } - - public: - /** - * \brief Constructor on a stream using ios::binary mode! - * - * We cannot call basic_binary_oprimitive::init which stores type - * sizes to the archive in order to detect transfers to non-compatible - * platforms. - * - * We could have called basic_binary_oarchive::init which would create - * the boost::serialization standard archive header containing also the - * library version. Due to efficiency we stick with our own. - */ - portable_oarchive(std::ostream& os, unsigned flags = 0) - #if BOOST_VERSION < 103400 - : portable_oprimitive(os, flags & boost::archive::no_codecvt) - #else - : portable_oprimitive(*os.rdbuf(), flags & boost::archive::no_codecvt) - #endif - , boost::archive::basic_binary_oarchive(flags) - { - init(flags); - } - - #if BOOST_VERSION >= 103400 - portable_oarchive(std::streambuf& sb, unsigned flags = 0) - : portable_oprimitive(sb, flags & boost::archive::no_codecvt) - , boost::archive::basic_binary_oarchive(flags) - { - init(flags); - } - #endif - - //! Save narrow strings. - void save(const std::string& s) - { - portable_oprimitive::save(s); - } - - #ifndef BOOST_NO_STD_WSTRING - /** - * \brief Save wide strings. - * - * This is rather tricky to get right for true portability as there - * are so many different character encodings around. However, wide - * strings that are encoded in one of the Unicode schemes only need - * to be _transcoded_ which is a lot easier actually. - * - * We expect the input string to be encoded in the system's native - * format, ie. UTF-16 on Windows and UTF-32 on Linux machines. Don't - * know about Mac here so I can't really say about that. - */ - void save(const std::wstring& s) - { - save(boost::to_utf8(s)); - } - #endif - - /** - * \brief Saving bool type. - * - * Saving bool directly, not by const reference - * because of tracking_type's operator (bool). - * - * \note If you cannot compile your application and it says something - * about save(bool) cannot convert your type const A& into bool then - * you should check your BOOST_CLASS_IMPLEMENTATION setting for A, as - * portable_archive is not able to handle custom primitive types in - * a general manner. - */ - void save(const bool& b) - { - save_signed_char(b); - if (b) save_signed_char('T'); - } - - /** - * \brief Save integer types. - * - * First we save the size information ie. the number of bytes that hold the - * actual data. We subsequently transform the data using store_little_endian - * and store non-zero bytes to the stream. - */ - template - typename boost::enable_if >::type - save(const T & t, dummy<2> = 0) - { - if (T temp = t) - { - // examine the number of bytes - // needed to represent the number - signed char size = 0; - do { temp >>= CHAR_BIT; ++size; } - while (temp != 0 && temp != (T) -1); - - // encode the sign bit into the size - save_signed_char(t > 0 ? size : -size); - BOOST_ASSERT(t > 0 || boost::is_signed::value); - - // we choose to use little endian because this way we just - // save the first size bytes to the stream and skip the rest -#if BOOST_VERSION >= 106900 - temp = endian::native_to_little(temp); -#else - endian::store_little_endian(&temp, t); -#endif - save_binary(&temp, size); - } - // zero optimization - else save_signed_char(0); - } - - /** - * \brief Save floating point types. - * - * We simply rely on fp_traits to extract the bit pattern into an (unsigned) - * integral type and store that into the stream. Francois Mauger provided - * standardized behaviour for special values like inf and NaN, that need to - * be serialized in his application. - * - * \note by Johan Rade (author of the floating point utilities library): - * Be warned that the math::detail::fp_traits::type::get_bits() function - * is *not* guaranteed to give you all bits of the floating point number. It - * will give you all bits if and only if there is an integer type that has - * the same size as the floating point you are copying from. It will not - * give you all bits for double if there is no uint64_t. It will not give - * you all bits for long double if sizeof(long double) > 8 or there is no - * uint64_t. - * - * The member fp_traits::type::coverage will tell you whether all bits - * are copied. This is a typedef for either math::detail::all_bits or - * math::detail::not_all_bits. - * - * If the function does not copy all bits, then it will copy the most - * significant bits. So if you serialize and deserialize the way you - * describe, and fp_traits::type::coverage is math::detail::not_all_bits, - * then your floating point numbers will be truncated. This will introduce - * small rounding off errors. - */ - template - typename boost::enable_if >::type - save(const T & t, dummy<3> = 0) - { - typedef typename fp::detail::fp_traits::type traits; - - // if the no_infnan flag is set we must throw here - if (get_flags() & no_infnan && !fp::isfinite(t)) - throw portable_archive_exception(t); - - // if you end here there are three possibilities: - // 1. you're serializing a long double which is not portable - // 2. you're serializing a double but have no 64 bit integer - // 3. your machine is using an unknown floating point format - // after reading the note above you still might decide to - // deactivate this static assert and try if it works out. - typename traits::bits bits; - BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); - - // examine value closely - switch (fp::fpclassify(t)) - { - //case FP_ZERO: bits = 0; break; -#if BOOST_VERSION >= 106900 - case FP_NAN: bits = traits::exponent | traits::significand; break; -#else - case FP_NAN: bits = traits::exponent | traits::mantissa; break; -#endif - case FP_INFINITE: bits = traits::exponent | (t<0) * traits::sign; break; - case FP_SUBNORMAL: assert(std::numeric_limits::has_denorm); // pass - case FP_ZERO: // note that floats can be ±0.0 - case FP_NORMAL: traits::get_bits(t, bits); break; - default: throw portable_archive_exception(t); - } - - save(bits); - } - - // in boost 1.44 version_type was splitted into library_version_type and - // item_version_type, plus a whole bunch of additional strong typedefs. - template - typename boost::disable_if >::type - save(const T& t, dummy<4> = 0) - { - // we provide a generic save routine for all types that feature - // conversion operators into an unsigned integer value like those - // created through BOOST_STRONG_TYPEDEF(X, some unsigned int) like - // library_version_type, collection_size_type, item_version_type, - // class_id_type, object_id_type, version_type and tracking_type - save((typename boost::uint_t::least)(t)); - } - }; - - // polymorphic portable binary oarchive typedef - typedef POLYMORPHIC(portable_oarchive) polymorphic_portable_oarchive; - #undef POLYMORPHIC - -} // namespace eos - -// required by export -#if BOOST_VERSION < 103500 -#define BOOST_ARCHIVE_CUSTOM_OARCHIVE_TYPES eos::portable_oarchive -#else -BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::portable_oarchive) -BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::polymorphic_portable_oarchive) -#endif - -// if you include this header multiple times and your compiler is picky -// about multiple template instantiations (eg. gcc is) then you need to -// define NO_EXPLICIT_TEMPLATE_INSTANTIATION before every include but one -// or you move the instantiation section into an implementation file -#ifndef NO_EXPLICIT_TEMPLATE_INSTANTIATION - -#include -#include - -#if BOOST_VERSION < 104000 -#include -#elif !defined BOOST_ARCHIVE_SERIALIZER_INCLUDED -#include -#define BOOST_ARCHIVE_SERIALIZER_INCLUDED -#endif - -namespace boost { namespace archive { - - // explicitly instantiate for this type of binary stream - template class basic_binary_oarchive; - - template class basic_binary_oprimitive< - eos::portable_oarchive - #if BOOST_VERSION < 103400 - , std::ostream - #else - , std::ostream::char_type - , std::ostream::traits_type - #endif - >; - -#if BOOST_VERSION < 104000 - template class detail::archive_pointer_oserializer; -#else - template class detail::archive_serializer_map; - //template class detail::archive_serializer_map; -#endif - -} } // namespace boost::archive - -#endif diff --git a/src/contrib/eos_portable_archive/release_notes.txt b/src/contrib/eos_portable_archive/release_notes.txt deleted file mode 100644 index 42e1fbd..0000000 --- a/src/contrib/eos_portable_archive/release_notes.txt +++ /dev/null @@ -1,36 +0,0 @@ -IMPORTANT: - -This is the last release from me as EOS employee. I plan to contribute all of this -work to the official boost libraries distribution and will continue to support users. -Francois Mauger joined me recently and already added a valuable tutorial for you! - - -Dear user, - -I am proud to announce the very first release of our portable_binary_[io]archive -which we use here at EOS to move data between different platforms. It really is -a conglomerate of pieces that already were there - as is most often the case in -OO world - we simply put them together in a way that seemed to make sense. I know -a lot of people were interested in portable binary archives, so here you are - -give it a try and let me know what you think about it! - -We rely heavily on boost::serialization and really appreciate the amount of time -and knowledge that went into it. By publishing this small missing piece we hope -to contribute our mite to this great library. - -The work extends the portable binary example which was done by Robert Ramey and -uses Beman Dawes' endian library plus the fp_utilities by Johan Rade. You will -need to get those two libraries in order to use our classes - look for them at -the boost vault (http://www.boost-consulting.com/vault/) in categories 'integer' -and 'math - numerics'. Finally you will find the portable binary archive in -category 'serialization' as well. - -Regards, -Christian Pfligersdorffer - -Munich, End of 2007 - --- -christian.pfligersdorffer@eos.info -christian.pfligersdorffer@gmx.at -http://www.eos.info \ No newline at end of file diff --git a/src/contrib/eos_portable_archive/tutorial/.DS_Store b/src/contrib/eos_portable_archive/tutorial/.DS_Store deleted file mode 100644 index 21909ef282924707c72fd64ddf814b5ecb5a9b5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%SyvQ6g{_w+9E=iF0*tc_y?gx!L8Z*=mRaJMEY2`%V+peet>^d&z-r1Hqos} zxfkx7d7L|$ITLa-0A#$KT>~Qk1G-{w$l?dnarKV%tfxT(c z*$r`p90eZf&G}W+Nm)%es;|Z^{bLu5H6X#1=RDJM?(i=6czrCe#4}zn$GXM+;1biV<&IMT;%>Eq0&m4c<|9XO^!P_ngeF?QFr-l-%zt+e?&(YwA5{BwcnpmTsxdko zNem^%P_Zk9#Blbf#>))rh%p>umk+Tgi``HpJe~8Wfey(cdg%(d0*4Bm#O6rz|IP3B z|HB|}xdN`hQ7IrvUgTqL$#QFFbDC>Y`V(DEd3D4lgq4tr$<{#1c)UV~Qr diff --git a/src/contrib/eos_portable_archive/tutorial/._.DS_Store b/src/contrib/eos_portable_archive/tutorial/._.DS_Store deleted file mode 100644 index 5f78509fd51b4cc28a0e204c48122c011add825a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIk*Y|peR=07!ne6 zx<*PEqJyCVtD;fC(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@RpmGQ>0?h+q zFpvw$$ShVUN-fSWElN&RNXswER>;gNNzE(C%+E{A$*EMxNlhzJNXkjf%LaCJp}K}N Ph3bE}S7aFE{{II6rXn5+ diff --git a/src/contrib/eos_portable_archive/tutorial/._code b/src/contrib/eos_portable_archive/tutorial/._code deleted file mode 100644 index 9c12873b8da27fa8e25d48186b91dfd9bea105ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v`aZSz zIz$J<44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+OFi| z2GPMV1E|~?O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-FfcGMv^F(0FtRi>PqcQ= z&ri=ujj1p)aLy>o&rP*9Ff=tXb1`z(H8!%a&^57eGSGE&GI!QBGqbQTH?TB!ws1B^ zvvQO>8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Au!xS0Myw8VK9&j$;d2LC`v8P zFD*(=RY=P(%2vqCD@g@*JM;4rb8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9?iCpZx&QwG D;0HGv diff --git a/src/contrib/eos_portable_archive/tutorial/._scripts b/src/contrib/eos_portable_archive/tutorial/._scripts deleted file mode 100644 index adaf7ea1136edec33a57f429aed07d858abce535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v`r`5P z2}B3O44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v(r;)z z2GPMV1E|~?O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-FfcGMv^F(0FtRi>PqcQ= z&ri=ujj1p)aLy>o&rP*9Ff=tXb1`z(H8!%a&^57eGSGE&GI!QBGqbQTH?TB!ws1B^ zvvQO>8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Au!xS0Myw8VK9&j$;d2LC`v8P zFD*(=RY=P(%2vqCD@g@*JM;4rb8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9?iCpZx&QwG DofbE# diff --git a/src/contrib/eos_portable_archive/tutorial/._tutorial.html b/src/contrib/eos_portable_archive/tutorial/._tutorial.html deleted file mode 100644 index 86bdd326289475e3ec4564bbab4ec378a8039ef5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+MIS` zH$(@+44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_0.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_0.cpp deleted file mode 100644 index 50122820c5ab0efa315ec23b043326d106845e1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103viqt;2 z1EPar22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E07+Cgv;Y7A diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_1.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_1.cpp deleted file mode 100644 index b11f48cebf0537b178f7fd2fbcd470963b539c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v5(~cf z6rzJ+22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0IM-K+W-In diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10.cpp deleted file mode 100644 index 9d9648f7f06dda5f0d6b108a27da644002f2fbd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vTE}@B zs2ik%VFnO8qiJD8h>IrY=jtUE6y&7p6_zFzCFYf6=A|+i7#J8@o0=LJSsI!rTD#}x zr{|=`R2UgJXB6eTH5A7|4ZWWELwFr55Lx z7A2=Dq~#Z7D`e)CqyoF0`FV*sIh6`Isc9t&NjZsm*}%RqRM(KEQ2h`0iVTC?|Nj8g C_cuBK diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10b.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_10b.cpp deleted file mode 100644 index ef839532e12324d7c7812e4c9229caae44f84f50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v%Ih>@ zhUj3J0aWgcriBs6hl-0P=jZAr78K;9>J^qI7A5ADWagzZ7#J8BTAP|07+D&cCtADb z=cnhS##9&?IA;{)=cZa47@8WHxfnU?8XH+y=$cqK8R$AXnLF#6nORtv8(5k%WMmdA6r~pD zmlh?bDx~EXWh-Rnm81f@o%wl*IXRUIIjLzS3Q0MMdD+0eFjUu&rcnJ4_lgXI-2eXo D1{gNm diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_11.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_11.cpp deleted file mode 100644 index 8614c6df9abe5a6918f57d68e872b1ec39694669..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+WMn> z4@3vU44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v3T=xm zgXmzG0aWgcriBs6hl-0P=jZAr78K;9>J^qI7A5ADWagzZ7#J8BTAP|07+D&cCtADb z=cnhS##9&?IA;{)=cZa47@8WHxfnU?8XH+y=$cqK8R$AXnLF#6nORtv8(5k%WMmdA6r~pD zmlh?bDx~EXWh-Rnm81f@o%wl*IXRUIIjLzS3Q0MMdD+0eFjUu&rcnJ4_lgXI-2eXo D_$4=8 diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_3.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_3.cpp deleted file mode 100644 index 3a1f786ea4ae4729d30a896542238b4f469e4394..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v%ANkW z8KQ$>22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0Cx2_82|tP diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_4.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_4.cpp deleted file mode 100644 index 8a45596aa663c1fc1feceffaa83fd5cfc2d52263..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vIzB!5 z4@3vU44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0Ht$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+P})% z6QYA*22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0L{-gtN;K2 diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_6.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_6.cpp deleted file mode 100644 index 73ebadaaf836a47239095ba69ca9359e17b2530e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+7ocm z3ZjEy22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0AzSK#sB~S diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_7.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_7.cpp deleted file mode 100644 index c04b6128b7009879a1bdacf60a8ccb54c6a5a60c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+W6A1 z9ioF_22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0LBS89smFU diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_8.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_8.cpp deleted file mode 100644 index a999cacdab7970cd73c2d617272750a264e81883..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v%5MH_ z0MWrP1E|~?O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-FfcGMv^F(0FtRi>PqcQ= z&ri=ujj1p)aLy>o&rP*9Ff=tXb1`z(H8!%a&^57eGSGE&GI!QBGqbQTH?TB!ws1B^ zvvQO>8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Au!xS0Myw8VK9&j$;d2LC`v8P zFD*(=RY=P(%2vqCD@g@*JM;4rb8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9?iCpZx&QwG D1}`_j diff --git a/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_9.cpp b/src/contrib/eos_portable_archive/tutorial/code/._tutorial_pba_9.cpp deleted file mode 100644 index 466d15a0fd2316d2c9ee15f38010d19b6431d2d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vN}lRg z3(>(a1E|~?O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-FfcGMv^F(0FtRi>PqcQ= z&ri=ujj1p)aLy>o&rP*9Ff=tXb1`z(H8!%a&^57eGSGE&GI!QBGqbQTH?TB!ws1B^ zvvQO>8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Au!xS0Myw8VK9&j$;d2LC`v8P zFD*(=RY=P(%2vqCD@g@*JM;4rb8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9?iCpZx&QwG D!^Ssi diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_0.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_0.cpp deleted file mode 100644 index aaec78c..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_0.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/** tutorial_pba_0.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This quick start example shows how to store some variables - * of basic types (bool, integer, floating point numbers, STL string) - * using the portable binary archive format associated to a - * standard output file stream. - * - */ - -#include -#include - -#include -#include - -int main (void) -{ - // The name for the example data file : - std::string filename = "pba_0.data"; - - // Some variables of various primitive types : - bool b = true; - char c = 'B'; - uint32_t answer = 42; - float computing_time = 7.5e6; - double e = 2.71828182845905; - std::string slogan = "DON'T PANIC"; - - // Open an output file stream in binary mode : - std::ofstream fout (filename.c_str (), std::ios_base::binary); - - { - // Create an output portable binary archive attached to the output file : - boost::archive::portable_binary_oarchive opba (fout); - - // Store (serializing) variables : - opba & b & c & answer & computing_time & e & slogan; - } - - return 0; -} - -// end of tutorial_pba_0.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_1.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_1.cpp deleted file mode 100644 index 1b5fb8f..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_1.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/** tutorial_pba_1.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization package. - * - * This quick start example shows how to load some variables - * of basic types (bool, integer, floating point numbers, STL string) - * using the portable binary archive format associated to a - * standard input file stream. - * - */ - -#include -#include -#include - -#include -#include - -int main (void) -{ - using namespace std; - - // The name for the example data file : - string filename = "pba_0.data"; - - // Some variables of various types : - bool b; - char c; - uint32_t answer; - float computing_time; - double e; - string slogan; - - // Open an input file stream in binary mode : - ifstream fin (filename.c_str (), ios_base::binary); - - { - // Create an input portable binary archive attached to the input file : - boost::archive::portable_binary_iarchive ipba (fin); - - // Loading (de-serializing) variables using the same - // order than for serialization (see tutorial_pba_0.cpp) : - ipba & b & c & answer & computing_time & e & slogan; - } - - cout.precision (15); - cout << "Variable 'b' is : " << b << " " << "(bool)" << endl; - cout << "Variable 'c' is : '" << c << "' " << " " << "(char)" << endl; - cout << "Variable 'answer' is : " << answer << " " << "(unsigned 32-bit integer)" << endl; - cout << "Variable 'computing_time' is : " << computing_time << " " << "(single precision 32-bit float)" << endl; - cout << "Variable 'e' is : " << e << " " << "(double precision 64-bit float)" << endl; - cout << "Variable 'slogan' is : \"" << slogan << "\" " << "(std::string)" << endl; - - return 0; -} - -// end of tutorial_pba_1.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10.cpp deleted file mode 100644 index a2d4439..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** tutorial_pba_10.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example shows how use PBAs combined with on-the-fly - * compressed I/O streams. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -class data_type -{ -private: - friend class boost::serialization::access; - template - void serialize (Archive & ar, const unsigned int version); -public: - void print (ostream & out, const string & title) const; -public: - vector values; - data_type (); -}; - -data_type::data_type () : values () -{ - return; -} - -void data_type::print (ostream & out, const string & title) const -{ - out << endl; - out << title << " :" << endl; - for (int i = 0; i < this->values.size (); ++i) - { - out.precision (16); - out.width (18); - out << this->values [i] << ' ' ; - if ((i%4) == 3) clog << endl; - } - out << endl; - return; -} - -template -void data_type::serialize (Archive & ar, const unsigned int version) -{ - ar & values; - return; -} - -void do_gzipped_out (void) -{ - // The name for the output data file : - string filename = "pba_10.data.gz"; - - // A data structure to be stored : - data_type my_data; - - // Fill the vector with arbitrary (possibly non-finite) values : - size_t dim = 1000; - my_data.values.reserve (dim); - for (int i = 0; i < dim; ++i) - { - double val = (i + 1) * (1.0 + 3 * numeric_limits::epsilon ()); - if (i == 4) val = numeric_limits::quiet_NaN (); - if (i == 23) val = numeric_limits::infinity (); - if (i == 73) val = -numeric_limits::infinity (); - if (i == 90) val = 0.0; - my_data.values.push_back (val); - } - - // Print: - my_data.print (clog, "Stored data"); - - // Create an output filtering stream : - boost::iostreams::filtering_ostream zout; - zout.push (boost::iostreams::gzip_compressor ()); - - // Open an output file stream in binary mode : - ofstream fout (filename.c_str (), ios_base::binary); - zout.push (fout); - - // Save to PBA : - { - // Create an output portable binary archive attached to the output file : - boost::archive::portable_binary_oarchive opba (zout); - - // Store (serializing) the data : - opba & my_data; - } - - // Clean termination of the streams : - zout.flush (); - zout.reset (); - - return; -} - -void do_gzipped_in (void) -{ - // The name for the input data file : - string filename = "pba_10.data.gz"; - - // A data structure to be loaded : - data_type my_data; - - // Create an input filtering stream : - boost::iostreams::filtering_istream zin; - zin.push (boost::iostreams::gzip_decompressor ()); - - // Open an input file stream in binary mode : - ifstream fin (filename.c_str (), ios_base::binary); - zin.push (fin); - - // Load from PBA : - { - // Create an input portable binary archive attached to the input file : - boost::archive::portable_binary_iarchive ipba (zin); - - // Load (deserializing) the data : - ipba & my_data; - } - - // Print: - my_data.print (clog, "Loaded data"); - - return; -} - -int main (void) -{ - do_gzipped_out (); - do_gzipped_in (); - return 0; -} - -// end of tutorial_pba_10.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10b.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10b.cpp deleted file mode 100644 index f1695f4..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_10b.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/** tutorial_pba_10b.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example shows how use PBAs combined with on-the-fly - * compressed I/O streams. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -class data_type -{ -private: - friend class boost::serialization::access; - template - void serialize (Archive & ar, const unsigned int version); -public: - void print (ostream & out, const string & title) const; -public: - vector values; - data_type (); -}; - -//BOOST_CLASS_VERSION(data_type, 7) - -data_type::data_type () : values () -{ - return; -} - -void data_type::print (ostream & out, const string & title) const -{ - out << endl; - out << title << " :" << endl; - for (int i = 0; i < this->values.size (); ++i) - { - out.precision (16); - out.width (18); - out << this->values [i] << ' ' ; - if ((i%4) == 3) clog << endl; - } - out << endl; - return; -} - -template -void data_type::serialize (Archive & ar, const unsigned int version) -{ - ar & BOOST_SERIALIZATION_NVP (values); - return; -} - -class data_type2 -{ -private: - friend class boost::serialization::access; - template - void serialize (Archive & ar, const unsigned int version); -public: - double value; - data_type2 (); -}; - -BOOST_CLASS_VERSION(data_type2, 99) - -data_type2::data_type2 () : value (666.666) -{ - return; -} - -template -void data_type2::serialize (Archive & ar, const unsigned int version) -{ - ar & BOOST_SERIALIZATION_NVP (value); - return; -} - -class data_type3 -{ -private: - friend class boost::serialization::access; - template - void serialize (Archive & ar, const unsigned int version); -public: - vector values; - data_type3 (); -}; - -BOOST_CLASS_VERSION(data_type3, 33) - -data_type3::data_type3 () -{ - { - data_type2 d; - d.value = 6.66; - values.push_back (d); - } - { - data_type2 d; - d.value = 66.66; - values.push_back (d); - } - { - data_type2 d; - d.value = 666.66; - values.push_back (d); - } - return; -} - -template -void data_type3::serialize (Archive & ar, const unsigned int version) -{ - ar & BOOST_SERIALIZATION_NVP (values); - return; -} - -/********************/ - -void do_xml_out (void) -{ - // The name for the output data file : - string filename = "pba_10.xml"; - - // A data structure to be stored : - data_type my_data; - - // Fill the vector with arbitrary (possibly non-finite) values : - size_t dim = 6; - my_data.values.reserve (dim); - for (int i = 0; i < dim; ++i) - { - double val = (i + 1) * (1.0 + 3 * numeric_limits::epsilon ()); - if (i == 4) val = numeric_limits::quiet_NaN (); - if (i == 7) val = numeric_limits::infinity (); - if (i == 9) val = -numeric_limits::infinity (); - if (i == 13) val = 0.0; - my_data.values.push_back (val); - } - - // Print: - my_data.print (clog, "Stored data"); - - data_type2 my_data2; - data_type3 my_data3; - - // Open an output file stream in binary mode : - ofstream fout (filename.c_str ()); - - // Save to PBA : - { - // Create an output XML archive attached to the output file : - boost::archive::xml_oarchive oxa (fout); - - // Store (serializing) the data : - oxa & BOOST_SERIALIZATION_NVP(my_data); - oxa & BOOST_SERIALIZATION_NVP(my_data2); - oxa & BOOST_SERIALIZATION_NVP(my_data3); - } - - return; -} - -int main (void) -{ - do_xml_out (); - return 0; -} - -// end of tutorial_pba_10b.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_11.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_11.cpp deleted file mode 100644 index 3e60648..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_11.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/** tutorial_pba_11.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example program compares the times needed to serialize - * and deserialize some large amount of data using PBA and - * text archives. - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -class data_type -{ -private: - friend class boost::serialization::access; - template - void serialize (Archive & ar, const unsigned int version); -public: - void print (ostream & out, const string & title) const; -public: - vector values; - data_type (); -}; - -data_type::data_type () : values () -{ - return; -} - -void data_type::print (ostream & out, const string & title) const -{ - out << endl; - out << title << " :" << endl; - bool skip = false; - for (int i = 0; i < this->values.size (); ++i) - { - if ((i >= 12) && (i < (int) this->values.size () - 8)) - { - if (! skip) out << " ..." << endl; - skip = true; - continue; - } - out.precision (16); - out.width (18); - out << this->values [i] << ' ' ; - if ((i%4) == 3) clog << endl; - } - out << endl; - return; -} - -template -void data_type::serialize (Archive & ar, const unsigned int version) -{ - ar & values; - return; -} - -double do_pba_out (const data_type & a_data) -{ - string filename = "pba_11.data"; - ofstream fout (filename.c_str (), ios_base::binary); - boost::timer io_timer; - { - boost::archive::portable_binary_oarchive opba (fout); - opba & a_data; - } - return io_timer.elapsed (); -} - -double do_pba_in (data_type & a_data) -{ - string filename = "pba_11.data"; - ifstream fin (filename.c_str (), ios_base::binary); - boost::timer io_timer; - { - boost::archive::portable_binary_iarchive ipba (fin); - ipba & a_data; - } - return io_timer.elapsed (); -} - -double do_text_out (const data_type & a_data) -{ - string filename = "pba_11.txt"; - ofstream fout (filename.c_str ()); - boost::timer io_timer; - { - boost::archive::text_oarchive ota (fout); - ota & a_data; - } - return io_timer.elapsed (); -} - -double do_text_in (data_type & a_data) -{ - string filename = "pba_11.txt"; - ifstream fin (filename.c_str ()); - boost::timer io_timer; - { - boost::archive::text_iarchive ita (fin); - ita & a_data; - } - return io_timer.elapsed (); -} - -int main (void) -{ - double elapsed_time_pba_out; - double elapsed_time_text_out; - double elapsed_time_pba_in; - double elapsed_time_text_in; - data_type my_data; // A data structure to be stored then loaded. - - { - // Fill the vector with random values : - size_t dim = 10000000; - my_data.values.reserve (dim); - boost::random::mt19937 rng; - boost::random::uniform_real_distribution<> flat (0.0, 100.0); - for (int i = 0; i < dim; ++i) - { - double val = flat (rng); - my_data.values.push_back (val); - } - my_data.print (clog, "Stored data in PBA and text archive"); - } - - { - // Store in PBA : - elapsed_time_pba_out = do_pba_out (my_data); - } - - { - // Store in text archive : - elapsed_time_text_out = do_text_out (my_data); - } - - { - my_data.values.clear (); - // Load from PBA : - elapsed_time_pba_in = do_pba_in (my_data); - my_data.print (clog, "Loaded data from PBA"); - } - - { - my_data.values.clear (); - // Load from text archive : - elapsed_time_text_in = do_text_in (my_data); - my_data.print (clog, "Loaded data from text archive"); - } - - clog << "PBA store I/O elapsed time : " << elapsed_time_pba_out << " (second)" << endl; - clog << "Text store I/O elapsed time : " << elapsed_time_text_out << " (second)" << endl; - clog << "PBA load I/O elapsed time : " << elapsed_time_pba_in << " (second)" << endl; - clog << "Text load I/O elapsed time : " << elapsed_time_text_in << " (second)" << endl; - - return 0; -} - -// end of tutorial_pba_11.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_2.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_2.cpp deleted file mode 100644 index 7f6c875..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_2.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** tutorial_pba_2.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This sample program shows how to use a portable binary archive - * to store/load floating point numbers including non-finite and - * special (denormalized) values. - * - */ - -#include -#include -#include - -#include -#include - -int main (void) -{ - using namespace std; - - // The name for the example data file : - string filename = "pba_2.data"; - - { - // A normal single precision floating point number : - float pi = 3.14159265; - - // Single precision zeroed floating point number : - float zero = 0.0; - - // A denormalized single precision floating point number : - float tiny = 1.e-40; - - // A single precision floating point number with `+Infinity' value : - float plus_infinity = numeric_limits::infinity (); - - // A single precision floating point number with `-Infinity' value : - float minus_infinity = -numeric_limits::infinity (); - - // A single precision `Not-a-Number' (NaN): - float nan = numeric_limits::quiet_NaN (); - - // Open an output file stream in binary mode : - ofstream fout (filename.c_str (), ios_base::binary); - - { - // Create an output portable binary archive attached to the output file : - boost::archive::portable_binary_oarchive opba (fout); - - // Store (serialize) variables : - opba & pi & zero & tiny & plus_infinity & minus_infinity & nan; - } - } - - { - // Single precision floating point numbers to be loaded : - float x[6]; - - // Open an input file stream in binary mode : - ifstream fin (filename.c_str (), ios_base::binary); - - { - // Create an input portable binary archive attached to the input file : - boost::archive::portable_binary_iarchive ipba (fin); - - // Load (de-serialize) variables using the same - // order than for serialization : - for (int i = 0; i < 6; ++i) - { - ipba & x[i]; - } - } - - // Print : - for (int i = 0; i < 6; ++i) - { - cout.precision (8); - cout << "Loaded x[" << i << "] = " << x[i]; - switch (fp::fpclassify(x[i])) - { - case FP_NAN: cout << " (NaN)"; break; - case FP_INFINITE: cout << " (infinite)"; break; - case FP_SUBNORMAL: cout << " (denormalized)"; break; - case FP_NORMAL: cout << " (normalized)"; break; - } - cout << endl; - } - } - - return 0; -} - -// end of tutorial_pba_2.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_3.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_3.cpp deleted file mode 100644 index 42df3bf..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_3.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/** tutorial_pba_3.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This sample program shows how to use a portable binary archive - * and prevent the serialization of non-finite floating numbers. - * - */ - -#include -#include -#include - -#include - -int main (void) -{ - using namespace std; - - // The name for the example data file : - string filename = "pba_3.data"; - - try - { - // An array of single precision floating numbers: - float x[5]; - x[0] = 3.14159; // Pi - x[1] = 6.022e22; // Avogadro constant - x[2] = 1.6e-19; // Electron charge magnitude - x[3] = 1.e-40; // A tiny (denormalized) value - x[4] = numeric_limits::infinity (); // This will fail while serializing... - - // Open an output file stream in binary mode : - ofstream fout (filename.c_str (), ios_base::binary); - - { - // Create an output portable binary archive attached to the output file, - // using the special 'boost::archive::no_infnan' flag : - boost::archive::portable_binary_oarchive opba (fout, boost::archive::no_infnan); - - // Store (serialize) variables : - for (int i = 0; i < 5; ++i) - { - clog << "Serializing value : " << x[i] << " ... "; - opba & x[i]; - clog << "Ok !" << endl; - } - } - } - catch (exception & x) - { - cerr << "ERROR: " << x.what () << endl; - return 1; - } - - return 0; -} - -// end of tutorial_pba_3.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_4.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_4.cpp deleted file mode 100644 index 61d05f6..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_4.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** tutorial_pba_4.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This sample program shows how to use a portable binary archive - * to store/load integer numbers of various sizes using the Boost - * portable integer typedefs. - * - */ - -#include -#include - -#include -#include -#include - -int main (void) -{ - using namespace std; - - // The name for the example data file : - string filename = "pba_4.data"; - - { - // Some integer numbers : - bool t = true; - char c = 'c'; - unsigned char u = 'u'; - int8_t b = -3; // char - uint8_t B = +6; // unsigned char - int16_t s = -16; - uint16_t S = +32; - int32_t l = -128; - uint32_t L = +127; - int64_t ll = -1024; - uint64_t LL = +2048; - - // Open an output file stream in binary mode : - ofstream fout (filename.c_str (), ios_base::binary); - - { - // Create an output portable binary archive attached to the output file : - boost::archive::portable_binary_oarchive opba (fout); - - // Store (serialize) variables : - opba & t & c & u & b & B & s & S & l & L & ll & LL; - } - } - - { - // Single precision floating numbers to be loaded : - // Some integer numbers : - bool t; - char c; - unsigned char u; - int8_t b; - uint8_t B; - int16_t s; - uint16_t S; - int32_t l; - uint32_t L; - int64_t ll; - uint64_t LL; - - // Open an input file stream in binary mode : - ifstream fin (filename.c_str (), ios_base::binary); - - { - // Create an input portable binary archive attached to the input file : - boost::archive::portable_binary_iarchive ipba (fin); - - // Load (de-serialize) variables using the same - // order than for serialization : - ipba & t & c & u & b & B & s & S & l & L & ll & LL; - } - - clog << "t = " << t << " (bool)" << endl; - clog << "c = '" << c << "' (char)" << endl; - clog << "u = '" << u << "' (unsigned char)" << endl; - clog << "b = " << (int) b << " (int8_t)" << endl; - clog << "B = " << (int) B << " (uint8_t)" << endl; - clog << "s = " << s << " (int16_t)" << endl; - clog << "S = " << S << " (uint16_t)" << endl; - clog << "l = " << l << " (int32_t)" << endl; - clog << "L = " << L << " (uint32_t)" << endl; - clog << "ll = " << ll << " (int64_t)" << endl; - clog << "LL = " << LL << " (uint64_t)" << endl; - } - - return 0; -} - -// end of tutorial_pba_4.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_5.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_5.cpp deleted file mode 100644 index 18f6139..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_5.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/** tutorial_pba_5.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This sample program shows how to use a portable binary archive - * to store/load data in a memory buffer. - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -int main (void) -{ - using namespace std; - - // The memory buffer is implemented using a STL vector : - typedef std::vector buffer_type; - buffer_type buffer; - - { - // Some data to be stored : - bool t = true; - char c = 'c'; - int16_t s = +16; - int32_t l = -128; - int64_t ll = +10000000000; - float pi = 3.14159; - double nan = numeric_limits::quiet_NaN (); - string hello = "World !"; - - buffer.reserve (1024); // pre-allocate some memory - - // The output stream interface to the buffer : - boost::iostreams::stream > output_stream (buffer); - - { - // Create an output portable binary archive attached to the output file : - boost::archive::portable_binary_oarchive opba (output_stream); - - // Store (serialize) variables : - opba & t & c & s & l & ll & pi & nan & hello; - } - - } - - clog << "Buffer content is " << buffer.size () << " bytes : " << endl << " "; - for (int i = 0; i < buffer.size (); ++i) - { - clog << (int) ((unsigned char) buffer[i]) << ' '; - if ((i + 1) % 20 == 0) clog << endl << " "; - } - clog << endl; - - { - // Some data to be loaded : - bool t; - char c; - int16_t s; - int32_t l; - int64_t ll; - float pi; - double nan; - string hello; - - // The input stream interface to the buffer : - boost::iostreams::stream input_stream (&buffer[0], - buffer.size ()); - - { - // Create an input portable binary archive attached to the input file : - boost::archive::portable_binary_iarchive ipba (input_stream); - - // Load (de-serialize) variables : - ipba & t & c & s & l & ll & pi & nan & hello; - } - - clog << "Loaded values from the buffer are: " << endl; - clog << " t = " << t << " (bool)" << endl; - clog << " c = '" << c << "' (char)" << endl; - clog << " s = " << s << " (int16_t)" << endl; - clog << " l = " << l << " (int32_t)" << endl; - clog << " ll = " << ll << " (int64_t)" << endl; - clog << " pi = " << pi << " (float)" << endl; - clog << " nan = " << nan << " (double)" << endl; - clog << " hello = \"" << hello << "\" (std::string)" << endl; - } - - return 0; -} - -// end of tutorial_pba_5.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_6.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_6.cpp deleted file mode 100644 index f32659a..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_6.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/** tutorial_pba_6.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This sample program shows how to use a portable binary archive - * associated to a memory buffer to copy a non-copyable object. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -using namespace std; - -/* A foo noncopyable class */ -struct foo : boost::noncopyable -{ - uint32_t status; - double value; - double special; - - string to_string () const - { - ostringstream sout; - sout << "foo={status=" << status << "; value=" << value << "; special=" << special<< "}"; - return sout.str(); - } - - template - void serialize (Archive & ar, const unsigned int version) - { - ar & status; - ar & value; - ar & special; - return; - } - -}; - -// A templatized copy function for Boost/Serialization equipped classes. -// Here we use PBAs associated to a memory buffer : -template -void copy (const Serializable & source, Serializable & target) -{ - namespace io = boost::iostreams; - namespace ba = boost::archive; - if (&source == &target) return; // self-copy guard - typedef std::vector buffer_type; - buffer_type buffer; - buffer.reserve (1024); - { - io::stream > output_stream (buffer); - ba::portable_binary_oarchive opba (output_stream); - opba & source; - } - { - io::stream input_stream (&buffer[0], buffer.size ()); - ba::portable_binary_iarchive ipba (input_stream); - ipba & target; - } - return; -} - -int main (void) -{ - // Some instance of the 'foo' class : - foo dummy; - dummy.status = 1; - dummy.value = 3.14159; - dummy.special = numeric_limits::quiet_NaN (); - clog << "dummy is : " << dummy.to_string () << endl; - - // Another instance of the 'foo' class : - foo clone; - - /* The following instruction is forbidden because foo - inherits 'boost::noncopyable' : - - clone = dummy; // this ends in a compilation error. - - */ - - // Anyway, we can use this workaround : - copy (dummy, clone); - clog << "clone is : " << clone.to_string () << endl; - - return 0; -} - -// end of tutorial_pba_6.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_7.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_7.cpp deleted file mode 100644 index 30722b1..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_7.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/** tutorial_pba_7.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example shows how the default behaviour of standard - * I/O streams does not support the read/write operations of - * non-finite floating point values in a portable way. - * - */ - -#include -#include -#include -#include - -using namespace std; - -int main (void) -{ - { - float x = numeric_limits::infinity (); - double y = numeric_limits::quiet_NaN (); - cout.precision (8); - cout << "x = " << x << endl; - cout.precision (16); - cout << "y = " << y << endl; - } - - { - string input ("inf nan"); - istringstream iss (input); - float x; - double y; - iss >> x >> y; - if (! iss) - { - cerr << "Cannot read 'x' or 'y' : non finite values are not supported !" << endl; - } - } - return 0; -} - -// end of tutorial_pba_7.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_8.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_8.cpp deleted file mode 100644 index a41e46f..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_8.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/** tutorial_pba_8.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example shows how to store some variables - * of basic types (bool, integer, floating point numbers, STL string) - * using the text or XML archive format associated to a - * standard output file stream supporting portable non-finite - * floating point values. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace std; - -void do_text_out (void) -{ - // The name for the example data text file : - string filename = "pba_8.txt"; - - // Some variables of various primitive types : - bool b = true; - char c = 'B'; - uint32_t answer = 42; - float value = numeric_limits::infinity (); - double precision = numeric_limits::quiet_NaN (); - string question = "What makes you think she's a witch?"; - - // Open an output file stream : - ofstream fout (filename.c_str ()); - - // Prepare the output file stream for inf/NaN support : - locale default_locale (locale::classic (), - new boost::archive::codecvt_null); - locale infnan_locale (default_locale, - new boost::math::nonfinite_num_put); - fout.imbue (infnan_locale); - - { - // Create an output text archive attached to the output file : - boost::archive::text_oarchive ota (fout, boost::archive::no_codecvt); - - // Store (serializing) variables : - ota & b & c & answer & value & precision & question; - } - - return; -} - -void do_xml_out (void) -{ - // The name for the example data XML file : - string filename = "pba_8.xml"; - - // Some variables of various primitive types : - bool b = true; - char c = 'B'; - uint32_t answer = 42; - float value = numeric_limits::infinity (); - double precision = numeric_limits::quiet_NaN (); - string question = "What makes you think she's a witch?"; - - // Open an output file stream : - ofstream fout (filename.c_str ()); - - // Prepare the output file stream for inf/NaN support : - locale default_locale (locale::classic (), - new boost::archive::codecvt_null); - locale infnan_locale (default_locale, - new boost::math::nonfinite_num_put); - fout.imbue (infnan_locale); - - { - // Create an output text archive attached to the output file : - boost::archive::xml_oarchive oxa (fout, boost::archive::no_codecvt); - - // Store (serializing) variables : - oxa & BOOST_SERIALIZATION_NVP(b) - & BOOST_SERIALIZATION_NVP(c) - & BOOST_SERIALIZATION_NVP(answer) - & BOOST_SERIALIZATION_NVP(value) - & BOOST_SERIALIZATION_NVP(precision) - & BOOST_SERIALIZATION_NVP(question); - } - - return; -} - -int main (void) -{ - do_text_out (); - do_xml_out (); - return 0; -} - -// end of tutorial_pba_8.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_9.cpp b/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_9.cpp deleted file mode 100644 index ff564be..0000000 --- a/src/contrib/eos_portable_archive/tutorial/code/tutorial_pba_9.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/** tutorial_pba_9.cpp - * - * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer - * - * Use, modification and distribution is subject to the Boost Software - * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - */ - -/** - * The intent of this program is to serve as a tutorial for - * users of the portable binary archive in the framework of - * the Boost/Serialization library. - * - * This example shows how to load some variables of basic - * types (bool, char, integer, floating point numbers, STL string) - * using the text or XML archive format associated to a - * standard file input stream supporting portable non-finite - * floating point values. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -void do_text_in (void) -{ - // The name for the example data text file : - string filename = "pba_8.txt"; - // Some variables of various primitive types : - bool b; - char c; - uint32_t answer; - float value; - double precision; - string question; - - // Open an input file stream : - ifstream fin (filename.c_str ()); - - // Prepare the input file stream for inf/NaN support : - locale default_locale (locale::classic (), - new boost::archive::codecvt_null); - locale infnan_locale (default_locale, - new boost::math::nonfinite_num_get); - fin.imbue (infnan_locale); - - { - // Create an input text archive attached to the input file : - boost::archive::text_iarchive ita (fin, boost::archive::no_codecvt); - - // Store (serializing) variables : - ita & b & c & answer & value & precision & question; - } - - clog << "Loaded values from text archive are: " << endl; - clog << " b = " << b << endl; - clog << " c = '" << c << "'" << endl; - clog << " answer = " << answer << endl; - clog << " value = " << value << endl; - clog << " precision = " << precision << endl; - clog << " question = \"" << question << "\"" << endl; - - return; -} - -void do_xml_in (void) -{ - // The name for the example data text file : - string filename = "pba_8.xml"; - - // Some variables of various primitive types : - bool b; - char c; - uint32_t answer; - float value; - double precision; - string question; - - // Open an input file stream : - ifstream fin (filename.c_str ()); - - // Prepare the input file stream for inf/NaN support : - locale default_locale (locale::classic (), - new boost::archive::codecvt_null); - locale infnan_locale (default_locale, - new boost::math::nonfinite_num_get); - fin.imbue (infnan_locale); - - { - // Create an output text archive attached to the output file : - boost::archive::xml_iarchive ixa (fin, boost::archive::no_codecvt); - - // Store (serializing) variables : - ixa & BOOST_SERIALIZATION_NVP(b) - & BOOST_SERIALIZATION_NVP(c) - & BOOST_SERIALIZATION_NVP(answer) - & BOOST_SERIALIZATION_NVP(value) - & BOOST_SERIALIZATION_NVP(precision) - & BOOST_SERIALIZATION_NVP(question); - } - - clog << "Loaded values from XML archive are: " << endl; - clog << " b = " << b << endl; - clog << " c = '" << c << "'" << endl; - clog << " answer = " << answer << endl; - clog << " value = " << value << endl; - clog << " precision = " << precision << endl; - clog << " question = \"" << question << "\"" << endl; - - return; -} - -int main (void) -{ - do_text_in (); - do_xml_in (); - return 0; -} - -// end of tutorial_pba_9.cpp diff --git a/src/contrib/eos_portable_archive/tutorial/images/._boost.png b/src/contrib/eos_portable_archive/tutorial/images/._boost.png deleted file mode 100644 index bfd75bc73fd63aa8ecb0784d16cad3137bcd19c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vidt5( z8=`|@22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0NW@x-T(jq diff --git a/src/contrib/eos_portable_archive/tutorial/images/._c++-source-code.png b/src/contrib/eos_portable_archive/tutorial/images/._c++-source-code.png deleted file mode 100644 index f4de9c38d82a214514a47176cc8912d178f58839..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103v+Vkm6 zHbe)*44`snG%bukK2%&ZIX_n~v7jI)Rj;r#u_!UGBr`9S!N9=4(Aw10z{t|jJki=c zKR-PuHKxMIz&WERKR4Cdz|hpl%*DuA*VxFyLf6E?$w1f9$=q4j%*?{V+`!V@*}~Zv z&B{^kXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQM$S0Z?ZXguy^ABqOs}p(wRD zzqBYhRUs|EC|e;juOt=N?aa?h%*m-#$Vp8rQAo;3%*zJ$g`v8JG==JaxL0HtFBa0e37VcyhIDVmU z@{ls-C8mlZam5cr4-}LM9~I+5QpH5B!st{k3!T70hd^+W0NtImr#tP}?9T4a!E3dj1z_;Mr#v4xEk87nE(}rB1UTm zKa|L!Z^8i&PqZ)yF-hzFM_NzLlL93gC7ET zJdxAJ{EsJc$dZZ?qg9C?H%=Uhp!gvq7>XFJZv2qJLp}|JA4)he6fs&g_@M!h`?nMP zFcdLboA{vt4?(r_Roi-xqGx{o#=A#n-1*mS9)0ddf6I7fwa{w^kL-K>P;dG%5-xZs zQRJxBWOpk;5K!*IW}S{3Ju`jj)R{TY{OdN4Fs58ZGa@umc6HJZt5OQL&~}BD_X#6j7>kzV+ag=2Su& z*^ps;xmpNk#CEA4JC#2;tfJUh!dn3pYI(23qBlJfZQ?4fYlU?p*Kk`A1ALJEPpm~v8j|n_ll(i4PgaZ13 zG^>0oNB>dv^v7BKk`xsxS_E!aRn@A>o_1@ALEROB#w}+2tSUIKBs+tQMKi_kkd+_mRx#&-V{N+jAABQf&vNoMc;Ws2q%1) z{8=;hPnY^J(l&BDqp(fNRmFH*7d}&;)-=P+(QOaIiC{Y1G@BPrGfL<=D*F1BCZ@Sa zOsbV+f#(AG(A<7G%6oCf574a>V~i2Jxw^-Ic-e2_{?*KZz$0X1Bn=ytnM z`EQTTK;;B!PeU*KP?{+TxD9#{j(x8m z+Pi!EU+%cGy-EPX28Yf04zXsO9^m%wZ4-NTOm+g=9<&Ru7e=T~7~R42G>SJ3b?%gF z(|_%DTbpS`MX{J(=f?~61|ORUX+o&!TwbBYL1N+xJzXr<;G`BC0?Vi=JuGCj2^uww;Ps)T>wAnJg8$7-muj&@gu7T&kDXSW29Gh-<7o(O+lU5Y2oyiHd?`LK z6crqRa0!{_f8{Et)vKOTh-~)QFLgMExye)oDIxUQ!6R*Ou)C7uGp8SaWGDTA+M9O6 z1y8ubN3U%-(_Q?~EI?>!ZVGSutf$W^7Em<1y|Ge@Gm(&pp=;M0!%3mUi75b2UP0Mn z(>2%({W0YZ$F-2RC5qk!L>*bzq4I`<(AJ4DP;$tl_%r|UMp&ZHZc+koiP=eQ|4K(&ze{(0QnjmthP*Fcy0LzCrRV>Tg!5Kn#ZbqVj zWTmdvO6l}40OQj|^ij4ImtglX*wcv!x+0DuVzgeV2t4u(SwIxQqqrICP8GQ~4iWGZ z`oL@g1NfD^#HE+*!XOg5Y`43iaUoZisr}=2#5r=3LbXzjBxC$N&6eTuP+nBU7p@8XbZ%e=OWn_*B+SieC!^#3vbo)%>dVe zvKI>PI^L}=j%EV)V~50dZv5C~QCd{Wl{)BS-yD}T&4@f`M(?Z$_AxHqc8!*aqnfIz z#jKRhfC{!yL<{+b*s+Jkt%&zQ$g1Y#MRZBgLw>4!+%t@o(!1)bYU2R*^gn!;zzUuW z2et=+iOn^}k3X`@Q#FUoC%^a5-rd{D+SKLHE=VmL(}x0{5c{!P_#t?%JsGrtrCJ&O z8_n==I3Q&6HfRE`er-rUFXReZG#wX(N*%p($~!d9BV?|5{9#eAH6e0kE=s@*F2BQN zbHG?+u5t)B(CCOQj?y>)U^FFrCfpin@7o1!%CpSYo4OUx(aU9X{`jGcymZH&C4{Oh z*C2hz*CgYz>YOPuez%YFl8DNRs#Y!~lPM_i*&?dcJfMOs2qD{Vv%vWxx==QBv`9>K z8D?z{T8MhN6%42ZH;!Y-$C(5s6zLV4y$_K=>vT-@tKIg>geZJamzO{K+dsa_8*+vA z@M^KHuG^5}Zy$>pAmy9$o{fMSoQN;N5|RqRd+hcChHNC;)w+}*cNfb~q{)FyN@=uY&C4Llo&3rg=+zuLu_ zNufs`p`I_BYtw(=sl2&kpQET&kShbp*w)Qa&SRl=qKLhEC_u4H*=RiuJO>^MT%b2+QUuW8)9tL+pT`g0d8FAtfL8rQK9g z!U^Q3o_!f!uPZ+>BOR>}j zkVOl5baFv6gXP?zaR}idWXdEC{a+T1B+-D#$&o}vE75Pe6H2%{O<{LLrk!?rxw*+i zX%_dZ-K`U21b-b30!@2n-|L6=?40y zE|=ZEGWJ6U0fe4^aesSV(Cy`q!RAlN%3EF$lc{(^vGNF7 zTcOCQD#|U+=ZfV_O1k-K?o<}LMyMG9Egsfv4my!~nm+SvEwP=_h=4v^U_(mF;IsBEG z$OC^IOU1>D#Z*3@Uq3i-?GS(bOkGi(YlJwirL7SRp?fx>q^M8DN@|%CXpJA7DiX+J zV=n&jwgGH&9fe}KL-zwE$2bH_zuL8OUU=p)kRAu#IoA0iD=?@$WlmqSvv8^U!RdmvCy1?p)|xqO#PX;I-&*U1J4VY<;v?G@1O z2U1C1Rq`c$4bQEc1k(ZFFofI|k!1*7okkntdIUGBR_w^>#Q33KR`vXg`*DNco*k3a zO3~>+FaNcJM{tb>a;f#JT{7(m?o!7&4?15S7Z^V@n-8wsybAH61l)S|Vr6bgX%+B- z(8~JN_dcsE7F0n%d}0GCWx;w`ALq7S!<*5iZeIfO+IaEi4SIfAQ6)|xAjf0bT$aiY zOXers6bIBm&j+|rWt`55lXyC4gRJ82SG(a7VG;s2huc&6LypK?uJDq`7c2F*ewW2* zca{f0vqDIlTHJeQbjT$WVx5Z?3MJj*+`t=GS3n41HeS5>O0+JfyA5KtIa5!~%?%_1 z>(J<3xQ{g9gb&%-weO8Xl)UoH&)*;j0XJy-)o$BFn6UD+Ckc}f-B?-Nss3h%Q&rVO z!)N``xl+xpq}eb-HiXVxsGeJ@^Bj`WgArw^Tvd}Ix_?5jAk?bK%MiMD&=fv3kwdLkU391`!WGMpvSxUi9Br&brLGHxB=QFu#0CTTff?ETbR6xi6o@ACoOvQ z;8eIPZQJ+1c`jJUD`FzfW%ISE6U(TvG_4tZW1cqSYbtVBxEBQ4e0F*7L)+cjBh5xRfLKopq+ji}BYE@CarWa40D>dhK8Vj%aW)!D23*?v)(l7D6dDr9(@td!T)M}cNJC72> z2`RFW*QzSAd7>M8S#hYfg~-(d`fo+9Bn5@%dE5qz2=gh`KmWU*bmN6S{e$n|=IqES zpIrb3T|N!`@#Oa&YERV+yWKkB9bvq4(<{&YV~AL4fBm+i ziE*Agw^TXxWzm}E)SA&dj%CuVUxS4kSDV6R>SK9yU2=Vrmt*UBC8tFPN75X!!>1X$ zbBW?Ep`R8@@R-8N!4&4AnH#h`>pK76?GKWS?)3+a)jaZu`aJ zm_CqF2bF{?h^W?Ydy*jN_s%aVEqkUZuyBTuty-rcR8sUgpJ-HwakWBG&X;tLcD@Kl zwE#z{T9oyppdU3jisf3VToaAeKAtiM5qI8M$X*J!gH5%KY(_&F7_GzYKj2_r^P`vT zc4J^7k4k~O7ojg_AmN8Ri&CrVuCp7jPDBNv(fX}*vaifLXy287bOh`dfHWg>DWQqG7KNl+W=pqKuJ6Fw-6t&beN0%{vgFNPQr zX098h+!>>1?S{U*)OS=ey`7YQTIk`V0rWS=y3X}+v|OnrVv(J9Z20AodAmM_TpLG` zeF^uB>pFL-Tn7!#cT4y{3B2N4(4yKTfY z5Zsu1ci%@NF-%B<-Q}yJhQ5~wmH)uuNU*-Wvs_X|DGvPk-@iM5_PpE*5^Zv^g@Q(7 zhEt*8JTRmNBqlb-?;VdrBb8EK;%lBCR-nfT<;NEue&VN{cs8#yK0|Q*=Fv{(J)pC} zEP4068Omu2;1Xad-)&9%+ir&+M6llNJ=-RNhEAK_LfkHJzTTbQ;l~c4tSlrY@qAAC z#XEB?ZyN?ep1!!hnam8t`9eua^QAU~58)Rlg6LPL_J)9u^-zH9G7R1h!3dm`PR2)u z^{J20qlx>~?ph*${2=1je&i~u@zDs+zcaIR{L@^6HLVZ*G?*0&p>N;5Zqs^Esj5OX zCkk93;e*2oLGoON;9<0?i4W>La5%W)BC1r3(9bOcR;a;>4c`!Q$T7=*ke2vOgCeAA zN=1jDK^A_jv^zogmKFmKqkiHC$8c`fuyvXiRi&m5#DxdHG17vN4L1n6M4XX--`CS{ zp?&M=k7v(W>9`an z)MmEfxRm#Ob@pfQebrEy{G3+1W_oBaJ(Nk)l=Lm!9z{I4>D2o}Z?& zG6&-Pg;F&siFe;P=-7aOb0>}el}a_0;3+?#?e;{sjU1qLQrEgg2ruMQoB-|v5S2TjS7v*!p8|L-pyw4Xk>eH-ra06dPu<6~EmpW&6a z4nymNIz68u5s&`U_xIo+1ck}%{_4>0-=6w|b-H)=eK<(Gvj6bZv6J?khj&d*-gaZx z@qkGg9d~Ol2 z>Nyyhg$aMr|4w}X;PFMQ`R4$5;PL+X@Aq_7S%}ae$1}&SK{fX5jqtIE>Rfs1^&Q0~ zBzPQPXtcF9kYm#H%q+ZF8u09U{SYWfka+XZ??I_}c-LLt$eEdi-pVfJfAbP`;F?2^76#m|i4zf`Vl8XdZG>o~UXavtzt7S0+v&;65sL{RpC zkMF-zXX3Yyd_Z_e$1?zU;4yG7$1F_v+YcM^1b}T}8z-rte?ic}D|+I`|4AuM!^Dr{ zE4-ec;B_YmHMlw3H|VAfuQa8T0CeKvK`K4?n$clkEHtZcE<@2IDuawEsB z=6QZZ#DSmAkrULn21xk$^f?e3!1rW}7W4$r8KA?+3Ip^C9B&>v`q$sStHT~L$KdH^ z1Q)^NHIYW(He;|KZWcJ{hsH(FQQ_gCJQyLsZ8-b@6T@E$$b?%gy$kmkQ0A`N#^LRO z$bxr1ed06$KW2r5zX)Chi~{gZ%#I_BQ*L(%h$HCe-sx{{5#$LWU&s;i-Li-fw-%yH z8uTmZs(r8j#ytJuqYn}WX6U5J!ExU@p~FBg@4SbAYk_w`8#HZSg062G9)uP_A2X{m zx#xlVwvk1dSrtGC#tXO$-jXMDUwP{=2Q~04oQ5*UjLk^>_3VsmvcNyA~KMXvK);NCX zq2gJllUY|rjMfN#Ix0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2ipn| z1tk;20$QK|000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000DQNkl?OsD>#jIvuEB*is z#6%a6Nmxuz0t8Hypn@A%t@KDca*|3asayB`>c0CzEgb;Af14`+i$z<}6?(S~4VX)cRS#{;g6{J!r7={5# z>6w6p5I8tEz`J+v@cQ*@^z`(A5E4`>l|7}@a9>~FKd0rO0MOFXf^0S$gK3&}<|~;@ zLen%*O5ytfEX&d|naodwkiVWid-l6hiku1-B|B@SA~D9G>pD`Y6w>K5C?zlq1BPKB zl}aTz=cCV`KmU7iaWV5nurLe}hGFv>mk=<eT+x~|7?x~?0#uJ@a!x%Bku z(+i&k3xWVa5HuBzQVP>Fkw}=Jlz?*{gT3!##yS5L!0Phy^5wc>sVP?!ONE~vA(_z&+~ri?Cd;D)E|*oQw6EU2eXF*% zw$cN8tDsFzp7$~L2#|Aq+J&hYTZZuRK$8kd> z&1TWs+KSH3pK<9@7c@-^DWxm%RuV$$Zsp?QBCcJ#)>Pw-K#vaxzeV_m;~9Z#M-`RqcuTn>bgc){pCm&-L2cjrzn_Pb0b1Ix0gQmP|=GBSd}!NIyoZQE{W@h`=FGTl6S^hoXO z?5OXpt*tFJH8rJbe&WrV#m*w76f{lyu$7$irj9&ct1t{>+oI8o-t5WZYb#a*MhH0< zU_lVnf=Mai`#z+U-wn$5eU!`Pn1R~1O+3%T?(QxQ4-fzM%7tMFAp|Ow3ikH)5Cp-o zr!6cj(5qLk!gXD&t*xQ0tqqoCfl>-7C8U(`-bV+d-hcJ9L6TA$Uy+FlA>wh!b={gl zl`k(ZOT#d#Z{EB~0>I|xCOGGDf|CvTEt@^MXN*;Gp7k$}QdMmGDNr*20000$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vx_nht z0iuIp22i;(nifVNA1W@IoS&!cbj9nnLwI+$%B+a{vDW E0MpzzoB#j- diff --git a/src/contrib/eos_portable_archive/tutorial/scripts/jquery-1.4.min.js b/src/contrib/eos_portable_archive/tutorial/scripts/jquery-1.4.min.js deleted file mode 100644 index 5c70e4c..0000000 --- a/src/contrib/eos_portable_archive/tutorial/scripts/jquery-1.4.min.js +++ /dev/null @@ -1,151 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://docs.jquery.com/License - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Jan 13 15:23:05 2010 -0500 - */ -(function(A,w){function oa(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(oa,1);return}c.ready()}}function La(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function $(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var o in b)$(a,o,b[o],f,e,d);return a}if(d!==w){f=!i&&f&&c.isFunction(d);for(o=0;o-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete t[p]}i=c(a.target).closest(f,a.currentTarget); -n=0;for(l=i.length;n)[^>]*$|^#([\w-]+)$/,Pa=/^.[^:#\[\.,]*$/,Qa=/\S/, -Ra=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Sa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],M,ca=Object.prototype.toString,da=Object.prototype.hasOwnProperty,ea=Array.prototype.push,R=Array.prototype.slice,V=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Oa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Sa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])]; -c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ua([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return U.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a)}else return!b||b.jquery?(b||U).find(a):c(b).find(a);else if(c.isFunction(a))return U.ready(a);if(a.selector!==w){this.selector=a.selector; -this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,this)},selector:"",jquery:"1.4",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length= -0;ea.apply(this,a);return this},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject|| -c(null)},push:ea,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length, -htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b, -a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function o(){c.support.noCloneEvent=false;d.detachEvent("onclick",o)});d.cloneNode(true).fireEvent("onclick")}c(function(){var o=s.createElement("div");o.style.width=o.style.paddingLeft="1px";s.body.appendChild(o);c.boxModel=c.support.boxModel=o.offsetWidth===2;s.body.removeChild(o).style.display="none"});a=function(o){var p=s.createElement("div");o="on"+o;var n=o in -p;if(!n){p.setAttribute(o,"return;");n=typeof p[o]==="function"}return n};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var H="jQuery"+K(),Ta=0,ya={},Ua={};c.extend({cache:{},expando:H,noData:{embed:true,object:true,applet:true},data:function(a, -b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var f=a[H],e=c.cache;if(!b&&!f)return null;f||(f=++Ta);if(typeof b==="object"){a[H]=f;e=e[f]=c.extend(true,{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Ua:(e[f]={});if(d!==w){a[H]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var d=a[H],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[H]}catch(i){a.removeAttribute&& -a.removeAttribute(H)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this, -a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this, -a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var za=/[\n\t]/g,fa=/\s+/,Va=/\r/g,Wa=/href|src|style/,Xa=/(button|input)/i,Ya=/(button|input|object|select|textarea)/i,Za=/^(a|area)$/i,Aa=/radio|checkbox/;c.fn.extend({attr:function(a, -b){return $(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.addClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(fa),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i=0;else if(c.nodeName(this,"select")){var z=c.makeArray(t);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),z)>=0});if(!z.length)this.selectedIndex= --1}else this.value=t}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Wa.test(b);if(b in a&&f&&!i){if(e){if(b==="type"&&Xa.test(a.nodeName)&&a.parentNode)throw"type property can't be changed";a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue; -if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Ya.test(a.nodeName)||Za.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var $a=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType=== -3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;if(!d.guid)d.guid=c.guid++;if(f!==w){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):w};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var o,p=0;o=b[p++];){var n=o.split(".");o=n.shift();d.type=n.slice(0).sort().join(".");var t=e[o],z=this.special[o]||{};if(!t){t=e[o]={}; -if(!z.setup||z.setup.call(a,f,n,d)===false)if(a.addEventListener)a.addEventListener(o,i,false);else a.attachEvent&&a.attachEvent("on"+o,i)}if(z.add)if((n=z.add.call(a,d,f,n,t))&&c.isFunction(n)){n.guid=n.guid||d.guid;d=n}t[d.guid]=d;this.global[o]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===w||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/); -for(var o=0;i=b[o++];){var p=i.split(".");i=p.shift();var n=!p.length,t=c.map(p.slice(0).sort(),$a);t=new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.)?")+"(\\.|$)");var z=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var B in f[i])if(n||t.test(f[i][B].type))delete f[i][B];z.remove&&z.remove.call(a,p,j);for(e in f[i])break;if(!e){if(!z.teardown||z.teardown.call(a,p)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+ -i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(B=c.data(a,"handle"))B.elem=null;c.removeData(a,"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[H]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== -8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;var i=c.data(d,"handle");i&&i.apply(d,b);var j,o;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){j=d[e];o=d["on"+e]}}catch(p){}i=c.nodeName(d,"a")&&e==="click";if(!f&&j&&!a.isDefaultPrevented()&&!i){this.triggered=true;try{d[e]()}catch(n){}}else if(o&&d["on"+e].apply(d,b)===false)a.result=false;this.triggered=false;if(!a.isPropagationStopped())(d=d.parentNode||d.ownerDocument)&&c.event.trigger(a,b,d,true)}, -handle:function(a){var b,d;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result}, -props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[H])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement|| -s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&& -a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;c.event.add(this,b.live,qa,b)},remove:function(a){if(a.length){var b=0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],qa)}},special:{}},beforeunload:{setup:function(a, -b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=K();this[H]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped= -ba;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:aa,isPropagationStopped:aa,isImmediatePropagationStopped:aa};var Ba=function(a){for(var b=a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ca=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover", -mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ca:Ba,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ca:Ba)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return pa("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+ -d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return pa("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var ga=/textarea|input|select/i;function Da(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex> --1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ha(a,b){var d=a.target,f,e;if(!(!ga.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Da(d);if(e!==f){if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",e);if(d.type!=="select"&&(f!=null||e)){a.type="change";return c.event.trigger(a,b,this)}}}}c.event.special.change={filters:{focusout:ha,click:function(a){var b=a.target,d=b.type;if(d=== -"radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ha.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ha.call(this,a)},beforeactivate:function(a){a=a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Da(a))}},setup:function(a,b,d){for(var f in W)c.event.add(this,f+".specialChange."+d.guid,W[f]);return ga.test(this.nodeName)}, -remove:function(a,b){for(var d in W)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),W[d]);return ga.test(this.nodeName)}};var W=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d, -f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){thisObject=e;e=f;f=w}var j=b==="one"?c.proxy(e,function(o){c(this).unbind(o,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e,thisObject):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a, -b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d0){y=u;break}}u=u[g]}m[r]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,i=Object.prototype.toString,j=false,o=true;[0,0].sort(function(){o=false;return 0});var p=function(g,h,k,m){k=k||[];var r=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return k;for(var q=[],v,u,y,S,I=true,N=x(h),J=g;(f.exec(""),v=f.exec(J))!==null;){J=v[3];q.push(v[1]);if(v[2]){S=v[3];break}}if(q.length>1&&t.exec(g))if(q.length===2&&n.relative[q[0]])u=ia(q[0]+q[1],h);else for(u=n.relative[q[0]]?[h]:p(q.shift(),h);q.length;){g=q.shift();if(n.relative[g])g+=q.shift(); -u=ia(g,u)}else{if(!m&&q.length>1&&h.nodeType===9&&!N&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){v=p.find(q.shift(),h,N);h=v.expr?p.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:q.pop(),set:B(m)}:p.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&h.parentNode?h.parentNode:h,N);u=v.expr?p.filter(v.expr,v.set):v.set;if(q.length>0)y=B(u);else I=false;for(;q.length;){var E=q.pop();v=E;if(n.relative[E])v=q.pop();else E="";if(v==null)v=h;n.relative[E](y,v,N)}}else y=[]}y||(y=u);if(!y)throw"Syntax error, unrecognized expression: "+ -(E||g);if(i.call(y)==="[object Array]")if(I)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&F(h,y[g])))k.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&k.push(u[g]);else k.push.apply(k,y);else B(y,k);if(S){p(S,r,k,m);p.uniqueSort(k)}return k};p.uniqueSort=function(g){if(D){j=o;g.sort(D);if(j)for(var h=1;h":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,r=g.length;m=0))k||m.push(v);else if(k)h[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,m,r,q){h=g[1].replace(/\\/g,"");if(!q&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,m,r){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=p(g[3],null,null,h);else{g=p.filter(g[3],h,k,true^r);k||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!p(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,k,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return hk[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,m){var r=h[1],q=n.filters[r];if(q)return q(g,k,h,m);else if(r==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(r==="not"){h= -h[3];k=0;for(m=h.length;k=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=n.attrHandle[k]?n.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?k===h:m==="*="?k.indexOf(h)>=0:m==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:m==="!="?k!==h:m==="^="?k.indexOf(h)===0:m==="$="?k.substr(k.length-h.length)===h:m==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,m){var r=n.setFilters[h[2]];if(r)return r(g,k,h,m)}}},t=n.match.POS;for(var z in n.match){n.match[z]=new RegExp(n.match[z].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[z]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[z].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var B=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){B=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,m=g.length;k";var k=s.documentElement;k.insertBefore(g,k.firstChild);if(s.getElementById(h)){n.find.ID=function(m,r,q){if(typeof r.getElementById!=="undefined"&&!q)return(r=r.getElementById(m[1]))?r.id===m[1]||typeof r.getAttributeNode!=="undefined"&& -r.getAttributeNode("id").nodeValue===m[1]?[r]:w:[]};n.filter.ID=function(m,r){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===r}}k.removeChild(g);k=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;k[m];m++)k[m].nodeType===1&&h.push(k[m]);k=h}return k};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=p,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){p=function(m,r,q,v){r=r||s;if(!v&&r.nodeType===9&&!x(r))try{return B(r.querySelectorAll(m),q)}catch(u){}return g(m,r,q,v)};for(var k in g)p[k]=g[k];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,k,m){if(typeof k.getElementsByClassName!=="undefined"&&!m)return k.getElementsByClassName(h[1])};g=null}}})();var F=s.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g, -h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ia=function(g,h){var k=[],m="",r;for(h=h.nodeType?[h]:h;r=n.match.PSEUDO.exec(g);){m+=r[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;r=0;for(var q=h.length;r=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var i=d;i0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i= -{},j;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var p=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,t){for(;t&&t.ownerDocument&&t!==b;){if(p?p.index(t)>-1:c(t).is(a))return t;t=t.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(sa(a[0])||sa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);ab.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||cb.test(f))&&bb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ga=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,db=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/"},G={option:[1,""], -legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};G.optgroup=G.option;G.tbody=G.tfoot=G.colgroup=G.caption=G.thead;G.th=G.td;if(!c.support.htmlSerialize)G._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this); -return d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.getText(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&& -this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this, -"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ga,"").replace(Y,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ta(this,b);ta(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType=== -1?this[0].innerHTML.replace(Ga,""):null;else if(typeof a==="string"&&!/ - - - - - - - - - - - - - - -
-

- Boost

-
-

Boost/Serialization ‐ Portable Binary Archives (PBA)

-

Tutorial

-

NOTE: Naming differs from the source code! This tutorial reflects our hope to get - the eos portable archives an official part of the boost serialization library. - Work is in progress :-) -

-
- - -
-
-
Quick start
- -
- -
Format -
- -
Examples
- -
-
- -

-

-
- -

Quick start

- -Are you impatient to enjoy the Boost Portable Binary Archives (PBA) ? -If so, this section is for you. - -

How to store some simple data in a portable binary output archive

- -

-The tutorial_pba_0.cpp sample -program uses a boost::archive::portable_binary_oarchive object -attached to a standard output file stream to store a couple of -variables of primitive types (bool, -char, integer -numbers, floating numbers) and even a std::string. -

- -
- The tutorial_pba_0.cpp source code DownloadShow/hide -
-/** tutorial_pba_0.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This quick start example shows how to store some variables
- * of basic types (bool, integer, floating point numbers, STL string) 
- * using the portable binary archive format associated to a 
- * standard output file stream.
- *
- */
-
-#include <string>
-#include <fstream>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_oarchive.hpp>
-
-int main (void)
-{
-  // The name for the example data file :  
-  std::string filename = "pba_0.data"; 
-
-  // Some variables of various primitive types :
-  bool        b              = true;
-  char        c              = 'B';
-  uint32_t    answer         = 42;
-  float       computing_time = 7.5e6;
-  double      e              = 2.71828182845905;
-  std::string slogan         = "DON'T PANIC";
-  
-  // Open an output file stream in binary mode :
-  std::ofstream fout (filename.c_str (), std::ios_base::binary);
-  
-  {
-    // Create an output portable binary archive attached to the output file :
-    boost::archive::portable_binary_oarchive opba (fout);
-    
-    // Store (serializing) variables :
-    opba & b & c & answer & computing_time & e & slogan;
-  }
-
-  return 0;   
-}
-
-// end of tutorial_pba_0.cpp
-
-
-

- - -

-The compiled executable creates the pba_0.data file which -contains the following bytes: -

127   1   9   1  84   1  66   1  42   4 192 225 228  74   8 116
- 87  20 139  10 191   5  64   1  11  68  79  78  39  84  32  80
- 65  78  73  67
-
-This format is explained in details below. - - -

Note: -

    -
  • the output of the byte content in the pba_0.data file -can be obtained invoking some command like -  od -t u1 pba_0.data  -on a GNU/Linux system.
    -
  • one should notice that this program makes use of -the typedef-ed integer types from -the boost/cstdint.hpp header (uint32_t...). It is a -strong recommendation to ensure cross-environment portability while -(de)serializing integer numbers (see also -the Examples section). -
-

- - - -
-To top -
-
- - -

How to load some simple data from a portable binary input archive

- -

-The tutorial_pba_1.cpp sample program uses -a boost::archive::portable_binary_iarchive object -attached to a standard input file stream in order to load the -data previously stored by -the tutorial_pba_0.cpp program in -the pba_0.data file. -

- - -
- The tutorial_pba_1.cpp source code DownloadShow/hide -
-/** tutorial_pba_1.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization package. 
- *
- * This quick start example shows how to load some variables
- * of basic types (bool, integer, floating point numbers, STL string) 
- * using the portable binary archive format associated to a 
- * standard input file stream. 
- *
- */
-
-#include <iostream>
-#include <string>
-#include <fstream>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-
-int main (void)
-{
-  using namespace std;
-
-  // The name for the example data file :  
-  string filename = "pba_0.data"; 
-
-  // Some variables of various types :
-  bool     b;
-  char     c;
-  uint32_t answer;
-  float    computing_time;
-  double   e;
-  string   slogan;
-   
-  // Open an input file stream in binary mode :
-  ifstream fin (filename.c_str (), ios_base::binary);
-  
-  {
-    // Create an input portable binary archive attached to the input file :
-    boost::archive::portable_binary_iarchive ipba (fin);
-    
-    // Loading (de-serializing) variables using the same 
-    // order than for serialization (see tutorial_pba_0.cpp) :
-    ipba & b & c & answer & computing_time & e & slogan;
-  }
-
-  cout.precision (15);
-  cout << "Variable 'b' is              : " << b << " " << "(bool)" << endl;
-  cout << "Variable 'c' is              : '" << c << "' " << " " << "(char)" << endl;
-  cout << "Variable 'answer' is         : " << answer  << " " << "(unsigned 32-bit integer)" << endl;
-  cout << "Variable 'computing_time' is : " << computing_time  << " " << "(single precision 32-bit float)" << endl;
-  cout << "Variable 'e' is              : " << e  << " " << "(double precision 64-bit float)" << endl;
-  cout << "Variable 'slogan' is         : \"" << slogan  << "\" " << "(std::string)" << endl;
-
-  return 0;   
-}
-
-// end of tutorial_pba_1.cpp
-
-
-

- - -

-The executable reads the pba_0.data file and deserializes its -contents in the same order it has been stored. It then prints the -restored values of the variables: -

Variable 'b' is              : 1 (bool)
-Variable 'c' is              : 'B'  (char)
-Variable 'answer' is         : 42 (unsigned 32-bit integer)
-Variable 'computing_time' is : 7500000 (single precision 32-bit float)
-Variable 'e' is              : 2.71828182845905 (double precision 64-bit float)
-Variable 'slogan' is         : "DON'T PANIC" (std::string)
-
-

- - - -
-To top -
-
- - - -
-

Format

- -

-This section aims to give some details about the binary format of -portable binary archives (PBA). We will analyse the byte contents of -the sample binary archive pba_0.data file -created by the tutorial_pba_0.cpp -program (see the previous section). -

- -

-Like any other archive format within Boost/Serialization, a PBA starts -with a header (this is the default behaviour but it is possible to -deactivate the use of this header using a special flag at -construction, see this example). This -header is made of two informations : -

    -
  • - a magic byte with the conventionnal decimal value : -
    127
    -
  • - the Boost library version number which is encoded as an integer - number. -

    The PBA encoding of integer numbers uses the following - scheme: - <size> <content>, - where first the size stores the minimal - number of non zero bytes needed to store the binary - representation of the integer value; then the bytes corresponding to the content are stored - starting from the less significant ones (see - also this example). For the library - version number we have here: -

    1 9
    - where 1 is the number of byte needed to store the - value 9 which comes with the Serialization library for - Boost version 1.47.0. Here, the 9 value being less than 256, - one unique byte is enough to store this number. -
-

-

- -

-Now we are done with the header, let's have a look on the serialized data ! -

- -
    -
  • -The first variable is of boolean type with value true. Here -the PBA conventionnaly encodes the true value with the -character 'T' which is stored using the corresponding ASCII -integer value (84). As 84 is less -than 256, this uses only 1 byte: -
    1  84
    -

    - -
  • The next variable uses 1 byte to store a 8-bit -character (char) taking value 'B'. Again the PBA -scheme encodes it using its ASCII integer value -(66). This gives: -
    1  66
    -

    - -
  • Then we have an unsigned 32-bit integer with -value 42 (a fondamental constant from -the H2G2). As the natural binary 32-bit encoding of this value -(<256) only needs -1 non-zero byte, the PBA stores : -
    1  42
    -This scheme results in saving 2 bytes compared to the size of the transient value. -

    - -
  • The next variable is a single precision number with -value 7.5×106. Following the IEEE 754 standard one thus uses -32 bits to encode the sign bit, -the 8-bit exponent and -the 23-bit significant (mantissa). -As 7.5×106 can be rewritten -in +1.78813934×222, we have the -following bits contents:
    -
    -010010101111001001110000111000000

    -where the phantom bit (not stored) is conventionaly set -at 1 and the exponent is stored after -being shifted conventionaly by 27-1=127, thus -(10010101)2=(149)10 -(subscripts indicate the number base) and 149-127=22.
    - -
    -Packing these bits using 4 -bytes, we get:

    - - - - - - - - - - - - - -
    01001010111001001110000111000000
    74228225192
    -
    - -Thus the PBA streams the following 5 bytes (first the size then the content -from the least significant byte to the most significant byte), giving : -
    4 192 225 228 74
    - -
  • The next floating number 2.71828182845905 = -+1.35914091422952×2(1024-1023), -is stored using the double precision IEEE 754 64-bit pattern (using the conventionnal exponent shift 210-1=1023): -

    - - - - - - - - - - - - - - - - - - - - - -
    0100000000000101110111110000101010001011000101000101011101110100
    645191101392087116
    -
    - -Thus the PBA uses the following 9 bytes, the first one for the size (8) and the other ones -for the content (starting with the LSB): -
    8 116 87 20 139 10 191 5 64
    - -
  • Finally the string "DON'T PANIC" is stored: -
      -
    • - first is given the number of characters using the PBA - integer encoding scheme; here - 1 byte is enough to store the - value 11:
      -
      1  11
      -
    • then the array of 11 characters is given using the - corresponding ASCII codes: -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      DON'T PANIC
      6879783984328065787367
      -
      -
      68  79  78  39  84  32  80 65  78  73  67 
      -
    - -
- -

- -

-Now the contents of the pba_0.data file can be fully -understood : -

127   1   9   1  84   1  66   1  42   4 192 225 228  74   8 116
- 87  20 139  10 191   5  64   1  11  68  79  78  39  84  32  80
- 65  78  73  67
-
- -More details about the format (non finite floating point values, -negative integer numbers) will be given in -the sample codes below. -

- - - -
-To top -
-
- - - -
-

Examples

- - - -

Handling special floating point values

- -

-The PBA has been designed in the aims to handle single and double -precision floating point numbers, including non-finite and special values: -

    -
  • ±infinity -
  • NaN (not a number) -
  • denormalized numbers (i.e. floating point numbers with non-guaranteed roundoff precision) -
-

- -

-The tutorial_pba_2.cpp sample program -illustrates the use of such special cases while serializing single precision -floating point numbers: -

- -
- The tutorial_pba_2.cpp source code DownloadShow/hide -
-/** tutorial_pba_2.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This sample program shows how to use a portable binary archive 
- * to store/load floating point numbers including non-finite and 
- * special (denormalized) values.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <limits>
-
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-
-int main (void)
-{
-  using namespace std;
-
-  // The name for the example data file :  
-  string filename = "pba_2.data"; 
-
-  {
-    // A normal single precision floating point number :
-    float pi = 3.14159265; 
-
-    // Single precision zeroed floating point number :
-    float zero = 0.0;
-
-    // A denormalized single precision floating point number :
-    float tiny = 1.e-40;
-    
-    // A single precision floating point number with `+Infinity' value :
-    float plus_infinity = numeric_limits<float>::infinity ();
-    
-    // A single precision floating point number with `-Infinity' value :
-    float minus_infinity = -numeric_limits<float>::infinity ();
-    
-    // A single precision `Not-a-Number' (NaN):
-    float nan = numeric_limits<float>::quiet_NaN ();
-    
-    // Open an output file stream in binary mode :
-    ofstream fout (filename.c_str (), ios_base::binary);
-    
-    {
-      // Create an output portable binary archive attached to the output file :
-      boost::archive::portable_binary_oarchive opba (fout);
-      
-      // Store (serialize) variables :
-      opba & pi & zero & tiny & plus_infinity & minus_infinity & nan;
-    }
-  }
-
-  { 
-    // Single precision floating point numbers to be loaded :
-    float x[6];
-
-    // Open an input file stream in binary mode :
-    ifstream fin (filename.c_str (), ios_base::binary);
-  
-    {
-      // Create an input portable binary archive attached to the input file :
-      boost::archive::portable_binary_iarchive ipba (fin);
-      
-      // Load (de-serialize) variables using the same 
-      // order than for serialization :
-      for (int i = 0; i < 6; ++i)
-	{
-	  ipba & x[i];
-	}
-    }
-
-    // Print :
-    for (int i = 0; i < 6; ++i)
-      {
-	cout.precision (8);
-	cout << "Loaded x[" << i << "] = " << x[i];
-	switch (fp::fpclassify(x[i]))
-	  {
-	  case FP_NAN: cout << " (NaN)"; break;
-	  case FP_INFINITE: cout << " (infinite)"; break;
-	  case FP_SUBNORMAL: cout << " (denormalized)"; break;
-	  case FP_NORMAL:  cout << " (normalized)"; break;
-	  }
-	cout << endl;
-      }
-  }
-
-  return 0;   
-}
-
-// end of tutorial_pba_2.cpp
-
-
-

- - -

-The pba_2.data output data file thus contains the following bytes: -

127   1   9   4 219  15  73  64   0   3 194  22   1   4   0   0
-128 127   4   0   0 128 255   4 255 255 255 127
-
-where: -
    - -
  • 127 1 9 is the standard archive header - -
  • 5 bytes are used to encode the value of π : one byte for the size=4 and 4 bytes for the content - (reversed order): -

    - - - - - - - - - - - - - -
    647315219
    01000000010010010000111111011011
    -
    - and π = +1.5707963×2(128-127) = 3.14159265. - -
  • the value zero is stored using only - one 0 byte (this is called zero optimization and this save bytes for storage). - -
  • a denormalized value then comes with only 3 bytes (note that the MSB byte is zero so it is omitted) -

    - - - - - - - - - - - - - -
    122194
    00000000000000010001011011000010
    -
    - Here the value - is +0.017014027×2(0-127) - = 0.9999946×10-40 which, as expected for - denormalized numbers, misses the requested - value 10-40 by the relative error of - magnitude 5.4×10-6, which is larger than the machine - roundoff precision (~10-7 for the single precision scheme). - -
  • the +∞ value is stored using one byte for the size - plus 4 content bytes, fulfilling the IEEE 754 standard, - i.e. maximal exponent and zero mantissa : -

    - - - - - - - - - - - - - -
    12712800
    01111111100000000000000000000000
    -
    - -
  • the -∞ value is stored using the same scheme as above, but the sign bit : -

    - - - - - - - - - - - - - -
    25512800
    11111111100000000000000000000000
    -
    - -
  • the final NaN value is stored also using one size byte plus 4 content bytes with maximal exponent and non-zero mantissa : -

    - - - - - - - - - - - - - -
    127255255255
    01111111111111111111111111111111
    -
    - See this link for an explanation of the IEEE 754 standard. - -
-

- - - -
-To top -
-
- - - -

Forbidding the serialization of non finite float values

- -

-One can ask a PBA to reject non-finite values. This is done by -passing the boost::archive::no_infnan flag to the constructor -of the output archive. Note that in this case, denormalized values are -still accepted, but infinite and NaNs aren't. -

- -

-The tutorial_pba_3.cpp sample -program that illustrates this special case: -

- -
- The tutorial_pba_3.cpp source code DownloadShow/hide -
-/** tutorial_pba_3.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This sample program shows how to use a portable binary archive 
- * and prevent the serialization of non-finite floating numbers.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <limits>
-
-#include <boost/archive/portable_binary_oarchive.hpp>
-
-int main (void)
-{
-  using namespace std;
-
-  // The name for the example data file :  
-  string filename = "pba_3.data"; 
-
-  try 
-    {
-      // An array of single precision floating numbers:
-      float x[5]; 
-      x[0] = 3.14159;  // Pi
-      x[1] = 6.022e22; // Avogadro constant
-      x[2] = 1.6e-19;  // Electron charge magnitude
-      x[3] = 1.e-40;   // A tiny (denormalized) value
-      x[4] = numeric_limits<float>::infinity (); // This will fail while serializing...
-
-      // Open an output file stream in binary mode :
-      ofstream fout (filename.c_str (), ios_base::binary);
-    
-      {
-	// Create an output portable binary archive attached to the output file,
-	// using the special 'boost::archive::no_infnan' flag :
-	boost::archive::portable_binary_oarchive opba (fout, boost::archive::no_infnan);
-	
-	// Store (serialize) variables :
-	for (int i = 0; i < 5; ++i)
-	  {
-	    clog << "Serializing value : " << x[i] << " ... ";
-	    opba & x[i];
-	    clog << "Ok !" << endl;
-	  }
-      }
-    }
-  catch (exception & x)
-    {
-      cerr << "ERROR: " << x.what () << endl;
-      return 1;
-    }
-
-  return 0;   
-}
-
-// end of tutorial_pba_3.cpp
-
-
-

- - -

-We can check that the PBA now throws an exception as soon as it -encounters a non finite floating point value during the serialization -process: -

-Serializing value : 3.14159 ... Ok !
-Serializing value : 6.022e+22 ... Ok !
-Serializing value : 1.6e-19 ... Ok !
-Serializing value : 9.99995e-41 ... Ok !
-Serializing value : inf ... ERROR: serialization of illegal floating point value: inf
-
-
-

- - - -
-To top -
-
- - - -

Serializing integer numbers

- -

-The PBA obviously handles integer numbers. Unfortunately, C/C++ does -not garantee the portable size of its primitive integer types (short, -int, long... and their unsigned versions). It depends on the -architecture (32-bit/64-bit) and the compiler. -

-

The Boost library -addresses this issue through a collection of typedefs for -integer types of common sizes. This technique is supposed to allow -the manipulation of integer variables in a portable way, typically with -text or XML archives. So, we are generally - encouraged to use the boost/cstdint.hpp header file and -the typedefs defined therein. -

-

Due to its encoding scheme -of integer numbers, the PBA does not strictly need such technique to ensure -a correct behaviour while (de)serializing integer numbers. -This is because the little endian encoding approach allows to only store the non-zero bytes. -It is thus possible to serialize a value using one integer type (short int) and then -deserialize it using another integer type (long long). -

-

-However, for a strict and safe portable behaviour -of PBA, we recommend that, in most cases, the user should systematically use such typedefs for all -serializable integer values. This applies particularly for member attributes -in structs and classes and should allows the transparent switching -to another kind of archive (text, XML) thanks to the serialize template method. -

- -

-The tutorial_pba_4.cpp sample -program illustrates the serialization/deserialization of 8-bit, -16-bit, 32-bit and 64-bit integer numbers: -

- -
- The tutorial_pba_4.cpp source code DownloadShow/hide -
-/** tutorial_pba_4.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This sample program shows how to use a portable binary archive 
- * to store/load integer numbers of various sizes using the Boost 
- * portable integer typedefs.
- *
- */
-
-#include <string>
-#include <fstream>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-
-int main (void)
-{
-  using namespace std;
-
-  // The name for the example data file :  
-  string filename = "pba_4.data"; 
-
-  {
-    // Some integer numbers :
-    bool t = true;
-    char c = 'c';
-    unsigned char u = 'u';
-    int8_t   b = -3; // char
-    uint8_t  B = +6; // unsigned char 
-    int16_t  s = -16;
-    uint16_t S = +32;
-    int32_t  l = -128;
-    uint32_t L = +127;
-    int64_t  ll = -1024;
-    uint64_t LL = +2048;
-
-    // Open an output file stream in binary mode :
-    ofstream fout (filename.c_str (), ios_base::binary);
-    
-    {
-      // Create an output portable binary archive attached to the output file :
-      boost::archive::portable_binary_oarchive opba (fout);
-      
-      // Store (serialize) variables :
-      opba & t & c & u & b & B & s & S & l & L & ll & LL;
-    }
-  }
-
-  { 
-    // Single precision floating numbers to be loaded :
-    // Some integer numbers :
-    bool t;
-    char c;
-    unsigned char u;
-    int8_t   b;
-    uint8_t  B;
-    int16_t  s;
-    uint16_t S;
-    int32_t  l;
-    uint32_t L;
-    int64_t  ll;
-    uint64_t LL;
-
-    // Open an input file stream in binary mode :
-    ifstream fin (filename.c_str (), ios_base::binary);
-  
-    {
-      // Create an input portable binary archive attached to the input file :
-      boost::archive::portable_binary_iarchive ipba (fin);
-      
-      // Load (de-serialize) variables using the same 
-      // order than for serialization :
-      ipba & t & c & u & b & B & s & S & l & L & ll & LL;
-    }
-
-    clog << "t  = " << t << " (bool)" << endl;
-    clog << "c  = '" << c << "' (char)" << endl;
-    clog << "u  = '" << u << "' (unsigned char)" << endl;
-    clog << "b  = " << (int) b << " (int8_t)" << endl;
-    clog << "B  = " << (int) B << " (uint8_t)" << endl;
-    clog << "s  = " << s << " (int16_t)" << endl;
-    clog << "S  = " << S << " (uint16_t)" << endl;
-    clog << "l  = " << l << " (int32_t)" << endl;
-    clog << "L  = " << L << " (uint32_t)" << endl;
-    clog << "ll = " << ll << " (int64_t)" << endl;
-    clog << "LL = " << LL << " (uint64_t)" << endl;
-  }
-
-  return 0;   
-}
-
-// end of tutorial_pba_4.cpp
-
-
-

- - -

-The resulting PBA file is: -

127   1   9   1  84   1  99   1 117 255 253   1   6 255 240   1
- 32 255 128   1 127 254   0 252   2   0   8
-
- -where: -
    - -
  • 127 1 9 is the archive header. - -
  • 1 84 indicates 1 byte to -store the true boolean value (ASCII code -is 84). - -
  • 1 99 indicates 1 byte to -store the ASCII code of character 'c' (99). - -
  • 1 117 indicates 1 byte to -store the ASCII code of character 'u' -(117). - -
  • 255 253 corresponds to the special case for a -negative integer: - 255 is the binary coding for value -1 -which means that the integer is negative and needs 1 byte to be -stored, 253, i.e. the 8-bit encoding of the signed -decimal value -3. - -
  • 1 6 indicates 1 byte to store -value 6. - -
  • 255 240 corresponds again to a negative -integer: - 255 is the byte coding for value -1 -(negative integer encoded using 1 single byte) -and 240 is the 8-bit encoding of decimal -value -16. - -
  • the same scheme is used for all remaining values in the archive : - the verification is let as an exercise. - -
- -

- -

Note that this coding scheme optimizes the number of streamed -bytes. Particularly, it discards the leading zero-ed bytes -(MSB) of the binary encoding of any integer value in order to save -storage. Also we recall that the exact 0 value (zero -or false for a boolean data) is always encoded using a -unique 0 byte (zero optimization). Note this approach is also -used for floating point numbers. -

- - - -
-To top -
-
- - - -

Using PBA serialization with a memory buffer

- -

-In some case, we don't want to serialize some data in a file -(std::ofstream), but we simply plan to stream it in a memory buffer. -

- -

-The tutorial_pba_5.cpp sample -program makes use of a memory buffer implemented with a STL vector of -characters. The PBA is associated to this buffer thanks to a special -streaming interface mechanism provided by the Boost/Iostreams -library. With such technique one can stream serializable data in -some memory buffer in place of a file : -

- -
- The tutorial_pba_5.cpp source code DownloadShow/hide -
-/** tutorial_pba_5.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This sample program shows how to use a portable binary archive 
- * to store/load data in a memory buffer.
- *
- */
-
-#include <string>
-#include <vector>
-
-#include <boost/iostreams/stream.hpp>
-#include <boost/iostreams/device/back_inserter.hpp>
-#include <boost/iostreams/device/array.hpp>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-
-int main (void)
-{
-  using namespace std;
-
-  // The memory buffer is implemented using a STL vector :
-  typedef std::vector<char> buffer_type;
-  buffer_type buffer; 
-
-  {
-    // Some data to be stored :
-    bool    t = true;
-    char    c = 'c';
-    int16_t s = +16;
-    int32_t l = -128;
-    int64_t ll = +10000000000;
-    float   pi = 3.14159;
-    double  nan = numeric_limits<double>::quiet_NaN ();
-    string  hello = "World !";
-
-    buffer.reserve (1024); // pre-allocate some memory
-
-    // The output stream interface to the buffer :
-    boost::iostreams::stream<boost::iostreams::back_insert_device<buffer_type> > output_stream (buffer);
-
-    {    
-      // Create an output portable binary archive attached to the output file :
-      boost::archive::portable_binary_oarchive opba (output_stream);
-      
-      // Store (serialize) variables :
-      opba & t & c & s & l & ll & pi & nan & hello;
-    }
-
-  }
-
-  clog << "Buffer content is " << buffer.size () << " bytes : " << endl << "  ";
-  for (int i = 0; i < buffer.size (); ++i)
-    {
-      clog << (int) ((unsigned char) buffer[i]) << ' '; 
-      if ((i + 1) % 20 == 0) clog << endl << "  ";
-    }
-  clog << endl;
-
-  { 
-    // Some data to be loaded :
-    bool    t;
-    char    c;
-    int16_t s;
-    int32_t l;
-    int64_t ll;
-    float   pi;
-    double  nan;
-    string  hello;
-
-    // The input stream interface to the buffer :
-    boost::iostreams::stream<boost::iostreams::array_source> input_stream (&buffer[0], 
-									   buffer.size ());
-
-    {
-      // Create an input portable binary archive attached to the input file :
-      boost::archive::portable_binary_iarchive ipba (input_stream);
-      
-      // Load (de-serialize) variables :
-      ipba & t & c & s & l & ll & pi & nan & hello;
-    }
-
-    clog << "Loaded values from the buffer are: " << endl;
-    clog << "  t  = " << t << " (bool)" << endl;
-    clog << "  c  = '" << c << "' (char)" << endl;
-    clog << "  s  = " << s << " (int16_t)" << endl;
-    clog << "  l  = " << l << " (int32_t)" << endl;
-    clog << "  ll = " << ll << " (int64_t)" << endl;
-    clog << "  pi = " << pi << " (float)" << endl;
-    clog << "  nan = " << nan << " (double)" << endl;
-    clog << "  hello = \"" << hello << "\" (std::string)" << endl;
-  }
-
-  return 0;   
-}
-
-// end of tutorial_pba_5.cpp
-
-
-

- - -

-After the storing of data in the archive, the content of the buffer of -characters is printed: -

-Buffer content is 40 bytes : 
-  127 1 9 1 84 1 99 1 16 255 128 5 0 228 11 84 2 4 208 15 
-  73 64 8 255 255 255 255 255 255 255 127 1 7 87 111 114 108 100 32 33 
-  
-Loaded values from the buffer are: 
-  t  = 1 (bool)
-  c  = 'c' (char)
-  s  = 16 (int16_t)
-  l  = -128 (int32_t)
-  ll = 10000000000 (int64_t)
-  pi = 3.14159 (float)
-  nan = nan (double)
-  hello = "World !" (std::string)
-
-
-Again the PBA encoding scheme can be easily interpreted. This is let -as an exercise. -

- -

Extra:

-

-You may have a look on the tutorial_pba_6.cpp program that shows a possible — and -provocative — combined usage of the Boost/Serialization concepts, the -Boost/Iostreams facilities and the PBA; it enables the copy of an object -of a non-copyable class. -

- -
- The tutorial_pba_6.cpp source code DownloadShow/hide -
-/** tutorial_pba_6.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of
- * the Boost/Serialization library.
- *
- * This sample program shows how to use a portable binary archive
- * associated to a memory buffer to copy a non-copyable object.
- *
- */
-
-#include <iostream>
-#include <string>
-#include <sstream>
-#include <vector>
-
-#include <boost/utility.hpp>
-#include <boost/iostreams/stream.hpp>
-#include <boost/iostreams/device/back_inserter.hpp>
-#include <boost/iostreams/device/array.hpp>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-
-using namespace std;
-
-/* A foo noncopyable class */
-struct foo : boost::noncopyable
-{
-  uint32_t status;
-  double   value;
-  double   special;
-
-  string to_string () const
-  {
-    ostringstream sout;
-    sout << "foo={status=" << status << "; value=" << value  << "; special=" << special<< "}";
-    return sout.str();
-  }
-
-  template<class Archive>
-  void serialize (Archive & ar, const unsigned int version)
-  {
-    ar & status;
-    ar & value;
-    ar & special;
-    return;
-  }
-
-};
-
-// A templatized copy function for Boost/Serialization equipped classes.
-// Here we use PBAs associated to a memory buffer :
-template <class Serializable>
-void copy (const Serializable & source, Serializable & target)
-{
-  namespace io = boost::iostreams;
-  namespace ba = boost::archive;
-  if (&source == &target) return; // self-copy guard
-  typedef std::vector<char> buffer_type;
-  buffer_type buffer;
-  buffer.reserve (1024);
-  {
-    io::stream<io::back_insert_device<buffer_type> > output_stream (buffer);
-    ba::portable_binary_oarchive opba (output_stream);
-    opba & source;
-  }
-  {
-    io::stream<io::array_source> input_stream (&buffer[0], buffer.size ());
-    ba::portable_binary_iarchive ipba (input_stream);
-    ipba & target;
-  }
-  return;
-}
-
-int main (void)
-{
-  // Some instance of the 'foo' class :
-  foo dummy;
-  dummy.status = 1;
-  dummy.value = 3.14159;
-  dummy.special = numeric_limits<double>::quiet_NaN ();
-  clog << "dummy is : " << dummy.to_string () << endl;
-
-  // Another instance of the 'foo' class :
-  foo clone;
-
-  /* The following instruction is forbidden because foo 
-     inherits 'boost::noncopyable' :
-   
-   clone = dummy; // this ends in a compilation error.
-   
-   */
-
-  // Anyway, we can use this workaround :
-  copy (dummy, clone);
-  clog << "clone is : " << clone.to_string () << endl;
-
-  return 0;
-}
-
-// end of tutorial_pba_6.cpp
-
-
-

- - -

Remark : if a class has been made non-copyable at design, -it is likely for a good reason; so it is not recommended to workaround -this trait using such a trick, unless you know what you are doing -and all the consequences ! -

- - - -
-To top -
-
- - - -

An alternative to PBA using text or XML archives made portable

- -

-In some circonstances, it may be useful to use the Boost text -and XML archives in somewhat portable way. For example, we may -want to benefit of the XML archive's human-friendly format for -debugging purpose before to switch to the PBA for production runs. -However, the text and XML archives provided by the Boost -serialization library are not strictly portable, particularly because -they does not support the serialization of non-finite floating point -numbers. This is because the serialization of floating point numbers -depends on some formatting features of standard I/O streams. See the -tutorial_pba_7.cpp sample program below : -

- -
- The tutorial_pba_7.cpp source code DownloadShow/hide -
-/** tutorial_pba_7.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This example shows how the default behaviour of standard 
- * I/O streams does not support the read/write operations of 
- * non-finite floating point values in a portable way.
- *
- */
-
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <limits>
-
-using namespace std;
-
-int main (void)
-{
-  {
-    float x = numeric_limits<float>::infinity ();
-    double y = numeric_limits<double>::quiet_NaN ();
-    cout.precision (8);
-    cout << "x = " << x << endl;
-    cout.precision (16);
-    cout << "y = " << y << endl;
-  }
-
-  {
-    string input ("inf nan");
-    istringstream iss (input);
-    float x; 
-    double y;
-    iss >> x >> y;
-    if (! iss)
-      {
-	cerr << "Cannot read 'x' or 'y' : non finite values are not supported !" << endl;
-      }
-  }
-  return 0;
-}
-
-// end of tutorial_pba_7.cpp
-
-
-

- - -

-Depending on the system, one can get some various representation -respectively for the infinity and NaN values : -

    -
  • typically on Windows : -
    -1.#INF
    -
    -and -
    --1.#IND
    -
    -
  • and on Linux : -
    -inf
    -
    -and -
    -nan
    -
    - -
-Usually one can print such non finite values in an output stream -(using such a non portable representation), but parsing it from an -input stream fails ! -

- -

-Hopefully this issue can be solved by configuring the I/O streams with -some special locale features provided by Boost -(see this -link). -

- -

-The tutorial_pba_8.cpp program -shows how this can be achieved through the use of special resources -from the boost/archive/codecvt_null.hpp and -boost/math/special_functions/nonfinite_num_facets.hpp headers : -

- -
- The tutorial_pba_8.cpp source code DownloadShow/hide -
-/** tutorial_pba_8.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This example shows how to store some variables
- * of basic types (bool, integer, floating point numbers, STL string) 
- * using the text or XML archive format associated to a 
- * standard output file stream supporting portable non-finite
- * floating point values.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <limits>
-#include <locale>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/xml_oarchive.hpp>
-#include <boost/archive/text_oarchive.hpp>
-#include <boost/serialization/nvp.hpp>
-#include <boost/archive/codecvt_null.hpp>
-#include <boost/math/special_functions/nonfinite_num_facets.hpp>
-
-using namespace std;
-
-void do_text_out (void)
-{
-  // The name for the example data text file :  
-  string filename = "pba_8.txt"; 
-
-  // Some variables of various primitive types :
-  bool        b         = true;
-  char        c         = 'B';
-  uint32_t    answer    = 42;
-  float       value     = numeric_limits<float>::infinity ();
-  double      precision = numeric_limits<double>::quiet_NaN ();
-  string      question  = "What makes you think she's a witch?";
-  
-  // Open an output file stream :
-  ofstream fout (filename.c_str ());
-
-  // Prepare the output file stream for inf/NaN support :
-  locale default_locale (locale::classic (),
-			 new boost::archive::codecvt_null<char>);
-  locale infnan_locale (default_locale,
-			new boost::math::nonfinite_num_put<char>);
-  fout.imbue (infnan_locale);
-  
-  {
-    // Create an output text archive attached to the output file :
-    boost::archive::text_oarchive ota (fout, boost::archive::no_codecvt);
-    
-    // Store (serializing) variables :
-    ota & b & c & answer & value & precision & question;
-  }
-
-  return;   
-}
-
-void do_xml_out (void)
-{
-  // The name for the example data XML file :  
-  string filename = "pba_8.xml"; 
-
-  // Some variables of various primitive types :
-  bool        b         = true;
-  char        c         = 'B';
-  uint32_t    answer    = 42;
-  float       value     = numeric_limits<float>::infinity ();
-  double      precision = numeric_limits<double>::quiet_NaN ();
-  string      question  = "What makes you think she's a witch?";
-  
-  // Open an output file stream :
-  ofstream fout (filename.c_str ());
-
-  // Prepare the output file stream for inf/NaN support :
-  locale default_locale (locale::classic (),
-			 new boost::archive::codecvt_null<char>);
-  locale infnan_locale (default_locale,
-			new boost::math::nonfinite_num_put<char>);
-  fout.imbue (infnan_locale);
-   
-  {
-    // Create an output text archive attached to the output file :
-    boost::archive::xml_oarchive oxa (fout, boost::archive::no_codecvt);
-    
-    // Store (serializing) variables :
-    oxa & BOOST_SERIALIZATION_NVP(b)
-      & BOOST_SERIALIZATION_NVP(c)
-      & BOOST_SERIALIZATION_NVP(answer)
-      & BOOST_SERIALIZATION_NVP(value)
-      & BOOST_SERIALIZATION_NVP(precision) 
-      & BOOST_SERIALIZATION_NVP(question);
-  }
-
-  return;   
-}
-
-int main (void)
-{
-  do_text_out ();
-  do_xml_out ();
-  return 0;
-}
-
-// end of tutorial_pba_8.cpp
-
-
-

- - -

-The program creates two output files : -

    -
  • pba_8.txt stores a text archive with - non finite floating point values : -
    -22 serialization::archive 9 1 66 42 inf nan 35 What makes you think she's a witch?
    -
    -
    -
  • pba_8.xml which stored the equivalent content - using the XML archive format : - -
    -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    -<!DOCTYPE boost_serialization>
    -<boost_serialization signature="serialization::archive" version="9">
    -<b>1</b>
    -<c>66</c>
    -<answer>42</answer>
    -<value>inf</value>
    -<precision>nan</precision>
    -<question>What makes you think she&apos;s a witch?</question>
    -</boost_serialization>
    -
    -
    - - -
-

- -

-The tutorial_pba_9.cpp program -deserializes the data from the text and XML archive files (respectively -pba_8.txt and pba_8.xml) and prints the restored variables : -

-Loaded values from text archive are: 
-  b         = 1
-  c         = 'B'
-  answer    = 42
-  value     = inf
-  precision = nan
-  question  = "What makes you think she's a witch?"
-Loaded values from XML archive are: 
-  b         = 1
-  c         = 'B'
-  answer    = 42
-  value     = inf
-  precision = nan
-  question  = "What makes you think she's a witch?"
-
-
-

- -

-

- The tutorial_pba_9.cpp source code DownloadShow/hide -
-/** tutorial_pba_9.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This example shows how to load some variables of basic 
- * types (bool, char, integer, floating point numbers, STL string) 
- * using the text or XML archive format associated to a 
- * standard file input stream supporting portable non-finite
- * floating point values.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <limits>
-#include <locale>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/xml_iarchive.hpp>
-#include <boost/archive/text_iarchive.hpp>
-#include <boost/serialization/nvp.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/archive/codecvt_null.hpp>
-#include <boost/math/special_functions/nonfinite_num_facets.hpp>
-
-using namespace std;
-
-void do_text_in (void)
-{
-  // The name for the example data text file :  
-  string filename = "pba_8.txt"; 
-  // Some variables of various primitive types :
-  bool        b;
-  char        c;
-  uint32_t    answer;
-  float       value;
-  double      precision;
-  string      question;
-  
-  // Open an input file stream :
-  ifstream fin (filename.c_str ());
-
-  // Prepare the input file stream for inf/NaN support :
-  locale default_locale (locale::classic (),
-			 new boost::archive::codecvt_null<char>);
-  locale infnan_locale (default_locale,
-			new boost::math::nonfinite_num_get<char>);
-  fin.imbue (infnan_locale);
- 
-  {
-    // Create an input text archive attached to the input file :
-    boost::archive::text_iarchive ita (fin, boost::archive::no_codecvt);
-    
-    // Store (serializing) variables :
-    ita & b & c & answer & value & precision & question;
-  }
-
-  clog << "Loaded values from text archive are: " << endl;
-  clog << "  b         = " << b << endl;
-  clog << "  c         = '" << c << "'" <<  endl;
-  clog << "  answer    = " << answer << endl;
-  clog << "  value     = " << value << endl;
-  clog << "  precision = " << precision << endl;
-  clog << "  question  = \"" << question << "\"" << endl;
-
-  return;   
-}
-
-void do_xml_in (void)
-{
-  // The name for the example data text file :  
-  string filename = "pba_8.xml"; 
-
-  // Some variables of various primitive types :
-  bool        b;
-  char        c;
-  uint32_t    answer;
-  float       value;
-  double      precision;
-  string      question;
-  
-  // Open an input file stream :
-  ifstream fin (filename.c_str ());
-
-  // Prepare the input file stream for inf/NaN support :
-  locale default_locale (locale::classic (),
-			 new boost::archive::codecvt_null<char>);
-  locale infnan_locale (default_locale,
-			new boost::math::nonfinite_num_get<char>);
-  fin.imbue (infnan_locale);
-
-  {
-    // Create an output text archive attached to the output file :
-    boost::archive::xml_iarchive ixa (fin, boost::archive::no_codecvt);
-    
-    // Store (serializing) variables :
-    ixa & BOOST_SERIALIZATION_NVP(b)
-      & BOOST_SERIALIZATION_NVP(c)
-      & BOOST_SERIALIZATION_NVP(answer)
-      & BOOST_SERIALIZATION_NVP(value)
-      & BOOST_SERIALIZATION_NVP(precision) 
-      & BOOST_SERIALIZATION_NVP(question);
-  }
-
-  clog << "Loaded values from XML archive are: " << endl;
-  clog << "  b         = " << b << endl;
-  clog << "  c         = '" << c << "'" <<  endl;
-  clog << "  answer    = " << answer << endl;
-  clog << "  value     = " << value << endl;
-  clog << "  precision = " << precision << endl;
-  clog << "  question  = \"" << question << "\"" << endl;
-
-  return;   
-}
-
-int main (void)
-{
-  do_text_in ();
-  do_xml_in ();
-  return 0;
-}
-
-// end of tutorial_pba_9.cpp
-
-
-

- -

- - - -
-To top -
-
- - - -

Using PBA serialization associated with on-the-fly (de)compressed file streams

- -

-The tutorial_pba_10.cpp program -illustrates how to serialize, then deserialize, a class from a PBA associated -to a GZIP compressed file stream, thanks to a technique -provided by the Boost/Iostreams library. The class contains a large -STL vector of double precision floating point numbers with arbitrary values: -

- -
- The tutorial_pba_10.cpp source code DownloadShow/hide -
-/** tutorial_pba_10.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This example shows how use PBAs combined with on-the-fly 
- * compressed I/O streams.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <limits>
-#include <vector>
-
-#include <boost/cstdint.hpp>
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-#include <boost/iostreams/filtering_stream.hpp>
-#include <boost/iostreams/filter/gzip.hpp>
-#include <boost/serialization/access.hpp>
-#include <boost/serialization/vector.hpp>
-
-using namespace std;
-
-class data_type
-{
-private:
-  friend class boost::serialization::access;
-  template<class Archive>
-  void serialize (Archive & ar, const unsigned int version);
-public:
-  void print (ostream & out, const string & title) const;
-public:
-  vector<double> values;
-  data_type ();
-};
-
-data_type::data_type () : values ()
-{
-  return;
-}
-
-void data_type::print (ostream & out, const string & title) const
-{
-  out << endl;
-  out << title << " :" << endl;
-  for (int i = 0; i < this->values.size (); ++i)
-    {
-      out.precision (16);
-      out.width (18);
-      out << this->values [i] << ' ' ;
-      if ((i%4) == 3) clog << endl;
-    }
-  out << endl;
-  return;
-}
-  
-template<class Archive>
-void data_type::serialize (Archive & ar, const unsigned int version)
-{
-  ar & values;
-  return;
-}
-
-void do_gzipped_out (void)
-{
-  // The name for the output data file :  
-  string filename = "pba_10.data.gz"; 
-
-  // A data structure to be stored :
-  data_type my_data;
-
-  // Fill the vector with arbitrary (possibly non-finite) values :
-  size_t dim = 1000;
-  my_data.values.reserve (dim);
-  for (int i = 0; i < dim; ++i)
-    {      
-      double val = (i + 1) * (1.0 + 3 * numeric_limits<double>::epsilon ());
-      if (i == 4) val = numeric_limits<double>::quiet_NaN ();
-      if (i == 23) val = numeric_limits<double>::infinity ();
-      if (i == 73) val = -numeric_limits<double>::infinity ();
-      if (i == 90) val = 0.0;
-      my_data.values.push_back (val);
-    }
-
-  // Print:
-  my_data.print (clog, "Stored data");
-
-  // Create an output filtering stream :
-  boost::iostreams::filtering_ostream zout;
-  zout.push (boost::iostreams::gzip_compressor ());
-  
-  // Open an output file stream in binary mode :
-  ofstream fout (filename.c_str (), ios_base::binary);
-  zout.push (fout);
-
-  // Save to PBA :
-  {
-    // Create an output portable binary archive attached to the output file :
-    boost::archive::portable_binary_oarchive opba (zout);
-    
-    // Store (serializing) the data :
-    opba & my_data;
-  }
-
-  // Clean termination of the streams :
-  zout.flush ();
-  zout.reset ();
-
-  return;   
-}
-
-void do_gzipped_in (void)
-{
-  // The name for the input data file :  
-  string filename = "pba_10.data.gz"; 
-
-  // A data structure to be loaded :
-  data_type my_data;
-
-  // Create an input filtering stream :
-  boost::iostreams::filtering_istream zin;
-  zin.push (boost::iostreams::gzip_decompressor ());
-  
-  // Open an input file stream in binary mode :
-  ifstream fin (filename.c_str (), ios_base::binary);
-  zin.push (fin);
-
-  // Load from PBA :
-  {
-    // Create an input portable binary archive attached to the input file :
-    boost::archive::portable_binary_iarchive ipba (zin);
-    
-    // Load (deserializing) the data :
-    ipba & my_data;
-  }
-
-  // Print:
-  my_data.print (clog, "Loaded data");
-
-  return;   
-}
-
-int main (void)
-{
-  do_gzipped_out (); 
-  do_gzipped_in ();
-  return 0;
-}
-
-// end of tutorial_pba_10.cpp
-
-
-

- - -

The resulting compressed pba_10.data.gz file contains 1,574 bytes. -This has to be compared with the size of the plain (uncompressed) -binary archive which equals 9,001 bytes: - -

127   1   9   0   0   2 232   3   0   8   3   0   0   0   0   0
-240  63   8   3   0   0   0   0   0   0  64   8   4   0   0   0
-  0   0   8  64   8   3   0   0   0   0   0  16  64   8 255 255
-255 255 255 255 255 127   8   4   0   0   0   0   0  24  64   8
-...
-
- -which can be interpreted as : -
    -
  • 3 bytes for the usual archive header : 127 1 -9, -
  • 2 zero-optimized bytes to store the class ID - and the class version :0 0, -
  • 3 bytes to store the size of the vector (1000) using the PBA -representation of integers (2 232 3), -
  • 1 zero-optimized byte to store the class version of the -objects stored in the STL vector (here -the primitive double type) : 0, -
  • 999 non-zero double precision floating point values (including non-finite values) each using 9 bytes (1 byte for -the size and 8 bytes for the content) : 8 ? ? ? ? ? -? ? ?, -
  • 1 zero floating point value that uses only one zero-optimized byte : 0. -
-Thus one here achieves a very interesting compression level. -

-

-It is also possible to use BZIP2 in a similar fashion -(using ressources from the boost/iostreams/filter/bzip2.hpp header -in place of boost/iostreams/filter/gzip.hpp). -

- - - -
-To top -
-
- - -

A simple PBA versus text archive benchmark test

- -

-The tutorial_pba_11.cpp program -runs a benchmark test in the aim to compare the relative fastness of PBA and text archives -both for read and write operations. It stores then loads a vector of many (107) -random double values and prints the associated (de)serialization time for both kinds of archives: -

- -
- The tutorial_pba_11.cpp source code DownloadShow/hide -
-/** tutorial_pba_11.cpp
- *
- * (C) Copyright 2011 François Mauger, Christian Pfligersdorffer
- *
- * Use, modification and distribution is subject to the Boost Software
- * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-/**
- * The intent of this program is to serve as a tutorial for
- * users of the portable binary archive in the framework of 
- * the Boost/Serialization library. 
- *
- * This example program compares the times needed to serialize
- * and deserialize some large amount of data using PBA and 
- * text archives.
- *
- */
-
-#include <string>
-#include <fstream>
-#include <vector>
-
-#include <boost/archive/portable_binary_oarchive.hpp>
-#include <boost/archive/portable_binary_iarchive.hpp>
-#include <boost/archive/text_oarchive.hpp>
-#include <boost/archive/text_iarchive.hpp>
-#include <boost/serialization/access.hpp>
-#include <boost/serialization/vector.hpp>
-#include <boost/random/mersenne_twister.hpp>
-#include <boost/random/uniform_real_distribution.hpp>
-#include <boost/timer.hpp>
-
-using namespace std;
-
-class data_type
-{
-private:
-  friend class boost::serialization::access;
-  template<class Archive>
-  void serialize (Archive & ar, const unsigned int version);
-public:
-  void print (ostream & out, const string & title) const;
-public:
-  vector<double> values;
-  data_type ();
-};
-
-data_type::data_type () : values ()
-{
-  return;
-}
-
-void data_type::print (ostream & out, const string & title) const
-{
-  out << endl;
-  out << title << " :" << endl;
-  bool skip = false;
-  for (int i = 0; i < this->values.size (); ++i)
-    {
-      if ((i >= 12) && (i < (int) this->values.size () - 8)) 
-	{
-	  if (! skip) out << " ..." << endl;
-	  skip = true;
-	  continue;
-	}
-      out.precision (16);
-      out.width (18);
-      out << this->values [i] << ' ' ;
-      if ((i%4) == 3) clog << endl;
-    }
-  out << endl;
-  return;
-}
-  
-template<class Archive>
-void data_type::serialize (Archive & ar, const unsigned int version)
-{
-  ar & values;
-  return;
-}
-
-double do_pba_out (const data_type & a_data)
-{
-  string filename = "pba_11.data"; 
-  ofstream fout (filename.c_str (), ios_base::binary);
-  boost::timer io_timer;    
-  {
-    boost::archive::portable_binary_oarchive opba (fout);
-    opba & a_data;
-  }
-  return io_timer.elapsed ();
-}
-
-double do_pba_in (data_type & a_data)
-{
-  string filename = "pba_11.data"; 
-  ifstream fin (filename.c_str (), ios_base::binary);
-  boost::timer io_timer;    
-  {
-    boost::archive::portable_binary_iarchive ipba (fin);
-    ipba & a_data;
-  }
-  return io_timer.elapsed ();
-}
-
-double do_text_out (const data_type & a_data)
-{
-  string filename = "pba_11.txt"; 
-  ofstream fout (filename.c_str ());
-  boost::timer io_timer;    
-  {
-    boost::archive::text_oarchive ota (fout);
-    ota & a_data;
-  }
-  return io_timer.elapsed ();
-}
-
-double do_text_in (data_type & a_data)
-{
-  string filename = "pba_11.txt"; 
-  ifstream fin (filename.c_str ());
-  boost::timer io_timer;    
-  {
-    boost::archive::text_iarchive ita (fin);
-    ita & a_data;
-  }
-  return io_timer.elapsed ();
-}
-
-int main (void)
-{
-  double elapsed_time_pba_out; 
-  double elapsed_time_text_out; 
-  double elapsed_time_pba_in; 
-  double elapsed_time_text_in; 
-  data_type my_data; // A data structure to be stored then loaded.
-
-  {
-    // Fill the vector with random values :
-    size_t dim = 10000000;
-    my_data.values.reserve (dim);
-    boost::random::mt19937 rng;
-    boost::random::uniform_real_distribution<> flat (0.0, 100.0);
-    for (int i = 0; i < dim; ++i)
-      {      
-	double val = flat (rng);
-	my_data.values.push_back (val);
-      }
-    my_data.print (clog, "Stored data in PBA and text archive");
-  }
-
-  {
-    // Store in PBA :
-    elapsed_time_pba_out = do_pba_out (my_data);
-  }
-
-  {
-    // Store in text archive :
-    elapsed_time_text_out = do_text_out (my_data);
-  }     
-
-  {
-    my_data.values.clear ();
-    // Load from PBA :
-    elapsed_time_pba_in = do_pba_in (my_data);
-    my_data.print (clog, "Loaded data from PBA");
-  }
-
-  {
-    my_data.values.clear ();
-    // Load from text archive :
-    elapsed_time_text_in = do_text_in (my_data);
-    my_data.print (clog, "Loaded data from text archive");
-  }
-  
-  clog << "PBA  store I/O elapsed time : " << elapsed_time_pba_out  << " (second)" << endl;
-  clog << "Text store I/O elapsed time : " << elapsed_time_text_out << " (second)" << endl;  
-  clog << "PBA  load  I/O elapsed time : " << elapsed_time_pba_in   << " (second)" << endl;
-  clog << "Text load  I/O elapsed time : " << elapsed_time_text_in  << " (second)" << endl;
-
-  return 0;
-}
-
-// end of tutorial_pba_11.cpp
-
-
-

- - -

On a 1.60 GHz processor running gcc 4.5.2 on Linux 2.6.38, the result is the following: -

PBA  store I/O elapsed time : 1.86 (second)
-Text store I/O elapsed time : 22.66 (second)
-PBA  load  I/O elapsed time : 1.53 (second)
-Text load  I/O elapsed time : 19.71 (second)
-
-It this simple case, the use of portable binary archives is faster by at least a factor 10 -compared to the traditional Boost text archives. This is a -significant saving in time. These performances are highly desirable in the typical framework -of scientific/computing activities where large amounts of data are accessed through files. -The PBA concept is thus a valuable candidate for such applications. -

- -

-One can also consider the sizes of the resulting archive files: -

    -
  • pba_11.data (PBA) : 90,000,010 bytes -
  • pba_11.txt (text archive) : 189,000,040 bytes -
-The PBA allows to save a typical factor 2 in storage space compared to text archive. -This is another strong argument for using PBA. -

- - - -
-To top -
-
- - - -
-

Revised 2011-11-07 -

© Copyright François Mauger, -Christian Pfligersdorffer 2011.
-Distributed under the Boost Software License, Version 1.0.
-(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -
-

- - - - - diff --git a/src/contrib/epee/LICENSE.txt b/src/contrib/epee/LICENSE.txt deleted file mode 100644 index 4a6b529..0000000 --- a/src/contrib/epee/LICENSE.txt +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Andrey N. Sabelnikov nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL Andrey N. Sabelnikov BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/contrib/epee/README.md b/src/contrib/epee/README.md deleted file mode 100644 index a69884f..0000000 --- a/src/contrib/epee/README.md +++ /dev/null @@ -1 +0,0 @@ -epee - is a small library of helpers, wrappers, tools and and so on, used to make my life easier. \ No newline at end of file diff --git a/src/contrib/epee/demo/.gitignore b/src/contrib/epee/demo/.gitignore deleted file mode 100644 index d9b4f01..0000000 --- a/src/contrib/epee/demo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/src/contrib/epee/demo/CMakeLists.txt b/src/contrib/epee/demo/CMakeLists.txt deleted file mode 100644 index b4ac2cc..0000000 --- a/src/contrib/epee/demo/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -set(Boost_USE_MULTITHREADED ON) -#set(Boost_DEBUG 1) -find_package(Boost COMPONENTS system filesystem thread date_time chrono regex ) - -include_directories( ${Boost_INCLUDE_DIRS} ) - - -IF (MSVC) - add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /nologo /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /bigobj" ) -ELSE() - # set stuff for other systems - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder -D_GNU_SOURCE") -ENDIF() - - -include_directories(.) -include_directories(../include) -include_directories(iface) - - -# Add folders to filters -file(GLOB_RECURSE LEVIN_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_levin_server/*.cpp) - -file(GLOB_RECURSE HTTP_GENERAL_SECTION RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.inl - ${CMAKE_CURRENT_SOURCE_DIR}/demo_http_server/*.cpp) - - - -source_group(general FILES ${LEVIN_GENERAL_SECTION} FILES ${HTTP_GENERAL_SECTION}) -#source_group(general FILES ${HTTP_GENERAL_SECTION}) - -add_executable(demo_http_server ${HTTP_GENERAL_SECTION} ) -add_executable(demo_levin_server ${LEVIN_GENERAL_SECTION} ) - -target_link_libraries( demo_http_server ${Boost_LIBRARIES} ) -target_link_libraries( demo_levin_server ${Boost_LIBRARIES} ) - -IF (NOT WIN32) - target_link_libraries (demo_http_server rt) - target_link_libraries (demo_levin_server rt) -ENDIF() - - diff --git a/src/contrib/epee/demo/README.txt b/src/contrib/epee/demo/README.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/contrib/epee/demo/demo_http_server/demo_http_server.cpp b/src/contrib/epee/demo/demo_http_server/demo_http_server.cpp deleted file mode 100644 index 85547e4..0000000 --- a/src/contrib/epee/demo/demo_http_server/demo_http_server.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "stdafx.h" -#include "console_handler.h" -#include "demo_http_server.h" -#include "net/http_client.h" -#include "storages/http_abstract_invoke.h" - - -template -bool communicate(const std::string url, t_request& req, t_response& rsp, const std::string& ip, const std::string& port, bool use_json, bool use_jrpc = false) -{ - epee::net_utils::http::http_simple_client http_client; - bool r = http_client.connect(ip, port, 1000); - CHECK_AND_ASSERT_MES(r, false, "failed to connect"); - if(use_json) - { - if(use_jrpc) - { - epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); - req_t.jsonrpc = "2.0"; - req_t.id = epee::serialization::storage_entry(10); - req_t.method = "command_example_1"; - req_t.params = req; - epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); - if(!epee::net_utils::invoke_http_json_remote_command2("/request_json_rpc", req_t, resp_t, http_client)) - { - return false; - } - rsp = resp_t.result; - return true; - }else - return epee::net_utils::invoke_http_json_remote_command2(url, req, rsp, http_client); - } - else - return epee::net_utils::invoke_http_bin_remote_command2(url, req, rsp, http_client); -} - - -int main(int argc, char* argv[]) -{ - TRY_ENTRY(); - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - - LOG_PRINT("Demo server starting ...", LOG_LEVEL_0); - - - demo::demo_http_server srv; - - start_default_console(&srv, "#"); - - std::string bind_param = "0.0.0.0"; - std::string port = "83"; - - if(!srv.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - //log loop - srv.run(); - size_t count = 0; - while (!srv.is_stop()) - { - - demo::COMMAND_EXAMPLE_1::request req; - req.sub = demo::get_test_data(); - demo::COMMAND_EXAMPLE_1::response rsp; - bool r = false; - if(count%2) - {//invoke json - r = communicate("/request_api_json_1", req, rsp, "127.0.0.1", port, true, true); - }else{ - r = communicate("/request_api_bin_1", req, rsp, "127.0.0.1", port, false); - } - CHECK_AND_ASSERT_MES(r, false, "failed to invoke http request"); - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - //misc_utils::sleep_no_w(1000); - ++count; - } - bool r = srv.wait_stop(); - CHECK_AND_ASSERT_MES(r, 1, "failed to wait server stop"); - srv.deinit(); - - LOG_PRINT("Demo server stoped.", LOG_LEVEL_0); - return 1; - - CATCH_ENTRY_L0("main", 1); -} - -/************************************************************************/ -/* */ -/************************************************************************/ -namespace demo -{ - bool demo_http_server::init(const std::string& bind_port, const std::string& bind_ip) - { - - - //set self as callback handler - m_net_server.get_config_object().m_phandler = this; - - //here set folder for hosting reqests - m_net_server.get_config_object().m_folder = ""; - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool demo_http_server::run() - { - m_stop = false; - //here you can set worker threads count - int thrds_count = 4; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count, false)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - return true; - } - - bool demo_http_server::deinit() - { - return m_net_server.deinit_server(); - } - - bool demo_http_server::send_stop_signal() - { - m_stop = true; - m_net_server.send_stop_signal(); - return true; - } - - bool demo_http_server::on_requestr_uri_1(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - return true; - } - - - bool demo_http_server::on_requestr_uri_2(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - return true; - } - - - bool demo_http_server::on_hosting_request( const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context) - { - //read file from filesystem here - return true; - } - - bool demo_http_server::on_request_api_1(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, connection_context& ctxt) - { - CHECK_AND_ASSERT_MES(req.sub == demo::get_test_data(), false, "wrong request"); - res.m_success = true; - res.subs.push_back(req.sub); - return true; - } - - bool demo_http_server::on_request_api_1_with_error(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, epee::json_rpc::error& error_resp, connection_context& ctxt) - { - error_resp.code = 232432; - error_resp.message = "bla bla bla"; - return false; - } - - bool demo_http_server::on_request_api_2(const COMMAND_EXAMPLE_2::request& req, COMMAND_EXAMPLE_2::response& res, connection_context& ctxt) - { - return true; - } -} diff --git a/src/contrib/epee/demo/demo_http_server/demo_http_server.h b/src/contrib/epee/demo/demo_http_server/demo_http_server.h deleted file mode 100644 index 088ead5..0000000 --- a/src/contrib/epee/demo/demo_http_server/demo_http_server.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "net/http_server_cp2.h" -#include "transport_defs.h" -#include "net/http_server_handlers_map2.h" - -using namespace epee; - -namespace demo -{ - - class demo_http_server: public net_utils::http::i_http_server_handler - { - public: - typedef epee::net_utils::connection_context_base connection_context; - - demo_http_server():m_stop(false){} - bool run(); - bool init(const std::string& bind_port = "11112", const std::string& bind_ip = "0.0.0.0"); - bool deinit(); - bool send_stop_signal(); - bool is_stop(){return m_stop;} - bool wait_stop(){return m_net_server.timed_wait_server_stop(100000);} - private: - - - CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map - - BEGIN_URI_MAP2() - MAP_URI2("/requestr_uri_1", on_requestr_uri_1) - MAP_URI2("/requestr_uri_2", on_requestr_uri_1) - //MAP_URI_AUTO_XML2("/request_api_xml_1", on_request_api_1, COMMAND_EXAMPLE_1) - //MAP_URI_AUTO_XML2("/request_api_xml_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_URI_AUTO_JON2("/request_api_json_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_URI_AUTO_JON2("/request_api_json_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_URI_AUTO_BIN2("/request_api_bin_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_URI_AUTO_BIN2("/request_api_bin_2", on_request_api_2, COMMAND_EXAMPLE_2) - BEGIN_JSON_RPC_MAP("/request_json_rpc") - MAP_JON_RPC("command_example_1", on_request_api_1, COMMAND_EXAMPLE_1) - MAP_JON_RPC("command_example_2", on_request_api_2, COMMAND_EXAMPLE_2) - MAP_JON_RPC_WE("command_example_1_we", on_request_api_1_with_error, COMMAND_EXAMPLE_1) - END_JSON_RPC_MAP() - CHAIN_URI_MAP2(on_hosting_request) - END_URI_MAP2() - - - - bool on_requestr_uri_1(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - - bool on_requestr_uri_2(const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - - - - bool on_hosting_request( const net_utils::http::http_request_info& query_info, - net_utils::http::http_response_info& response, - const net_utils::connection_context_base& m_conn_context); - - bool on_request_api_1(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, connection_context& ctxt); - bool on_request_api_2(const COMMAND_EXAMPLE_2::request& req, COMMAND_EXAMPLE_2::response& res, connection_context& ctxt); - - bool on_request_api_1_with_error(const COMMAND_EXAMPLE_1::request& req, COMMAND_EXAMPLE_1::response& res, epee::json_rpc::error& error_resp, connection_context& ctxt); - - net_utils::boosted_http_server_custum_handling m_net_server; - std::atomic m_stop; - }; -} - diff --git a/src/contrib/epee/demo/demo_http_server/stdafx.cpp b/src/contrib/epee/demo/demo_http_server/stdafx.cpp deleted file mode 100644 index ecec246..0000000 --- a/src/contrib/epee/demo/demo_http_server/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// demo_http_server.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/src/contrib/epee/demo/demo_http_server/stdafx.h b/src/contrib/epee/demo/demo_http_server/stdafx.h deleted file mode 100644 index e288832..0000000 --- a/src/contrib/epee/demo/demo_http_server/stdafx.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" - - diff --git a/src/contrib/epee/demo/demo_http_server/targetver.h b/src/contrib/epee/demo/demo_http_server/targetver.h deleted file mode 100644 index 6fe8eb7..0000000 --- a/src/contrib/epee/demo/demo_http_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/src/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp b/src/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp deleted file mode 100644 index a99a1f5..0000000 --- a/src/contrib/epee/demo/demo_levin_server/demo_levin_server.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "stdafx.h" -#include "demo_levin_server.h" -#include "console_handler.h" - - -template -bool communicate(net_utils::boosted_levin_async_server& transport, int id, t_request& req, const std::string& ip, const std::string& port, bool use_async) -{ - if(use_async) - { - //IMPORTANT: do not pass local parameters from stack by reference! connect_async returns immediately, and callback will call in any thread later - transport.connect_async(ip, port, 10000, [&transport, id, req, ip, port](net_utils::connection_context_base& ctx, const boost::system::error_code& ec_) - { - if(!!ec_) - { - LOG_ERROR("Failed to connect to " << ip << ":" << port); - }else - {//connected ok! - - epee::net_utils::async_invoke_remote_command2(ctx.m_connection_id, id, req, transport.get_config_object(), [&transport, ip, port](int res_code, demo::COMMAND_EXAMPLE_1::response& rsp, net_utils::connection_context_base& ctx) - { - if(res_code < 0) - { - LOG_ERROR("Failed to invoke to " << ip << ":" << port); - }else - {//invoked ok - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 async invoked ok", LOG_LEVEL_0); - } - transport.get_config_object().close(ctx.m_connection_id); - return true; - }); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 async invoke requested", LOG_LEVEL_0); - } - }); - }else - { - net_utils::connection_context_base ctx = AUTO_VAL_INIT(ctx); - bool r = transport.connect(ip, port, 10000, ctx); - CHECK_AND_ASSERT_MES(r, false, "failed to connect to " << ip << ":" << port); - demo::COMMAND_EXAMPLE_1::response rsp = AUTO_VAL_INIT(rsp); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 sync invoke requested", LOG_LEVEL_0); - r = epee::net_utils::invoke_remote_command2(ctx.m_connection_id, id, req, rsp, transport.get_config_object()); - CHECK_AND_ASSERT_MES(r, false, "failed to invoke levin request"); - CHECK_AND_ASSERT_MES(rsp.m_success, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.size()==1, false, "wrong response"); - CHECK_AND_ASSERT_MES(rsp.subs.front() == demo::get_test_data(), false, "wrong response"); - transport.get_config_object().close(ctx.m_connection_id); - LOG_PRINT_GREEN("Client COMMAND_EXAMPLE_1 sync invoked ok", LOG_LEVEL_0); - } - return true; -} - - -int main(int argc, char* argv[]) -{ - TRY_ENTRY(); - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - - LOG_PRINT("Demo server starting ...", LOG_LEVEL_0); - - - demo::demo_levin_server srv; - - start_default_console(&srv, "#"); - - std::string bind_param = "0.0.0.0"; - std::string port = "12345"; - - if(!srv.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv.run(); - - size_t c = 1; - while (!srv.is_stop()) - { - - demo::COMMAND_EXAMPLE_1::request req; - req.sub = demo::get_test_data(); - bool r = communicate(srv.get_server(), demo::COMMAND_EXAMPLE_1::ID, req, "127.0.0.1", port, (c%2 == 0)); - misc_utils::sleep_no_w(1000); - ++c; - } - bool r = srv.wait_stop(); - CHECK_AND_ASSERT_MES(r, 1, "failed to wait server stop"); - - - srv.deinit(); - - LOG_PRINT("Demo server stoped.", LOG_LEVEL_0); - return 1; - - CATCH_ENTRY_L0("main", 1); -} - -/************************************************************************/ -/* */ -/************************************************************************/ -namespace demo -{ - bool demo_levin_server::init(const std::string& bind_port, const std::string& bind_ip) - { - m_net_server.get_config_object().m_pcommands_handler = this; - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool demo_levin_server::run() - { - m_stop = false; - //here you can set worker threads count - int thrds_count = 4; - m_net_server.get_config_object().m_invoke_timeout = 10000; - m_net_server.get_config_object().m_pcommands_handler = this; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count, false)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool demo_levin_server::deinit() - { - return m_net_server.deinit_server(); - } - - bool demo_levin_server::send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - int demo_levin_server::handle_command_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context) - { - CHECK_AND_ASSERT_MES(arg.sub == demo::get_test_data(), false, "wrong request"); - rsp.m_success = true; - rsp.subs.push_back(arg.sub); - LOG_PRINT_GREEN("Server COMMAND_EXAMPLE_1 ok", LOG_LEVEL_0); - return 1; - } - int demo_levin_server::handle_command_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - return 1; - } - int demo_levin_server::handle_notify_1(int command, COMMAND_EXAMPLE_1::request& arg, const net_utils::connection_context_base& context) - { - return 1; - } - int demo_levin_server::handle_notify_2(int command, COMMAND_EXAMPLE_2::request& arg, const net_utils::connection_context_base& context) - { - return 1; - } -} diff --git a/src/contrib/epee/demo/demo_levin_server/demo_levin_server.h b/src/contrib/epee/demo/demo_levin_server/demo_levin_server.h deleted file mode 100644 index 5a6f68f..0000000 --- a/src/contrib/epee/demo/demo_levin_server/demo_levin_server.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "net/levin_server_cp2.h" -#include "transport_defs.h" -#include "storages/levin_abstract_invoke2.h" - -using namespace epee; - -namespace demo -{ - - class demo_levin_server: public levin::levin_commands_handler<> - { - public: - bool run(); - bool init(const std::string& bind_port = "11112", const std::string& bind_ip = "0.0.0.0"); - bool deinit(); - bool send_stop_signal(); - bool is_stop(){return m_stop;} - bool wait_stop(){return m_net_server.timed_wait_server_stop(100000);} - net_utils::boosted_levin_async_server& get_server(){return m_net_server;} - private: - - - CHAIN_LEVIN_INVOKE_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP2(demo_levin_server) - HANDLE_INVOKE_T2(COMMAND_EXAMPLE_1, &demo_levin_server::handle_command_1) - HANDLE_INVOKE_T2(COMMAND_EXAMPLE_2, &demo_levin_server::handle_command_2) - HANDLE_NOTIFY_T2(COMMAND_EXAMPLE_1, &demo_levin_server::handle_notify_1) - HANDLE_NOTIFY_T2(COMMAND_EXAMPLE_2, &demo_levin_server::handle_notify_2) - END_INVOKE_MAP2() - - //----------------- commands handlers ---------------------------------------------- - int handle_command_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context); - int handle_command_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context); - int handle_notify_1(int command, COMMAND_EXAMPLE_1::request& arg, const net_utils::connection_context_base& context); - int handle_notify_2(int command, COMMAND_EXAMPLE_2::request& arg, const net_utils::connection_context_base& context); - //---------------------------------------------------------------------------------- - net_utils::boosted_levin_async_server m_net_server; - std::atomic m_stop; - - }; -} - diff --git a/src/contrib/epee/demo/demo_levin_server/stdafx.cpp b/src/contrib/epee/demo/demo_levin_server/stdafx.cpp deleted file mode 100644 index d6ea1c6..0000000 --- a/src/contrib/epee/demo/demo_levin_server/stdafx.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "stdafx.h" - diff --git a/src/contrib/epee/demo/demo_levin_server/stdafx.h b/src/contrib/epee/demo/demo_levin_server/stdafx.h deleted file mode 100644 index e288832..0000000 --- a/src/contrib/epee/demo/demo_levin_server/stdafx.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "targetver.h" - - -#include - - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" - - diff --git a/src/contrib/epee/demo/demo_levin_server/targetver.h b/src/contrib/epee/demo/demo_levin_server/targetver.h deleted file mode 100644 index 6fe8eb7..0000000 --- a/src/contrib/epee/demo/demo_levin_server/targetver.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - diff --git a/src/contrib/epee/demo/generate_gcc.sh b/src/contrib/epee/demo/generate_gcc.sh deleted file mode 100644 index fcd0a8a..0000000 --- a/src/contrib/epee/demo/generate_gcc.sh +++ /dev/null @@ -1,4 +0,0 @@ -mkdir build -cd build -cmake .. -#cmake -DBOOST_ROOT=/usr/local/proj/boost_1_49_0 -DBOOST_LIBRARYDIR=/usr/local/proj/boost_1_49_0/stage/lib .. diff --git a/src/contrib/epee/demo/generate_vc_proj.bat b/src/contrib/epee/demo/generate_vc_proj.bat deleted file mode 100644 index 1114059..0000000 --- a/src/contrib/epee/demo/generate_vc_proj.bat +++ /dev/null @@ -1,7 +0,0 @@ -mkdir build - -cd build - -cmake "-DBoost_USE_STATIC_LIBS=TRUE" -G "Visual Studio 11 Win64" .. -cd .. -pause \ No newline at end of file diff --git a/src/contrib/epee/demo/iface/transport_defs.h b/src/contrib/epee/demo/iface/transport_defs.h deleted file mode 100644 index 8463eb9..0000000 --- a/src/contrib/epee/demo/iface/transport_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -#pragma once - -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_base.h" - -namespace demo -{ - - struct some_test_subdata - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - END_KV_SERIALIZE_MAP() - }; - - struct some_test_data - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - std::list m_list_of_str; - std::list m_list_of_uint64_t; - std::list m_list_of_uint32_t; - std::list m_list_of_uint16_t; - std::list m_list_of_uint8_t; - std::list m_list_of_int64_t; - std::list m_list_of_int32_t; - std::list m_list_of_int16_t; - std::list m_list_of_int8_t; - std::list m_list_of_double; - std::list m_list_of_bool; - some_test_subdata m_subobj; - std::list m_list_of_self; - epee::serialization::storage_entry m_storage_entry_int; - epee::serialization::storage_entry m_storage_entry_string; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_str) - KV_SERIALIZE(m_uint64) - KV_SERIALIZE(m_uint32) - KV_SERIALIZE(m_uint16) - KV_SERIALIZE(m_uint8) - KV_SERIALIZE(m_int64) - KV_SERIALIZE(m_int32) - KV_SERIALIZE(m_int16) - KV_SERIALIZE(m_int8) - KV_SERIALIZE(m_double) - KV_SERIALIZE(m_bool) - KV_SERIALIZE(m_subobj) - KV_SERIALIZE(m_list_of_str) - KV_SERIALIZE(m_list_of_uint64_t) - KV_SERIALIZE(m_list_of_uint32_t) - KV_SERIALIZE(m_list_of_uint16_t) - KV_SERIALIZE(m_list_of_uint8_t) - KV_SERIALIZE(m_list_of_int64_t) - KV_SERIALIZE(m_list_of_int32_t) - KV_SERIALIZE(m_list_of_int16_t) - KV_SERIALIZE(m_list_of_int8_t) - KV_SERIALIZE(m_list_of_double) - KV_SERIALIZE(m_list_of_bool) - KV_SERIALIZE(m_list_of_self) - KV_SERIALIZE(m_storage_entry_int) - KV_SERIALIZE(m_storage_entry_string) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request - { - std::string example_string_data; - some_test_data sub; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data) - KV_SERIALIZE(sub) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - bool m_success; - std::list subs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - KV_SERIALIZE(subs) - END_KV_SERIALIZE_MAP() - }; - }; - - - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request - { - std::string example_string_data2; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(example_string_data2) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - bool m_success; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_success) - END_KV_SERIALIZE_MAP() - }; - }; - - - //------------------------------------------------------------------------------------- - //------------------------------------------------------------------------------------- - //in debug purpose - bool operator != (const some_test_subdata& a, const some_test_subdata& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const some_test_data& a, const some_test_data& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - || b.m_storage_entry_int.which() != a.m_storage_entry_int.which() - || b.m_storage_entry_string.which() != a.m_storage_entry_string.which() - ) - return false; - return true; - } - - inline some_test_data get_test_data() - { - some_test_data s; - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - s.m_storage_entry_int = epee::serialization::storage_entry(uint64_t(22222));; - s.m_storage_entry_string = epee::serialization::storage_entry(std::string("sdsvsdvs")); - return s; - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/auto_val_init.h b/src/contrib/epee/include/auto_val_init.h deleted file mode 100644 index d35f9a0..0000000 --- a/src/contrib/epee/include/auto_val_init.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006-2017, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include - - - -#define AUTO_VAL_INIT(v) boost::value_initialized() -#define AUTO_VAL_INIT_T(t) boost::value_initialized() diff --git a/src/contrib/epee/include/cache_helper.h b/src/contrib/epee/include/cache_helper.h deleted file mode 100644 index 0da2162..0000000 --- a/src/contrib/epee/include/cache_helper.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2006-2016, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include -#include -#include -#include -#include "boost/optional.hpp" -#include "syncobj.h" -#include "include_base_utils.h" - -namespace epee -{ - namespace misc_utils - { - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct container_selector; - - template - struct container_selector - { - typedef std::map container; - }; - - template - struct container_selector - { - typedef std::unordered_map container; - }; - - - - template - class cache_base - { - uint64_t mac_allowed_elements; - std::list most_recet_acessed; - typename container_selector::iterator> >::container data; - protected: - critical_section m_lock; - public: - - cache_base() : mac_allowed_elements(max_elements) - {} - - size_t size() - { - - return data.size(); - } - - void set_max_elements(uint64_t e) - { - mac_allowed_elements = e; - } - - bool get(const t_key& k, t_value& v) - { - CRITICAL_REGION_LOCAL(m_lock); - auto it = data.find(k); - if (it == data.end()) - return false; - - most_recet_acessed.splice(most_recet_acessed.begin(), most_recet_acessed, it->second.second); - v = it->second.first; - return true; - } - - bool set(const t_key& k, const t_value& v) - { - CRITICAL_REGION_LOCAL(m_lock); - most_recet_acessed.push_front(k); - data[k] = std::pair::iterator>(v, most_recet_acessed.begin()); - - trim(); - return true; - } - - void clear() - { - CRITICAL_REGION_LOCAL(m_lock); - data.clear(); - most_recet_acessed.clear(); - } - - bool erase(const t_key& k) - { - CRITICAL_REGION_LOCAL(m_lock); - auto data_it = data.find(k); - if (data_it == data.end()) - return false; - - most_recet_acessed.erase(data_it->second.second); - data.erase(data_it); - return true; - } - protected: - void trim() - { - CRITICAL_REGION_LOCAL(m_lock); - while (most_recet_acessed.size() > mac_allowed_elements) - { - auto data_it = data.find(most_recet_acessed.back()); - if (data_it != data.end()) - data.erase(data_it); - most_recet_acessed.erase(--most_recet_acessed.end()); - } - } - }; - - class isolation_lock - { - private: - critical_section m_my_lock; - critical_section& m_lock; - boost::optional m_current_writer_thread; - public: - isolation_lock() :m_lock(m_my_lock) - {} - - isolation_lock(critical_section& lock) :m_lock(lock) - {} - - template - res_type isolated_access(callback_t cb) const - { - CRITICAL_REGION_LOCAL(m_lock); - if (m_current_writer_thread.is_initialized()) - { - //has writer - if (std::this_thread::get_id() != m_current_writer_thread.get()) - { - // cache isolated (not allowed) - return cb(false); - } - } - //cache shared(allowed) - return cb(true); - } - - - template - res_type isolated_write_access(callback_t cb) const - { - return isolated_access([&](bool is_allowed_cache) - { - if (!is_allowed_cache) - { - ASSERT_MES_AND_THROW("internal error: writer not allowed while it's not in writer transaction"); - } - return cb(); - }); - } - - void set_isolation_mode() - { - CRITICAL_REGION_LOCAL(m_lock); - CHECK_AND_ASSERT_THROW_MES(!m_current_writer_thread.is_initialized(), "Isolation mode already enabled for cache"); - m_current_writer_thread = std::this_thread::get_id(); - } - - void reset_isolation_mode() - { - CRITICAL_REGION_LOCAL(m_lock); - CHECK_AND_ASSERT_THROW_MES(m_current_writer_thread.is_initialized(), "Isolation mode already disable for cache"); - m_current_writer_thread = boost::optional(); - } - }; - - - template - class cache_with_write_isolation : public cache_base - { - typedef cache_base base_class; - isolation_lock& m_isolation; - public: - cache_with_write_isolation(isolation_lock& isolation) : m_isolation(isolation) - {} - - bool get(const t_key& k, t_value& v) - { - return m_isolation.isolated_access([&](bool allowed_cache) - { - if (allowed_cache) - return base_class::get(k, v); - else - return false; - }); - } - - bool set(const t_key& k, const t_value& v) - { - return m_isolation.isolated_access([&] (bool cache_allowed) - { - if (cache_allowed) - return base_class::set(k, v); - return true; - }); - } - - void clear() - { - m_isolation.isolated_access([&](bool cache_allowed) - { - if (cache_allowed) - base_class::clear(); - return true; - }); - - } - - bool erase(const t_key& k) - { - return m_isolation.isolated_write_access([&](){return base_class::erase(k); }); - } - }; - - template - class cache_dummy : public cache_base - { - typedef cache_base base_class; - isolation_lock& m_isolation; - public: - cache_dummy(isolation_lock& isolation) : m_isolation(isolation){} - bool get(const t_key& k, t_value& v){return false;} - bool set(const t_key& k, const t_value& v){return true;} - void clear(){} - bool erase(const t_key& k){return true;} - }; - - } - -} diff --git a/src/contrib/epee/include/console_handler.h b/src/contrib/epee/include/console_handler.h deleted file mode 100644 index 2d098e3..0000000 --- a/src/contrib/epee/include/console_handler.h +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include -#include -#include - -namespace epee -{ - class async_stdin_reader - { - public: - async_stdin_reader() - : m_run(true) - , m_has_read_request(false) - , m_read_status(state_init) - { - m_reader_thread = std::thread(std::bind(&async_stdin_reader::reader_thread_func, this)); - } - - ~async_stdin_reader() - { - stop(); - } - - // Not thread safe. Only one thread can call this method at once. - bool get_line(std::string& line) - { - if (!start_read()) - return false; - - std::unique_lock lock(m_response_mutex); - while (state_init == m_read_status) - { - m_response_cv.wait(lock); - } - - bool res = false; - if (state_success == m_read_status) - { - line = m_line; - res = true; - } - - m_read_status = state_init; - - return res; - } - - void stop() - { - if (m_run) - { - m_run.store(false, std::memory_order_relaxed); - -#if defined(WIN32) - ::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE)); -#endif - - m_request_cv.notify_one(); - m_reader_thread.join(); - } - } - - private: - bool start_read() - { - std::unique_lock lock(m_request_mutex); - if (!m_run.load(std::memory_order_relaxed) || m_has_read_request) - return false; - - m_has_read_request = true; - m_request_cv.notify_one(); - return true; - } - - bool wait_read() - { - std::unique_lock lock(m_request_mutex); - while (m_run.load(std::memory_order_relaxed) && !m_has_read_request) - { - m_request_cv.wait(lock); - } - - if (m_has_read_request) - { - m_has_read_request = false; - return true; - } - - return false; - } - - bool wait_stdin_data() - { -#if !defined(WIN32) - int stdin_fileno = ::fileno(stdin); - - while (m_run.load(std::memory_order_relaxed)) - { - fd_set read_set; - FD_ZERO(&read_set); - FD_SET(stdin_fileno, &read_set); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100 * 1000; - - int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv); - if (retval < 0) - return false; - else if (0 < retval) - return true; - } -#endif - - return true; - } - - void reader_thread_func() - { - while (true) - { - if (!wait_read()) - break; - - std::string line; - bool read_ok = true; - if (wait_stdin_data()) - { - if (m_run.load(std::memory_order_relaxed)) - { - std::getline(std::cin, line); - read_ok = !std::cin.eof() && !std::cin.fail(); - } - } - else - { - read_ok = false; - } - - { - std::unique_lock lock(m_response_mutex); - if (m_run.load(std::memory_order_relaxed)) - { - m_line = std::move(line); - m_read_status = read_ok ? state_success : state_error; - } - else - { - m_read_status = state_cancelled; - } - m_response_cv.notify_one(); - } - } - } - - enum t_state - { - state_init, - state_success, - state_error, - state_cancelled - }; - - private: - std::thread m_reader_thread; - std::atomic m_run; - - std::string m_line; - bool m_has_read_request; - t_state m_read_status; - - std::mutex m_request_mutex; - std::mutex m_response_mutex; - std::condition_variable m_request_cv; - std::condition_variable m_response_cv; - }; - - - template - bool empty_commands_handler(t_server* psrv, const std::string& command) - { - return true; - } - - - class async_console_handler - { - public: - async_console_handler() - { - } - - template - bool run(t_server* psrv, chain_handler ch_handler, const std::string& prompt = "#", const std::string& usage = "") - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(psrv, cmd); }, [&] { psrv->send_stop_signal(); }); - } - - template - bool run(chain_handler ch_handler, const std::string& prompt = "#", const std::string& usage = "") - { - return run(prompt, usage, [&](const std::string& cmd) { return ch_handler(cmd); }, [] { }); - } - - void stop() - { - m_stdin_reader.stop(); - } - - private: - template - bool run(const std::string& prompt, const std::string& usage, const t_cmd_handler& cmd_handler, const t_exit_handler& exit_handler) - { - TRY_ENTRY(); - bool continue_handle = true; - while(continue_handle) - { - if (!prompt.empty()) - { - epee::log_space::set_console_color(epee::log_space::console_color_yellow, true); - std::cout << prompt; - if (' ' != prompt.back()) - std::cout << ' '; - epee::log_space::reset_console_color(); - std::cout.flush(); - } - - std::string command; - if(!m_stdin_reader.get_line(command)) - { - LOG_PRINT("Failed to read line. Stopping...", LOG_LEVEL_0); - continue_handle = false; - break; - } - string_tools::trim(command); - - LOG_PRINT_L2("Read command: " << command); - if(0 == command.compare("exit") || 0 == command.compare("q")) - { - cmd_handler(command); - continue_handle = false; - }else if (!command.compare(0, 7, "set_log")) - { - //parse set_log command - static const std::string command_wrong_syntax = "set_log: wrong syntax, usage: set_log log_level_number | log_channel_name_1,log_channel_name_2,... 0|1"; - std::string args = epee::string_tools::trim(command.substr(7)); - if (args.empty()) - { - std::set& enabled_channels = epee::log_space::log_singletone::get_enabled_channels(); - std::cout << "current log level: " << log_space::get_set_log_detalisation_level() << ", enabled channels: "; - for(auto& channel : enabled_channels) - std::cout << channel << " "; - std::cout << std::endl; - continue; - } - - size_t args_space_pos = args.find(' '); - if (args_space_pos != std::string::npos) - { - // channel enabling / disabling - std::string channel_str = args.substr(0, args_space_pos); - std::string value_str = args.substr(args_space_pos + 1); - if (channel_str.empty() || value_str.empty()) - { - std::cout << command_wrong_syntax << std::endl; - continue; - } - - bool multi_channels = channel_str.find_first_of(",;:") != std::string::npos; - - if (value_str == "1" || value_str == "e" || value_str == "y") - if (multi_channels) - epee::log_space::log_singletone::enable_channels(channel_str); - else - epee::log_space::log_singletone::enable_channel(channel_str); - else - if (multi_channels) - epee::log_space::log_singletone::disable_channels(channel_str); - else - epee::log_space::log_singletone::disable_channel(channel_str); - } - else - { - // log level set - uint16_t n = 0; - if(!string_tools::get_xtype_from_string(n, args)) - { - std::cout << command_wrong_syntax << std::endl; - continue; - } - uint16_t previous_log_level = log_space::get_set_log_detalisation_level(); - log_space::get_set_log_detalisation_level(true, n); - if (n < LOG_LEVEL_2) - std::cout << "log level: " << previous_log_level << " -> " << n << std::endl; - LOG_PRINT_L2("log level: " << previous_log_level << " -> " << n); - } - - if (args.empty()) - { - std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl; - continue; - } - }else if (command.empty()) - { - continue; - } - else if(cmd_handler(command)) - { - continue; - } else - { - std::cout << "unknown command: " << command << std::endl; - std::cout << usage; - } - } - exit_handler(); - return true; - CATCH_ENTRY_L0("console_handler", false); - } - - private: - async_stdin_reader m_stdin_reader; - }; - - - template - bool start_default_console(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - std::shared_ptr console_handler = std::make_shared(); - boost::thread([=](){console_handler->run(ptsrv, handlr, prompt, usage);}).detach(); - return true; - } - - template - bool start_default_console(t_server* ptsrv, const std::string& prompt, const std::string& usage = "") - { - return start_default_console(ptsrv, empty_commands_handler, prompt, usage); - } - - template - bool no_srv_param_adapter(t_server* ptsrv, const std::string& cmd, t_handler handlr) - { - return handlr(cmd); - } - - template - bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - async_console_handler console_handler; - return console_handler.run(ptsrv, boost::bind(no_srv_param_adapter, boost::placeholders::_1, boost::placeholders::_2, handlr), prompt, usage); - } - - template - bool start_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") - { - boost::thread( boost::bind(run_default_console_handler_no_srv_param, ptsrv, handlr, prompt, usage) ); - return true; - } - - /*template - bool f(int i, a l) - { - return true; - }*/ - /* - template - bool default_console_handler2(chain_handler ch_handler, const std::string usage) - */ - - - /*template - bool start_default_console2(t_handler handlr, const std::string& usage = "") - { - //std::string usage_local = usage; - boost::thread( boost::bind(default_console_handler2, handlr, usage) ); - //boost::function p__ = boost::bind(f, 1, handlr); - //boost::function p__ = boost::bind(default_console_handler2, handlr, usage); - //boost::thread tr(p__); - return true; - }*/ - - /************************************************************************/ - /* */ - /************************************************************************/ - class console_handlers_binder - { - typedef boost::function &)> console_command_handler; - typedef std::map > command_handlers_map; - std::unique_ptr m_console_thread; - command_handlers_map m_command_handlers; - async_console_handler m_console_handler; - public: - std::string get_usage() - { - std::stringstream ss; - size_t max_command_len = 0; - for(auto& x:m_command_handlers) - if(x.first.size() > max_command_len) - max_command_len = x.first.size(); - - for(auto& x:m_command_handlers) - { - ss << " " << std::left << std::setw(max_command_len + 3) << x.first << " " << x.second.second << ENDL; - } - return ss.str(); - } - void set_handler(const std::string& cmd, const console_command_handler& hndlr, const std::string& usage = "") - { - command_handlers_map::mapped_type & vt = m_command_handlers[cmd]; - vt.first = hndlr; - vt.second = usage; - } - bool process_command_vec(const std::vector& cmd) - { - if(!cmd.size()) - return false; - auto it = m_command_handlers.find(cmd.front()); - if(it == m_command_handlers.end()) - return false; - std::vector cmd_local(cmd.begin()+1, cmd.end()); - return it->second.first(cmd_local); - } - - bool process_command_str(const std::string& cmd) - { - std::vector cmd_v; - boost::split(cmd_v,cmd,boost::is_any_of(" "), boost::token_compress_on); - return process_command_vec(cmd_v); - } - - /*template - bool start_handling(t_srv& srv, const std::string& usage_string = "") - { - start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1)); - return true; - }*/ - - bool start_handling(const std::string& prompt, const std::string& usage_string = "") - { - m_console_thread.reset(new boost::thread(boost::bind(&console_handlers_binder::run_handling, this, prompt, usage_string))); - m_console_thread->detach(); - return true; - } - - void stop_handling() - { - m_console_handler.stop(); - } - - bool run_handling(const std::string& prompt, const std::string& usage_string) - { - return m_console_handler.run(boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1), prompt, usage_string); - } - - bool help(const std::vector& /*args*/) - { - std::cout << get_usage() << ENDL; - return true; - } - /*template - bool run_handling(t_srv& srv, const std::string& usage_string) - { - return run_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1), usage_string); - }*/ - }; - - /* work around because of broken boost bind */ - template - class srv_console_handlers_binder: public console_handlers_binder - { - bool process_command_str(t_server* /*psrv*/, const std::string& cmd) - { - return console_handlers_binder::process_command_str(cmd); - } - public: - bool start_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string = "") - { - boost::thread(boost::bind(&srv_console_handlers_binder::run_handling, this, psrv, prompt, usage_string)).detach(); - return true; - } - - bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) - { - return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, boost::placeholders::_1, boost::placeholders::_2), prompt, usage_string); - } - - void stop_handling() - { - m_console_handler.stop(); - } - - //-------------------------------------------------------------------------------- - - private: - async_console_handler m_console_handler; - }; -} diff --git a/src/contrib/epee/include/copyable_atomic.h b/src/contrib/epee/include/copyable_atomic.h deleted file mode 100644 index 6b5691a..0000000 --- a/src/contrib/epee/include/copyable_atomic.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -namespace epee -{ - class copyable_atomic: public std::atomic - { - public: - copyable_atomic() - {}; - copyable_atomic(const copyable_atomic& a):std::atomic(a.load()) - {} - copyable_atomic& operator= (const copyable_atomic& a) - { - store(a.load()); - return *this; - } - uint32_t operator++() - { - return std::atomic::operator++(); - } - uint32_t operator++(int fake) - { - return std::atomic::operator++(fake); - } - }; -} \ No newline at end of file diff --git a/src/contrib/epee/include/file_io_utils.h b/src/contrib/epee/include/file_io_utils.h deleted file mode 100644 index 7ece78b..0000000 --- a/src/contrib/epee/include/file_io_utils.h +++ /dev/null @@ -1,585 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _FILE_IO_UTILS_H_ -#define _FILE_IO_UTILS_H_ - - -//#include -//#include - -#include -#include -#include - -#ifndef MAKE64 - #define MAKE64(low,high) ((__int64)(((DWORD)(low)) | ((__int64)((DWORD)(high))) << 32)) -#endif - -#ifdef WINDOWS_PLATFORM -#include -#include -#include -#include -#endif - -#ifndef WIN32 -#include -#endif - -//#include "include_base_utils.h" -#include "string_coding.h" - -namespace epee -{ -namespace file_io_utils -{ -#ifdef WINDOWS_PLATFORM - - inline - std::string get_temp_file_name_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - - char sz_temp_file[MAX_PATH*2] = {0}; - if(!::GetTempFileNameA( sz_temp, "mail", 0, sz_temp_file)) - return str_result; - sz_temp_file[sizeof(sz_temp_file)-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } - - -#ifdef BOOST_LEXICAL_CAST_INCLUDED - inline - bool get_not_used_filename(const std::string& folder, std::string& result_name) - { - DWORD folder_attr = ::GetFileAttributesA(folder.c_str()); - if(folder_attr == INVALID_FILE_ATTRIBUTES) - return false; - if(!(folder_attr&FILE_ATTRIBUTE_DIRECTORY)) - return false; - - - std::string base_name = folder + "\\tmp"; - std::string tmp_name; - bool name_found = false; - int current_index = 0; - tmp_name = base_name + boost::lexical_cast(current_index) + ".tmp"; - while(!name_found) - { - if(INVALID_FILE_ATTRIBUTES == ::GetFileAttributesA(tmp_name.c_str())) - name_found = true; - else - { - current_index++; - tmp_name = base_name + boost::lexical_cast(current_index) + ".tmp"; - } - } - result_name = tmp_name; - return true; - } -#endif - - inline - std::string get_temp_folder_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - sz_temp[(sizeof(sz_temp)/sizeof(sz_temp[0])) -1] = 0; - str_result = sz_temp; - return str_result; - } - - std::string convert_from_device_path_to_standart(const std::string& path) - { - - - STRSAFE_LPSTR pszFilename = (STRSAFE_LPSTR)path.c_str(); - - // Translate path with device name to drive letters. - char szTemp[4000] = {0}; - - if (::GetLogicalDriveStringsA(sizeof(szTemp)-1, szTemp)) - { - char szName[MAX_PATH]; - char szDrive[3] = " :"; - BOOL bFound = FALSE; - char* p = szTemp; - - do - { - // Copy the drive letter to the template string - *szDrive = *p; - - // Look up each device name - if (::QueryDosDeviceA(szDrive, szName, sizeof(szName))) - { - UINT uNameLen = strlen(szName); - - if (uNameLen < MAX_PATH) - { - bFound = _mbsnbicmp((const unsigned char*)pszFilename, (const unsigned char*)szName, - uNameLen) == 0; - - if (bFound) - { - // Reconstruct pszFilename using szTempFile - // Replace device path with DOS path - char szTempFile[MAX_PATH] = {0}; - StringCchPrintfA(szTempFile, - MAX_PATH, - "%s%s", - szDrive, - pszFilename+uNameLen); - return szTempFile; - //::StringCchCopyNA(pszFilename, MAX_PATH+1, szTempFile, strlen(szTempFile)); - } - } - } - - // Go to the next NULL character. - while (*p++); - } while (!bFound && *p); // end of string - } - - return ""; - } - - inline - std::string get_process_path_by_pid(DWORD pid) - { - std::string res; - - HANDLE hprocess = 0; - if( hprocess = ::OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid) ) - { - char buff[MAX_PATH]= {0}; - if(!::GetModuleFileNameExA( hprocess, 0, buff, MAX_PATH - 1 )) - res = "Unknown_b"; - else - { - buff[MAX_PATH - 1]=0; //be happy! - res = buff; - std::string::size_type a = res.rfind( '\\' ); - if ( a != std::string::npos ) - res.erase( 0, a+1); - - } - ::CloseHandle( hprocess ); - }else - res = "Unknown_a"; - - return res; - } - - - - - - inline - std::wstring get_temp_file_name_w() - { - std::wstring str_result; - wchar_t sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathW( sizeof(sz_temp)/sizeof(sz_temp[0]), sz_temp )) - return str_result; - - wchar_t sz_temp_file[MAX_PATH+1] = {0}; - if(!::GetTempFileNameW( sz_temp, L"mail", 0, sz_temp_file)) - return str_result; - - sz_temp_file[(sizeof(sz_temp_file)/sizeof(sz_temp_file[0]))-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } -#endif - - inline const std::wstring& convert_utf8_to_wstring_if_needed(const std::wstring& s) - { - return s; - } - - inline std::wstring convert_utf8_to_wstring_if_needed(const std::string& s) - { - return epee::string_encoding::utf8_to_wstring(s); - } - - template - bool is_file_exist(const t_string& path) - { - boost::filesystem::path p(convert_utf8_to_wstring_if_needed(path)); - return boost::filesystem::exists(p); - } - - /* - inline - bool save_string_to_handle(HANDLE hfile, const std::string& str) - { - - - - if( INVALID_HANDLE_VALUE != hfile ) - { - DWORD dw; - if( !::WriteFile( hfile, str.data(), (DWORD) str.size(), &dw, NULL) ) - { - int err_code = GetLastError(); - //LOG_PRINT("Failed to write to file handle: " << hfile<< " Last error code:" << err_code << " : " << log_space::get_win32_err_descr(err_code), LOG_LEVEL_2); - return false; - } - ::CloseHandle(hfile); - return true; - }else - { - //LOG_WIN32_ERROR(::GetLastError()); - return false; - } - - return false; - }*/ - - - template - bool save_string_to_file_throw(const t_string& path_to_file, const std::string& str) - { - //std::ofstream fstream; - boost::filesystem::ofstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(convert_utf8_to_wstring_if_needed(path_to_file), std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); - fstream << str; - fstream.close(); - return true; - } - - template - bool save_string_to_file(const t_string& path_to_file, const std::string& str) - { - try - { - return save_string_to_file_throw(path_to_file, str); - } - catch (const std::exception& /*ex*/) - { - return false; - } - - catch(...) - { - return false; - } - } - - template - bool load_file_to_string(const t_string& path_to_file, std::string& target_str) - { - try - { - boost::filesystem::ifstream fstream; - //fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(convert_utf8_to_wstring_if_needed(path_to_file), std::ios_base::binary | std::ios_base::in | std::ios::ate); - if (!fstream.good()) - return false; - std::ifstream::pos_type file_size = fstream.tellg(); - - if (file_size > 1000000000) - return false;//don't get crazy - size_t file_size_t = static_cast(file_size); - - target_str.resize(file_size_t); - - fstream.seekg(0, std::ios::beg); - fstream.read((char*)target_str.data(), target_str.size()); - if (!fstream.good()) - return false; - - fstream.close(); - return true; - } - catch (...) - { - return false; - } - } - - - /* - inline - bool load_form_handle(HANDLE hfile, std::string& str) - { - if( INVALID_HANDLE_VALUE != hfile ) - { - bool res = true; - DWORD dw = 0; - DWORD fsize = ::GetFileSize(hfile, &dw); - if(fsize > 300000000) - { - ::CloseHandle(hfile); - return false; - } - if(fsize) - { - str.resize(fsize); - if(!::ReadFile( hfile, (LPVOID)str.data(), (DWORD)str.size(), &dw, NULL)) - res = false; - } - ::CloseHandle(hfile); - return res; - } - return false; - } - */ - inline - bool get_file_time(const std::string& path_to_file, time_t& ft) - { - boost::system::error_code ec; - ft = boost::filesystem::last_write_time(epee::string_encoding::utf8_to_wstring(path_to_file), ec); - if(!ec) - return true; - else - return false; - } - - inline - bool set_file_time(const std::string& path_to_file, const time_t& ft) - { - boost::system::error_code ec; - boost::filesystem::last_write_time(epee::string_encoding::utf8_to_wstring(path_to_file), ft, ec); - if(!ec) - return true; - else - return false; - } - - - - -#ifdef WIN32 - typedef HANDLE native_filesystem_handle; -#else - typedef int native_filesystem_handle; -#endif - - // uses UTF-8 for unicode names for all systems - inline bool open_and_lock_file(const std::string file_path, native_filesystem_handle& h_file) - { -#ifdef WIN32 - std::wstring file_path_w = epee::string_encoding::utf8_to_wstring(file_path); - h_file = ::CreateFileW(file_path_w.c_str(), // name of the file - GENERIC_WRITE, // open for writing - 0, // do not share - NULL, // default security - OPEN_ALWAYS, // create new file only - FILE_ATTRIBUTE_NORMAL, // normal file - NULL); // no attr. template - if (h_file == INVALID_HANDLE_VALUE) - return false; - else - return true; -#else - h_file = open(file_path.c_str(), O_RDWR | O_CREAT, 0666); // open or create lockfile - if (h_file < 0) - return false; - //check open success... - int rc = flock(h_file, LOCK_EX | LOCK_NB); // grab exclusive lock, fail if can't obtain. - if (rc < 0) - { - return false; - } - return true; -#endif - } - - inline bool unlock_and_close_file(native_filesystem_handle& h_file) - { -#ifdef WIN32 - ::CloseHandle(h_file); // no attr. template -#else - flock(h_file, LOCK_UN); // grab exclusive lock, fail if can't obtain. - close(h_file); -#endif - return true; - } - - - inline - bool load_last_n_from_file_to_string(const std::string& path_to_file, uint64_t size_to_load, std::string& target_str) - { - try - { - std::ifstream fstream; - //fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate); - if (!fstream.good()) - return false; - std::ifstream::pos_type file_size = fstream.tellg(); - - uint64_t size_to_load_to_buff = file_size; - if (static_cast(file_size) > size_to_load) - { - fstream.seekg(size_to_load_to_buff - size_to_load, std::ios::beg); - size_to_load_to_buff = size_to_load; - }else - { - fstream.seekg(0, std::ios::beg); - } - - size_t size_to_load_to_buff_t = static_cast(size_to_load_to_buff); - - target_str.resize(size_to_load_to_buff_t); - - - fstream.read((char*)target_str.data(), target_str.size()); - if (!fstream.good()) - return false; - - fstream.close(); - return true; - } - - catch (...) - { - return false; - } - } - - inline - bool copy_file(const std::string& source, const std::string& destination) - { - boost::system::error_code ec; - boost::filesystem::copy_file(epee::string_encoding::utf8_to_wstring(source), epee::string_encoding::utf8_to_wstring(destination), ec); - if (ec) - return false; - else - return true; - } - - inline - bool append_string_to_file(const std::string& path_to_file, const std::string& str) - { - try - { - boost::filesystem::ofstream fstream; - fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - fstream.open(epee::string_encoding::utf8_to_wstring(path_to_file), std::ios_base::binary | std::ios_base::out | std::ios_base::app); - fstream << str; - fstream.close(); - return true; - } - - catch(...) - { - return false; - } - } - - /* - bool remove_dir_and_subirs(const char* path_to_dir); - - inline - bool clean_dir(const char* path_to_dir) - { - if(!path_to_dir) - return false; - - std::string folder = path_to_dir; - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((folder + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - if(find_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - if(!remove_dir_and_subirs((folder + "\\" + find_data.cFileName).c_str())) - return false; - }else - { - if(!::DeleteFileA((folder + "\\" + find_data.cFileName).c_str())) - return false; - } - - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } - */ -#ifdef WINDOWS_PLATFORM - inline bool get_folder_content(const std::string& path, std::list& target_list) - { - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((path + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - target_list.push_back(find_data); - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } -#endif - inline bool get_folder_content(const std::string& path, std::list& target_list, bool only_files = false) - { - try - { - - boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end - for ( boost::filesystem::directory_iterator itr( epee::string_encoding::utf8_to_wstring(path) ); itr != end_itr; ++itr ) - { - if ( only_files && boost::filesystem::is_directory(itr->status()) ) - { - continue; - } - target_list.push_back(itr->path().filename().string()); - } - - } - - catch(...) - { - return false; - } - return true; - } -} -} - -#endif //_FILE_IO_UTILS_H_ diff --git a/src/contrib/epee/include/global_stream_operators.h b/src/contrib/epee/include/global_stream_operators.h deleted file mode 100644 index 6fbdbc2..0000000 --- a/src/contrib/epee/include/global_stream_operators.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -std::stringstream& operator<<(std::stringstream& out, const std::wstring& ws) -{ - std::string as = string_encoding::convert_to_ansii(ws); - out << as; - return out; -} diff --git a/src/contrib/epee/include/gzip_encoding.h b/src/contrib/epee/include/gzip_encoding.h deleted file mode 100644 index e2e1ea2..0000000 --- a/src/contrib/epee/include/gzip_encoding.h +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _GZIP_ENCODING_H_ -#define _GZIP_ENCODING_H_ -#include "boost/core/ignore_unused.hpp" -#include "net/http_client_base.h" -#include "zlib/zlib.h" - - -namespace epee -{ -namespace net_utils -{ - - - - class content_encoding_gzip: public i_sub_handler - { - public: - /*! \brief - * Function content_encoding_gzip : Constructor - * - */ - inline - content_encoding_gzip(i_target_handler* powner_filter, bool is_deflate_mode = false, int compression_level = Z_DEFAULT_COMPRESSION) :m_powner_filter(powner_filter), - m_is_stream_ended(false), - m_is_deflate_mode(is_deflate_mode), - m_is_first_update_in(true) - { - memset(&m_zstream_in, 0, sizeof(m_zstream_in)); - memset(&m_zstream_out, 0, sizeof(m_zstream_out)); - int ret = 0; - boost::ignore_unused(ret); - if(is_deflate_mode) - { - ret = inflateInit(&m_zstream_in); - ret = deflateInit(&m_zstream_out, compression_level); - }else - { - ret = inflateInit2(&m_zstream_in, 0x1F); - ret = deflateInit2(&m_zstream_out, compression_level, Z_DEFLATED, 0x1F, 8, Z_DEFAULT_STRATEGY); - } - } - /*! \brief - * Function content_encoding_gzip : Destructor - * - */ - inline - ~content_encoding_gzip() - { - inflateEnd(& m_zstream_in ); - deflateEnd(& m_zstream_out ); - } - /*! \brief - * Function update_in : Entry point for income data - * - */ - inline - virtual bool update_in( std::string& piece_of_transfer) - { - - bool is_first_time_here = m_is_first_update_in; - m_is_first_update_in = false; - - if(m_pre_decode.size()) - m_pre_decode += piece_of_transfer; - else - m_pre_decode.swap(piece_of_transfer); - piece_of_transfer.clear(); - - std::string decode_summary_buff; - - size_t ungzip_size = m_pre_decode.size() * 0x30; - std::string current_decode_buff(ungzip_size, 'X'); - auto slh = misc_utils::create_scope_leave_handler([&]() { m_zstream_in.next_out = nullptr; } ); // make sure local pointer to current_decode_buff.data() won't be used out of this scope - - //Here the cycle is introduced where we unpack the buffer, the cycle is required - //because of the case where if after unpacking the data will exceed the awaited size, we will not halt with error - bool continue_unpacking = true; - bool first_step = true; - while(m_pre_decode.size() && continue_unpacking) - { - - //fill buffers - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - m_zstream_in.next_out = (Bytef*)current_decode_buff.data(); - m_zstream_in.avail_out = (uInt)ungzip_size; - - int flag = Z_NO_FLUSH; - int ret = inflate(&m_zstream_in, flag); - CHECK_AND_ASSERT_MES(ret>=0 || m_zstream_in.avail_out ||m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. ret = " << ret << ", msg: " << (m_zstream_in.msg ? m_zstream_in.msg : "")); - - if(Z_STREAM_END == ret) - m_is_stream_ended = true; - else if(Z_DATA_ERROR == ret && is_first_time_here && m_is_deflate_mode&& first_step) - { - // some servers (notably Apache with mod_deflate) don't generate zlib headers - // insert a dummy header and try again - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - inflateReset(&m_zstream_in); - m_zstream_in.next_in = (Bytef*) dummy_head; - m_zstream_in.avail_in = sizeof(dummy_head); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - m_zstream_in.next_in = (Bytef*)m_pre_decode.data(); - m_zstream_in.avail_in = (uInt)m_pre_decode.size(); - - ret = inflate(&m_zstream_in, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - m_pre_decode.swap(piece_of_transfer); - return false; - } - } - else - { - CHECK_AND_ASSERT_MES(Z_DATA_ERROR != ret, false, "content_encoding_gzip::update_in() Failed to inflate. err = Z_DATA_ERROR"); - } - - - //leave only unpacked part in the output buffer to start with it the next time - m_pre_decode.erase(0, m_pre_decode.size()-m_zstream_in.avail_in); - //if decoder gave nothing to return, then everything is ahead, now simply break - if(ungzip_size == m_zstream_in.avail_out) - break; - - //decode_buff currently stores data parts that were unpacked, fix this size - current_decode_buff.resize(ungzip_size - m_zstream_in.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_size); - first_step = false; - } - - //Process these data if required - return m_powner_filter->handle_target_data(decode_summary_buff); - } - /*! \brief - * Function stop : Entry point for stop signal and flushing cached data buffer. - * - */ - inline - virtual void stop(std::string& OUT collect_remains) - { - } - protected: - private: - /*! \brief - * Pointer to parent HTTP-parser - */ - i_target_handler* m_powner_filter; - /*! \brief - * ZLIB object for income stream - */ - z_stream m_zstream_in; - /*! \brief - * ZLIB object for outcome stream - */ - z_stream m_zstream_out; - /*! \brief - * Data that could not be unpacked immediately, left to wait for the next packet of data - */ - std::string m_pre_decode; - /*! \brief - * The data are accumulated for a package in the buffer to send the web client - */ - std::string m_pre_encode; - /*! \brief - * Signals that stream looks like ended - */ - bool m_is_stream_ended; - /*! \brief - * If this flag is set, income data is in HTTP-deflate mode - */ - bool m_is_deflate_mode; - /*! \brief - * Marks that it is a first data packet - */ - bool m_is_first_update_in; - }; // class content_encoding_gzip - - struct abstract_callback_base - { - virtual bool do_call(const std::string& piece_of_transfer) = 0; - virtual ~abstract_callback_base() {} - }; - - template - struct abstract_callback : public abstract_callback_base - { - callback_t m_cb; - - abstract_callback(callback_t cb) : m_cb(cb){} - virtual bool do_call(const std::string& piece_of_transfer) - { - return m_cb(piece_of_transfer); - } - }; - - class gzip_decoder_lambda : public content_encoding_gzip, - public i_target_handler - { - std::shared_ptr m_pcb; - - virtual bool handle_target_data(std::string& piece_of_transfer) - { - bool r = m_pcb->do_call(piece_of_transfer); - piece_of_transfer.clear(); - return r; - } - public: - gzip_decoder_lambda() : content_encoding_gzip(this, true, Z_BEST_COMPRESSION) - {} - - template - bool update_in(std::string& piece_of_transfer, callback_t cb) - { - m_pcb.reset(new abstract_callback(cb)); - return content_encoding_gzip::update_in(piece_of_transfer); - } - template - bool stop(callback_t cb) - {return true;} - }; // class gzip_decoder_lambda - - class gzip_encoder_lyambda - { - bool m_initialized; - z_stream m_zstream; - public: - gzip_encoder_lyambda(int compression_level = Z_DEFAULT_COMPRESSION) :m_initialized(false), m_zstream(AUTO_VAL_INIT(m_zstream)) - { - int ret = deflateInit(&m_zstream, compression_level); - if (ret == Z_OK) - m_initialized = true; - } - - ~gzip_encoder_lyambda() - { - deflateEnd(&m_zstream); - } - - template - bool update_in(const std::string& target, callback_t cb) - { - if (!m_initialized) - { - return false; - } - - if (!target.size()) - { - return true; - } - - std::string result_packed_buff; - auto slh = misc_utils::create_scope_leave_handler([&]() { m_zstream.next_out = nullptr; } ); // make sure local pointer to result_packed_buff.data() won't be used out of this scope - - //theoretically it supposed to be smaller - result_packed_buff.resize(target.size(), 'X'); - while (true) - { - m_zstream.next_in = (Bytef*)target.data(); - m_zstream.avail_in = (uInt)target.size(); - m_zstream.next_out = (Bytef*)result_packed_buff.data(); - m_zstream.avail_out = (uInt)result_packed_buff.size(); - - int ret = deflate(&m_zstream, Z_NO_FLUSH); - CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate. err = " << ret); - if (m_zstream.avail_out == 0) - { - //twice bigger buffer - result_packed_buff.resize(result_packed_buff.size()*2); - continue; - } - CHECK_AND_ASSERT_MES(result_packed_buff.size() >= m_zstream.avail_out, false, "result_packed_buff.size()=" << result_packed_buff.size() << " >= m_zstream.avail_out=" << m_zstream.avail_out); - result_packed_buff.resize(result_packed_buff.size() - m_zstream.avail_out); - break; - } - - return cb(result_packed_buff); - } - - template - bool stop(callback_t cb) - { - if (!m_initialized) - { - return false; - } - - std::string result_packed_buff; - //theoretically it supposed to be smaller - result_packed_buff.resize(1000000, 'X'); - while (true) - { - m_zstream.next_in = nullptr; - m_zstream.avail_in = 0; - m_zstream.next_out = (Bytef*)result_packed_buff.data(); - m_zstream.avail_out = (uInt)result_packed_buff.size(); - - int ret = deflate(&m_zstream, Z_FINISH); - CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate at finish. err = " << ret); - if (ret != Z_STREAM_END) - { - //twice bigger buffer - result_packed_buff.resize(result_packed_buff.size() * 2); - continue; - } - - CHECK_AND_ASSERT_MES(result_packed_buff.size() >= m_zstream.avail_out, false, "result_packed_buff.size()=" << result_packed_buff.size() << " >= m_zstream.avail_out=" << m_zstream.avail_out); - result_packed_buff.resize(result_packed_buff.size() - m_zstream.avail_out); - - m_initialized = false; - break; - } - - return cb(result_packed_buff); - } - - }; // class gzip_encoder_lyambda - -} // namespace net_utils -} // namespace epee - - - -#endif //_GZIP_ENCODING_H_ diff --git a/src/contrib/epee/include/hmac-md5.h b/src/contrib/epee/include/hmac-md5.h deleted file mode 100644 index 2a4e0d4..0000000 --- a/src/contrib/epee/include/hmac-md5.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* hmac-md5.h -- HMAC_MD5 functions - */ - -/* - * $Id: hmac-md5.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -#ifndef HMAC_MD5_H -#define HMAC_MD5_H 1 - -namespace md5 -{ - - - -#define HMAC_MD5_SIZE 16 - - /* intermediate MD5 context */ - typedef struct HMAC_MD5_CTX_s { - MD5_CTX ictx, octx; - } HMAC_MD5_CTX; - - /* intermediate HMAC state - * values stored in network byte order (Big Endian) - */ - typedef struct HMAC_MD5_STATE_s { - UINT4 istate[4]; - UINT4 ostate[4]; - } HMAC_MD5_STATE; - - /* One step hmac computation - * - * digest may be same as text or key - */ - void hmac_md5(const unsigned char *text, int text_len, - const unsigned char *key, int key_len, - unsigned char digest[HMAC_MD5_SIZE]); - - /* create context from key - */ - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, int key_len); - - /* precalculate intermediate state from key - */ - void hmac_md5_precalc(HMAC_MD5_STATE *hmac, - const unsigned char *key, int key_len); - - /* initialize context from intermediate state - */ - void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); - -#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) - - /* finish hmac from intermediate result. Intermediate result is zeroed. - */ - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac); - -} - -#endif /* HMAC_MD5_H */ diff --git a/src/contrib/epee/include/include_base_utils.h b/src/contrib/epee/include/include_base_utils.h deleted file mode 100644 index 8412a00..0000000 --- a/src/contrib/epee/include/include_base_utils.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#define BOOST_FILESYSTEM_VERSION 3 -#define ENABLE_RELEASE_LOGGING - -#include "misc_log_ex.h" - - diff --git a/src/contrib/epee/include/math_helper.h b/src/contrib/epee/include/math_helper.h deleted file mode 100644 index 9ae935a..0000000 --- a/src/contrib/epee/include/math_helper.h +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - - -#include -#include -#include -#include -#include - -#include "misc_os_dependent.h" - -namespace epee -{ -namespace math_helper -{ - - template - class average - { - public: - - average() - { - m_base = default_base; - m_count = 0; - } - - bool set_base() - { - CRITICAL_REGION_LOCAL(m_lock); - - m_base = default_base; - if(m_list.size() > m_base) - m_list.resize(m_base); - - return true; - } - - typedef val value_type; - - void push(const value_type& vl) - { - CRITICAL_REGION_LOCAL(m_lock); - -//#ifndef DEBUG_STUB - m_count++; - m_list.push_back(vl); - if(m_list.size() > m_base ) - m_list.pop_front(); -//#endif - } - - double update(const value_type& vl) - { - CRITICAL_REGION_LOCAL(m_lock); -//#ifndef DEBUG_STUB - push(vl); -//#endif - - return get_avg(); - } - - double get_avg() const - { - CRITICAL_REGION_LOCAL( static_cast(m_lock)); - - value_type vl = std::accumulate(m_list.begin(), m_list.end(), value_type(0)); - if(m_list.size()) - return (double)(vl/m_list.size()); - - return (double)vl; - } - - value_type get_last_val() - { - CRITICAL_REGION_LOCAL(m_lock); - if(m_list.size()) - return m_list.back(); - - return 0; - } - uint64_t& get_count() - { - return m_count; - } - - void reset() - { - m_count = 0; - m_list.clear(); - } - - private: - unsigned int m_base; - uint64_t m_count; - std::list m_list; - mutable critical_section m_lock; - }; - - -#ifdef WINDOWS_PLATFORM - - /************************************************************************/ - /* */ - /************************************************************************/ - class timing_guard_base - { - public: - virtual ~timing_guard_base(){}; - }; - - template - class timing_guard: public timing_guard_base - { - public: - timing_guard(T& avrg):m_avrg(avrg) - { - m_start_ticks = ::GetTickCount(); - } - - ~timing_guard() - { - m_avrg.push(::GetTickCount()-m_start_ticks); - } - - private: - T& m_avrg; - DWORD m_start_ticks; - }; - - template - timing_guard_base* create_timing_guard(t_timing& timing){return new timing_guard(timing);} - -#define BEGIN_TIMING_ZONE(timing_var) { boost::shared_ptr local_timing_guard_ptr(math_helper::create_timing_guard(timing_var)); -#define END_TIMING_ZONE() } -#endif - -//#ifdef WINDOWS_PLATFORM_EX - template - class speed - { - public: - - speed() - { - m_time_window = default_time_window; - m_last_speed_value = 0; - } - bool chick() - { -#ifndef DEBUG_STUB - uint64_t ticks = misc_utils::get_tick_count(); - CRITICAL_REGION_BEGIN(m_lock); - m_chicks.push_back(ticks); - CRITICAL_REGION_END(); - //flush(ticks); -#endif - return true; - } - - bool chick(size_t count) - { - for(size_t s = 0; s != count; s++) - chick(); - - return true; - } - - - size_t get_speed() - { - flush(misc_utils::get_tick_count()); - return m_last_speed_value = m_chicks.size(); - } - private: - - bool flush(uint64_t ticks) - { - CRITICAL_REGION_BEGIN(m_lock); - std::list::iterator it = m_chicks.begin(); - while(it != m_chicks.end()) - { - if(*it + m_time_window < ticks) - m_chicks.erase(it++); - else - break; - } - CRITICAL_REGION_END(); - return true; - } - - std::list m_chicks; - uint64_t m_time_window; - size_t m_last_speed_value; - critical_section m_lock; - }; -//#endif - - template - void randomize_list(tlist& t_list) - { - for(typename tlist::iterator it = t_list.begin();it!=t_list.end();it++) - { - size_t offset = rand()%t_list.size(); - typename tlist::iterator it_2 = t_list.begin(); - for(size_t local_offset = 0;local_offset!=offset;local_offset++) - it_2++; - if(it_2 == it) - continue; - std::swap(*it_2, *it); - } - - } -PUSH_GCC_WARNINGS -DISABLE_GCC_WARNING(strict-aliasing) - inline - uint64_t generated_random_uint64() - { - boost::uuids::uuid id___ = boost::uuids::random_generator()(); - return *reinterpret_cast(&id___.data[0]); //(*reinterpret_cast(&id___.data[0]) ^ *reinterpret_cast(&id___.data[8])); - } -POP_GCC_WARNINGS - template - class once_a_time_seconds - { - public: - once_a_time_seconds():m_interval(default_interval) - { - m_last_worked_time = 0; - if(!start_immediate) - time(&m_last_worked_time); - } - - template - bool do_call(functor_t functr) - { - time_t current_time = 0; - time(¤t_time); - - if(current_time - m_last_worked_time > m_interval) - { - bool res = functr(); - time(&m_last_worked_time); - return res; - } - return true; - } - - private: - time_t m_last_worked_time; - time_t m_interval; - }; - -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/md5_l.h b/src/contrib/epee/include/md5_l.h deleted file mode 100644 index fe4c67d..0000000 --- a/src/contrib/epee/include/md5_l.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5.h,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ - */ - -/* MD5.H - header file for MD5C.C - */ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. -These notices must be retained in any copies of any part of this -documentation and/or software. - */ -#ifndef MD5_H -#define MD5_H - - -#include "md5global.h" - -namespace md5 -{ - /* MD5 context. */ - typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ - } MD5_CTX; - - static void MD5Init(MD5_CTX * context); - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ); - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ); - static void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest); - - - inline bool md5( unsigned char *input, int ilen, unsigned char output[16] ) - { - MD5_CTX ctx; - - MD5Init( &ctx ); - MD5Update( &ctx, input, ilen ); - MD5Final( output, &ctx); - - memset( &ctx, 0, sizeof( MD5_CTX) ); - return true; - } - - -} - -#include "md5_l.inl" - -#endif diff --git a/src/contrib/epee/include/md5_l.inl b/src/contrib/epee/include/md5_l.inl deleted file mode 100644 index c3da1a3..0000000 --- a/src/contrib/epee/include/md5_l.inl +++ /dev/null @@ -1,563 +0,0 @@ -/* -* libEtPan! -- a mail stuff library -* -* Copyright (C) 2001, 2005 - DINH Viet Hoa -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the libEtPan! project nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -* SUCH DAMAGE. -*/ - -/* -* $Id: md5.c,v 1.1.1.1 2005/03/18 20:17:27 zautrix Exp $ -*/ - -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm -*/ - -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. -*/ - -/* do i need all of this just for htonl()? damn. */ -//#include -//#include -//#include -//#include - - - -#include "md5global.h" -#include "md5_l.h" -#include "hmac-md5.h" - -namespace md5 -{ - /* Constants for MD5Transform routine. - */ - -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - - /* - static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); - static void Encode PROTO_LIST - ((unsigned char *, UINT4 *, unsigned int)); - static void Decode PROTO_LIST - ((UINT4 *, unsigned char *, unsigned int)); - static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); - static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); - */ - - static void MD5_memcpy (POINTER output, POINTER input, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - output[i] = input[i]; - } - - /* Note: Replace "for loop" with standard memset if possible. - */ - - static void MD5_memset (POINTER output, int value, unsigned int len) - { - unsigned int i; - - for (i = 0; i < len; i++) - ((char *)output)[i] = (char)value; - } - - static void MD5Transform (UINT4 state[4], unsigned char block[64]); - - static unsigned char* PADDING() - { - static unsigned char local_PADDING[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - return local_PADDING; - - } - - - - /* F, G, H and I are basic MD5 functions. - - */ -#ifdef I - /* This might be defined via NANA */ -#undef I -#endif - -#define MD5_M_F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define MD5_M_G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define MD5_M_H(x, y, z) ((x) ^ (y) ^ (z)) -#define MD5_M_I(x, y, z) ((y) ^ ((x) | (~z))) - - /* ROTATE_LEFT rotates x left n bits. - - */ - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - - /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. - Rotation is separate from addition to prevent recomputation. - */ - -#define FF(a, b, c, d, x, s, ac) { (a) += MD5_M_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define GG(a, b, c, d, x, s, ac) { (a) += MD5_M_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define HH(a, b, c, d, x, s, ac) { (a) += MD5_M_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define II(a, b, c, d, x, s, ac) { (a) += MD5_M_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } - - /* MD5 initialization. Begins an MD5 operation, writing a new context. - */ - - static void MD5Init(MD5_CTX * context) - { - context->count[0] = context->count[1] = 0; - - /* Load magic initialization constants. - - */ - context->state[0] = 0x67452301; - context->state[1] = 0xefcdab89; - context->state[2] = 0x98badcfe; - context->state[3] = 0x10325476; - } - - /* MD5 block update operation. Continues an MD5 message-digest - operation, processing another message block, and updating the context. - */ - - static void MD5Update( MD5_CTX *context, const unsigned char *input, unsigned int inputLen ) - { - unsigned int i, index, partLen; - - /* Compute number of bytes mod 64 */ - index = (unsigned int)((context->count[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((context->count[0] += ((UINT4)inputLen << 3)) - < ((UINT4)inputLen << 3)) - context->count[1]++; - context->count[1] += ((UINT4)inputLen >> 29); - - partLen = 64 - index; - - /* Transform as many times as possible. - - */ - if (inputLen >= partLen) - { - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)input, partLen ); - MD5Transform( context->state, context->buffer ); - - for (i = partLen; i + 63 < inputLen; i += 64) - MD5Transform (context->state, (unsigned char*)&input[i]); - - index = 0; - } - else - i = 0; - - /* Buffer remaining input */ - MD5_memcpy( (POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i ); - - } - - /* Encodes input (UINT4) into output (unsigned char). Assumes len is - a multiple of 4. - - */ - - static void Encode (unsigned char *output, UINT4 *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (unsigned char)(input[i] & 0xff); - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); - } - } - - /* Decodes input (unsigned char) into output (UINT4). Assumes len is - a multiple of 4. - - */ - - static void Decode (UINT4 *output, unsigned char *input, unsigned int len) - { - unsigned int i, j; - - for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) - | (((UINT4)input[j+3]) << 24); - } - - /* MD5 finalization. Ends an MD5 message-digest operation, writing the - the message digest and zeroizing the context. - - */ - - static void MD5Final ( unsigned char digest[16], MD5_CTX *context ) - { - unsigned char bits[8]; - unsigned int index, padLen; - - /* Save number of bits */ - Encode (bits, context->count, 8); - - /* Pad out to 56 mod 64. - - */ - index = (unsigned int)((context->count[0] >> 3) & 0x3f); - padLen = (index < 56) ? (56 - index) : (120 - index); - MD5Update (context, PADDING(), padLen); - - /* Append length (before padding) */ - MD5Update (context, bits, 8); - - /* Store state in digest */ - Encode (digest, context->state, 16); - - /* Zeroize sensitive information. - - */ - MD5_memset ((POINTER)context, 0, sizeof (*context)); - } - - /* MD5 basic transformation. Transforms state based on block. - - */ - - static void MD5Transform (UINT4 state[4], unsigned char block[64]) - { - UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - - Decode (x, block, 64); - - /* Round 1 */ - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - - /* Zeroize sensitive information. - */ - MD5_memset ((POINTER)x, 0, sizeof (x)); - } - - /* Note: Replace "for loop" with standard memcpy if possible. - - */ - inline - void hmac_md5_init(HMAC_MD5_CTX *hmac, - const unsigned char *key, - int key_len) - { - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - MD5Init(&hmac->ictx); /* init inner context */ - MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ - - MD5Init(&hmac->octx); /* init outer context */ - MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ - - /* scrub the pads and key context (if used) */ - MD5_memset( (POINTER)&k_ipad, 0, sizeof(k_ipad)); - MD5_memset( (POINTER)&k_opad, 0, sizeof(k_opad)); - MD5_memset( (POINTER)&tk, 0, sizeof(tk)); - - /* and we're done. */ - } - - /* The precalc and import routines here rely on the fact that we pad - * the key out to 64 bytes and use that to initialize the md5 - * contexts, and that updating an md5 context with 64 bytes of data - * leaves nothing left over; all of the interesting state is contained - * in the state field, and none of it is left over in the count and - * buffer fields. So all we have to do is save the state field; we - * can zero the others when we reload it. Which is why the decision - * was made to pad the key out to 64 bytes in the first place. */ - inline - void hmac_md5_precalc(HMAC_MD5_STATE *state, - const unsigned char *key, - int key_len) - { - HMAC_MD5_CTX hmac; - unsigned lupe; - - hmac_md5_init(&hmac, key, key_len); - for (lupe = 0; lupe < 4; lupe++) { - state->istate[lupe] = htonl(hmac.ictx.state[lupe]); - state->ostate[lupe] = htonl(hmac.octx.state[lupe]); - } - MD5_memset( (POINTER)&hmac, 0, sizeof(hmac)); - } - - - inline - void hmac_md5_import(HMAC_MD5_CTX *hmac, - HMAC_MD5_STATE *state) - { - unsigned lupe; - MD5_memset( (POINTER)hmac, 0, sizeof(HMAC_MD5_CTX)); - for (lupe = 0; lupe < 4; lupe++) { - hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); - hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); - } - /* Init the counts to account for our having applied - * 64 bytes of key; this works out to 0x200 (64 << 3; see - * MD5Update above...) */ - hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; - } - - inline - void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], - HMAC_MD5_CTX *hmac) - { - MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ - MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ - MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ - } - - - void hmac_md5(const unsigned char* text, int text_len, const unsigned char* key, int key_len, unsigned char *digest) - { - MD5_CTX context; - - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - MD5_memset(k_ipad, '\0', sizeof k_ipad); - MD5_memset(k_opad, '\0', sizeof k_opad); - MD5_memcpy( k_ipad, (POINTER)key, key_len); - MD5_memcpy( k_opad, (POINTER)key, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ - - MD5Init(&context); /* init context for 1st - * pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final(digest, &context); /* finish up 1st pass */ - - /* - * perform outer MD5 - */ - MD5Init(&context); /* init context for 2nd - * pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st - * hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ - - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/md5global.h b/src/contrib/epee/include/md5global.h deleted file mode 100644 index afc2290..0000000 --- a/src/contrib/epee/include/md5global.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * libEtPan! -- a mail stuff library - * - * Copyright (C) 2001, 2005 - DINH Viet Hoa - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the libEtPan! project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $ - */ - -/* GLOBAL.H - RSAREF types and constants - */ - -#ifndef MD5GLOBAL_H -#define MD5GLOBAL_H - -namespace md5 -{ - - - /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. - The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. - */ -#ifndef PROTOTYPES -#define PROTOTYPES 0 -#endif - - /* POINTER defines a generic pointer type */ - typedef unsigned char *POINTER; - - /* UINT2 defines a two byte word */ - typedef unsigned short int UINT2; - - /* UINT4 defines a four byte word */ - //typedef unsigned long int UINT4; - typedef unsigned int UINT4; - - /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. - If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. - */ -#if PROTOTYPES -#define PROTO_LIST(list) list -#else -#define PROTO_LIST(list) () -#endif - -} - -#endif diff --git a/src/contrib/epee/include/misc_helpers.h b/src/contrib/epee/include/misc_helpers.h deleted file mode 100644 index dd3067c..0000000 --- a/src/contrib/epee/include/misc_helpers.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2019, Zano Project -// Copyright (c) 2006-2019, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once - -#define COMBINE1(X,Y) X##Y // helper macro -#define COMBINE(X,Y) COMBINE1(X,Y) -#define _STR(X) #X -#define STR(X) _STR(X) - -#if defined(_MSC_VER) -#define LOCAL_FUNCTION_DEF__ __FUNCTION__ -#define UNUSED_ATTRIBUTE -#else -#define LOCAL_FUNCTION_DEF__ __FUNCTION__ -#define UNUSED_ATTRIBUTE __attribute__((unused)) -#endif - -#define LOCATION_SS "[" << LOCAL_FUNCTION_DEF__ << ("] @ " __FILE__ ":" STR(__LINE__)) -#define LOCATION_STR (std::string("[") + LOCAL_FUNCTION_DEF__ + "] @ " __FILE__ ":" STR(__LINE__)) - - -// -// Try-catch helpers -// - -#define TRY_ENTRY() try { -#define CATCH_ALL_DO_NOTHING() }catch(...) {} - -#define CATCH_ENTRY_CUSTOM(location, custom_code, return_val) } \ - catch(const std::exception& ex) \ -{ \ - (void)(ex); \ - LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ - custom_code; \ - return return_val; \ -} \ - catch(...) \ -{ \ - LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \ - custom_code; \ - return return_val; \ -} -#define CATCH_ENTRY(location, return_val) CATCH_ENTRY_CUSTOM(location, (void)0, return_val) -#define CATCH_ENTRY2(return_val) CATCH_ENTRY_CUSTOM(LOCATION_SS, (void)0, return_val) - -#define CATCH_ENTRY_L0(location, return_val) CATCH_ENTRY(location, return_val) -#define CATCH_ENTRY_L1(location, return_val) CATCH_ENTRY(location, return_val) -#define CATCH_ENTRY_L2(location, return_val) CATCH_ENTRY(location, return_val) -#define CATCH_ENTRY_L3(location, return_val) CATCH_ENTRY(location, return_val) -#define CATCH_ENTRY_L4(location, return_val) CATCH_ENTRY(location, return_val) - -/// @brief Catches TRY_ENTRY without returning -/// @details Useful within a dtor - but only if nested within another try block -/// (since we can still potentially throw here). See NESTED_*ENTRY() -/// @todo Exception dispatcher class -#define CATCH_ENTRY_NO_RETURN_CUSTOM(location, custom_code) } \ - catch(const std::exception& ex) \ -{ \ - (void)(ex); \ - LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ - custom_code; \ -} \ - catch(...) \ -{ \ - LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \ - custom_code; \ -} - -#define CATCH_ENTRY_NO_RETURN() CATCH_ENTRY_NO_RETURN_CUSTOM(LOCATION_SS, (void)0) - -#define CATCH_ENTRY_WITH_FORWARDING_EXCEPTION() } \ - catch(const std::exception& ex) \ -{ \ - LOG_ERROR("Exception at [" << LOCATION_SS << "], what=" << ex.what()); \ - throw std::runtime_error(std::string("[EXCEPTION FORWARDED]: ") + ex.what()); \ -} \ - catch(...) \ -{ \ - LOG_ERROR("Exception at [" << LOCATION_SS << "], generic unknown exception \"...\""); \ - throw std::runtime_error("[EXCEPTION FORWARDED]"); \ -} - - - -#define NESTED_TRY_ENTRY() try { TRY_ENTRY(); - -#define NESTED_CATCH_ENTRY(location) \ - CATCH_ENTRY_NO_RETURN_CUSTOM(location, {}); \ - } catch (...) {} - - - diff --git a/src/contrib/epee/include/misc_language.h b/src/contrib/epee/include/misc_language.h deleted file mode 100644 index 276dfe0..0000000 --- a/src/contrib/epee/include/misc_language.h +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -#include -#include "include_base_utils.h" -#include "auto_val_init.h" - - -#define MARK_AS_POD_C11(type) \ -namespace std \ -{ \ - template<> \ -struct is_pod< type > \ - { \ - static const bool value = true; \ - }; \ -} - - -namespace epee -{ -#define STD_TRY_BEGIN() try { - -#define STD_TRY_CATCH(where_, ret_val) \ - } \ - catch (const std::exception &e) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ << ", mes: "<< e.what()); \ - return ret_val; \ - } \ - catch (...) \ - { \ - LOG_ERROR("EXCEPTION: " << where_ ); \ - return ret_val; \ - } - - -#define STD_TRY_CATCH_LOCATION(return_val) STD_TRY_CATCH(LOCATION_SS, return_val) - - /* helper class, to make able get namespace via decltype()::*/ - template - class namespace_accessor: public base_class{}; - - -#define STRINGIFY_EXPAND(s) STRINGIFY(s) -#define STRINGIFY(s) #s - - - -namespace misc_utils -{ - template - struct triple - { // store a pair of values - typedef _Ty1 first_type; - typedef _Ty2 second_type; - typedef _Ty3 third_type; - - triple() - : first(), second(), third() - { // default construct - } - - triple(const _Ty1& _Val1, const _Ty2& _Val2, const _Ty3& _Val3) - : first(_Val1), second(_Val2), third(_Val3) - { // construct from specified values - } - - _Ty1 first; // the first stored value - _Ty2 second; // the second stored value - _Ty3 third; // the second stored value - }; - - - - template - t_type get_max_t_val(t_type t) - { - return (std::numeric_limits::max)(); - } - - // TEMPLATE STRUCT less - template - struct less_as_pod - : public std::binary_function<_Ty, _Ty, bool> - { // functor for operator< - bool operator()(const _Ty& _Left, const _Ty& _Right) const - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - }; - - template - bool is_less_as_pod(const _Ty& _Left, const _Ty& _Right) - { // apply operator< to operands - return memcmp(&_Left, &_Right, sizeof(_Left)) < 0; - } - - - inline - bool sleep_no_w(long ms ) - { - boost::this_thread::sleep( - boost::get_system_time() + - boost::posix_time::milliseconds( std::max(ms,0) ) ); - - return true; - } - /************************************************************************/ - /* */ - /************************************************************************/ - template - class median_helper - { - typedef std::multiset ordered_items_container; - typedef std::pair queued_item_type; - typedef std::list queued_items_container; - typedef std::list > recent_items_container; - ordered_items_container ordered_items; - queued_items_container queued_items; - recent_items_container recent_items; // this needed to have chance to roll back at least for some depth, so we keep elements removed from median window for a while - bool had_been_in_recent_items; - mutable critical_section m_lock; - - typename ordered_items_container::iterator m_current_median_it; - uint64_t current_index; - - virtual void handle_purge_back_item() {} - virtual void handle_add_front_item(const key& k, const associated_data& ad) {} - virtual void handle_remove_front_item(const key& k) {} - void push_item_as_recent(const key& k, const associated_data& ad) - { - CRITICAL_REGION_LOCAL(m_lock); - auto it = ordered_items.insert(k); - queued_items.push_front(queued_item_type(it, ad)); - } - public: - median_helper() :had_been_in_recent_items(false) - { - m_current_median_it = ordered_items.end(); - current_index = 0; - } - void clear() - { - CRITICAL_REGION_LOCAL(m_lock); - ordered_items.clear(); - queued_items.clear(); - recent_items.clear(); - had_been_in_recent_items = false; - m_current_median_it = ordered_items.end(); - current_index = 0; - } - - void push_item(const key& k, const associated_data& ad) - { - CRITICAL_REGION_LOCAL(m_lock); - auto it = ordered_items.insert(k); - queued_items.push_back(queued_item_type(it, ad)); - handle_add_front_item(k, ad); - } - - void pop_item() - { - CRITICAL_REGION_LOCAL(m_lock); - if (!queued_items.empty()) - { - auto it = queued_items.back().first; - handle_remove_front_item(*it); - ordered_items.erase(it); - queued_items.pop_back(); - } - } - - /* - cb(key, associated_data) - enumerating while result is false - when returned true - clean items behind and move it to recent_items - - cb_final_remove(key, associated_data) - for every element in recent_items if returned false - element removed forever - */ - template - bool scan_items(cb_t cb, cb_t2 cb_final_remove) - { - CRITICAL_REGION_LOCAL(m_lock); - //process median window items - for (auto it = queued_items.begin(); it != queued_items.end(); it++) - { - if (cb(*it->first, it->second)) - { - //stop element, remove all items before this - for (auto clean_it = queued_items.begin(); clean_it != it; clean_it++) - { - //std::pair p(*it->first, it->second); - recent_items.push_back(std::make_pair(*clean_it->first, clean_it->second)); - had_been_in_recent_items = true; - ordered_items.erase(clean_it->first); - } - queued_items.erase(queued_items.begin(), it); - break; - } - } - //process recent items front part (put back to median window set if needed) - for (auto it = recent_items.rbegin(); it != recent_items.rend();) - { - if (!cb(it->first, it->second)) - break;//element should stay in recent - - //element should be back to median window - this->push_item_as_recent(it->first, it->second); - it = typename recent_items_container::reverse_iterator(recent_items.erase((++it).base())); // remove *it and advance 'it' by 1 - } - - - //process recent items back part (remove outdated elements) - while (recent_items.size() && !cb_final_remove(recent_items.begin()->first, recent_items.begin()->second)) - { - recent_items.erase(recent_items.begin()); - handle_purge_back_item(); - } - - //detect if recent_items exhausted - if (!recent_items.size() && had_been_in_recent_items) - { - LOG_PRINT_RED_L0("[MEDIAN_HELPER]: recent_items exhausted, need to rebuild median from scratch"); - return false; - } - return true; - } - - uint64_t get_median() const - { - CRITICAL_REGION_LOCAL(m_lock); - if (!ordered_items.size()) - return 0; - - size_t n = ordered_items.size() / 2; - //std::sort(v.begin(), v.end()); - - auto n_it = std::next(ordered_items.begin(), n); - - //nth_element(v.begin(), v.begin()+n-1, v.end()); - if (ordered_items.size() % 2) - {//1, 3, 5... - return *n_it; - } - else - {//2, 4, 6... - auto n_it_sub = n_it; - --n_it_sub; - return (*n_it_sub + *n_it) / 2; - } - } - - template - friend std::ostream & operator<< (std::ostream &out, median_helper const &mh); - }; // class median_helper - - template - std::ostream & operator<< (std::ostream &s, median_helper const &mh) - { - s << "median_helper<" << typeid(key_t).name() << ", " << typeid(associated_data_t).name() << "> instance 0x" << &mh << ENDL - << " ordered_items: " << mh.ordered_items.size() << ENDL - << " queued_items: " << mh.queued_items.size() << ENDL - << " recent_items: " << mh.recent_items.size() << ENDL - << " had_been_in_recent_items: " << mh.had_been_in_recent_items << ENDL; - return s; - } - - /************************************************************************/ - /* */ - /************************************************************************/ - template - type_vec_type median(std::vector &v) - { - //CRITICAL_REGION_LOCAL(m_lock); - if(v.empty()) - return boost::value_initialized(); - if(v.size() == 1) - return v[0]; - - size_t n = (v.size()) / 2; - std::sort(v.begin(), v.end()); - //nth_element(v.begin(), v.begin()+n-1, v.end()); - if(v.size()%2) - {//1, 3, 5... - return v[n]; - }else - {//2, 4, 6... - return (v[n-1] + v[n])/2; - } - - } - - /************************************************************************/ - /* */ - /************************************************************************/ - - struct call_befor_die_base - { - virtual ~call_befor_die_base(){} - }; - - typedef boost::shared_ptr auto_scope_leave_caller; - - - template - struct call_befor_die: public call_befor_die_base - { - t_scope_leave_handler m_func; - call_befor_die(t_scope_leave_handler f):m_func(f) - {} - ~call_befor_die() - { - NESTED_TRY_ENTRY(); - - m_func(); - - NESTED_CATCH_ENTRY(__func__); - } - }; - - template - auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f) - { - auto_scope_leave_caller slc(new call_befor_die(f)); - return slc; - } - - -#define ON_EXIT misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler - - - template< typename t_contaner, typename t_redicate> - void erase_if( t_contaner& items, const t_redicate& predicate ) - { - for(auto it = items.begin(); it != items.end(); ) - { - if( predicate(*it) ) - it = items.erase(it); - else - ++it; - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct call_basic - { - virtual void do_call(){}; - }; - - - template - struct call_specific: public call_basic - { - call_specific(t_callback cb):m_cb(cb) - {} - virtual void do_call() - { - m_cb(); - } - private: - t_callback m_cb; - }; - - template - auto build_abstract_callback(t_callback cb) -> std::shared_ptr - { - return std::shared_ptr(new call_specific(cb)); - } - - - - template - bool static_initializer(callback_type cb) - { - return cb(); - }; - - - template - typename t_container_type::mapped_type& get_or_insert_value_initialized(t_container_type& container, const typename t_container_type::key_type& key) - { - auto it = container.find(key); - if (it != container.end()) - { - return it->second; - } - - auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type()))); - return res.first->second; - } - - template - typename t_container_type::iterator it_get_or_insert_value_initialized(t_container_type& container, const typename t_container_type::key_type& key) - { - auto it = container.find(key); - if (it != container.end()) - { - return it; - } - - auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type()))); - return res.first; - } - -} // namespace misc_utils -} // namespace epee - -template -std::ostream& print_container_content(std::ostream& out, const T& v); - -namespace std -{ - template - std::ostream& operator<< (std::ostream& out, const std::vector& v) - { - return print_container_content(out, v); - } - - template - std::ostream& operator<< (std::ostream& out, const std::list& v) - { - return print_container_content(out, v); - } - -} // namespace std - -template -std::ostream& print_container_content(std::ostream& out, const T& v) -{ - - out << "["; - if (!v.size()) - { - out << "]"; - return out; - } - - typename T::const_iterator last_it = --v.end(); - - for (typename T::const_iterator it = v.begin(); it != v.end(); it++) - { - out << *it; - if (it != last_it) - out << ", "; - } - out << "]"; - return out; -} - - diff --git a/src/contrib/epee/include/misc_log_ex.h b/src/contrib/epee/include/misc_log_ex.h deleted file mode 100644 index 0b957a5..0000000 --- a/src/contrib/epee/include/misc_log_ex.h +++ /dev/null @@ -1,1764 +0,0 @@ -// Copyright (c) 2019, Zano Project -// Copyright (c) 2019, anonimal -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _MISC_LOG_EX_H_ -#define _MISC_LOG_EX_H_ - -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef Q_MOC_RUN -#include -#include -#include -#include -#include -#endif -#if defined(WIN32) -#include -#else -#include -#endif -#include "os_defenitions.h" -#include "warnings.h" -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4100) - - -#include "misc_helpers.h" -#include "static_helpers.h" -#include "string_tools.h" -#include "time_helper.h" -#include "misc_os_dependent.h" - -#include "syncobj.h" -#include "sync_locked_object.h" -#include "string_coding.h" -#include "file_io_utils.h" - -#define LOG_LEVEL_SILENT -1 -#define LOG_LEVEL_0 0 -#define LOG_LEVEL_1 1 -#define LOG_LEVEL_2 2 -#define LOG_LEVEL_3 3 -#define LOG_LEVEL_4 4 -#define LOG_LEVEL_MIN LOG_LEVEL_SILENT -#define LOG_LEVEL_MAX LOG_LEVEL_4 - - -#define LOGGER_NULL 0 -#define LOGGER_FILE 1 -#define LOGGER_DEBUGGER 2 -#define LOGGER_CONSOLE 3 -#define LOGGER_DUMP 4 - -#define LOG_JOURNAL_MAX_ELEMENTS 100 - -#ifdef _DEBUG - #define _ASSERTE__(expr) if(!expr) {__debugbreak();} -#else - #define _ASSERTE__(expr) -#endif - - -#ifndef LOCAL_ASSERT - #include - #if (defined _MSC_VER) - #define LOCAL_ASSERT(expr) {if(epee::debug::get_set_enable_assert()){_ASSERTE__(expr);}} - #define FORCE_ASSERT(expr) { _ASSERTE(expr); } - #else - #define LOCAL_ASSERT(expr) - #define FORCE_ASSERT(expr) - #endif -#endif - - -#if !defined(DISABLE_RELEASE_LOGGING) - #define ENABLE_LOGGING_INTERNAL -#endif - -#define LOG_DEFAULT_CHANNEL NULL - -#define ENABLE_CHANNEL_BY_DEFAULT(ch_name) \ - static bool COMBINE(init_channel, __LINE__) UNUSED_ATTRIBUTE = epee::misc_utils::static_initializer([](){ \ - epee::log_space::log_singletone::enable_channel(ch_name); return true; \ -}); - - - -#if defined(ENABLE_LOGGING_INTERNAL) - -#define LOG_PRINT_CHANNEL_NO_PREFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str() , y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}} - -#define LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}} - -#define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}} - -#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);cb(ss________.str());CATCH_ALL_DO_NOTHING();}} - -#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name); cb(ss________.str());CATCH_ALL_DO_NOTHING();}} - -#define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);CATCH_ALL_DO_NOTHING();}} - -#define LOG_ERROR2_CB(log_name, x, cb) { \ - TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "[ERROR] Location: " << std::endl << LOCATION_SS << epee::misc_utils::get_callstack() << " Message:" << std::endl << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name); LOCAL_ASSERT(0); epee::log_space::increase_error_count(LOG_DEFAULT_CHANNEL); cb(ss________.str()); CATCH_ALL_DO_NOTHING();} - -#define LOG_ERROR2(log_name, x) LOG_ERROR2_CB(log_name, x, epee::log_space::log_stub) -#define LOG_PRINT_CHANNEL2(log_channel, log_name, x, y) LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, epee::log_space::log_stub) -#define LOG_PRINT_CHANNEL_COLOR2(log_channel, log_name, x, y, color) LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, epee::log_space::log_stub) - -#define LOG_FRAME2(log_name, x, y) epee::log_space::log_frame frame(x, y, log_name) - -#else // #if defined(ENABLE_LOGGING_INTERNAL) - -#define LOG_PRINT_NO_PREFIX2(log_name, x, y) -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) -#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) -#define LOG_PRINT_COLOR2(log_name, x, y, color) -#define LOG_PRINT2_JORNAL(log_name, x, y) -#define LOG_PRINT2(log_name, x, y) -#define LOG_ERROR2(log_name, x) -#define LOG_FRAME2(log_name, x, y) - -#endif // #if defined(ENABLE_LOGGING_INTERNAL) - -#define LOG_PRINT_NO_PREFIX2(log_name, x, y) LOG_PRINT_CHANNEL_NO_PREFIX2(LOG_DEFAULT_CHANNEL, log_name, x, y) -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_CHANNEL, log_name, x, y) -#define LOG_PRINT_NO_POSTFIX2(log_name, x, y) LOG_PRINT_CHANNEL_NO_POSTFIX2(LOG_DEFAULT_CHANNEL, log_name, x, y) -#define LOG_PRINT2(log_name, x, y) LOG_PRINT_CHANNEL2(LOG_DEFAULT_CHANNEL, log_name, x, y) -#define LOG_PRINT2_CB(log_name, x, y, cb) LOG_PRINT_CHANNEL2_CB(LOG_DEFAULT_CHANNEL, log_name, x, y, cb) -#define LOG_PRINT_COLOR2(log_name, x, y, color) LOG_PRINT_CHANNEL_COLOR2(LOG_DEFAULT_CHANNEL, log_name, x, y, color) -#define LOG_PRINT_COLOR2_CB(log_name, x, y, color, cb) LOG_PRINT_CHANNEL_COLOR2_CB(LOG_DEFAULT_CHANNEL, log_name, x, y, color, cb) -#define LOG_PRINT2_JORNAL(log_name, x, y) LOG_PRINT_CHANNEL_2_JORNAL(LOG_DEFAULT_CHANNEL, log_name, x, y) - -#ifndef LOG_DEFAULT_TARGET - #define LOG_DEFAULT_TARGET NULL -#endif - -#define LOG_PRINT_NO_POSTFIX(mess, level) LOG_PRINT_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT_NO_PREFIX(mess, level) LOG_PRINT_NO_PREFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT_NO_PREFIX_NO_POSTFIX(mess, level) LOG_PRINT_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) - -#define LOG_PRINT(mess, level) LOG_PRINT2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT_CB(mess, level, cb) LOG_PRINT2_CB(LOG_DEFAULT_TARGET, mess, level, cb) -#define LOG_PRINT_COLOR_CB(mess, level, color, cb) LOG_PRINT_COLOR2_CB(LOG_DEFAULT_TARGET, mess, level, color, cb) - -#define LOG_COLOR_RED epee::log_space::console_color_red -#define LOG_COLOR_GREEN epee::log_space::console_color_green -#define LOG_COLOR_BLUE epee::log_space::console_color_blue -#define LOG_COLOR_YELLOW epee::log_space::console_color_yellow -#define LOG_COLOR_CYAN epee::log_space::console_color_cyan -#define LOG_COLOR_MAGENTA epee::log_space::console_color_magenta - -#define LOG_PRINT_COLOR(mess, level, color) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, color) -#define LOG_PRINT_RED(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_RED) -#define LOG_PRINT_GREEN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_GREEN) -#define LOG_PRINT_BLUE(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_BLUE) -#define LOG_PRINT_YELLOW(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_YELLOW) -#define LOG_PRINT_CYAN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_CYAN) -#define LOG_PRINT_MAGENTA(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_MAGENTA) - -#define LOG_PRINT_RED_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_red) -#define LOG_PRINT_GREEN_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_green) - -#define LOG_PRINT_L0(mess) LOG_PRINT(mess, LOG_LEVEL_0) -#define LOG_PRINT_L1(mess) LOG_PRINT(mess, LOG_LEVEL_1) -#define LOG_PRINT_L2(mess) LOG_PRINT(mess, LOG_LEVEL_2) -#define LOG_PRINT_L3(mess) LOG_PRINT(mess, LOG_LEVEL_3) -#define LOG_PRINT_L4(mess) LOG_PRINT(mess, LOG_LEVEL_4) -#define LOG_PRINT_J(mess, level) LOG_PRINT2_JORNAL(LOG_DEFAULT_TARGET, mess, level) - -#define LOG_ERROR(mess) LOG_ERROR2(LOG_DEFAULT_TARGET, mess) -#define LOG_ERROR_CB(mess, cb) LOG_ERROR2_CB(LOG_DEFAULT_TARGET, mess, cb) -#define LOG_FRAME(mess, level) LOG_FRAME2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_VALUE(mess, level) LOG_VALUE2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_ARRAY(mess, level) LOG_ARRAY2(LOG_DEFAULT_TARGET, mess, level) -//#define LOGWIN_PLATFORM_ERROR(err_no) LOGWINDWOS_PLATFORM_ERROR2(LOG_DEFAULT_TARGET, err_no) -#define LOG_SOCKET_ERROR(err_no) LOG_SOCKET_ERROR2(LOG_DEFAULT_TARGET, err_no) -//#define LOGWIN_PLATFORM_ERROR_UNCRITICAL(mess) LOGWINDWOS_PLATFORM_ERROR_UNCRITICAL2(LOG_DEFAULT_TARGET, mess) - -#define ENDL std::endl - - -#define ASSERT_MES_AND_THROW(message) {LOG_ERROR(message); std::stringstream ss; ss << message; throw std::runtime_error(ss.str());} - -#define CHECK_AND_ASSERT_THROW_MES(expr, message) {if(!(expr)) ASSERT_MES_AND_THROW(message << ENDL << "thrown from " << LOCATION_SS);} -#define CHECK_AND_ASSERT_THROW(expr, exception_exp) {if(!(expr)) {LOG_ERROR("EXCEPTION is thrown from " << LOCATION_SS); throw exception_exp; };} - -#ifndef CHECK_AND_ASSERT -#define CHECK_AND_ASSERT(expr, fail_ret_val) do{if(!(expr)){LOCAL_ASSERT(expr); return fail_ret_val;};}while(0) -#endif - -#define NOTHING - -#ifndef CHECK_AND_ASSERT_MES -#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_ERROR(message); return fail_ret_val;};}while(0) -#endif - -#ifndef CHECK_AND_FORCE_ASSERT_MES -#define CHECK_AND_FORCE_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_ERROR(message); FORCE_ASSERT(expr); return fail_ret_val;};}while(0) -#endif - -#ifndef CHECK_AND_ASSERT_MES_CUSTOM -#define CHECK_AND_ASSERT_MES_CUSTOM(expr, fail_ret_val, custom_code, message) do{if(!(expr)) {LOG_ERROR(message); custom_code; return fail_ret_val;};}while(0) -#endif - -/*#ifndef CHECK_AND_ASSERT_MES_AND_THROW -#define CHECK_AND_ASSERT_MES_AND_THROW(expr, message) do{if(!(expr)) {LOG_ERROR(message); throw std::runtime_error(message);};}while(0) -#endif -*/ - -#ifndef CHECK_AND_NO_ASSERT_MES -#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_PRINT_MAGENTA(message, LOG_LEVEL_0); /*LOCAL_ASSERT(expr);*/ return fail_ret_val;};}while(0) -#endif - -#ifndef CHECK_AND_NO_ASSERT_MES_LEVEL -#define CHECK_AND_NO_ASSERT_MES_LEVEL(expr, fail_ret_val, message, log_level) do{if(!(expr)) {LOG_PRINT(message, log_level); return fail_ret_val;};}while(0) -#endif - -#ifndef CHECK_AND_ASSERT_MES_NO_RET -#define CHECK_AND_ASSERT_MES_NO_RET(expr, message) do{if(!(expr)) {LOG_ERROR(message);};}while(0) -#endif - -#ifndef CHECK_AND_ASSERT_MES2 -#define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0) -#endif - -namespace epee -{ -namespace debug -{ - inline bool get_set_enable_assert(bool set = false, bool v = false) - { - static bool e = true; - if(set) - e = v; - return e; - } -} -namespace log_space -{ - class logger; - class log_message; - class log_singletone; - - /************************************************************************/ - /* */ - /************************************************************************/ - enum console_colors - { - console_color_default, - console_color_white, - console_color_red, - console_color_green, - console_color_blue, - console_color_cyan, - console_color_magenta, - console_color_yellow - }; - - - struct ibase_log_stream - { - ibase_log_stream(){} - virtual ~ibase_log_stream(){} - virtual bool out_buffer( const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL)=0; - virtual int get_type(){return 0;} - - virtual bool set_max_logfile_size(uint64_t max_size){return true;}; - virtual bool set_log_rotate_cmd(const std::string& cmd){return true;}; - virtual bool truncate_log_files() { return true; } - virtual std::string copy_logs_to_buffer() { return ""; } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - /*struct ibase_log_value - { - public: - virtual void debug_out( std::stringstream* p_stream)const = 0; - };*/ - - /************************************************************************/ - /* */ - /************************************************************************/ - /*class log_message: public std::stringstream - { - public: - log_message(const log_message& lm): std::stringstream(), std::stringstream::basic_ios() - {} - log_message(){} - - template - log_message& operator<< (T t) - { - std::stringstream* pstrstr = this; - (*pstrstr) << t; - - return *this; - } - }; - inline - log_space::log_message& operator<<(log_space::log_message& sstream, const ibase_log_value& log_val) - { - log_val.debug_out(&sstream); - return sstream; - } - */ - /************************************************************************/ - /* */ - /************************************************************************/ -#define CONSOLE_DEFAULT_STREAM std::cout - - inline void log_stub(const std::string& /**/) {} - - struct delete_ptr - { - template - void operator() (P p) - { - delete p.first; - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - //------------------------------------------------------------------------ -#define max_dbg_str_len 80 -#ifdef _MSC_VER - class debug_output_stream: public ibase_log_stream - { - virtual bool out_buffer( const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL) - { - for ( int i = 0; i < buffer_len; i = i + max_dbg_str_len ) - { - std::string s( buffer + i, buffer_len- i < max_dbg_str_len ? - buffer_len - i : max_dbg_str_len ); - - ::OutputDebugStringA( s.c_str() ); - } - return true; - } - - }; -#endif - - inline bool is_stdout_a_tty() - { -#ifndef ANDROID_BUILD - static std::atomic initialized(false); - static std::atomic is_a_tty(false); - - if (!initialized.load(std::memory_order_acquire)) - { -#if defined(WIN32) - is_a_tty.store(0 != _isatty(_fileno(stdout)), std::memory_order_relaxed); -#else - is_a_tty.store(0 != isatty(fileno(stdout)), std::memory_order_relaxed); -#endif - initialized.store(true, std::memory_order_release); - } - - return is_a_tty.load(std::memory_order_relaxed); -#else - return false; -#endif - } - - inline void set_console_color(int color, bool bright) - { - if (!is_stdout_a_tty()) - return; - - switch(color) - { - case console_color_default: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE| (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;37m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0m"; -#endif - } - break; - case console_color_white: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;37m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;37m"; -#endif - } - break; - case console_color_red: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;31m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;31m"; -#endif - } - break; - case console_color_green: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;32m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;32m"; -#endif - } - break; - - case console_color_blue: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_INTENSITY);//(bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;34m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;34m"; -#endif - } - break; - - case console_color_cyan: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;36m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;36m"; -#endif - } - break; - - case console_color_magenta: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;35m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;35m"; -#endif - } - break; - - case console_color_yellow: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - CONSOLE_DEFAULT_STREAM << "\033[1;33m"; - else - CONSOLE_DEFAULT_STREAM << "\033[0;33m"; -#endif - } - break; - - } - } - - inline void reset_console_color() { - if (!is_stdout_a_tty()) - return; - -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); -#else - CONSOLE_DEFAULT_STREAM << "\033[0m"; - CONSOLE_DEFAULT_STREAM.flush(); -#endif - } - - class console_output_stream: public ibase_log_stream - { -#ifdef _MSC_VER - bool m_have_to_kill_console; -#endif - - public: - console_output_stream() - { -#ifdef _MSC_VER - - if(!::GetStdHandle(STD_OUTPUT_HANDLE)) - m_have_to_kill_console = true; - else - m_have_to_kill_console = false; - - ::AllocConsole(); - freopen("CONOUT$", "w", stdout); - std::cout.clear(); -#endif - } - - ~console_output_stream() - { -#ifdef _MSC_VER - if(m_have_to_kill_console) - ::FreeConsole(); -#endif - } - int get_type(){return LOGGER_CONSOLE;} - - - - virtual bool out_buffer( const char* buffer, int buffer_len , int log_level, int color, const char* plog_name = NULL) - { - if(plog_name) - return true; //skip alternative logs from console - - set_console_color(color, log_level < 1); - -#ifdef _MSC_VER - const char* ptarget_buf = NULL; - char* pallocated_buf = NULL; - - // - int i = 0; - for(; i < buffer_len; i++) - if(buffer[i] == '\a') break; - if(i == buffer_len) - ptarget_buf = buffer; - else - { - pallocated_buf = new char[buffer_len]; - ptarget_buf = pallocated_buf; - for(i = 0; i < buffer_len; i++) - { - if(buffer[i] == '\a') - pallocated_buf[i] = '^'; - else - pallocated_buf[i] = buffer[i]; - } - } - - //uint32_t b = 0; - //::WriteConsoleA(::GetStdHandle(STD_OUTPUT_HANDLE), ptarget_buf, buffer_len, (DWORD*)&b, 0); - CONSOLE_DEFAULT_STREAM << ptarget_buf; - if(pallocated_buf) delete [] pallocated_buf; -#else - std::string buf(buffer, buffer_len); - for(size_t i = 0; i!= buf.size(); i++) - { - if(static_cast(buf[i]) == 0x7 || static_cast(buf[i]) == 0x95) - buf[i] = '^'; - } - - CONSOLE_DEFAULT_STREAM << buf; -#endif - reset_console_color(); - return true; - } - - - }; - - inline bool rotate_log_file(const char* pfile_path) - { -#ifdef _MSC_VER - if(!pfile_path) - return false; - - std::string file_path = pfile_path; - std::string::size_type a = file_path .rfind('.'); - if ( a != std::string::npos ) - file_path .erase( a, file_path .size()); - - ::DeleteFileA( (file_path + ".0").c_str() ); - ::MoveFileA( (file_path + ".log").c_str(), (file_path + ".0").c_str() ); -#else - return false;//not implemented yet -#endif - return true; - } - - - - - //--------------------------------------------------------------------------// - class file_output_stream : public ibase_log_stream - { - public: - typedef std::map > named_log_streams; - - file_output_stream( const std::string& default_log_file_name, const std::string& log_path ) - { - m_default_log_filename = default_log_file_name; - m_max_logfile_size = 0; - m_default_log_path_w = epee::string_encoding::utf8_to_wstring(log_path); - m_pdefault_file_stream = add_new_stream_and_open(default_log_file_name.c_str()); - } - - ~file_output_stream() - { - for(named_log_streams::iterator it = m_log_file_names.begin(); it!=m_log_file_names.end(); it++) - { - if ( it->second.first->is_open() ) - { - it->second.first->flush(); - it->second.first->close(); - } - delete it->second.first; - } - } - private: - named_log_streams m_log_file_names; - std::wstring m_default_log_path_w; - boost::filesystem::ofstream* m_pdefault_file_stream; - std::string m_log_rotate_cmd; - std::string m_default_log_filename; - uint64_t m_max_logfile_size; - - - // gets utf-8 encoded string - boost::filesystem::ofstream* add_new_stream_and_open(const char* pstream_name) - { - //log_space::rotate_log_file((m_default_log_path + "\\" + pstream_name).c_str()); - boost::system::error_code ec; - boost::filesystem::create_directories(m_default_log_path_w, ec); - boost::filesystem::ofstream* pstream = new boost::filesystem::ofstream; - - std::wstring target_path = epee::string_encoding::utf8_to_wstring(pstream_name); - if (!m_default_log_path_w.empty()) - target_path = m_default_log_path_w + L"/" + target_path; - - pstream->open( target_path.c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */); - if(pstream->fail()) - return NULL; - m_log_file_names[pstream_name] = std::pair(pstream, target_path); - return pstream; - } - - bool set_max_logfile_size(uint64_t max_size) - { - m_max_logfile_size = max_size; - return true; - } - - bool set_log_rotate_cmd(const std::string& cmd) - { - m_log_rotate_cmd = cmd; - return true; - } - - bool truncate_log_files() - { - for (named_log_streams::iterator it = m_log_file_names.begin(); it != m_log_file_names.end(); it++) - { - std::wstring target_path = it->second.second; - //close and delete current stream - if (it->second.first->is_open()) - { - it->second.first->flush(); - it->second.first->close(); - } - delete it->second.first; - it->second.first = nullptr; - //reopen it with truncate - boost::filesystem::ofstream* pstream = new boost::filesystem::ofstream; - pstream->open(target_path.c_str(), std::ios_base::out | std::ios::trunc ); - if (pstream->fail()) - { - throw std::runtime_error("Unexpected error: failed to re-open log stream on truncate"); - } - it->second.first = pstream; - } - return true; - } - - std::string copy_logs_to_buffer() - { - std::stringstream res; - - for (named_log_streams::iterator it = m_log_file_names.begin(); it != m_log_file_names.end(); it++) - { - std::wstring target_path = it->second.second; - res << "[" << epee::string_encoding::convert_to_ansii(target_path) << "]" << ENDL; - std::string res_buf; - if (!epee::file_io_utils::load_file_to_string(target_path, res_buf)) - { - res << "ERROR"; - } - else - { - res << res_buf; - } - } - return res.str(); - } - - - virtual bool out_buffer( const char* buffer, int buffer_len, int log_level, int color, const char* plog_name = NULL ) - { - boost::filesystem::ofstream* m_target_file_stream = m_pdefault_file_stream; - if(plog_name) - { //find named stream - named_log_streams::iterator it = m_log_file_names.find(plog_name); - if(it == m_log_file_names.end()) - m_target_file_stream = add_new_stream_and_open(plog_name); - else - m_target_file_stream = it->second.first; - } - if(!m_target_file_stream || !m_target_file_stream->is_open()) - return false;//TODO: add assert here - - m_target_file_stream->write(buffer, buffer_len ); - m_target_file_stream->flush(); - - /* - if(m_max_logfile_size) - { - boost::filesystem::ofstream::pos_type pt = m_target_file_stream->tellp(); - uint64_t current_sz = pt; - if(current_sz > m_max_logfile_size) - { - CONSOLE_DEFAULT_STREAM << "current_sz= " << current_sz << " m_max_logfile_size= " << m_max_logfile_size << std::endl; - std::string log_file_name; - if(!plog_name) - log_file_name = m_default_log_filename; - else - log_file_name = plog_name; - - m_target_file_stream->close(); - std::string new_log_file_name = log_file_name; - - time_t tm = 0; - time(&tm); - - int err_count = 0; - boost::system::error_code ec; - do - { - new_log_file_name = string_tools::cut_off_extension(log_file_name); - if(err_count) - new_log_file_name += misc_utils::get_time_str_v2(tm) + "(" + boost::lexical_cast(err_count) + ")" + ".log"; - else - new_log_file_name += misc_utils::get_time_str_v2(tm) + ".log"; - - err_count++; - }while(boost::filesystem::exists(m_default_log_path + "/" + new_log_file_name, ec)); - - std::string new_log_file_path = m_default_log_path + "/" + new_log_file_name; - boost::filesystem::rename(m_default_log_path + "/" + log_file_name, new_log_file_path, ec); - if(ec) - { - CONSOLE_DEFAULT_STREAM << "Filed to rename, ec = " << ec.message() << std::endl; - } - - if(m_log_rotate_cmd.size()) - { - - std::string m_log_rotate_cmd_local_copy = m_log_rotate_cmd; - //boost::replace_all(m_log_rotate_cmd, "[*SOURCE*]", new_log_file_path); - boost::replace_all(m_log_rotate_cmd_local_copy, "[*TARGET*]", new_log_file_path); - - misc_utils::call_sys_cmd(m_log_rotate_cmd_local_copy); - } - - - m_target_file_stream->open( (m_default_log_path + "/" + log_file_name).c_str(), std::ios_base::out | std::ios::app / * ios_base::trunc * /); - if(m_target_file_stream->fail()) - return false; - } - } - */ - return true; - } - int get_type(){return LOGGER_FILE;} - }; - /************************************************************************/ - /* */ - /************************************************************************/ - class log_stream_splitter - { - public: - typedef std::list > streams_container; - - log_stream_splitter(){} - ~log_stream_splitter() - { - //free pointers - std::for_each(m_log_streams.begin(), m_log_streams.end(), delete_ptr()); - } - - bool set_max_logfile_size(uint64_t max_size) - { - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - it->first->set_max_logfile_size(max_size); - return true; - } - - bool set_log_rotate_cmd(const std::string& cmd) - { - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - it->first->set_log_rotate_cmd(cmd); - return true; - } - - bool truncate_log_files() - { - for (streams_container::iterator it = m_log_streams.begin(); it != m_log_streams.end(); it++) - it->first->truncate_log_files(); - return true; - } - - std::string copy_logs_to_buffer() - { - std::string res; - for (streams_container::iterator it = m_log_streams.begin(); it != m_log_streams.end(); it++) - res += it->first->copy_logs_to_buffer(); - return res; - } - - - bool do_log_message(const std::string& rlog_mes, int log_level, int color, const char* plog_name = NULL) - { - std::string str_mess = rlog_mes; - size_t str_len = str_mess.size(); - const char* pstr = str_mess.c_str(); - for(streams_container::iterator it = m_log_streams.begin(); it!=m_log_streams.end();it++) - if(it->second >= log_level) - it->first->out_buffer(pstr, (int)str_len, log_level, color, plog_name); - return true; - } - - std::string get_log_file_path() - { - return m_default_log_file_path; - } - - bool add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit = LOG_LEVEL_4 ) - { - ibase_log_stream* ls = NULL; - - switch( type ) - { - case LOGGER_FILE: - m_default_log_file_path = std::string(pdefault_log_folder) + "/" + pdefault_file_name; - ls = new file_output_stream( pdefault_file_name, pdefault_log_folder ); - break; - - case LOGGER_DEBUGGER: -#ifdef _MSC_VER - ls = new debug_output_stream( ); -#else - return false;//not implemented yet -#endif - break; - case LOGGER_CONSOLE: - ls = new console_output_stream( ); - break; - } - - if ( ls ) { - m_log_streams.push_back(streams_container::value_type(ls, log_level_limit)); - return true; - } - return false; - } - bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4 ) - { - m_log_streams.push_back(streams_container::value_type(pstream, log_level_limit) ); - return true; - } - - bool remove_logger(int type) - { - streams_container::iterator it = m_log_streams.begin(); - for(;it!=m_log_streams.end(); it++) - { - if(it->first->get_type() == type) - { - delete it->first; - m_log_streams.erase(it); - return true; - } - } - return false; - - } - - protected: - private: - - streams_container m_log_streams; - std::string m_default_log_file_path; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - inline int get_set_log_detalisation_level(bool is_need_set = false, int log_level_to_set = LOG_LEVEL_1); - inline int get_set_time_level(bool is_need_set = false, int time_log_level = LOG_LEVEL_0); - inline bool get_set_need_thread_id(bool is_need_set = false, bool is_need_val = false); - inline bool get_set_need_proc_name(bool is_need_set = false, bool is_need_val = false); - - typedef std::map channels_err_stat_container_type; - inline epee::locked_object_proxy get_channels_errors_stat_container() - { - static epee::static_helpers::wrapper cs; - static epee::static_helpers::wrapper errors_by_channel; - epee::locked_object_proxy res(errors_by_channel, cs); - return res; - } - - inline void increase_error_count(const char* channel) - { - auto ch_container = get_channels_errors_stat_container(); - std::string ch_name = channel ? channel : ""; - uint64_t& r = (*ch_container)[ch_name]; - r++; - } - - inline std::string get_daytime_string2() - { - boost::posix_time::ptime p = boost::posix_time::microsec_clock::local_time(); - return misc_utils::get_time_str_v3(p); - } - inline std::string get_day_time_string() - { - return get_daytime_string2(); - //time_t tm = 0; - //time(&tm); - //return misc_utils::get_time_str(tm); - } - - inline std::string get_time_string() - { - return get_daytime_string2(); - - } -#ifdef _MSC_VER - inline std::string get_time_string_adv(SYSTEMTIME* pst = NULL) - { - SYSTEMTIME st = {0}; - if(!pst) - { - pst = &st; - GetSystemTime(&st); - } - std::stringstream str_str; - str_str.fill('0'); - str_str << std::setw(2) << pst->wHour << "_" - << std::setw(2) << pst->wMinute << "_" - << std::setw(2) << pst->wSecond << "_" - << std::setw(3) << pst->wMilliseconds; - return str_str.str(); - } -#endif - - - - - - class logger - { - public: - friend class log_singletone; - - logger() - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - init(); - FAST_CRITICAL_REGION_END(); - } - ~logger() - { - } - - bool set_max_logfile_size(uint64_t max_size) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.set_max_logfile_size(max_size); - FAST_CRITICAL_REGION_END(); - return true; - } - - bool set_log_rotate_cmd(const std::string& cmd) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.set_log_rotate_cmd(cmd); - FAST_CRITICAL_REGION_END(); - return true; - } - - std::string copy_logs_to_buffer() - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.copy_logs_to_buffer(); - FAST_CRITICAL_REGION_END(); - } - - - bool truncate_log_files() - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.truncate_log_files(); - FAST_CRITICAL_REGION_END(); - } - - bool take_away_journal(std::list& journal) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - m_journal.swap(journal); - FAST_CRITICAL_REGION_END(); - return true; - } - - bool get_journal_items(std::list& journal, size_t count) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - size_t i = 0; - for (auto it = m_journal.rbegin(); it != m_journal.rend() && i!= count; it++, i++) - { - journal.push_front(*it); - } - FAST_CRITICAL_REGION_END(); - return true; - } - bool do_log_message(const std::string& rlog_mes, int log_level, int color, bool add_to_journal = false, const char* plog_name = NULL) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - m_log_target.do_log_message(rlog_mes, log_level, color, plog_name); - if (add_to_journal) - { - m_journal.push_back(rlog_mes); - if (m_journal.size() > m_journal_max_elements) - m_journal.pop_front(); - } - - return true; - FAST_CRITICAL_REGION_END(); - } - - bool add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder , int log_level_limit = LOG_LEVEL_4) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.add_logger( type, pdefault_file_name, pdefault_log_folder, log_level_limit); - FAST_CRITICAL_REGION_END(); - } - bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.add_logger(pstream, log_level_limit); - FAST_CRITICAL_REGION_END(); - } - - bool remove_logger(int type) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - return m_log_target.remove_logger(type); - FAST_CRITICAL_REGION_END(); - } - - - bool set_thread_prefix(const std::string& prefix) - { - FAST_CRITICAL_REGION_BEGIN(m_critical_sec); - m_thr_prefix_strings[misc_utils::get_thread_string_id()] = prefix; - FAST_CRITICAL_REGION_END(); - return true; - } - std::string get_thread_prefix() - { - FAST_CRITICAL_REGION_LOCAL(m_critical_sec); - return m_thr_prefix_strings[misc_utils::get_thread_string_id()]; - } - - std::string get_default_log_file() - { - return m_default_log_file; - } - - std::string get_default_log_folder() - { - return m_default_log_folder; - } - - void set_default_log_folder(const std::string& folder) - { - m_default_log_folder = folder; - } - - std::string get_actual_log_file_path() - { - return m_log_target.get_log_file_path(); - } - - protected: - private: - bool init() - { - // - m_journal_max_elements = LOG_JOURNAL_MAX_ELEMENTS; - m_process_name = string_tools::get_current_module_name(); - - init_log_path_by_default(); - - //this need ti initialize static critical section in get_channels_errors_stat_container() - get_channels_errors_stat_container(); - - //init default set of loggers - init_default_loggers(); - - std::stringstream ss; - ss << get_time_string() << " Init logging. Level=" << get_set_log_detalisation_level() - << "Default log path=" << m_default_log_folder << std::endl; - this->do_log_message(ss.str(), console_color_white, LOG_LEVEL_0); - return true; - } - bool init_default_loggers() - { - //TODO: - return true; - } - - bool init_log_path_by_default() - { - m_default_log_file = m_process_name; - std::string::size_type a = m_default_log_file.rfind('.'); - if (a != std::string::npos) - m_default_log_file.erase(a, m_default_log_file.size()); - - //load process name - m_default_log_folder = string_tools::get_current_module_folder(); - - m_default_log_file += ".log"; - - return true; - } - - log_stream_splitter m_log_target; - - std::string m_default_log_folder; - std::string m_default_log_file; - std::string m_process_name; - std::map m_thr_prefix_strings; - std::list m_journal; - size_t m_journal_max_elements; - critical_section m_critical_sec; - }; - /************************************************************************/ - /* */ - /************************************************************************/ - class log_singletone - { - public: - friend class static_helpers::initializer; - friend class logger; - static int get_log_detalisation_level() - { - get_or_create_instance();//to initialize logger, if it not initialized - return get_set_log_detalisation_level(); - } - - //get_enabled_channels not thread-safe, at the moment leave it like this because it's configured in main, before other threads started - static std::set& get_enabled_channels() - { - static epee::static_helpers::wrapper> genabled_channels; - return genabled_channels; - } - - static bool channel_enabled(const std::string& ch_name) - { - std::set& genabled_channels = get_enabled_channels(); - return genabled_channels.find(ch_name) != genabled_channels.end(); - } - - static void enable_channels(const std::string& channels_set) - { - std::set& genabled_channels = get_enabled_channels(); - std::list list_of_channels; - boost::split(list_of_channels, channels_set, boost::is_any_of(",;: "), boost::token_compress_on); - std::cout << "log channels: "; - for (const auto& ch : list_of_channels) - { - genabled_channels.insert(ch); - std::cout << ch << " "; - } - std::cout << " enabled" << std::endl; - } - - static void enable_channel(const std::string& ch_name) - { - std::set& genabled_channels = get_enabled_channels(); - //lazy synchronization: just replace with modified copy of whole set - std::set enabled_channels_local = genabled_channels; - enabled_channels_local.insert(ch_name); - genabled_channels.swap(enabled_channels_local); -#ifndef ANDROID_BUILD - std::cout << "log channel '" << ch_name << "' enabled" << std::endl; -#endif - } - - static void disable_channels(const std::string& channels_set) - { - std::set& genabled_channels = get_enabled_channels(); - std::list list_of_channels; - boost::split(list_of_channels, channels_set, boost::is_any_of(",;: "), boost::token_compress_on); - std::cout << "log channels: "; - for (const auto& ch : list_of_channels) - { - genabled_channels.erase(ch); - std::cout << ch << " "; - } - std::cout << " disabled" << std::endl; - } - - static void disable_channel(const std::string& ch_name) - { - std::set& genabled_channels = get_enabled_channels(); - //lazy synchronization: just replace with modified copy of whole set - std::set enabled_channels_local = genabled_channels; - auto it = enabled_channels_local.find(ch_name); - if (it != enabled_channels_local.end()) - enabled_channels_local.erase(it); - genabled_channels.swap(enabled_channels_local); - std::cout << "log channel '" << ch_name << "' disabled" << std::endl; - } - - static bool channel_enabled(const char* pch_name) - { - //null channel, enabled by default - if (!pch_name) - return true; - return channel_enabled(std::string(pch_name)); - } - - - static bool is_filter_error(int error_code) - { - return false; - } - - - static bool do_log_message(const std::string& rlog_mes, int log_level, int color, bool keep_in_journal, const char* plog_name = NULL) - { - logger* plogger = get_or_create_instance(); - bool res = false; - if(plogger) - res = plogger->do_log_message(rlog_mes, log_level, color, keep_in_journal, plog_name); - else - { //globally uninitialized, create new logger for each call of do_log_message() and then delete it - plogger = new logger(); - //TODO: some extra initialization - res = plogger->do_log_message(rlog_mes, log_level, color, keep_in_journal, plog_name); - delete plogger; - plogger = NULL; - } - return res; - } - - static bool take_away_journal(std::list& journal) - { - logger* plogger = get_or_create_instance(); - bool res = false; - if(plogger) - res = plogger->take_away_journal(journal); - - return res; - } - - static bool get_journal_items(std::list& journal, size_t count) - { - logger* plogger = get_or_create_instance(); - bool res = false; - if (plogger) - res = plogger->get_journal_items(journal, count); - - return res; - } - - static bool set_max_logfile_size(uint64_t file_size) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_max_logfile_size(file_size); - } - - - static bool set_log_rotate_cmd(const std::string& cmd) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_log_rotate_cmd(cmd); - } - - - static std::string copy_logs_to_buffer() - { - logger* plogger = get_or_create_instance(); - if (!plogger) return ""; - return plogger->copy_logs_to_buffer(); - } - - - static bool truncate_log_files() - { - logger* plogger = get_or_create_instance(); - if (!plogger) return false; - return plogger->truncate_log_files(); - } - - - - static bool add_logger( int type, const char* pdefault_file_name, const char* pdefault_log_folder, int log_level_limit = LOG_LEVEL_4) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->add_logger(type, pdefault_file_name, pdefault_log_folder, log_level_limit); - } - - static std::string get_default_log_file() - { - logger* plogger = get_or_create_instance(); - if(plogger) - return plogger->get_default_log_file(); - - return ""; - } - - static std::string get_actual_log_file_path() - { - logger* plogger = get_or_create_instance(); - if (plogger) - return plogger->get_actual_log_file_path(); - return ""; - } - - static std::string get_default_log_folder() - { - logger* plogger = get_or_create_instance(); - if(plogger) - return plogger->get_default_log_folder(); - - return ""; - } - - static void set_default_log_folder(const std::string& folder) - { - logger* plogger = get_or_create_instance(); - if (plogger) - plogger->set_default_log_folder(folder); - - } - - static bool add_logger( ibase_log_stream* pstream, int log_level_limit = LOG_LEVEL_4 ) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->add_logger(pstream, log_level_limit); - } - - - static bool remove_logger( int type ) - { - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->remove_logger(type); - } -PUSH_GCC_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - static int get_set_log_detalisation_level(bool is_need_set = false, int log_level_to_set = LOG_LEVEL_1) - { - - static int log_detalisation_level = LOG_LEVEL_1; - if (is_need_set) - { - log_detalisation_level = log_level_to_set; - } - return log_detalisation_level; - } -POP_GCC_WARNINGS - static int get_set_time_level(bool is_need_set = false, int time_log_level = LOG_LEVEL_0) - { - static int val_time_log_level = LOG_LEVEL_0; - if(is_need_set) - val_time_log_level = time_log_level; - - return val_time_log_level; - } - - static int get_set_process_level(bool is_need_set = false, int process_log_level = LOG_LEVEL_0) - { - static int val_process_log_level = LOG_LEVEL_0; - if(is_need_set) - val_process_log_level = process_log_level; - - return val_process_log_level; - } - - /*static int get_set_tid_level(bool is_need_set = false, int tid_log_level = LOG_LEVEL_0) - { - static int val_tid_log_level = LOG_LEVEL_0; - if(is_need_set) - val_tid_log_level = tid_log_level; - - return val_tid_log_level; - }*/ - - static bool get_set_need_thread_id(bool is_need_set = false, bool is_need_val = false) - { - static bool is_need = false; - if(is_need_set) - is_need = is_need_val; - - return is_need; - } - - static bool get_set_need_proc_name(bool is_need_set = false, bool is_need_val = false) - { - static bool is_need = true; - if(is_need_set) - is_need = is_need_val; - - return is_need; - } - - -#ifdef _MSC_VER - - - static void SetThreadName( DWORD dwThreadID, const char* threadName) - { -#define MS_VC_EXCEPTION 0x406D1388 - -#pragma pack(push,8) - typedef struct tagTHREADNAME_INFO - { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. - } THREADNAME_INFO; -#pragma pack(pop) - - - - Sleep(10); - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = (char*)threadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - __try - { - RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - } -#endif - - static bool set_thread_log_prefix(const std::string& prefix) - { -#ifdef _MSC_VER - SetThreadName(-1, prefix.c_str()); -#endif - - logger* plogger = get_or_create_instance(); - if(!plogger) return false; - return plogger->set_thread_prefix(prefix); - } - - static std::string get_thread_log_prefix() - { - logger* plogger = get_or_create_instance(); - if (!plogger) return ""; - return plogger->get_thread_prefix(); - } - - static std::string get_prefix_entry() - { - std::stringstream str_prefix; - //write time entry - if ( get_set_time_level() <= get_set_log_detalisation_level() ) - str_prefix << get_day_time_string() << " "; - - //write process info - logger* plogger = get_or_create_instance(); - //bool res = false; - if(!plogger) - { //globally uninitialized, create new logger for each call of get_prefix_entry() and then delete it - plogger = new logger(); - } - - //if ( get_set_need_proc_name() && get_set_process_level() <= get_set_log_detalisation_level() ) - // str_prefix << "[" << plogger->m_process_name << " (id=" << GetCurrentProcessId() << ")] "; -//#ifdef _MSC_VER_EX - if ( get_set_need_thread_id() /*&& get_set_tid_level() <= get_set_log_detalisation_level()*/ ) - str_prefix << "[tid:" << misc_utils::get_thread_string_id() << "] "; -//#endif - - if(plogger->m_thr_prefix_strings.size()) - { - FAST_CRITICAL_REGION_LOCAL(plogger->m_critical_sec); - std::string thr_str = misc_utils::get_thread_string_id(); - std::map::iterator it = plogger->m_thr_prefix_strings.find(thr_str); - if(it!=plogger->m_thr_prefix_strings.end()) - { - str_prefix << it->second; - } - } - - - if(get_set_is_uninitialized()) - delete plogger; - - return str_prefix.str(); - } - - private: - log_singletone(){}//restric to create an instance - //static initializer m_log_initializer;//must be in one .cpp file (for example main.cpp) via DEFINE_LOGGING macro - - static bool init() - { - return true;/*do nothing here*/ - } - static bool un_init() - { - //delete object - logger* plogger = get_set_instance_internal(); - if(plogger) delete plogger; - //set uninitialized - get_set_is_uninitialized(true, true); - get_set_instance_internal(true, NULL); - return true; - } - - static logger* get_or_create_instance() - { - logger* plogger = get_set_instance_internal(); - if(!plogger) - if(!get_set_is_uninitialized()) - get_set_instance_internal(true, plogger = new logger); - - return plogger; - } - - static logger* get_set_instance_internal(bool is_need_set = false, logger* pnew_logger_val = NULL) - { - static logger* val_plogger = NULL; - - if(is_need_set) - val_plogger = pnew_logger_val; - - return val_plogger; - } - - static bool get_set_is_uninitialized(bool is_need_set = false, bool is_uninitialized = false) - { - static bool val_is_uninitialized = false; - - if(is_need_set) - val_is_uninitialized = is_uninitialized; - - return val_is_uninitialized; - } - //static int get_set_error_filter(bool is_need_set = false) - }; - - const static static_helpers::initializer log_initializer; - /************************************************************************/ - /* */ -// /************************************************************************/ -// class log_array_value -// { -// int num; -// log_message& m_ref_log_mes; -// -// public: -// -// log_array_value( log_message& log_mes ) : num(0), m_ref_log_mes(log_mes) {} -// -// void operator ( )( ibase_log_value *val ) { -// m_ref_log_mes << "\n[" << num++ << "] "/* << val*/; } -// -// -// template -// void operator ()(T &value ) -// { -// m_ref_log_mes << "\n[" << num++ << "] " << value; -// } -// }; - - class log_frame - { - std::string m_name; - int m_level; - const char* m_plog_name; - public: - - log_frame(const std::string& name, int dlevel = LOG_LEVEL_2 , const char* plog_name = NULL) - { -#ifdef _MSC_VER - int lasterr=::GetLastError(); -#endif - m_plog_name = plog_name; - if ( dlevel <= log_singletone::get_log_detalisation_level() ) - { - m_name = name; - std::stringstream ss; - ss << log_space::log_singletone::get_prefix_entry() << "-->>" << m_name << std::endl; - log_singletone::do_log_message(ss.str(), dlevel, console_color_default, false, m_plog_name); - } - m_level = dlevel; -#ifdef _MSC_VER - ::SetLastError(lasterr); -#endif - } - ~log_frame() - { - NESTED_TRY_ENTRY(); -#ifdef _MSC_VER - int lasterr=::GetLastError(); -#endif - if (m_level <= log_singletone::get_log_detalisation_level() ) - { - std::stringstream ss; - ss << log_space::log_singletone::get_prefix_entry() << "<<--" << m_name << std::endl; - log_singletone::do_log_message(ss.str(), m_level, console_color_default, false,m_plog_name); - } -#ifdef _MSC_VER - ::SetLastError(lasterr); -#endif - NESTED_CATCH_ENTRY(__func__); - } - }; - - inline int get_set_time_level(bool is_need_set, int time_log_level) - { - return log_singletone::get_set_time_level(is_need_set, time_log_level); - } - inline int get_set_log_detalisation_level(bool is_need_set, int log_level_to_set) - { - return log_singletone::get_set_log_detalisation_level(is_need_set, log_level_to_set); - } - inline std::string get_prefix_entry() - { - return log_singletone::get_prefix_entry(); - } - inline bool get_set_need_thread_id(bool is_need_set, bool is_need_val) - { - return log_singletone::get_set_need_thread_id(is_need_set, is_need_val); - } - inline bool get_set_need_proc_name(bool is_need_set, bool is_need_val ) - { - return log_singletone::get_set_need_proc_name(is_need_set, is_need_val); - } - - inline std::string get_win32_err_descr(int err_no) - { -#ifdef _MSC_VER - LPVOID lpMsgBuf; - - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - err_no, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (char*) &lpMsgBuf, - 0, NULL ); - - std::string fix_sys_message = "(null)"; - if(lpMsgBuf) fix_sys_message = (char*)lpMsgBuf; - std::string::size_type a; - if ( (a = fix_sys_message.rfind( '\n' )) != std::string::npos ) - fix_sys_message.erase(a); - if ( (a = fix_sys_message.rfind( '\r' )) != std::string::npos ) - fix_sys_message.erase(a); - - LocalFree(lpMsgBuf); - return fix_sys_message; -#else - return "Not implemented yet"; -#endif - } - - inline bool getwin32_err_text(std::stringstream& ref_message, int error_no) - { - ref_message << "win32 error:" << get_win32_err_descr(error_no); - return true; - } -} - -} // namespace epee - -POP_VS_WARNINGS - -#endif //_MISC_LOG_EX_H_ diff --git a/src/contrib/epee/include/misc_os_dependent.h b/src/contrib/epee/include/misc_os_dependent.h deleted file mode 100644 index c06e5d9..0000000 --- a/src/contrib/epee/include/misc_os_dependent.h +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#ifdef WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - - //#ifdef _WIN32_WINNT - // #undef _WIN32_WINNT - // #define _WIN32_WINNT 0x0600 - //#endif - - -#include -#endif - -#ifdef __MACH__ -#include -#include -#endif - -#pragma once -namespace epee -{ -namespace misc_utils -{ - - inline uint64_t get_tick_count() - { -#if defined(_MSC_VER) - typedef ULONGLONG(*GetTickCount64Ptr)(); - static GetTickCount64Ptr get_tick_count64 = (GetTickCount64Ptr)(GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetTickCount64")); - if (get_tick_count64) - return (*get_tick_count64)(); - return GetTickCount(); -#elif defined(__MACH__) - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - return (mts.tv_sec * 1000) + (mts.tv_nsec/1000000); -#else - struct timespec ts; - if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - return 0; - } - return (ts.tv_sec * 1000) + (ts.tv_nsec/1000000); -#endif - } - - - inline int call_sys_cmd(const std::string& cmd) - { - std::cout << "# " << cmd << std::endl; - - FILE * fp ; - //char tstCommand[] ="ls *"; - char path[1000] = {0}; -#if !defined(__GNUC__) - fp = _popen(cmd.c_str(), "r"); -#else - fp = popen(cmd.c_str(), "r"); -#endif - while ( fgets( path, 1000, fp ) != NULL ) - std::cout << path; - -#if !defined(__GNUC__) - _pclose(fp); -#else - pclose(fp); -#endif - return 0; - - } - - - inline std::string get_thread_string_id() - { -#if defined(_MSC_VER) - return boost::lexical_cast(GetCurrentThreadId()); -#elif defined(__GNUC__) - return boost::lexical_cast(pthread_self()); -#endif - } - - -#if defined(__GNUC__) && !defined(__ANDROID__) -#include -#include -#endif - inline std::string print_trace_default() - { - std::stringstream ss; -#if defined(__GNUC__) && !defined(__ANDROID__) - ss << std::endl << "STACK" << std::endl; - const size_t max_depth = 100; - size_t stack_depth; - void *stack_addrs[max_depth]; - char **stack_strings; - - stack_depth = backtrace(stack_addrs, max_depth); - stack_strings = backtrace_symbols(stack_addrs, stack_depth); - - for (size_t i = 1; i < stack_depth; i++) - { - ss << boost::core::demangle(stack_strings[i]) << std::endl; - } - free(stack_strings); // malloc()ed by backtrace_symbols -#endif - return ss.str(); - } - - typedef std::string (stack_retrieving_function_t)(); - - // - // To get stack trace call it with the defaults. - // - inline std::string get_callstack(stack_retrieving_function_t* p_stack_retrieving_function_to_be_added = nullptr, bool remove_func = false) - { - static stack_retrieving_function_t* p_srf = nullptr; - - if (remove_func) - { - p_srf = nullptr; - return ""; - } - - if (p_stack_retrieving_function_to_be_added != nullptr) - { - p_srf = p_stack_retrieving_function_to_be_added; - return ""; - } - - if (p_srf != nullptr) - return p_srf(); - - return print_trace_default(); - } - -} -} diff --git a/src/contrib/epee/include/net/abstract_tcp_server2.h b/src/contrib/epee/include/net/abstract_tcp_server2.h deleted file mode 100644 index be9fc2a..0000000 --- a/src/contrib/epee/include/net/abstract_tcp_server2.h +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _ABSTRACT_TCP_SERVER2_H_ -#define _ABSTRACT_TCP_SERVER2_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "net_utils_base.h" -#include "syncobj.h" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "net_server" - -#define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 1000 - -namespace epee { -namespace net_utils { - -struct i_connection_filter { - virtual bool is_remote_ip_allowed(uint32_t adress) = 0; - - protected: - virtual ~i_connection_filter() - { - } -}; - -/************************************************************************/ -/* */ -/************************************************************************/ -/// Represents a single connection from a client. -template -class connection - : public boost::enable_shared_from_this>, - private boost::noncopyable, - public i_service_endpoint { - public: - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter*& pfilter); - - virtual ~connection(); - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket(); - - /// Start the first asynchronous operation for the connection. - bool start(bool is_income, bool is_multithreaded); - - void get_context(t_connection_context& context_) - { - context_ = context; - } - - void call_back_starter(); - bool is_shutdown() - { - return m_was_shutdown; - } - bool cancel(); - - private: - //----------------- i_service_endpoint --------------------- - virtual bool do_send(const void* ptr, size_t cb); - virtual bool close(); - virtual bool call_run_once_service_io(); - virtual bool request_callback(); - virtual boost::asio::io_service& get_io_service(); - virtual bool add_ref(); - virtual bool release(); - //------------------------------------------------------ - boost::shared_ptr> safe_shared_from_this(); - bool shutdown(); - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred); - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e, size_t cb); - - /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// Buffer for incoming data. - boost::array buffer_; - - boost::asio::io_service& m_rio_service; - t_connection_context context; - volatile uint32_t m_want_close_connection; - std::atomic m_was_shutdown; - critical_section m_send_que_lock; - std::list m_send_que; - volatile uint32_t& m_ref_sockets_count; - i_connection_filter*& m_pfilter; - volatile bool m_is_multithreaded; - std::list>> m_self_refs; // add_ref/release support - critical_section m_self_refs_lock; - - t_protocol_handler m_protocol_handler; - //this should be the last line with m_protocol_handler, because it could be wait on destructor, while other activities possible on other threads - //DON'T ADD ANYTHING HERE!!! -}; - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class boosted_tcp_server - : private boost::noncopyable { - public: - typedef boost::shared_ptr> connection_ptr; - typedef typename t_protocol_handler::connection_context t_connection_context; - /// Construct the server to listen on the specified TCP address and port, and - /// serve up files from the given directory. - boosted_tcp_server(); - explicit boosted_tcp_server(boost::asio::io_service& external_io_service); - ~boosted_tcp_server(); - - bool init_server(uint32_t port, const std::string address = "0.0.0.0"); - bool init_server(const std::string port, const std::string& address = "0.0.0.0"); - - /// Run the server's io_service loop. - bool run_server(size_t threads_count, bool wait = true); - - /// wait for service workers stop - bool timed_wait_server_stop(uint64_t wait_mseconds); - - /// Stop the server. - void send_stop_signal(); - - bool is_stop_signal_sent(); - - void set_threads_prefix(const std::string& prefix_name); - - bool deinit_server() - { - return true; - } - - size_t get_threads_count() - { - return m_threads_count; - } - - void set_connection_filter(i_connection_filter* pfilter); - - bool connect(const std::string& adr, const std::string& port, uint32_t conn_timeot, t_connection_context& cn, const std::string& bind_ip = "0.0.0.0"); - template - bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback& cb, const std::string& bind_ip = "0.0.0.0"); - - typename t_protocol_handler::config_type& get_config_object() - { - return m_config; - } - - int get_binded_port() - { - return m_port; - } - - boost::asio::io_service& get_io_service() - { - return io_service_; - } - - struct idle_callback_conext_base { - virtual ~idle_callback_conext_base() - { - } - - virtual bool call_handler() - { - return true; - } - - idle_callback_conext_base(boost::asio::io_service& io_serice): m_timer(io_serice), - m_period(0) - { - } - boost::asio::deadline_timer m_timer; - uint64_t m_period; - }; - - template - struct idle_callback_conext : public idle_callback_conext_base { - idle_callback_conext(boost::asio::io_service& io_serice, t_handler& h, uint64_t period) - : idle_callback_conext_base(io_serice), - m_handler(h) - { - this->m_period = period; - } - - t_handler m_handler; - virtual bool call_handler() - { - return m_handler(); - } - }; - - template - bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms) - { - boost::shared_ptr ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); - //needed call handler here ?... - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - bool global_timer_handler(/*const boost::system::error_code& err, */ boost::shared_ptr ptr) - { - //if handler return false - he don't want to be called anymore - try { - if(!ptr->call_handler()) - return true; - } - catch(std::exception& e) - { - LOG_ERROR("exeption caught in boosted_tcp_server::global_timer_handler: " << e.what() << ENDL << "won't be called anymore"); - return true; - } - catch(...) - { - LOG_ERROR("unknown exeption caught in boosted_tcp_server::global_timer_handler, it won't be called anymore"); - return true; - } - - ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); - return true; - } - - template - bool async_call(t_handler t_callback) - { - io_service_.post(t_callback); - return true; - } - - protected: - typename t_protocol_handler::config_type m_config; - - private: - /// Run the server's io_service loop. - bool worker_thread(); - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e); - - bool is_thread_worker(); - - /// The io_service used to perform asynchronous operations. - std::unique_ptr m_io_service_local_instance; - boost::asio::io_service& io_service_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - //std::mutex connections_mutex; - //std::deque connections_; - std::atomic m_stop_signal_sent; - uint32_t m_port; - volatile uint32_t m_sockets_count; - std::string m_address; - std::string m_thread_name_prefix; - size_t m_threads_count; - i_connection_filter* m_pfilter; - std::vector> m_threads; - boost::thread::id m_main_thread_id; - critical_section m_threads_lock; - volatile uint32_t m_thread_index; -}; -} // namespace net_utils -} // namespace epee - -#include "abstract_tcp_server2.inl" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - -#endif diff --git a/src/contrib/epee/include/net/abstract_tcp_server2.inl b/src/contrib/epee/include/net/abstract_tcp_server2.inl deleted file mode 100644 index 2bb45f6..0000000 --- a/src/contrib/epee/include/net/abstract_tcp_server2.inl +++ /dev/null @@ -1,805 +0,0 @@ -// Copyright (c) 2019, anonimal -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include "net_utils_base.h" -#include -#include -#include -#include -#include -#include -#include -#include "misc_language.h" -#include "warnings.h" - -PUSH_VS_WARNINGS -namespace epee { -namespace net_utils { -/************************************************************************/ -/* */ -/************************************************************************/ -DISABLE_VS_WARNINGS(4355) - -template -connection::connection(boost::asio::io_service& io_service, - typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter*& pfilter) - : m_rio_service(io_service), - strand_(io_service), - socket_(io_service), - m_protocol_handler(this, config, context), - m_want_close_connection(0), - m_was_shutdown(0), - m_ref_sockets_count(sock_count), - m_pfilter(pfilter), - m_is_multithreaded(false) -{ - boost::interprocess::ipcdetail::atomic_inc32(&m_ref_sockets_count); -} -DISABLE_VS_WARNINGS(4355) -//--------------------------------------------------------------------------------- -template -connection::~connection() -{ - NESTED_TRY_ENTRY(); - - if(!m_was_shutdown) { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Socket destroyed without shutdown."); - shutdown(); - } - - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Socket destroyed"); - boost::interprocess::ipcdetail::atomic_dec32(&m_ref_sockets_count); - VALIDATE_MUTEX_IS_FREE(m_send_que_lock); - VALIDATE_MUTEX_IS_FREE(m_self_refs_lock); - - NESTED_CATCH_ENTRY(__func__); -} -//--------------------------------------------------------------------------------- -template -boost::asio::ip::tcp::socket& connection::socket() -{ - return socket_; -} -//--------------------------------------------------------------------------------- -template -boost::shared_ptr> connection::safe_shared_from_this() -{ - try { - return connection::shared_from_this(); - } - catch(const boost::bad_weak_ptr&) { - // It happens when the connection is being deleted - return boost::shared_ptr>(); - } -} -//--------------------------------------------------------------------------------- -template -bool connection::start(bool is_income, bool is_multithreaded) -{ - TRY_ENTRY(); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) { - LOG_PRINT_RED("Failed to start conntection, failed to call safe_shared_from_this", LOG_LEVEL_2); - return false; - } - - m_is_multithreaded = is_multithreaded; - - boost::system::error_code ec; - auto remote_ep = socket_.remote_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!m_was_shutdown, false, "was shutdown on start connection"); - - CHECK_AND_NO_ASSERT_MES_LEVEL(!ec, false, "Failed to get remote endpoint(" << (is_income ? "INT" : "OUT") << "): " << ec.message() << ':' << ec.value(), LOG_LEVEL_2); - - auto local_ep = socket_.local_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value()); - - context = boost::value_initialized(); - long ip_ = boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong()); - - context.set_details(boost::uuids::random_generator()(), ip_, remote_ep.port(), is_income); - context.m_last_send = context.m_last_recv = time(NULL); - - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] new connection, remote end_point: " << print_connection_context_short(context) << " local end_point: " << local_ep.address().to_string() << ':' << local_ep.port() << ", total sockets objects " << m_ref_sockets_count); - - if(is_income && m_pfilter && !m_pfilter->is_remote_ip_allowed(context.m_remote_ip)) { - LOG_PRINT_L0("[sock " << socket_.native_handle() << "] ip denied " << string_tools::get_ip_string_from_int32(context.m_remote_ip) << ", shutdowning connection"); - close(); - return false; - } - - m_protocol_handler.after_init_connection(); - - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, self, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - - return true; - - CATCH_ENTRY_L0("connection::start()", false); -} -//--------------------------------------------------------------------------------- -template -bool connection::request_callback() -{ - TRY_ENTRY(); - LOG_PRINT_L2("[" << print_connection_context_short(context) << "] request_callback"); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - - strand_.post(boost::bind(&connection::call_back_starter, self)); - CATCH_ENTRY_L0("connection::request_callback()", false); - return true; -} -//--------------------------------------------------------------------------------- -template -boost::asio::io_service& connection::get_io_service() -{ - return m_rio_service; -} -//--------------------------------------------------------------------------------- -template -bool connection::add_ref() -{ - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] add_ref"); - CRITICAL_REGION_LOCAL(m_self_refs_lock); - - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - if(m_was_shutdown) - return false; - m_self_refs.push_back(self); - return true; - CATCH_ENTRY_L0("connection::add_ref()", false); -} -//--------------------------------------------------------------------------------- -template -bool connection::release() -{ - TRY_ENTRY(); - boost::shared_ptr> back_connection_copy; - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] release"); - CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection::release() call"); - //erasing from container without additional copy can cause start deleting object, including m_self_refs - back_connection_copy = m_self_refs.back(); - m_self_refs.pop_back(); - CRITICAL_REGION_END(); - return true; - CATCH_ENTRY_L0("connection::release()", false); -} -//--------------------------------------------------------------------------------- -template -void connection::call_back_starter() -{ - TRY_ENTRY(); - LOG_PRINT_L2("[" << print_connection_context_short(context) << "] fired_callback"); - m_protocol_handler.handle_qued_callback(); - CATCH_ENTRY_L0("connection::call_back_starter()", void()); -} -//--------------------------------------------------------------------------------- -template -void connection::handle_read(const boost::system::error_code& e, - std::size_t bytes_transferred) -{ - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Assync read calledback."); - - if(!e) { - LOG_PRINT("[sock " << socket_.native_handle() << "] RECV " << bytes_transferred, LOG_LEVEL_4); - context.m_last_recv = time(NULL); - context.m_recv_cnt += bytes_transferred; - bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred); - if(!recv_res) { - LOG_PRINT("[sock " << socket_.native_handle() << "] protocol_want_close", LOG_LEVEL_4); - - //some error in protocol, protocol handler ask to close connection - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(!m_send_que.size()) - do_shutdown = true; - CRITICAL_REGION_END(); - if(do_shutdown) - shutdown(); - } - else { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, connection::shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "]Assync read requested."); - } - } - else { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Some not success at read: " << e.message() << ':' << e.value()); - if(e.value() != 2) { - LOG_PRINT_L3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value()); - shutdown(); - } - } - // If an error occurs then no new asynchronous operations are started. This - // means that all shared_ptr references to the connection object will - // disappear and the object will be destroyed automatically after this - // handler returns. The connection class's destructor closes the socket. - CATCH_ENTRY_L0("connection::handle_read", void()); -} -//--------------------------------------------------------------------------------- -template -bool connection::call_run_once_service_io() -{ - TRY_ENTRY(); - if(!m_is_multithreaded) { - //single thread model, we can wait in blocked call - size_t cnt = m_rio_service.run_one(); - - if(!cnt) //service is going to quit - return false; - } - else { - //multi thread model, we can't(!) wait in blocked call - //so we make non blocking call and releasing CPU by calling sleep(0); - //if no handlers were called - //TODO: Maybe we need to have have critical section + event + callback to upper protocol to - //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = m_rio_service.poll_one(); - if(!cnt) - misc_utils::sleep_no_w(0); - } - - return true; - CATCH_ENTRY_L0("connection::call_run_once_service_io", false); -} -//--------------------------------------------------------------------------------- -template -bool connection::do_send(const void* ptr, size_t cb) -{ - TRY_ENTRY(); - // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted - auto self = safe_shared_from_this(); - if(!self) - return false; - if(m_was_shutdown) - return false; - - LOG_PRINT("[sock " << socket_.native_handle() << "] SEND " << cb, LOG_LEVEL_4); - context.m_last_send = time(NULL); - context.m_send_cnt += cb; - //some data should be wrote to stream - //request complete - - CRITICAL_REGION_LOCAL_VAR(m_send_que_lock, send_guard); - if(m_send_que.size() > ABSTRACT_SERVER_SEND_QUE_MAX_COUNT) { - send_guard.unlock(); //manual unlock - LOG_ERROR("send to [" << print_connection_context_short(context) << ", (" << (void*)this << ")] que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection"); - close(); - shutdown(); - return false; - } - - m_send_que.resize(m_send_que.size() + 1); - m_send_que.back().assign((const char*)ptr, cb); - - if(m_send_que.size() > 1) { - //active operation should be in progress, nothing to do, just wait last operation callback - } - else { - //no active operation - if(m_send_que.size() != 1) { - LOG_ERROR("Looks like no active operations, but send que size != 1!!"); - return false; - } - - boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), m_send_que.front().size()), - //strand_.wrap( - boost::bind(&connection::handle_write, self, boost::placeholders::_1, boost::placeholders::_2) - //) - ); - - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Assync send requested " << m_send_que.front().size()); - } - - return true; - - CATCH_ENTRY_L0("connection::do_send", false); -} -//--------------------------------------------------------------------------------- -template -bool connection::shutdown() -{ - if(m_was_shutdown) - return true; - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_was_shutdown = true; - m_protocol_handler.release_protocol(); - return true; -} -//--------------------------------------------------------------------------------- -template -bool connection::close() -{ - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Que Shutdown called."); - size_t send_que_size = 0; - CRITICAL_REGION_BEGIN(m_send_que_lock); - send_que_size = m_send_que.size(); - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); - if(!send_que_size) { - shutdown(); - } - - return true; - CATCH_ENTRY_L0("connection::close", false); -} -//--------------------------------------------------------------------------------- -template -bool connection::cancel() -{ - return close(); -} -//--------------------------------------------------------------------------------- -template -void connection::handle_write(const boost::system::error_code& e, size_t cb) -{ - TRY_ENTRY(); - LOG_PRINT_L4("[sock " << socket_.native_handle() << "] Assync send calledback " << cb); - - if(e) { - LOG_PRINT_L0("[sock " << socket_.native_handle() << "] Some problems at write: " << e.message() << ':' << e.value()); - shutdown(); - return; - } - - bool do_shutdown = false; - CRITICAL_REGION_BEGIN(m_send_que_lock); - if(m_send_que.empty()) { - LOG_ERROR("[sock " << socket_.native_handle() << "] m_send_que.size() == 0 at handle_write!"); - return; - } - - m_send_que.pop_front(); - if(m_send_que.empty()) { - if(boost::interprocess::ipcdetail::atomic_read32(&m_want_close_connection)) { - do_shutdown = true; - } - } - else { - //have more data to send - boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), m_send_que.front().size()), - //strand_.wrap( - boost::bind(&connection::handle_write, connection::shared_from_this(), boost::placeholders::_1, boost::placeholders::_2)); - //); - } - CRITICAL_REGION_END(); - - if(do_shutdown) { - shutdown(); - } - CATCH_ENTRY_L0("connection::handle_write", void()); -} -/************************************************************************/ -/* */ -/************************************************************************/ -template -boosted_tcp_server::boosted_tcp_server() - : m_io_service_local_instance(new boost::asio::io_service()), - io_service_(*m_io_service_local_instance.get()), - acceptor_(io_service_), - new_connection_(new connection(io_service_, m_config, m_sockets_count, m_pfilter)), - m_stop_signal_sent(false), m_port(0), m_sockets_count(0), m_threads_count(0), m_pfilter(NULL), m_thread_index(0) -{ - m_thread_name_prefix = "NET"; -} - -template -boosted_tcp_server::boosted_tcp_server(boost::asio::io_service& extarnal_io_service) - : io_service_(extarnal_io_service), - acceptor_(io_service_), - new_connection_(new connection(io_service_, m_config, m_sockets_count, m_pfilter)), - m_stop_signal_sent(false), m_port(0), m_sockets_count(0), m_threads_count(0), m_pfilter(NULL), m_thread_index(0) -{ - m_thread_name_prefix = "NET"; -} -//--------------------------------------------------------------------------------- -template -boosted_tcp_server::~boosted_tcp_server() -{ - NESTED_TRY_ENTRY(); - - this->send_stop_signal(); - timed_wait_server_stop(10000); - - NESTED_CATCH_ENTRY(__func__); -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::init_server(uint32_t port, const std::string address) -{ - TRY_ENTRY(); - m_stop_signal_sent = false; - m_port = port; - m_address = address; - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast(port)); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint(); - m_port = binded_endpoint.port(); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - return true; - CATCH_ENTRY_L0("boosted_tcp_server::init_server", false); -} -//----------------------------------------------------------------------------- -PUSH_GCC_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) -template -bool boosted_tcp_server::init_server(const std::string port, const std::string& address) -{ - uint32_t p = 0; - - if(port.size() && !string_tools::get_xtype_from_string(p, port)) { - LOG_ERROR("Failed to convert port no = " << port); - return false; - } - return this->init_server(p, address); -} -POP_GCC_WARNINGS -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::worker_thread() -{ - TRY_ENTRY(); - uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - std::string thread_name = std::string("[") + m_thread_name_prefix; - thread_name += boost::to_string(local_thr_index) + "]"; - log_space::log_singletone::set_thread_log_prefix(thread_name); - while(!m_stop_signal_sent) { - try { - io_service_.run(); - } - catch(const std::exception& ex) { - LOG_ERROR("Exception at server worker thread, what=" << ex.what()); - } - catch(...) { - LOG_ERROR("Exception at server worker thread, unknown execption"); - } - } - LOG_PRINT_L4("Worker thread finished"); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::worker_thread", false); -} -//--------------------------------------------------------------------------------- -template -void boosted_tcp_server::set_threads_prefix(const std::string& prefix_name) -{ - m_thread_name_prefix = prefix_name; -} -//--------------------------------------------------------------------------------- -template -void boosted_tcp_server::set_connection_filter(i_connection_filter* pfilter) -{ - m_pfilter = pfilter; -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::run_server(size_t threads_count, bool wait) -{ - TRY_ENTRY(); - m_threads_count = threads_count; - m_main_thread_id = boost::this_thread::get_id(); - log_space::log_singletone::set_thread_log_prefix("[SRV_MAIN]"); - while(!m_stop_signal_sent) { - // Create a pool of threads to run all of the io_services. - CRITICAL_REGION_BEGIN(m_threads_lock); - for(std::size_t i = 0; i < threads_count; ++i) { - boost::shared_ptr thread(new boost::thread( - boost::bind(&boosted_tcp_server::worker_thread, this))); - m_threads.push_back(thread); - } - CRITICAL_REGION_END(); - // Wait for all threads in the pool to exit. - if(wait) { - for(std::size_t i = 0; i < m_threads.size(); ++i) - m_threads[i]->join(); - m_threads.clear(); - } - else { - return true; - } - - if(wait && !m_stop_signal_sent) { - //some problems with the listening socket ?.. - LOG_PRINT_L0("Net service stopped without stop request, restarting..."); - if(!this->init_server(m_port, m_address)) { - LOG_PRINT_L0("Reiniting service failed, exit."); - return false; - } - else { - LOG_PRINT_L0("Reiniting OK."); - } - } - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::run_server", false); -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::is_thread_worker() -{ - TRY_ENTRY(); - CRITICAL_REGION_LOCAL(m_threads_lock); - BOOST_FOREACH(boost::shared_ptr& thp, m_threads) { - if(thp->get_id() == boost::this_thread::get_id()) - return true; - } - if(m_threads_count == 1 && boost::this_thread::get_id() == m_main_thread_id) - return true; - return false; - CATCH_ENTRY_L0("boosted_tcp_server::is_thread_worker", false); -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::timed_wait_server_stop(uint64_t wait_mseconds) -{ - TRY_ENTRY(); - boost::chrono::milliseconds ms(wait_mseconds); - for(std::size_t i = 0; i < m_threads.size(); ++i) { -#ifdef ANDROID_BUILD - if (m_threads[i]->joinable()) - { - m_threads[i]->join(); - } -#else - if (m_threads[i]->joinable() && !m_threads[i]->try_join_for(ms)) - { - LOG_PRINT_L0("Interrupting thread " << m_threads[i]->native_handle()); - m_threads[i]->interrupt(); - } -#endif - } - return true; - CATCH_ENTRY_L0("boosted_tcp_server::timed_wait_server_stop", false); -} -//--------------------------------------------------------------------------------- -template -void boosted_tcp_server::send_stop_signal() -{ - m_stop_signal_sent = true; - TRY_ENTRY(); - m_config.on_send_stop_signal(); - - io_service_.stop(); - CATCH_ENTRY_L0("boosted_tcp_server::send_stop_signal()", void()); -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::is_stop_signal_sent() -{ - return m_stop_signal_sent; -} -//--------------------------------------------------------------------------------- -template -void boosted_tcp_server::handle_accept(const boost::system::error_code& e) -{ - TRY_ENTRY(); - if(!e) { - connection_ptr conn(std::move(new_connection_)); - - new_connection_.reset(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&boosted_tcp_server::handle_accept, this, - boost::asio::placeholders::error)); - - conn->start(true, 1 < m_threads_count); - } - else { - LOG_ERROR("Some problems at accept: " << e.message() << ", connections_count = " << m_sockets_count); - } - CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); -} -//--------------------------------------------------------------------------------- -template -bool boosted_tcp_server::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip) -{ - TRY_ENTRY(); - - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) { - LOG_ERROR("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "") { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - /* - NOTICE: be careful to make sync connection from event handler: in case if all threads suddenly do sync connect, there will be no thread to dispatch events from io service. - */ - - boost::system::error_code ec = boost::asio::error::would_block; - - //have another free thread(s), work in wait mode, without event handling - struct local_async_context { - boost::system::error_code ec; - boost::mutex connect_mut; - boost::condition_variable cond; - }; - - boost::shared_ptr local_shared_context(new local_async_context()); - local_shared_context->ec = boost::asio::error::would_block; - boost::unique_lock lock(local_shared_context->connect_mut); - auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr shared_context) { - CRITICAL_SECTION_LOCK(shared_context->connect_mut); - shared_context->ec = ec_; - CRITICAL_SECTION_UNLOCK(shared_context->connect_mut); - shared_context->cond.notify_one(); - }; - - sock_.async_connect(remote_endpoint, boost::bind(connect_callback, _1, local_shared_context)); - while(local_shared_context->ec == boost::asio::error::would_block) { - bool r = false; - try { - r = local_shared_context->cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(conn_timeout)); - } - catch(...) { - //timeout - sock_.close(); - LOG_PRINT_L3("timed_wait throwed, " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")"); - return false; - } - if(local_shared_context->ec == boost::asio::error::would_block && !r) { - //timeout - sock_.close(); - LOG_PRINT_L3("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")"); - return false; - } - } - ec = local_shared_context->ec; - - if(ec || !sock_.is_open()) { - LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); - return false; - } - - LOG_PRINT_L3("Connected success to " << adr << ':' << port); - - bool r = new_connection_l->start(false, 1 < m_threads_count); - if(r) { - new_connection_l->get_context(conn_context); - //new_connection_l.reset(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - } - - return r; - - CATCH_ENTRY_L0("boosted_tcp_server::connect", false); -} -//--------------------------------------------------------------------------------- -template -template -bool boosted_tcp_server::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback& cb, const std::string& bind_ip) -{ - TRY_ENTRY(); - connection_ptr new_connection_l(new connection(io_service_, m_config, m_sockets_count, m_pfilter)); - boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket(); - - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) { - LOG_ERROR("Failed to resolve " << adr); - return false; - } - ////////////////////////////////////////////////////////////////////////// - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - sock_.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "") { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(adr.c_str()), 0); - sock_.bind(local_endpoint); - } - - boost::shared_ptr sh_deadline(new boost::asio::deadline_timer(io_service_)); - //start deadline - sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout)); - sh_deadline->async_wait([=](const boost::system::error_code& error) { - if(error != boost::asio::error::operation_aborted) { - LOG_PRINT_L3("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")"); - new_connection_l->socket().close(); - } - }); - //start async connect - sock_.async_connect(remote_endpoint, [=](const boost::system::error_code& ec_) { - t_connection_context conn_context = AUTO_VAL_INIT(conn_context); - boost::system::error_code ignored_ec; - boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket().local_endpoint(ignored_ec); - if(!ec_) { //success - if(!sh_deadline->cancel()) { - cb(conn_context, boost::asio::error::operation_aborted); //this mean that deadline timer already queued callback with cancel operation, rare situation - } - else if(new_connection_l->is_shutdown()) { - //if deadline timer started and finished callback right after async_connect callback is started and before deadline timer sh_deadline->cancel() is called - cb(conn_context, boost::asio::error::operation_aborted); - } - else { - LOG_PRINT_L3("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port << " from " << lep.address().to_string() << ':' << lep.port()); - bool r = new_connection_l->start(false, 1 < m_threads_count); - if(r) { - new_connection_l->get_context(conn_context); - cb(conn_context, ec_); - } - else { - cb(conn_context, boost::asio::error::fault); - } - } - } - else { - LOG_PRINT_L3("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port << " from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value()); - cb(conn_context, ec_); - } - }); - return true; - CATCH_ENTRY_L0("boosted_tcp_server::connect_async", false); -} -} // namespace net_utils -} // namespace epee -POP_VS_WARNINGS diff --git a/src/contrib/epee/include/net/http_base.h b/src/contrib/epee/include/net/http_base.h deleted file mode 100644 index cca1add..0000000 --- a/src/contrib/epee/include/net/http_base.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include - -#include "string_tools.h" -namespace epee -{ -namespace net_utils -{ - namespace http - { - - enum http_method{ - http_method_get, - http_method_post, - http_method_put, - http_method_head, - http_method_etc, - http_method_unknown - }; - - enum http_content_type - { - http_content_type_text_html, - http_content_type_image_gif, - http_content_type_other, - http_content_type_not_set - }; - - typedef std::list > fields_list; - - inline - std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields) - { - fields_list::const_iterator it = fields.begin(); - for(; it != fields.end(); it++) - if(!string_tools::compare_no_case(param_name, it->first)) - break; - - if(it==fields.end()) - return std::string(); - - return it->second; - } - - - inline - std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri) - { - std::string buff = "([\\?|&])"; - buff += param_name + "=([^&]*)"; - boost::regex match_param(buff.c_str(), boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(boost::regex_search(uri, result, match_param, boost::match_default) && result[0].matched) - { - return result[2]; - } - return std::string(); - } - - - - struct http_header_info - { - std::string m_connection; //"Connection:" - std::string m_referer; //"Referer:" - std::string m_content_length; //"Content-Length:" - std::string m_content_type; //"Content-Type:" - std::string m_transfer_encoding;//"Transfer-Encoding:" - std::string m_content_encoding; //"Content-Encoding:" - std::string m_host; //"Host:" - std::string m_cookie; //"Cookie:" - fields_list m_etc_fields; - - void clear() - { - m_connection.clear(); - m_referer.clear(); - m_content_length.clear(); - m_content_type.clear(); - m_transfer_encoding.clear(); - m_content_encoding.clear(); - m_host.clear(); - m_cookie.clear(); - m_etc_fields.clear(); - } - }; - - struct uri_content - { - std::string m_path; - std::string m_query; - std::string m_fragment; - std::list > m_query_params; - }; - - struct url_content - { - std::string schema; - std::string host; - std::string uri; - uint64_t port; - uri_content m_uri_content; - }; - - - struct http_request_info - { - http_request_info():m_http_method(http_method_unknown), - m_http_ver_hi(0), - m_http_ver_lo(0), - m_have_to_block(false), - m_full_request_buf_size(0) - {} - - http_method m_http_method; - std::string m_URI; - std::string m_http_method_str; - std::string m_full_request_str; - std::string m_replace_html; - std::string m_request_head; - int m_http_ver_hi; - int m_http_ver_lo; - bool m_have_to_block; - http_header_info m_header_info; - uri_content m_uri_content; - size_t m_full_request_buf_size; - std::string m_body; - - void clear() - { - this->~http_request_info(); - new(this) http_request_info(); - } - }; - - - struct http_response_info - { - int m_response_code; - std::string m_response_comment; - fields_list m_additional_fields; - std::string m_body; - std::string m_mime_tipe; - http_header_info m_header_info; - int m_http_ver_hi;// OUT paramter only - int m_http_ver_lo;// OUT paramter only - - void clear() - { - this->~http_response_info(); - new(this) http_response_info(); - } - }; - } -} -} diff --git a/src/contrib/epee/include/net/http_client.h b/src/contrib/epee/include/net/http_client.h deleted file mode 100644 index be81ba4..0000000 --- a/src/contrib/epee/include/net/http_client.h +++ /dev/null @@ -1,1043 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -//#include -#include -#include -#include - -#include "net_helper.h" -#include "http_client_base.h" - -//#ifdef HTTP_ENABLE_GZIP -#include "gzip_encoding.h" -//#endif - -#include "string_tools.h" -#include "reg_exp_definer.h" -#include "http_base.h" -#include "to_nonconst_iterator.h" -#include "net_parse_helpers.h" - -//#include "shlwapi.h" - -//#pragma comment(lib, "shlwapi.lib") - -extern epee::critical_section gregexp_lock; - - -namespace epee -{ -namespace net_utils -{ - -using namespace std; - - /*struct url - { - public: - void parse(const std::string& url_s) - { - const string prot_end("://"); - string::const_iterator prot_i = search(url_s.begin(), url_s.end(), - prot_end.begin(), prot_end.end()); - protocol_.reserve(distance(url_s.begin(), prot_i)); - transform(url_s.begin(), prot_i, - back_inserter(protocol_), - ptr_fun(tolower)); // protocol is icase - if( prot_i == url_s.end() ) - return; - advance(prot_i, prot_end.length()); - string::const_iterator path_i = find(prot_i, url_s.end(), '/'); - host_.reserve(distance(prot_i, path_i)); - transform(prot_i, path_i, - back_inserter(host_), - ptr_fun(tolower)); // host is icase - string::const_iterator query_i = find(path_i, url_s.end(), '?'); - path_.assign(path_i, query_i); - if( query_i != url_s.end() ) - ++query_i; - query_.assign(query_i, url_s.end()); - } - - std::string protocol_; - std::string host_; - std::string path_; - std::string query_; - };*/ - - - - - //--------------------------------------------------------------------------- - static inline const char* get_hex_vals() - { - static char hexVals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - return hexVals; - } - - static inline const char* get_unsave_chars() - { - //static char unsave_chars[] = "\"<>%\\^[]`+$,@:;/!#?=&"; - static char unsave_chars[] = "\"<>%\\^[]`+$,@:;!#&"; - return unsave_chars; - } - - static inline bool is_unsafe(unsigned char compare_char) - { - if(compare_char <= 32 || compare_char >= 123) - return true; - - const char* punsave = get_unsave_chars(); - - for(int ichar_pos = 0; 0!=punsave[ichar_pos] ;ichar_pos++) - if(compare_char == punsave[ichar_pos]) - return true; - - return false; - } - - static inline - std::string dec_to_hex(char num, int radix) - { - int temp=0; - std::string csTmp; - int num_char; - - num_char = (int) num; - if (num_char < 0) - num_char = 256 + num_char; - - while (num_char >= radix) - { - temp = num_char % radix; - num_char = (int)floor((float)num_char / (float)radix); - csTmp = get_hex_vals()[temp]; - } - - csTmp += get_hex_vals()[num_char]; - - if(csTmp.size() < 2) - { - csTmp += '0'; - } - - std::reverse(csTmp.begin(), csTmp.end()); - //_mbsrev((unsigned char*)csTmp.data()); - - return csTmp; - } - - static inline std::string convert(char val) - { - std::string csRet; - csRet += "%"; - csRet += dec_to_hex(val, 16); - return csRet; - } - static inline std::string conver_to_url_format(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - if(is_unsafe(uri[i])) - result += convert(uri[i]); - else - result += uri[i]; - - } - - return result; - } - - static inline std::string convert_to_url_format_force_all(const std::string& uri) - { - - std::string result; - - for(size_t i = 0; i!= uri.size(); i++) - { - result += convert(uri[i]); - } - - return result; - } - - - - - - namespace http - { - - class http_simple_client: public i_target_handler - { - public: - - - private: - enum reciev_machine_state - { - reciev_machine_state_header, - reciev_machine_state_body_content_len, - reciev_machine_state_body_connection_close, - reciev_machine_state_body_chunked, - reciev_machine_state_done, - reciev_machine_state_error - }; - - - - enum chunked_state{ - http_chunked_state_chunk_head, - http_chunked_state_chunk_body, - http_chunked_state_done, - http_chunked_state_undefined - }; - - - blocked_mode_client m_net_client; - std::string m_host_buff; - std::string m_port; - //unsigned int m_timeout; - unsigned int m_connection_timeout; - unsigned int m_recv_timeout; - std::string m_header_cache; - http_response_info m_response_info; - //std::string* m_ptarget_buffer; - boost::shared_ptr m_pcontent_encoding_handler; - reciev_machine_state m_state; - chunked_state m_chunked_state; - std::string m_chunked_cache; - critical_section m_lock; - - protected: - uint64_t m_len_in_summary; - uint64_t m_len_in_remain; - - public: - void set_host_name(const std::string& name) - { - CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = name; - } - - boost::asio::ip::tcp::socket& get_socket() - { - return m_net_client.get_socket(); - } - - - bool connect(const std::string& host, int port, unsigned int timeout) - { - return connect(host, std::to_string(port), timeout); - } - - bool set_timeouts(unsigned int connection_timeout, unsigned int recv_timeout) - { - m_connection_timeout = connection_timeout; - m_recv_timeout = recv_timeout; - return true; - } - - bool connect(const std::string& host, std::string port) - { - CRITICAL_REGION_LOCAL(m_lock); - m_host_buff = host; - m_port = port; - - return m_net_client.connect(host, port, m_connection_timeout, m_recv_timeout); - } - - bool connect(const std::string& host, const std::string& port, unsigned int timeout) - { - m_connection_timeout = m_recv_timeout = timeout; - return connect(host, port); - } - //--------------------------------------------------------------------------- - bool disconnect() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.disconnect(); - } - //--------------------------------------------------------------------------- - bool is_connected() - { - CRITICAL_REGION_LOCAL(m_lock); - return m_net_client.is_connected(); - } - //--------------------------------------------------------------------------- - virtual bool handle_target_data(std::string& piece_of_transfer) - { - CRITICAL_REGION_LOCAL(m_lock); - m_response_info.m_body += piece_of_transfer; - piece_of_transfer.clear(); - return true; - } - //--------------------------------------------------------------------------- - inline - bool invoke_get(const std::string& uri, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "GET", body, ppresponse_info, additional_params); - } - - //--------------------------------------------------------------------------- - inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!is_connected()) - { - LOG_PRINT("Reconnecting...", LOG_LEVEL_3); - if(!connect(m_host_buff, m_port)) - { - LOG_PRINT("Failed to connect to " << m_host_buff << ":" << m_port, LOG_LEVEL_3); - return false; - } - } - m_response_info.clear(); - std::string req_buff = method + " "; - req_buff += uri + " HTTP/1.1\r\n" + - "Host: "+ m_host_buff +"\r\n" + "Content-Length: " + boost::lexical_cast(body.size()) + "\r\n"; - - - //handle "additional_params" - for(fields_list::const_iterator it = additional_params.begin(); it!=additional_params.end(); it++) - req_buff += it->first + ": " + it->second + "\r\n"; - req_buff += "\r\n"; - //-- - - bool res = m_net_client.send(req_buff); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - if(body.size()) - res = m_net_client.send(body); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); - - if(ppresponse_info) - *ppresponse_info = &m_response_info; - - m_state = reciev_machine_state_header; - return handle_reciev(); - } - //--------------------------------------------------------------------------- - inline bool invoke_post(const std::string& uri, const std::string& body, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) - { - CRITICAL_REGION_LOCAL(m_lock); - return invoke(uri, "POST", body, ppresponse_info, additional_params); - } - private: - //--------------------------------------------------------------------------- - inline bool handle_reciev() - { - CRITICAL_REGION_LOCAL(m_lock); - bool keep_handling = true; - bool need_more_data = true; - std::string recv_buffer; - while(keep_handling) - { - if(need_more_data) - { - if(!m_net_client.recv(recv_buffer)) - { - LOG_PRINT("Unexpected reciec fail", LOG_LEVEL_3); - m_state = reciev_machine_state_error; - } - if(!recv_buffer.size()) - { - //connection is going to be closed - if(reciev_machine_state_body_connection_close != m_state) - { - m_state = reciev_machine_state_error; - } - } - need_more_data = false; - } - switch(m_state) - { - case reciev_machine_state_header: - keep_handling = handle_header(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_content_len: - keep_handling = handle_body_content_len(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_connection_close: - keep_handling = handle_body_connection_close(recv_buffer, need_more_data); - break; - case reciev_machine_state_body_chunked: - keep_handling = handle_body_body_chunked(recv_buffer, need_more_data); - break; - case reciev_machine_state_done: - keep_handling = false; - break; - case reciev_machine_state_error: - keep_handling = false; - break; - } - - } - m_header_cache.clear(); - if(m_state != reciev_machine_state_error) - { - if(m_response_info.m_header_info.m_connection.size() && !string_tools::compare_no_case("close", m_response_info.m_header_info.m_connection)) - disconnect(); - - return true; - } - else - { - LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state); - return false; - } - } - //--------------------------------------------------------------------------- - inline - bool handle_header(std::string& recv_buff, bool& need_more_data) - { - - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_ERROR("Connection closed at handle_header"); - m_state = reciev_machine_state_error; - return false; - } - - m_header_cache += recv_buff; - recv_buff.clear(); - std::string::size_type pos = m_header_cache.find("\r\n\r\n"); - if(pos != std::string::npos) - { - recv_buff.assign(m_header_cache.begin()+pos+4, m_header_cache.end()); - m_header_cache.erase(m_header_cache.begin()+pos+4, m_header_cache.end()); - - analize_cached_header_and_invoke_state(); - m_header_cache.clear(); - if(!recv_buff.size() && (m_state != reciev_machine_state_error && m_state != reciev_machine_state_done)) - need_more_data = true; - - return true; - }else - need_more_data = true; - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_content_len(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_PRINT("Warning: Content-Len mode, but connection unexpectedly closed", LOG_LEVEL_3); - m_state = reciev_machine_state_done; - return true; - } - CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); - m_len_in_remain -= recv_buff.size(); - bool r = m_pcontent_encoding_handler->update_in(recv_buff); - //CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_pcontent_encoding_handler->update_in returned false"); - if (!r) - { - m_state = reciev_machine_state_error; - disconnect(); - return false; - } - - if(m_len_in_remain == 0) - m_state = reciev_machine_state_done; - else - need_more_data = true; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_connection_close(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - m_state = reciev_machine_state_done; - return true; - } - need_more_data = true; - m_pcontent_encoding_handler->update_in(recv_buff); - - - return true; - } - //--------------------------------------------------------------------------- - inline bool is_hex_symbol(char ch) - { - - if( (ch >= '0' && ch <='9')||(ch >= 'A' && ch <='F')||(ch >= 'a' && ch <='f')) - return true; - else - return false; - } - //--------------------------------------------------------------------------- - inline - bool get_len_from_chunk_head(const std::string &chunk_head, uint64_t& result_size) - { - std::stringstream str_stream; - str_stream << std::hex; - if(!(str_stream << chunk_head && str_stream >> result_size)) - return false; - - return true; - } - //--------------------------------------------------------------------------- - inline - bool get_chunk_head(std::string& buff, uint64_t& chunk_size, bool& is_matched) - { - is_matched = false; - size_t offset = 0; - for(std::string::iterator it = buff.begin(); it!= buff.end(); it++, offset++) - { - if(!is_hex_symbol(*it)) - { - if(*it == '\r' || *it == ' ' ) - { - offset--; - continue; - } - else if(*it == '\n') - { - std::string chunk_head = buff.substr(0, offset); - if(!get_len_from_chunk_head(chunk_head, chunk_size)) - return false; - - if(0 == chunk_size) - { - //Here is a small confusion - //In breif - if the chunk is the last one we need to get terminating sequence - //along with the cipher, generally in the "ddd\r\n\r\n" form - - for(it++;it != buff.end(); it++) - { - if('\r' == *it) - continue; - else if('\n' == *it) - break; - else - { - LOG_ERROR("http_stream_filter: Wrong last chunk terminator"); - return false; - } - } - - if(it == buff.end()) - return true; - } - - buff.erase(buff.begin(), ++it); - - is_matched = true; - return true; - } - else - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline - bool handle_body_body_chunked(std::string& recv_buff, bool& need_more_data) - { - CRITICAL_REGION_LOCAL(m_lock); - if(!recv_buff.size()) - { - LOG_PRINT("Warning: CHUNKED mode, but connection unexpectedly closed", LOG_LEVEL_3); - m_state = reciev_machine_state_done; - return true; - } - m_chunked_cache += recv_buff; - recv_buff.clear(); - bool is_matched = false; - - while(true) - { - if(!m_chunked_cache.size()) - { - need_more_data = true; - break; - } - - switch(m_chunked_state) - { - case http_chunked_state_chunk_head: - if(m_chunked_cache[0] == '\n' || m_chunked_cache[0] == '\r') - { - //optimize a bit - if(m_chunked_cache[0] == '\r' && m_chunked_cache.size()>1 && m_chunked_cache[1] == '\n') - m_chunked_cache.erase(0, 2); - else - m_chunked_cache.erase(0, 1); - break; - } - if(!get_chunk_head(m_chunked_cache, m_len_in_remain, is_matched)) - { - LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head:" << m_chunked_cache); - m_state = reciev_machine_state_error; - return false; - } - - if(!is_matched) - { - need_more_data = true; - return true; - }else - { - m_chunked_state = http_chunked_state_chunk_body; - if(m_len_in_remain == 0) - {//last chunk, let stop the stream and fix the chunk queue. - m_state = reciev_machine_state_done; - return true; - } - m_chunked_state = http_chunked_state_chunk_body; - break; - } - break; - case http_chunked_state_chunk_body: - { - std::string chunk_body; - if(m_len_in_remain >= m_chunked_cache.size()) - { - m_len_in_remain -= m_chunked_cache.size(); - chunk_body.swap(m_chunked_cache); - }else - { - chunk_body.assign(m_chunked_cache, 0, m_len_in_remain); - m_chunked_cache.erase(0, m_len_in_remain); - m_len_in_remain = 0; - } - - m_pcontent_encoding_handler->update_in(chunk_body); - - if(!m_len_in_remain) - m_chunked_state = http_chunked_state_chunk_head; - } - break; - case http_chunked_state_done: - m_state = reciev_machine_state_done; - return true; - case http_chunked_state_undefined: - default: - LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state" << m_chunked_state); - return false; - } - } - - return true; - } - //--------------------------------------------------------------------------- - inline - bool parse_header(http_header_info& body_info, const std::string& m_cache_to_process) - { - LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_4); - - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)" - // 12 3 4 5 6 7 8 9 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //10 1112 13 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = m_cache_to_process.begin(); - std::string::const_iterator it_end_bound = m_cache_to_process.end(); - - - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 12; - //const size_t field_etc_name = 10; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Connection" - body_info.m_connection = result[field_val]; - else if(result[i++].matched)//"Referrer" - body_info.m_referer = result[field_val]; - else if(result[i++].matched)//"Content-Length" - body_info.m_content_length = result[field_val]; - else if(result[i++].matched)//"Content-Type" - body_info.m_content_type = result[field_val]; - else if(result[i++].matched)//"Transfer-Encoding" - body_info.m_transfer_encoding = result[field_val]; - else if(result[i++].matched)//"Content-Encoding" - body_info.m_content_encoding = result[field_val]; - else if(result[i++].matched)//"Host" - { body_info.m_host = result[field_val]; - string_tools::trim(body_info.m_host); - } - else if(result[i++].matched)//"Cookie" - body_info.m_cookie = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - {;} - else - {CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<(result[1]); - m_response_info.m_http_ver_lo = boost::lexical_cast(result[2]); - m_response_info.m_response_code = boost::lexical_cast(result[3]); - - m_header_cache.erase(to_nonsonst_iterator(m_header_cache, result[0].first), to_nonsonst_iterator(m_header_cache, result[0].second)); - return true; - }else - { - LOG_ERROR("http_stream_filter::handle_invoke_reply_line(): Failed to match first response line:" << m_header_cache); - return false; - } - - } - inline - bool set_reply_content_encoder() - { - STATIC_REGEXP_EXPR_1(rexp_match_gzip, "^.*?((gzip)|(deflate))", boost::regex::icase | boost::regex::normal); - boost::smatch result; // 12 3 - if(boost::regex_search( m_response_info.m_header_info.m_content_encoding, result, rexp_match_gzip, boost::match_default) && result[0].matched) - { -#ifdef HTTP_ENABLE_GZIP - m_pcontent_encoding_handler.reset(new content_encoding_gzip(this, result[3].matched)); -#else - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - LOG_ERROR("GZIP encoding not supported in this build, please add zlib to your project and define HTTP_ENABLE_GZIP"); - return false; -#endif - } - else - { - m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - } - - return true; - } - inline - bool analize_cached_header_and_invoke_state() - { - m_response_info.clear(); - analize_first_response_line(); - std::string fake_str; //gcc error workaround - - bool res = parse_header(m_response_info.m_header_info, m_header_cache); - CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " << m_header_cache); - - set_reply_content_encoder(); - - m_len_in_summary = 0; - bool content_len_valid = false; - if(m_response_info.m_header_info.m_content_length.size()) - content_len_valid = string_tools::get_xtype_from_string(m_len_in_summary, m_response_info.m_header_info.m_content_length); - - - - if(!m_len_in_summary && ((m_response_info.m_response_code>=100&&m_response_info.m_response_code<200) - || 204 == m_response_info.m_response_code - || 304 == m_response_info.m_response_code) ) - {//There will be no response body, server will display the local page with error - m_state = reciev_machine_state_done; - return true; - }else if(m_response_info.m_header_info.m_transfer_encoding.size()) - { - string_tools::trim(m_response_info.m_header_info.m_transfer_encoding); - if(string_tools::compare_no_case(m_response_info.m_header_info.m_transfer_encoding, "chunked")) - { - LOG_ERROR("Wrong Transfer-Encoding:" << m_response_info.m_header_info.m_transfer_encoding); - m_state = reciev_machine_state_error; - return false; - } - m_state = reciev_machine_state_body_chunked; - m_chunked_state = http_chunked_state_chunk_head; - return true; - } - else if(!m_response_info.m_header_info.m_content_length.empty()) - { - //In the response header the length was specified - if(!content_len_valid) - { - LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<(u_c.port), timeout)) - { - LOG_PRINT_L2("invoke_request: cannot connect to " << u_c.host << ":" << u_c.port); - return false; - } - } - - return tr.invoke(u_c.uri, method, body, ppresponse_info, additional_params); - } - - struct idle_handler_base - { - virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) = 0; - virtual ~idle_handler_base() {} - }; - - template - struct idle_handler : public idle_handler_base - { - callback_t m_cb; - - idle_handler(callback_t cb) : m_cb(cb) {} - virtual bool do_call(const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - return m_cb(piece_of_data, total_bytes, received_bytes); - } - }; - - class interruptible_http_client : public http_simple_client - { - std::shared_ptr m_pcb; - bool m_permanent_error = false; - - virtual bool handle_target_data(std::string& piece_of_transfer) - { - bool r = m_pcb->do_call(piece_of_transfer, m_len_in_summary, m_len_in_summary - m_len_in_remain); - piece_of_transfer.clear(); - return r; - } - - public: - template - bool invoke_cb(callback_t cb, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) - { - m_pcb.reset(new idle_handler(cb)); - const http_response_info* p_hri = nullptr; - bool r = invoke_request(url, *this, timeout, &p_hri, method, body, additional_params); - if (p_hri && !(p_hri->m_response_code >= 200 && p_hri->m_response_code < 300)) - { - LOG_PRINT_L0("HTTP request to " << url << " failed with code: " << p_hri->m_response_code); - m_permanent_error = true; - return false; - } - return r; - } - - template - bool download(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), const fields_list& additional_params = fields_list()) - { - std::ofstream fs; - fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc); - if (!fs.is_open()) - { - LOG_ERROR("Fsiled to open " << path_for_file); - return false; - } - auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - fs.write(piece_of_data.data(), piece_of_data.size()); - return cb(total_bytes, received_bytes); - }; - bool r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params); - fs.close(); - return r; - } - - // - template - bool download_and_unzip(callback_t cb, const std::string& path_for_file, const std::string& url, uint64_t timeout, const std::string& method = "GET", const std::string& body = std::string(), uint64_t fails_count = 1000, const fields_list& additional_params = fields_list()) - { - std::ofstream fs; - fs.open(path_for_file, std::ios::binary | std::ios::out | std::ios::trunc); - if (!fs.is_open()) - { - LOG_ERROR("Fsiled to open " << path_for_file); - return false; - } - std::string buff; - gzip_decoder_lambda zip_decoder; - uint64_t state_total_bytes = 0; - uint64_t state_received_bytes_base = 0; - uint64_t state_received_bytes_current = 0; - bool stopped = false; - auto local_cb = [&](const std::string& piece_of_data, uint64_t total_bytes, uint64_t received_bytes) - { - //remember total_bytes only for first attempt, where fetched full lenght of the file - if (!state_total_bytes) - state_total_bytes = total_bytes; - - buff += piece_of_data; - return zip_decoder.update_in(buff, [&](const std::string& unpacked_buff) - { - state_received_bytes_current = received_bytes; - fs.write(unpacked_buff.data(), unpacked_buff.size()); - stopped = !cb(unpacked_buff, state_total_bytes, state_received_bytes_base + received_bytes); - return !stopped; - }); - }; - uint64_t current_err_count = 0; - bool r = false; - m_permanent_error = false; - while (!r && current_err_count < fails_count) - { - LOG_PRINT_L0("Attempt " << current_err_count + 1 << "/" << fails_count << " to get " << url << " (offset:" << state_received_bytes_base << ")"); - fields_list additional_params_local = additional_params; - additional_params_local.push_back(std::make_pair("Range", std::string("bytes=") + std::to_string(state_received_bytes_base) + "-")); - r = this->invoke_cb(local_cb, url, timeout, method, body, additional_params_local); - if (!r) - { - if (stopped || m_permanent_error) - break; - current_err_count++; - state_received_bytes_base += state_received_bytes_current; - state_received_bytes_current = 0; - boost::this_thread::sleep_for(boost::chrono::milliseconds(2000)); - } - } - - if (current_err_count >= fails_count) - { - LOG_PRINT_YELLOW("Downloading from " << url << " FAILED as it's reached maximum (" << fails_count << ") number of attempts. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0); - } - else if (m_permanent_error) - { - LOG_PRINT_YELLOW("Downloading from " << url << " FAILED due to permanent HTTP error. Downloaded " << state_received_bytes_base << " bytes.", LOG_LEVEL_0); - } - - fs.close(); - return r; - } - }; - - - } // namespace http - -} // namespace net_utils -} // namespace epee diff --git a/src/contrib/epee/include/net/http_client_abstract_invoke.h b/src/contrib/epee/include/net/http_client_abstract_invoke.h deleted file mode 100644 index 425a355..0000000 --- a/src/contrib/epee/include/net/http_client_abstract_invoke.h +++ /dev/null @@ -1,98 +0,0 @@ - -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "storages/serializeble_struct_helper.h" - -namespace epee -{ - namespace net_utils - { - namespace http - { - template - bool invoke_http_json_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - StorageNamed::InMemStorageSpace::json::store_t_to_json(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return StorageNamed::InMemStorageSpace::json::load_t_from_json(result_struct, pri->m_body); - } - - - - template - bool invoke_http_bin_remote_command(const std::string& url, TArg& out_struct, TResult& result_struct, TTransport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - epee::StorageNamed::save_struct_as_storage_to_buff(out_struct, req_param); - - const http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return epee::StorageNamed::load_struct_from_storage_buff(result_struct, pri->m_body); - } - - - } - } -} diff --git a/src/contrib/epee/include/net/http_client_base.h b/src/contrib/epee/include/net/http_client_base.h deleted file mode 100644 index 571e27f..0000000 --- a/src/contrib/epee/include/net/http_client_base.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace epee -{ - namespace net_utils - { - struct i_sub_handler - { - virtual ~i_sub_handler(){} - - virtual bool update_in( std::string& piece_of_transfer)=0; - virtual void stop(std::string& OUT collect_remains)=0; - virtual bool update_and_stop(std::string& OUT collect_remains, bool& is_changed) - { - is_changed = true; - bool res = this->update_in(collect_remains); - if(res) - this->stop(collect_remains); - return res; - } - }; - - - struct i_target_handler - { - virtual ~i_target_handler(){} - virtual bool handle_target_data( std::string& piece_of_transfer)=0; - }; - - - class do_nothing_sub_handler: public i_sub_handler - { - public: - do_nothing_sub_handler(i_target_handler* powner_filter):m_powner_filter(powner_filter) - {} - virtual bool update_in( std::string& piece_of_transfer) - { - return m_powner_filter->handle_target_data(piece_of_transfer); - } - virtual void stop(std::string& OUT collect_remains) - { - - } - i_target_handler* m_powner_filter; - }; - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/http_client_via_api_helper.h b/src/contrib/epee/include/net/http_client_via_api_helper.h deleted file mode 100644 index 45a7099..0000000 --- a/src/contrib/epee/include/net/http_client_via_api_helper.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#pragma comment(lib, "Wininet.lib") - -namespace epee -{ -namespace net_utils -{ - inline - bool http_ssl_invoke(const std::string& url, const std::string usr, const std::string psw, std::string& http_response_body, bool use_post = false) - { - bool final_res = false; - - ATL::CUrl url_obj; - BOOL crack_rss = url_obj.CrackUrl(string_encoding::convert_to_t >(url).c_str()); - - HINTERNET hinet = ::InternetOpenA(SHARED_JOBSCOMMON_HTTP_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(!hinet) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - DWORD dwFlags = 0; - DWORD dwBuffLen = sizeof(dwFlags); - - if(usr.size()) - { - dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID| - INTERNET_FLAG_PRAGMA_NOCACHE | SECURITY_FLAG_IGNORE_UNKNOWN_CA|INTERNET_FLAG_SECURE; - }else - { - dwFlags |= INTERNET_FLAG_PRAGMA_NOCACHE; - } - - - int port = url_obj.GetPortNumber(); - BOOL res = FALSE; - - HINTERNET hsession = ::InternetConnectA(hinet, string_encoding::convert_to_ansii(url_obj.GetHostName()).c_str(), port/*INTERNET_DEFAULT_HTTPS_PORT*/, usr.c_str(), psw.c_str(), INTERNET_SERVICE_HTTP, dwFlags, NULL); - if(hsession) - { - const std::string uri = string_encoding::convert_to_ansii(url_obj.GetUrlPath()) + string_encoding::convert_to_ansii(url_obj.GetExtraInfo()); - - HINTERNET hrequest = ::HttpOpenRequestA(hsession, use_post?"POST":NULL, uri.c_str(), NULL, NULL,NULL, dwFlags, NULL); - if(hrequest) - { - while(true) - { - res = ::HttpSendRequestA(hrequest, NULL, 0, NULL, 0); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - - DWORD code = 0; - DWORD buf_len = sizeof(code); - DWORD index = 0; - res = ::HttpQueryInfo(hrequest, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &code, &buf_len, &index); - if(!res) - { - //ERROR_INTERNET_INVALID_CA 45 - //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) - int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(code < 200 || code > 299) - { - LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code , LOG_LEVEL_0); - break; - } - - - char buff[100000] = {0}; - DWORD readed = 0; - while(true) - { - res = ::InternetReadFile(hrequest, buff, sizeof(buff), &readed); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - break; - } - if(readed) - { - http_response_body.append(buff, readed); - } - else - break; - } - - if(!res) - break; - - - //we success - final_res = true; - - res = ::InternetCloseHandle(hrequest); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - break; - } - } - else - { - //ERROR_INTERNET_INVALID_CA - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - return false; - } - - res = ::InternetCloseHandle(hsession); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - }else - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - - - - res = ::InternetCloseHandle(hinet); - if(!res) - { - int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); - } - return final_res; - } -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/http_protocol_handler.h b/src/contrib/epee/include/net/http_protocol_handler.h deleted file mode 100644 index aa4dfa9..0000000 --- a/src/contrib/epee/include/net/http_protocol_handler.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_H_ -#define _HTTP_SERVER_H_ - -#include -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct http_server_config - { - void on_send_stop_signal(){} - std::string m_folder; - critical_section m_lock; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - class simple_http_connection_handler - { - public: - typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context; - typedef http_server_config config_type; - - simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config); - virtual ~simple_http_connection_handler(){} - - bool release_protocol() - { - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - bool after_init_connection() - { - return true; - } - virtual bool handle_recv(const void* ptr, size_t cb); - virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response); - - - //temporary here - //bool parse_uri(const std::string uri, uri_content& content); - - private: - enum machine_state{ - http_state_retriving_comand_line, - http_state_retriving_header, - http_state_retriving_body, - http_state_connection_close, - http_state_error - }; - - enum body_transfer_type{ - http_body_transfer_chunked, - http_body_transfer_measure,//mean "Content-Length" valid - http_body_transfer_chunked_instead_measure, - http_body_transfer_connection_close, - http_body_transfer_multipart, - http_body_transfer_undefined - }; - - bool handle_buff_in(std::string& buf); - - bool analize_cached_request_header_and_invoke_state(size_t pos); - - bool handle_invoke_query_line(); - bool parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos); - std::string::size_type match_end_of_header(const std::string& buf); - bool get_len_from_content_lenght(const std::string& str, size_t& len); - bool handle_retriving_query_body(); - bool handle_query_measure(); - bool set_ready_state(); - bool slash_to_back_slash(std::string& str); - std::string get_file_mime_tipe(const std::string& path); - std::string get_response_header(const http_response_info& response); - - //major function - inline bool handle_request_and_send_response(const http::http_request_info& query_info); - - - std::string get_not_found_response_body(const std::string& URI); - - std::string m_root_path; - std::string m_cache; - machine_state m_state; - body_transfer_type m_body_transfer_type; - bool m_is_stop_handling; - http::http_request_info m_query_info; - size_t m_len_summary, m_len_remain; - size_t m_precommand_line_chars; - config_type& m_config; - bool m_want_close; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - template - struct i_http_server_handler - { - virtual ~i_http_server_handler(){} - virtual bool handle_http_request(const http_request_info& query_info, http_response_info& response, t_connection_context& m_conn_context)=0; - virtual bool init_server_thread(){return true;} - virtual bool deinit_server_thread(){return true;} - }; - - template - struct custum_handler_config: public http_server_config - { - i_http_server_handler* m_phandler; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class http_custom_handler: public simple_http_connection_handler - { - public: - typedef custum_handler_config config_type; - - http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context):simple_http_connection_handler(psnd_hndlr, config), - m_config(config), - m_conn_context(conn_context) - {} - inline bool handle_request(const http_request_info& query_info, http_response_info& response) - { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); - //fill with default values - response.m_mime_tipe = "text/plain"; - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_body.clear(); - return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context); - } - - virtual bool thread_init() - { - return m_config.m_phandler->init_server_thread();; - } - - virtual bool thread_deinit() - { - return m_config.m_phandler->deinit_server_thread(); - } - void handle_qued_callback() - {} - bool after_init_connection() - { - return true; - } - - private: - //simple_http_connection_handler::config_type m_stub_config; - config_type& m_config; - t_connection_context& m_conn_context; - }; - } -} -} - -#include "http_protocol_handler.inl" - -#endif //_HTTP_SERVER_H_ diff --git a/src/contrib/epee/include/net/http_protocol_handler.inl b/src/contrib/epee/include/net/http_protocol_handler.inl deleted file mode 100644 index a5f42c4..0000000 --- a/src/contrib/epee/include/net/http_protocol_handler.inl +++ /dev/null @@ -1,696 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#include -#include -#include "http_protocol_handler.h" -#include "reg_exp_definer.h" -#include "string_tools.h" -#include "file_io_utils.h" -#include "net_parse_helpers.h" - -#define HTTP_MAX_URI_LEN 9000 -#define HTTP_MAX_PRE_COMMAND_LINE_CHARS 20 -#define HTTP_MAX_HEADER_LEN 100000 - -PUSH_GCC_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - - -namespace epee -{ -namespace net_utils -{ - namespace http - { - - struct multipart_entry - { - std::list > m_etc_header_fields; - std::string m_content_disposition; - std::string m_content_type; - std::string m_body; - }; - - inline - bool match_boundary(const std::string& content_type, std::string& boundary) - { - STATIC_REGEXP_EXPR_1(rexp_match_boundary, "boundary=(.*?)(($)|([;\\s,]))", boost::regex::icase | boost::regex::normal); - // 1 - boost::smatch result; - if(boost::regex_search(content_type, result, rexp_match_boundary, boost::match_default) && result[0].matched) - { - boundary = result[1]; - return true; - } - - return false; - } - - inline - bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Content-Disposition)|(Content-Type)" - // 12 3 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //4 56 7 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = it_begin; - std::string::const_iterator it_end_bound = it_end; - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 6; - const size_t field_etc_name = 4; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Content-Disposition" - entry.m_content_disposition = result[field_val]; - else if(result[i++].matched)//"Content-Type" - entry.m_content_type = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - entry.m_etc_header_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:"<& out_values) - { - //bool res = file_io_utils::load_file_to_string("C:\\public\\multupart_data", body); - - std::string boundary; - if(!match_boundary(content_type, boundary)) - { - LOG_PRINT("Failed to match boundary in content type: " << content_type, LOG_LEVEL_0); - return false; - } - - boundary+="\r\n"; - bool is_stop = false; - bool first_step = true; - - std::string::const_iterator it_begin = body.begin(); - std::string::const_iterator it_end; - while(!is_stop) - { - std::string::size_type pos = body.find(boundary, std::distance(body.begin(), it_begin)); - - if(std::string::npos == pos) - { - is_stop = true; - boundary.erase(boundary.size()-2, 2); - boundary+= "--"; - pos = body.find(boundary, std::distance(body.begin(), it_begin)); - if(std::string::npos == pos) - { - LOG_PRINT("Error: Filed to match closing multipart tag", LOG_LEVEL_0); - it_end = body.end(); - }else - { - it_end = body.begin() + pos; - } - }else - it_end = body.begin() + pos; - - - if(first_step && !is_stop) - { - first_step = false; - it_begin = it_end + boundary.size(); - std::string temp = "\r\n--"; - boundary = temp + boundary; - continue; - } - - out_values.push_back(multipart_entry()); - if(!handle_part_of_multipart(it_begin, it_end, out_values.back())) - { - LOG_PRINT("Failed to handle_part_of_multipart", LOG_LEVEL_0); - return false; - } - - it_begin = it_end + boundary.size(); - } - - return true; - } - - - - - //-------------------------------------------------------------------------------------------- - template - simple_http_connection_handler::simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config): - m_state(http_state_retriving_comand_line), - m_body_transfer_type(http_body_transfer_undefined), - m_is_stop_handling(false), - m_len_summary(0), - m_len_remain(0), - m_config(config), - m_want_close(false), - m_psnd_hndlr(psnd_hndlr), - m_precommand_line_chars(0) - { - - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::set_ready_state() - { - m_is_stop_handling = false; - m_state = http_state_retriving_comand_line; - m_body_transfer_type = http_body_transfer_undefined; - m_query_info.clear(); - m_len_summary = 0; - m_precommand_line_chars = 0; - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_recv(const void* ptr, size_t cb) - { - std::string buf((const char*)ptr, cb); - //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf); - //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast(ptr), std::string((const char*)ptr, cb)); - - bool res = handle_buff_in(buf); - if(m_want_close/*m_state == http_state_connection_close || m_state == http_state_error*/) - return false; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_buff_in(std::string& buf) - { - - if(m_cache.size()) - m_cache += buf; - else - m_cache.swap(buf); - - m_is_stop_handling = false; - while(!m_is_stop_handling) - { - switch(m_state) - { - case http_state_retriving_comand_line: - //The HTTP protocol does not place any a priori limit on the length of a URI. (c)RFC2616 - //but we forebly restirct it len to HTTP_MAX_URI_LEN to make it more safely - if(!m_cache.size()) - break; - - //check_and_handle_fake_response(); - if((m_cache[0] == '\r' || m_cache[0] == '\n')) - { - //some times it could be that before query line cold be few line breaks - //so we have to be calm down without panic and asserts - m_cache.erase(0, 1); - - //fixed bug with possible '\r\n' chars flood, thanks to @anonimal (https://github.com/anonimal) for pointing this - ++m_precommand_line_chars; - if (m_precommand_line_chars > HTTP_MAX_PRE_COMMAND_LINE_CHARS) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line"); - m_state = http_state_error; - return false; - } - break; - } - if(std::string::npos != m_cache.find('\n', 0)) - handle_invoke_query_line(); - else - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_URI_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long URI line"); - m_state = http_state_error; - return false; - } - } - break; - case http_state_retriving_header: - { - std::string::size_type pos = match_end_of_header(m_cache); - if(std::string::npos == pos) - { - m_is_stop_handling = true; - if(m_cache.size() > HTTP_MAX_HEADER_LEN) - { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area"); - m_state = http_state_error; - return false; - } - break; - } - analize_cached_request_header_and_invoke_state(pos); - break; - } - case http_state_retriving_body: - return handle_retriving_query_body(); - case http_state_connection_close: - return false; - default: - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Wrong state: " << m_state); - return false; - case http_state_error: - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Error state!!!"); - return false; - } - - if(!m_cache.size()) - m_is_stop_handling = true; - } - - return true; - } - //-------------------------------------------------------------------------------------------- - inline bool analize_http_method(const boost::smatch& result, http::http_method& method, int& http_ver_major, int& http_ver_minor) - { - CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); - http_ver_major = boost::lexical_cast(result[11]); - http_ver_minor = boost::lexical_cast(result[12]); - if(result[4].matched) - method = http::http_method_get; - else if(result[5].matched) - method = http::http_method_head; - else if(result[6].matched) - method = http::http_method_post; - else if(result[7].matched) - method = http::http_method_put; - else - method = http::http_method_etc; - - return true; - } - - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_invoke_query_line() - { - LOG_FRAME("simple_http_connection_handler::handle_invoke_query_line(*)", LOG_LEVEL_3); - - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+).(\\d+))\r?\n", boost::regex::icase | boost::regex::normal); - // 123 4 5 6 7 8 9 10 11 12 - //size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi); - m_query_info.m_URI = result[10]; - parse_uri(m_query_info.m_URI, m_query_info.m_uri_content); - m_query_info.m_http_method_str = result[2]; - m_query_info.m_full_request_str = result[0]; - - m_cache.erase(m_cache.begin(), to_nonsonst_iterator(m_cache, result[0].second)); - - m_state = http_state_retriving_header; - - return true; - }else - { - m_state = http_state_error; - LOG_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: " << m_cache); - return false; - } - - return false; - } - //-------------------------------------------------------------------------------------------- - template - std::string::size_type simple_http_connection_handler::match_end_of_header(const std::string& buf) - { - - //Here we returning head size, including terminating sequence (\r\n\r\n or \n\n) - std::string::size_type res = buf.find("\r\n\r\n"); - if(std::string::npos != res) - return res+4; - res = buf.find("\n\n"); - if(std::string::npos != res) - return res+2; - return res; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::analize_cached_request_header_and_invoke_state(size_t pos) - { - //LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos)); - - LOG_FRAME("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(*)", LOG_LEVEL_3); - - m_query_info.m_full_request_buf_size = pos; - m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos); - - if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache); - m_state = http_state_error; - } - - m_cache.erase(0, pos); - - std::string req_command_str = m_query_info.m_full_request_str; - //if we have POST or PUT command, it is very possible tha we will get body - //but now, we suppose than we have body only in case of we have "ContentLength" - if(m_query_info.m_header_info.m_content_length.size()) - { - m_state = http_state_retriving_body; - m_body_transfer_type = http_body_transfer_measure; - if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary)) - { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="< - bool simple_http_connection_handler::handle_retriving_query_body() - { - switch(m_body_transfer_type) - { - case http_body_transfer_measure: - return handle_query_measure(); - case http_body_transfer_chunked: - case http_body_transfer_connection_close: - case http_body_transfer_multipart: - case http_body_transfer_undefined: - default: - LOG_ERROR("simple_http_connection_handler::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type); - m_state = http_state_error; - return false; - } - - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_query_measure() - { - - if(m_len_remain >= m_cache.size()) - { - m_len_remain -= m_cache.size(); - m_query_info.m_body += m_cache; - m_cache.clear(); - }else - { - m_query_info.m_body.append(m_cache.begin(), m_cache.begin() + m_len_remain); - m_cache.erase(0, m_len_remain); - m_len_remain = 0; - } - - if(!m_len_remain) - { - if(handle_request_and_send_response(m_query_info)) - set_ready_state(); - else - m_state = http_state_error; - } - return true; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos) - { - LOG_FRAME("http_stream_filter::parse_cached_header(*)", LOG_LEVEL_3); - - STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)" - // 12 3 4 5 6 7 8 9 - "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //10 1112 13 - boost::regex::icase | boost::regex::normal); - - boost::smatch result; - std::string::const_iterator it_current_bound = m_cache_to_process.begin(); - std::string::const_iterator it_end_bound = m_cache_to_process.begin()+pos; - - body_info.clear(); - - //lookup all fields and fill well-known fields - while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) - { - const size_t field_val = 12; - const size_t field_etc_name = 10; - - int i = 2; //start position = 2 - if(result[i++].matched)//"Connection" - body_info.m_connection = result[field_val]; - else if(result[i++].matched)//"Referer" - body_info.m_referer = result[field_val]; - else if(result[i++].matched)//"Content-Length" - body_info.m_content_length = result[field_val]; - else if(result[i++].matched)//"Content-Type" - body_info.m_content_type = result[field_val]; - else if(result[i++].matched)//"Transfer-Encoding" - body_info.m_transfer_encoding = result[field_val]; - else if(result[i++].matched)//"Content-Encoding" - body_info.m_content_encoding = result[field_val]; - else if(result[i++].matched)//"Host" - body_info.m_host = result[field_val]; - else if(result[i++].matched)//"Cookie" - body_info.m_cookie = result[field_val]; - else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) - body_info.m_etc_fields.push_back(std::pair(result[field_etc_name], result[field_val])); - else - { - LOG_ERROR("simple_http_connection_handler::parse_cached_header() not matched last entry in:"< - bool simple_http_connection_handler::get_len_from_content_lenght(const std::string& str, size_t& OUT len) - { - STATIC_REGEXP_EXPR_1(rexp_mach_field, "\\d+", boost::regex::normal); - std::string res; - boost::smatch result; - if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched)) - return false; - - len = boost::lexical_cast(result[0]); - return true; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request_and_send_response(const http::http_request_info& query_info) - { - http_response_info response; - bool res = handle_request(query_info, response); - //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); - - std::string response_data = get_response_header(response); - - //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body); - LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data); - - m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - if(response.m_body.size()) - m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size()); - return res; - } - //----------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::handle_request(const http::http_request_info& query_info, http_response_info& response) - { - - std::string uri_to_path = query_info.m_uri_content.m_path; - if("/" == uri_to_path) - uri_to_path = "/index.html"; - - //slash_to_back_slash(uri_to_path); - CRITICAL_SECTION_LOCK(m_config.m_lock); - std::string destination_file_path = m_config.m_folder + uri_to_path; - CRITICAL_SECTION_UNLOCK(m_config.m_lock); - if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body)) - { - LOG_PRINT("URI \""<< query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size()-2) << "\" [" << destination_file_path << "] Not Found (404 )" , LOG_LEVEL_1); - response.m_body = get_not_found_response_body(query_info.m_URI); - response.m_response_code = 404; - response.m_response_comment = "Not found"; - response.m_mime_tipe = "text/html"; - return true; - } - - LOG_PRINT(" -->> " << query_info.m_full_request_str << "\r\n<<--OK" , LOG_LEVEL_3); - response.m_response_code = 200; - response.m_response_comment = "OK"; - response.m_mime_tipe = get_file_mime_tipe(uri_to_path); - - - return true; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_response_header(const http_response_info& response) - { - std::string buf = "HTTP/1.1 "; - buf += boost::lexical_cast(response.m_response_code) + " " + response.m_response_comment + "\r\n" + - "Server: Epee-based\r\n" - "Content-Length: "; - buf += boost::lexical_cast(response.m_body.size()) + "\r\n"; - buf += "Content-Type: "; - buf += response.m_mime_tipe + "\r\n"; - - buf += "Last-Modified: "; - time_t tm; - time(&tm); - buf += misc_utils::get_internet_time_str(tm) + "\r\n"; - buf += "Accept-Ranges: bytes\r\n"; - //Wed, 01 Dec 2010 03:27:41 GMT" - - string_tools::trim(m_query_info.m_header_info.m_connection); - if(m_query_info.m_header_info.m_connection.size()) - { - if(!string_tools::compare_no_case("close", m_query_info.m_header_info.m_connection)) - { - //closing connection after sending - buf += "Connection: close\r\n"; - m_state = http_state_connection_close; - m_want_close = true; - } - } - //add additional fields, if it is - for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++) - buf += it->first + ":" + it->second + "\r\n"; - - buf+="\r\n"; - - return buf; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_file_mime_tipe(const std::string& path) - { - std::string result; - std::string ext = string_tools::get_extension(path); - if(!string_tools::compare_no_case(ext, "gif")) - result = "image/gif"; - else if(!string_tools::compare_no_case(ext, "jpg")) - result = "image/jpeg"; - else if(!string_tools::compare_no_case(ext, "html")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "htm")) - result = "text/html"; - else if(!string_tools::compare_no_case(ext, "js")) - result = "application/x-javascript"; - else if(!string_tools::compare_no_case(ext, "css")) - result = "text/css"; - else if(!string_tools::compare_no_case(ext, "xml")) - result = "application/xml"; - else if(!string_tools::compare_no_case(ext, "svg")) - result = "image/svg+xml"; - - - return result; - } - //----------------------------------------------------------------------------------- - template - std::string simple_http_connection_handler::get_not_found_response_body(const std::string& URI) - { - std::string body = - "\r\n" - "\r\n" - "404 Not Found\r\n" - "\r\n" - "

Not Found

\r\n" - "

The requested URL \r\n"; - body += URI; - body += "was not found on this server.

\r\n" - "\r\n"; - - return body; - } - //-------------------------------------------------------------------------------------------- - template - bool simple_http_connection_handler::slash_to_back_slash(std::string& str) - { - for(std::string::iterator it = str.begin(); it!=str.end(); it++) - if('/' == *it) - *it = '\\'; - return true; - } - } -} -} - -POP_GCC_WARNINGS -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------- diff --git a/src/contrib/epee/include/net/http_server_cp.h b/src/contrib/epee/include/net/http_server_cp.h deleted file mode 100644 index bbb167f..0000000 --- a/src/contrib/epee/include/net/http_server_cp.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "http_server.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_http_server_file_system; - typedef cp_server_impl cp_http_server_custum_handling; -} -} - - - -#endif - - diff --git a/src/contrib/epee/include/net/http_server_cp2.h b/src/contrib/epee/include/net/http_server_cp2.h deleted file mode 100644 index 1a503a4..0000000 --- a/src/contrib/epee/include/net/http_server_cp2.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP2_H_ -#define _HTTP_SERVER_CP2_H_ - -#include "abstract_tcp_server2.h" -#include "http_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_http_server_file_system; - typedef boosted_tcp_server > boosted_http_server_custum_handling; -} -} - - -#endif - - diff --git a/src/contrib/epee/include/net/http_server_handlers_map2.h b/src/contrib/epee/include/net/http_server_handlers_map2.h deleted file mode 100644 index 6b45950..0000000 --- a/src/contrib/epee/include/net/http_server_handlers_map2.h +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "http_base.h" - -template -bool auto_doc_t(const std::string& prefix_name, std::string& generate_reference) -{ - if (!generate_reference.size()) return true; - request_t req = AUTO_VAL_INIT(req); - response_t res = AUTO_VAL_INIT(res); - std::stringstream ss; - ss << prefix_name << ENDL - << "REQUEST: " << ENDL << epee::serialization::store_t_to_json(req) << ENDL << "--------------------------------" << ENDL - << "RESPONSE: " << ENDL << epee::serialization::store_t_to_json(res) << ENDL << "################################" << ENDL; - generate_reference += ss.str(); - return true; -} - - -template -bool auto_doc(const std::string& prefix_name, std::string& generate_reference) -{ - return auto_doc_t(prefix_name, generate_reference); -} - - -#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response, \ - context_type& m_conn_context) \ -{\ - response.m_response_code = 200; \ - response.m_response_comment = "Ok"; \ - std::string reference_stub; \ - bool call_found = false; \ - if(!handle_http_request_map(query_info, response, m_conn_context, call_found, reference_stub) && response.m_response_code == 200) \ - { response.m_response_code = 500; response.m_response_comment = "Internal Server Error"; return true; } \ - if (!call_found) \ - { response.m_response_code = 404; response.m_response_comment = "Not Found"; return true; } \ - return true; \ -} - -#define BEGIN_URI_MAP2() template bool handle_http_request_map(const epee::net_utils::http::http_request_info& query_info, \ - epee::net_utils::http::http_response_info& response_info, \ - t_context& m_conn_context, bool& call_found, std::string& generate_reference) { \ - call_found = false; \ - if(false) return true; //just a stub to have "else if" - -#define MAP_URI2(pattern, callback) else if(std::string::npos != query_info.m_URI.find(pattern)) return callback(query_info, response_info, m_conn_context); - -#define MAP_URI_AUTO_XML2(s_pattern, callback_f, command_type) //TODO: don't think i ever again will use xml - ambiguous and "overtagged" format - -#define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) \ - else if(auto_doc(s_pattern "[JSON]", generate_reference) && query_info.m_URI == s_pattern) \ - { \ - call_found = true; \ - uint64_t ticks = misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool res = epee::serialization::load_t_from_json(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(res, false, "Failed to parse json: \r\n" << query_info.m_body); \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - res = callback_f(static_cast(req), static_cast(resp), m_conn_context); \ - CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - LOG_PRINT("[HTTP/JSON][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ - } - -#define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ - else if(auto_doc(s_pattern "[BIN]", generate_reference) && query_info.m_URI == s_pattern) \ - { \ - call_found = true; \ - uint64_t ticks = misc_utils::get_tick_count(); \ - boost::value_initialized req; \ - bool res = epee::serialization::load_t_from_binary(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ - uint64_t ticks1 = misc_utils::get_tick_count(); \ - boost::value_initialized resp;\ - res = callback_f(static_cast(req), static_cast(resp), m_conn_context); \ - CHECK_AND_ASSERT_MES(res, false, "Failed to call " << #callback_f << "() while handling " << s_pattern); \ - uint64_t ticks2 = misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_binary(static_cast(resp), response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = " application/octet-stream"; \ - response_info.m_header_info.m_content_type = " application/octet-stream"; \ - LOG_PRINT( "[HTTP/BIN][" << epee::string_tools::get_ip_string_from_int32(m_conn_context.m_remote_ip ) << "][" << query_info.m_URI << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); \ - } - -#define CHAIN_URI_MAP2(callback) else {callback(query_info, response_info, m_conn_context);call_found = true;} - -#define END_URI_MAP2() return true;} - - - - -namespace epee -{ - namespace json_rpc - { - template - struct request - { - std::string jsonrpc; - std::string method; - epee::serialization::storage_entry id; - t_param params; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(method) - KV_SERIALIZE(params) - END_KV_SERIALIZE_MAP() - }; - - struct error - { - int64_t code; - std::string message; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(code) - KV_SERIALIZE(message) - END_KV_SERIALIZE_MAP() - }; - - struct dummy_error - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct dummy_result - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - t_error error; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - std::string method; - t_error error; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(method) - KV_SERIALIZE(id) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - typedef response error_response; - } -} - -template -struct json_command_type_t -{ - typedef typename epee::json_rpc::request request; - typedef typename epee::json_rpc::request response; -}; - -#define JSON_RPC_REFERENCE_MARKER "JSON_RPC" - - - -#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == JSON_RPC_REFERENCE_MARKER || query_info.m_URI == uri) \ - { \ - if(query_info.m_URI == JSON_RPC_REFERENCE_MARKER) {generate_reference = "JSON RPC URL: " uri "\n";} \ - LOG_PRINT_L4("[JSON_REQUEST_BODY]: " << ENDL << query_info.m_body); \ - uint64_t ticks = epee::misc_utils::get_tick_count(); \ - epee::serialization::portable_storage ps; \ - if(!ps.load_from_json(query_info.m_body)) \ - { \ - boost::value_initialized rsp; \ - static_cast(rsp).error.code = -32700; \ - static_cast(rsp).error.message = "Parse error"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - epee::serialization::storage_entry id_; \ - id_ = epee::serialization::storage_entry(std::string()); \ - ps.get_value("id", id_, nullptr); \ - std::string callback_name; \ - if(!ps.get_value("method", callback_name, nullptr)) \ - { \ - epee::json_rpc::error_response rsp; \ - rsp.jsonrpc = "2.0"; \ - rsp.error.code = -32600; \ - rsp.error.message = "Invalid Request"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - return true; \ - } \ - if(false) return true; //just a stub to have "else if" - - - - -#define PREPARE_OBJECTS_FROM_JSON(command_type) \ - call_found = true; \ - boost::value_initialized > req_; \ - epee::json_rpc::request& req = static_cast&>(req_);\ - if(!req.load(ps)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32602; \ - fail_resp.error.message = "Invalid params"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ - boost::value_initialized > resp_; \ - epee::json_rpc::response& resp = static_cast &>(resp_); \ - resp.jsonrpc = "2.0"; \ - resp.id = req.id; - -#define FINALIZE_OBJECTS_TO_JSON(method_name) \ - uint64_t ticks2 = epee::misc_utils::get_tick_count(); \ - epee::serialization::store_t_to_json(resp, response_info.m_body); \ - uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - response_info.m_mime_tipe = "application/json"; \ - response_info.m_header_info.m_content_type = " application/json"; \ - LOG_PRINT( query_info.m_URI << "[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2); - -#define MAP_JON_RPC_WE(method_name, callback_f, command_type) \ - else if(auto_doc>("[" method_name "]", generate_reference) && callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.method = req.method; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC_WERI(method_name, callback_f, command_type) \ - else if(auto_doc>("[" method_name "]", generate_reference) && callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.method = req.method; \ - fail_resp.id = req.id; \ - if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \ - { \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC(method_name, callback_f, command_type) \ - else if(auto_doc>(std::string("[") + method_name + "]", generate_reference) && callback_name == method_name) \ -{ \ - PREPARE_OBJECTS_FROM_JSON(command_type) \ - if(!callback_f(req.params, resp.result, m_conn_context)) \ - { \ - epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ - fail_resp.jsonrpc = "2.0"; \ - fail_resp.method = req.method; \ - fail_resp.id = req.id; \ - fail_resp.error.code = -32603; \ - fail_resp.error.message = "Internal error"; \ - epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ - return true; \ - } \ - FINALIZE_OBJECTS_TO_JSON(method_name) \ - return true;\ -} - -#define MAP_JON_RPC_N(callback_f, command_type) MAP_JON_RPC(command_type::methodname(), callback_f, command_type) - -#define END_JSON_RPC_MAP() \ - epee::json_rpc::error_response rsp; \ - rsp.id = id_; \ - rsp.jsonrpc = "2.0"; \ - rsp.method = callback_name; \ - rsp.error.code = -32601; \ - rsp.error.message = "Method not found"; \ - epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ - LOG_PRINT_L4("[JSON_RESPONSE_BODY]: " << ENDL << query_info.m_body); \ - return true; \ - } - - diff --git a/src/contrib/epee/include/net/http_server_impl_base.h b/src/contrib/epee/include/net/http_server_impl_base.h deleted file mode 100644 index c02475c..0000000 --- a/src/contrib/epee/include/net/http_server_impl_base.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - - -#include -#include - -#include "net/http_server_cp2.h" -#include "net/http_server_handlers_map2.h" - -namespace epee -{ - - template - class http_server_impl_base: public net_utils::http::i_http_server_handler - { - - public: - http_server_impl_base() - : m_net_server() - {} - - explicit http_server_impl_base(boost::asio::io_service& external_io_service) - : m_net_server(external_io_service) - {} - - bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0") - { - - //set self as callback handler - m_net_server.get_config_object().m_phandler = static_cast(this); - - //here set folder for hosting reqests - m_net_server.get_config_object().m_folder = ""; - - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip); - if(!res) - { - LOG_ERROR("Failed to bind server"); - return false; - } - return true; - } - - bool run(size_t threads_count, bool wait = true) - { - //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(threads_count, wait)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool timed_wait_server_stop(uint64_t ms) - { - return m_net_server.timed_wait_server_stop(ms); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - int get_binded_port() - { - return m_net_server.get_binded_port(); - } - - protected: - net_utils::boosted_tcp_server > m_net_server; - }; -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/http_server_thread_per_connect.h b/src/contrib/epee/include/net/http_server_thread_per_connect.h deleted file mode 100644 index bec43b7..0000000 --- a/src/contrib/epee/include/net/http_server_thread_per_connect.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server.h" -#include "http_server.h" - -namespace epee -{ -namespace net_utils -{ - typedef abstract_tcp_server mt_http_server_file_system; - typedef abstract_tcp_server mt_http_server_custum_handling; - -} -} - - -#endif - - diff --git a/src/contrib/epee/include/net/levin_base.h b/src/contrib/epee/include/net/levin_base.h deleted file mode 100644 index 4f55b0d..0000000 --- a/src/contrib/epee/include/net/levin_base.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_BASE_H_ -#define _LEVIN_BASE_H_ - -#include "net_utils_base.h" - -#define LEVIN_SIGNATURE 0x0101010101012101LL //Bender's nightmare - -namespace epee -{ -namespace levin -{ -#pragma pack(push) -#pragma pack(1) - struct bucket_head - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_reservedA; //probably some flags in future - uint32_t m_reservedB; //probably some check sum in future - }; -#pragma pack(pop) - - -#pragma pack(push) -#pragma pack(1) - struct bucket_head2 - { - uint64_t m_signature; - uint64_t m_cb; - bool m_have_to_return_data; - uint32_t m_command; - int32_t m_return_code; - uint32_t m_flags; - uint32_t m_protocol_version; - }; -#pragma pack(pop) - - -#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED 0 -#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default - -#define LEVIN_PACKET_REQUEST 0x00000001 -#define LEVIN_PACKET_RESPONSE 0x00000002 - - -#define LEVIN_PROTOCOL_VER_0 0 -#define LEVIN_PROTOCOL_VER_1 1 - - template - struct levin_commands_handler - { - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out, t_connection_context& context)=0; - virtual int notify(int command, const std::string& in_buff, t_connection_context& context)=0; - virtual void callback(t_connection_context& context){}; - - virtual void on_connection_new(t_connection_context& context){}; - virtual void on_connection_close(t_connection_context& context){}; - - }; - -#define LEVIN_OK 0 -#define LEVIN_ERROR_CONNECTION -1 -#define LEVIN_ERROR_CONNECTION_NOT_FOUND -2 -#define LEVIN_ERROR_CONNECTION_DESTROYED -3 -#define LEVIN_ERROR_CONNECTION_TIMEDOUT -4 -#define LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL -5 -#define LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED -6 -#define LEVIN_ERROR_FORMAT -7 -#define LEVIN_ERROR_EXCEPTION -8 -#define LEVIN_ERROR_UNKNOWN_ERROR -9 -#define LEVIN_ERROR_INTERNAL -10 -#define LEVIN_ERROR_PROTOCOL_INCONSISTENT -11 -#define LEVIN_ERROR_NET_ERROR -12 -#define LEVIN_ERROR_SIGNATURE_MISMATCH -13 - -#define DESCRIBE_RET_CODE(code) case code: return #code; - inline - const char* get_err_descr(int err) - { - switch(err) - { - DESCRIBE_RET_CODE(LEVIN_OK); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NOT_FOUND); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_DESTROYED); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_TIMEDOUT); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL); - DESCRIBE_RET_CODE(LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED); - DESCRIBE_RET_CODE(LEVIN_ERROR_FORMAT); - default: - return "unknown code"; - } - } - - -} -} - - -#endif //_LEVIN_BASE_H_ diff --git a/src/contrib/epee/include/net/levin_client.h b/src/contrib/epee/include/net/levin_client.h deleted file mode 100644 index 335f6ba..0000000 --- a/src/contrib/epee/include/net/levin_client.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - - -#ifndef _LEVIN_CLIENT_H_ -#define _LEVIN_CLIENT_H_ - -#include "net_helper.h" -#include "levin_base.h" - - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - -namespace epee -{ -namespace levin -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl - { - public: - levin_client_impl(); - virtual ~levin_client_impl(); - - bool connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip = "0.0.0.0"); - bool is_connected(); - bool disconnect(); - - virtual int invoke(int command, const std::string& in_buff, std::string& buff_out); - virtual int notify(int command, const std::string& in_buff); - - protected: - net_utils::blocked_mode_client m_transport; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class levin_client_impl2: public levin_client_impl - { - public: - - int invoke(int command, const std::string& in_buff, std::string& buff_out); - int notify(int command, const std::string& in_buff); - }; - -} -namespace net_utils -{ - typedef levin::levin_client_impl levin_client; - typedef levin::levin_client_impl2 levin_client2; -} -} - -#include "levin_client.inl" - -#endif //_LEVIN_CLIENT_H_ diff --git a/src/contrib/epee/include/net/levin_client.inl b/src/contrib/epee/include/net/levin_client.inl deleted file mode 100644 index 6f7c473..0000000 --- a/src/contrib/epee/include/net/levin_client.inl +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -#include "string_tools.h" -namespace epee -{ -namespace levin -{ -inline -bool levin_client_impl::connect(u_long ip, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(string_tools::get_ip_string_from_int32(ip), port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline - bool levin_client_impl::connect(const std::string& addr, int port, unsigned int timeout, const std::string& bind_ip) -{ - return m_transport.connect(addr, port, timeout, timeout, bind_ip); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::is_connected() -{ - return m_transport.is_connected(); -} -//------------------------------------------------------------------------------ -inline -bool levin_client_impl::disconnect() -{ - return m_transport.disconnect(); -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::levin_client_impl() -{ -} -//------------------------------------------------------------------------------ -inline -levin_client_impl::~levin_client_impl() -{ - disconnect(); -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = command; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - std::string local_buff; - if(!m_transport.recv_n(local_buff, sizeof(bucket_head))) - return -1; - - head = *(bucket_head*)local_buff.data(); - - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_PRINT_L0("Signature missmatch in response"); - return -1; - } - - if(!m_transport.recv_n(buff_out, head.m_cb)) - return -1; - - return head.m_return_code; -} -//------------------------------------------------------------------------------ -inline -int levin_client_impl::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::invoke(int command, const std::string& in_buff, std::string& buff_out) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_command = static_cast(command); - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - if(!m_transport.send(&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - //Since other side of connection could be running by async server, - //we can receive some unexpected notify(forwarded broadcast notifications for example). - //let's ignore every notify in the channel until we get invoke response - std::string local_buff; - - while (true) - { - if (!m_transport.recv_n(local_buff, sizeof(bucket_head2))) - return LEVIN_ERROR_NET_ERROR; - - head = *(bucket_head2*)local_buff.data(); - if (head.m_signature != LEVIN_SIGNATURE) - { - LOG_PRINT_L0("Signature missmatch in response"); - return LEVIN_ERROR_SIGNATURE_MISMATCH; - } - if (!m_transport.recv_n(buff_out, head.m_cb)) - return LEVIN_ERROR_NET_ERROR; - - //now check if this is response to invoke (and extra validate if it's response to this(!) invoke) - if (head.m_flags&LEVIN_PACKET_RESPONSE) - { - //we got response, extra validate if its response to our request - CHECK_AND_ASSERT_MES(head.m_command == static_cast(command), LEVIN_ERROR_PROTOCOL_INCONSISTENT, "command id missmatch in response: " << head.m_command << ", expected: " << command); - return head.m_return_code; - } - } - //never comes here - return LEVIN_ERROR_INTERNAL; -} -//------------------------------------------------------------------------------ -inline - int levin_client_impl2::notify(int command, const std::string& in_buff) -{ - if(!is_connected()) - return -1; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - - if(!m_transport.send((const char*)&head, sizeof(head))) - return -1; - - if(!m_transport.send(in_buff)) - return -1; - - return 1; -} - -} -} -//------------------------------------------------------------------------------ \ No newline at end of file diff --git a/src/contrib/epee/include/net/levin_client_async.h b/src/contrib/epee/include/net/levin_client_async.h deleted file mode 100644 index 9e76cd5..0000000 --- a/src/contrib/epee/include/net/levin_client_async.h +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -#include "" -#include "net_helper.h" -#include "levin_base.h" - - -namespace epee -{ -namespace levin -{ - - /************************************************************************ - * levin_client_async - probably it is not really fast implementation, - * each handler thread could make up to 30 ms latency. - * But, handling events in reader thread will cause dead locks in - * case of recursive call (call invoke() to the same connection - * on reader thread on remote invoke() handler) - ***********************************************************************/ - - - class levin_client_async - { - levin_commands_handler* m_pcommands_handler; - volatile uint32_t m_is_stop; - volatile uint32_t m_threads_count; - ::critical_section m_send_lock; - - std::string m_local_invoke_buff; - ::critical_section m_local_invoke_buff_lock; - volatile int m_invoke_res; - - volatile uint32_t m_invoke_data_ready; - volatile uint32_t m_invoke_is_active; - - boost::mutex m_invoke_event; - boost::condition_variable m_invoke_cond; - size_t m_timeout; - - ::critical_section m_recieved_packets_lock; - struct packet_entry - { - bucket_head m_hd; - std::string m_body; - uint32_t m_connection_index; - }; - std::list m_recieved_packets; - /* - m_current_connection_index needed when some connection was broken and reconnected - in this - case we could have some received packets in que, which shoud not be handled - */ - volatile uint32_t m_current_connection_index; - ::critical_section m_invoke_lock; - ::critical_section m_reciev_packet_lock; - ::critical_section m_connection_lock; - net_utils::blocked_mode_client m_transport; - public: - levin_client_async():m_pcommands_handler(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - levin_client_async(const levin_client_async& /*v*/):m_pcommands_handler(NULL), m_is_stop(0), m_threads_count(0), m_invoke_data_ready(0), m_invoke_is_active(0) - {} - ~levin_client_async() - { - boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1); - disconnect(); - - - while(boost::interprocess::ipcdetail::atomic_read32(&m_threads_count)) - ::Sleep(100); - } - - void set_handler(levin_commands_handler* phandler) - { - m_pcommands_handler = phandler; - } - - bool connect(uint32_t ip, uint32_t port, uint32_t timeout) - { - loop_call_guard(); - critical_region cr(m_connection_lock); - - m_timeout = timeout; - bool res = false; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock); - CRITICAL_REGION_BEGIN(m_send_lock); - res = levin_client_impl::connect(ip, port, timeout); - boost::interprocess::ipcdetail::atomic_inc32(&m_current_connection_index); - CRITICAL_REGION_END(); - CRITICAL_REGION_END(); - if(res && !boost::interprocess::ipcdetail::atomic_read32(&m_threads_count) ) - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 0);//m_is_stop = false; - boost::thread( boost::bind(&levin_duplex_client::reciever_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - boost::thread( boost::bind(&levin_duplex_client::handler_thread, this) ); - } - - return res; - } - bool is_connected() - { - loop_call_guard(); - critical_region cr(m_cs); - return levin_client_impl::is_connected(); - } - - inline - bool check_connection() - { - loop_call_guard(); - critical_region cr(m_cs); - - if(!is_connected()) - { - if( !reconnect() ) - { - LOG_ERROR("Reconnect Failed. Failed to invoke() becouse not connected!"); - return false; - } - } - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, char* pbuff, size_t cb) - { - while(cb) - { - int res = ::recv(m_socket, pbuff, (int)cb, 0); - - if(SOCKET_ERROR == res) - { - if(!m_connected) - return false; - - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - //reconnect(); - return false; - }else if(res == 0) - { - disconnect(); - //reconnect(); - return false; - } - LOG_PRINT_L4("[" << m_socket <<"] RECV " << res); - cb -= res; - pbuff += res; - } - - return true; - } - - //------------------------------------------------------------------------------ - inline - bool recv_n(SOCKET s, std::string& buff) - { - size_t cb_remain = buff.size(); - char* m_current_ptr = (char*)buff.data(); - return recv_n(s, m_current_ptr, cb_remain); - } - - bool disconnect() - { - //boost::interprocess::ipcdetail::atomic_write32(&m_is_stop, 1);//m_is_stop = true; - loop_call_guard(); - critical_region cr(m_cs); - levin_client_impl::disconnect(); - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.clear(); - m_invoke_res = LEVIN_ERROR_CONNECTION_DESTROYED; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - return true; - } - - void loop_call_guard() - { - - } - - void on_leave_invoke() - { - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 0); - } - - int invoke(const GUID& target, int command, const std::string& in_buff, std::string& buff_out) - { - - critical_region cr_invoke(m_invoke_lock); - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_is_active, 1); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 0); - misc_utils::destr_ptr hdlr = misc_utils::add_exit_scope_handler(boost::bind(&levin_duplex_client::on_leave_invoke, this)); - - loop_call_guard(); - - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - LOG_PRINT("[" << m_socket <<"] Sending invoke data", LOG_LEVEL_4); - - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - //hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles. - boost::system_time timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - size_t timeout_count = 0; - boost::unique_lock lock(m_invoke_event); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_data_ready)) - { - if(!m_invoke_cond.timed_wait(lock, timeout)) - { - if(timeout_count < 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::milliseconds(100); - ++timeout_count; - continue; - }else if(timeout_count == 10) - { - //workaround to avoid freezing at timed_wait called after notify_all. - timeout = boost::get_system_time()+ boost::posix_time::minutes(10); - ++timeout_count; - continue; - }else - { - LOG_PRINT("[" << m_socket <<"] Timeout on waiting invoke result. ", LOG_LEVEL_0); - //disconnect(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - } - } - - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - buff_out.swap(m_local_invoke_buff); - m_local_invoke_buff.clear(); - CRITICAL_REGION_END(); - return m_invoke_res; - } - - int notify(const GUID& target, int command, const std::string& in_buff) - { - if(!check_connection()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = false; - head.m_id = target; -#ifdef TRACE_LEVIN_PACKETS_BY_GUIDS - ::UuidCreate(&head.m_id); -#endif - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket <<"] SEND " << sizeof(head)); - int res = ::send(m_socket, (const char*)&head, sizeof(head), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - LOG_PRINT_L4("[" << m_socket <<"] SEND " << (int)in_buff.size()); - res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); - if(SOCKET_ERROR == res) - { - int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\""); - disconnect(); - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - return 1; - } - - - private: - bool have_some_data(SOCKET sock, int interval = 1) - { - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); - - fd_set fdse; - FD_ZERO(&fdse); - FD_SET(sock, &fdse); - - - timeval tv; - tv.tv_sec = interval; - tv.tv_usec = 0; - - int sel_res = select(0, &fds, 0, &fdse, &tv); - if(0 == sel_res) - return false; - else if(sel_res == SOCKET_ERROR) - { - if(m_is_stop) - return false; - int err_code = ::WSAGetLastError(); - LOG_ERROR("Filed to call select, err code = " << err_code); - disconnect(); - }else - { - if(fds.fd_array[0]) - {//some read operations was performed - return true; - }else if(fdse.fd_array[0]) - {//some error was at the socket - return true; - } - } - return false; - } - - - bool reciev_and_process_incoming_data() - { - bucket_head head = {0}; - uint32_t conn_index = 0; - bool is_request = false; - std::string local_buff; - CRITICAL_REGION_BEGIN(m_reciev_packet_lock);//to protect from socket reconnect between head and body - - if(!recv_n(m_socket, (char*)&head, sizeof(head))) - { - if(m_is_stop) - return false; - LOG_ERROR("Failed to recv_n"); - return false; - } - - conn_index = boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index); - - if(head.m_signature!=LEVIN_SIGNATURE) - { - LOG_ERROR("Signature missmatch in response"); - return false; - } - - is_request = (head.m_protocol_version == LEVIN_PROTOCOL_VER_1 && head.m_flags&LEVIN_PACKET_REQUEST); - - - local_buff.resize((size_t)head.m_cb); - if(!recv_n(m_socket, local_buff)) - { - if(m_is_stop) - return false; - LOG_ERROR("Filed to reciev"); - return false; - } - CRITICAL_REGION_END(); - - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - if(is_request) - { - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - m_recieved_packets.resize(m_recieved_packets.size() + 1); - m_recieved_packets.back().m_hd = head; - m_recieved_packets.back().m_body.swap(local_buff); - m_recieved_packets.back().m_connection_index = conn_index; - CRITICAL_REGION_END(); - /* - - */ - }else - {//this is some response - - CRITICAL_REGION_BEGIN(m_local_invoke_buff_lock); - m_local_invoke_buff.swap(local_buff); - m_invoke_res = head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_data_ready, 1); //m_invoke_data_ready = true; - m_invoke_cond.notify_all(); - - } - return true; - } - - bool reciever_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - if(!m_connected) - { - Sleep(100); - continue; - } - - if(have_some_data(m_socket, 1)) - { - if(!reciev_and_process_incoming_data()) - { - if(m_is_stop) - { - break;//boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //return true; - } - LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); - //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - //disconnect_no_wait(); - //break; - } - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - - bool process_recieved_packet(bucket_head& head, const std::string& local_buff, uint32_t conn_index) - { - - net_utils::connection_context_base conn_context; - conn_context.m_remote_ip = m_ip; - conn_context.m_remote_port = m_port; - if(head.m_have_to_return_data) - { - std::string return_buff; - if(m_pcommands_handler) - head.m_return_code = m_pcommands_handler->invoke(head.m_id, head.m_command, local_buff, return_buff, conn_context); - else - head.m_return_code = LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; - - - - head.m_cb = return_buff.size(); - head.m_have_to_return_data = false; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_RESPONSE; - - std::string send_buff((const char*)&head, sizeof(head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(conn_index != boost::interprocess::ipcdetail::atomic_read32(&m_current_connection_index)) - {//there was reconnect, send response back is not allowed - return true; - } - int res = ::send(m_socket, (const char*)send_buff.data(), send_buff.size(), 0); - if(res == SOCKET_ERROR) - { - int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); - return false; - } - CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); - - } - else - { - if(m_pcommands_handler) - m_pcommands_handler->notify(head.m_id, head.m_command, local_buff, conn_context); - } - - return true; - } - - bool handler_thread() - { - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); - log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER"); - boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); - - while(!m_is_stop) - { - bool have_some_work = false; - std::string local_buff; - bucket_head bh = {0}; - uint32_t conn_index = 0; - - CRITICAL_REGION_BEGIN(m_recieved_packets_lock); - if(m_recieved_packets.size()) - { - bh = m_recieved_packets.begin()->m_hd; - conn_index = m_recieved_packets.begin()->m_connection_index; - local_buff.swap(m_recieved_packets.begin()->m_body); - have_some_work = true; - m_recieved_packets.pop_front(); - } - CRITICAL_REGION_END(); - - if(have_some_work) - { - process_recieved_packet(bh, local_buff, conn_index); - }else - { - //Idle when no work - Sleep(30); - } - } - - boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket <<"] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]"); - return true; - } - }; - -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/levin_client_async.inl b/src/contrib/epee/include/net/levin_client_async.inl deleted file mode 100644 index e69de29..0000000 diff --git a/src/contrib/epee/include/net/levin_helper.h b/src/contrib/epee/include/net/levin_helper.h deleted file mode 100644 index a840610..0000000 --- a/src/contrib/epee/include/net/levin_helper.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "levin_base.h" -#include "serializeble_struct_helper.h" - -namespace epee -{ -namespace levin -{ - template - bool pack_struct_to_levin_message(const t_struct& t, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - std::string buff_strg; - if(!StorageNamed::save_struct_as_storage_to_buff_t(t, buff_strg)) - return false; - - head.m_cb = buff_strg.size(); - buff.append(buff_strg); - return true; - } - - - bool pack_data_to_levin_message(const std::string& data, std::string& buff, int command_id) - { - buff.resize(sizeof(levin::bucket_head)); - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = 0; - head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; - head.m_reservedA = rand(); //probably some flags in future - head.m_reservedB = rand(); //probably some check summ in future - - head.m_cb = data.size(); - buff.append(data); - return true; - } - - bool load_levin_data_from_levin_message(std::string& levin_data, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_PRINT_L3("sizes missmatch, at load_struct_from_levin_message"); - return false; - } - - //std::string buff_strg; - levin_data.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - command = head.m_command; - return true; - } - - template - bool load_struct_from_levin_message(t_struct& t, const std::string& buff, int& command) - { - if(buff.size() < sizeof(levin::bucket_head) ) - { - LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); - return false; - } - - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - if(head.m_signature != LEVIN_SIGNATURE) - { - LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); - return false; - } - if(head.m_cb != buff.size()-sizeof(levin::bucket_head)) - { - LOG_ERROR("sizes missmatch, at load_struct_from_levin_message"); - return false; - } - - std::string buff_strg; - buff_strg.assign(&buff[sizeof(levin::bucket_head)], buff.size()-sizeof(levin::bucket_head)); - - if(!StorageNamed::load_struct_from_storage_buff_t(t, buff_strg)) - { - LOG_ERROR("Failed to read storage, at load_struct_from_levin_message"); - return false; - } - command = head.m_command; - return true; - } -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/levin_protocol_handler.h b/src/contrib/epee/include/net/levin_protocol_handler.h deleted file mode 100644 index e693d2f..0000000 --- a/src/contrib/epee/include/net/levin_protocol_handler.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _LEVIN_PROTOCOL_HANDLER_H_ -#define _LEVIN_PROTOCOL_HANDLER_H_ - -#include -#include "levin_base.h" - - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "net_protocol" - -namespace epee -{ -namespace levin -{ - template - struct protocl_handler_config - { - levin_commands_handler* m_pcommands_handler; - }; - - template - class protocol_handler - { - public: - typedef t_connection_context connection_context; - typedef protocl_handler_config config_type; - - protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context); - virtual ~protocol_handler(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - enum connection_data_state - { - conn_state_reading_head, - conn_state_reading_body - }; - - - config_type& m_config; - t_connection_context& m_conn_context; - net_utils::i_service_endpoint* m_psnd_hndlr; - std::string m_cach_in_buffer; - connection_data_state m_state; - bucket_head m_current_head; - }; - - template - protocol_handler::protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context): - m_config(config), - m_conn_context(conn_context), - m_psnd_hndlr(psnd_hndlr), - m_state(conn_state_reading_head), - m_current_head(bucket_head()) - {} - - template - bool protocol_handler::handle_recv(const void* ptr, size_t cb) - { - if(!m_config.m_pcommands_handler) - { - LOG_ERROR("Command handler not set!"); - return false; - } - m_cach_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case conn_state_reading_head: - if(m_cach_in_buffer.size() < sizeof(bucket_head)) - { - if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) - { - LOG_ERROR("Signature missmatch on accepted connection"); - return false; - } - is_continue = false; - break; - } - { - bucket_head* phead = (bucket_head*)m_cach_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_ERROR("Signature missmatch on accepted connection"); - return false; - } - m_current_head = *phead; - } - m_cach_in_buffer.erase(0, sizeof(bucket_head)); - m_state = conn_state_reading_body; - break; - case conn_state_reading_body: - if(m_cach_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - break; - } - { - std::string buff_to_invoke; - if(m_cach_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cach_in_buffer); - else - { - buff_to_invoke.assign(m_cach_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cach_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke(m_current_head.m_command, buff_to_invoke, return_buff, m_conn_context); - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - - if(!m_psnd_hndlr->do_send(send_buff.data(), send_buff.size())) - return false; - - } - else - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_conn_context); - } - m_state = conn_state_reading_head; - break; - default: - LOG_ERROR("Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } -} -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - - -#endif //_LEVIN_PROTOCOL_HANDLER_H_ - diff --git a/src/contrib/epee/include/net/levin_protocol_handler_async.h b/src/contrib/epee/include/net/levin_protocol_handler_async.h deleted file mode 100644 index c3cdd02..0000000 --- a/src/contrib/epee/include/net/levin_protocol_handler_async.h +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright (c) 2019, anonimal -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include -#include - -#include -#include -#include - -#include "levin_base.h" -#include "misc_language.h" -#include "profile_tools.h" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "levin_protocol" -ENABLE_CHANNEL_BY_DEFAULT("levin_protocol"); - -namespace epee -{ -namespace levin -{ - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler; - -template -class async_protocol_handler_config -{ - typedef std::unordered_map* , boost::hash > connections_map; - critical_section m_connects_lock; - std::atomic m_is_in_sendstop_loop; - connections_map m_connects; - - void add_connection(async_protocol_handler* pc); - void del_connection(async_protocol_handler* pc); - - async_protocol_handler* find_connection(boost::uuids::uuid connection_id) const; - int find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph); - - friend class async_protocol_handler; - -public: - typedef t_connection_context connection_context; - levin_commands_handler* m_pcommands_handler; - uint64_t m_max_packet_size; - uint64_t m_invoke_timeout; - - void on_send_stop_signal(); - int invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id); - template - int invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t& cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED); - - int notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id); - bool close(boost::uuids::uuid connection_id); - bool update_connection_context(const t_connection_context& contxt); - bool request_callback(boost::uuids::uuid connection_id); - template - bool foreach_connection(callback_t cb); - size_t get_connections_count(); - - async_protocol_handler_config() :m_pcommands_handler(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_is_in_sendstop_loop(false), m_invoke_timeout{} - {} - ~async_protocol_handler_config() - { - NESTED_TRY_ENTRY(); - - CRITICAL_REGION_LOCAL(m_connects_lock); - m_connects.clear(); - - NESTED_CATCH_ENTRY(__func__); - } -}; - - -/************************************************************************/ -/* */ -/************************************************************************/ -template -class async_protocol_handler -{ -public: - typedef t_connection_context connection_context; - typedef async_protocol_handler_config config_type; - - enum stream_state - { - stream_state_head, - stream_state_body - }; - - std::atomic m_deletion_initiated; - std::atomic m_protocol_released; - volatile uint32_t m_invoke_buf_ready; - - volatile int m_invoke_result_code; - - critical_section m_local_inv_buff_lock; - std::string m_local_inv_buff; - - critical_section m_send_lock; - critical_section m_call_lock; - - volatile uint32_t m_wait_count; - volatile uint32_t m_close_called; - bucket_head2 m_current_head; - net_utils::i_service_endpoint* m_pservice_endpoint; - config_type& m_config; - t_connection_context& m_connection_context; - - std::string m_cache_in_buffer; - stream_state m_state; - - int32_t m_oponent_protocol_ver; - bool m_connection_initialized; - - struct invoke_response_handler_base - { - virtual bool handle(int res, const std::string& buff, connection_context& context)=0; - virtual bool is_timer_started() const=0; - virtual void cancel()=0; - virtual bool cancel_timer()=0; - }; - template - struct invoke_handler: invoke_response_handler_base - { - invoke_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command) - :m_cb(cb), m_con(con), m_timer(con.m_pservice_endpoint->get_io_service()), m_timer_started(false), - m_cancel_timer_called(false), m_timer_cancelled(false), m_command(command) - { - if(m_con.start_outer_call()) - { - m_timer.expires_from_now(boost::posix_time::milliseconds(timeout)); - m_timer.async_wait([&con, command, cb](const boost::system::error_code& ec) - { - if(ec == boost::asio::error::operation_aborted) - return; - LOG_PRINT_CC(con.get_context_ref(), "Timeout on invoke operation happened, command: " << command, LOG_LEVEL_2); - std::string fake; - cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); - con.close(); - con.finish_outer_call(); - }); - m_timer_started = true; - } - } - virtual ~invoke_handler() - {} - callback_t m_cb; - async_protocol_handler& m_con; - boost::asio::deadline_timer m_timer; - bool m_timer_started; - std::atomic m_cancel_timer_called; - bool m_timer_cancelled; - int m_command; - virtual bool handle(int res, const std::string& buff, typename async_protocol_handler::connection_context& context) - { - if(!cancel_timer()) - return false; - m_cb(res, buff, context); - m_con.finish_outer_call(); - return true; - } - virtual bool is_timer_started() const - { - return m_timer_started; - } - virtual void cancel() - { - if(cancel_timer()) - { - std::string fake; - m_cb(LEVIN_ERROR_CONNECTION_DESTROYED, fake, m_con.get_context_ref()); - m_con.finish_outer_call(); - } - } - virtual bool cancel_timer() - { - if(!m_cancel_timer_called) - { - m_cancel_timer_called = true; - boost::system::error_code ignored_ec; - m_timer_cancelled = 1 == m_timer.cancel(ignored_ec); - } - return m_timer_cancelled; - } - }; - critical_section m_invoke_response_handlers_lock; - std::list > m_invoke_response_handlers; - - template - bool add_invoke_response_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command) - { - CRITICAL_REGION_LOCAL(m_invoke_response_handlers_lock); - if (m_protocol_released) - { - LOG_PRINT_L0("ERROR: Adding response handler to a released object"); - return false; - } - boost::shared_ptr handler(boost::make_shared>(cb, timeout, con, command)); - m_invoke_response_handlers.push_back(handler); - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] INVOKE_HANDLER_QUE: PUSH_BACK RESPONSE HANDLER"); - return handler->is_timer_started(); - } - template friend struct invoke_handler; -public: - async_protocol_handler(net_utils::i_service_endpoint* psnd_hndlr, - config_type& config, - t_connection_context& conn_context): - m_invoke_buf_ready{}, - m_invoke_result_code{}, - m_current_head(bucket_head2()), - m_pservice_endpoint(psnd_hndlr), - m_config(config), - m_connection_context(conn_context), - m_state(stream_state_head) - { - m_close_called = 0; - m_deletion_initiated = false; - m_protocol_released = false; - m_wait_count = 0; - m_oponent_protocol_ver = 0; - m_connection_initialized = false; - LOG_PRINT_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "] CONSTRUCTED", LOG_LEVEL_4); - } - - virtual ~async_protocol_handler() - { - NESTED_TRY_ENTRY(); - - m_deletion_initiated = true; - if(m_connection_initialized) - { - m_config.del_connection(this); - } - - for (size_t i = 0; i < 60 * 1000 / 100 && 0 != boost::interprocess::ipcdetail::atomic_read32(&m_wait_count); ++i) - { - misc_utils::sleep_no_w(100); - } - CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); - - LOG_PRINT_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "] DESTRUCTING", LOG_LEVEL_4); - - VALIDATE_MUTEX_IS_FREE(m_local_inv_buff_lock); - VALIDATE_MUTEX_IS_FREE(m_send_lock); - VALIDATE_MUTEX_IS_FREE(m_call_lock); - VALIDATE_MUTEX_IS_FREE(m_invoke_response_handlers_lock); - - NESTED_CATCH_ENTRY(__func__); - } - - bool start_outer_call() - { - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] -->> start_outer_call"); - if(!m_pservice_endpoint->add_ref()) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "] -->> start_outer_call failed", LOG_LEVEL_4); - return false; - } - boost::interprocess::ipcdetail::atomic_inc32(&m_wait_count); - return true; - } - bool finish_outer_call() - { - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] <<-- finish_outer_call"); - boost::interprocess::ipcdetail::atomic_dec32(&m_wait_count); - m_pservice_endpoint->release(); - return true; - } - - bool release_protocol() - { - decltype(m_invoke_response_handlers) local_invoke_response_handlers; - CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock); - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] INVOKE_HANDLER_QUE: Invoke response_handlers(" << m_invoke_response_handlers.size() <<") swap, protocol released"); - local_invoke_response_handlers.swap(m_invoke_response_handlers); - m_protocol_released = true; - CRITICAL_REGION_END(); - - // Never call callback inside critical section, that can cause deadlock. Callback can be called when - // invoke_response_handler_base is cancelled - std::for_each(local_invoke_response_handlers.begin(), local_invoke_response_handlers.end(), [](const boost::shared_ptr& pinv_resp_hndlr) { - pinv_resp_hndlr->cancel(); - }); - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] Invoke response_handlers(" << local_invoke_response_handlers.size() << ") canceled"); - return true; - } - - bool close() - { - boost::interprocess::ipcdetail::atomic_inc32(&m_close_called); - - m_pservice_endpoint->close(); - return true; - } - - void update_connection_context(const connection_context& contxt) - { - m_connection_context = contxt; - } - - void request_callback() - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - m_pservice_endpoint->request_callback(); - } - - void handle_qued_callback() - { - m_config.m_pcommands_handler->callback(m_connection_context); - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - if(boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - return false; //closing connections - - //update threads name to see connection context where errors came from - std::string original_prefix = epee::log_space::log_singletone::get_thread_log_prefix(); - epee::log_space::log_singletone::set_thread_log_prefix(original_prefix + "[" + epee::net_utils::print_connection_context_short(m_connection_context) + "]"); - ON_EXIT([&](){epee::log_space::log_singletone::set_thread_log_prefix(original_prefix); }); - - //create_scope_leave_handler() - - if(!m_config.m_pcommands_handler) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Commands handler not set!"); - return false; - } - - if(m_cache_in_buffer.size() + cb > m_config.m_max_packet_size) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet received " << m_cache_in_buffer.size() + cb - << ", connection will be closed."); - return false; - } - - m_cache_in_buffer.append((const char*)ptr, cb); - - bool is_continue = true; - while(is_continue) - { - switch(m_state) - { - case stream_state_body: - if(m_cache_in_buffer.size() < m_current_head.m_cb) - { - is_continue = false; - break; - } - { - std::string buff_to_invoke; - if(m_cache_in_buffer.size() == m_current_head.m_cb) - buff_to_invoke.swap(m_cache_in_buffer); - else - { - buff_to_invoke.assign(m_cache_in_buffer, 0, (std::string::size_type)m_current_head.m_cb); - m_cache_in_buffer.erase(0, (std::string::size_type)m_current_head.m_cb); - } - - bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE); - - - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] RECIEVED PACKET [" << (is_response ? ("RESP"):(m_current_head.m_have_to_return_data? "-->INVOKE":"-->NOTIFY")) << "][len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", v=" << m_current_head.m_protocol_version); - - if(is_response) - {//response to some invoke - CRITICAL_REGION_LOCAL_VAR(m_invoke_response_handlers_lock, invoke_response_handlers_guard); - if(!m_invoke_response_handlers.empty()) - {//async call scenario - boost::shared_ptr response_handler = m_invoke_response_handlers.front(); - bool timer_cancelled = response_handler->cancel_timer(); - - if (timer_cancelled) - { - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] INVOKE_HANDLER_QUE: POP_FRONT"); - m_invoke_response_handlers.pop_front(); - } - invoke_response_handlers_guard.unlock();//manual unlock(this type of guard let manual unlock) - - if(timer_cancelled) - response_handler->handle(m_current_head.m_return_code, buff_to_invoke, m_connection_context); - } - else - { - invoke_response_handlers_guard.unlock();//manual unlock(this type of guard let manual unlock) - //use sync call scenario - if(!boost::interprocess::ipcdetail::atomic_read32(&m_wait_count) && !boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) - { - if(!m_protocol_released) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]no active invoke when response came, wtf?"); - } - return false; - }else - { - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_to_invoke.swap(m_local_inv_buff); - buff_to_invoke.clear(); - m_invoke_result_code = m_current_head.m_return_code; - CRITICAL_REGION_END(); - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 1); - } - } - }else - { - if(m_current_head.m_have_to_return_data) - { - std::string return_buff; - TIME_MEASURE_START_MS(invoke_handle_time); - m_current_head.m_return_code = m_config.m_pcommands_handler->invoke( - m_current_head.m_command, - buff_to_invoke, - return_buff, - m_connection_context); - TIME_MEASURE_FINISH_MS(invoke_handle_time); - LOG_PRINT_CC_L3(m_connection_context, "[LEVIN_PROTOCOL" << this << "] INVOKE HANDLER: " << invoke_handle_time << "ms, command: " << m_current_head.m_command); - if (invoke_handle_time > m_config.m_invoke_timeout / 2) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "] LONG INVOKE HANDLER: " << invoke_handle_time << "ms, command: " << m_current_head.m_command, LOG_LEVEL_0); - } - - m_current_head.m_cb = return_buff.size(); - m_current_head.m_have_to_return_data = false; - m_current_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - m_current_head.m_flags = LEVIN_PACKET_RESPONSE; - std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); - send_buff += return_buff; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) - return false; - CRITICAL_REGION_END(); - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] PACKET_SENT. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - <<", cmd = " << m_current_head.m_command - << ", ver=" << m_current_head.m_protocol_version); - } - else - { - - TIME_MEASURE_START_MS(notify_handle_time); - m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context); - TIME_MEASURE_FINISH_MS(notify_handle_time); - LOG_PRINT_CC_L3(m_connection_context, "[LEVIN_PROTOCOL" << this << "] NOTIFY HANDLER: " << notify_handle_time << "ms, command: " << m_current_head.m_command); - if (notify_handle_time > m_config.m_invoke_timeout / 2) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "] LONG NOTIFY HANDLER: " << notify_handle_time << "ms, command: " << m_current_head.m_command, LOG_LEVEL_0); - } - - } - - } - } - m_state = stream_state_head; - break; - case stream_state_head: - { - if(m_cache_in_buffer.size() < sizeof(bucket_head2)) - { - if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) - { - LOG_PRINT_CC_L0(m_connection_context, "[LEVIN_PROTOCOL" << this << "] Signature mismatch, connection will be closed"); - return false; - } - is_continue = false; - break; - } - - bucket_head2* phead = (bucket_head2*)m_cache_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) - { - LOG_PRINT_CC_L0(m_connection_context, "[LEVIN_PROTOCOL" << this << "] Signature mismatch, connection will be closed"); - return false; - } - m_current_head = *phead; - - m_cache_in_buffer.erase(0, sizeof(bucket_head2)); - m_state = stream_state_body; - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] RECEIVED_HEADER(command " << m_current_head.m_command << ")"); - m_oponent_protocol_ver = m_current_head.m_protocol_version; - if(m_current_head.m_cb > m_config.m_max_packet_size) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet header received " << m_current_head.m_cb - << ", connection will be closed."); - return false; - } - } - break; - default: - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); - return false; - } - } - - return true; - } - - bool after_init_connection() - { - if (!m_connection_initialized) - { - m_connection_initialized = true; - m_config.add_connection(this); - } - return true; - } - - template - bool async_invoke(int command, const std::string& in_buff, const callback_t& cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(timeout == LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - timeout = static_cast(m_config.m_invoke_timeout); - - int err_code = LEVIN_OK; - do - { - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - CRITICAL_REGION_LOCAL1(m_invoke_response_handlers_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Failed to do_send", LOG_LEVEL_2); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] SENT_HEADER(command " << command << ")"); - - - //add response handler before do_send of the last - //part of packet, in case if it somehow lead to situation when response - //comes before it return control and response could be handled - //by protocol state machine without proper invoke_response_handler - if (!add_invoke_response_handler(cb, timeout, *this, command)) - { - err_code = LEVIN_ERROR_CONNECTION_DESTROYED; - break; - } - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] ADD_INVOKE_HANDLER(command " << command << ")"); - - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_PRINT_CC_RED(m_connection_context, "Failed to do_send", LOG_LEVEL_2); - err_code = LEVIN_ERROR_CONNECTION; - break; - } - LOG_PRINT_L4("[LEVIN_PROTOCOL" << this << "] SENT_BODY(command " << command << ")"); - - - CRITICAL_REGION_END(); - } while (false); - - if (LEVIN_OK != err_code) - { - std::string stub_buff; - // Never call callback inside critical section, that can cause deadlock - cb(err_code, stub_buff, m_connection_context); - return false; - } - - return true; - } - - int invoke(int command, const std::string& in_buff, std::string& buff_out) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); - head.m_have_to_return_data = true; - - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - - boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_ERROR_CC(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Failed to do_send"); - return LEVIN_ERROR_CONNECTION; - } - CRITICAL_REGION_END(); - - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] PACKET_SENT. [len=" << head.m_cb - << ", f=" << head.m_flags - << ", r?=" << head.m_have_to_return_data - << ", cmd = " << head.m_command - << ", ver=" << head.m_protocol_version); - - uint64_t ticks_start = misc_utils::get_tick_count(); - - while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_deletion_initiated && !m_protocol_released) - { - if(misc_utils::get_tick_count() - ticks_start > m_config.m_invoke_timeout) - { - LOG_PRINT_CC_L2(m_connection_context, "[LEVIN_PROTOCOL" << this << "] invoke timeout (" << m_config.m_invoke_timeout << "), closing connection "); - close(); - return LEVIN_ERROR_CONNECTION_TIMEDOUT; - } - if(!m_pservice_endpoint->call_run_once_service_io()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - } - - if(m_deletion_initiated || m_protocol_released) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_BEGIN(m_local_inv_buff_lock); - buff_out.swap(m_local_inv_buff); - m_local_inv_buff.clear(); - CRITICAL_REGION_END(); - - return m_invoke_result_code; - } - - int notify(int command, const std::string& in_buff) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&async_protocol_handler::finish_outer_call, this)); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - CRITICAL_REGION_LOCAL(m_call_lock); - - if(m_deletion_initiated) - return LEVIN_ERROR_CONNECTION_DESTROYED; - - bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_have_to_return_data = false; - head.m_cb = in_buff.size(); - - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; - CRITICAL_REGION_BEGIN(m_send_lock); - if(!m_pservice_endpoint->do_send(&head, sizeof(head))) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Failed to do_send()", LOG_LEVEL_2); - return -1; - } - - if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) - { - LOG_PRINT_CC_RED(m_connection_context, "[LEVIN_PROTOCOL" << this << "]Failed to do_send()", LOG_LEVEL_2); - return -1; - } - CRITICAL_REGION_END(); - LOG_PRINT_CC_L4(m_connection_context, "[LEVIN_PROTOCOL" << this << "] PACKET_SENT. [len=" << head.m_cb << - ", f=" << head.m_flags << - ", r?=" << head.m_have_to_return_data << - ", cmd = " << head.m_command << - ", ver=" << head.m_protocol_version); - - return 1; - } - //------------------------------------------------------------------------------------------ - boost::uuids::uuid get_connection_id() {return m_connection_context.m_connection_id;} - //------------------------------------------------------------------------------------------ - t_connection_context& get_context_ref() {return m_connection_context;} -}; -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::del_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - //in case if ->close() leads to phisical erasing any connections in the same thread - just ignore it - - if (m_is_in_sendstop_loop == true) - { - //LOG_ERROR("Internal problem on close connections: attempt to erase connection object while on_send_stop_signal loop is working"); - // edit2: as soon as we added local copy of map of pointers in caller function, now we can erase it - LOG_PRINT_L0(" [LEVIN_PROTOCOL_CONFIG]NOTICE: ERASING CONNECTION FROM SAME THREAD (assuming that local copy in caller function should handle it) In case of crush look at this code."); - m_connects.erase(pconn->get_connection_id()); - } - else - { - m_connects.erase(pconn->get_connection_id()); - } - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_close(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::add_connection(async_protocol_handler* pconn) -{ - CRITICAL_REGION_BEGIN(m_connects_lock); - m_connects[pconn->get_connection_id()] = pconn; - CRITICAL_REGION_END(); - m_pcommands_handler->on_connection_new(pconn->m_connection_context); -} -//------------------------------------------------------------------------------------------ -template -async_protocol_handler* async_protocol_handler_config::find_connection(boost::uuids::uuid connection_id) const -{ - auto it = m_connects.find(connection_id); - return it == m_connects.end() ? 0 : it->second; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::find_and_lock_connection(boost::uuids::uuid connection_id, async_protocol_handler*& aph) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - aph = find_connection(connection_id); - if(0 == aph) - return LEVIN_ERROR_CONNECTION_NOT_FOUND; - if(!aph->start_outer_call()) - return LEVIN_ERROR_CONNECTION_DESTROYED; - return LEVIN_OK; -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::invoke(int command, const std::string& in_buff, std::string& buff_out, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->invoke(command, in_buff, buff_out) : r; -} -//------------------------------------------------------------------------------------------ -template template -int async_protocol_handler_config::invoke_async(int command, const std::string& in_buff, boost::uuids::uuid connection_id, const callback_t& cb, size_t timeout) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->async_invoke(command, in_buff, cb, timeout) : r; -} -//------------------------------------------------------------------------------------------ -template template -bool async_protocol_handler_config::foreach_connection(callback_t cb) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - for(auto& c: m_connects) - { - async_protocol_handler* aph = c.second; - if(!cb(aph->get_context_ref())) - return false; - } - return true; -} -//------------------------------------------------------------------------------------------ -template -void async_protocol_handler_config::on_send_stop_signal() -{ - //at the moment we put workaround here, since this sync_handler has collection of connections - CRITICAL_REGION_LOCAL(m_connects_lock); - m_is_in_sendstop_loop = true; - /* Some times aph->close() can lead to call del_connection() wich erase - item from m_connects and this leads to undefined behavior in range-based for loop. - Since connections_map is light container we just do local copy of this for enumeration - */ - connections_map local_lonnects = m_connects; - - for (auto& c : local_lonnects) - { - async_protocol_handler* aph = c.second; - aph->close(); - } - m_is_in_sendstop_loop = false; -} -//------------------------------------------------------------------------------------------ -template -size_t async_protocol_handler_config::get_connections_count() -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - return m_connects.size(); -} -//------------------------------------------------------------------------------------------ -template -int async_protocol_handler_config::notify(int command, const std::string& in_buff, boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - return LEVIN_OK == r ? aph->notify(command, in_buff) : r; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::close(boost::uuids::uuid connection_id) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(connection_id); - return 0 != aph ? aph->close() : false; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::update_connection_context(const t_connection_context& contxt) -{ - CRITICAL_REGION_LOCAL(m_connects_lock); - async_protocol_handler* aph = find_connection(contxt.m_connection_id); - if(0 == aph) - return false; - aph->update_connection_context(contxt); - return true; -} -//------------------------------------------------------------------------------------------ -template -bool async_protocol_handler_config::request_callback(boost::uuids::uuid connection_id) -{ - async_protocol_handler* aph; - int r = find_and_lock_connection(connection_id, aph); - if(LEVIN_OK == r) - { - aph->request_callback(); - return true; - } - else - { - return false; - } -} -} -} - - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - - - - diff --git a/src/contrib/epee/include/net/levin_server_cp.h b/src/contrib/epee/include/net/levin_server_cp.h deleted file mode 100644 index 8ece350..0000000 --- a/src/contrib/epee/include/net/levin_server_cp.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server_cp.h" -#include "levin_protocol_handler.h" -namespace epee -{ -namespace net_utils -{ - typedef cp_server_impl cp_levin_server; -} -} - - - -#endif - - diff --git a/src/contrib/epee/include/net/levin_server_cp2.h b/src/contrib/epee/include/net/levin_server_cp2.h deleted file mode 100644 index b29d49b..0000000 --- a/src/contrib/epee/include/net/levin_server_cp2.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _HTTP_SERVER_CP_H_ -#define _HTTP_SERVER_CP_H_ - -#include "abstract_tcp_server2.h" -#include "levin_protocol_handler.h" -#include "levin_protocol_handler_async.h" - -namespace epee -{ -namespace net_utils -{ - typedef boosted_tcp_server > boosted_levin_server; - typedef boosted_tcp_server > boosted_levin_async_server; -} -} - - - -#endif - - diff --git a/src/contrib/epee/include/net/local_ip.h b/src/contrib/epee/include/net/local_ip.h deleted file mode 100644 index 0d45896..0000000 --- a/src/contrib/epee/include/net/local_ip.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -namespace epee -{ - namespace net_utils - { - inline - bool is_ip_local(uint32_t ip) - { - /* - local ip area - 10.0.0.0 — 10.255.255.255 - 172.16.0.0 — 172.31.255.255 - 192.168.0.0 — 192.168.255.255 - */ - if( (ip | 0xffffff00) == 0xffffff0a) - return true; - - if( (ip | 0xffff0000) == 0xffffa8c0) - return true; - - if( (ip | 0xffffff00) == 0xffffffac) - { - uint32_t second_num = (ip << 8) & 0xff000000; - if(second_num >= 16 && second_num <= 31 ) - return true; - } - return false; - } - inline - bool is_ip_loopback(uint32_t ip) - { - if( (ip | 0xffffff00) == 0xffffff7f) - return true; - //MAKE_IP - /* - loopback ip - 127.0.0.0 — 127.255.255.255 - */ - return false; - } - - } -} - diff --git a/src/contrib/epee/include/net/multiprotocols_server.h b/src/contrib/epee/include/net/multiprotocols_server.h deleted file mode 100644 index 4807a44..0000000 --- a/src/contrib/epee/include/net/multiprotocols_server.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MULTIPROTOCOLS_SERVER_H_ -#define _MULTIPROTOCOLS_SERVER_H_ - -//#include "abstract_tcp_server_cp.h" -#include "protocol_switcher.h" -#include "abstract_tcp_server2.h" - -namespace epee -{ -namespace net_utils -{ - //typedef cp_server_impl multiprotocol_server; - typedef boosted_tcp_server boosted_multiprotocol_server; -} -} - - -#endif //_MULTIPROTOCOLS_SERVER_H_ - diff --git a/src/contrib/epee/include/net/munin_connection_handler.h b/src/contrib/epee/include/net/munin_connection_handler.h deleted file mode 100644 index 8579339..0000000 --- a/src/contrib/epee/include/net/munin_connection_handler.h +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_CONNECTION_HANDLER_H_ -#define _MUNIN_CONNECTION_HANDLER_H_ - -#include -#include "net_utils_base.h" -#include "to_nonconst_iterator.h" -#include "http_base.h" -#include "reg_exp_definer.h" - -#define MUNIN_ARGS_DEFAULT(vertial_lable_str) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " \n" -#define MUNIN_ARGS_FORCE_AUPPER_LIMIT(vertial_lable_str, limit) "graph_args --base 1000 -l 0 --vertical-label " vertial_lable_str " --rigid --upper-limit " limit " \n" -#define MUNIN_TITLE(title_str) "graph_title " title_str "\n" -#define MUNIN_CATEGORY(category_str) "graph_category " category_str "\n" -#define MUNIN_INFO(info_str) "graph_info " info_str "\n" -#define MUNIN_ENTRY(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" -#define MUNIN_ENTRY_AREA(var_name) #var_name".label " #var_name "\n" #var_name".info "#var_name".\n" #var_name".draw AREASTACK\n" -#define MUNIN_ENTRY_ALIAS(var_name, alias) #var_name".label " #alias"\n" #var_name".info "#alias".\n" -#define BEGIN_MUNIN_SERVICE(servivece_name_str) if(servivece_name_str == pservice->m_service_name) { -#define END_MUNIN_SERVICE() } -#define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast(variable) + "\n" - - - - -namespace epee -{ -namespace net_utils -{ - namespace munin - { - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct munin_service; - - struct munin_service_data_provider - { - virtual bool update_service_data(munin_service* pservice, std::string& paramters_text)=0; - }; - - struct munin_service - { - std::string m_service_name; - std::string m_service_config_string; - munin_service_data_provider* m_pdata_provider; - }; - - struct node_server_config - { - std::list m_services; - //TODO: - }; - - struct fake_send_handler: public i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb) - { - m_cache += std::string((const char*)ptr, cb); - return true; - } - public: - - std::string m_cache; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class munin_node_server_connection_handler - { - public: - typedef node_server_config config_type; - typedef connection_context_base connection_context; - - munin_node_server_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, const connection_context_base& context):m_psnd_hndlr(psnd_hndlr), - m_machine_state(http_state_retriving_comand_line), - m_config(config) - { - init(); - } - virtual ~munin_node_server_connection_handler() - { - - } - - bool release_protocol() - { - return true; - } - bool after_init_connection() - { - std::string hello_str = "# munin node at "; - hello_str += m_host_name + "\n"; - send_hook(hello_str); - return true; - } - - virtual bool thread_init() - { - return true; - } - - virtual bool thread_deinit() - { - return true; - } - - void handle_qued_callback() - { - - } - - virtual bool handle_recv(const void* ptr, size_t cb) - { - - const char* pbuff = (const char*)ptr; - std::string recvd_buff(pbuff, cb); - LOG_PRINT("munin_recv: \n" << recvd_buff, LOG_LEVEL_3); - - m_cache += recvd_buff; - - bool stop_handling = false; - while(!stop_handling) - { - switch(m_machine_state) - { - case http_state_retriving_comand_line: - { - - std::string::size_type fpos = m_cache.find('\n'); - if(std::string::npos != fpos ) - { - bool res = handle_command(m_cache); - if(!res) - return false; - m_cache.erase(0, fpos+1); - continue; - } - stop_handling = true; - } - break; - case http_state_error: - stop_handling = true; - return false; - default: - LOG_ERROR("Error in munin state machine! Unkonwon state=" << m_machine_state); - stop_handling = true; - m_machine_state = http_state_error; - return false; - } - - } - - return true; - } - - private: - - - bool init() - { - char hostname[64] = {0}; - int res = gethostname(hostname, 64); - hostname[63] = 0;//be happy - m_host_name = hostname; - return true; - } - bool handle_command(const std::string& command) - { - // list, nodes, config, fetch, version or quit - STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^((list)|(nodes)|(config)|(fetch)|(version)|(quit))(\\s+(\\S+))?", boost::regex::icase | boost::regex::normal); - // 12 3 4 5 6 7 8 9 - size_t match_len = 0; - boost::smatch result; - if(boost::regex_search(command, result, rexp_match_command_line, boost::match_default) && result[0].matched) - { - if(result[2].matched) - {//list command - return handle_list_command(); - }else if(result[3].matched) - {//nodes command - return handle_nodes_command(); - }else if(result[4].matched) - {//config command - if(result[9].matched) - return handle_config_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[5].matched) - {//fetch command - if(result[9].matched) - return handle_fetch_command(result[9]); - else - { - send_hook("Unknown service\n"); - } - }else if(result[6].matched) - {//version command - return handle_version_command(); - }else if(result[7].matched) - {//quit command - return handle_quit_command(); - } - else - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n"); - } - - return send_hook("Unknown command. Try list, nodes, config, fetch, version or quit\n");; - } - - bool handle_list_command() - { - std::string buff_to_send; - for(std::list::const_iterator it = m_config.m_services.begin(); it!=m_config.m_services.end();it++) - { - buff_to_send += it->m_service_name + " "; - } - buff_to_send+='\n'; - return send_hook(buff_to_send); - } - bool handle_nodes_command() - { - //supports only one node - host name - send_hook(m_host_name + "\n.\n"); - return true; - } - bool handle_config_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - - return send_hook(psrv->m_service_config_string + ".\n"); - } - - bool handle_fetch_command(const std::string& service_name) - { - munin_service* psrv = get_service_by_name(service_name); - if(!psrv) - return send_hook(std::string() + "Unknown service\n"); - - std::string buff; - psrv->m_pdata_provider->update_service_data(psrv, buff); - - buff += ".\n"; - return send_hook(buff); - } - bool handle_version_command() - { - return send_hook("Munin node component by Andrey Sabelnikov\n"); - } - bool handle_quit_command() - { - return false; - } - - bool send_hook(const std::string& buff) - { - LOG_PRINT("munin_send: \n" << buff, LOG_LEVEL_3); - - if(m_psnd_hndlr) - return m_psnd_hndlr->do_send(buff.data(), buff.size()); - else - return false; - } - - - munin_service* get_service_by_name(const std::string& srv_name) - { - std::list::iterator it = m_config.m_services.begin(); - for(; it!=m_config.m_services.end(); it++) - if(it->m_service_name == srv_name) - break; - - if(it==m_config.m_services.end()) - return NULL; - - return &(*it); - } - - enum machine_state{ - http_state_retriving_comand_line, - http_state_error - }; - - - config_type& m_config; - machine_state m_machine_state; - std::string m_cache; - std::string m_host_name; - protected: - i_service_endpoint* m_psnd_hndlr; - }; - - - inline bool test_self() - { - /*WSADATA w; - ::WSAStartup(MAKEWORD(1, 1), &w); - node_server_config sc; - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service"; - - sc.m_services.back().m_service_config_string = - "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n" - "graph_title REPORTS STATICTICS\n" - "graph_category bind\n" - "graph_info This graph shows how many reports came in fixed time period.\n" - "graph_order apps free swap\n" - "apps.label apps\n" - "apps.draw AREA\n" - "apps.info Memory used by user-space applications.\n" - "swap.label swap\n" - "swap.draw STACK\n" - "swap.info Swap space used.\n" - "free.label unused\n" - "free.draw STACK\n" - "free.info Wasted memory. Memory that is not used for anything at all.\n" - "committed.label committed\n" - "committed.draw LINE2\n" - "committed.warn 625410048\n" - "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used.\n"; - - - sc.m_services.push_back(munin_service()); - sc.m_services.back().m_service_name = "test_service1"; - fake_send_handler fh; - munin_node_server_connection_handler mh(&fh, sc); - - std::string buff = "list\n"; - mh.handle_recv(buff.data(), buff.size()); - - - buff = "nodes\n"; - mh.handle_recv(buff.data(), buff.size()); -*/ - return true; - } - - } -} -} -#endif//!_MUNIN_CONNECTION_HANDLER_H_ \ No newline at end of file diff --git a/src/contrib/epee/include/net/munin_node_server.h b/src/contrib/epee/include/net/munin_node_server.h deleted file mode 100644 index 07637f5..0000000 --- a/src/contrib/epee/include/net/munin_node_server.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _MUNIN_NODE_SERVER_H_ -#define _MUNIN_NODE_SERVER_H_ - -#include -//#include "net_utils_base.h" -#include "munin_connection_handler.h" -//#include "abstract_tcp_server.h" -//#include "abstract_tcp_server_cp.h" -#include "abstract_tcp_server2.h" -namespace epee -{ -namespace net_utils -{ - namespace munin - { - typedef boosted_tcp_server munin_node_server; - //typedef cp_server_impl munin_node_cp_server; - } -} -} -#endif//!_MUNIN_NODE_SERVER_H_ \ No newline at end of file diff --git a/src/contrib/epee/include/net/net_helper.h b/src/contrib/epee/include/net/net_helper.h deleted file mode 100644 index 72ff4e7..0000000 --- a/src/contrib/epee/include/net/net_helper.h +++ /dev/null @@ -1,690 +0,0 @@ -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "net/net_utils_base.h" -#include "misc_language.h" -//#include "profile_tools.h" -#include "../string_tools.h" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - - -namespace epee -{ -namespace net_utils -{ - - class blocked_mode_client - { - - - struct handler_obj - { - handler_obj(boost::system::error_code& error, size_t& bytes_transferred):ref_error(error), ref_bytes_transferred(bytes_transferred) - {} - handler_obj(const handler_obj& other_obj):ref_error(other_obj.ref_error), ref_bytes_transferred(other_obj.ref_bytes_transferred) - {} - - boost::system::error_code& ref_error; - size_t& ref_bytes_transferred; - - void operator()(const boost::system::error_code& error, // Result of operation. - std::size_t bytes_transferred // Number of bytes read. - ) - { - ref_error = error; - ref_bytes_transferred = bytes_transferred; - } - }; - - public: - inline - blocked_mode_client():m_socket(m_io_service), - m_initialized(false), - m_connected(false), - m_deadline(m_io_service), - m_shutdowned(0), - m_connect_timeout{}, - m_reciev_timeout{} - { - - - m_initialized = true; - - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_deadline(); - - } - inline - ~blocked_mode_client() - { - NESTED_TRY_ENTRY(); - - //profile_tools::local_coast lc("~blocked_mode_client()", 3); - shutdown(); - - NESTED_CATCH_ENTRY(__func__); - } - - inline void set_recv_timeout(int reciev_timeout) - { - m_reciev_timeout = reciev_timeout; - } - - inline - bool connect(const std::string& addr, int port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") - { - return connect(addr, std::to_string(port), connect_timeout, reciev_timeout, bind_ip); - } - - inline - bool connect(const std::string& addr, const std::string& port, unsigned int connect_timeout, unsigned int reciev_timeout, const std::string& bind_ip = "0.0.0.0") - { - m_connect_timeout = connect_timeout; - m_reciev_timeout = reciev_timeout; - m_connected = false; - if(!m_reciev_timeout) - m_reciev_timeout = m_connect_timeout; - - try - { - m_socket.close(); - // Get a list of endpoints corresponding to the server name. - - - ////////////////////////////////////////////////////////////////////////// - - boost::asio::ip::tcp::resolver resolver(m_io_service); - boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); - boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; - if(iterator == end) - { - LOG_ERROR("Failed to resolve " << addr); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - - - //boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port); - boost::asio::ip::tcp::endpoint remote_endpoint(*iterator); - - - m_socket.open(remote_endpoint.protocol()); - if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" ) - { - boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(addr.c_str()), 0); - m_socket.bind(local_endpoint); - } - - - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_connect_timeout)); - - - boost::system::error_code ec = boost::asio::error::would_block; - - //m_socket.connect(remote_endpoint); - m_socket.async_connect(remote_endpoint, boost::lambda::var(ec) = boost::lambda::_1); - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (!ec && m_socket.is_open()) - { - m_connected = true; - m_deadline.expires_at(boost::posix_time::pos_infin); - return true; - }else - { - LOG_PRINT("Some problems at connect, message: " << ec.message(), LOG_LEVEL_3); - return false; - } - - } - catch(const boost::system::system_error& er) - { - LOG_PRINT("Some problems at connect, message: " << er.what(), LOG_LEVEL_4); - return false; - } - catch(...) - { - LOG_PRINT("Some fatal problems.", LOG_LEVEL_4); - return false; - } - - return true; - } - - - inline - bool disconnect() - { - try - { - if(m_connected) - { - m_connected = false; - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); - - } - } - - catch(const boost::system::system_error& /*er*/) - { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); - return false; - } - catch(...) - { - //LOG_ERROR("Some fatal problems."); - return false; - } - return true; - } - - - inline - bool send(const std::string& buff) - { - - try - { - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(buff), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - } - */ - boost::system::error_code ec; - - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); - - - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at send, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - bool is_connected() - { - return m_connected && m_socket.is_open(); - //TRY_ENTRY() - //return m_socket.is_open(); - //CATCH_ENTRY_L0("is_connected", false) - } - - inline - bool recv(std::string& buff) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - handler_obj hndlr(ec, bytes_transfered); - - char local_buff[10000] = {0}; - //m_socket.async_read_some(boost::asio::buffer(local_buff, sizeof(local_buff)), hndlr); - boost::asio::async_read(m_socket, boost::asio::buffer(local_buff, sizeof(local_buff)), boost::asio::transfer_at_least(1), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - - if (ec) - { - LOG_PRINT_L4("READ ENDS: Connection err_code " << ec.value()); - if(ec == boost::asio::error::eof) - { - LOG_PRINT_L4("Connection err_code eof."); - //connection closed there, empty - return true; - } - - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - LOG_PRINT_L4("READ ENDS: Success. bytes_tr: " << bytes_transfered); - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - /*if(!bytes_transfered) - return false;*/ - - buff.assign(local_buff, bytes_transfered); - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - - } - - inline bool recv_n(std::string& buff, int64_t sz) - { - - try - { - // Set a deadline for the asynchronous operation. Since this function uses - // a composed operation (async_read_until), the deadline applies to the - // entire operation, rather than individual reads from the socket. - m_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - //boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - - buff.resize(static_cast(sz)); - boost::system::error_code ec = boost::asio::error::would_block; - size_t bytes_transfered = 0; - - - handler_obj hndlr(ec, bytes_transfered); - - //char local_buff[10000] = {0}; - boost::asio::async_read(m_socket, boost::asio::buffer((char*)buff.data(), buff.size()), boost::asio::transfer_at_least(buff.size()), hndlr); - - // Block until the asynchronous operation has completed. - while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) - { - m_io_service.run_one(); - } - - if (ec) - { - LOG_PRINT_L3("Problems at read: " << ec.message()); - m_connected = false; - return false; - }else - { - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - if(bytes_transfered != buff.size()) - { - LOG_ERROR("Transferred missmatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); - return false; - } - - return true; - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at read, message: " << er.what()); - m_connected = false; - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems at read."); - return false; - } - - - - return false; - } - - bool shutdown() - { - m_deadline.cancel(); - boost::system::error_code ignored_ec; - m_socket.cancel(ignored_ec); - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - m_socket.close(ignored_ec); - boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); - m_connected = false; - return true; - } - - void set_connected(bool connected) - { - m_connected = connected; - } - boost::asio::io_service& get_io_service() - { - return m_io_service; - } - - boost::asio::ip::tcp::socket& get_socket() - { - return m_socket; - } - - private: - - void check_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_connected = false; - m_socket.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_deadline.async_wait(boost::bind(&blocked_mode_client::check_deadline, this)); - } - - - - protected: - boost::asio::io_service m_io_service; - boost::asio::ip::tcp::socket m_socket; - int m_connect_timeout; - int m_reciev_timeout; - bool m_initialized; - bool m_connected; - boost::asio::deadline_timer m_deadline; - volatile uint32_t m_shutdowned; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class async_blocked_mode_client: public blocked_mode_client - { - public: - async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service) - { - - // No deadline is required until the first socket operation is started. We - // set the deadline to positive infinity so that the actor takes no action - // until a specific deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - - // Start the persistent actor that checks for deadline expiry. - check_send_deadline(); - } - ~async_blocked_mode_client() - { - m_send_deadline.cancel(); - } - - bool shutdown() - { - blocked_mode_client::shutdown(); - m_send_deadline.cancel(); - return true; - } - - inline - bool send(const void* data, size_t sz) - { - try - { - /* - m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout)); - - // Set up the variable that receives the result of the asynchronous - // operation. The error code is set to would_block to signal that the - // operation is incomplete. Asio guarantees that its asynchronous - // operations will never fail with would_block, so any other value in - // ec indicates completion. - boost::system::error_code ec = boost::asio::error::would_block; - - // Start the asynchronous operation itself. The boost::lambda function - // object is used as a callback and will update the ec variable when the - // operation completes. The blocking_udp_client.cpp example shows how you - // can use boost::bind rather than boost::lambda. - boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); - - // Block until the asynchronous operation has completed. - while(ec == boost::asio::error::would_block) - { - m_io_service.run_one(); - }*/ - - boost::system::error_code ec; - - size_t writen = m_socket.write_some(boost::asio::buffer(data, sz), ec); - - if (!writen || ec) - { - LOG_PRINT_L3("Problems at write: " << ec.message()); - return false; - }else - { - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - } - - catch(const boost::system::system_error& er) - { - LOG_ERROR("Some problems at connect, message: " << er.what()); - return false; - } - catch(...) - { - LOG_ERROR("Some fatal problems."); - return false; - } - - return true; - } - - - private: - - boost::asio::deadline_timer m_send_deadline; - - void check_send_deadline() - { - // Check whether the deadline has passed. We compare the deadline against - // the current time since a new asynchronous operation may have moved the - // deadline before this actor had a chance to run. - if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) - { - // The deadline has passed. The socket is closed so that any outstanding - // asynchronous operations are cancelled. This allows the blocked - // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); - m_socket.close(); - - // There is no longer an active deadline. The expiry is set to positive - // infinity so that the actor takes no action until a new deadline is set. - m_send_deadline.expires_at(boost::posix_time::pos_infin); - } - - // Put the actor back to sleep. - m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this)); - } - }; -} -} diff --git a/src/contrib/epee/include/net/net_parse_helpers.h b/src/contrib/epee/include/net/net_parse_helpers.h deleted file mode 100644 index 586dac9..0000000 --- a/src/contrib/epee/include/net/net_parse_helpers.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "http_base.h" -#include "reg_exp_definer.h" - - -namespace epee -{ -namespace net_utils -{ - - inline bool parse_uri_query(const std::string& query, std::list >& params) - { - enum state - { - st_param_name, - st_param_val - }; - state st = st_param_name; - std::string::const_iterator start_it = query.begin(); - std::pair e; - for(std::string::const_iterator it = query.begin(); it != query.end(); it++) - { - switch(st) - { - case st_param_name: - if(*it == '=') - { - e.first.assign(start_it, it); - start_it = it;++start_it; - st = st_param_val; - } - break; - case st_param_val: - if(*it == '&') - { - e.second.assign(start_it, it); - start_it = it;++start_it; - params.push_back(e); - e.first.clear();e.second.clear(); - st = st_param_name; - } - break; - default: - LOG_ERROR("Unknown state " << (int)st); - return false; - } - } - if(st == st_param_name) - { - if(start_it != query.end()) - { - e.first.assign(start_it, query.end()); - params.push_back(e); - } - }else - { - if(start_it != query.end()) - e.second.assign(start_it, query.end()); - - if(e.first.size()) - params.push_back(e); - } - return true; - } - - inline - bool parse_uri(const std::string uri, http::uri_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - content.m_query_params.clear(); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - - boost::smatch result; - if(!boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched) - { - LOG_PRINT_L0("[PARSE URI] regex not matched for uri: " << uri); - content.m_path = uri; - return true; - } - if(result[1].matched) - { - content.m_path = result[1]; - } - if(result[3].matched) - { - content.m_query = result[3]; - } - if(result[5].matched) - { - content.m_fragment = result[5]; - } - if(content.m_query.size()) - { - parse_uri_query(content.m_query, content.m_query_params); - } - return true; - } - - - inline - bool parse_url(const std::string url_str, http::url_content& content) - { - - ///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash= - //STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal); - STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal); - // 12 34 5 6 7 - content.port = 0; - boost::smatch result; - if(!boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched) - { - LOG_PRINT_L0("[PARSE URI] regex not matched for uri: " << rexp_match_uri); - //content.m_path = uri; - return true; - } - if(result[2].matched) - { - content.schema = result[2]; - } - if(result[4].matched) - { - content.host = result[4]; - } - if(result[6].matched) - { - content.port = boost::lexical_cast(result[6]); - } - if(result[7].matched) - { - content.uri = result[7]; - return parse_uri(result[7], content.m_uri_content); - } - - return true; - } - -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/net_utils_base.h b/src/contrib/epee/include/net/net_utils_base.h deleted file mode 100644 index 1ef0677..0000000 --- a/src/contrib/epee/include/net/net_utils_base.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _NET_UTILS_BASE_H_ -#define _NET_UTILS_BASE_H_ - -#include -#include "string_tools.h" - -#ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) -#endif - - -namespace epee -{ -namespace net_utils -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct connection_context_base - { - const boost::uuids::uuid m_connection_id; - const uint32_t m_remote_ip; - const uint32_t m_remote_port; - const bool m_is_income; - const time_t m_started; - time_t m_last_recv; - time_t m_last_send; - uint64_t m_recv_cnt; - uint64_t m_send_cnt; - - connection_context_base(boost::uuids::uuid connection_id, long remote_ip, int remote_port, bool is_income, time_t last_recv = 0, time_t last_send = 0, uint64_t recv_cnt = 0, uint64_t send_cnt = 0): - m_connection_id(connection_id), - m_remote_ip(remote_ip), - m_remote_port(remote_port), - m_is_income(is_income), - m_last_recv(last_recv), - m_last_send(last_send), - m_recv_cnt(recv_cnt), - m_send_cnt(send_cnt), - m_started(time(NULL)) - {} - - connection_context_base(): m_connection_id(), - m_remote_ip(0), - m_remote_port(0), - m_is_income(false), - m_last_recv(0), - m_last_send(0), - m_recv_cnt(0), - m_send_cnt(0), - m_started(time(NULL)) - {} - - connection_context_base& operator=(const connection_context_base& a) - { - set_details(a.m_connection_id, a.m_remote_ip, a.m_remote_port, a.m_is_income); - return *this; - } - - private: - template - friend class connection; - void set_details(boost::uuids::uuid connection_id, long remote_ip, int remote_port, bool is_income) - { - this->~connection_context_base(); - new(this) connection_context_base(connection_id, remote_ip, remote_port, is_income); - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_service_endpoint - { - virtual bool do_send(const void* ptr, size_t cb)=0; - virtual bool close()=0; - virtual bool call_run_once_service_io()=0; - virtual bool request_callback()=0; - virtual boost::asio::io_service& get_io_service()=0; - //protect from deletion connection object(with protocol instance) during external call "invoke" - virtual bool add_ref()=0; - virtual bool release()=0; - protected: - virtual ~i_service_endpoint(){} - }; - - - //some helpers - - - inline std::string print_connection_context(const connection_context_base& ctx) - { - std::stringstream ss; - ss << epee::string_tools::get_ip_string_from_int32(ctx.m_remote_ip) << ":" << ctx.m_remote_port << " " << epee::string_tools::get_str_from_guid_a(ctx.m_connection_id) << (ctx.m_is_income ? " INC":" OUT"); - return ss.str(); - } - - inline std::ostream &operator <<(std::ostream &o, const connection_context_base& ctx) - { - o << epee::string_tools::get_ip_string_from_int32(ctx.m_remote_ip) << ":" << ctx.m_remote_port << (ctx.m_is_income ? " INC" : " OUT"); - return o; - } - - inline std::string print_connection_context_short(const connection_context_base& ctx) - { - std::stringstream ss; - ss << ctx; - return ss.str(); - } - - inline std::string print_connection_context_list(const std::list& contexts, const std::string& delim = std::string("\n")) - { - std::stringstream ss; - for (auto& c : contexts) - { - if (ss.tellp()) - ss << delim; - ss << c; - } - return ss.str(); - } - -#define LOG_PRINT_CC(ct, message, log_level) LOG_PRINT(message, log_level) -#define LOG_PRINT_CC_GREEN(ct, message, log_level) LOG_PRINT_GREEN(message, log_level) -#define LOG_PRINT_CC_RED(ct, message, log_level) LOG_PRINT_RED(message, log_level) -#define LOG_PRINT_CC_BLUE(ct, message, log_level) LOG_PRINT_BLUE(message, log_level) -#define LOG_PRINT_CC_YELLOW(ct, message, log_level) LOG_PRINT_YELLOW(message, log_level) -#define LOG_PRINT_CC_CYAN(ct, message, log_level) LOG_PRINT_CYAN(message, log_level) -#define LOG_PRINT_CC_MAGENTA(ct, message, log_level) LOG_PRINT_MAGENTA(message, log_level) -#define LOG_ERROR_CC(ct, message) LOG_ERROR(message) - -#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(message) -#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(message) -#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(message) -#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(message) -#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(message) - -#define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message) -#define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message) -#define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message) -#define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message) -#define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message) - -#define LOG_PRINT_CCONTEXT_GREEN(message, log_level) LOG_PRINT_CC_GREEN(context, message, log_level) -#define LOG_PRINT_CCONTEXT_RED(message, log_level) LOG_PRINT_CC_RED(context, message, log_level) -#define LOG_PRINT_CCONTEXT_BLUE(message, log_level) LOG_PRINT_CC_BLUE(context, message, log_level) -#define LOG_PRINT_CCONTEXT_YELLOW(message, log_level) LOG_PRINT_CC_YELLOW(context, message, log_level) -#define LOG_PRINT_CCONTEXT_CYAN(message, log_level) LOG_PRINT_CC_CYAN(context, message, log_level) -#define LOG_PRINT_CCONTEXT_MAGENTA(message, log_level) LOG_PRINT_CC_MAGENTA(context, message, log_level) - -#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message) - -} // namespace net_utils -} // namespace epee - -#endif //_NET_UTILS_BASE_H_ diff --git a/src/contrib/epee/include/net/protocol_switcher.h b/src/contrib/epee/include/net/protocol_switcher.h deleted file mode 100644 index ca0ce6f..0000000 --- a/src/contrib/epee/include/net/protocol_switcher.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _PROTOCOL_SWITCHER_H_ -#define _PROTOCOL_SWITCHER_H_ - -#include "levin_base.h" -#include "http_server.h" -#include "levin_protocol_handler.h" -//#include "abstract_tcp_server.h" - -namespace epee -{ -namespace net_utils -{ - struct protocl_switcher_config - { - http::http_custom_handler::config_type m_http_config; - levin::protocol_handler::config_type m_levin_config; - }; - - - struct i_protocol_handler - { - virtual bool handle_recv(const void* ptr, size_t cb)=0; - }; - - template - class t_protocol_handler: public i_protocol_handler - { - public: - typedef t t_type; - t_protocol_handler(i_service_endpoint* psnd_hndlr, typename t_type::config_type& config, const connection_context& conn_context):m_hadler(psnd_hndlr, config, conn_context) - {} - private: - bool handle_recv(const void* ptr, size_t cb) - { - return m_hadler.handle_recv(ptr, cb); - } - t_type m_hadler; - }; - - - class protocol_switcher - { - public: - typedef protocl_switcher_config config_type; - - protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context); - virtual ~protocol_switcher(){} - - virtual bool handle_recv(const void* ptr, size_t cb); - - bool after_init_connection(){return true;} - private: - t_protocol_handler m_http_handler; - t_protocol_handler m_levin_handler; - i_protocol_handler* pcurrent_handler; - - std::string m_cached_buff; - }; - - protocol_switcher::protocol_switcher(net_utils::i_service_endpoint* psnd_hndlr, config_type& config, const net_utils::connection_context_base& conn_context):m_http_handler(psnd_hndlr, config.m_http_config, conn_context), m_levin_handler(psnd_hndlr, config.m_levin_config, conn_context), pcurrent_handler(NULL) - {} - - bool protocol_switcher::handle_recv(const void* ptr, size_t cb) - { - if(pcurrent_handler) - return pcurrent_handler->handle_recv(ptr, cb); - else - { - m_cached_buff.append((const char*)ptr, cb); - if(m_cached_buff.size() < sizeof(uint64_t)) - return true; - - if(*((uint64_t*)&m_cached_buff[0]) == LEVIN_SIGNATURE) - { - pcurrent_handler = &m_levin_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - } - if(m_cached_buff.substr(0, 4) == "GET " || m_cached_buff.substr(0, 4) == "POST") - { - pcurrent_handler = &m_http_handler; - return pcurrent_handler->handle_recv(m_cached_buff.data(), m_cached_buff.size()); - }else - { - LOG_ERROR("Wrong protocol accepted on port..."); - return false; - } - } - - return true; - } -} -} -#endif //_PROTOCOL_SWITCHER_H_ \ No newline at end of file diff --git a/src/contrib/epee/include/net/rpc_method_name.h b/src/contrib/epee/include/net/rpc_method_name.h deleted file mode 100644 index cd9a6f3..0000000 --- a/src/contrib/epee/include/net/rpc_method_name.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - - -#define RPC_METHOD_NAME(name) static inline const char* methodname(){return name;} - diff --git a/src/contrib/epee/include/net/smtp.h b/src/contrib/epee/include/net/smtp.h deleted file mode 100644 index d2e8598..0000000 --- a/src/contrib/epee/include/net/smtp.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - using boost::asio::ip::tcp; - using namespace boost::archive::iterators; - typedef base64_from_binary > base64_text; - - /************************************************************************/ - /* */ - /************************************************************************/ - class smtp_client - { - public: - smtp_client(std::string pServer,unsigned int pPort,std::string pUser,std::string pPassword): - mServer(pServer),mPort(pPort),mUserName(pUser),mPassword(pPassword),mSocket(mIOService),mResolver(mIOService) - { - tcp::resolver::query qry(mServer,boost::lexical_cast( mPort )); - mResolver.async_resolve(qry,boost::bind(&smtp_client::handleResolve,this,boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); - } - bool Send(std::string pFrom,std::string pTo,std::string pSubject,std::string pMessage) - { - mHasError = true; - mFrom=pFrom; - mTo=pTo; - mSubject=pSubject; - mMessage=pMessage; - mIOService.run(); - return !mHasError; - } - private: - std::string encodeBase64(std::string pData) - { - std::stringstream os; - size_t sz=pData.size(); - std::copy(base64_text(pData.c_str()),base64_text(pData.c_str()+sz),std::ostream_iterator(os)); - return os.str(); - } - void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if(!err) - { - tcp::endpoint endpoint=*endpoint_iterator; - mSocket.async_connect(endpoint, - boost::bind(&smtp_client::handleConnect,this,boost::asio::placeholders::error,++endpoint_iterator)); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - void writeLine(std::string pData) - { - std::ostream req_strm(&mRequest); - req_strm << pData << "\r\n"; - boost::asio::write(mSocket,mRequest); - req_strm.clear(); - } - void readLine(std::string& pData) - { - boost::asio::streambuf response; - boost::asio::read_until(mSocket, response, "\r\n"); - std::istream response_stream(&response); - response_stream >> pData; - } - void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator) - { - if (!err) - { - std::string read_buff; - // The connection was successful. Send the request. - std::ostream req_strm(&mRequest); - writeLine("EHLO "+mServer); - readLine(read_buff);//220 - writeLine("AUTH LOGIN"); - readLine(read_buff);// - writeLine(encodeBase64(mUserName)); - readLine(read_buff); - writeLine(encodeBase64(mPassword)); - readLine(read_buff); - writeLine( "MAIL FROM:<"+mFrom+">"); - writeLine( "RCPT TO:<"+mTo+">"); - writeLine( "DATA"); - writeLine( "SUBJECT:"+mSubject); - writeLine( "From:"+mFrom); - writeLine( "To:"+mTo); - writeLine( ""); - writeLine( mMessage ); - writeLine( "\r\n.\r\n"); - readLine(read_buff); - if(read_buff == "250") - mHasError = false; - writeLine( "QUIT"); - } - else - { - mHasError=true; - mErrorMsg= err.message(); - } - } - std::string mServer; - std::string mUserName; - std::string mPassword; - std::string mFrom; - std::string mTo; - std::string mSubject; - std::string mMessage; - unsigned int mPort; - boost::asio::io_service mIOService; - tcp::resolver mResolver; - tcp::socket mSocket; - boost::asio::streambuf mRequest; - boost::asio::streambuf mResponse; - bool mHasError; - std::string mErrorMsg; - }; - - - bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_email, /*"STIL CRAWLER",*/ - const std::string& maillist, const std::string& subject, const std::string& body) - { - STD_TRY_BEGIN(); - //smtp_client mailc("yoursmtpserver.com",25,"user@yourdomain.com","password"); - //mailc.Send("from@yourdomain.com","to@somewhere.com","subject","Hello from C++ SMTP Client!"); - smtp_client mailc(server,port,login,pass); - return mailc.Send(from_email,maillist,subject,body); - STD_TRY_CATCH("at send_mail", false); - } - - } -} -} - -//#include "smtp.inl" \ No newline at end of file diff --git a/src/contrib/epee/include/net/smtp.inl b/src/contrib/epee/include/net/smtp.inl deleted file mode 100644 index d42c8b9..0000000 --- a/src/contrib/epee/include/net/smtp.inl +++ /dev/null @@ -1,1569 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#include "md5.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - - ////////////////////////////////////////////////////////////////////////// - inline char * convert_hex( unsigned char *in, int len ) - { - static char hex[] = "0123456789abcdef"; - char * out; - int i; - - out = (char *) malloc(len * 2 + 1); - if (out == NULL) - return NULL; - - for (i = 0; i < len; i++) { - out[i * 2] = hex[in[i] >> 4]; - out[i * 2 + 1] = hex[in[i] & 15]; - } - - out[i*2] = 0; - - return out; - } - - ////////////////////////////////////////////////////////////////////////// - inline char * hash_md5(const char * sec_key, const char * data, int len) - { - char key[65], digest[24]; - char * hash_hex; - - int sec_len, i; - - sec_len = strlen(sec_key); - - if (sec_len < 64) { - memcpy(key, sec_key, sec_len); - for (i = sec_len; i < 64; i++) { - key[i] = 0; - } - } else { - memcpy(key, sec_key, 64); - } - - md5::hmac_md5( (const unsigned char*)data, len, (const unsigned char*)key, 64, (unsigned char*)digest ); - hash_hex = convert_hex( (unsigned char*)digest, 16 ); - - return hash_hex; - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::CSMTPClient(void) - { - m_dwSupportedAuthModesCount = 0; - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - m_pErrorText = NULL; - - // Initialize WinSock - WORD wVer = MAKEWORD( 2, 2 ); - if ( WSAStartup( wVer, &m_wsaData ) != NO_ERROR ) - { - SetErrorText( "WSAStartup.", WSAGetLastError() ); - throw; - } - if ( LOBYTE( m_wsaData.wVersion ) != 2 || HIBYTE( m_wsaData.wVersion ) != 2 ) - { - SetErrorText( "Can't find a useable WinSock DLL." ); - WSACleanup(); - throw; - } - } - - ////////////////////////////////////////////////////////////////////////// - inline CSMTPClient::~CSMTPClient(void) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - if ( m_bConnected ) - ServerDisconnect(); - - // Cleanup - WSACleanup(); - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::SetErrorText( LPCSTR szErrorText, DWORD dwErrorCode ) - { - if ( m_pErrorText ) - { - free( m_pErrorText ); - m_pErrorText = NULL; - } - - LPVOID lpMsgBuf = NULL; - if ( dwErrorCode ) - { - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR) &lpMsgBuf, - 0, NULL ); - } - - if ( szErrorText && strlen( szErrorText ) ) - { - m_pErrorText = (LPBYTE)malloc( strlen( szErrorText ) + 1 ); - strcpy( (char*)m_pErrorText, szErrorText ); - - if ( lpMsgBuf ) - { - strcat( (char*)m_pErrorText, " " ); - strcpy( (char*)m_pErrorText, (char*)lpMsgBuf ); - - LocalFree( lpMsgBuf ); - } - } - } - - inline void CSMTPClient::SetErrorText( PBYTE szErrorText, DWORD dwErrorCode ) - { - SetErrorText( (LPCSTR)szErrorText, dwErrorCode ); - } - - ////////////////////////////////////////////////////////////////////////// - inline char* CSMTPClient::GetLastErrorText() - { - return (char*)m_pErrorText; - } - - ////////////////////////////////////////////////////////////////////////// - inline DWORD CSMTPClient::ReceiveData( SOCKET hSocket, PBYTE pReceiveBuffer, DWORD dwReceiveBufferSize ) - { - DWORD dwReceivedDataSize = 0; - - if ( hSocket != INVALID_SOCKET && pReceiveBuffer && dwReceiveBufferSize ) - { - int iReceived = 0; - int iLength = 0; - - iLength = recv( hSocket, (LPSTR)pReceiveBuffer + iReceived, dwReceiveBufferSize - iReceived, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iReceived += iLength; - - dwReceivedDataSize = iReceived; - - pReceiveBuffer[ iReceived ] = 0; - } - - return dwReceivedDataSize; - } - - inline ////////////////////////////////////////////////////////////////////////// - DWORD CSMTPClient::SendData( SOCKET hSocket, PBYTE pSendBuffer, DWORD dwSendBufferSize ) - { - DWORD dwSended = 0; - - if ( hSocket != INVALID_SOCKET && pSendBuffer && dwSendBufferSize ) - { - int iSended = 0; - int iLength = 0; - - while ( iLength != SOCKET_ERROR && dwSendBufferSize - iSended > 0 ) - { - iLength = send( hSocket, (LPSTR)pSendBuffer + iSended, dwSendBufferSize - iSended, - NO_FLAGS ); - - if ( iLength != 0 && iLength != SOCKET_ERROR ) - iSended += iLength; - } - - dwSended = iSended; - } - - //if ( dwSended ) - // printf( "C: %s", pSendBuffer ); - - return dwSended; - } - - ////////////////////////////////////////////////////////////////////////// - inline unsigned short CSMTPClient::GetResponseCode( LPBYTE pBuffer, DWORD dwBufferSize ) - { - unsigned short iCode = 0; - - if ( dwBufferSize >= 3 ) - { - CHAR szResponseCode[ 4 ] = { 0 }; - memcpy( szResponseCode, pBuffer, 3 ); - szResponseCode[ 3 ] = 0; - iCode = atoi( szResponseCode ); - } - - return iCode; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ParseESMTPExtensions( LPBYTE pBuffer, DWORD dwBufferSize ) - { - const char *szSubstring = strstr( (const char*)pBuffer, "250-AUTH " ); - if ( !szSubstring ) - { - szSubstring = strstr( (const char*)pBuffer, "250 AUTH " ); - } - - if ( szSubstring ) - { - const char *szSubstringEnd = strstr( (const char*)szSubstring, "\r\n" ); - if ( szSubstringEnd ) - { - szSubstring += 9; - char szAuthMode[ 256 ] = { 0 }; - for ( ; szSubstring < szSubstringEnd + 1 ; szSubstring++ ) - { - if ( *szSubstring == ' ' || *szSubstring == '\r' ) - { - if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_PLAIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_PLAIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_LOGIN ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_LOGIN; - m_dwSupportedAuthModesCount++; - } - else if ( _strcmpi( szAuthMode, SMTP_COMMAND_AUTH_CRAM_MD5 ) == 0 ) - { - m_aSupportedAuthModes[ m_dwSupportedAuthModesCount ] = AUTH_MODE_CRAM_MD5; - m_dwSupportedAuthModesCount++; - } - - szAuthMode[ 0 ] = 0; - - if ( m_dwSupportedAuthModesCount == MAX_AUTH_MODES_COUND ) - break; - } - else - { - szAuthMode[ strlen( szAuthMode ) + 1 ] = 0; - szAuthMode[ strlen( szAuthMode ) ] = *szSubstring; - } - } - } - } - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - if ( m_bConnected ) - ServerDisconnect(); - - m_bConnected = FALSE; - m_hSocket = INVALID_SOCKET; - - m_hSocket = _connectServerSocket( szServerAddress, iPortNumber ); - - if ( m_hSocket != INVALID_SOCKET ) - { - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 220 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 220 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error. ", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // EHLO / HELO - BYTE szHelloBuffer[ 256 ]; - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_EHLO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 500 ) - { - SetErrorText( pReceiveBuffer ); - - sprintf( (char*)szHelloBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_HELO, (char*)szServerAddress ); - if ( SendData( m_hSocket, (PBYTE)szHelloBuffer, strlen( (const char*)szHelloBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - } - else if ( iResponseCode != 250 ) - { - SetErrorText( pReceiveBuffer ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - // Parse AUTH supported modes - ParseESMTPExtensions( pReceiveBuffer, iReceived ); - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - ServerDisconnect(); - return FALSE; - } - - free( pReceiveBuffer ); - } - } - else - { - return FALSE; - } - - m_bConnected = TRUE; - - return TRUE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerConnect( LPCSTR szServerAddress, const unsigned short iPortNumber, LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - bSuccess = ServerConnect( szServerAddress, iPortNumber ); - if ( bSuccess ) - { - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline SOCKET CSMTPClient::_connectServerSocket( LPCSTR szServerAddress, const unsigned short iPortNumber ) - { - int nConnect; - short nProtocolPort = iPortNumber; - LPHOSTENT lpHostEnt; - SOCKADDR_IN sockAddr; - - SOCKET hServerSocket = INVALID_SOCKET; - - lpHostEnt = gethostbyname( szServerAddress ); - if (lpHostEnt) - { - hServerSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (hServerSocket != INVALID_SOCKET) - { - sockAddr.sin_family = AF_INET; - sockAddr.sin_port = htons( nProtocolPort ); - sockAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list); - - nConnect = connect( hServerSocket, (PSOCKADDR)&sockAddr, - sizeof(sockAddr) ); - - if ( nConnect != 0 ) - { - SetErrorText( "connect error.", WSAGetLastError() ); - hServerSocket = INVALID_SOCKET; - } - } - else - { - SetErrorText( "Invalid socket." ); - throw; - } - } - else - { - SetErrorText( "Error retrieving host by name.", WSAGetLastError() ); - } - - return hServerSocket ; - } - - ////////////////////////////////////////////////////////////////////////// - inline void CSMTPClient::ServerDisconnect() - { - if ( m_hSocket != INVALID_SOCKET ) - { - if ( SendData( m_hSocket, (PBYTE)SMTP_COMMAND_QUIT, strlen( SMTP_COMMAND_QUIT ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - - if ( iReceived ) - SetErrorText( pReceiveBuffer ); - - free( pReceiveBuffer ); - } - - m_hSocket = INVALID_SOCKET; - } - - m_bConnected = FALSE; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::GetAuthModeIsSupported( int iMode ) - { - BOOL bSupported = FALSE; - - for ( int i = 0 ; i < m_dwSupportedAuthModesCount ; i++ ) - { - if ( m_aSupportedAuthModes[ i ] == iMode ) - { - bSupported = TRUE; - break; - } - } - - return bSupported; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword, int iAuthMode ) - { - BOOL bSuccess = FALSE; - - if ( iAuthMode == AUTH_MODE_PLAIN ) - { - bSuccess = ServerLoginMethodPlain( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_LOGIN ) - { - bSuccess = ServerLoginMethodLogin( szUsername, szPassword ); - } - else if ( iAuthMode == AUTH_MODE_CRAM_MD5 ) - { - bSuccess = ServerLoginMethodCramMD5( szUsername, szPassword ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - if ( GetAuthModeIsSupported( AUTH_MODE_CRAM_MD5 ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_CRAM_MD5 ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_PLAIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_PLAIN ); - } - else - if ( GetAuthModeIsSupported( AUTH_MODE_LOGIN ) ) - { - bSuccess = ServerLogin( szUsername, szPassword, AUTH_MODE_LOGIN ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodPlain( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_PLAIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - // Encode. - DWORD dwLoginBuffer = strlen( szUsername ) + strlen( szPassword ) + 3; - char *pLoginBuffer = (char*)malloc( dwLoginBuffer ); - if ( pLoginBuffer ) - { - ZeroMemory( pLoginBuffer, dwLoginBuffer ); - strcpy( pLoginBuffer + 1, szUsername ); - strcpy( pLoginBuffer + 1 + strlen( szUsername ) + 1, szPassword ); - - Base64Coder coder; - coder.Encode( (const PBYTE)pLoginBuffer, dwLoginBuffer - 1 ); - LPCSTR szLoginBufferEncoded = coder.EncodedMessage(); - - if ( szLoginBufferEncoded && strlen( szLoginBufferEncoded ) > 0 ) - { - DWORD dwSendBufferSize = strlen( szLoginBufferEncoded ) + 4; - char* pSendBuffer = (char*)malloc( dwSendBufferSize ); - if ( pSendBuffer ) - { - strcpy( pSendBuffer, szLoginBufferEncoded ); - strcat( pSendBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)pSendBuffer, strlen( (const char*)pSendBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pSendBuffer ); - free( pLoginBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pSendBuffer ); - } - } - - free( pLoginBuffer ); - - // check result - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodLogin( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_LOGIN ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest = coder.DecodedMessage(); - if ( szRequest && strlen( szRequest ) > 0 ) - { - if ( strcmpi( szRequest, "Username:" ) == 0 ) - { - coder.Encode( (const PBYTE)szUsername, strlen( szUsername ) ); - LPCSTR szUsernameEncoded = coder.EncodedMessage(); - - char* szLoginUsernameBuffer = (char*)malloc( strlen( szUsernameEncoded ) + 4 ); - if ( szLoginUsernameBuffer ) - { - strcpy( szLoginUsernameBuffer, szUsernameEncoded ); - strcat( szLoginUsernameBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginUsernameBuffer, strlen( (const char*)szLoginUsernameBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginUsernameBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szRequest2 = coder.DecodedMessage(); - if ( szRequest2 && strlen( szRequest2 ) > 0 ) - { - if ( strcmpi( szRequest2, "Password:" ) == 0 ) - { - coder.Encode( (const PBYTE)szPassword, strlen( szPassword ) ); - LPCSTR szPasswordEncoded = coder.EncodedMessage(); - - char* szLoginPasswordBuffer = (char*)malloc( strlen( szPasswordEncoded ) + 4 ); - if ( szLoginPasswordBuffer ) - { - strcpy( szLoginPasswordBuffer, szPasswordEncoded ); - strcat( szLoginPasswordBuffer, "\r\n" ); - - if ( SendData( m_hSocket, (PBYTE)szLoginPasswordBuffer, strlen( (const char*)szLoginPasswordBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szLoginPasswordBuffer ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - } - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::ServerLoginMethodCramMD5( LPCSTR szUsername, LPCSTR szPassword ) - { - BOOL bSuccess = FALSE; - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "%s %s\r\n", (char*)SMTP_COMMAND_AUTH, (char*)SMTP_COMMAND_AUTH_CRAM_MD5 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - // Connected. Wait server hello string. - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 334 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 334 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - // Check request - if ( iReceived > 6 ) - { - Base64Coder coder; - coder.Decode( pReceiveBuffer + 4, iReceived - 6 ); - LPCSTR szResponse = coder.DecodedMessage(); - if ( szResponse && strlen( szResponse ) > 0 ) - { - char *auth_hex = hash_md5( szPassword, szResponse, strlen(szResponse) ); - if ( !auth_hex ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szCommand = (char*)malloc( strlen( szUsername ) + strlen( auth_hex ) + 5 ); - if ( szCommand ) - { - sprintf( szCommand, "%s %s", szUsername, auth_hex ); - - free( auth_hex ); - - coder.Encode( (const PBYTE)szCommand, strlen( szCommand ) ); - - free( szCommand ); - - LPCSTR szAuthEncoded = coder.EncodedMessage(); - if ( szAuthEncoded == NULL ) - { - free( pReceiveBuffer ); - return FALSE; - } - - char *szAuthCommand = (char*)malloc( strlen( szAuthEncoded ) + 4 ); - if ( szAuthCommand ) - { - strcpy( szAuthCommand, szAuthEncoded ); - strcat( szAuthCommand, "\r\n" ); - - // Send auth data - if ( SendData( m_hSocket, (PBYTE)szAuthCommand, strlen( (const char*)szAuthCommand ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szAuthCommand ); - free( pReceiveBuffer ); - return FALSE; - } - - // Check response - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 235 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 235 ) - { - free( pReceiveBuffer ); - return FALSE; - } - - bSuccess = TRUE; - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( szAuthCommand ); - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( auth_hex ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - free( pReceiveBuffer ); - return FALSE; - } - } - - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - return FALSE; - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc() failed.", GetLastError() ); - } - - return bSuccess; - } - - ////////////////////////////////////////////////////////////////////////// - inline BOOL CSMTPClient::SendMessage( LPCSTR szFromAddress, LPCSTR szFromName, LPCSTR szToAddresses, LPCSTR szSubject, LPCSTR szXMailer, LPBYTE pBodyBuffer, DWORD dwBodySize ) - { - BOOL bSuccess = FALSE; - - // Format Header - if ( !szFromAddress ) - { - SetErrorText( "SendMessage. Invalid Parameters!" ); - return NULL; - } - - char *szHeaderBuffer = (char*)malloc( 1024 * 16 ); - if ( szHeaderBuffer ) - { - // get the current date and time - char szDate[ 500 ]; - char sztTime[ 500 ]; - - SYSTEMTIME st = { 0 }; - ::GetSystemTime(&st); - - ::GetDateFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), 0, &st, "ddd',' dd MMM yyyy", szDate , sizeof( szDate ) ); - ::GetTimeFormatA( MAKELCID( MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), TIME_FORCE24HOURFORMAT, &st, "HH':'mm':'ss", sztTime, sizeof( sztTime ) ); - - sprintf( szHeaderBuffer, "DATE: %s %s\r\n", szDate, sztTime ); - - // X-Mailer Field - if ( szXMailer && strlen( szXMailer ) ) - { - strcat( szHeaderBuffer, "X-Mailer: " ); - strcat( szHeaderBuffer, szXMailer ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // From: - strcat( szHeaderBuffer, "From: " ); - if ( szFromName ) - { - strcat( szHeaderBuffer, "\"" ); - strcat( szHeaderBuffer, szFromName ); - strcat( szHeaderBuffer, "\" <" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - else - { - strcat( szHeaderBuffer, "<" ); - strcat( szHeaderBuffer, szFromAddress ); - strcat( szHeaderBuffer, ">\r\n" ); - } - - // Subject: - if ( szSubject && strlen( szSubject ) ) - { - strcat( szHeaderBuffer, "Subject: " ); - strcat( szHeaderBuffer, szSubject ); - strcat( szHeaderBuffer, "\r\n" ); - } - - // To Fields - strcat( szHeaderBuffer, "To: " ); - strcat( szHeaderBuffer, szToAddresses ); - strcat( szHeaderBuffer, "\r\n" ); - - // MIME - strcat( szHeaderBuffer, "MIME-Version: 1.0\r\nContent-type: text/plain; charset=US-ASCII\r\n" ); - - // End Header - strcat( szHeaderBuffer, "\r\n" ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - return FALSE; - } - - - BYTE szCommandBuffer[ 256 ]; - sprintf( (char*)szCommandBuffer, "MAIL FROM:<%s> SIZE=%u\r\n", (char*)szFromAddress, strlen( szHeaderBuffer ) + dwBodySize + 2 ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - return FALSE; - } - - DWORD dwReceiveBufferSize = 1024*16; - PBYTE pReceiveBuffer = (PBYTE)malloc( dwReceiveBufferSize ); - if ( pReceiveBuffer ) - { - DWORD iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 250 ) - { - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - // Post "RCTP TO:" - char *szCurrentAddr = (char*)malloc( strlen( szToAddresses ) + 1 ); - if ( !szCurrentAddr ) - { - SetErrorText( "malloc error.", GetLastError() ); - free( szHeaderBuffer ); - free( pReceiveBuffer ); - return FALSE; - } - - const char* szToOffset = szToAddresses; - char* szZap = NULL; - - BOOL bRCPTAccepted = FALSE; - do - { - strcpy( szCurrentAddr, szToOffset ); - char *szExtractedAdress = szCurrentAddr; - szZap = strchr( szCurrentAddr, ',' ); - - if ( szZap ) - { - *szZap = 0; - szToOffset = szZap + 1; - } - - char *pSkobka1 = strchr( szCurrentAddr, '<' ); - char *pSkobka2 = strchr( szCurrentAddr, '>' ); - - if ( pSkobka1 && pSkobka2 && pSkobka2 > pSkobka1 ) - { - szExtractedAdress = pSkobka1 + 1; - *pSkobka2 = NULL; - } - - if ( szExtractedAdress && strlen( szExtractedAdress ) > 0 ) - { - sprintf( (char*)szCommandBuffer, "RCPT TO:<%s>\r\n", (char*)szExtractedAdress ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bRCPTAccepted = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( szCurrentAddr ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - - } while( szZap ); - - free( szCurrentAddr ); - - if ( bRCPTAccepted ) - { - sprintf( (char*)szCommandBuffer, "DATA\r\n" ); - if ( SendData( m_hSocket, (PBYTE)szCommandBuffer, strlen( (const char*)szCommandBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 354 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode != 354 ) - { - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - // Send message data (header + body + .) - if ( SendData( m_hSocket, (PBYTE)szHeaderBuffer, strlen( (const char*)szHeaderBuffer ) ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)pBodyBuffer, dwBodySize ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - if ( SendData( m_hSocket, (PBYTE)"\r\n.\r\n", 5 ) == 0 ) - { - SetErrorText( "SendData error.", WSAGetLastError() ); - free( pReceiveBuffer ); - free( szHeaderBuffer ); - return FALSE; - } - - iReceived = ReceiveData( m_hSocket, pReceiveBuffer, dwReceiveBufferSize ); - if ( iReceived ) - { - SetErrorText( pReceiveBuffer ); - - // Check 250 - int iResponseCode = GetResponseCode( pReceiveBuffer, iReceived ); - if ( iResponseCode == 250 ) - { - bSuccess = TRUE; - } - } - else - { - SetErrorText( "ReceiveData error.", WSAGetLastError() ); - } - } - - free( pReceiveBuffer ); - } - else - { - SetErrorText( "malloc error.", GetLastError() ); - } - - if ( szHeaderBuffer ) - free( szHeaderBuffer ); - - return bSuccess; - } - - - - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - - -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif - -#ifndef ROUNDTOPAGE -#define ROUNDTOPAGE(a) (((a/4096)+1)*4096) -#endif - - ////////////////////////////////////////////////////////////////////// - // Construction/Destruction - ////////////////////////////////////////////////////////////////////// - - inline Base64Coder::Base64Coder() - : m_pDBuffer(NULL), - m_pEBuffer(NULL), - m_nDBufLen(0), - m_nEBufLen(0) - { - - } - - inline Base64Coder::~Base64Coder() - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - } - - inline LPCSTR Base64Coder::DecodedMessage() const - { - return (LPCSTR) m_pDBuffer; - } - - inline LPCSTR Base64Coder::EncodedMessage() const - { - return (LPCSTR) m_pEBuffer; - } - - inline void Base64Coder::AllocEncode(DWORD nSize) - { - if(m_nEBufLen < nSize) - { - if(m_pEBuffer != NULL) - delete [] m_pEBuffer; - - m_nEBufLen = ROUNDTOPAGE(nSize); - m_pEBuffer = new BYTE[m_nEBufLen]; - } - - ::ZeroMemory(m_pEBuffer, m_nEBufLen); - m_nEDataLen = 0; - } - - inline void Base64Coder::AllocDecode(DWORD nSize) - { - if(m_nDBufLen < nSize) - { - if(m_pDBuffer != NULL) - delete [] m_pDBuffer; - - m_nDBufLen = ROUNDTOPAGE(nSize); - m_pDBuffer = new BYTE[m_nDBufLen]; - } - - ::ZeroMemory(m_pDBuffer, m_nDBufLen); - m_nDDataLen = 0; - } - - inline void Base64Coder::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - DWORD i = 0; - - AllocEncode(nBufLen); - while(i < nBufLen) - { - if(!_IsBadMimeChar(pBuffer[i])) - { - m_pEBuffer[m_nEDataLen] = pBuffer[i]; - m_nEDataLen++; - } - - i++; - } - } - - inline void Base64Coder::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen) - { - AllocDecode(nBufLen); - ::CopyMemory(m_pDBuffer, pBuffer, nBufLen); - m_nDDataLen = nBufLen; - } - - inline void Base64Coder::Encode(const PBYTE pBuffer, DWORD nBufLen) - { - SetDecodeBuffer(pBuffer, nBufLen); - AllocEncode(nBufLen * 2); - - TempBucket Raw; - DWORD nIndex = 0; - - while((nIndex + 3) <= nBufLen) - { - Raw.Clear(); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3); - Raw.nSize = 3; - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - nIndex += 3; - m_nEDataLen += 4; - } - - if(nBufLen > nIndex) - { - Raw.Clear(); - Raw.nSize = (BYTE) (nBufLen - nIndex); - ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex); - _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen); - m_nEDataLen += 4; - } - } - - inline void Base64Coder::Encode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Encode((const PBYTE)szMessage, strlen( (const char*)szMessage)); - } - - inline void Base64Coder::Decode(const PBYTE pBuffer, DWORD dwBufLen) - { - if(is_init()) - _Init(); - - SetEncodeBuffer(pBuffer, dwBufLen); - - AllocDecode(dwBufLen); - - TempBucket Raw; - - DWORD nIndex = 0; - - while((nIndex + 4) <= m_nEDataLen) - { - Raw.Clear(); - Raw.nData[0] = DecodeTable()[m_pEBuffer[nIndex]]; - Raw.nData[1] = DecodeTable()[m_pEBuffer[nIndex + 1]]; - Raw.nData[2] = DecodeTable()[m_pEBuffer[nIndex + 2]]; - Raw.nData[3] = DecodeTable()[m_pEBuffer[nIndex + 3]]; - - if(Raw.nData[2] == 255) - Raw.nData[2] = 0; - if(Raw.nData[3] == 255) - Raw.nData[3] = 0; - - Raw.nSize = 4; - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - nIndex += 4; - m_nDDataLen += 3; - } - - // If nIndex < m_nEDataLen, then we got a decode message without padding. - // We may want to throw some kind of warning here, but we are still required - // to handle the decoding as if it was properly padded. - if(nIndex < m_nEDataLen) - { - Raw.Clear(); - for(DWORD i = nIndex; i < m_nEDataLen; i++) - { - Raw.nData[i - nIndex] = DecodeTable()[m_pEBuffer[i]]; - Raw.nSize++; - if(Raw.nData[i - nIndex] == 255) - Raw.nData[i - nIndex] = 0; - } - - _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen); - m_nDDataLen += (m_nEDataLen - nIndex); - } - } - - inline void Base64Coder::Decode(LPCSTR szMessage) - { - if(szMessage != NULL) - Base64Coder::Decode((const PBYTE)szMessage, strlen((const char*)szMessage)); - } - - inline DWORD Base64Coder::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - DWORD nCount = 0; - - _DecodeRaw(Data, Decode); - - for(int i = 0; i < 3; i++) - { - pBuffer[i] = Data.nData[i]; - if(pBuffer[i] != 255) - nCount++; - } - - return nCount; - } - - - inline void Base64Coder::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) - { - TempBucket Data; - - _EncodeRaw(Data, Decode); - - for(int i = 0; i < 4; i++) - pBuffer[i] = Base64Digits()[Data.nData[i]]; - - switch(Decode.nSize) - { - case 1: - pBuffer[2] = '='; - case 2: - pBuffer[3] = '='; - } - } - - inline void Base64Coder::_DecodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] <<= 2; - - nTemp = Decode.nData[1]; - nTemp >>= 4; - nTemp &= 0x03; - Data.nData[0] |= nTemp; - - Data.nData[1] = Decode.nData[1]; - Data.nData[1] <<= 4; - - nTemp = Decode.nData[2]; - nTemp >>= 2; - nTemp &= 0x0F; - Data.nData[1] |= nTemp; - - Data.nData[2] = Decode.nData[2]; - Data.nData[2] <<= 6; - nTemp = Decode.nData[3]; - nTemp &= 0x3F; - Data.nData[2] |= nTemp; - } - - inline void Base64Coder::_EncodeRaw(TempBucket &Data, const TempBucket &Decode) - { - BYTE nTemp; - - Data.nData[0] = Decode.nData[0]; - Data.nData[0] >>= 2; - - Data.nData[1] = Decode.nData[0]; - Data.nData[1] <<= 4; - nTemp = Decode.nData[1]; - nTemp >>= 4; - Data.nData[1] |= nTemp; - Data.nData[1] &= 0x3F; - - Data.nData[2] = Decode.nData[1]; - Data.nData[2] <<= 2; - - nTemp = Decode.nData[2]; - nTemp >>= 6; - - Data.nData[2] |= nTemp; - Data.nData[2] &= 0x3F; - - Data.nData[3] = Decode.nData[2]; - Data.nData[3] &= 0x3F; - } - - inline BOOL Base64Coder::_IsBadMimeChar(BYTE nData) - { - switch(nData) - { - case '\r': case '\n': case '\t': case ' ' : - case '\b': case '\a': case '\f': case '\v': - return TRUE; - default: - return FALSE; - } - } - - inline void Base64Coder::_Init() - { // Initialize Decoding table. - - int i; - - for(i = 0; i < 256; i++) - DecodeTable()[i] = -2; - - for(i = 0; i < 64; i++) - { - DecodeTable()[Base64Digits()[i]] = i; - DecodeTable()[Base64Digits()[i]|0x80] = i; - } - - DecodeTable()['='] = -1; - DecodeTable()['='|0x80] = -1; - - is_init() = TRUE; - } - - - } -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/net/smtp_helper.h b/src/contrib/epee/include/net/smtp_helper.h deleted file mode 100644 index b8252e1..0000000 --- a/src/contrib/epee/include/net/smtp_helper.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once -#include "smtp.h" - -namespace epee -{ -namespace net_utils -{ - namespace smtp - { - - inline bool send_mail(const std::string& server, int port, const std::string& login, const std::string& pass, const std::string& from_addres, const std::string& from_name, const std::string& maillist, const std::string& subject, const std::string& mail_body) - { - net_utils::smtp::CSMTPClient smtp; - - if ( !smtp.ServerConnect( server.c_str(), port ) ) - { - LOG_PRINT("Reporting: Failed to connect to server " << server <<":"<< port, LOG_LEVEL_0); - return false; - } - - if(login.size() && pass.size()) - { - if ( !smtp.ServerLogin( login.c_str(), pass.c_str()) ) - { - LOG_PRINT("Reporting: Failed to auth on server " << server <<":"<< port, LOG_LEVEL_0); - return false; - - } - } - - if ( !smtp.SendMessage( from_addres.c_str(), - from_name.c_str(), - maillist.c_str(), - subject.c_str(), - "bicycle-client", - (LPBYTE)mail_body.data(), - mail_body.size())) - { - char *szErrorText = smtp.GetLastErrorText(); - if ( szErrorText ) - { - LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0); - } - else - { - LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0); - } - return false; - } - - smtp.ServerDisconnect(); - - return true; - - - } - } -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/os_defenitions.h b/src/contrib/epee/include/os_defenitions.h deleted file mode 100644 index 0cd80a9..0000000 --- a/src/contrib/epee/include/os_defenitions.h +++ /dev/null @@ -1,49 +0,0 @@ - -// Copyright (c) 2006-2016, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - - - -// Check windows -#if _WIN32 || _WIN64 -#if _WIN64 -#define ENV64BIT -#else -#define ENV32BIT -#endif -#endif - -// Check GCC -#if __GNUC__ -#if __x86_64__ || __ppc64__ -#define ENV64BIT -#else -#define ENV32BIT -#endif -#endif \ No newline at end of file diff --git a/src/contrib/epee/include/print_fixed_point_helper.h b/src/contrib/epee/include/print_fixed_point_helper.h deleted file mode 100644 index c652f60..0000000 --- a/src/contrib/epee/include/print_fixed_point_helper.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2006-2017, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once - -namespace epee -{ - namespace string_tools - { - template - inline std::string print_fixed_decimal_point(t_number amount, size_t decimal_point) - { - std::string s = boost::lexical_cast(amount); - if (s.size() < decimal_point + 1) - { - s.insert(0, decimal_point + 1 - s.size(), '0'); - } - s.insert(s.size() - decimal_point, "."); - return s; - } - } -} diff --git a/src/contrib/epee/include/profile_tools.h b/src/contrib/epee/include/profile_tools.h deleted file mode 100644 index b66adac..0000000 --- a/src/contrib/epee/include/profile_tools.h +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2019, anonimal -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _PROFILE_TOOLS_H_ -#define _PROFILE_TOOLS_H_ - -#include -#include -#include "misc_log_ex.h" -#include "print_fixed_point_helper.h" -#define ENABLE_PROFILING - -namespace epee -{ - -#ifdef ENABLE_PROFILING -#define PROFILE_FUNC(profile_name_str) static epee::profile_tools::local_call_account lcl_acc(profile_name_str); \ - epee::profile_tools::call_frame cf(lcl_acc); - -#define PROFILE_FUNC_SECOND(profile_name_str) static epee::profile_tools::local_call_account lcl_acc2(profile_name_str); \ - epee::profile_tools::call_frame cf2(lcl_acc2); - -#define PROFILE_FUNC_THIRD(profile_name_str) static epee::profile_tools::local_call_account lcl_acc3(profile_name_str); \ - epee::profile_tools::call_frame cf3(lcl_acc3); - -#define PROFILE_FUNC_ACC(acc) \ - epee::profile_tools::call_frame cf(acc); - - -#else -#define PROFILE_FUNC(profile_name_str) -#define PROFILE_FUNC_SECOND(profile_name_str) -#define PROFILE_FUNC_THIRD(profile_name_str) -#define PROFILE_FUNC_ACC(profile_name_str) -#endif - -#define START_WAY_POINTS() uint64_t _____way_point_time = misc_utils::get_tick_count(); -#define WAY_POINT(name) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} -#define WAY_POINT2(name, avrg_obj) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} - - -#define TIME_MEASURE_START_MS(var_name) uint64_t var_name = epee::misc_utils::get_tick_count(); -#define TIME_MEASURE_FINISH_MS(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; - - - -#define TIME_MEASURE_START(var_name) uint64_t var_name = 0;std::chrono::high_resolution_clock::time_point var_name##_chrono = std::chrono::high_resolution_clock::now(); -#define TIME_MEASURE_FINISH(var_name) var_name = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - var_name##_chrono).count(); - - -#define TIME_MEASURE_START_PD_MS(var_name) TIME_MEASURE_START_MS(var_name) -#define TIME_MEASURE_FINISH_PD_MS(var_name) TIME_MEASURE_FINISH_MS(var_name);m_performance_data.var_name.push(var_name); - -#define TIME_MEASURE_START_PD(var_name) TIME_MEASURE_START(var_name) -#define TIME_MEASURE_FINISH_PD(var_name) TIME_MEASURE_FINISH(var_name);m_performance_data.var_name.push(var_name); -#define TIME_MEASURE_FINISH_PD_COND(cond, var_name) if(cond){TIME_MEASURE_FINISH(var_name);m_performance_data.var_name.push(var_name);} - - - -namespace profile_tools -{ - - static inline void init_profile_session() - { - static std::atomic is_initialized(false); - if (!is_initialized) - { - is_initialized = true; - LOG_PRINT2("profile_details.log", "=================================================================================================================================================", LOG_LEVEL_0); - } - } - - struct local_call_account - { - local_call_account(const char* pstr) :m_count_of_call(0), m_summary_time_used(0), m_name(pstr) - { - init_profile_session(); - } - local_call_account() :m_count_of_call(0), m_summary_time_used(0) - { - init_profile_session(); - } - ~local_call_account() - { - NESTED_TRY_ENTRY(); - - LOG_PRINT2("profile_details.log", "PROFILE "<< std::left << std::setw(50) << (m_name + ":") - << "av_time:" << std::setw(15) << epee::string_tools::print_fixed_decimal_point (m_count_of_call ? (m_summary_time_used / m_count_of_call) : 0, 3) - << "sum_time: " << std::setw(15) << epee::string_tools::print_fixed_decimal_point(m_summary_time_used, 3) - << "call_count: " << std::setw(15) << m_count_of_call, LOG_LEVEL_0); - - NESTED_CATCH_ENTRY(__func__); - } - - size_t m_count_of_call; - uint64_t m_summary_time_used; - std::string m_name; - }; - - struct call_frame - { - - call_frame(local_call_account& cc):m_cc(cc) - { - m_call_time = boost::posix_time::microsec_clock::local_time(); - } - - ~call_frame() - { - NESTED_TRY_ENTRY(); - - boost::posix_time::ptime now_t(boost::posix_time::microsec_clock::local_time()); - boost::posix_time::time_duration delta_microsec = now_t - m_call_time; - uint64_t microseconds_used = delta_microsec.total_microseconds(); - m_cc.m_summary_time_used += microseconds_used; - m_cc.m_count_of_call++; - - NESTED_CATCH_ENTRY(__func__); - } - - private: - local_call_account& m_cc; - boost::posix_time::ptime m_call_time; - }; - - -} -} - - -#endif //_PROFILE_TOOLS_H_ diff --git a/src/contrib/epee/include/readwrite_lock.h b/src/contrib/epee/include/readwrite_lock.h deleted file mode 100644 index f3152e2..0000000 --- a/src/contrib/epee/include/readwrite_lock.h +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2006-2017, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include -#include -#include -#include - - -namespace epee -{ - - template - class per_thread_data - { - typedef std::map container; - public: - std::recursive_mutex cs; - container th_data; - public: - typename container::iterator get_it() - { - std::unique_lock lk(cs); - auto it = th_data.find(std::this_thread::get_id()); - if (it == th_data.end()) - { - it = th_data.insert(std::make_pair(std::this_thread::get_id(), AUTO_VAL_INIT(t_data()))).first; - } - return it; - } - - t_data& get() - { - std::unique_lock lk(cs); - return get_it()->second; - } - - void erase(typename container::iterator it) - { - std::unique_lock lk(cs); - th_data.erase(it); - } - void erase() - { - std::unique_lock lk(cs); - auto it = th_data.find(std::this_thread::get_id()); - if (it != th_data.end()) - th_data.erase(it); - } - }; - - - /* - Naive implementation of shared recursive mutex with restriction: if you already have acquired shared ownership then - attempt to acquire exclusive ownership will cause deadlock. - */ - class shared_recursive_mutex - { - struct thread_data - { - uint64_t recursion_count; - bool is_writer_thread; - }; - - - - std::condition_variable cv; - std::atomic readers_count; - std::recursive_mutex exclusive_lock; - std::mutex cv_mutex; - per_thread_data ptc; - public: - shared_recursive_mutex() - : readers_count(0) - {} - - ~shared_recursive_mutex() - {} - - void lock() - { - exclusive_lock.lock(); - std::unique_lock lk(cv_mutex); - thread_data& thd = ptc.get(); - if (thd.recursion_count != 0 && !thd.is_writer_thread) - { - ASSERT_MES_AND_THROW("attempt to acquire exclusive ownership while shared ownership already owning"); - } - thd.is_writer_thread = true; - thd.recursion_count++; - - if (readers_count == 0) - return; - - cv.wait(lk, [&](){return readers_count == 0; }); - } - // bool try_lock(); - void unlock() - { - auto thd_it = ptc.get_it(); - thd_it->second.recursion_count--; - if (thd_it->second.recursion_count == 0) - ptc.erase(thd_it); - - exclusive_lock.unlock(); - } - void lock_shared() - { - thread_data& td = ptc.get(); - if (!td.recursion_count) - { - //lock exclusive lock only first entrance to reader lock - exclusive_lock.lock(); - - //always lock cv_mutex when modifying readers_count - std::lock_guard lk(cv_mutex); - readers_count++; - } - - td.recursion_count++; - if (td.recursion_count == 1) - exclusive_lock.unlock(); - } - // bool try_lock_shared(); - void unlock_shared() - { - bool do_notify = false; - { - //process per thread data - auto thd_it = ptc.get_it(); - thd_it->second.recursion_count--; - if (thd_it->second.recursion_count == 0) - { - { - std::lock_guard lk(cv_mutex); - readers_count--; - } - if (readers_count == 0) - do_notify = true; - - ptc.erase(thd_it); - } - } - if (do_notify) - cv.notify_all(); - } - }; - - - - /* - Shared membership for mutex - */ - template - class shared_membership - { - t_shared_mutex& m_mutex; - public: - //to make copy fake! - shared_membership(t_shared_mutex& m) :m_mutex(m) - { - } - ~shared_membership() - { - } - void lock() - { - m_mutex.lock_shared(); - } - void unlock() - { - m_mutex.unlock_shared(); - } - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - //for now ignore shared mutex stuff - template<> - class guarded_critical_region_t : public critical_region_t - { - public: - guarded_critical_region_t(epee::shared_recursive_mutex& cs, const char* /*func_name*/, const char* /*location*/, const char* /*lock_name*/, const std::string& /*thread_name*/) : critical_region_t(cs) - {} - }; - template<> - class guarded_critical_region_t > : public critical_region_t> - { - public: - guarded_critical_region_t(shared_membership& cs, const char* /*func_name*/, const char* /*location*/, const char* /*lock_name*/, const std::string& /*thread_name*/) : critical_region_t>(cs) - {} - }; - - -} diff --git a/src/contrib/epee/include/reg_exp_definer.h b/src/contrib/epee/include/reg_exp_definer.h deleted file mode 100644 index 06e476f..0000000 --- a/src/contrib/epee/include/reg_exp_definer.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _REG_EXP_DEFINER_H_ -#define _REG_EXP_DEFINER_H_ - -#include - - -namespace epee -{ - class global_regexp_critical_section - { - private: - mutable critical_section regexp_lock; - public: - global_regexp_critical_section(){} - critical_section& get_lock()const {return regexp_lock;} - }; - - const static global_regexp_critical_section gregexplock; - - inline const boost::regex* build_regexp(const char* p, boost::regex::flag_type f) - { - return new boost::regex(p, f); - } - -#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_1 = 0;\ - volatile uint32_t local_is_initialized_1 = regexp_initialized_1;\ - if(!local_is_initialized_1)\ - gregexplock.get_lock().lock();\ - static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\ - if(!local_is_initialized_1)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_1, 1);\ - gregexplock.get_lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_2(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_2 = 0;\ - volatile uint32_t local_is_initialized_2 = regexp_initialized_2;\ - if(!local_is_initialized_2)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\ - if(!local_is_initialized_2)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_2, 1);\ - gregexplock.get_lock().lock().unlock();\ -} - -#define STATIC_REGEXP_EXPR_3(var_name, xpr_text, reg_exp_flags) \ - static volatile uint32_t regexp_initialized_3 = 0;\ - volatile uint32_t local_is_initialized_3 = regexp_initialized_3;\ - if(!local_is_initialized_3)\ - gregexplock.get_lock().lock().lock();\ - static const boost::regex& var_name = *build_regexp(xpr_text, reg_exp_flags);\ - if(!local_is_initialized_3)\ -{\ - boost::interprocess::ipcdetail::atomic_write32(®exp_initialized_3, 1);\ - gregexplock.get_lock().lock().unlock();\ -} -} - -#endif //_REG_EXP_DEFINER_H_ diff --git a/src/contrib/epee/include/reg_utils.h b/src/contrib/epee/include/reg_utils.h deleted file mode 100644 index 22227a9..0000000 --- a/src/contrib/epee/include/reg_utils.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _MUSC_UTILS_EX_H_ -#define _MUSC_UTILS_EX_H_ - -namespace epee -{ -namespace reg_utils -{ - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const T& valToSave, bool force_create = true) - { - HKEY hRegKey = 0; - DWORD dw = 0; - - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - if(force_create && (::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS) ) - return false; - - - DWORD val_type = (sizeof(valToSave) == sizeof(DWORD)) ? REG_DWORD:REG_BINARY; - - BOOL res = ::RegSetValueExA( hRegKey, pValName, 0, val_type, (LPBYTE)&valToSave, sizeof(valToSave)) == ERROR_SUCCESS; - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetPODValue(HKEY hParentKey, const char* pSubKey, const char* pValName, T& valToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || (sizeof(valToSave) < lSize) ) - { - ::RegCloseKey(hRegKey); - return false; - } - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)&valToSave, &lSize); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegSetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& strToSave) - { - HKEY hRegKey = 0; - DWORD dw = 0; - DWORD res_ = 0; - if( (res_ = ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw)) != ERROR_SUCCESS ) - if( (res_= ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey)) != ERROR_SUCCESS ) - return false; - - DWORD valType = REG_SZ; - const char* pStr = strToSave.c_str(); - DWORD sizeOfStr = (DWORD)strToSave.size()+1; - LSTATUS res = ::RegSetValueExA(hRegKey, pValName, 0, valType, (LPBYTE)pStr, sizeOfStr); - - ::RegCloseKey(hRegKey); - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetANSIString(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& strToSave) - { - HKEY hRegKey = 0; - LONG res = 0; - - - if((res = ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey)) == ERROR_SUCCESS ) - { - DWORD dwType, lSize = 0; - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res) - { - - ::RegCloseKey(hRegKey); - return false; - } - char* pTmpStr = new char[lSize+2]; - memset(pTmpStr, 0, lSize+2); - res = ::RegQueryValueExA(hRegKey, pValName, 0, &dwType, (LPBYTE)pTmpStr, &lSize); - pTmpStr[lSize+1] = 0; //be happy ;) - strToSave = pTmpStr; - delete [] pTmpStr; - ::RegCloseKey(hRegKey); - } - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.get(0), (DWORD)valToSave.get_size()); - - return ERROR_SUCCESS==res ? true:false; - } - //---------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hKey, const char* pValName, const std::string & valToSave, DWORD valType = REG_BINARY) - { - LONG res = ::RegSetValueExA( hKey, pValName, 0, valType, (CONST BYTE*)valToSave.data(), (DWORD)valToSave.size()); - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - valToSave.release(); - return false; - } - if(valToSave.get_size() < lSize) - valToSave.alloc_buff(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.get(0), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegGetRAWValue(HKEY hKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - DWORD dwType, lSize = 0; - LONG res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, NULL, &lSize); - if(ERROR_SUCCESS!=res || 0 >= lSize) - { - return false; - } - - valToSave.resize(lSize); - res = ::RegQueryValueExA(hKey, pValName, 0, &dwType, (LPBYTE)valToSave.data(), &lSize); - if(pRegType) *pRegType = dwType; - - return ERROR_SUCCESS==res ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const TMemoryObject& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - bool RegSetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, const std::string& valToSave, DWORD valType = REG_BINARY) - { - HKEY hRegKey = 0; - DWORD dw = 0; - bool res = false; - - if( ::RegCreateKeyExA(hParentKey, pSubKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hRegKey, &dw) != ERROR_SUCCESS ) - if( ::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_WRITE, &hRegKey) != ERROR_SUCCESS ) - return false; - - res = RegSetRAWValue(hRegKey, pValName, valToSave, valType); - - ::RegCloseKey(hRegKey); - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - template - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, TMemoryObject& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegGetRAWValue(HKEY hParentKey, const char* pSubKey, const char* pValName, std::string& valToSave, DWORD* pRegType) - { - HKEY hRegKey = 0; - bool res = false; - - if(::RegOpenKeyExA(hParentKey, pSubKey, 0, KEY_READ, &hRegKey) == ERROR_SUCCESS ) - { - res = RegGetRAWValue(hRegKey, pValName, valToSave, pRegType); - ::RegCloseKey(hRegKey); - } - return res; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveValue(HKEY hParentKey, const char* pValName) - { - //CHECK_AND_ASSERT(hParentKey&&pValName, false); - return ::RegDeleteValueA(hParentKey, pValName)==ERROR_SUCCESS ? true:false; - } - //----------------------------------------------------------------------------------------------------------------------------------- - inline - bool RegRemoveKey(HKEY hParentKey, const char* pKeyName) - { - //CHECK_AND_ASSERT(hParentKey&&pKeyName, false); - return ::RegDeleteKeyA(hParentKey, pKeyName)==ERROR_SUCCESS ? true:false; - } - -} -} -#endif //_MUSC_UTILS_EX_H_ diff --git a/src/contrib/epee/include/serialization/keyvalue_helper_structs.h b/src/contrib/epee/include/serialization/keyvalue_helper_structs.h deleted file mode 100644 index e0e3f16..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_helper_structs.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2006-2021, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace epee -{ - - template - struct kvserializable_pair : public std::pair<_Ty1, _Ty2> - { - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(first) - KV_SERIALIZE(second) - END_KV_SERIALIZE_MAP() - }; -} \ No newline at end of file diff --git a/src/contrib/epee/include/serialization/keyvalue_helpers.h b/src/contrib/epee/include/serialization/keyvalue_helpers.h deleted file mode 100644 index 0ae911b..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_helpers.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "misc_language.h" -namespace epee -{ - - template - struct enableable - { - t_obj v; - bool enabled; - - enableable() - : v(t_obj()), enabled(true) - { // construct from defaults - } - - enableable(const t_obj& _v) - : v(_v), enabled(true) - { // construct from specified values - } - - enableable(const enableable& _v) - : v(_v.v), enabled(_v.enabled) - { // construct from specified values - } - }; - - - //basic helpers for pod-to-hex serialization - template - std::string transform_t_pod_to_str(const t_pod_type & a) - { - return epee::string_tools::pod_to_hex(a); - } - template - t_pod_type transform_str_to_t_pod(const std::string& a) - { - t_pod_type res = AUTO_VAL_INIT(res); - if (!epee::string_tools::hex_to_pod(a, res)) - throw std::runtime_error(std::string("Unable to transform \"") + a + "\" to pod type " + typeid(t_pod_type).name()); - return res; - } - - //basic helpers for blob-to-hex serialization - - inline std::string transform_binbuf_to_hexstr(const std::string& a) - { - return epee::string_tools::buff_to_hex_nodelimer(a); - } - - inline std::string transform_hexstr_to_binbuff(const std::string& a) - { - std::string res; - if (!epee::string_tools::parse_hexstr_to_binbuff(a, res)) - { - CHECK_AND_ASSERT_THROW_MES(false, "Failed to parse hex string:" << a); - } - return res; - } - //------------------------------------------------------------------------------------------------------------------- -#pragma pack(push, 1) - template - struct pod_pair - { - first_t first; - second_t second; - }; -#pragma pack(pop) -} \ No newline at end of file diff --git a/src/contrib/epee/include/serialization/keyvalue_hexemizer.h b/src/contrib/epee/include/serialization/keyvalue_hexemizer.h deleted file mode 100644 index 47e7e34..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_hexemizer.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2006-2019, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "keyvalue_serialization.h" -namespace epee -{ - - struct hexemizer - { - std::string blob; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_HEX_STRING(blob) - END_KV_SERIALIZE_MAP() - }; - - -} \ No newline at end of file diff --git a/src/contrib/epee/include/serialization/keyvalue_serialization.h b/src/contrib/epee/include/serialization/keyvalue_serialization.h deleted file mode 100644 index 31c90df..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_serialization.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include "misc_log_ex.h" -#include "keyvalue_helpers.h" -#include "keyvalue_serialization_overloads.h" -namespace epee -{ - /************************************************************************/ - /* Serialize map declarations */ - /************************************************************************/ -#define BEGIN_KV_SERIALIZE_MAP() \ -public: \ - template \ - bool store(t_storage& st, typename t_storage::hsection hparent_section = nullptr) const\ - {\ - return serialize_map(*this, st, hparent_section); \ -}\ - template \ - bool _load(t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ - {\ - return serialize_map(*this, stg, hparent_section); \ -}\ - template \ - bool load(t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ - {\ - try{\ - return serialize_map(*this, stg, hparent_section); \ -}\ - catch (const std::exception& err) \ - { \ - (void)(err); \ - LOG_ERROR("Exception on unserializing: " << err.what()); \ - return false; \ - }\ -}\ - template \ - static bool serialize_map(this_type& this_ref, t_storage& stg, typename t_storage::hsection hparent_section) \ -{ - -#define KV_SERIALIZE_N(varialble, val_name) \ - epee::serialization::selector::serialize(this_ref.varialble, stg, hparent_section, val_name); - -#define KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, val_name) \ - epee::serialization::selector::template serialize_custom(this_ref.varialble, stg, hparent_section, val_name, from_v_to_stored, from_stored_to_v); - -#define KV_SERIALIZE_EPHEMERAL_N(stored_type, from_v_to_stored, val_name) \ - epee::serialization::selector::template serialize_ephemeral(this_ref, stg, hparent_section, val_name, from_v_to_stored); - - -#define KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, val_name) \ - KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_t_pod_to_str, epee::transform_str_to_t_pod, val_name) - -#define KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, val_name) \ - KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_binbuf_to_hexstr, epee::transform_hexstr_to_binbuff, val_name) - - -#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \ - epee::serialization::selector::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name); - -#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, val_name) \ - static_assert(std::is_pod::value, "t_type must be a POD type."); \ - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) - -#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \ - epee::serialization::selector::serialize_stl_container_pod_val_as_blob(this_ref.varialble, stg, hparent_section, val_name); - -#define END_KV_SERIALIZE_MAP() return true;} - -#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble) -#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble) -#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check -#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble) -#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble) -#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble) -#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble) - - - -#define KV_CHAIN_MAP(variable_obj) epee::namespace_accessor::template serialize_map(this_ref.variable_obj, stg, hparent_section); -#define KV_CHAIN_BASE(base_type) base_type::serialize_map(static_cast(const_cast::type&>(this_ref)), stg, hparent_section); - - - - template - struct uint_mask_selector - { - template - inline static bool get_value_of_flag_by_mask(const t_uint& given_flags) - { - return (given_flags&mask) == 0 ? false : true; - } - }; - - -#define KV_SERIALIZE_EPHEMERAL_BOOL_FROM_FLAG_N(var, mask, val_name) \ - KV_SERIALIZE_EPHEMERAL_N(bool, uint_mask_selector::get_value_of_flag_by_mask, val_name) - - - - -} - - - - diff --git a/src/contrib/epee/include/serialization/keyvalue_serialization_boost_variant.h b/src/contrib/epee/include/serialization/keyvalue_serialization_boost_variant.h deleted file mode 100644 index ecb44dd..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_serialization_boost_variant.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include - -namespace epee -{ - namespace serialization - { - - template - struct serialize_variant_visitor : public boost::static_visitor - { - serialize_variant_visitor(t_storage& rstg, typename t_storage::hsection hsection, const char* pn) - :stg(rstg), hparent_section(hsection), pname(pn) - {} - t_storage& stg; - typename t_storage::hsection hparent_section; - const char* pname; - - template - bool operator()(const t_type& v) const - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(v, stg, hparent_section, pname); - } - }; - - template - bool kv_serialize(const boost::variant& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - serialize_variant_visitor sv(stg, hparent_section, pname); - return boost::apply_visitor(sv, d); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(boost::variant &d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - LOG_ERROR("kv_unserialize on boost::variant call not allowed"); - return false; - } - } -} diff --git a/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h deleted file mode 100644 index 01f9e25..0000000 --- a/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -namespace epee -{ - namespace serialization - { - template - static bool serialize_t_val(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.set_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_val(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.get_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - std::string blob((const char *)&d, sizeof(d)); - return stg.set_value(pname, blob, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - std::string blob; - if(!stg.get_value(pname, blob, hparent_section)) - return false; - CHECK_AND_ASSERT_MES(blob.size() == sizeof(d), false, "unserialize_t_val_as_blob: size of " << typeid(t_type).name() << " = " << sizeof(t_type) << ", but stored blod size = " << blob.size() << ", value name = " << pname); - d = *(const t_type*)blob.data(); - return true; - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_obj(const serializible_type& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - CHECK_AND_ASSERT_MES(hchild_section, false, "serialize_t_obj: failed to open/create section " << pname); - return obj.store(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_obj(serializible_type& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - if(!hchild_section) return false; - return obj._load(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_t_obj(enableable& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!obj.enabled) - return true; - return serialize_t_obj(obj.v, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_t_obj(enableable& obj, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - obj.enabled = false; - typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - if(!hchild_section) return false; - obj.enabled = true; - return obj.v._load(stg, hchild_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_t_val (const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - if(!container.size()) return true; - typename stl_container::const_iterator it = container.begin(); - typename t_storage::harray hval_array = stg.insert_first_value(pname, *it, hparent_section); - CHECK_AND_ASSERT_MES(hval_array, false, "failed to insert first value to storage"); - it++; - for(;it!= container.end();it++) - stg.insert_next_value(hval_array, *it); - - return true; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_t_val(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - container.clear(); - typename stl_container::value_type exchange_val; - typename t_storage::harray hval_array = stg.get_first_value(pname, exchange_val, hparent_section); - if(!hval_array) return false; - container.push_back(std::move(exchange_val)); - while(stg.get_next_value(hval_array, exchange_val)) - container.push_back(std::move(exchange_val)); - return true; - }//-------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_pod_val_as_blob(const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - static_assert(std::is_trivial::value, "Item supposed to be 'trivial'(trivially copyable)"); - if(!container.size()) return true; - std::string mb; - mb.resize(sizeof(typename stl_container::value_type)*container.size()); - typename stl_container::value_type* p_elem = (typename stl_container::value_type*)mb.data(); - BOOST_FOREACH(const typename stl_container::value_type& v, container) - { - *p_elem = v; - p_elem++; - } - return stg.set_value(pname, mb, hparent_section); - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_pod_val_as_blob(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - static_assert(std::is_trivial::value, "Item supposed to be 'trivial'(trivially copyable)"); - container.clear(); - std::string buff; - bool res = stg.get_value(pname, buff, hparent_section); - if(res) - { - size_t loaded_size = buff.size(); - typename stl_container::value_type* pelem = (typename stl_container::value_type*)buff.data(); - CHECK_AND_ASSERT_MES(!(loaded_size%sizeof(typename stl_container::value_type)), - false, - "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type)); - size_t count = (loaded_size/sizeof(typename stl_container::value_type)); - for(size_t i = 0; i < count; i++) - container.push_back(*(pelem++)); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool serialize_stl_container_t_obj (const stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - bool res = false; - if(!container.size()) return true; - typename stl_container::const_iterator it = container.begin(); - typename t_storage::hsection hchild_section = nullptr; - typename t_storage::harray hsec_array = stg.insert_first_section(pname, hchild_section, hparent_section); - CHECK_AND_ASSERT_MES(hsec_array && hchild_section, false, "failed to insert first section with section name " << pname); - res = it->store(stg, hchild_section); - it++; - for(;it!= container.end();it++) - { - stg.insert_next_section(hsec_array, hchild_section); - res |= it->store(stg, hchild_section); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - static bool unserialize_stl_container_t_obj(stl_container& container, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - bool res = false; - container.clear(); - typename stl_container::value_type val = typename stl_container::value_type(); - typename t_storage::hsection hchild_section = nullptr; - typename t_storage::harray hsec_array = stg.get_first_section(pname, hchild_section, hparent_section); - if(!hsec_array || !hchild_section) return false; - res = val._load(stg, hchild_section); - container.push_back(val); - while(stg.get_next_section(hsec_array, hchild_section)) - { - typename stl_container::value_type val_l = typename stl_container::value_type(); - res |= val_l._load(stg, hchild_section); - container.push_back(std::move(val_l)); - } - return res; - } - //-------------------------------------------------------------------------------------------------------------------- - template - struct kv_serialization_overloads_impl_is_base_serializable_types; - - template<> - struct kv_serialization_overloads_impl_is_base_serializable_types - { - template - static bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.set_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return stg.get_value(pname, d, hparent_section); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_val(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - }; - template<> - struct kv_serialization_overloads_impl_is_base_serializable_types - { - template - static bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_serialize(const std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return serialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - static bool kv_unserialize(std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return unserialize_stl_container_t_obj(d, stg, hparent_section, pname); - } - }; - template - struct base_serializable_types: public boost::mpl::vector::type - {}; - //------------------------------------------------------------------------------------------------------------------- - template struct selector; - template<> - struct selector - { - template - static bool serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialize(d, stg, hparent_section, pname); - } - - template - static bool serialize_stl_container_pod_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::serialize_stl_container_pod_val_as_blob(d, stg, hparent_section, pname); - } - - template - static bool serialize_t_val_as_blob(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::serialize_t_val_as_blob(d, stg, hparent_section, pname); - } - template< class t_type_stored, class t_type, class t_storage, typename cb_serialize, typename cb_unserialize> - static bool serialize_custom(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, cb_serialize cb_s, cb_unserialize cb_us) - { - t_type_stored a = cb_s(d); - return epee::serialization::selector::serialize(a, stg, hparent_section, pname); - } - template< class t_type_stored, class t_type, class t_storage, typename cb_serialize> - static bool serialize_ephemeral(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, cb_serialize cb_s) - { - t_type_stored a = cb_s(d); - return epee::serialization::selector::serialize(a, stg, hparent_section, pname); - } - - }; - template<> - struct selector - { - template - static bool serialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_unserialize(d, stg, hparent_section, pname); - } - template - static bool serialize_stl_container_pod_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::unserialize_stl_container_pod_val_as_blob(d, stg, hparent_section, pname); - } - - template - static bool serialize_t_val_as_blob(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return epee::serialization::unserialize_t_val_as_blob(d, stg, hparent_section, pname); - } - template< class t_type_stored, class t_type, class t_storage, typename cb_serialize, typename cb_unserialize> - static bool serialize_custom(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, cb_serialize cb_s, cb_unserialize cb_us) - { - t_type_stored a; - bool r = epee::serialization::selector::serialize(a, stg, hparent_section, pname); - if (!r) - return r; - d = cb_us(a); - return r; - } - - template< class t_type_stored, class t_type, class t_storage, typename cb_serialize> - static bool serialize_ephemeral(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname, cb_serialize cb_s) - { - //just a stub here - return true; - } - }; - - template - bool kv_serialize(const t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(t_type& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_serialize(const std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(std::vector& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_serialize(const std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(std::list& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_serialize(const std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_serialize(d, stg, hparent_section, pname); - } - //------------------------------------------------------------------------------------------------------------------- - template - bool kv_unserialize(std::deque& d, t_storage& stg, typename t_storage::hsection hparent_section, const char* pname) - { - return kv_serialization_overloads_impl_is_base_serializable_types, typename std::remove_const::type>::value>::kv_unserialize(d, stg, hparent_section, pname); - } - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/serialization/serialize_base.h b/src/contrib/epee/include/serialization/serialize_base.h deleted file mode 100644 index 84a1624..0000000 --- a/src/contrib/epee/include/serialization/serialize_base.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once - diff --git a/src/contrib/epee/include/service_impl_base.h b/src/contrib/epee/include/service_impl_base.h deleted file mode 100644 index 6e9aefc..0000000 --- a/src/contrib/epee/include/service_impl_base.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _SERVICE_IMPL_BASE_H_ -#define _SERVICE_IMPL_BASE_H_ - -#pragma comment(lib, "advapi32.lib") - - -namespace epee -{ -class service_impl_base { - public: - service_impl_base(); - virtual ~service_impl_base(); - - virtual const char *get_name() = 0; - virtual const char *get_caption() = 0; - virtual const char *get_description() = 0; - - bool run_service(); - virtual bool install(); - virtual bool remove(); - virtual bool init(); - void set_control_accepted(unsigned controls); - void set_status(unsigned state, unsigned pending = 0); - unsigned get_control_accepted(); - - private: - virtual void service_main() = 0; - virtual unsigned service_handler(unsigned control, unsigned event_code, - void *pdata) = 0; - //------------------------------------------------------------------------- - static service_impl_base*& instance(); - //------------------------------------------------------------------------- - static DWORD __stdcall _service_handler(DWORD control, DWORD event, - void *pdata, void *pcontext); - static void __stdcall service_entry(DWORD argc, char **pargs); - virtual SERVICE_FAILURE_ACTIONSA* get_failure_actions(); - - private: - SC_HANDLE m_manager; - SC_HANDLE m_service; - SERVICE_STATUS_HANDLE m_status_handle; - DWORD m_accepted_control; -}; - -inline service_impl_base::service_impl_base() { - m_manager = 0; - m_service = 0; - m_status_handle = 0; - m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN - | SERVICE_ACCEPT_PAUSE_CONTINUE; - - instance() = this; -} -//----------------------------------------------------------------------------- -inline service_impl_base::~service_impl_base() { - if (m_service) { - ::CloseServiceHandle(m_service); - } - m_service = 0; - if (m_manager) { - ::CloseServiceHandle(m_manager); - } - m_manager = 0; - instance() = 0; -} -//----------------------------------------------------------------------------- -inline service_impl_base*& service_impl_base::instance() { - static service_impl_base *pservice = NULL; - return pservice; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::install() { - CHECK_AND_ASSERT(!m_service, false); - const char *psz_descr = get_description(); - SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions(); - - char sz_path[MAX_PATH]; - ::GetModuleFileNameA(0, sz_path, sizeof(sz_path)); - ::GetShortPathNameA(sz_path, sz_path, sizeof(sz_path)); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - m_service = ::CreateServiceA(m_manager, get_name(), get_caption(), - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, - SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to CreateService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - if (psz_descr) { - SERVICE_DESCRIPTIONA sd = { (char*) psz_descr }; - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION, - &sd)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (fail_acts) { - if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS, - fail_acts)) { - int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - LOG_PRINT("Installed succesfully.", LOG_LEVEL_0); - return true; - } - LOG_PRINT("Failed to install.", LOG_LEVEL_0); - return false; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::remove() { - CHECK_AND_ASSERT(!m_service, false); - - while (TRUE) { - if (!m_manager) { - m_manager = ::OpenSCManager(0, 0, GENERIC_ALL); - if (!m_manager) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!m_service) { - m_service = ::OpenServiceA(m_manager, get_name(), SERVICE_STOP | DELETE); - if (!m_service) { - int err = GetLastError(); - LOG_ERROR( - "Failed to OpenService(), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - SERVICE_STATUS status = { }; - if (!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) { - int err = ::GetLastError(); - if (err == ERROR_SHUTDOWN_IN_PROGRESS) - continue; - else if (err != ERROR_SERVICE_NOT_ACTIVE) { - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - } - - if (!::DeleteService(m_service)) { - int err = ::GetLastError(); - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); - break; - } - - LOG_PRINT("Removed successfully.", LOG_LEVEL_0); - break; - } - - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::init() { - return true; -} -//----------------------------------------------------------------------------- -inline -bool service_impl_base::run_service() { - CHECK_AND_ASSERT(!m_service, false); - - long error_code = 0; - - SERVICE_TABLE_ENTRYA service_table[2]; - ZeroMemory(&service_table, sizeof(service_table)); - - service_table->lpServiceName = (char*) get_name(); - service_table->lpServiceProc = service_entry; - - LOG_PRINT("[+] Start service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - - error_code = 1; - BOOL res = ::StartServiceCtrlDispatcherA(service_table); - if (!res) { - int err = GetLastError(); - LOG_PRINT( - "[+] Error starting service control dispatcher, err=" - << log_space::get_win32_err_descr(err), LOG_LEVEL_1); - return false; - } else { - LOG_PRINT("[+] End service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); - } - return true; -} -//----------------------------------------------------------------------------- -inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, - DWORD event, void *pdata, void *pcontext) { - CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); - - service_impl_base *pservice = (service_impl_base*) pcontext; - return pservice->service_handler(control, event, pdata); -} -//----------------------------------------------------------------------------- -inline -void __stdcall service_impl_base::service_entry(DWORD argc, char **pargs) { - service_impl_base *pme = instance(); - LOG_PRINT("instance: " << pme, LOG_LEVEL_4); - if (!pme) { - LOG_ERROR("Error: at service_entry() pme = NULL"); - return; - } - pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(), - _service_handler, pme); - - pme->set_status(SERVICE_RUNNING); - pme->service_main(); - pme->set_status(SERVICE_STOPPED); -} -//----------------------------------------------------------------------------- -inline -void service_impl_base::set_status(unsigned state, unsigned pending) { - if (!m_status_handle) - return; - - SERVICE_STATUS status = { 0 }; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - status.dwCurrentState = state; - status.dwControlsAccepted = m_accepted_control; - /*status.dwWin32ExitCode = NO_ERROR; - status.dwServiceSpecificExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - status.dwCheckPoint = 0; - status.dwWaitHint = 0; - - status.dwCurrentState = state;*/ - - if (state == SERVICE_START_PENDING || state == SERVICE_STOP_PENDING - || state == SERVICE_CONTINUE_PENDING || state == SERVICE_PAUSE_PENDING) { - status.dwWaitHint = 2000; - status.dwCheckPoint = pending; - } - ::SetServiceStatus(m_status_handle, &status); -} -//----------------------------------------------------------------------------------------- -inline -void service_impl_base::set_control_accepted(unsigned controls) { - m_accepted_control = controls; -} -//----------------------------------------------------------------------------------------- -inline -unsigned service_impl_base::get_control_accepted() { - return m_accepted_control; -} -//----------------------------------------------------------------------------------------- -inline SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() { - // first 3 failures in 30 minutes. Service will be restarted. - // do nothing for next failures - static SC_ACTION sa[] = { { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_RESTART, 3 * 1000 }, { SC_ACTION_RESTART, 3 * 1000 }, { - SC_ACTION_NONE, 0 } }; - - static SERVICE_FAILURE_ACTIONSA sfa = { 1800, // interval for failures counter - 30 min - "", NULL, 4, (SC_ACTION*) &sa }; - - // TODO: refactor this code, really unsafe! - return &sfa; -} -} - -#endif //_SERVICE_IMPL_BASE_H_ diff --git a/src/contrib/epee/include/sha1.h b/src/contrib/epee/include/sha1.h deleted file mode 100644 index ce42082..0000000 --- a/src/contrib/epee/include/sha1.h +++ /dev/null @@ -1,51 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SHA1_DEFINED -#define SHA1_DEFINED - -namespace sha1 { - - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - void calc(const void* src, const int bytelength, unsigned char* hash); - - /** - @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. - @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. - */ - void toHexString(const unsigned char* hash, char* hexstring); - -} // namespace sha1 - -#include "sha1.inl" - -#endif // SHA1_DEFINED diff --git a/src/contrib/epee/include/sha1.inl b/src/contrib/epee/include/sha1.inl deleted file mode 100644 index d332027..0000000 --- a/src/contrib/epee/include/sha1.inl +++ /dev/null @@ -1,179 +0,0 @@ - -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Contributors: - Gustav - Several members in the gamedev.se forum. - Gregory Petrosyan - */ - -#include "sha1.h" - -namespace sha1 { -namespace {// local -// Rotate an integer value to left. -inline const unsigned int rol(const unsigned int value, - const unsigned int steps) { - return ((value << steps) | (value >> (32 - steps))); -} - -// Sets the first 16 integers in the buffert to zero. -// Used for clearing the W buffert. -inline void clearWBuffert(unsigned int* buffert) { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } -} - -inline -void innerHash(unsigned int* result, unsigned int* w) { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; - - int round = 0; - -#define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } - - while (round < 16) { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) { - w[round] = rol( - (w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } - -#undef sha1macro - - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; -} -} // namespace - -inline -void calc(const void* src, const int bytelength, unsigned char* hash) { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, - 0xc3d2e1f0 }; - - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; - - // The reusable round buffer - unsigned int w[80]; - - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock(0); - - while (currentBlock <= endOfFullBlocks) { - endCurrentBlock = currentBlock + 64; - - // Init the round buffer with the 64 byte block data. - for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) - { - // This line will swap endian on big endian and keep endian on little endian. - w[roundPos++] = (unsigned int) sarray[currentBlock + 3] - | (((unsigned int) sarray[currentBlock + 2]) << 8) - | (((unsigned int) sarray[currentBlock + 1]) << 16) - | (((unsigned int) sarray[currentBlock]) << 24); - } - innerHash(result, w); - } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (; lastBlockBytes < endCurrentBlock; ++lastBlockBytes) { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes - + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) - & 0xff; - } -} -inline -void toHexString(const unsigned char* hash, char* hexstring) { - const char hexDigits[] = { "0123456789abcdef" }; - - for (int hashByte = 20; --hashByte >= 0;) - { - hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf]; - hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf]; - } - hexstring[40] = 0; -} -} // namespace sha1 diff --git a/src/contrib/epee/include/singleton.h b/src/contrib/epee/include/singleton.h deleted file mode 100644 index a770ab2..0000000 --- a/src/contrib/epee/include/singleton.h +++ /dev/null @@ -1,84 +0,0 @@ - -// Copyright (c) 2006-2018, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - - -#pragma once - -#include -#include "static_helpers.h" - -template -class abstract_singleton -{ - - static std::shared_ptr get_set_instance_internal(bool is_need_set = false, owned_object_t* pnew_obj = nullptr) - { - static epee::static_helpers::wrapper> val_pobj; - - if (is_need_set) - val_pobj.reset(pnew_obj); - - return val_pobj; - } - - static bool get_is_deinitialized(bool need_to_set = false, bool val_to_set = false) - { - static bool is_deintialized = false; - if (need_to_set) - is_deintialized = val_to_set; - return is_deintialized; - } - - -public: - inline static bool init() - { - //better to call before multiple threads start to call it - get_instance(); - return true;/*do nothing here*/ - } - inline static bool un_init() - { - get_is_deinitialized(true, true); - get_set_instance_internal(true, nullptr); - return true; - } - - static std::shared_ptr get_instance() - { - std::shared_ptr val_pobj = get_set_instance_internal(); - if (!val_pobj.get() && !get_is_deinitialized()) - { - owned_object_t*pnewobj = new owned_object_t(); - get_set_instance_internal(true, pnewobj); - val_pobj = get_set_instance_internal(); - } - return val_pobj; - } -}; \ No newline at end of file diff --git a/src/contrib/epee/include/soci_helper.h b/src/contrib/epee/include/soci_helper.h deleted file mode 100644 index 813edc1..0000000 --- a/src/contrib/epee/include/soci_helper.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -#include "soci.h" -#include "soci-postgresql.h" - -using namespace epee; -namespace soci -{ - - template <> - struct type_conversion - { - typedef long long base_type; - - static void from_base(base_type a_, indicator ind, uint64_t & mi) - { - if (ind == i_null) - { - mi = 0; - //throw soci_error("Null value not allowed for this type"); - } - mi = (uint64_t)a_; - //mi.set(i); - } - - static void to_base(const uint64_t & mi, base_type & i, indicator & ind) - { - i = (base_type)mi; - ind = i_ok; - } - }; - - - - template <> - struct type_conversion - { - typedef int base_type; - - static void from_base(base_type a_, indicator ind, bool& mi) - { - if (ind == i_null) - { - mi = false; - //throw soci_error("Null value not allowed for this type"); - } - mi = a_? true:false; - //mi.set(i); - } - - static void to_base(const bool & mi, base_type & i, indicator & ind) - { - i = mi? 1:0; - ind = i_ok; - } - }; - - - - class per_thread_session - { - public: - bool init(const std::string& connection_string) - { - m_connection_string = connection_string; - - return true; - } - - soci::session& get() - { - - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[epee::misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(!conn_ptr.get()) - { - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - //init new connection - return *conn_ptr.get(); - } - - bool reopen() - { - //soci::session - - m_db_connections_lock.lock(); - boost::shared_ptr& conn_ptr = m_db_connections[misc_utils::get_thread_string_id()]; - m_db_connections_lock.unlock(); - if(conn_ptr.get()) - { - conn_ptr->close(); - conn_ptr.reset(new soci::session(soci::postgresql, m_connection_string)); - } - - //init new connection - return true; - } - - //---------------------------------------------------------------------------------------------- - bool check_status() - { - return true; - } - - protected: - private: - std::map > m_db_connections; - epee::critical_section m_db_connections_lock; - std::string m_connection_string; - }; -} -/*}*/ \ No newline at end of file diff --git a/src/contrib/epee/include/static_helpers.h b/src/contrib/epee/include/static_helpers.h deleted file mode 100644 index d3c11c8..0000000 --- a/src/contrib/epee/include/static_helpers.h +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2006-2020, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once -#include -#include -#include -#include -#include "include_base_utils.h" -#include "auto_val_init.h" - -#define DEFINE_SECURE_STATIC_VAR(type, var) static epee::static_helpers::wrapper var##inst; \ - static type& var = var##inst; - -namespace epee -{ - namespace static_helpers - { - template - class initializer - { - public: - initializer() - { - to_initialize::init(); - //get_set_is_initialized(true, true); - } - ~initializer() - { - to_initialize::un_init(); - //get_set_is_uninitialized(true, true); - } - }; - - - typedef void(*static_destroy_handler_type)(); - - inline - bool set_or_call_on_destruct(bool set = false, static_destroy_handler_type destr_ptr = nullptr) - { - volatile static bool deinit_called = false; - volatile static static_destroy_handler_type static_destroy_handler = nullptr; - - if (set) - { - static_destroy_handler = destr_ptr; - return true; - } - if (!deinit_called) - { - - if (static_destroy_handler) - static_destroy_handler(); - - deinit_called = true; - } - - return true; - } - - template - struct wrapper : public t_base - { - ~wrapper() - { - set_or_call_on_destruct(); - } - - }; - - } - - - - -} diff --git a/src/contrib/epee/include/static_initializer.h b/src/contrib/epee/include/static_initializer.h deleted file mode 100644 index 43ccff6..0000000 --- a/src/contrib/epee/include/static_initializer.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _STATIC_INITIALIZER_H_ -#define _STATIC_INITIALIZER_H_ - - -namespace epee -{ -/*********************************************************************** -class initializer - useful to initialize some static classes - which have init() and un_init() static members -************************************************************************/ - - - -template -class initializer -{ -public: - initializer() - { - to_initialize::init(); - //get_set_is_initialized(true, true); - } - ~initializer() - { - to_initialize::un_init(); - //get_set_is_uninitialized(true, true); - } - - /*static inline bool is_initialized() - { - return get_set_is_initialized(); - } - static inline bool is_uninitialized() - { - return get_set_is_uninitialized(); - } - -private: - static inline bool get_set_is_initialized(bool need_to_set = false, bool val_to_set= false) - { - static bool val_is_initialized = false; - if(need_to_set) - val_is_initialized = val_to_set; - return val_is_initialized; - } - static inline bool get_set_is_uninitialized(bool need_to_set = false, bool val_to_set = false) - { - static bool val_is_uninitialized = false; - if(need_to_set) - val_is_uninitialized = val_to_set; - return val_is_uninitialized; - }*/ -}; - -} -#endif //_STATIC_INITIALIZER_H_ diff --git a/src/contrib/epee/include/storages/activity_notifier.h b/src/contrib/epee/include/storages/activity_notifier.h deleted file mode 100644 index 14b6ebb..0000000 --- a/src/contrib/epee/include/storages/activity_notifier.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "inmemtoxml.h" - -//#include "levin/levin_server.h" - -namespace epee -{ - -class activity_printer_base -{ -public: - activity_printer_base(){} - virtual ~activity_printer_base(){} -}; - -template -class notify_activity_printer: public activity_printer_base -{ -public: - notify_activity_printer(int level, A& arg, bool is_notify_mode = true):m_ref_arg(arg), m_level(level), m_is_notify_mode(is_notify_mode) - { - m_command_name = typeid(m_ref_arg).name(); - m_command_name.erase(0, 7); - m_command_name.erase(m_command_name.size()-10, m_command_name.size()-1); - if(level == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(m_command_name, level); - } - else if(level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" -->>" << m_command_name, level); - } - else if(level+2 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" -->>" << m_command_name << "\n" << StorageNamed::xml::get_t_as_xml(m_ref_arg), level); - } - } - - virtual ~notify_activity_printer() - { - if(m_is_notify_mode) - { - if(m_level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name, m_level); - } - } - } -protected: - std::string m_command_name; - A& m_ref_arg; - int m_level; - bool m_is_notify_mode; -}; - -template -class command_activity_printer: public notify_activity_printer -{ -public: - command_activity_printer(int level, A& arg, R& rsp):notify_activity_printer(level, arg, false), m_ref_rsp(rsp) - { - } - - virtual ~command_activity_printer() - { - if(m_level+1 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name, m_level); - } - else if(m_level+2 == log_space::get_set_log_detalisation_level()) - { - LOG_PRINT(" <<--" << m_command_name << "\n" << StorageNamed::trace_as_xml(m_ref_rsp), m_level); - } - } -private: - R& m_ref_rsp; -}; - -template -activity_printer_base* create_activity_printer(int level, A& arg, R& rsp) -{ - return new command_activity_printer(level, arg, rsp); -} - -template -activity_printer_base* create_activity_printer(int level, A& arg) -{ - return new notify_activity_printer(level, arg); -} - -} - -#define PRINT_COMMAND_ACTIVITY(level) boost::shared_ptr local_activity_printer(create_activity_printer(level, in_struct, out_struct)); -#define PRINT_NOTIFY_ACTIVITY(level) boost::shared_ptr local_activity_printer(create_activity_printer(level, in_struct)); - -#define PRINT_ACTIVITY(level) \ -{std::string some_str = typeid(in_struct).name(); \ - some_str.erase(0, 7); \ - some_str.erase(some_str.size()-10, some_str.size()-1); \ - LOG_PRINT(some_str, level);} - -} - diff --git a/src/contrib/epee/include/storages/crypted_storage.h b/src/contrib/epee/include/storages/crypted_storage.h deleted file mode 100644 index d6e6edc..0000000 --- a/src/contrib/epee/include/storages/crypted_storage.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _CRYPTED_STORAGE_H_ -#define _CRYPTED_STORAGE_H_ - -#include "cryptopp_helper.h" - -namespace epee -{ -template -class crypted_storage: public t_base_storage -{ -public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!crypt_provider::encrypt(targetObj, t_key_provider::get_storage_default_key())) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_decrypt = pTargetObj; - if(crypt_provider::decrypt(buff_to_decrypt, t_key_provider::get_storage_default_key())) - return t_base_storage::LoadFromSolidBuffer(buff_to_decrypt); - - return 0; - } -}; -} - -#endif //_CRYPTED_STORAGE_H_ \ No newline at end of file diff --git a/src/contrib/epee/include/storages/gzipped_inmemstorage.h b/src/contrib/epee/include/storages/gzipped_inmemstorage.h deleted file mode 100644 index 5c53fff..0000000 --- a/src/contrib/epee/include/storages/gzipped_inmemstorage.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _GZIPPED_INMEMSTORAGE_H_ -#define _GZIPPED_INMEMSTORAGE_H_ - -#include "zlib_helper.h" -namespace epee -{ -namespace StorageNamed -{ - - template - class gziped_storage: public t_base_storage - { - public: - size_t PackToSolidBuffer(std::string& targetObj) - { - size_t res = t_base_storage::PackToSolidBuffer(targetObj); - if(res <= 0) - return res; - - if(!zlib_helper::pack(targetObj)) - return 0; - - return targetObj.size(); - } - - size_t LoadFromSolidBuffer(const std::string& pTargetObj) - { - std::string buff_to_ungzip = pTargetObj; - if(zlib_helper::unpack(buff_to_ungzip)) - return t_base_storage::LoadFromSolidBuffer(buff_to_ungzip); - - return 0; - } - - private: - }; - -} -} - -#endif \ No newline at end of file diff --git a/src/contrib/epee/include/storages/http_abstract_invoke.h b/src/contrib/epee/include/storages/http_abstract_invoke.h deleted file mode 100644 index 0b6ef8e..0000000 --- a/src/contrib/epee/include/storages/http_abstract_invoke.h +++ /dev/null @@ -1,145 +0,0 @@ - -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "portable_storage_template_helper.h" -#include "net/http_base.h" -#include "net/http_server_handlers_map2.h" - -namespace epee -{ - namespace net_utils - { - template - bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - if(!serialization::store_t_to_json(out_struct, req_param)) - return false; - - const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return serialization::load_t_from_json(result_struct, pri->m_body); - } - - - - template - bool invoke_http_bin_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") - { - std::string req_param; - if(!serialization::store_t_to_binary(out_struct, req_param)) - return false; - - const http::http_response_info* pri = NULL; - if(!invoke_request(url, transport, timeout, &pri, method, req_param)) - { - LOG_PRINT_L1("Failed to invoke http request to " << url); - return false; - } - - if(!pri->m_response_code) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); - return false; - } - - if(pri->m_response_code != 200) - { - LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); - return false; - } - - return serialization::load_t_from_binary(result_struct, pri->m_body); - } - - - template - bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, epee::json_rpc::error& err, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { - epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); - req_t.jsonrpc = "2.0"; - req_t.id = req_id; - req_t.method = method_name; - req_t.params = out_struct; - epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); - if (!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) - { - return false; - } - err = resp_t.error; - result_struct = resp_t.result; - return true; - } - - template - bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { - epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); - req_t.jsonrpc = "2.0"; - req_t.id = req_id; - req_t.method = method_name; - req_t.params = out_struct; - epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); - if(!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) - { - return false; - } - if(resp_t.error.code || resp_t.error.message.size()) - { - LOG_PRINT_L0("RPC call of \"" << method_name << "\" returned error: " << resp_t.error.code << ", message: " << resp_t.error.message); - return false; - } - result_struct = resp_t.result; - return true; - } - - template - bool invoke_http_json_rpc(const std::string& url, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { - return invoke_http_json_rpc(url, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id); - } - - } -} diff --git a/src/contrib/epee/include/storages/levin_abstract_invoke2.h b/src/contrib/epee/include/storages/levin_abstract_invoke2.h deleted file mode 100644 index 1b2c74a..0000000 --- a/src/contrib/epee/include/storages/levin_abstract_invoke2.h +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include "portable_storage_template_helper.h" -#include -#include "net/levin_base.h" - -namespace epee -{ - namespace net_utils - { - template - bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - int res = 0; - TRY_ENTRY() - res = transport.invoke(command, buff_to_send, buff_to_recv); - CATCH_ENTRY2(false) - if( res <=0 ) - { - LOG_PRINT_RED("Failed to invoke command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ")", LOG_LEVEL_1); - return false; - } - serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - return false; - } - result_struct.load(stg_ret); - return true; - } - - template - bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport) - { - if(!transport.is_connected()) - return false; - - serialization::portable_storage stg; - out_struct.store(&stg); - std::string buff_to_send; - stg.store_to_binary(buff_to_send); - int res = 0; - TRY_ENTRY() - res = transport.notify(command, buff_to_send); - CATCH_ENTRY2(false) - if(res <=0 ) - { - LOG_ERROR("Failed to notify command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ")"); - return false; - } - return true; - } - - template - bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) - { - - typename serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - int res = 0; - TRY_ENTRY() - res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id); - CATCH_ENTRY2(false) - if( res <=0 ) - { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ")"); - return false; - } - typename serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - return false; - } - result_struct.load(stg_ret); - - return true; - } - - template - bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport, const callback_t& cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) - { - typename serialization::portable_storage stg; - const_cast(out_struct).store(stg);//TODO: add true const support to searilzation - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool - { - t_result result_struct = AUTO_VAL_INIT(result_struct); - if( code <=0 ) - { - LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::get_callstack()); - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code << "(" << epee::levin::get_err_descr(code) << ")context:" << print_connection_context(context)); - TRY_ENTRY() - cb(code, result_struct, context); - CATCH_ENTRY2(true) - return false; - } - serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff)) - { - LOG_ERROR("Failed to load_from_binary on command " << command); - TRY_ENTRY(); - cb(LEVIN_ERROR_FORMAT, result_struct, context); - CATCH_ENTRY2(true); - return false; - } - result_struct.load(stg_ret); - TRY_ENTRY() - cb(code, result_struct, context); - CATCH_ENTRY2(true) - return true; - }, inv_timeout); - if( res <=0 ) - { - LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::get_callstack()); - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ") conn_id=" << conn_id); - return false; - } - return true; - } - - template - bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport) - { - - serialization::portable_storage stg; - out_struct.store(stg); - std::string buff_to_send, buff_to_recv; - stg.store_to_binary(buff_to_send); - int res = LEVIN_ERROR_UNKNOWN_ERROR; - TRY_ENTRY() - res = transport.notify(command, buff_to_send, conn_id); - CATCH_ENTRY2(false) - if(res <=0 ) - { - LOG_PRINT_RED_L0("Failed to notify command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ")"); - return false; - } - return true; - } - //---------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------- - template - int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) - { - serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) - { - LOG_ERROR("Failed to load_from_binary in command " << command); - return LEVIN_ERROR_FORMAT; - } - boost::value_initialized in_struct; - boost::value_initialized out_struct; - - static_cast(in_struct).load(strg); - int res = LEVIN_ERROR_UNKNOWN_ERROR; - TRY_ENTRY() - res = cb(command, static_cast(in_struct), static_cast(out_struct), context); - CATCH_ENTRY2(LEVIN_ERROR_EXCEPTION) - serialization::portable_storage strg_out; - static_cast(out_struct).store(strg_out); - - if(!strg_out.store_to_binary(buff_out)) - { - LOG_ERROR("Failed to store_to_binary in command" << command); - return LEVIN_ERROR_INTERNAL; - } - - return res; - }; - - template - int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) - { - serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) - { - LOG_ERROR("Failed to load_from_binary in notify " << command); - return LEVIN_ERROR_FORMAT; - } - boost::value_initialized in_struct; - static_cast(in_struct).load(strg); - int res = LEVIN_ERROR_UNKNOWN_ERROR; - TRY_ENTRY() - res = cb(command, in_struct, context); - CATCH_ENTRY2(LEVIN_ERROR_EXCEPTION) - return res; - }; - -#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ - { \ - bool handled = false; \ - return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ - int notify(int command, const std::string& in_buff, context_type& context) \ - { \ - bool handled = false; std::string fake_str;\ - return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ - } - - -#define CHAIN_LEVIN_INVOKE_MAP() \ - int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ - { \ - bool handled = false; \ - return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_MAP() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ - { \ - bool handled = false; std::string fake_str;\ - return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ - } - -#define CHAIN_LEVIN_NOTIFY_STUB() \ - int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ - { \ - return -1; \ - } - -#define BEGIN_INVOKE_MAP2(owner_type) \ - template int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ - { \ - typedef owner_type internal_owner_type_name; - -#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \ - if(!is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} - -#define HANDLE_INVOKE_T2(COMMAND, func) \ - if(!is_notify && COMMAND::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} - - -#define HANDLE_NOTIFY2(command_id, func, type_name_in) \ - if(is_notify && command_id == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} - -#define HANDLE_NOTIFY_T2(NOTIFY, func) \ - if(is_notify && NOTIFY::ID == command) \ - {handled=true;return epee::net_utils::buff_to_t_adapter(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} - - -#define CHAIN_INVOKE_MAP2(func) \ - { \ - int res = func(is_notify, command, in_buff, buff_out, context, handled); \ - if(handled) \ - return res; \ - } - -#define CHAIN_INVOKE_MAP_TO_OBJ2(obj) \ - { \ - int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, context, handled); \ - if(handled) \ - return res; \ - } - -#define CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(obj, context_type) \ - { \ - int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, static_cast(context), handled); \ - if(handled) return res; \ - } - - -#define END_INVOKE_MAP2() \ - LOG_ERROR("Unkonown command:" << command); \ - return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \ - } - } -} - diff --git a/src/contrib/epee/include/storages/parserse_base_utils.h b/src/contrib/epee/include/storages/parserse_base_utils.h deleted file mode 100644 index bd40c68..0000000 --- a/src/contrib/epee/include/storages/parserse_base_utils.h +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -namespace epee -{ -namespace misc_utils -{ - namespace parse - { - inline std::string transform_to_escape_sequence(const std::string& src) - { - //std::stringstream res; - std::string res; - for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) - { - switch(*it) - { - case '\b': //Backspace (ascii code 08) - res+="\\b"; break; - case '\f': //Form feed (ascii code 0C) - res+="\\f"; break; - case '\n': //New line - res+="\\n"; break; - case '\r': //Carriage return - res+="\\r"; break; - case '\t': //Tab - res+="\\t"; break; - case '\v': //Vertical tab - res+="\\v"; break; - //case '\'': //Apostrophe or single quote - // res+="\\'"; break; - case '"': //Double quote - res+="\\\""; break; - case '\\': //Backslash caracter - res+="\\\\"; break; - case '/': //Backslash caracter - res+="\\/"; break; - default: - res.push_back(*it); - } - } - return res; - } - - /* Escapes JSON control characters and ASCII control characters (00h-1Fh => \u00XX) according to JSON reference. - UTF-8-safe. - from https://www.json.org/ : - char -- any-Unicode-character-except-"-or-\-or-control-character: \" \\ \/ \b \f \n \r \t \uDDDD - */ - inline std::string transform_to_json_escape_sequence(const std::string& str) - { - std::string result; - - static const char hex_map[17] = "0123456789abcdef"; - static const std::string su00 = "\\u00"; - - const char* c_str = str.c_str(); - for(size_t i = 0, len = str.length(); i < len; ++i) - { - char c = c_str[i]; - switch(c) - { - case '\b': // ASCII 08h - result += "\\b"; - break; - case '\t': // ASCII 09h - result += "\\t"; - break; - case '\n': // ASCII 0Ah - result += "\\n"; - break; - case '\f': // ASCII 0Ch - result += "\\f"; - break; - case '\r': // ASCII 0Dh - result += "\\r"; - break; - case '"': // ASCII 22h - case '\\': // ASCII 5Ch - case '/': // ASCII 2Fh - result.push_back('\\'); - result.push_back(c); - break; - - default: - if (static_cast(c) < 0x20) - result += su00 + hex_map[(c >> 4) & 0xf] + hex_map[c & 0xf]; // encode all other control characters as \uDDDD - else - result.push_back(c); - } - } - return result; - } - - /* - - \b Backspace (ascii code 08) - \f Form feed (ascii code 0C) - \n New line - \r Carriage return - \t Tab - \v Vertical tab - \' Apostrophe or single quote - \" Double quote - \\ Backslash character - \u00XY ASCII character with code 0xXY - - */ - inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - bool escape_mode = false; - val.reserve(buf_end - star_end_string); - std::string::const_iterator it = star_end_string; - ++it; - for(;it != buf_end;it++) - { - if(escape_mode/*prev_ch == '\\'*/) - { - switch(*it) - { - case 'b': //Backspace (ascii code 08) - val.push_back(0x08);break; - case 'f': //Form feed (ascii code 0C) - val.push_back(0x0C);break; - case 'n': //New line - val.push_back('\n');break; - case 'r': //Carriage return - val.push_back('\r');break; - case 't': //Tab - val.push_back('\t');break; - case 'v': //Vertical tab - val.push_back('\v');break; - case '\'': //Apostrophe or single quote - val.push_back('\'');break; - case '"': //Double quote - val.push_back('"');break; - case '\\': //Backslash character - val.push_back('\\');break; - case '/': //Slash character - val.push_back('/');break; - case 'u': // \uDDDD sequence - { - bool ok = false; - size_t chars_left = buf_end - it - 1; - size_t chars_to_get = std::min(static_cast(4), chars_left); // in [0, 4] - char tmp[10] = {0}; - memcpy(tmp, &(*(it+1)), chars_to_get); - it = it + chars_to_get; // move forward to skip 0..4 digits - if (chars_to_get == 4) - { - char *p_last_decoded_char = nullptr; - unsigned long value = strtoul(tmp, &p_last_decoded_char, 16); // expected value is from 0x0000 (\u0000) to 0x00ff (\u00ff) - if (value <= 0xff && p_last_decoded_char - tmp == 4) - { - val.push_back(static_cast(value)); - ok = true; - } - } - if (!ok) - { - LOG_PRINT_L0("JSON invalid escape sequence: \\u" << tmp); - } - } - break; - default: - val.push_back(*it); - LOG_PRINT_L0("JSON unknown escape sequence :\"\\" << *it << "\""); - } - escape_mode = false; - }else if(*it == '"') - { - star_end_string = it; - return; - }else if(*it == '\\') - { - escape_mode = true; - } - else - { - val.push_back(*it); - } - } - ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - - match_string2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } - inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val, bool& is_float_val, bool& is_signed_val) - { - val.clear(); - is_float_val = false; - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.' ) || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+' )) ) - { - if(!val.size() && *it == '-') - is_signed_val = true; - if(*it == '.' ) - is_float_val = true; - val.push_back(*it); - } - else - { - if(val.size()) - { - star_end_string = --it; - return; - } - else - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - bool is_v_float = false;bool is_signed_val = false; - match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val); - return !is_v_float; - } - catch(...) - { - return false; - } - } - inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(!isalpha(*it)) - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return; - }else - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } - } - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); - } - inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - try - { - match_word2(star_end_string, buf_end, val); - return true; - } - catch(...) - { - return false; - } - } - inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) - { - val.clear(); - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(!isalnum(*it) && *it != '-' && *it != '_') - { - val.assign(star_end_string, it); - if(val.size()) - { - star_end_string = --it; - return true; - }else - return false; - } - } - return false; - } - inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) - { - word_end = star_end_string; - - for(std::string::const_iterator it = star_end_string;it != buf_end;it++) - { - if(isspace(*it)) - { - - continue; - }else if( *it == '=' ) - { - star_end_string = it; - word_end = it; - return true; - } - } - return false; - } - } -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/storages/portable_storage.h b/src/contrib/epee/include/storages/portable_storage.h deleted file mode 100644 index 4d36cc0..0000000 --- a/src/contrib/epee/include/storages/portable_storage.h +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include "misc_language.h" -#include "portable_storage_base.h" -#include "portable_storage_to_bin.h" -#include "portable_storage_from_bin.h" -#include "portable_storage_to_json.h" -#include "portable_storage_from_json.h" -#include "portable_storage_val_converters.h" - -namespace epee -{ - namespace serialization - { - /************************************************************************/ - /* */ - /************************************************************************/ - class portable_storage - { - public: - typedef epee::serialization::hsection hsection; - typedef epee::serialization::harray harray; - typedef storage_entry meta_entry; - - portable_storage(){} - virtual ~portable_storage(){} - hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false); - template - bool get_value(const std::string& value_name, t_value& val, hsection hparent_section); - bool get_value(const std::string& value_name, storage_entry& val, hsection hparent_section); - template - bool set_value(const std::string& value_name, const t_value& target, hsection hparent_section); - - //serial access for arrays of values -------------------------------------- - //values - template - harray get_first_value(const std::string& value_name, t_value& target, hsection hparent_section); - template - bool get_next_value(harray hval_array, t_value& target); - template - harray insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section); - template - bool insert_next_value(harray hval_array, const t_value& target); - //sections - harray get_first_section(const std::string& pSectionName, hsection& h_child_section, hsection hparent_section); - bool get_next_section(harray hSecArray, hsection& h_child_section); - harray insert_first_section(const std::string& pSectionName, hsection& hinserted_childsection, hsection hparent_section); - bool insert_next_section(harray hSecArray, hsection& hinserted_childsection); - //------------------------------------------------------------------------ - //delete entry (section, value or array) - bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr); - - //------------------------------------------------------------------------------- - bool store_to_binary(binarybuffer& target); - bool load_from_binary(const binarybuffer& target); - template - bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); - bool dump_as_json(std::string& targetObj, size_t indent = 0, end_of_line_t eol = eol_crlf); - bool load_from_json(const std::string& source); - - private: - section m_root; - hsection get_root_section() {return &m_root;} - storage_entry* find_storage_entry(const std::string& pentry_name, hsection psection); - template - storage_entry* insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry); - - hsection insert_new_section(const std::string& pentry_name, hsection psection); - -#pragma pack(push) -#pragma pack(1) - struct storage_block_header - { - uint32_t m_signature_a; - uint32_t m_signature_b; - uint8_t m_ver; - }; -#pragma pack(pop) - }; - inline - bool portable_storage::dump_as_json(std::string& buff, size_t indent /* = 0 */, end_of_line_t eol /* = eol_crlf */) - { - TRY_ENTRY(); - std::stringstream ss; - epee::serialization::dump_as_json(ss, m_root, indent, eol); - buff = ss.str(); - return true; - CATCH_ENTRY("portable_storage::dump_as_json", false) - } - inline - bool portable_storage::load_from_json(const std::string& source) - { - TRY_ENTRY(); - return json::load_from_json(source, *this); - CATCH_ENTRY("portable_storage::load_from_json", false) - } - - template - bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name) - { - return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format - } - - inline - bool portable_storage::store_to_binary(binarybuffer& target) - { - TRY_ENTRY(); - std::stringstream ss; - storage_block_header sbh = AUTO_VAL_INIT(sbh); - sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; - sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; - sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; - ss.write((const char*)&sbh, sizeof(storage_block_header)); - pack_entry_to_buff(ss, m_root); - target = ss.str(); - return true; - CATCH_ENTRY("portable_storage::store_to_binary", false) - } - inline - bool portable_storage::load_from_binary(const binarybuffer& source) - { - m_root.m_entries.clear(); - if(source.size() < sizeof(storage_block_header)) - { - LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header)); - return false; - } - storage_block_header* pbuff = (storage_block_header*)source.data(); - if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB - ) - { - LOG_PRINT_RED_L0("portable_storage: wrong binary format - signature missmatch"); - return false; - } - if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER) - { - LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver); - return false; - } - TRY_ENTRY(); - throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header)); - buf_reader.read(m_root); - return true;//TODO: - CATCH_ENTRY("portable_storage::load_from_binary", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist) - { - TRY_ENTRY(); - hparent_section = hparent_section ? hparent_section:&m_root; - storage_entry* pentry = find_storage_entry(section_name, hparent_section); - if(!pentry) - { - if(!create_if_notexist) - return nullptr; - return insert_new_section(section_name, hparent_section); - } - CHECK_AND_ASSERT(pentry , nullptr); - //check that section_entry we find is real "CSSection" - if(pentry->type() != typeid(section)) - { - if(create_if_notexist) - *pentry = storage_entry(section());//replace - else - return nullptr; - } - return &boost::get
(*pentry); - CATCH_ENTRY("portable_storage::open_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_value_visitor: boost::static_visitor - { - to_type& m_target; - get_value_visitor(to_type& target):m_target(target){} - template - void operator()(const from_type& v){convert_t(v, m_target);} - }; - - template - bool portable_storage::get_value(const std::string& value_name, t_value& val, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return false; - - get_value_visitor gvv(val); - boost::apply_visitor(gvv, *pentry); - return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section) - { - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return false; - - val = *pentry; - return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - template - bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains::type, t_value> )); - TRY_ENTRY(); - if(!hparent_section) - hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, v); - if(!pentry) - return false; - return true; - } - *pentry = storage_entry(v); - return true; - CATCH_ENTRY("portable_storage::template<>set_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); - auto it = psection->m_entries.find(pentry_name); - if(it == psection->m_entries.end()) - return nullptr; - - return &it->second; - CATCH_ENTRY("portable_storage::find_storage_entry", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); - auto ins_res = psection->m_entries.insert(std::pair(pentry_name, entry)); - return &ins_res.first->second; - CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection) - { - TRY_ENTRY(); - storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section()); - if(!pse) return nullptr; - return &boost::get
(*pse); - CATCH_ENTRY("portable_storage::insert_new_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_first_value_visitor: boost::static_visitor - { - to_type& m_target; - get_first_value_visitor(to_type& target):m_target(target){} - template - bool operator()(const array_entry_t& a) - { - const from_type* pv = a.get_first_val(); - if(!pv) - return false; - convert_t(*pv, m_target); - return true; - } - }; - //--------------------------------------------------------------------------------------------------------------- - template - harray portable_storage::get_first_value(const std::string& value_name, t_value& target, hsection hparent_section) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - return nullptr; - if(pentry->type() != typeid(array_entry)) - return nullptr; - array_entry& ar_entry = boost::get(*pentry); - - get_first_value_visitor gfv(target); - if(!boost::apply_visitor(gfv, ar_entry)) - return nullptr; - return &ar_entry; - //CATCH_ENTRY("portable_storage::get_first_value", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - struct get_next_value_visitor: boost::static_visitor - { - to_type& m_target; - get_next_value_visitor(to_type& target):m_target(target){} - template - bool operator()(const array_entry_t& a) - { - //TODO: optimize code here: work without get_next_val function - const from_type* pv = a.get_next_val(); - if(!pv) - return false; - convert_t(*pv, m_target); - return true; - } - }; - - - template - bool portable_storage::get_next_value(harray hval_array, t_value& target) - { - BOOST_MPL_ASSERT(( boost::mpl::contains )); - //TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); - array_entry& ar_entry = *hval_array; - get_next_value_visitor gnv(target); - if(!boost::apply_visitor(gnv, ar_entry)) - return false; - return true; - //CATCH_ENTRY("portable_storage::get_next_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - template - harray portable_storage::insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(value_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, array_entry(array_entry_t())); - if(!pentry) - return nullptr; - } - if(pentry->type() != typeid(array_entry)) - *pentry = storage_entry(array_entry(array_entry_t())); - - array_entry& arr = boost::get(*pentry); - if(arr.type() != typeid(array_entry_t)) - arr = array_entry(array_entry_t()); - - array_entry_t& arr_typed = boost::get >(arr); - arr_typed.insert_first_val(target); - return &arr; - CATCH_ENTRY("portable_storage::insert_first_value", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - template - bool portable_storage::insert_next_value(harray hval_array, const t_value& target) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); - - CHECK_AND_ASSERT_MES(hval_array->type() == typeid(array_entry_t), - false, "unexpected type in insert_next_value: " << typeid(array_entry_t).name()); - - array_entry_t& arr_typed = boost::get >(*hval_array); - arr_typed.insert_next_value(target); - return true; - CATCH_ENTRY("portable_storage::insert_next_value", false); - } - //--------------------------------------------------------------------------------------------------------------- - //sections - inline - harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(sec_name, hparent_section); - if(!pentry) - return nullptr; - if(pentry->type() != typeid(array_entry)) - return nullptr; - array_entry& ar_entry = boost::get(*pentry); - if(ar_entry.type() != typeid(array_entry_t
)) - return nullptr; - array_entry_t
& sec_array = boost::get>(ar_entry); - section* psec = sec_array.get_first_val(); - if(!psec) - return nullptr; - h_child_section = psec; - return &ar_entry; - CATCH_ENTRY("portable_storage::get_first_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); - if(hsec_array->type() != typeid(array_entry_t
)) - return false; - array_entry_t
& sec_array = boost::get>(*hsec_array); - h_child_section = sec_array.get_next_val(); - if(!h_child_section) - return false; - return true; - CATCH_ENTRY("portable_storage::get_next_section", false); - } - //--------------------------------------------------------------------------------------------------------------- - inline - harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section) - { - TRY_ENTRY(); - if(!hparent_section) hparent_section = &m_root; - storage_entry* pentry = find_storage_entry(sec_name, hparent_section); - if(!pentry) - { - pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t
())); - if(!pentry) - return nullptr; - } - if(pentry->type() != typeid(array_entry)) - *pentry = storage_entry(array_entry(array_entry_t
())); - - array_entry& ar_entry = boost::get(*pentry); - if(ar_entry.type() != typeid(array_entry_t
)) - ar_entry = array_entry(array_entry_t
()); - - array_entry_t
& sec_array = boost::get>(ar_entry); - hinserted_childsection = &sec_array.insert_first_val(section()); - return &ar_entry; - CATCH_ENTRY("portable_storage::insert_first_section", nullptr); - } - //--------------------------------------------------------------------------------------------------------------- - inline - bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection) - { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); - CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t
), - false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name()); - - array_entry_t
& sec_array = boost::get>(*hsec_array); - hinserted_childsection = &sec_array.insert_next_value(section()); - return true; - CATCH_ENTRY("portable_storage::insert_next_section", false); - } - //--------------------------------------------------------------------------------------------------------------- - } -} diff --git a/src/contrib/epee/include/storages/portable_storage_base.h b/src/contrib/epee/include/storages/portable_storage_base.h deleted file mode 100644 index 99c792e..0000000 --- a/src/contrib/epee/include/storages/portable_storage_base.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include -#include - -#define PORTABLE_STORAGE_SIGNATUREA 0x01011101 -#define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare -#define PORTABLE_STORAGE_FORMAT_VER 1 - -#define PORTABLE_RAW_SIZE_MARK_MASK 0x03 -#define PORTABLE_RAW_SIZE_MARK_BYTE 0 -#define PORTABLE_RAW_SIZE_MARK_WORD 1 -#define PORTABLE_RAW_SIZE_MARK_DWORD 2 -#define PORTABLE_RAW_SIZE_MARK_INT64 3 - -#ifndef MAX_STRING_LEN_POSSIBLE -#define MAX_STRING_LEN_POSSIBLE 2000000000 //do not let string be so big -#endif - -//data types -#define SERIALIZE_TYPE_INT64 1 -#define SERIALIZE_TYPE_INT32 2 -#define SERIALIZE_TYPE_INT16 3 -#define SERIALIZE_TYPE_INT8 4 -#define SERIALIZE_TYPE_UINT64 5 -#define SERIALIZE_TYPE_UINT32 6 -#define SERIALIZE_TYPE_UINT16 7 -#define SERIALIZE_TYPE_UINT8 8 -#define SERIALIZE_TYPE_DUOBLE 9 -#define SERIALIZE_TYPE_STRING 10 -#define SERIALIZE_TYPE_BOOL 11 -#define SERIALIZE_TYPE_OBJECT 12 -#define SERIALIZE_TYPE_ARRAY 13 - -#define SERIALIZE_FLAG_ARRAY 0x80 - - -namespace epee -{ - namespace serialization - { - enum end_of_line_t { eol_crlf = 0, eol_lf = 1, eol_cr = 2, eol_space = 3 }; - - struct section; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct array_entry_t - { - array_entry_t():m_it(m_array.end()){} - array_entry_t(const array_entry_t& other):m_array(other.m_array), m_it(m_array.end()){} - - const t_entry_type* get_first_val() const - { - m_it = m_array.begin(); - return get_next_val(); - } - - t_entry_type* get_first_val() - { - m_it = m_array.begin(); - return get_next_val(); - } - - - const t_entry_type* get_next_val() const - { - if(m_it == m_array.end()) - return nullptr; - return &(*(m_it++)); - } - - t_entry_type* get_next_val() - { - if(m_it == m_array.end()) - return nullptr; - return (t_entry_type*)&(*(m_it++));//fuckoff - } - - t_entry_type& insert_first_val(const t_entry_type& v) - { - m_array.clear(); - m_it = m_array.end(); - return insert_next_value(v); - } - - t_entry_type& insert_next_value(const t_entry_type& v) - { - m_array.push_back(v); - return m_array.back(); - } - - std::list m_array; - mutable typename std::list::const_iterator m_it; - }; - - - typedef boost::make_recursive_variant< - array_entry_t
, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t, - array_entry_t
, - array_entry_t - >::type array_entry; - - typedef boost::variant storage_entry; - - typedef std::string binarybuffer;//it's ok - - /************************************************************************/ - /* */ - /************************************************************************/ - struct section - { - std::map m_entries; - }; - - //handle-like aliases - typedef section* hsection; - typedef array_entry* harray; - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/storages/portable_storage_from_bin.h b/src/contrib/epee/include/storages/portable_storage_from_bin.h deleted file mode 100644 index 2f84d4b..0000000 --- a/src/contrib/epee/include/storages/portable_storage_from_bin.h +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" - -#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT -#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT -#else -#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100 -#endif - -namespace epee -{ - namespace serialization - { - struct throwable_buffer_reader - { - throwable_buffer_reader(const void* ptr, size_t sz); - void read(void* target, size_t count); - void read_sec_name(std::string& sce_name); - template - void read(t_pod_type& pod_val); - template - t_type read(); - template - storage_entry read_ae(); - storage_entry load_storage_array_entry(uint8_t type); - uint64_t read_varint(); - template - storage_entry read_se(); - storage_entry load_storage_entry(); - void read(section& sec); - void read(std::string& str); - private: - struct recursuion_limitation_guard - { - size_t& m_counter_ref; - recursuion_limitation_guard(size_t& counter):m_counter_ref(counter) - { - ++m_counter_ref; - CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded"); - } - ~recursuion_limitation_guard() BOOST_NOEXCEPT_IF(false) - { - CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()"); - --m_counter_ref; - } - }; -#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count) - - const uint8_t* m_ptr; - size_t m_count; - size_t m_recursion_count; - }; - - inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz) - { - if(!ptr) - throw std::runtime_error("throwable_buffer_reader: ptr==nullptr"); - if(!sz) - throw std::runtime_error("throwable_buffer_reader: sz==0"); - m_ptr = (uint8_t*)ptr; - m_count = sz; - m_recursion_count = 0; - } - inline - void throwable_buffer_reader::read(void* target, size_t count) - { - RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained"); - memcpy(target, m_ptr, count); - m_ptr += count; - m_count -= count; - } - inline - void throwable_buffer_reader::read_sec_name(std::string& sce_name) - { - RECURSION_LIMITATION(); - uint8_t name_len = 0; - read(name_len); - sce_name.resize(name_len); - read((void*)sce_name.data(), name_len); - } - - template - void throwable_buffer_reader::read(t_pod_type& pod_val) - { - RECURSION_LIMITATION(); - read(&pod_val, sizeof(pod_val)); - } - - template - t_type throwable_buffer_reader::read() - { - RECURSION_LIMITATION(); - t_type v; - read(v); - return v; - } - - - template - storage_entry throwable_buffer_reader::read_ae() - { - RECURSION_LIMITATION(); - //for pod types - array_entry_t sa; - uint64_t size = read_varint(); - //TODO: add some optimization here later - while(size--) - sa.m_array.push_back(read()); - return storage_entry(array_entry(sa)); - } - - inline - storage_entry throwable_buffer_reader::load_storage_array_entry(uint8_t type) - { - RECURSION_LIMITATION(); - type &= ~SERIALIZE_FLAG_ARRAY; - switch(type) - { - case SERIALIZE_TYPE_INT64: return read_ae(); - case SERIALIZE_TYPE_INT32: return read_ae(); - case SERIALIZE_TYPE_INT16: return read_ae(); - case SERIALIZE_TYPE_INT8: return read_ae(); - case SERIALIZE_TYPE_UINT64: return read_ae(); - case SERIALIZE_TYPE_UINT32: return read_ae(); - case SERIALIZE_TYPE_UINT16: return read_ae(); - case SERIALIZE_TYPE_UINT8: return read_ae(); - case SERIALIZE_TYPE_DUOBLE: return read_ae(); - case SERIALIZE_TYPE_BOOL: return read_ae(); - case SERIALIZE_TYPE_STRING: return read_ae(); - case SERIALIZE_TYPE_OBJECT: return read_ae
(); - case SERIALIZE_TYPE_ARRAY: return read_ae(); - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type); - } - } - - inline - uint64_t throwable_buffer_reader::read_varint() - { - RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint"); - uint64_t v = 0; - uint8_t size_mask = (*(uint8_t*)m_ptr) &PORTABLE_RAW_SIZE_MARK_MASK; - switch (size_mask) - { - case PORTABLE_RAW_SIZE_MARK_BYTE: v = read();break; - case PORTABLE_RAW_SIZE_MARK_WORD: v = read();break; - case PORTABLE_RAW_SIZE_MARK_DWORD: v = read();break; - case PORTABLE_RAW_SIZE_MARK_INT64: v = read();break; - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask); - } - v >>= 2; - return v; - } - - template - storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - t_type v; - read(v); - return storage_entry(v); - } - - template<> - inline storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - return storage_entry(read()); - } - - - template<> - inline storage_entry throwable_buffer_reader::read_se
() - { - RECURSION_LIMITATION(); - section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio - storage_entry se(s); - section& section_entry = boost::get
(se); - read(section_entry); - return se; - } - - template<> - inline storage_entry throwable_buffer_reader::read_se() - { - RECURSION_LIMITATION(); - uint8_t ent_type = 0; - read(ent_type); - CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses"); - return load_storage_array_entry(ent_type); - } - - inline - storage_entry throwable_buffer_reader::load_storage_entry() - { - RECURSION_LIMITATION(); - uint8_t ent_type = 0; - read(ent_type); - if(ent_type&SERIALIZE_FLAG_ARRAY) - return load_storage_array_entry(ent_type); - - switch(ent_type) - { - case SERIALIZE_TYPE_INT64: return read_se(); - case SERIALIZE_TYPE_INT32: return read_se(); - case SERIALIZE_TYPE_INT16: return read_se(); - case SERIALIZE_TYPE_INT8: return read_se(); - case SERIALIZE_TYPE_UINT64: return read_se(); - case SERIALIZE_TYPE_UINT32: return read_se(); - case SERIALIZE_TYPE_UINT16: return read_se(); - case SERIALIZE_TYPE_UINT8: return read_se(); - case SERIALIZE_TYPE_DUOBLE: return read_se(); - case SERIALIZE_TYPE_BOOL: return read_se(); - case SERIALIZE_TYPE_STRING: return read_se(); - case SERIALIZE_TYPE_OBJECT: return read_se
(); - case SERIALIZE_TYPE_ARRAY: return read_se(); - default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type); - } - } - inline - void throwable_buffer_reader::read(section& sec) - { - RECURSION_LIMITATION(); - sec.m_entries.clear(); - uint64_t count = read_varint(); - while(count--) - { - //read section name string - std::string sec_name; - read_sec_name(sec_name); - sec.m_entries.insert(std::make_pair(sec_name, load_storage_entry())); - } - } - inline - void throwable_buffer_reader::read(std::string& str) - { - RECURSION_LIMITATION(); - size_t len = static_cast(read_varint()); - CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len); - CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count); - //do this manually to avoid double memory write in huge strings (first time at resize, second at read) - str.assign((const char*)m_ptr, len); - m_ptr+=len; - m_count -= len; - } - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/storages/portable_storage_from_json.h b/src/contrib/epee/include/storages/portable_storage_from_json.h deleted file mode 100644 index 4e74fb7..0000000 --- a/src/contrib/epee/include/storages/portable_storage_from_json.h +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "parserse_base_utils.h" -#include "file_io_utils.h" - -namespace epee -{ - using namespace misc_utils::parse; - namespace serialization - { - namespace json - { -#define CHECK_ISSPACE() if(!isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} - - /*inline void parse_error() - { - ASSERT_MES_AND_THROW("json parse error"); - }*/ - template - inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg) - { - - std::string::const_iterator sub_element_start; - std::string name; - typename t_storage::harray h_array = nullptr; - enum match_state - { - match_state_lookup_for_section_start, - match_state_lookup_for_name, - match_state_waiting_separator, - match_state_wonder_after_separator, - match_state_wonder_after_value, - match_state_wonder_array, - match_state_array_after_value, - match_state_array_waiting_value, - match_state_error - }; - - enum array_mode - { - array_mode_undifined = 0, - array_mode_sections, - array_mode_string, - array_mode_numbers, - array_mode_booleans - }; - - match_state state = match_state_lookup_for_section_start; - array_mode array_md = array_mode_undifined; - std::string::const_iterator it = sec_buf_begin; - for(;it != buf_end;it++) - { - switch (state) - { - case match_state_lookup_for_section_start: - if(*it == '{') - state = match_state_lookup_for_name; - else CHECK_ISSPACE(); - break; - case match_state_lookup_for_name: - switch(*it) - { - case '"': - match_string2(it, buf_end, name); - state = match_state_waiting_separator; - break; - case '}': - //this is it! section ends here. - //seems that it is empty section - sec_buf_begin = it; - return; - default: - CHECK_ISSPACE(); - } - break; - case match_state_waiting_separator: - if(*it == ':') - state = match_state_wonder_after_separator; - else CHECK_ISSPACE(); - break; - case match_state_wonder_after_separator: - if(*it == '"') - {//just a named string value started - std::string val; - match_string2(it, buf_end, val); - //insert text value - stg.set_value(name, val, current_section); - state = match_state_wonder_after_value; - }else if (isdigit(*it) || *it == '-') - {//just a named number value started - std::string val; - bool is_v_float = false;bool is_signed = false; - match_number2(it, buf_end, val, is_v_float, is_signed); - if(!is_v_float) - { - if(is_signed) - { - int64_t nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - }else - { - uint64_t nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - } - }else - { - double nval = boost::lexical_cast(val); - stg.set_value(name, nval, current_section); - } - state = match_state_wonder_after_value; - }else if(isalpha(*it) ) - {// could be null, true or false - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "null")) - { - state = match_state_wonder_after_value; - //just skip this, - }else if(boost::iequals(word, "true")) - { - stg.set_value(name, true, current_section); - state = match_state_wonder_after_value; - }else if(boost::iequals(word, "false")) - { - stg.set_value(name, false, current_section); - state = match_state_wonder_after_value; - }else ASSERT_MES_AND_THROW("Unknown value keyword " << word); - }else if(*it == '{') - { - //sub section here - typename t_storage::hsection new_sec = stg.open_section(name, current_section, true); - CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end)); - run_handler(new_sec, it, buf_end, stg); - state = match_state_wonder_after_value; - }else if(*it == '[') - {//array of something - state = match_state_wonder_array; - }else CHECK_ISSPACE(); - break; - case match_state_wonder_after_value: - if(*it == ',') - state = match_state_lookup_for_name; - else if(*it == '}') - { - //this is it! section ends here. - sec_buf_begin = it; - return; - }else CHECK_ISSPACE(); - break; - case match_state_wonder_array: - if(*it == '[') - { - ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry"); - //mean array of array - } - if(*it == '{') - { - //mean array of sections - typename t_storage::hsection new_sec = nullptr; - h_array = stg.insert_first_section(name, new_sec, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section"); - run_handler(new_sec, it, buf_end, stg); - state = match_state_array_after_value; - array_md = array_mode_sections; - }else if(*it == '"') - { - //mean array of strings - std::string val; - match_string2(it, buf_end, val); - h_array = stg.insert_first_value(name, val, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); - state = match_state_array_after_value; - array_md = array_mode_string; - }else if (isdigit(*it) || *it == '-') - {//array of numbers value started - std::string val; - bool is_v_float = false;bool is_signed_val = false; - match_number2(it, buf_end, val, is_v_float, is_signed_val); - if(!is_v_float) - { - int64_t nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - }else - { - double nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - } - - state = match_state_array_after_value; - array_md = array_mode_numbers; - }else if(*it == ']')//empty array - { - array_md = array_mode_undifined; - state = match_state_wonder_after_value; - }else if(isalpha(*it) ) - {// array of booleans - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "true")) - { - h_array = stg.insert_first_value(name, true, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - state = match_state_array_after_value; - array_md = array_mode_booleans; - }else if(boost::iequals(word, "false")) - { - h_array = stg.insert_first_value(name, false, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); - state = match_state_array_after_value; - array_md = array_mode_booleans; - - }else ASSERT_MES_AND_THROW("Unknown value keyword " << word) - }else CHECK_ISSPACE(); - break; - case match_state_array_after_value: - if(*it == ',') - state = match_state_array_waiting_value; - else if(*it == ']') - { - h_array = nullptr; - array_md = array_mode_undifined; - state = match_state_wonder_after_value; - }else CHECK_ISSPACE(); - break; - case match_state_array_waiting_value: - switch(array_md) - { - case array_mode_sections: - if(*it == '{') - { - typename t_storage::hsection new_sec = NULL; - bool res = stg.insert_next_section(h_array, new_sec); - CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section"); - run_handler(new_sec, it, buf_end, stg); - state = match_state_array_after_value; - }else CHECK_ISSPACE(); - break; - case array_mode_string: - if(*it == '"') - { - std::string val; - match_string2(it, buf_end, val); - bool res = stg.insert_next_value(h_array, val); - CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); - state = match_state_array_after_value; - }else CHECK_ISSPACE(); - break; - case array_mode_numbers: - if (isdigit(*it) || *it == '-') - {//array of numbers value started - std::string val; - bool is_v_float = false;bool is_signed_val = false; - match_number2(it, buf_end, val, is_v_float, is_signed_val); - bool insert_res = false; - if(!is_v_float) - { - int64_t nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - - }else - { - //TODO: optimize here if need - double nval = boost::lexical_cast(val); //string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - } - CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); - state = match_state_array_after_value; - array_md = array_mode_numbers; - }else CHECK_ISSPACE(); - break; - case array_mode_booleans: - if(isalpha(*it) ) - {// array of booleans - std::string word; - match_word2(it, buf_end, word); - if(boost::iequals(word, "true")) - { - bool r = stg.insert_next_value(h_array, true); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); - state = match_state_array_after_value; - }else if(boost::iequals(word, "false")) - { - bool r = stg.insert_next_value(h_array, false); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); - state = match_state_array_after_value; - } - else ASSERT_MES_AND_THROW("Unknown value keyword " << word); - }else CHECK_ISSPACE(); - break; - case array_mode_undifined: - default: - ASSERT_MES_AND_THROW("Bad array state"); - } - break; - case match_state_error: - default: - ASSERT_MES_AND_THROW("WRONG JSON STATE"); - } - } - } -/* -{ - "firstName": "John", - "lastName": "Smith", - "age": 25, - "address": { - "streetAddress": "21 2nd Street", - "city": "New York", - "state": "NY", - "postalCode": -10021, - "have_boobs": true, - "have_balls": false - }, - "phoneNumber": [ - { - "type": "home", - "number": "212 555-1234" - }, - { - "type": "fax", - "number": "646 555-4567" - } - ], - "phoneNumbers": [ - "812 123-1234", - "916 123-4567" - ] -} -*/ - template - inline bool load_from_json(const std::string& buff_json, t_storage& stg) - { - std::string::const_iterator sec_buf_begin = buff_json.begin(); - try - { - run_handler(nullptr, sec_buf_begin, buff_json.end(), stg); - return true; - } - catch(const std::exception& ex) - { - LOG_PRINT_RED_L0("Failed to parse json, what: " << ex.what()); - return false; - } - catch(...) - { - LOG_PRINT_RED_L0("Failed to parse json"); - return false; - } - } - } - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/storages/portable_storage_template_helper.h b/src/contrib/epee/include/storages/portable_storage_template_helper.h deleted file mode 100644 index 896f9eb..0000000 --- a/src/contrib/epee/include/storages/portable_storage_template_helper.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once -#include "parserse_base_utils.h" -#include "portable_storage.h" -#include "file_io_utils.h" - -namespace epee -{ - namespace serialization - { - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_json(t_struct& out, const std::string& json_buff) - { - portable_storage ps; - bool rs = ps.load_from_json(json_buff); - if(!rs) - return false; - - return out.load(ps); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_json_file(t_struct& out, const std::string& json_file) - { - std::string f_buff; - if(!file_io_utils::load_file_to_string(json_file, f_buff)) - return false; - - return load_t_from_json(out, f_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool store_t_to_json(const t_struct& str_in, std::string& json_buff, size_t indent = 0, end_of_line_t eol = eol_crlf) - { - portable_storage ps; - str_in.store(ps); - ps.dump_as_json(json_buff, indent, eol); - return true; - } - //----------------------------------------------------------------------------------------------------------- - template - std::string store_t_to_json(const t_struct& str_in, size_t indent = 0, end_of_line_t eol = eol_crlf) - { - std::string json_buff; - store_t_to_json(str_in, json_buff, indent); - return json_buff; - } - //----------------------------------------------------------------------------------------------------------- - template - bool store_t_to_json_file(const t_struct& str_in, const std::string& fpath) - { - std::string json_buff; - store_t_to_json(str_in, json_buff); - return file_io_utils::save_string_to_file(fpath, json_buff); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_binary(t_struct& out, const std::string& binary_buff) - { - portable_storage ps; - bool rs = ps.load_from_binary(binary_buff); - if(!rs) - return false; - - return out.load(ps); - } - //----------------------------------------------------------------------------------------------------------- - template - bool load_t_from_binary_file(t_struct& out, const std::string& binary_file) - { - std::string f_buff; - if(!file_io_utils::load_file_to_string(binary_file, f_buff)) - return false; - - return load_t_from_binary(out, f_buff); - } - //----------------------------------------------------------------------------------------------------------- -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4100) - template - bool store_t_to_binary(const t_struct& str_in, std::string& binary_buff, size_t indent = 0) - { - portable_storage ps; - str_in.store(ps); - return ps.store_to_binary(binary_buff); - } -POP_VS_WARNINGS - //----------------------------------------------------------------------------------------------------------- - template - std::string store_t_to_binary(const t_struct& str_in, size_t indent = 0) - { - std::string binary_buff; - store_t_to_binary(str_in, binary_buff, indent); - return binary_buff; - } - } -} diff --git a/src/contrib/epee/include/storages/portable_storage_to_bin.h b/src/contrib/epee/include/storages/portable_storage_to_bin.h deleted file mode 100644 index 97c5cd5..0000000 --- a/src/contrib/epee/include/storages/portable_storage_to_bin.h +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" - -namespace epee -{ - namespace serialization - { - - template - size_t pack_varint_t(t_stream& strm, uint8_t type_or, const uint64_t& pv) - { - pack_value v = (*((pack_value*)&pv)) << 2; - v |= type_or; - strm.write((const char*)&v, sizeof(pack_value)); - return sizeof(pack_value); - } - - PUSH_GCC_WARNINGS - DISABLE_GCC_WARNING(strict-aliasing) - template - size_t pack_varint(t_stream& strm, uint64_t val) - { //the first two bits always reserved for size information - - if(val <= 63) - {//mean enough one byte - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_BYTE, val); - } - else if(val <= 16383) - {//mean need word - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_WORD, val); - }else if(val <= 1073741823) - {//mean need dword - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_DWORD, val); - }else - { - CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val); - return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_INT64, val); - } - } - POP_GCC_WARNINGS - - template - bool put_string(t_stream& strm, const std::string& v) - { - pack_varint(strm, v.size()); - if(v.size()) - strm.write((const char*)v.data(), v.size()); - return true; - } - - template - struct array_entry_store_visitor: public boost::static_visitor - { - t_stream& m_strm; - - template - bool pack_pod_array_type(uint8_t contained_type, const array_entry_t& arr_pod) - { - uint8_t type = contained_type|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_pod.m_array.size()); - for(const t_pod_type& x: arr_pod.m_array) - m_strm.write((const char*)&x, sizeof(t_pod_type)); - return true; - } - - array_entry_store_visitor(t_stream& strm):m_strm(strm){} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT64, v);} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT32, v);} - bool operator()(const array_entry_t& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT16, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_UINT8, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT64, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT32, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT16, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT8, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_DUOBLE, v);} - bool operator()(const array_entry_t& v) { return pack_pod_array_type(SERIALIZE_TYPE_BOOL, v);} - bool operator()(const array_entry_t& arr_str) - { - uint8_t type = SERIALIZE_TYPE_STRING|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_str.m_array.size()); - for(const std::string& s: arr_str.m_array) - put_string(m_strm, s); - return true; - } - bool operator()(const array_entry_t
& arr_sec) - { - uint8_t type = SERIALIZE_TYPE_OBJECT|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arr_sec.m_array.size()); - for(const section& s: arr_sec.m_array) - pack_entry_to_buff(m_strm, s); - return true; - } - bool operator()(const array_entry_t& arra_ar) - { - uint8_t type = SERIALIZE_TYPE_ARRAY|SERIALIZE_FLAG_ARRAY; - m_strm.write((const char*)&type, 1); - pack_varint(m_strm, arra_ar.m_array.size()); - for(const array_entry& s: arra_ar.m_array) - pack_entry_to_buff(m_strm, s); - return true; - } - }; - - template - struct storage_entry_store_visitor: public boost::static_visitor - { - t_stream& m_strm; - storage_entry_store_visitor(t_stream& strm):m_strm(strm){} - template - bool pack_pod_type(uint8_t type, const pod_type& v) - { - m_strm.write((const char*)&type, 1); - m_strm.write((const char*)&v, sizeof(pod_type)); - return true; - } - //section, array_entry - bool operator()(const uint64_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT64, v);} - bool operator()(const uint32_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT32, v);} - bool operator()(const uint16_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT16, v);} - bool operator()(const uint8_t& v) { return pack_pod_type(SERIALIZE_TYPE_UINT8, v);} - bool operator()(const int64_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT64, v);} - bool operator()(const int32_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT32, v);} - bool operator()(const int16_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT16, v);} - bool operator()(const int8_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT8, v);} - bool operator()(const double& v) { return pack_pod_type(SERIALIZE_TYPE_DUOBLE, v);} - bool operator()(const bool& v) { return pack_pod_type(SERIALIZE_TYPE_BOOL, v);} - bool operator()(const std::string& v) - { - uint8_t type = SERIALIZE_TYPE_STRING; - m_strm.write((const char*)&type, 1); - put_string(m_strm, v); - return true; - } - bool operator()(const section& v) - { - uint8_t type = SERIALIZE_TYPE_OBJECT; - m_strm.write((const char*)&type, 1); - return pack_entry_to_buff(m_strm, v); - } - - bool operator()(const array_entry& v) - { - //uint8_t type = SERIALIZE_TYPE_ARRAY; - //m_strm.write((const char*)&type, 1); - return pack_entry_to_buff(m_strm, v); - } - }; - - template - bool pack_entry_to_buff(t_stream& strm, const array_entry& ae) - { - array_entry_store_visitor aesv(strm); - return boost::apply_visitor(aesv, ae); - } - - template - bool pack_entry_to_buff(t_stream& strm, const storage_entry& se) - { - storage_entry_store_visitor sv(strm); - return boost::apply_visitor(sv, se); - } - - template - bool pack_entry_to_buff(t_stream& strm, const section& sec) - { - typedef std::map::value_type section_pair; - pack_varint(strm, sec.m_entries.size()); - for(const section_pair& se: sec.m_entries) - { - CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first); - uint8_t len = static_cast(se.first.size()); - strm.write((const char*)&len, sizeof(len)); - strm.write(se.first.data(), size_t(len)); - pack_entry_to_buff(strm, se.second); - } - return true; - } - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/storages/portable_storage_to_json.h b/src/contrib/epee/include/storages/portable_storage_to_json.h deleted file mode 100644 index 1e2d5d9..0000000 --- a/src/contrib/epee/include/storages/portable_storage_to_json.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" - -namespace epee -{ - namespace serialization - { - - template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol = eol_crlf); - template - void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol = eol_crlf); - - - inline std::string make_indent(size_t indent) - { - return std::string(indent*2, ' '); - } - - template - struct array_entry_store_to_json_visitor: public boost::static_visitor - { - t_stream& m_strm; - size_t m_indent; - end_of_line_t m_eol; - - array_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol) - : m_strm(strm) - , m_indent(indent) - , m_eol(eol) - {} - - template - void operator()(const array_entry_t& a) - { - m_strm << "["; - if(a.m_array.size()) - { - auto last_it = --a.m_array.end(); - for(auto it = a.m_array.begin(); it != a.m_array.end(); it++) - { - dump_as_json(m_strm, *it, m_indent, m_eol); - if(it != last_it) - m_strm << ","; - } - } - m_strm << "]"; - } - }; - - template - struct storage_entry_store_to_json_visitor: public boost::static_visitor - { - t_stream& m_strm; - size_t m_indent; - end_of_line_t m_eol; - - storage_entry_store_to_json_visitor(t_stream& strm, size_t indent, end_of_line_t eol) - : m_strm(strm) - , m_indent(indent) - , m_eol(eol) - {} - - //section, array_entry - template - void operator()(const visited_type& v) - { - dump_as_json(m_strm, v, m_indent, m_eol); - } - }; - - template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, end_of_line_t eol) - { - array_entry_store_to_json_visitor aesv(strm, indent, eol); - boost::apply_visitor(aesv, ae); - } - - template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, end_of_line_t eol) - { - storage_entry_store_to_json_visitor sv(strm, indent, eol); - boost::apply_visitor(sv, se); - } - - template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent, end_of_line_t eol) - { - strm << "\"" << misc_utils::parse::transform_to_json_escape_sequence(v) << "\""; - } - - template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, end_of_line_t eol) - { - strm << static_cast(v); - } - - template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, end_of_line_t eol) - { - strm << static_cast(v); - } - - template - void dump_as_json(t_stream& strm, const bool& v, size_t indent, end_of_line_t eol) - { - if(v) - strm << "true"; - else - strm << "false"; - } - - template - void dump_as_json(t_stream& strm, const double& v, size_t indent, end_of_line_t eol) - { - boost::io::ios_flags_saver ifs(strm); - strm.precision(8); - strm << std::fixed << v; - } - - template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent, end_of_line_t eol) - { - strm << v; - } - - template - void dump_as_json(t_stream& strm, const section& sec, size_t indent, end_of_line_t eol) - { - auto put_eol = [&]() { - switch (eol) - { - case eol_lf: strm << "\n"; break; - case eol_cr: strm << "\r"; break; - case eol_space: strm << " "; break; - default: strm << "\r\n"; break; - } - }; - - size_t local_indent = indent + 1; - strm << "{"; - put_eol(); - std::string indent_str = make_indent(local_indent); - if(sec.m_entries.size()) - { - auto it_last = --sec.m_entries.end(); - for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++) - { - strm << indent_str << "\"" << misc_utils::parse::transform_to_json_escape_sequence(it->first) << "\"" << ": "; - dump_as_json(strm, it->second, local_indent, eol); - if(it_last != it) - strm << ","; - put_eol(); - } - } - strm << make_indent(indent) << "}"; - } - } -} diff --git a/src/contrib/epee/include/storages/portable_storage_val_converters.h b/src/contrib/epee/include/storages/portable_storage_val_converters.h deleted file mode 100644 index caf7a32..0000000 --- a/src/contrib/epee/include/storages/portable_storage_val_converters.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "misc_language.h" -#include "portable_storage_base.h" -#include "warnings.h" - -namespace epee -{ - namespace serialization - { -#define ASSERT_AND_THROW_WRONG_CONVERSION() ASSERT_MES_AND_THROW("WRONG DATA CONVERSION: from type=" << typeid(from).name() << " to type " << typeid(to).name()) - - template - void convert_int_to_uint(const from_type& from, to_type& to) - { -PUSH_VS_WARNINGS -PUSH_GCC_WARNINGS -DISABLE_VS_WARNINGS(4018) - CHECK_AND_ASSERT_THROW_MES(from >=0, "unexpected int value with signed storage value less than 0, and unsigned receiver value: " << from); -DISABLE_GCC_AND_CLANG_WARNING(sign-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); - to = static_cast(from); -POP_GCC_WARNINGS -POP_VS_WARNINGS - } - template - void convert_int_to_int(const from_type& from, to_type& to) - { - CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds::lowest(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with lowest possible value = " << boost::numeric::bounds::lowest()); -PUSH_GCC_WARNINGS -DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); -POP_GCC_WARNINGS - to = static_cast(from); - } - template - void convert_uint_to_any_int(const from_type& from, to_type& to) - { -PUSH_VS_WARNINGS -PUSH_GCC_WARNINGS -DISABLE_VS_WARNINGS(4018) -DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "uint value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); - to = static_cast(from); -POP_GCC_WARNINGS -POP_VS_WARNINGS - } - - template //is from signed, is from to signed - struct convert_to_signed_unsigned; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from signed to signed - convert_int_to_int(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from signed to unsigned - convert_int_to_uint(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - {//from unsigned to signed - convert_uint_to_any_int(from, to); - } - }; - - template - struct convert_to_signed_unsigned - { - static void convert(const from_type& from, to_type& to) - { - //from unsigned to unsigned - convert_uint_to_any_int(from, to); - } - }; - - template - struct convert_to_integral; - - template - struct convert_to_integral - { - static void convert(const from_type& from, to_type& to) - { - convert_to_signed_unsigned::value, std::is_signed::value>::convert(from, to); - } - }; - - template - struct convert_to_integral - { - static void convert(const from_type& from, to_type& to) - { - ASSERT_AND_THROW_WRONG_CONVERSION(); - } - }; - - template - struct is_convertable: std::integral_constant::value && - std::is_integral::value && - !std::is_same::value && - !std::is_same::value > {}; - - template - struct convert_to_same; - - template - struct convert_to_same - { - static void convert(const from_type& from, to_type& to) - { - to = from; - } - }; - - template - struct convert_to_same - { - static void convert(const from_type& from, to_type& to) - { - convert_to_integral::value>::convert(from, to);// ASSERT_AND_THROW_WRONG_CONVERSION(); - } - }; - - inline void convert_t(const uint64_t& from, double& to) - { - to = static_cast(from); - } - inline void convert_t(const int64_t& from, double& to) - { - to = static_cast(from); - } - - template - void convert_t(const from_type& from, to_type& to) - { - convert_to_same::value>::convert(from, to); - } - } -} \ No newline at end of file diff --git a/src/contrib/epee/include/string_coding.h b/src/contrib/epee/include/string_coding.h deleted file mode 100644 index 0b125bb..0000000 --- a/src/contrib/epee/include/string_coding.h +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _STRING_CODING_H_ -#define _STRING_CODING_H_ - -#include -#include -#include -#ifdef WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include -#endif -#include "warnings.h" - - -namespace epee -{ -namespace string_encoding -{ - - inline std::wstring utf8_to_wstring(const std::string& str) - { - return boost::locale::conv::utf_to_utf(str.c_str(), str.c_str() + str.size()); - } - - inline std::string wstring_to_utf8(const std::wstring& str) - { - return boost::locale::conv::utf_to_utf(str.c_str(), str.c_str() + str.size()); - } - - - - - - inline std::string convert_to_ansii(const std::wstring& str_from) - { - PUSH_VS_WARNINGS - DISABLE_VS_WARNINGS(4244) - std::string res(str_from.begin(), str_from.end()); - POP_VS_WARNINGS - return res; - } -#ifdef WIN32 - inline std::string convert_to_ansii_win(const std::wstring& str_from) - { - - int code_page = CP_ACP; - std::string str_trgt; - if(!str_from.size()) - return str_trgt; - int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 ); - if(!cb) - return str_trgt; - str_trgt.resize(cb); - ::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(), - (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); - return str_trgt; - } -#endif - - inline std::string convert_to_ansii(const std::string& str_from) - { - return str_from; - } -#ifdef WIN32 - inline std::wstring convert_to_unicode(const std::string& str_from) - { - std::wstring str_trgt; - if(!str_from.size()) - return str_trgt; - - int cb = ::MultiByteToWideChar(CP_ACP, 0, str_from.data(), (int)str_from.size(), 0, 0); - if(!cb) - return str_trgt; - - str_trgt.resize(cb); - ::MultiByteToWideChar(CP_ACP, 0, str_from.data(), (int)str_from.size(), - (wchar_t*)str_trgt.data(),(int)str_trgt.size()); - return str_trgt; - } -#else - inline std::wstring convert_to_unicode(const std::string& str_from) - { - std::wstring result; - std::locale loc__; - for (unsigned int i = 0; i < str_from.size(); ++i) - { - result += std::use_facet >(loc__).widen(str_from[i]); - } - return result; - } -#endif - inline std::wstring convert_to_unicode(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::wstring& str_from); - - template<> - inline std::string convert_to_t(const std::wstring& str_from) - { - return convert_to_ansii(str_from); - } - - template<> - inline std::wstring convert_to_t(const std::wstring& str_from) - { - return str_from; - } - - template - inline target_string convert_to_t(const std::string& str_from); - - template<> - inline std::string convert_to_t(const std::string& str_from) - { - return str_from; - } - - template<> - inline std::wstring convert_to_t(const std::string& str_from) - { - return convert_to_unicode(str_from); - } - -#ifdef WIN32 - inline std::string convert_ansii_to_utf8(const std::string& str_from) - { - try - { - - std::wstring wstr = epee::string_encoding::convert_to_unicode(str_from); - return epee::string_encoding::wstring_to_utf8(wstr); - } - catch(...) - { - return "BAD_CAST"; - } - } -#endif - - inline - std::string& base64_chars() - { - - static std::string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - return chars; - - } - - inline - std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len) { - std::string ret; - int i = 0; - int j = 0; - unsigned char char_array_3[3]; - unsigned char char_array_4[4]; - - while (in_len--) { - char_array_3[i++] = *(bytes_to_encode++); - if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for(i = 0; (i <4) ; i++) - ret += base64_chars()[char_array_4[i]]; - i = 0; - } - } - - if (i) - { - for(j = i; j < 3; j++) - char_array_3[j] = '\0'; - - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += base64_chars()[char_array_4[j]]; - - while((i++ < 3)) - ret += '='; - - } - - return ret; - - } - - inline - std::string base64_encode(const std::string& str) - { - return base64_encode((unsigned char const* )str.data(), str.size()); - } - - inline bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); - } - - - inline - std::string base64_decode(std::string const& encoded_string) { - size_t in_len = encoded_string.size(); - size_t i = 0; - size_t j = 0; - size_t in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; - - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = (unsigned char)base64_chars().find(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } - - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; - - for (j = 0; j <4; j++) - char_array_4[j] = (unsigned char)base64_chars().find(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; - } - - return ret; - } - - //md5 -#ifdef MD5_H - inline - std::string get_buf_as_hex_string(const void* pbuf, size_t len) - { - std::ostringstream result; - - const unsigned char* p_buff = (const unsigned char*)pbuf; - - for(unsigned int i=0;i(len), output); - return get_buf_as_hex_string(output, sizeof(output)); - } - - inline - std::string get_md5_as_hexstring(const std::string& src) - { - return get_md5_as_hexstring(src.data(), src.size()); - } -#endif - - -} -} - -#endif //_STRING_CODING_H_ diff --git a/src/contrib/epee/include/string_tools.h b/src/contrib/epee/include/string_tools.h deleted file mode 100644 index 95a5d88..0000000 --- a/src/contrib/epee/include/string_tools.h +++ /dev/null @@ -1,808 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _STRING_TOOLS_H_ -#define _STRING_TOOLS_H_ - -//#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include "warnings.h" -#include "auto_val_init.h" -#include "string_coding.h" - - -#ifndef OUT - #define OUT -#endif - -#ifdef WINDOWS_PLATFORM -#pragma comment (lib, "Rpcrt4.lib") -#endif - -namespace epee -{ -namespace string_tools -{ - - - inline std::wstring get_str_from_guid(const boost::uuids::uuid& rid) - { - return boost::lexical_cast(rid); - } - //---------------------------------------------------------------------------- - inline std::string get_str_from_guid_a(const boost::uuids::uuid& rid) - { - return boost::lexical_cast(rid); - } - //---------------------------------------------------------------------------- - inline bool get_guid_from_string( boost::uuids::uuid& inetifer, std::wstring str_id) - { - if(str_id.size() < 36) - return false; - - if('{' == *str_id.begin()) - str_id.erase(0, 1); - - if('}' == *(--str_id.end())) - str_id.erase(--str_id.end()); - - try - { - inetifer = boost::lexical_cast(str_id); - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - inline - std::string get_user_home_dir(std::string path) - { - const char* phomedir = getenv("HOME"); - if (phomedir) - return phomedir; - else - return "~"; - } - //---------------------------------------------------------------------------- - inline bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id) - { - std::string local_str_id = str_id; - if(local_str_id.size() < 36) - return false; - - if('{' == *local_str_id.begin()) - local_str_id.erase(0, 1); - - if('}' == *(--local_str_id.end())) - local_str_id.erase(--local_str_id.end()); - - try - { - inetifer = boost::lexical_cast(local_str_id); - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - template< typename T > - std::string int_to_hex(T i) - { - std::stringstream stream; - stream << "0x" - << std::setfill('0') << std::setw(sizeof(T)* 2) - << std::hex << i; - return stream.str(); - } - //---------------------------------------------------------------------------- - template - std::basic_string buff_to_hex(const std::basic_string& s) - { - using namespace std; - basic_stringstream hexStream; - hexStream << hex << noshowbase << setw(2); - - for(typename std::basic_string::const_iterator it = s.begin(); it != s.end(); it++) - { - hexStream << "0x"<< static_cast(static_cast(*it)) << " "; - } - return hexStream.str(); - } - //---------------------------------------------------------------------------- - template - std::basic_string buff_to_hex_nodelimer(const std::basic_string& s) - { - using namespace std; - basic_stringstream hexStream; - hexStream << hex << noshowbase; - - for(typename std::basic_string::const_iterator it = s.begin(); it != s.end(); it++) - { - hexStream << setw(2) << setfill('0') << static_cast(static_cast(*it)); - } - return hexStream.str(); - } - - - //---------------------------------------------------------------------------- - template - bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res) - { - res.clear(); - try - { - long v = 0; - for(size_t i = 0; i < (s.size() + 1) / 2; i++) - { - CharT byte_str[3]; - size_t copied = s.copy(byte_str, 2, 2 * i); - byte_str[copied] = CharT(0); - CharT* endptr; - v = strtoul(byte_str, &endptr, 16); - if (v < 0 || 0xFF < v || endptr != byte_str + copied) - { - return false; - } - res.push_back(static_cast(v)); - } - - return true; - }catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - template - bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod) - { - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(t_pod_type)) - { - return false; - } - else - { - buf.copy(reinterpret_cast(&t_pod), sizeof(t_pod_type)); - return true; - } - } - //---------------------------------------------------------------------------- - template - t_pod_type parse_tpod_from_hex_string(const std::string& str_hash) - { - t_pod_type t_pod = AUTO_VAL_INIT(t_pod); - parse_tpod_from_hex_string(str_hash, t_pod); - return t_pod; - } - //---------------------------------------------------------------------------- -PUSH_GCC_WARNINGS -DISABLE_GCC_WARNING(maybe-uninitialized) - template - inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id) - { - if (std::is_integral::value && !std::numeric_limits::is_signed && !std::is_same::value) - { - for (char c : str_id) - { - if (!std::isdigit(c)) - return false; - } - } - - try - { - val = boost::lexical_cast(str_id); - return true; - } - catch(std::exception& /*e*/) - { - //const char* pmsg = e.what(); - return false; - } - catch(...) - { - return false; - } - - return true; - } -POP_GCC_WARNINGS - //--------------------------------------------------- - template - bool get_xnum_from_hex_string(const std::string str, int_t& res ) - { - try - { - std::stringstream ss; - ss << std::hex << str; - ss >> res; - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- - template - inline bool xtype_to_string(const XType& val, std::string& str) - { - try - { - str = boost::lexical_cast(val); - } - catch(...) - { - return false; - } - - return true; - } - - typedef std::map command_line_params_a; - typedef std::map command_line_params_w; - - template - void append_pod_to_strbuff(std::string& buff, const t_pod_data& pod) - { - buff.append(reinterpret_cast(&pod), sizeof(pod)); - } - - template - bool get_pod_from_strbuff(const std::string& buff, pod_t& output) - { - if (buff.size() != sizeof(pod_t)) - return false; - output = *reinterpret_cast(buff.data()); - return true; - } - - template - bool parse_commandline(std::map& res, int argc, char** argv) - { - t_string key; - for(int i = 1; i < argc; i++) - { - if(!argv[i]) - break; - t_string s = argv[i]; - std::string::size_type p = s.find('='); - if(std::string::npos == p) - { - res[s] = ""; - }else - { - std::string ss; - t_string nm = s.substr(0, p); - t_string vl = s.substr(p+1, s.size()); - res[nm] = vl; - } - } - return true; - } - -/* template - bool get_xparam_from_command_line(const std::map& res, const std::basic_string & key, t_type& val) - { - - } - */ - - template - bool get_xparam_from_command_line(const std::map& res, const t_string & key, t_type& val) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - if(it->second.size()) - { - return get_xtype_from_string(val, it->second); - } - - return true; - } - - template - t_type get_xparam_from_command_line(const std::map& res, const t_string & key, const t_type& default_value) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return default_value; - - if(it->second.size()) - { - t_type s; - get_xtype_from_string(s, it->second); - return s; - } - - return default_value; - } - - template - bool have_in_command_line(const std::map& res, const std::basic_string& key) - { - typename std::map::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - return true; - } - - //---------------------------------------------------------------------------- -//#ifdef _WINSOCK2API_ - inline std::string get_ip_string_from_int32(uint32_t ip) - { - in_addr adr; - adr.s_addr = ip; - const char* pbuf = inet_ntoa(adr); - if(pbuf) - return pbuf; - else - return "[failed]"; - } - //---------------------------------------------------------------------------- - inline bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str) - { - ip = inet_addr(ip_str.c_str()); - if(INADDR_NONE == ip) - return false; - - return true; - } - //---------------------------------------------------------------------------- - inline bool parse_peer_from_string(uint32_t& ip, uint32_t& port, const std::string& addres) - { - //parse ip and address - std::string::size_type p = addres.find(':'); - if(p == std::string::npos) - { - return false; - } - std::string ip_str = addres.substr(0, p); - std::string port_str = addres.substr(p+1, addres.size()); - - if(!get_ip_int32_from_string(ip, ip_str)) - { - return false; - } - - if(!get_xtype_from_string(port, port_str)) - { - return false; - } - return true; - } - -//#endif - //---------------------------------------------------------------------------- - template - inline std::string get_t_as_hex_nwidth(const t& v, std::streamsize w = 8) - { - std::stringstream ss; - ss << std::setfill ('0') << std::setw (w) << std::hex << std::noshowbase; - ss << v; - return ss.str(); - } - - inline std::string num_to_string_fast(int64_t val) - { - /* - char buff[30] = {0}; - i64toa_s(val, buff, sizeof(buff)-1, 10); - return buff;*/ - return boost::lexical_cast(val); - } - //---------------------------------------------------------------------------- - inline bool string_to_num_fast(const std::string& buff, int64_t& val) - { - //return get_xtype_from_string(val, buff); -#if (defined _MSC_VER) - val = _atoi64(buff.c_str()); -#else - val = atoll(buff.c_str()); -#endif - /* - * val = atoi64(buff.c_str()); - */ - if(buff != "0" && val == 0) - return false; - return true; - } - //---------------------------------------------------------------------------- - inline bool string_to_num_fast(const std::string& buff, int& val) - { - val = atoi(buff.c_str()); - if(buff != "0" && val == 0) - return false; - - return true; - } - //---------------------------------------------------------------------------- -#ifdef WINDOWS_PLATFORM - inline std::string system_time_to_string(const SYSTEMTIME& st) - { - - /* - TIME_ZONE_INFORMATION tzi; - GetTimeZoneInformation(&tzi); - SystemTimeToTzSpecificLocalTime(&tzi, &stUTC, &stLocal); - */ - - char szTime[25], szDate[25]; - ::GetTimeFormatA( - LOCALE_USER_DEFAULT, // locale - TIME_FORCE24HOURFORMAT, // options - &st, // time - NULL, // time format string - szTime, // formatted string buffer - 25 // size of string buffer - ); - - ::GetDateFormatA( - LOCALE_USER_DEFAULT, // locale - NULL, // options - &st, // date - NULL, // date format - szDate, // formatted string buffer - 25 // size of buffer - ); - szTime[24] = szDate[24] = 0; //be happy :) - - std::string res = szDate; - (res += " " )+= szTime; - return res; - - } -#endif - //---------------------------------------------------------------------------- - - inline bool compare_no_case(const std::string& str1, const std::string& str2) - { - - return !boost::iequals(str1, str2); - } - //---------------------------------------------------------------------------- - inline bool compare_no_case(const std::wstring& str1, const std::wstring& str2) - { - return !boost::iequals(str1, str2); - } - //---------------------------------------------------------------------------- - inline bool is_match_prefix(const std::wstring& str1, const std::wstring& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- - inline bool is_match_prefix(const std::string& str1, const std::string& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- - inline std::string& get_current_module_name() - { - static std::string module_name; - return module_name; - } - //---------------------------------------------------------------------------- - inline std::string& get_current_module_folder() - { - static std::string module_folder; - return module_folder; - } - //---------------------------------------------------------------------------- - inline bool set_module_name_and_folder(const std::string& path_to_process_) - { - boost::filesystem::path path(epee::string_encoding::utf8_to_wstring(path_to_process_)); - - get_current_module_folder() = epee::string_encoding::wstring_to_utf8(path.parent_path().wstring()); - get_current_module_name() = epee::string_encoding::wstring_to_utf8(path.filename().wstring()); - - return true; - } - //---------------------------------------------------------------------------- - inline bool trim_left(std::string& str) - { - for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast(*it));) - str.erase(str.begin()); - - return true; - } - //---------------------------------------------------------------------------- - inline bool trim_right(std::string& str) - { - - for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast(*it));) - str.erase( --((it++).base())); - - return true; - } - //---------------------------------------------------------------------------- - inline std::string& trim(std::string& str) - { - - trim_left(str); - trim_right(str); - return str; - } - //---------------------------------------------------------------------------- - inline std::string trim(const std::string& str_) - { - std::string str = str_; - trim_left(str); - trim_right(str); - return str; - } - //---------------------------------------------------------------------------- - template - std::string pod_to_hex(const t_pod_type& s) - { - std::string buff; - buff.assign(reinterpret_cast(&s), sizeof(s)); - return buff_to_hex_nodelimer(buff); - } - //---------------------------------------------------------------------------- - template - bool hex_to_pod(const std::string& hex_str, t_pod_type& s) - { - std::string hex_str_tr = trim(hex_str); - if(sizeof(s)*2 != hex_str.size()) - return false; - std::string bin_buff; - if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) - return false; - if(bin_buff.size()!=sizeof(s)) - return false; - - s = *(t_pod_type*)bin_buff.data(); - return true; - } - //---------------------------------------------------------------------------- - template - t_pod_type hex_to_pod(const std::string& hex_str) - { - t_pod_type p = AUTO_VAL_INIT(p); - if (!hex_to_pod(hex_str, p)) - return AUTO_VAL_INIT_T(t_pod_type); - return p; - } - //---------------------------------------------------------------------------- - inline std::string get_extension(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('.'); - if(std::string::npos == pos) - return res; - - res = str.substr(pos+1, str.size()-pos); - return res; - } - //---------------------------------------------------------------------------- - inline std::string get_filename_from_path(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('\\'); - if(std::string::npos == pos) - return str; - - res = str.substr(pos+1, str.size()-pos); - return res; - } - //---------------------------------------------------------------------------- - inline std::string cut_off_extension(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('.'); - if(std::string::npos == pos) - return str; - - res = str.substr(0, pos); - return res; - } - //---------------------------------------------------------------------------- - inline std::wstring cut_off_extension(const std::wstring& str) - { - std::wstring res; - std::wstring::size_type pos = str.rfind('.'); - if (std::wstring::npos == pos) - return str; - - res = str.substr(0, pos); - return res; - } - //---------------------------------------------------------------------------- - // replaces all non-ascii characters with mask_character - inline std::string mask_non_ascii_chars(const std::string& str, const char mask_character = '?') - { - std::string result; - result.reserve(str.size()); - for (char c : str) - { - if ((unsigned char)c >= (unsigned char)' ' && - (unsigned char)c <= (unsigned char)'~') - { - result += c; - } - else - { - result += mask_character; - } - } - return result; - } - //---------------------------------------------------------------------------- -#ifdef _WININET_ - inline std::string get_string_from_systemtime(const SYSTEMTIME& sys_time) - { - std::string result_string; - - char buff[100] = {0}; - BOOL res = ::InternetTimeFromSystemTimeA(&sys_time, INTERNET_RFC1123_FORMAT, buff, 99); - if(!res) - { - LOG_ERROR("Failed to load SytemTime to string"); - } - - result_string = buff; - return result_string; - - } - //------------------------------------------------------------------------------------- - inline SYSTEMTIME get_systemtime_from_string(const std::string& buff) - { - SYSTEMTIME result_time = {0}; - - BOOL res = ::InternetTimeToSystemTimeA(buff.c_str(), &result_time, NULL); - if(!res) - { - LOG_ERROR("Failed to load SytemTime from string " << buff << "interval set to 15 minutes"); - } - - return result_time; - } -#endif - -#ifdef WINDOWS_PLATFORM - static const DWORD INFO_BUFFER_SIZE = 10000; - - static const wchar_t* get_pc_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetComputerNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } - - static const wchar_t* get_user_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetUserNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } -#endif - -#ifdef _LM_ - static const wchar_t* get_domain_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = 0; - static bool init = false; - - if (!init) { - LPWSTR domain( NULL ); - NETSETUP_JOIN_STATUS status; - info[0] = 0; - - if (NET_API_STATUS result = NetGetJoinInformation( NULL, &domain, &status )) - { - LOG_ERROR("get_domain_name error: " << log_space::get_win32_err_descr(result)); - } else - { - StringCchCopyW( info, sizeof(info)/sizeof( info[0] ), domain ); - NetApiBufferFree((void*)domain); - init = true; - } - } - - return info; - } -#endif -#ifdef WINDOWS_PLATFORM - inline - std::string load_resource_string_a(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - char buff[2000] = {0}; - - ::LoadStringA( h, id, buff, sizeof(buff)); - buff[sizeof(buff)-1] = 0; //be happy :) - return buff; - } - inline - std::wstring load_resource_string_w(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - wchar_t buff[2000] = {0}; - - ::LoadStringW( h, id, buff, sizeof(buff) / sizeof( buff[0] ) ); - buff[(sizeof(buff)/sizeof(buff[0]))-1] = 0; //be happy :) - return buff; - } -#endif -} -} -#endif //_STRING_TOOLS_H_ diff --git a/src/contrib/epee/include/sync_locked_object.h b/src/contrib/epee/include/sync_locked_object.h deleted file mode 100644 index 2980bbb..0000000 --- a/src/contrib/epee/include/sync_locked_object.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "syncobj.h" -#include "misc_log_ex.h" - -namespace epee -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct default_lock_time_watching_policy - { - inline static void watch_lock_time(uint64_t lock_time) {} - }; - - template - class locked_object_proxy - { - uint64_t start_lock_time; - t_object& rt; - std::unique_lock lock; - public: - locked_object_proxy(t_object& t, std::recursive_mutex& m) :rt(t), lock(m), start_lock_time(epee::misc_utils::get_tick_count()) - {} - locked_object_proxy(const locked_object_proxy& lop) :rt(lop.rt), lock(*lop.lock.mutex()), start_lock_time(epee::misc_utils::get_tick_count()) - {} - ~locked_object_proxy() - { - TRY_ENTRY(); - uint64_t lock_time = epee::misc_utils::get_tick_count() - start_lock_time; - lock_time_watching_policy::watch_lock_time(lock_time); - CATCH_ALL_DO_NOTHING(); - } - - /* - t_object& operator()() - { - return rt; - }*/ - t_object* operator ->() - { - return &rt; - } - t_object& operator *() - { - return rt; - } - }; - - template - class locked_object - { - - t_object t; - mutable std::recursive_mutex m; - template - friend class locked_object_proxy; - public: - std::shared_ptr> lock() - { - std::shared_ptr> res; - res.reset(new locked_object_proxy(t, m)); - return res; - } - - std::shared_ptr> try_lock() - { - std::shared_ptr> res; - if (CRITICAL_SECTION_TRY_LOCK(m)) - { - res.reset(new locked_object_proxy(t, m)); - CRITICAL_SECTION_UNLOCK(m); - } - return res; - } - t_object& unlocked_get() - { - return t; - } - - locked_object_proxy operator->() - { - return locked_object_proxy(t, m); - } - locked_object_proxy operator*() - { - return locked_object_proxy(t, m); - } - - locked_object_proxy operator->() const - { - return locked_object_proxy(t, m); - } - - locked_object_proxy operator*() const - { - return locked_object_proxy(t, m); - } - - /*locked_object_proxy operator()() - { - return locked_object_proxy(t, m); - }*/ - }; -} \ No newline at end of file diff --git a/src/contrib/epee/include/syncobj.h b/src/contrib/epee/include/syncobj.h deleted file mode 100644 index 07c0a48..0000000 --- a/src/contrib/epee/include/syncobj.h +++ /dev/null @@ -1,714 +0,0 @@ -// Copyright (c) 2019, Zano Project -// Copyright (c) 2019, anonimal, -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#pragma once -#include -#include -#include -#include -#include -#include -#include - -#include "singleton.h" -#include "static_helpers.h" -#include "misc_helpers.h" - -//#define DISABLE_DEADLOCK_GUARD - - -namespace epee -{ - - struct simple_event - { - simple_event() : m_rised(false) - { - } - - void raise() - { - std::unique_lock lock(m_mx); - m_rised = true; - m_cond_var.notify_one(); - } - - void wait() - { - std::unique_lock lock(m_mx); - while (!m_rised) - m_cond_var.wait(lock); - m_rised = false; - } - - private: - std::mutex m_mx; - std::condition_variable m_cond_var; - bool m_rised; - }; - - - class critical_region; - - class critical_section - { - boost::recursive_mutex m_section; - - public: - //to make copy fake! - critical_section(const critical_section& section) - { - } - - critical_section() - { - } - - ~critical_section() - { - } - - void lock() - { - m_section.lock(); - //EnterCriticalSection( &m_section ); - } - - void unlock() - { - m_section.unlock(); - } - - bool try_lock() - { - return m_section.try_lock(); - } - - // to make copy fake - critical_section& operator=(const critical_section& section) - { - return *this; - } - }; - - class dummy_critical_section - { - - public: - //to make copy fake! - dummy_critical_section(const critical_section& section) - { - } - dummy_critical_section() - { - } - ~dummy_critical_section() - { - } - void lock(){} - void unlock(){} - void lock_exclusive(){} - void unlock_exclusive(){} - - bool tryLock(){ return true; } - - // to make copy fake - dummy_critical_section& operator=(const dummy_critical_section& section) - { - return *this; - } - }; - - - - - template - class critical_region_t - { - t_lock& m_locker; - bool m_unlocked; - - critical_region_t(const critical_region_t&) {} - - public: - critical_region_t(t_lock& cs): m_locker(cs), m_unlocked(false) - { - m_locker.lock(); - } - - ~critical_region_t() - { - unlock(); - } - - void unlock() - { - if (!m_unlocked) - { - m_locker.unlock(); - m_unlocked = true; - } - } - }; - - - -#if defined(WINDWOS_PLATFORM) - class shared_critical_section - { - public: - shared_critical_section() - { - ::InitializeSRWLock(&m_srw_lock); - } - ~shared_critical_section() - {} - - bool lock_shared() - { - AcquireSRWLockShared(&m_srw_lock); - return true; - } - bool unlock_shared() - { - ReleaseSRWLockShared(&m_srw_lock); - return true; - } - bool lock_exclusive() - { - ::AcquireSRWLockExclusive(&m_srw_lock); - return true; - } - bool unlock_exclusive() - { - ::ReleaseSRWLockExclusive(&m_srw_lock); - return true; - } - private: - SRWLOCK m_srw_lock; - }; - - - class shared_guard - { - public: - shared_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_shared(); - } - - ~shared_guard() - { - m_ref_sec.unlock_shared(); - } - - private: - shared_critical_section& m_ref_sec; - }; - - - class exclusive_guard - { - public: - exclusive_guard(shared_critical_section& ref_sec):m_ref_sec(ref_sec) - { - m_ref_sec.lock_exclusive(); - } - - ~exclusive_guard() - { - m_ref_sec.unlock_exclusive(); - } - - private: - shared_critical_section& m_ref_sec; - }; - -#endif - - - - - -#if defined(WINDWOS_PLATFORM) - inline const char* get_wait_for_result_as_text(DWORD res) - { - switch(res) - { - case WAIT_ABANDONED: return "WAIT_ABANDONED"; - case WAIT_TIMEOUT: return "WAIT_TIMEOUT"; - case WAIT_OBJECT_0: return "WAIT_OBJECT_0"; - case WAIT_OBJECT_0+1: return "WAIT_OBJECT_1"; - case WAIT_OBJECT_0+2: return "WAIT_OBJECT_2"; - default: return "UNKNOWN CODE"; - } - } -#endif - -#ifdef ENABLE_DLG_DEBUG_MESSAGES -#define DO_DEBUG_COUT(mes) std::cout << mes; -#else -#define DO_DEBUG_COUT(mes) -#endif - -#define POTENTIAL_HANG_PREVENT_LIMIT 1000 - - - - /************************************************************************/ - /* */ - /************************************************************************/ - class deadlock_guard - { - public: - typedef void* lock_reference_type; - private: - struct thread_info - { - std::map m_owned_objects; - bool is_blocked; - lock_reference_type blocker_lock; - const char* block_location; - const char* func_name; - const char* lock_name; - std::string thread_name; - }; - - std::recursive_mutex m_lock; - - //thread_id -> owned locks(lock_id, recursion_count) - typedef std::map thread_id_to_info_map; - std::map m_thread_owned_locks; - //lock -> owner thread it - std::map m_owned_locks_to_thread; - // deadlock journal - std::list m_deadlock_journal; - - public: - void on_before_lock(lock_reference_type lock, const char* func_name, const char* loction, const char* lock_name, const std::string& thread_name) - { - std::lock_guard gd(m_lock); - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][BEFORE_LOCK]:" << lock << std::endl); - std::thread::id this_id = std::this_thread::get_id(); - is_lock_safe(lock, this_id, func_name, loction, lock_name, thread_name);//can return only true, if false throw exception - - thread_info& ti = m_thread_owned_locks[this_id]; - ti.is_blocked = true; - ti.blocker_lock = lock; - ti.block_location = loction; - ti.func_name = func_name; - ti.lock_name = lock_name; - ti.thread_name = thread_name; - } - void on_after_lock(lock_reference_type lock) - { - std::lock_guard gd(m_lock); - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][AFTER_LOCK]:" << lock << std::endl); - add_ownership(lock); - } - - void on_unlock(lock_reference_type lock) - { - std::lock_guard gd(m_lock); - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][UNLOCK]:" << lock << std::endl); - std::thread::id this_id = std::this_thread::get_id(); - auto it = m_thread_owned_locks.find(this_id); - if (it == m_thread_owned_locks.end()) - { - throw std::runtime_error("Internal error: unknown thread is unlocking mutex"); - } - - if (it->second.is_blocked) - { - throw std::runtime_error("Internal error: thread is trying to unlock while is_blocked = true"); - } - auto ownership_it = it->second.m_owned_objects.find(lock); - if (ownership_it == it->second.m_owned_objects.end()) - { - throw std::runtime_error("Internal error: can't find ownership for locker on unlock"); - } - - ownership_it->second--; - if (!ownership_it->second) - { - // ownership liquidation - auto lock_to_thread_it = m_owned_locks_to_thread.find(lock); - if (lock_to_thread_it == m_owned_locks_to_thread.end()) - { - throw std::runtime_error("Internal error: can't find ownership for locker on unlock"); - } - else - { - m_owned_locks_to_thread.erase(lock_to_thread_it); - } - it->second.m_owned_objects.erase(ownership_it); - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][REMOVED_OWNERSHIP]: " << lock << std::endl); - } - } - - std::string get_dlg_state() - { - std::lock_guard gd(m_lock); - std::stringstream ss; - ss << "Threads lockers ownership:" << std::endl; - for (auto& tol : m_thread_owned_locks) - { - ss << tol.second.thread_name << "(tid:" << tol.first << ") owned: "; - for (auto& owned_obj: tol.second.m_owned_objects) - { - ss << "(" << owned_obj.first << ":" << owned_obj.second << ")"; - } - if (tol.second.is_blocked) - { - ss << "BLOCKED BY: \"" << tol.second.lock_name << "\"(" << tol.second.blocker_lock << ") at " << tol.second.func_name << " @ " << tol.second.block_location; - } - ss << std::endl; - } - - ss << "Lockers to threads links:" << std::endl; - for(auto& lock_to_thread: m_owned_locks_to_thread) - { - ss << "locker: " << lock_to_thread.first << " owned by " << lock_to_thread.second->first << std::endl; - } - ss << "Deadlocks history:" << std::endl; - for (auto err : m_deadlock_journal) - { - ss << "-----------------------------------------------------------------------" << std::endl << err << std::endl; - } - - return ss.str(); - } - - std::list get_deadlock_journal() - { - return m_deadlock_journal; - } - - private: - void add_ownership(lock_reference_type lock) - { - std::thread::id this_id = std::this_thread::get_id(); - auto it = m_thread_owned_locks.find(this_id); - if (it == m_thread_owned_locks.end()) - { - // it's ok, probably someone used try_lock and didn't call on_before_lock - auto r = m_thread_owned_locks.insert(std::make_pair(this_id, thread_info())); - it = r.first; - } - thread_info& ti = it->second; - ti.is_blocked = false; - auto lock_it = ti.m_owned_objects.find(lock); - if (lock_it == ti.m_owned_objects.end()) - { - //non-recursive ownership - ti.m_owned_objects[lock] = 1; - //need to add lock-to-thread reccord - m_owned_locks_to_thread[lock] = it; - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][ADDED_OWNERSHIP]: " << lock << std::endl); - } - else - { - lock_it->second++; - DO_DEBUG_COUT("[" << std::this_thread::get_id() << "][INC_OWNERSHIP]: " << lock << std::endl); - } - } - - bool is_lock_safe(lock_reference_type lock, const std::thread::id& this_id, const char* func_name, const char* location, const char* lock_name, const std::string& thread_name) - { - //lookup if this lock is already owned by someone - auto it_th_owned_locks = m_thread_owned_locks.find(this_id); - if (it_th_owned_locks == m_thread_owned_locks.end()) - { - return true; - } - //we already own some locks, let's figure out if this lock is owned by someone - auto it_to_owner_thread = m_owned_locks_to_thread.find(lock); - if (it_to_owner_thread == m_owned_locks_to_thread.end() || it_to_owner_thread->second->first == this_id) - { - //lock is free or owned by this thread - return true; - } - std::listsecond)> threads_chain; - threads_chain.push_back(it_to_owner_thread->second); - - //lookup loop - while (true) - { - if (!it_to_owner_thread->second->second.is_blocked) - { - return true; - } - if (it_to_owner_thread->second->second.m_owned_objects.count(it_to_owner_thread->second->second.blocker_lock)) - { - //recursive lock is happening - return true; - } - - auto new_it_to_owner_thread = m_owned_locks_to_thread.find(it_to_owner_thread->second->second.blocker_lock); - if (new_it_to_owner_thread == m_owned_locks_to_thread.end()) - { - //this could happen when on_before_lock already worked and on_after_lock not called yet, but mutex itself is free, - //still theoretically possible deadlock that can be missed(or not ?) - return true; - } - if (it_to_owner_thread == new_it_to_owner_thread) - { - //newer should happen - throw std::runtime_error("Internal error: thread referred to itself, despite the the check in m_owned_locks_to_thread.find(it_to_owner_thread->second->second.blocker_lock); "); - } - it_to_owner_thread = new_it_to_owner_thread; - - threads_chain.push_back(it_to_owner_thread->second); - if (threads_chain.size() > POTENTIAL_HANG_PREVENT_LIMIT) - { - throw std::runtime_error("Internal error: threads_chain size is too big, endless loop detected"); - } - if (it_to_owner_thread->second->first == this_id) - { - //got deadlock! - std::stringstream ss; - ss << "Deadlock detected at: " << std::endl << std::endl; - auto prev_it = m_thread_owned_locks.end(); - auto current_it = *threads_chain.begin(); - for (auto it = threads_chain.begin(); it != threads_chain.end(); it++) - { - current_it = *it; - if (prev_it == m_thread_owned_locks.end()) - { - prev_it = current_it; - continue; - } - ss << prev_it->second.thread_name << "(tid:" << prev_it->first << ") blocked by locker \"" << prev_it->second.lock_name - << "\"(owned by " << current_it->second.thread_name << " tid:" << current_it->first << ")] at " - << prev_it->second.func_name << " @ " << prev_it->second.block_location << std::endl << " |" << std::endl << " V" << std::endl; - prev_it = current_it; - } - if (prev_it != m_thread_owned_locks.end()) - { - ss << prev_it->second.thread_name << "(tid:" << prev_it->first << ") blocked by locker \"" << lock_name << "(owned by " << (*threads_chain.begin())->second.thread_name << " tid:" << (*threads_chain.begin())->first << ")] at " - << func_name << " @ " << location << std::endl; - } - m_deadlock_journal.push_back(ss.str()); - throw std::runtime_error(ss.str()); - } - - } - } - }; - - //const static initializer > singleton_initializer; - - /************************************************************************/ - /* */ - /************************************************************************/ - class deadlock_guard_singleton - { - public: - static void on_before_lock(deadlock_guard::lock_reference_type lock, const char* func_name, const char* loction, const char* lock_name, const std::string& thread_name) - { - auto dlg_ptr = abstract_singleton::get_instance(); - if (dlg_ptr) - dlg_ptr->on_before_lock(lock, func_name, loction, lock_name, thread_name); - } - static void on_after_lock(deadlock_guard::lock_reference_type lock) - { - auto dlg_ptr = abstract_singleton::get_instance(); - if (dlg_ptr) - dlg_ptr->on_after_lock(lock); - } - static void on_unlock(deadlock_guard::lock_reference_type lock) - { - auto dlg_ptr = abstract_singleton::get_instance(); - if (dlg_ptr) - dlg_ptr->on_unlock(lock); - } - - static std::string get_dlg_state() - { - auto dlg_ptr = abstract_singleton::get_instance(); - if (dlg_ptr) - return dlg_ptr->get_dlg_state(); - return ""; - } - - static std::list get_deadlock_journal() - { - auto dlg_ptr = abstract_singleton::get_instance(); - if (dlg_ptr) - return dlg_ptr->get_deadlock_journal(); - return std::list(); - } - }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - - template - class guarded_critical_region_t - { - t_lock& m_locker; - std::atomic m_unlocked; - - guarded_critical_region_t(const guarded_critical_region_t&) {} - - public: - guarded_critical_region_t(t_lock& cs, const char* func_name, const char* location, const char* lock_name, const std::string& thread_name) : m_locker(cs), m_unlocked(false) - { - deadlock_guard_singleton::on_before_lock(&m_locker, func_name, location, lock_name, thread_name); - m_locker.lock(); - deadlock_guard_singleton::on_after_lock(&m_locker); - } - - ~guarded_critical_region_t() - { - TRY_ENTRY(); - unlock(); - CATCH_ALL_DO_NOTHING(); - } - - void unlock() - { - if (!m_unlocked) - { - deadlock_guard_singleton::on_unlock(&m_locker); - m_locker.unlock(); - m_unlocked = true; - } - } - }; - - template - inline bool dlg_try_lock_locker(locker_t& lock) - { - bool res = lock.try_lock(); - if (res) - { - deadlock_guard_singleton::on_after_lock(&lock); - } - return res; - } - - - -#define _DEADLOCK_STRINGIFY(X) #X -#define DEADLOCK_STRINGIFY(X) _DEADLOCK_STRINGIFY(X) - -#if defined(_MSC_VER) -#define DEADLOCK_FUNCTION_DEF __FUNCTION__ -#else -#define DEADLOCK_FUNCTION_DEF __PRETTY_FUNCTION__ -#endif - -#define DEADLOCK_LOCATION __FILE__ ":" DEADLOCK_STRINGIFY(__LINE__) - - /* - - We do DEADLOCK_LOCATION and DEADLOCK_FUNCTION_DEF as separate variables passed into deadlock_guard - because in GCC __PRETTY_FUNCTION__ is not a literal (like __FILE__ macro) but const variable, and - can't concatenate it with other macro like we did in DEADLOCK_LOCATION. - - */ - -#define VALIDATE_MUTEX_IS_FREE(mutex_mame) \ - if (mutex_mame.try_lock()) \ - { \ - mutex_mame.unlock(); \ - return; \ - } \ - else \ - { \ - auto state_str = epee::deadlock_guard_singleton::get_dlg_state(); \ - LOG_ERROR("MUTEX IS NOT FREE ON DESTRUCTOR: " << #mutex_mame << ", address:" << (void*)&mutex_mame << ENDL << "DEAD LOCK GUARD state:" << ENDL << state_str); \ - } - - - -#define DLG_CRITICAL_REGION_LOCAL_VAR(lock, varname) epee::guarded_critical_region_t varname(lock, DEADLOCK_FUNCTION_DEF, DEADLOCK_LOCATION, #lock, epee::log_space::log_singletone::get_thread_log_prefix()) -#define DLG_CRITICAL_REGION_BEGIN_VAR(lock, varname) { epee::guarded_critical_region_t varname(lock, DEADLOCK_FUNCTION_DEF, DEADLOCK_LOCATION, #lock, epee::log_space::log_singletone::get_thread_log_prefix()) - -#define DLG_CRITICAL_SECTION_LOCK(lck) epee::deadlock_guard_singleton::on_before_lock(&lck, DEADLOCK_FUNCTION_DEF, DEADLOCK_LOCATION, #lck, epee::log_space::log_singletone::get_thread_log_prefix());\ - lck.lock();\ - epee::deadlock_guard_singleton::on_after_lock(&lck) - -#define DLG_CRITICAL_SECTION_TRY_LOCK(lock) dlg_try_lock_locker(lock) - -#define DLG_CRITICAL_SECTION_UNLOCK(lock) epee::deadlock_guard_singleton::on_unlock(&lock);\ - lock.unlock(); - - - -#define FAST_CRITICAL_REGION_LOCAL_VAR(x, varname) epee::critical_region_t varname(x) -#define FAST_CRITICAL_REGION_BEGIN_VAR(x, varname) {epee::critical_region_t varname(x) -#define FAST_CRITICAL_REGION_LOCAL(x) FAST_CRITICAL_REGION_LOCAL_VAR(x, critical_region_var) -#define FAST_CRITICAL_REGION_BEGIN(x) FAST_CRITICAL_REGION_BEGIN_VAR(x, critical_region_var) -#define FAST_CRITICAL_REGION_END() } - -#define FAST_CRITICAL_SECTION_LOCK(x) x.lock() -#define FAST_CRITICAL_SECTION_TRY_LOCK(x) x.try_lock() -#define FAST_CRITICAL_SECTION_UNLOCK(x) x.unlock() - - -//#define DISABLE_DEADLOCK_GUARD - -#ifdef DISABLE_DEADLOCK_GUARD -#define CRITICAL_REGION_LOCAL_VAR(x, varname) FAST_CRITICAL_REGION_LOCAL_VAR(x, varname) -#define CRITICAL_REGION_BEGIN_VAR(x, varname) FAST_CRITICAL_REGION_BEGIN_VAR(x, varname) - -#define CRITICAL_SECTION_LOCK(x) FAST_CRITICAL_SECTION_LOCK(x) -#define CRITICAL_SECTION_TRY_LOCK(x) FAST_CRITICAL_SECTION_TRY_LOCK(x) -#define CRITICAL_SECTION_UNLOCK(x) FAST_CRITICAL_SECTION_UNLOCK(x) -#else -#define CRITICAL_REGION_LOCAL_VAR(x, varname) DLG_CRITICAL_REGION_LOCAL_VAR(x, varname) -#define CRITICAL_REGION_BEGIN_VAR(x, varname) DLG_CRITICAL_REGION_BEGIN_VAR(x, varname) - -#define CRITICAL_SECTION_LOCK(x) DLG_CRITICAL_SECTION_LOCK(x) -#define CRITICAL_SECTION_TRY_LOCK(x) DLG_CRITICAL_SECTION_TRY_LOCK(x) -#define CRITICAL_SECTION_UNLOCK(x) DLG_CRITICAL_SECTION_UNLOCK(x) -#endif - - -#define CRITICAL_REGION_LOCAL(x) CRITICAL_REGION_LOCAL_VAR(x, critical_region_var) -#define CRITICAL_REGION_LOCAL1(x) CRITICAL_REGION_LOCAL_VAR(x, critical_region_var1) -#define CRITICAL_REGION_BEGIN(x) CRITICAL_REGION_BEGIN_VAR(x, critical_region_var) -#define CRITICAL_REGION_BEGIN1(x) CRITICAL_REGION_BEGIN_VAR(x, critical_region_var1) -#define CRITICAL_REGION_END() } - - -#define CIRITCAL_OPERATION(obj,op) {obj##_lock.lock();obj . op;obj##_lock.unlock();} - -#define SHARED_CRITICAL_REGION_LOCAL(x) boost::shared_lock< boost::shared_mutex > critical_region_var(x) -#define EXCLUSIVE_CRITICAL_REGION_LOCAL(x) boost::unique_lock< boost::shared_mutex > critical_region_var(x) - -#define SHARED_CRITICAL_REGION_BEGIN(x) { SHARED_CRITICAL_REGION_LOCAL(x) -#define SHARED_CRITICAL_REGION_END() } -#define EXCLUSIVE_CRITICAL_REGION_BEGIN(x) { EXCLUSIVE_CRITICAL_REGION_LOCAL(x) -#define EXCLUSIVE_CRITICAL_REGION_END() } - -} diff --git a/src/contrib/epee/include/time_helper.h b/src/contrib/epee/include/time_helper.h deleted file mode 100644 index 4081142..0000000 --- a/src/contrib/epee/include/time_helper.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -//#include -//#include -#include -#include -#include "warnings.h" - -namespace epee -{ -namespace misc_utils -{ - -#ifdef __ATLTIME_H__ - - inline - bool get_time_t_from_ole_date(DATE src, time_t& res) - { - SYSTEMTIME st = {0}; - if(TRUE != ::VariantTimeToSystemTime(src, &st)) - return false; - ATL::CTime ss(st); - res = ss.GetTime(); - return true; - } -#endif - inline - std::string get_time_str(const time_t& time_) - { - - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4996) - pt = localtime(&time_); -POP_VS_WARNINGS - - if(pt) - strftime( tmpbuf, 199, "%d.%m.%Y %H:%M:%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; - } - - inline - std::string get_time_str_v2(const time_t& time_) - { - - char tmpbuf[200] = {0}; - tm* pt = NULL; -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4996) - pt = localtime(&time_); -POP_VS_WARNINGS - - if(pt) - strftime( tmpbuf, 199, "%Y-%m-%d %H-%M-%S", pt ); - else - { - std::stringstream strs; - strs << "[wrong_time: " << std::hex << time_ << "]"; - return strs.str(); - } - return tmpbuf; - } - - inline - std::string get_time_str_v3(const boost::posix_time::ptime& time_) - { - return boost::posix_time::to_simple_string(time_); - } - - - - inline std::string get_internet_time_str(const time_t& time_) - { - char tmpbuf[200] = {0}; - tm* pt = NULL; -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4996) - pt = gmtime(&time_); -POP_VS_WARNINGS - strftime( tmpbuf, 199, "%a, %d %b %Y %H:%M:%S GMT", pt ); - return tmpbuf; - } - - inline std::string get_time_interval_string(const time_t& time_) - { - std::string res; - time_t tail = time_; - if (tail < 0) - { - tail = -tail; - res = "-"; - } -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4244) - int days = tail/(60*60*24); - tail = tail%(60*60*24); - int hours = tail/(60*60); - tail = tail%(60*60); - int minutes = tail/(60); - tail = tail%(60); - int seconds = tail; -POP_VS_WARNINGS - res += std::string("d") + boost::lexical_cast(days) + ".h" + boost::lexical_cast(hours) + ".m" + boost::lexical_cast(minutes) + ".s" + boost::lexical_cast(seconds); - return res; - } - -#ifdef __SQLEXT - inline - bool odbc_time_to_oledb_taime(const SQL_TIMESTAMP_STRUCT& odbc_timestamp, DATE& oledb_date) - { - - SYSTEMTIME st = {0}; - st.wYear = odbc_timestamp.year; - st.wDay = odbc_timestamp.day; - st.wHour = odbc_timestamp.hour ; - st.wMilliseconds = (WORD)odbc_timestamp.fraction ; - st.wMinute = odbc_timestamp.minute ; - st.wMonth = odbc_timestamp.month ; - st.wSecond = odbc_timestamp.second ; - - if(TRUE != ::SystemTimeToVariantTime(&st, &oledb_date)) - return false; - return true; - } - -#endif -} -} \ No newline at end of file diff --git a/src/contrib/epee/include/tiny_ini.h b/src/contrib/epee/include/tiny_ini.h deleted file mode 100644 index 2bc71fc..0000000 --- a/src/contrib/epee/include/tiny_ini.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#ifndef _TINY_INI_H_ -#define _TINY_INI_H_ - -#include -#include -#include "string_tools.h" - -namespace epee -{ -namespace tiny_ini -{ - - inline - bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res) - { - std::string expr_str = std::string() + "^("+ param_name +") *=(.*?)$"; - const boost::regex match_ini_entry( expr_str, boost::regex::icase | boost::regex::normal); - boost::smatch result; - if(!boost::regex_search(ini_entry, result, match_ini_entry, boost::match_default)) - return false; - res = result[2]; - string_tools::trim(res); - return true; - } - inline - std::string get_param_value(const std::string& param_name, const std::string& ini_entry) - { - std::string buff; - get_param_value(param_name, ini_entry, buff); - return buff; - } - - template - bool get_param_value_as_t(const std::string& param_name, const std::string& ini_entry, T& res) - { - std::string str_res = get_param_value(param_name, ini_entry); - - string_tools::trim(str_res); - if(!str_res.size()) - return false; - - return string_tools::get_xtype_from_string(res, str_res); - } - -} -} - -#endif //_TINY_INI_H_ diff --git a/src/contrib/epee/include/to_nonconst_iterator.h b/src/contrib/epee/include/to_nonconst_iterator.h deleted file mode 100644 index 729b0e8..0000000 --- a/src/contrib/epee/include/to_nonconst_iterator.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#ifndef _TO_NONCONST_ITERATOR_H_ -#define _TO_NONCONST_ITERATOR_H_ - -namespace epee -{ - -template -typename Type::iterator to_nonsonst_iterator(Type& obj, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(obj.begin()), it); - typename Type::iterator res_it = obj.begin()+dist; - return res_it; -} - - -template -typename Type::iterator to_nonsonst_iterator(typename Type::iterator base_it, typename Type::const_iterator it) -{ - typename Type::difference_type dist = std::distance(static_cast(base_it), it); - typename Type::iterator res_it = base_it+dist; - return res_it; -} -}//namespace epee -#endif //_TO_NONCONST_ITERATOR_H_ diff --git a/src/contrib/epee/include/warnings.h b/src/contrib/epee/include/warnings.h deleted file mode 100644 index bbdcd9f..0000000 --- a/src/contrib/epee/include/warnings.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#if defined(_MSC_VER) - -#define PUSH_VS_WARNINGS __pragma(warning(push)) -#define POP_VS_WARNINGS __pragma(warning(pop)) - -#define PUSH_GCC_WARNINGS -#define POP_GCC_WARNINGS - -#define DISABLE_VS_WARNINGS(w) __pragma(warning(disable: w)) -#define DISABLE_GCC_WARNING(w) -#define DISABLE_CLANG_WARNING(w) -#define DISABLE_GCC_AND_CLANG_WARNING(w) - -#else - -#include - -#define PUSH_VS_WARNINGS -#define POP_VS_WARNINGS - -#define PUSH_GCC_WARNINGS _Pragma("GCC diagnostic push") -#define POP_GCC_WARNINGS _Pragma("GCC diagnostic pop") - -#define DISABLE_VS_WARNINGS(w) - -#if defined(__clang__) -#define DISABLE_GCC_WARNING(w) -#define DISABLE_CLANG_WARNING DISABLE_GCC_AND_CLANG_WARNING -#else -#define DISABLE_GCC_WARNING DISABLE_GCC_AND_CLANG_WARNING -#define DISABLE_CLANG_WARNING(w) -#endif - -#define DISABLE_GCC_AND_CLANG_WARNING(w) _Pragma(BOOST_PP_STRINGIZE(GCC diagnostic ignored BOOST_PP_STRINGIZE(-W##w))) - -#endif - - - - diff --git a/src/contrib/epee/include/zlib_helper.h b/src/contrib/epee/include/zlib_helper.h deleted file mode 100644 index f63b589..0000000 --- a/src/contrib/epee/include/zlib_helper.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - -#pragma once -extern "C" { -#include "zlib/zlib.h" -} - -namespace epee -{ -namespace zlib_helper -{ - inline bool pack(const std::string& target, std::string& result_packed_buff) -{ - result_packed_buff.clear(); - - z_stream zstream = {0}; - int ret = deflateInit(&zstream, Z_DEFAULT_COMPRESSION); - if(target.size()) - { - size_t estimated_output_size_max = deflateBound(&zstream, static_cast(target.size())); - result_packed_buff.resize(estimated_output_size_max, 'X'); - - zstream.next_in = (Bytef*)target.data(); - zstream.avail_in = (uInt)target.size(); - zstream.next_out = (Bytef*)result_packed_buff.data(); - zstream.avail_out = (uInt)result_packed_buff.size(); - - ret = deflate(&zstream, Z_FINISH); - // as we allocated enough room for a signel pass avail_out should not be zero - CHECK_AND_ASSERT_MES(ret == Z_STREAM_END && zstream.avail_out != 0, false, "Failed to deflate. err = " << ret); - - result_packed_buff.resize(result_packed_buff.size() - zstream.avail_out); - result_packed_buff.erase(0, 2); - } - - deflateEnd(& zstream ); - return true; - } - - inline bool pack(std::string& target) - { - std::string result_packed_buff; - bool r = pack(target, result_packed_buff); - if (r) - result_packed_buff.swap(target); - return r; - } - - inline bool unpack(const std::string& target, std::string& decode_summary_buff) - { - z_stream zstream = {0}; - int ret = inflateInit(&zstream);// - - decode_summary_buff.clear(); - size_t ungzip_buff_size = target.size() * 0x30; - std::string current_decode_buff(ungzip_buff_size, 'X'); - - uInt current_offset = 0; - - while (target.size() > current_offset) - { - zstream.next_out = (Bytef*)current_decode_buff.data(); - zstream.avail_out = (uInt)ungzip_buff_size; - - static char dummy_head[2] = - { - 0x8 + 0x7 * 0x10, - (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, - }; - zstream.next_in = (Bytef*) dummy_head; - zstream.avail_in = sizeof(dummy_head); - ret = inflate(&zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - LOCAL_ASSERT(0); - return false; - } - - zstream.next_in = (Bytef*)target.data() + current_offset; - zstream.avail_in = (uInt)target.size() - current_offset; - - ret = inflate(&zstream, Z_SYNC_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - LOCAL_ASSERT(0); - return false; - } - - - //target.erase(0, target.size()-zstream.avail_in); - current_offset += zstream.total_in; - - if(ungzip_buff_size == zstream.avail_out) - { - LOG_ERROR("Can't unpack buffer"); - return false; - } - - - current_decode_buff.resize(ungzip_buff_size - zstream.avail_out); - if(decode_summary_buff.size()) - decode_summary_buff += current_decode_buff; - else - current_decode_buff.swap(decode_summary_buff); - - current_decode_buff.resize(ungzip_buff_size); - } - - inflateEnd(&zstream ); - - - return true; - } - - inline bool unpack(std::string& target) - { - std::string decode_summary_buff; - bool r = unpack(target, decode_summary_buff); - if (r) - decode_summary_buff.swap(target); - return r; - } - -}; -}//namespace epee diff --git a/src/contrib/epee/tests/.gitignore b/src/contrib/epee/tests/.gitignore deleted file mode 100644 index d9b4f01..0000000 --- a/src/contrib/epee/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build/* diff --git a/src/contrib/epee/tests/data/storages/invalid_storage_1.bin b/src/contrib/epee/tests/data/storages/invalid_storage_1.bin deleted file mode 100644 index fac7b3e97c6efbf757593b29c2f2c0653c501d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109577 zcmeF))pu4`qv&A*v{0ulZK>k!?(Xg`0fIwtcXxMpcXxMpcXy|*C(pjw`~lxSWA~iJ z#WMmI$(!HB9Bay&%r08;&7~h^3=9d06&_l*MT=&UB8Nl`2@h@7xJ}#877aohH*Xs$ zYRIW*F(O6$i4lUxh=Qni2k#;pqT@Zhj}P!6KElWN1ioR6Pw^Q(M@)QyFYy&(;cI+@ zZ}ArwF7(v7jj`-*?K7n5%#;5oUpCcx|z?b+6vG6s%!MFGh-{S|w zMjXUNJj6!=Bt#-4MiL}NG9*U|q(myDMjE6=I;2MiWJD%pMiyj6He^Q*=HB?6p)I=?WqBiQFF2Ya` z_0a$g(Fl#v1WnNl;b@K)Xo*&6jW%eDc4&_d=!j0}j4tSkZs?94=!stFjXvm$e&~+@ z7>Gd_j3F3`VHl1P7>Q9BjWHODaTt#Yn21T3j47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+xQI)*j4QZ`Yq*XZxQSc1jXSuDd$^AWc!)=Mj3;=CXLybm zc!^hdjW-ee_i);#ezOLVqC^de`Ty`>8zYecH!+eRDUu;MQXnN#AvMw@+Ar!Sy2XzsKdZ>>EXoyB=j3#J`W(Y@fv_MO=LTj`^TeL%abU;URLT7YA zS9C*n^gvJaLT~gzU-UzN48TAP!e9)+Pz=LxjKD~Y!f1@aSd7DXOu$4;!emUrR7}Hk z%)m^{!fedJT+G9KEWko6!eT7JQY^!AtiVdF!fLF+TCBr*Y`{ir!e(s2R&2v|?7&X! z!fx!rUhKnu9Kb;w!eJc2Q5?f@oWMz(!fBkrS)9XpT);(K!ev~+Rb0b$+`vuT!fo8a zUEITcJitRd!eczaQ#`|SyueGm!fU+2kN62c;}`sj-|##Bz@PXFf8!rS3W*>Dkr4$^ z@ebZaG(^XHcpo3&Lwtmf@d;w!Q+$Tc5ffkFOMHb`_!{5fTYQJ_@dIKb4&ovn;v)eP zA`ucJ36dfik|PCDA{A024bmbV(jx;hA`>zr3$h{`vLgp_A{TNa5Aq@(@}mF>q7VwB z2#TT@ilYQdq7+J_49cP$%A*1*q7o{j3aX+Ss-p&Kq836?8+A|@VW@}tXn=-jgvMxs zrf7z6G)D`xL@TsL8?;3`v_}VYL??7c7j#88bVm>LL@)G4AM`~(^v3`U#2^gD5DdjI z495tJ#3+o$7>va@jK>5_#3W3{6imf5OvenOCl9L&W$%*O&O#3C%l5-i0sEXNA0 z#44=D8mz@Stj7jy#3pRU7Hq{fY{w4l#4hZ{9_+L8U{D|^5EKXs1Ooks_Mg9M_)qnjR{C=e6~3j8Yz1oMLb&9k=Pvjqi$0zrYGKu{nk5EKXs1O@)@ z6bR-8|93hEKP4y-6bK3g1%d)WfuKN8ASm#^xxjyRUhx0)`})Bvq!DkCRP!cWb<{vj z)Ium~qYmmK4E0bS4bTvc&=^h76wMHh=4gSIXoc2jgSKdg_UM3)=!DMbg0AR>?&yJ@ z=!M?sgTCm8{uqFP7=*zXf}t3O;TVCD7=_UogRvNg@tA;#n1sogf~lB>>6n3;n1$Jx zgSnW8`B;F3ScJt`f~8o7$riNxP{xegS)tg`*?td zc!bAzf~R=HB?6p)I=?WqBiQFF2Ya`_0a$g(Fl#v1WnNl;b@K) zXo*&6jW%eDc4&_d=!j0}j4tSkZs?94=!stFjXvm$e&~+@7>Gd_j3F3`VHl1P7>Q9B zjWHODaTt#Yn21T3j47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+ zxQI)*j4QZ`Yq*XZxQSc1jXSuDd$^AWc!)=Mj3;=CXLybmc!^hdjW-dz^$O{KT^kZ3 zxHiPdo(idv25FHF>5%~$kqMcR1zC{|*^vV|kqfzz2YHbX`B4A`Q3!=m1VvE{#Zdw! zQ3|C|24ztW)9hGPUqViZPW z48~#{#$y5|ViG1}3Z`Njreg+XVism&4(4JW=3@aCVi6W&36^3RmSY80Vii_n4c1~E z)?))UViPuF3$|h#wqpl&Vi$H}5B6do_TvB!;t&qw2#(?yj^hMQ;uKEf49?;l&f@|u z;u0?73a;WBuHy!7;udb>4({R}?&AR-;t?L>37+B^p5p~x;uT)w4SvK=_!+<8SNw+G z@dy6IU-%pUAW}#KA&879h>CacE}|hi-oyL&03YHbe2h;J1E1nEe2$p-0$<`Q#KPD3 z2H)a4e2*Ux8*va9@em&gkPwNG7)g*6$&ef=kP@ko8flOg>5v{7kP(@X8Cj4O*^nJM zkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!xR;36*JGOpk%uHiav;3jV2Htygq?%_Tj;2|F2 zF`nQlp5ZxO;3Zz+HQq$<)-zvlZOFg!Sor_uCFtO@1qFfvL4lw^P#`D}6bK6Z&lL!^ z`y-YWJeC< zL@wk;9^^$nXpau)h)(E?F6fGG=#C!fiC*Z9 zKIn^n=#K#yh(Q>PAsC8b7>*GbiBTAhF&K++7>@~Th(~yg zCwPiyc#ao%iC1`yH~0}h;b;7UU-27$#~=6;f8lTZgGeC}gdj4aAS&L$yNHJ9cn|O6 z1AK^&@G(9?419{u@Ht}Q3w(*M5DQ=98+?oJ@I8J&Y{Wra#6x@}Ktd!!VkALQBtvqf zKuV-SYNSD0q(gdSKt^OjW@JHDWJ7l3Ku+XBZsb8;8KuMHB zX_P@(ltXz`Kt)tSWmG{`R6}*tKuy#_C~Bh)>LLvFP#+D@5RK3nP0$q05RT?(ftF~6 z)@XyaXovRbfR5;d&gg=!=!Wj-fu87v-spqA=!gCofPol3~(fsq)6(HMiV z7>DtgfQgud$(Vwvn1<Q~(IEVANfQz_< z%eaE8xQ6Svft$F6+qi?fxQF|AfQNX5$9RILc!uYAftPrN*LV}bTT8#e{}PhIpq>(` zkQ!-_7U_^48ITc~kQrH!71@v-Igk^%kQ;fB7x|DM1yB%$P#8r}6va>+B~TKjP#R@W z7UfVL6;KhCP#INF71dB3HBb|^5Q^HUgSrSqJ=8}7G(;mbMiVqeGlZi#TA(Fbp*7l| zE!v?yI-nyup)xVVK??*FZN+S4&WdT;V_QiD30McPT(X?;WW0)oCB8x|e2s7LExyC| z_yMsI2XPS(@sR)tkqC*A1WAz$$&msnkqW7i25FHF>5%~$kqMcR1zC{|*^vV|kqfzz z2YHbX`B4A`Q3!=m1VvE{#Zdw!Q3|C|24ztW)9hGPUqViZPW48~#{#$y5|ViG1}3Z`Njreg+XVism&4(4JW=3@aC zVi6W&36^3RmSY80Vii_n4c1~E)?))UViPuF3$|h#wqpl&Vi$H}5B6do_TvB!;t&qw z2#(?yj^hMQ;uKEf49?;l&f@|u;u0?73a;WBuHy!7;udb>4({R}?&AR-;t?L>37+B^ zp5p~x;uT)wO$2W}^99@e!FGR8ASe(N2nqxRf&xK-pg>UIUsK>eyWJnm3;yR0W(40k zC=e6~3Iqj$0zrYGKu{nk@IP1JKRYi7ZvC?Hn+mCs25FHF>5%~$kqMcR1zC{|*^vV| zkqfzz2YHbX`B4A`Q3!=m1VvE{#Zdw!Q3|C|24ztW)9hGPUqViZPW48~#{#$y5|ViG1}3Z`Njreg+XVism&4(4JW z=3@aCVi6W&36^3RmSY80Vii_n4c1~E)?))UViPuF3$|h#wqpl&Vi$H}5B6do_TvB! z;t&qw2#(?yj^hMQ;uKEf49?;l&f@|u;u0?73a;WBuHy!7;udb>4({R}?&AR-;t?L> z37+B^p5p~x;uT)w4SvK=_!+<8SNw+G@dy6IU-%pUAW}#KA&879h>CacE}|hi-oyL& z03YHbe2h;J1E1nEe2$p-0$<`Q#KPD32H)a4e2*Ux8*va9@em&gkPwNG7)g*6$&ef= zkP@ko8flOg>5v{7kP(@X8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq3 z8f8!xR;36*J zGOpk%uHiav;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQq$<*3$2P9RrRY-1=o? zPleP-gS1G8^vHmW$b`(uf~?4f?8t$f$c5af~u&7>ZpO5sD)6}Mjg~e80w)u8lWK>p)s1EDViZ1&Cvoa(F(26 z25r#}?a=`p(FvW=1zph%-O&R*(F?uN2Yt~G{V@OoF$jY(1Vb?l!!ZIQF$$wG24gV} z<1qmfF$t3~1yeB%(=h`xF$=RX2XiqG^RWO6u?UN?1WU0D%drA0u?nlP25Yen>#+eF zu?d^81zWKV+pz;Xu?xGg2Yay(`*8pVaR`TT1V?cU$8iEDaSEq#24`^&=WziSaS4}k z1y^wm*Kq?kaSOL`2X}D~_wfJ^@d%Ic1W)k{&+!5;@d~f;20!8_{ET1lD}KZ8_yd39 zFZ_*v5Gf>r5JW~4M8!LJ7ts(M@8NxXfDiEzKE@}Aflu)nK1WP^fiLkDV&Q9igKzO2 zzQ+%UjW~#lc!-Y#NQgv8j3h{kWJrz_NQqQPjWkG$bV!d3$cRkHj4a5CY{-rr$cbFY zjXcPUe8`UiD2PHRj3OwCVknLhD2Y-ijWQ^Uawv}qsEA6aj4G&#YN(DHsEJw#MQzkU zU4)??>Z1V~q7fRS37VoA!qFTp&=RfC8g0-P?a&?_&=H-`8C}p7-OwF9&=bAT8-36h z{m>r+Fc5<<7(*}=!!R5pFcPCM8e=dP<1ii*FcFh58B;J7(=Z(~FcY&d8*?xh^DrL^ zun>!|7)!7e%di|PuoA1V8f&l?>#!ahuo0WE8C$Rw+prxwuoJtm8+))9`>-Dea1e)Z z7)Njv$8a1ca1y6*8fS18=Wreua1obq8CP%>*Ki#-a1*z18+ULQ_i!H%@DPvi7*FsN z&+r^C@Di`^8gC+a>zOY&2K=u%^6@{nXdHa!pg>R{C=e6~3Iqj$0zrX)OMzg!KVs>_ zs!VLeL0rT`d?Y|ZBtl{&K~f|`a-={?q(W+>L0Y6kdSpOGWI|?SK~`i#cH}@#kb<{vj)Ium~qYmmK z4E0bS4bTvc&=^h76wMHh=4gSIXoc2jgSKdg_UM3)=!DMbg0AR>?&yJ@=!M?sgTCm8 z{uqFP7=*zXf}t3O;TVCD7=_UogRvNg@tA;#n1sogf~lB>>6n3;n1$JxgSnW8`B;F3 zScJt`f~8o7$riNxP{xegS)tg`*?tdc!bAzf~R=HB?6p)I=?WqBiQFF2Ya`_0a$g(Fl#v1WnNl;b@K)Xo*&6jW%eD zc4&_d=!j0}j4tSkZs?94=!stFjXvm$e&~+@7>Gd_j3F3`VHl1P7>Q9BjWHODaTt#Y zn21T3j47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+xQI)*j4QZ` zYq*XZxQSc1jXSuDd$^AWc!)=Mj3;=CXLybmc!^hdjW-dzwe%a@`jx_5v{7kP(@X8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!xR;36*JGOpk%uHiav z;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQwMy{DhzJ3x36K_#J=XPyB_y@ed+} zL=b|=h=Qni2k#;pqT@Zhj}P!6KElWN1TpX_KEvmTi7)UazCtW~jc@QRzQgzU0kIJW zaS;#kkpKyi2#JvdNs$c6kpd}^3aOC>X^{@;kpUTz37L@vS&CfiG($L=qXk-`6{x}qDpqX&AT7kZ-)`l28DV*mzX z5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko7G`4(=3*Y^V*wUo5f)60>c7ISHC=e6~3Iqj$0zrYGKv3XcQ{X?l-5<;g{w>Emg3lQg2nqxR zf&xK-pg>R{C=e8QyFf56c)LdMbx5v{7kP(@X8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!x zR;36*JGOpk% zuHiav;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQwMy{DhzJ3x36K_#J=XPyB_y z@ed+}L=b|=h=Qni2k#;pqT@Zhj}P!6KElWN1TpX_KEvmTi7)UazCtW~jc@QRzQgzU z0kIJWaS;#kkpKyi2#JvdNs$c6kpd}^3aOC>X^{@;kpUTz37L@vS&CfiG($L=qXk-`6{x}qDpqX&AT7kZ-)`l28D zV*mzX5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko7G`4(=3*Y^V*wUo z5f)8KuMHBX_P@(ltXz`Kt)tSWmG{`R6}*tKuy#_C~Bh)>LLvF zP#+D@5RK3nP0$q05RT?(ftF~6)@XyaXovRbfR5;d&gg=!=!Wj-fu87v-spqA=!gCo zfPol3~(fsq)6(HMiV7>DtgfQgud$(Vwvn1<Q~(IEVANfQz_<%eaE8xQ6Svft$F6+qi?fxQF|AfQNX5$9RILc!uYA zftPrN*LZ^;@e_W=FZdO|;dlIjKk*m-#y^M@5rL0K0d&Q_y`~4 z6U4x$_za&TCceOz_zJP`HNL^O_zvIW2gF7k#6>*BM*<{7A|yrCS*nyWJNY)M-JpfF62fYArwXt6h$!Yy&dP!ILd01eRyjnM>6(G1~ejuvQ%R%nejXp44e zj}GXFPUws-=!$OWjvnZVUg(WJ=!<^nj{z8nK^Tl77>Z#Sju9A%Q5cOe7>jWjj|rHF zNtlc&n2Kqbjv1JVS(uGEn2ULsj|EtWMOcg_Sc+v>julvmRalKRSc`R7j}6#}P1uYr z*otk~jvd&EUD%C1*o%GGj{`V}LpY2hIErI9juSYEQ#g$?IE!;Qj|;enOSp_HxQc7I zjvKg%TeyuoxQlzZj|X^&M|g}Uc#3Cuju&`|S9py#5xn)x7rY+$uQ>|-|L1~s@LLB3 zf&xK-pg>R{C=e6~3cOt)*zS*5`mib!8*va9@em&gkPwNG7)g*6$&ef=kP@ko8flOg z>5v{7kP(@X8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!xR;36*JGOpk%uHiav z;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQwMy{DhzJ3x36K_#J=XPyB_y@ed+} zL=b|=h=Qni2k#;pqT@Zhj}P!6KElWN1TpX_KEvmTi7)UazCtW~jc@QRzQgzU0kIJW zaS;#kkpKyi2#JvdNs$c6kpd}^3aOC>X^{@;kpUTz37L@vS&CfiG($L=qXk-`6{x}qDpqX&AT7kZ-)`l28DV*mzX z5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko7G`4(=3*Y^V*wUo5f)CS*nyWJNY)M-JpfF62fY zArwXt6h$!Yy&dP!ILd01eRy zjnM>6(G1~ejuvQ%R%nejXp44ej}GXFPUws-=!$OWjvnZVUg(WJ=!<^nj{z8nK^Tl7 z7>Z#Sju9A%Q5cOe7>jWjj|rHFNtlc&n2Kqbjv1JVS(uGEn2ULsj|EtWMOcg_Sc+v> zjulvmRalKRSc`R7j}6#}P1uYr*otk~jvd&EUD%C1*o%GGj{`V}LpY2hIErI9juSYE zQ#g$?IE!;Qj|;enOSp_HxQc7IjvKg%TeyuoxQlzZj|X^&M|g}Uc#3Cuju&`|S9py# z_z^$hXZ(U+@f&`}ANUi0;cxtdNFfn~ATpvLD&E1nh=%BR5AWjxe29Ie2UNT zIbz}qe2K3R3t!_Ke2ee!J$^uJ#6eudLwqDaLL@?BBtcRnLvo}*N~A(+q(NGwLwaOD zMr1-}WIt^6hToGLvfTqNt8lqltEdPLwQs{MN~p% zR6$i#Lv_?ZP1HgtYNHP7A`JCV9}UnDjnEiP&=k!Oj^=2AmS~06XoI$BhxX`zj_8EW z=z^~3hVJNrp6G?%=!3rKhyECVff$6r7=ob~hT#~2kr;*17=y7Ghw+$ziI{}Rn1ZR8 zhUu7rnV5yyn1i{Phxu55g;<2eSc0WkhUHj+l~{$;hy6H!gE)l4ID(@%hT}MalQ@ObID@k|hx53Ai@1c#xPq&=hU>V2o4AGB zxP!a6hx>Sdhj@g?c!H;RhUa*Jmw1KOcoV@}&wRmlf3V#j6bK3g1%d)WfuKN8ASe(N z_}3Kp&u;ez^MbdJQUqTI1%d)WfuKN8ASe(N2nqxR{w)Rmv-5)B)-M~ssgN3JkQV8X z9vP4knUEP-kQLdG9XXH_xsV%qkQe!o9|celg-{qpP!z>b93@Z^rBE7WP!{D-9u-g# zl~5T~P!-is9W_uBwGfKhsDru)Lp{_-12jYIa;74TA?-Cpe@>=JvyKx zI-xVVpewqeJ9?ledZ9P^pfCENKL%hR24OIUU?_%RI7VP3MqxC@U@XRAJSJcwCSfwB zU@E3zI%Z%dW??qwU@qoiJ{Djh7GW`#U@4YiIaXjLR$(>PU@g{RJvLw?HeoZiU@Nv^ zJ9c0vc40U6U@!JzKMvp^4&gA4;3$saI8NXsPT@4p;4IGJJTBlOF5xn+;3}@+I&R=5 zZs9iW;4bdrJ|5s99^o;b;3=NrIbPr;Ug0&~;79y~pYaQR#c%i>f8bC2g}?C+B85Z{ zg2;%1sCWnOA{wIOJ-m+(@F70J$M^&>@F_mS=ZJ|f@Fl)NEPRb`@GZW>_xJ&^5eIP* z5Al%z36ThikpxMR49SrKDUk}Pkp^jz4(X8r8IcK@kp)?i4cU6bB~c2cQ3hpE4&_k+6;TP5Q3X{|4b@QtHBk$psEs)aV-40~9oAz5HewStV+*!o8@6Kyc48NHV-NOXANJz_4&o3F;|Px87>?rv zPT~|!;|$K?9M0ncF5(g{;|i|g8m{98ZsHbh;|}iP9`54-9^w%m;|ZSP8J^<>Ug8yA z<4pu_E&cx2G2rOItzSm=R7j09NQ-nxj||9&OvsEZ$ck*pjvUB|T*!?)$cuc)j{+!& zLMV(PD2iezjuI$|QYeiwD2s9^j|!-WN~nw~sETT+jvAvC9|JHDgD@CF zFciZu93wCiqc9p{Fc#x59uqJTlQ0=mFcs4<9WyW!voITTFc4JD1)*nhw`X^il~Ij zsDi4fhU%z+ny7_P)J7fDMHuR#J{q7Q8lf?opedRm9L>=JEzt_C(FSeN4(-ta9nlG$ z(FI-64c*ZLJ<$uj(Fc9e5B)I!12G7LF$6;~48t)3BQXl2F$QBX4&yNa6EO*sF$GgG z4bw3LGcgOZF$Z%o5A(4A3$X}`u>?!849l?sE3pczu?B0g4(qW28?gzSu?1VP4coB; zJFyG9u?Ksx5BqTd2XP38aRf(k499T-Cvgg=aRz5`4(D+J7jX%faRpa#4cBo4H*pKM zaR+yC5BKo^5Ag_(@dQut4A1cbFYyYm@g{<|p80}f!2g;fAODsm=-_h(1%d)WfuKN8 zASe(N2nzhq6$rNbBbGj_%EU$-#6>*BM*<{7A|yr zCS*nyWJNY)M-JpfF62fYArwXt6h$!Yy&dP!ILd01eRyjnM>6(G1~ejuvQ%R%nejXp44ej}GXFPUws- z=!$OWjvnZVUg(WJ=!<^nj{z8nK^Tl77>Z#Sju9A%Q5cOe7>jWjj|rHFNtlc&n2Kqb zjv1JVS(uGEn2ULsj|EtWMOcg_Sc+v>julvmRalKRSc`R7j}6#}P1uYr*otk~jvd&E zUD%C1*o%GGj{`V}LpY2hIErI9juSYEQ#g$?IE!;Qj|;enOSp_HxQc7IjvKg%Teyuo zxQlzZj|X^&M|g}Uc#3Cuju&`|S9py#_z^$hXZ(U+@f&`}ANUi0;cxtdNFfn~ATpvL zD&E1nh=%BR5AWjxe29Ie2UNTIbz}qe2K3R3t!_Ke2ee!J$^uJ#6eudLwqDa zLL@?BBtcRnLvo}*N~A(+q(NGwLwaODMr1-}WIt^ z6hToGLvfTqNt8lqltEdPLwQs{MN~p%R6$i#Lv_?ZP1HgtYNHP7A`JCV9}UnDjnEiP z&=k!Oj^=2AmS~06XoI$BhxX`zj_8EW=z^~3hVJNrp6G?%=!3rKhyECVff$6r7=ob~ zhT#~2kr;*17=y7Ghw+$ziI{}Rn1ZR8hUu7rnV5yyn1i{Phxu55g;<2eSc0WkhUHj+ zl~{$;hy6H!gE)l4ID(@%hT}MalQ@Ob zID@k|hx53Ai@1c#xPq&=hU>V2o4AGBxP!a6hx>Sdhj@g?c!H;RhUa*Jmw1KOcoV@} zOTWRbUnvagDUk}Pkp^jz4(X8r8IcK@kp)?i4cU6bB~c2cQ3hpE4&_k+6;TP5Q3X{|4b@QtHBk$psEs)a zV-40~9oAz5HewStV+*!o8@6Kyc48NHV-NOXANJz_4&o3F;|Px87>?rvPT~|!;|$K? z9M0ncF5(g{;|i|g8m{98ZsHbh;|}iP9`54-9^w%m;|ZSP8J^<>Ug8yA;|+eqPxu+X z;8*;H-|+|j#9#Ou{~%IG1R;owD2R%8@GhbuI^M(k_y8Z`BYccc5Cfm$GklJi_yS+z zE5yRr_y*tNJA98H5F2q27x54u36KzpkQhmj6v>brDUcGWkQ!-_7U_^48ITc~kQrH! z71@v-Igk^%kQ;fB7x|DM1yB%$P#8r}6va>+B~TKjP#R@W7UfVL6;KhCP#INF71dB3 zHBb|^5Q^HUgSrSqJ=8}7G(;mbMiVqeGlZi#TA(Fbp*7l|E!v?yI-nyup)xVVK??* zFZN+S4&WdT;V_QiD30McPT(X?;WWOQBC63IN2mavQ2i$nCz27a!gLiIk_ZLa!qc@J(-h7@=RXI zJNYEvC4b+1p8Gxb6Cgl<009C72oPu^uTFFW zK!5-N0t5&UAkam?UeM*HoRa_n0t5&UAV7dXoq)Zd&emiC1PBlyK!5-N0$l{`1zm2+ VISCLTK!5-N0t5)u39P#p`~YH9P(uI! diff --git a/src/contrib/epee/tests/data/storages/invalid_storage_2.bin b/src/contrib/epee/tests/data/storages/invalid_storage_2.bin deleted file mode 100644 index a8c29f155ab0634fedda8b5a8424f4611c6dbf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 bcmZ4F>HGPn-24tkMv2_`r2PCG1|}{5SEUB% diff --git a/src/contrib/epee/tests/data/storages/invalid_storage_3.bin b/src/contrib/epee/tests/data/storages/invalid_storage_3.bin deleted file mode 100644 index b5c31aa..0000000 --- a/src/contrib/epee/tests/data/storages/invalid_storage_3.bin +++ /dev/null @@ -1 +0,0 @@ -¢IMóÙŸˆm_bo \ No newline at end of file diff --git a/src/contrib/epee/tests/data/storages/invalid_storage_4.bin b/src/contrib/epee/tests/data/storages/invalid_storage_4.bin deleted file mode 100644 index 4f8372d1978598fcbcbc6a73a5d76ee90c3d6936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18 ZcmZ4F>HGPn-24tkMv2_`r2PCG1^`Ll2HXGu diff --git a/src/contrib/epee/tests/data/storages/valid_storage.bin b/src/contrib/epee/tests/data/storages/valid_storage.bin deleted file mode 100644 index e13f780b17a5a6253dfbf52560d240339ea91b50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180345 zcmeF)Rg6{HqNrgC=!SN>n|8t7-QC??3Md>3E8N}P-QC^Y-QC@tcD?oOm)kGr~kg$U&2a&T7M;jVQbdxVx`_(`hLd1kdQCKL+iC{**r?rkmw=dq0O5_v<+?9FtkaF zwo#&ooQe@EO60FtA&81-h>o}LHew(q-od+g5AWjxe29noP;vqf~AR!VVF_IuDk|8-#ASF^EHPRq0(jh%EAR{s%GqNBnvLQQi zASZGmH}W7a@*zJ8pdbpNFp8ikilI14pd?D6G|HeX%Aq_epdu=vGOC~|s-Ze+peAae zHbPMcbx{vtsE-C{h(>6PCTNOgXpV5SKufejYqUWG+M*rWqXRmk6FQ>{x}qDpqX&AT z7kZ-)`l28DV*mzX5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko7G`4( z=3*Y^V*wUo5f)B>4j<@hOVjw2o z!Mk`5@8bh}h>u__jrB1;!Ka9g&+s|Ez?b+6U*j8mi|_C~;vg>KAwCiyArc`mk{~IP zAvsbYB~l?Z(jYC;Aw4o6BQhZ~vLGw6Av=dVjRX}0w!V-CSwYwVj8An24-RwW@8TKVjkvW0TyBr7GnvPVi}fW1y*7eR$~p; zVjb3F12$q4He(C6VjH$&2XxV zVK??*FZN+S4&WdT;V_QiD30McPT(X?;WW zcnfbM24dnJyo>knK0d&Q_z1D^F+Rbkh>g$iIljP`_zGX+8+?oJ@IB%nF5)3R5+ETG zAu*C5DUu;MQXnN#AvMw@+p*BKM2X#>oVW^J=XoyB=j3#J` zW@wIZv_MO=LTj`^1lpn<+M@$Hq7yo!3%a5kx}yhrq8ECj5Bj1X`eOhFVh{#n2!>)9 zhGPUqViZPW48~#{#$y5|ViG1}3Z`Njreg+XVism&4(4JW=3@aCVi6W&36^3RmSY80 zVii_n4c1~E)?))UViPuF3$|h#wqpl&Vi$H}5B6do_TvB!;t&qw2#(?yj^hMQ;uKEf z49?;l&f@|u;u0?73a;WBuHy!7;udb>4({R}?&AR-;t?L>37+B^p5p~x;uT)wO(g%A z^R;agC3@6TF=9tVgoV`)3R{C=e6~3IqlII~NEKjfkAVM~!;5ZdkLr z;q}9kGz)JK)*w7AlCbc)VUfQH4-2nRw@D-|8~k5e|Lc|3EgOV~wsV*tH6+&8BceqK zj{9x!q(&N~MLMKM24qAgWJVTbMK)wd4&+2GOR7Mq4MKx4M4b(&})J7=kpf2hm4E50f4bcdV(F9G=49yXa7HEl9 zXpJ_AKwGp!dvriYbV6rzL05D`cl1C{^g?g+L0|Mke+L0Y6kdSpOGWI|?SK~`i#cH}@# zkb<{vj)Ix29 zq7Le!9>P!`4bTvc&=^h76wS~a;b?)DXoc2jg9x-mJG4g!bVMg~Mi+ENH*`l2^h7W8 zMj!M=KlH}{48$M|#t;m}Fbu~CjKnC6#u$vnIE=>xOvEHi#uQA&G)%_~%)~6r#vIJW zJj}-eEW{!##u6;WGAzdmti&p;#u}`}I;_VAY{VvP#ujYFHf+ZZ?8GkY#vbg&KJ3Q< z9K<0U#t|IFF&xJUoWv=d#u=Q&Ih@A@T*M_@#uZ$}HC)FH+{7*1#vR16wJj5eB z#uGfnGd#x&yu>TK#+yj~vGx0}6PCTNOgXpV5SKufejYqUWG+M*rWqXRmk6FQ>{x}qDpqX&AT7kZ-) z`l28DV*mzX5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko7G`4(=3*Y^ zV*wUo5f)B>4j<@hOVjw2o!Mk`5 z@8bh}h>s8pALA2zirDxJpW_RBiLdZAzQMQn4&NgV;vyd6BLNa35fUQ_k|G(BBLz|- z6;dM&(jpzwBLgxb6EY(UvLYL@BL{LK7jh#H@**GdqW}t`5DKFRilP{bqXbH#6iTBE z%Ay>~qXH_T5-Ot#s-haIqXufC7HT6Dbx;@e5Qh3_fQD#<#%O}3XoltpM+>w>E3`%% zM4&C&p*=dFBRZiox}Yn%p*wn@Cwieb`k*iRp+5#-AO>MDhF~a$VK_!$Bt~I0#$YVQ zVLT>aA|_!nreG?jVLE1DCT3wa=3p-7VLldMAr@gVmS8ECVL4V{C01cI)?h8xVLdir zBQ{|(wqPr^VLNtUCw5^s_FymeVLuMwAP(U$j^HSc;W$pMCT`(2?%*!&;XWSVAs*o|p5Q5-;W=L5C0^k*-bC_`IbU$xA6#+>3Iqj$ z0zrYGKu{nk5EKXs{Kpjd_a65L>w^EzS382QEhrEa2nqxRf&xK-pg>R{DDYnu`1h_0 zf@{DIep4e2(jpzwBLgxb6EY(UvLYL@BL{LK7jh#H@**GdqW}t`5DKFRilP{bqXbH# z6iTBE%Ay>~qXH_T5-Ot#s-haIqXufC7HT6Dbx;@e5Qh3_fQD#<#%O}3XoltpM+>w> zE3`%%M4&C&p*=dFBRZiox}Yn%p*wn@Cwieb`k*iRp+5#-AO>MDhF~a$VK_!$Bt~I0 z#$YVQVLT>aA|_!nreG?jVLE1DCT3wa=3p-7VLldMAr@gVmS8ECVL4V{C01cI)?h8x zVLdirBQ{|(wqPr^VLNtUCw5^s_FymeVLuMwAP(U$j^HSc;W$pMCT`(2?%*!&;XWSVAs*o|p5Q5-;W=L5C0^k*-rxuPh@bE?e!;K! z4Zq_L{E5HtH==|@5`w6RhUj<;ZzBd`;vKw;_wYVGz=!wKAwCiyArc`mk{~IPAvsbYB~l?Z(jYC;Aw4o6BQhZ~vLGw6Av=dVjRX}0w!V-CSwYwVj8An24-RwW@8TK zVjkvW0TyBr7GnvPVi}fW1y*7eR$~p;Vjb3F12$q4He(C6VjH$&2XkLSLL@)G4 zAM`~(^v3`U#2^gD5DdjI495tJ#3+o$7>va@jK>5_#3W3{6imf5OvenOCl9L&W$ z%*O&O#3C%l5-i0sEXNA0#44=D8mz@Stj7jy#3pRU7Hq{fY{w4l#4hZ{9_+WJeCLCpE(Ett62#wJMP0KWK6+SOv7}{z)Z}-Y|O!2%)@*vz(Op-Vl2T@EW>iFz)GybYOKLptiyV2 zz(#DsW^BP$Y{Pc!z)tMKZtTHc?8AN>z(E|sVI09x9K&&(z)76KX`I1XoWprsz(rib zWn95kT*GzTz)jr3ZQQ|K+{1l5z(YL3V?4oAJi~Lmz)QTsYrKi%A9KFo8t{M2m5={w z%QtvEC=e6~3Iqj$0zrYGKv3X+Pl4dLKXU8Cu1p-nMLfhu0whEtBt{Y>MKUBu3Zz6T zq(&N~MLMKM24qAgWJVTbMK)wd4&+2GOR7Mq4MKx4M4b(&})J7=kpf2hm4E50f4bcdV(F9G=49yXa7HEl9XpJ_A zKwGp!dvriYbV6rzL05D`cl1C{^g?g+L0|Mke+L0Y6kdSpOGWI|?SK~`i#cH}@#kb<{vj)Ix29q7Le! z9>P!`4bTvc&=^h76wS~a;b?)DXoc2jg9x-mJG4g!bVMg~Mi+ENH*`l2^h7W8Mj!M= zKlH}{48$M|#t;m}Fbu~CjKnC6#u$vnIE=>xOvEHi#uQA&G)%_~%)~6r#vIJWJj}-e zEW{!##u6;WGAzdmti&p;#u}`}I;_VAY{VvP#ujYFHf+ZZ?8GkY#vbg&KJ3Q<9K<0U z#t|IFF&xJUoWv=d#u=Q&Ih@A@T*M_@#uZ$}HC)FH+{7*1#vR16wJj5eB#uGfn zGd#x&yu>TK#+yj~vGp4~^(&=8Jrzzr3$h{`vLgp_A{TNa5Aq@( z@}mF>q7VwB2#TT@ilYQdq7+J_49cP$%A*1*q7o{j3aX+Ss-p&Kq84f+6m?J+^$>>o zXn=-jgvMxsrf7!d2uBOFL@TsL8$_Tj+MzuR;36*JGOpk%uHiav;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO z;3Zz+HQwL{{D`0MGk(FZ_zl0~5B!P0@He7_L=u9ih=%BR3vVL^V&WaVi}&z8KEQ|g z2(j=nKEbDmjnD8ozQC9G3SZ+Je2ee!J>noP;vqf~AR!VVF_IuDk|8-#ASF^EHPRq0 z(jh%EAR{s%GqNBnvLQQiASZGmH}W7a@*zJ8pdbpNFp8ikilI14pd?D6G|HeX%Aq_e zpdu=vGOC~|s-Ze+peAaeHbPMcbx{vtsE-C{h(>6PCTNOgXpV5SKufejYqUWG+M*rW zqXRmk6FQ>{x}qDpqX&AT7kZ-)`l28DV*mzX5C&rihGH0oV+2NG6h>nV#$p`CV*(~( z5+-8`reYeVV+Lko7G`4(=3*Y^V*wUo5f)$N61;_otaeq)CC=e6~3Iqj$ z0zrYGKv3X6rog}VxIb7I{O`Fa61>x(Ku{nk5EKXs1Ow@5Ez%GQQMjE6=I;2MiWJD%pMiyj6He^Q*=HB?6p)I=@RMkwl_ zF6to+_0a$g(Fl#v1WnNl%@K|kXo*&6jW&otTeL%abU;URLT7YAS9C*n^gvJaLT~gz zU-UzN48TAP!e9)+Pz=LxjKD~Y!f1@aSd7DXOu$4;!emUrR7}Hk%)m^{!fedJT+G9K zEWko6!eT7JQY^!AtiVdF!fLF+TCBr*Y`{ir!e(s2R&2v|?7&X!!fx!rUhKnu9Kb;w z!eJc2Q5?f@oWMz(!fBkrS)9XpT);(K!ev~+Rb0b$+`vuT!fo8aUEITcJitRd!ecza zQ#`|SyueGm!fU+25BL#3;b;7UU-27$#~=6;f8lRL35g^GQ4tN%@fO}j48+7cco*;C zeSClq@eyL-V|;>75gVW3b9{j>@fE(tH~1Fc;d{hET*O0sBtSwWLSiIAQY1riq(Dlf zLTaQzTBJjIWI#q_LS|$^R%AnVkLSLL@)G4AM`~(^v3`U#2^gD5DdjI495tJ#3+o$7>va@ zjK>5_#3W3{6imf5OvenOCl9L&W$%*O&O#3C%l5-i0sEXNA0#44=D8mz@Stj7jy z#3pRU7Hq{fY{w4l#4hZ{9_+6PCTNOgXpV5SKufejYqUWG z+M*rWqXRmk6FQ>{x}qDpqX&AT7kZ-)`l28DV*mzX5C&rihGH0oV+2NG6h>nV#$p`C zV*(~(5+-8`reYeVV+Lko7G`4(=3*Y^V*wUo5f)B>4j<@hOVjw2o!Mk`5@8bh}h>s8pALA2zirDxJpW_RBiLdZAzQMQn z4&NgV;vyd6BLNa35fUQ_k|G(BBLz|-6;dM&(jpzwBLgxb6EY(UvLYL@BL{LK7jh#H z@**GdqW}t`5DKFRilP{bqXbH#6iTBE%Ay>~qXH_T5-Ot#s-haIqXufC7HT6Dbx;@e z5Qh3_fQD#<#%O}3XoltpM+>w>E3`%%M4&C&p*=dFBRZiox}Yn%p*wn@Cwieb`k*iR zp+5#-AO>MDhF~a$VK_!$Bt~I0#$YVQVLT>aA|_!nreG?jVLE1DCT3wa=3p-7VLldM zAr@gVmS8ECVL4V{C01cI)?h8xVLdirBQ{|(wqPr^VLNtUCw5^s_FymeVLuMwAP(U$ zj^HSc;W$pMCT`(2?%*!&;XWSVAs*o|p5Q5- z;W=L5C0^k*-bC_`IbZPc!2g)5;QwzM!oi;k3Iqj$0zrYGKu{nk5ES^IR3JF+kKFpO zD-#EC5fAZ^011%@iID_JkqpU^0x6LSsgVY0kq+sR0U41AnUMuqkqz0A138fkxseBX zkq`M%00mJ9g;4}WQ4GaV0wqxjrBMcDQ4Zx%0TodRl~Dy%Q4Q5m12s_#wGoOssEc|C zLwz(rLo`BTG(l4|Lvw_q1zMsNTB8jj&=&2`9v#pTozNLw&=uX#9X-$!z0ezd&=>vC z9|JHDgD@CFFciZu93wCiqc9p{Fc#x59uqJTlQ0=mFcs4<9WyW!voITTFcdKK~zLTbi9SP5d$&t4&KFkcpo3& zLwtl-_!ytyQ^dw+_#9v0OMHc|@eRJkclaK05Etb93@Z^rBE7WP!{D- z9u-g#l~5T~P!-is9W_uBwNM+OsDrwwhcMJf12jY?!849l?sE3pczu?B0g4(qW28?gzS zu?1VP4coB;JFyG9u?Ksx5BqTd2XP38aRf(k499T-Cvgg=aRz5`4(D+J7jX%faRpa# z4cBo4H*pKMaR+yC5BKo^5Ag_(@dQut4A1cbFYyYm@g|agZ2bmL15RmBPleP-gS1G8 z^vHmW$b`(uf~?4f?8t$f$c5af~u&7>ZpO5sD;`HMIF>dJ%ph?8lWK>p)s1EDVm`Gd_j3F3`VHl1P7>Q9BjWHODaTt#Yn21T3 zj47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+xQI)*j4QZ`Yq*XZ zxQSc1jXSuDd$^AWc!)=Mj3;=CXLybmc!^hdjW_rKKjJ6+j9>68e#7th1ApQ#{Ea9f zk%S;Bq9Hoo!rO>}n0N>8;yt{N5AY#ALM(iYPw**X<1>7YFYqP4!q@l)-{L!bk2r{n zc!-Y#NQgv8j3h{kWJrz_NQqQPjWkG$bV!d3$cRkHj4a5CY{-rr$cbFYjXcPUe8`Ui zD2PHRj3OwCVknLhD2Y-ijWQ^Uawv}qsEA6aj4G&#YN(DHsEJyrjZoAZ1V~ zq7fRS37VoAnj;)7&=RfC8f_4PwrGd;=zxysgwE)KuIPsD=z*T-h2H3czUYVk7=VEo zguxhsp%{kY7=e)(h0z#;u^5N(n1G3xgvpqKshEc8n1Pv?h1r;cxtNFfSb&9CgvD5b zrC5gLSb>#Th1FPtwOEJs*no}Lgw5E3t=NX`*nyqch27YLz1WBSIDmsVgu^(3qd11+ zIDwNmh0{2Lvp9$IxPXhegv+>stGI^ixPhCvh1f~u&7>ZpO5sD;`HMIF>dJ%ph? z8lWK>p)s1EDVm`Gd_j3F3`VHl1P7>Q9BjWHODaTt#Yn21T3j47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+xQI)*j4QZ`Yq*XZxQSc1jXSuDd$^AWc!)=Mj3;=CXLybm zc!^hdjW_rKKjJ6+j9>68e#7th1ApQ#{Ea9fk%S;Bq9Hoo!rO>}n0N>8;yt{N5AY#A zLM(iYPw**X<1>7YFYqP4!q@l)-{L!bk2r{nc!-Y#NQgv8j3h{kWJrz_NQqQPjWkG$ zbV!d3$cRkHj4a5CY{-rr$cbFYjXcPUe8`UiD2PHRj3OwCVknLhD2Y-ijWQ^Uawv}q zsEA6aj4G&#YN(DHsEJyrjZoAZ1V~q7fRS37VoAnj;)7&=RfC8f_4PwrGd; z=zxysgwE)KuIPsD=z*T-h2H3czUYVk7=VEoguxhsp%{kY7=e)(h0z#;u^5N(n1G3x zgvpqKshEc8n1Pv?h1r;cxtNFfSb&9CgvD5brC5gLSb>#Th1FPtwOEJs*no}Lgw5E3 zt=NX`*nyqch27YLz1WBSIDmsVgu^(3qd11+IDwNmh0{2Lvp9$IxPXhegv+>stGI^i zxPhCvh1kb<{vj)Ix29q7Le!9>P!`4bTvc&=^h76wS~a;b?)DXoc2jg9x-mJG4g! zbVMg~Mi+ENH*`l2^h7W8Mj!M=KlH}{48$M|#t;m}Fbu~CjKnC6#u$vnIE=>xOvEHi z#uQA&G)%_~%)~6r#vIJWJj}-eEW{!##u6;WGAzdmti&p;#u}`}I;_VAY{VvP#ujYF zHf+ZZ?8GkY#vbg&KJ3Q<9K<0U#t|IFF&xJUoWv=d#u=Q&Ih@A@T*M_@#uZ$}HC)FH z+{7*1#vR16wJj5eB#uGfnGd#x&yu>TK#vA;AAMq1@#xM94zu|ZMfj{vV{zjCL zNJ0=5(GVSP;cdh~OuU14@gCmC2lx;lAr?NyC-@Yx@fkkH7x)ri;cI+@Z}A=HB?6p)I=@RMkwl_F6to+_0a$g z(Fl#v1WnNl%@K|kXo*&6jW&otTeL%abU;URLT7YAS9C*n^gvJaLT~gzU-UzN48TAP z!e9)+Pz=LxjKD~Y!f1@aSd7DXOu$4;!emUrR7}Hk%)m^{!fedJT+G9KEWko6!eT7J zQY^!AtiVdF!fLF+TCBr*Y`{ir!e(s2R&2v|?7&X!!fx!rUhKnu9Kb;w!eJc2Q5?f@ zoWMz(!fBkrS)9XpT);(K!ev~+Rb0b$+`vuT!fo8aUEITcJitRd!eczaQ#`|SyueGm z!fU*V6v_fmNK?K^O9onM)aV-40~9oAz5HewStV+*!o8@6Kyc48NHV-NOXANJz_4&o3F;|Px87>?rv zPT~|!;|$K?9M0ncF5(g{;|i|g8m{98ZsHbh;|}iP9`54-9^w%m;|ZSP8J^<>Ug8yA z;|+emkN62c;}`sj-|##Bz@PXFeojcn|O61AK^&5DOpU z6MTx;_za)p3w(*M@HM`{xA+d$k7>c6=N}?1>qYTQT9Ll2tDxwl9 zqYA2`8mglPYN8fuBNTN|7xfT^`e=ZLXoSXSf~IJO<_Jd%v_vbkMjJ$+E!v?yI-nyu zp)xVVK??*FZN+S4&WdT;V_QiD30McPT(X?;WW5v{7kP(@X z8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!xcFP2#c`vcx3ahaOYq1XNu>l*g37fG6Td@t>u>(7? z3%jugd$AAuaR3K#2#0Y5M{x|taRMiC3a4=fXK@baaRC=`372sNS8)y3aRWDT3%79x zcX1E*@c<9;2#@guPw@=T@d7XL3a{}7Kj26FgrD&Xe#LM29e?0Y{Dr>}B_xs%L`5`2 z$6I(CF%T2);9b0j_wfNf#7BsQkMRjUMQnVA&+!Gm#8>zl-{4z(hwl*waS;#kkpKyi z2#JvdNs$c6kpd}^3aOC>X^{@;kpUTz37L@vS&Cfi zG(&TQqXk-`6kJo5uMN(UCcO{6TQ$Ieb5*E&>sUZ5Q8unLogJ> zFdQQ=5~DC0V=xxuFdh>y5tA?(Q!o|NFdZ{66SFWIb1)b4FdqxB5R0%FORyBnupBF} z605KpYp@pUupS$*5u30XTd)<|upK+F6T7e*d$1S#upb9-5QlIWM{pF!a2zLa5~pw) zXK)tha2^+M5tncoS8x^Aa2+>r6Sr_1cW@W?a32rw5RdQ}Pw*7a@EkAj60h(YZzB1} zoG&=;503kT0zrYGKu{nk5EKXs1O6bB~c2cQ3hpE4&_k+6;TP5Q3X{|4b@QtHBk$-5sEsfi+Tt{ zeKbHrG(uxEK~pqCbA+P>TA~$NqYWa^7VXd;9ncY-&>3CO72VJsJMZw7yZy5 z127PSFc?EH6vHqaBQO%9FdAbp7UM7;6EG2zFd0)Y71J;sGcXggFdK6)7xOS53$PH2 zuoz3Q6w9z2E3gu)uo`Qy7VEGc8?X_Zuo+vh72B{KJFpYGup4`@7yGau2XGLFa2Q8$ z6vuEJCvXy{a2jWD7Uyst7jO}ma2Z!{71wYbH*gcTa2t1U7x!=<5AYC=@EA|<6wmM+ zFYpqt@EULM1AfF$_!+<8SNw+G@dy6IU-%nQLLv!4R768`yoI+B12ORq-o<-(A0OaD ze1ur|7@y!%#Kvd%9ADr|e1)&^4Zg*9_#SZ(7x54u36KzpkQhmj6v>brDUcGWkQ!-_ z7U_^48ITc~kQrH!71@v-Igk^%kQ;fB7x|DM1yB%$P#8r}6va>+B~TKjP#R@W7UfVL z6;KhCP#INF71dB3HBb|^P#dABgSx1PFw{o_G(;mbMiVqeGc-pyTA(Fbp*7kd0&UR_ z?a=`p(FvW=1zph%-O&R*(F?uN2Yt~G{V@OoF$jY(1Vb?l!!ZIQF$$wG24gV}<1qmf zF$t3~1yeB%(=h`xF$=RX2XiqG^RWO6u?UN?1WU0D%drA0u?nlP25Yen>#+eFu?d^8 z1zWKV+pz;Xu?xGg2Yay(`*8pVaR`TT1V?cU$8iEDaSEq#24`^&=WziSaS4}k1y^wm z*Kq?kaSOL`2X}D~_wfJ^@d%Ic1W)k{&+!5;@d~f;CX#<#75~>`Lt+I#CB(>{8flOg z>5v{7kP(@X8Cj4O*^nJMkQ2F(8+niy`H&w4P!NSs7)4MN#ZVk2P!gq38f8!xcFP2#c`vcx3ahaOYq1XNu>l*g37fG6 zTd@t>u>(7?3%jugd$AAuaR3K#2#0Y5M{x|taRMiC3a4=fXK@baaRC=`372sNS8)y3 zaRWDT3%79xcX1E*@c<9;2#@guPw@=T@d7XL3a{}7Kj26FgrD&Xe#LM29e?0Y{Dr>} zB_xs%L`5`2$6I(CF%T2);9b0j_wfNf#7BsQkMRjUMQnWbf7-jJCe5yf0mGSal1!Y8 zZQHhO+ctYVJ+^Jzwr$(?#G0?K?`VEND)pvnpInFi?7F*a*V3~Z5fKTI5d~2Z4bc$; zF%b)~5eIP*5Al%z36ThikpxMR49SrKDUk}Pkp^jz4(X8r8IcK@kp)?i4cU6bB~c2cQ3hpE4&_k+6;TP5Q3X{|4b@QtHBk$-Q3rKV z5B1Ri4bcdV(F9G=49(F3Ezt_C(FSeN4(-ta9nlG$(FI-64I$``9_Wc)=#4(;i+%`2 ze+6f95Nq|I5qH!LtPgf&xK-pg>R{C=e6~3j8|-g6;mWr4Oqz zu@D<^5Etb93@Z^rBE7WP!{D-9u-g#l~5T~P!-is9W_uBwNM*%P#5)3 z9}UnDjnEiP&=k$k94*iitcP#W|eE1zf}>T*eh##Wh^V4cx>n+{PW;#Xa1|13bhdJjN3|#WOs| z3%tZDyv7^+h@bE?e!;K!4Zq_L{E5HtH{RmCaAAbQ`}hDK;v;;FPY@oT;xl}X2>1eD z;wyZOZ}2U?!}s_B5fKTI5d~2Z4bc$;F%b)~5eIP*5Al%z36ThikpxMR49SrKDUk}P zkp^jz4(X8r8IcK@kp)?i4cU6bB~c2cQ3hpE z4&_k+6;TP5Q3X{|4b@QtHBk$-Q3rKV5B1Ri4bcdV(F9G=49(F3Ezt_C(FSeN4(-ta z9nlG$(FI-64I$``9_Wc)=#4(;i+%`2e+ zfQqPu%BX^>sD|pOftsj=+NguNsE7J!fQD#<#%O}3Xolu!ftF~6)@XyaXovRbfR5;d z&gg=!=!OtMDhF~a$VK_!$Bt~I0#$YVQVLT>aA|_!n zreG?jVLE1DCT3wa=3p-7VLldMAr@gVmS8ECVL4V{C01cI)?h8xVLdirBQ{|(wqPr^ zVLNtUCw5^s_FymeVLuMwAP(U$j^HSc;W$pM zCT`(2?%*!&;XWSVAs*o|p5Q5-;W=L5C0^k*-rz_4grD&Xe#LM29e?0Y{Dr^q7Vm`% zBOKnx2lx;l;bVM)@c0y;;d4a57x)ri;cI+@Z}AB>4ju?oEScr`{ zh>LiLj|51FL`aMzNQz`gjuc3VR7j09NQ-nxj||9&OvsEZ$ck*pjvUB|T*!?)$cuc) zj{+!&LMV(PD2iezjuI$|QYeiwD2s9^j|!-WN~nw~sETT+jvA^g&=dVjRX}0w!V-CSwYwVj8An24-RwW@8TKVjkvW0TyBr7GnvP zVi}fW1y*7eR$~p;Vjb3F12$q4He(C6VjH$&2XR{DDa;t@Xv1d2lIk|=a5G5DM5jtKu{nk z5EKXs1O+B~TKjP#R@W7UfVL6;KhCP#INF71dB3HBb|^P#bkn7xhpd z4bTvc&=^h76wS~aEzlCJ&>C&f7VXd;9ncY-&>3CO72Obm?&yJ@=!M?sgTCm8Q1r(D z48$M|#t;m}Fbu~CjKnC6#u$vnIE=>xOvEHi#uQA&G)%_~%)~6r#vIJWJj}-eEW{!# z#u6;WGAzdmti&p;#u}`}I;_VAY{VvP#ujYFHf+ZZ?8GkY#vbg&KJ3Q<9K<0U#t|IF zF&xJUoWv=d#u=Q&Ih@A@T*M_@#uZ$}HC)FH+{7*1#vR16wJj5eB#uGfnGd#x& zyu>TK#vA;IpYSt&!LRrYzvB=5iNEkS-r~J*VT8l`_y8Z`BYccc5FVf6GklH+_yS+z zD}0S_@GZW>_xJ%35ebnI1yK5%~$kqMcR1zC{|*^vV|kqfzz2YHbX`B4A`Q3!=m1VvE{#Zdw!Q3|C|24ztW zo_0a$g(Fl#v1WnNl&Cvoa(F(2625r#}?a=`p z(FvW=1zph%A?S`C=!stFjXvm$eh5W>48TAP!e9)+Pz=LxjKD~Y!f1@aSd7DXOu$4; z!emUrR7}Hk%)m^{!fedJT+G9KEWko6!eT7JQY^!AtiVdF!fLF+TCBr*Y`{ir!e(s2 zR&2v|?7&X!!fx!rUhKnu9Kb;w!eJc2Q5?f@oWMz(!fBkrS)9XpT);(K!ev~+Rb0b$ z+`vuT!fo8aUEITcJitRd!eczaQ#`|SyueGm!fU(<{5`AvMw< zEz%)9G9V)|Av3ZdE3zRwav&#iAvf|MFY+Nj3ZNhgp)iV|D2kytN}wc4p)|^%EXtug zDxe}Np)#tVDypG6YM>@+p*HHEF6yB^8lWK>p)s1EDVm`B-O&R*(F?uN2Yt~Gq3DkR7>Gd_j3F3`VHl1P7>Q9BjWHODaTt#Yn21T3 zj47CkX_$@~n2A}KjX9W$d6pfzIEhm@jWallb2yI+xQI)*j4QZ`Yq*XZ zxQSc1jXSuDd$^AWc!)=Mj3;=CXLybmc!^hdjW_raKjCNmf?x3)e#am96Mx}vyv2Lr z!U%`=@c}->NB9_@AUrzr3$h{`vLgp_A{TNa5Aq@( z@}mF>q7VwB2#TT@ilYQdq7+J_49cP$%A*1*q7o{j3aX+Ss-p&Kq84hS4(g&F>Z1V~ zq7fRS37VoAnxh3;q7_=B4cej|+M@$Hq7yo!3%a5kLeL#O&=bAT8-36h{Sb=&7=VEo zguxhsp%{kY7=e)(h0z#;u^5N(n1G3xgvpqKshEc8n1Pv?h1r;cxtNFfSb&9CgvD5b zrC5gLSb>#Th1FPtwOEJs*no}Lgw5E3t=NX`*nyqch27YLz1WBSIDmsVgu^(3qd11+ zIDwNmh0{2Lvp9$IxPXhegv+>stGI^ixPhCvh1UXy#6}#% zMLfhu0whEtBt{Y>MKUBu3Zz6Tq(&N~MLMKM24qAgWJVTbMK)wd4&+2GOR7Mq4MKx4M4b(&})J7fDMLpC<12jY< zG)5CNMKd%<3$#Qlv_>1WMLV=d2XsUybVe6+MK^??J9?ledZ9P^pfCC%6#X#(12G7L zF$6;~48t)3BQXl2F$QBX4&yNa6EO*sF$GgG4bw3LGcgOZF$Z%o5A(4A3$X}`u>?!8 z49l?sE3pczu?B0g4(qW28?gzSu?1VP4coB;JFyG9u?Ksx5BqTd2XP38aRf(k499T- zCvgg=aRz5`4(D+J7jX%faRpa#4cBo4H*pKMaR+yC5BKo^5Ag_(@dQut4A1cbFYyYm z@diKQC;W_G@GE}9@Aw0M;xGJ-w|FmH7~$|fKEQ|g2p{7UgvY1&44)$czQC9G3SZ+J ze2ee!J$^t$L_%alK~zLTbi_bR#6oPuL0rT`d?Y|ZBtl{&K~f|`a-={?q(W+>L0Y6k zdSpOGWI|?SK~`i#cH}@#kb<{vj)Ix34L0!~CeKbHrG(uxEK~pqCbF@H9v_fmNL0hy#dvriYbV6rz zL05D`2)d&OdZHJ4qYwI`A41U|127PSFc?EH6vHqaBQO%9FdAbp7UM7;6EG2zFd0)Y z71J;sGcXggFdK6)7xOS53$PH2uoz3Q6w9z2E3gu)uo`Qy7VEGc8?X_Zuo+vh72B{K zJFpYGup4`@7yGau2XGLFa2Q8$6vuEJCvXy{a2jWD7Uyst7jO}ma2Z!{71wYbH*gcT za2t1U7x!=<5AYC=@EA|<6wmM+FYpqt@EUKzcxUN1xb-W!mwF1ML@K048l*)!q(=s1 zL?&cL7Gy;>WJeCcFP2#c`vcx3ahaOYq1XNu>l*g37fG6Td@t>u>(7? z3%jugd$AAuaR3K#2#0Y5M{x|taRMiC3a4=fXK@baaRC=`372sNS8)y3aRWDT3%79x zcX1E*@c<9;2#@guPw@=T@d7XL3a{}7KjJ6+j9>68e#7th1ApQ#{EfGGFI*Vm@IF4k zhxiB|;}e9(r}zw?BLcp_m-q@_;~RX7@9;f-Ktx1BWJEz!L_>7MKup9!Y{Wra#6x@} zKtd!!VkALQBtvqfKuV-SYNSD0q(gdSKt^OjW@JHDWJ7l3Ku+XBZsb8;8KuMHBX_P@(ltXz`Kt)tSWmG{`R6}*tKuy#_ZPYCfi zG(&T=KufejYqUXIv_pGzKu2^!XLLbVbVCTbqX&AT7kZ-)`l25~(H{da5Q8unLogJ> zFdQQ=5~DC0V=xxuFdh>y5tA?(Q!o|NFdZ{66SFWIb1)b4FdqxB5R0%FORyBnupBF} z605KpYp@pUupS$*5u30XTd)<|upK+F6T7e*d$1S#upb9-5QlIWM{pF!a2zLa5~pw) zXK)tha2^+M5tncoS8x^Aa2+>r6Sr_1cW@W?a32rw5RdQ}Pw*7a@EkAj60h(YZ^C$I z%ol9;2iyHYfuKN8ASe(N2nqxRf&xK-|4e~@cDp~A7yK8Gd<4%N6bK3g1%d)WfuKN8 zASe(N2<8RB-#}0xC=e6~3Iqj$0zrYGKu{nk@XyW*g4=){2u+DpNR2c|i*!hj49JK~ z$c!w=ifqV^9LR}W$c;S6i+sqB0w{<=D2yT~iee~^5-5pMD2*~Gi*hKB3aE%msEjJ8 zifX8i8mNg{sEs)aV-40~9oAz5HewStV+*!o8@6Kyc48NH zV-NOXANJz_4&o3F;|Px87>?rvPT~|!;|$K?9M0ncF5(g{;|i|g8m{98ZsHbh;|}iP z9`54-9^w%m;|ZSP8J^<>Ug8yA;|+eqPxu+X;8*;H-|+|j#9#OuZ}DEZFv8(|e1H$} z5kAHz2#-(k89qk@e1R|V6~4wd_!i&cd;EZih=j<9f~bgw=!k)sh=tgQgSd!?_(*_+ zNQA^lf}}`>f~u&7>ZpO5sD;|7gSx1P`e=ZLXoSXSf~IJO z=4gSIXoc2jgSKdg_UM3)=!DMbg0AR>5OhZm^h7W8Mj!M=KZK$`24EltVK9bZD28D; zMqngHVKl~IEXH9xCSW2aVKSy*DyCsNW?&{}VK(MqF6LoA7GNP3VKJ6qDVAY5R$wJo zVKvrZE!JT@Hee$*VKcU1E4E=fc3>xVVK??*FZN+S4&WdT;V_QiD30McPT(X?;WW5h1|%4yvT?AD1d?}gu*C- zq9}&qD1nkFh0-X4vM7i0sDO&7gvzLbs;GwQsDYZOh1#ftx~PZxXn=-jgvMxsrf7!d zXn~e!h1O_;wrGd;=zxysgwE)KuIPpkbVm>LL@)G4AM`~(grYwNU?2uzFos|#hG95H zU?fIiG{#^o#$h}rU?L`AGNxcEreQi}U?yf^Hs)Y1=3zb-U?CP^F_vH{mSH(oU?o;z zHP&D))?qz1U?VnRGqzwWwqZMVU?+BAH}+sJ_F+E`;2;j+Fpl6Tj^Q{?;3Q7rG|u2G z&fz>R;36*JGOpk%uHiav;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQwMy{DhzJ z3x36K_#J=XPyB_y@fPoe3nLuf#|QWjAK_zsg7EkhpW$;vz!&%uU*T(fgKzO2zQ+%U zh)9TxD2R$^h>jSDiCBn@IEagQh>rwFh(t(?BuI*6NRAXpiBw39G)RkdNRJH2h)l?g zEXay%$c`MyiCoByJjjcD$d3Xjh(aigA}EStD2@^+iBc$yGAN63D31!Lh)Sr8DyWKT zsE!(_iCU6PCTNOgXpRXpau)h)(E?F6fGG2tjxB zKu`2SZ}dT5^g}56V*mzX5C&rihGH0oV+2NG6h>nV#$p`CV*(~(5+-8`reYeVV+Lko z7G`4(=3*Y^V*wUo5f)R{C=e6~3Iqj$0zrXb zyFYB{!>UXy#6}#%MLfhu0whEtBt{Y>MKUBu3Zz6Tq(&N~MLMKM24qAgWJVTbMK)wd z4&+2GOR7Mq4MKx4M4b(&} z)J7fDMLpC<12jY1WMLV=d2XsUybVe6+MK^??J9?ledZ9P^ zpfCC%6#X#(12G7LF$6;~48t)3BQXl2F$QBX4&yNa6EO*sF$GgG4bw3LGcgOZF$Z%o z5A(4A3$X}`u>?!849l?sE3pczu?B0g4(qW28?gzSu?1VP4coB;JFyG9u?Ksx5BqTd z2XP38aRf(k499T-Cvgg=aRz5`4(D+J7jX%faRpa#4cBo4H*pKMaR+yC5BKo^5Ag_( z@dQut4A1cbFYyYm@diKQC;W_G@GE}9@Aw0M;xGJ-w|FmH7~$|fKEQ|g2p{7UgvY1& z44)$czQC9G3SZ+Je2ee!J$^t$L_%alK~zLTbi_bR#6oPuL0rT`d?Y|ZBtl{&K~f|` za-={?q(W+>L0Y6kdSpOGWI|?SK~`i#cH}@#kb<{vj)Ix34L0!~CeKbHrG(uxEK~pqCbF@H9v_fmN zL0hy#dvriYbV6rzL05D`2)d&OdZHJ4qYwI`A41U|127PSFc?EH6vHqaBQO%9FdAbp z7UM7;6EG2zFd0)Y71J;sGcXggFdK6)7xOS53$PH2uoz3Q6w9z2E3gu)uo`Qy7VEGc z8?X_Zuo+vh72B{KJFpYGup4`@7yGau2XGLFa2Q8$6vuEJCvXy{a2jWD7Uyst7jO}m za2Z!{71wYbH*gcTa2t1U7x!=<5AYC=@EA|<6wmM+FYpqt@EUKzcxUN1xD7bDmwF1M zL@K048l*)!q(=s1L?&cL7Gy;>WJeCcFP2#c`vcx3ahaOYq1XNu>l*g z37fG6Td@t>u>(7?3%jugd$AAuaR3K#2#0Y5M{x|taRMiC3a4=fXK@baaRC=`372sN zS8)y3aRWDT3%79xcX1E*@c<9;2#@guPw@=T@d7XL3a{}7KjJ6+j9>68e#7th1ApQ# z{EfGGFI*Vm@IF4khxiB|;}e9(r}zw?BLcp_m-q@_;~RX7@9;f-Ktx1BWJEz!L_>7M zKup9!Y{Wra#6x@}Ktd!!VkALQBtvqfKuV-SYNSD0q(gdSKt^OjW@JHDWJ7l3Ku+XB zZsb8;8KuMHBX_P@(ltXz`Kt)tSWmG{`R6}*tKuy#_ZPYCfiG(&T=KufejYqUXIv_pGzKu2^!XLLbVbVCTbqX&AT7kZ-)`l25~ z(H{da5Q8unLogJ>FdQQ=5~DC0V=xxuFdh>y5tA?(Q!o|NFdZ{66SFWIb1)b4FdqxB z5R0%FORyBnupBF}605KpYp@pUupS$*5u30XTd)<|upK+F6T7e*d$1S#upb9-5QlIW zM{pF!a2zLa5~pw)XK)tha2^+M5tncoS8x^Aa2+>r6Sr_1cW@W?a32rw5RdQ}Pw*7a z@EkAj60h(YZ^C$I%ol9;2iyHYfuKN8ASe(N2nqxRf&xK-|4e~@cDp~A7X$}Lf&xK- zpg>R{C=e6~3Iqj$0{_JV|LnXVxb@4%Z%U*>YNSD0q(gdSKt^OjW@JHDWJ7l3Ku+XB zZsb8;8KuMHBX_P@(ltXz`Kt)tSWmG{`R6}*tKuy#_ZPYCfiG(&T=KufejYqUXIv_pGzKu2^!XLLbVbVCTbqX&AT7kZ-)`l25~ z(H{da5Q8unLogJ>FdQQ=5~DC0V=xxuFdh>y5tA?(Q!o|NFdZ{66SFWIb1)b4FdqxB z5R0%FORyBnupBF}605KpYp@pUupS$*5u30XTd)<|upK+F6T7e*d$1S#upb9-5QlIW zM{pF!a2zLa5~pw)XK)tha2^+M5tncoS8x^Aa2+>r6Sr_1cW@W?a32rw5RdQ}Pw*7a z@EkAj60h(YZ}202!q4~xzv4Iijz91x{=(mQi}%8X5f1O;1AK^&@G(9?czlY_@Hryj z3w(*M@HM`{xA+d<;|D}UBt%9OL`5`2M-0S7EW}0}#6>*BM*<{7A|yrCS*nyWJNY)M-JpfF62fYArwXt6h$!w>E3`%%v_(6# zM+bC7Cv-*^bVWCWpgVe?Cwieb`k*iRAr$>F00S`ygE0g{F$}{o0wXaBqcH|!F%IJ~ z0TVF^lQ9KTF%8o(12ZuTvoQyAF%R>x01L4Qi?IYtu?)+x0xPi!tFZ=au@3980UNOi zo3RC3u?^d?13R$`yRip*u@C!k00(ghhj9c)aSX?C0w-|_r*Q^naSrEk0T*!zmvIGG zaShjT12=ICw{Zt|aS!+L01xp9kMRUg@eI%L0x$6jukj{~cb0zt{}^!i;MOm1_LNA4 z)JTK0NQd;ufQ-n5%*cYQ$cF65ft<*N+{lBx$cOwWfPyH5!YG2GD2C!Ffs!bN(kO$n zD2MW>fQqPu%BX^>sD|pOftsj=+NguNsE7J!fQD#<#%O}3Xolu!ftF~6)@XyaXovRb zfR5;d&gg=!=!OtMDhF~a$VK_!$Bt~I0#$YVQVLT>a zA|_!nreG?jVLE1DCT3wa=3p-7VLldMAr@gVmS8ECVL4V{C01cI)?h8xVLdirBQ{|( zwqPr^VLNtUCw5^s_FymeVLuMwAP(U$j^HSc;W$pMCT`(2?%*!&;XWSVAs*o|p5Q5-;W=L5C0^k*-rz_4grD&Xe#LM29e?0Y{Dr^q z7Vm`%BOKnx2lx;l;bVM)@c0y;;d4a57x)ri;cI+@Z}AB>4ju?oE zScr`{h>LiLj|51FL`aMzNQz`gjuc3VR7j09NQ-nxj||9&OvsEZ$ck*pjvUB|T*!?) z$cuc)j{+!&LMV(PD2iezjuI$|QYeiwD2s9^j|!-WN~nw~sETT+jvA^g&=dVjRX}0w!V-CSwYwVj8An24-RwW@8TKVjkvW0TyBr z7GnvPVi}fW1y*7eR$~p;Vjb3F12$q4He(C6VjH$&2X=sR{C=e6~3IqlI*#g0Kf7sH8Rhd|b zjW~#lc!-Y#NQgv8j3h{kWJrz_NQqQPjWkG$bV!d3$cRkHj4a5CY{-rr$cbFYjXcPU ze8`UiD2PHRj3OwCVknLhD2Y-ijWQ^Uawv}qsEA6aj4G&#YN(DHsEJyrjXJ1{dZ>>E zXoyB=j3#J`W@wHUXo*&6jW%eDc4&_d=!j0}j4tSkZU{kl^gvJaLT~gzU-UyL`eOhF zVh{#n2!>)9hGPUqViZPW48~#{#$y5|ViG1}3Z`Njreg+XVism&4(4JW=3@aCVi6W& z36^3RmSY80Vii_n4c1~E)?))UViPuF3$|h#wqpl&Vi$H}5B6do_TvB!;t&qw2#(?y zj^hMQ;uKEf49?;l&f@|u;u0?73a;WBuHy!7;udb>4({R}?&AR-;t?L>37+B^p5p~x z;uT)w4SvK=_!+<8SNw+G@dy6IU-%nu@m{zv!r^^h=G`hh1iILxQK`NNPvV$gv3aKq)3M3NP(0{h15uc zv`B~a$bgK5h1|%4yvT?AD1d?}gu*C-q9}&qD1nkFh0-X4vM7i0 zsDO&7gvzLbs;GwQsDYZOh1#ftx~PZxXn=-jgvMxsrf7!dXn~e!h1O_;wrGd;=zxys zgwE)KuIPpkbVm>LL@)G4AM`~(grYwNU?2uzFos|#hG95HU?fIiG{#^o#$h}rU?L`A zGNxcEreQi}U?yf^Hs)Y1=3zb-U?CP^F_vH{mSH(oU?o;zHP&D))?qz1U?VnRGqzwW zwqZMVU?+BAH}+sJ_F+E`;2;j+Fpl6Tj^Q{?;3Q7rG|u2G&fz>R;36*JGOpk%uHiav z;3jV2Htygq?%_Tj;2|F2F`nQlp5ZxO;3Zz+HQt2r&eCsi>sN9w^%O{nR7j09NQ-nx zj||9&OvsEZ$ck*pjvUB|T*!?)$cuc)j{+!&LMV(PD2iezjuI$|QYeiwD2s9^j|!-W zN~nw~sETT+jvA^g&=dVjRX}0w!V-CSwYw zVj8An24-RwW@8TKVjkvW0TyBr7GnvPVi}fW1y*7eR$~p;Vjb3F12$q4He(C6VjH$& z2X4JD1)*nhw`X^il~IjsDi4fhU%z+ny7`^sDrwwhx%xMhG>Mw zXo99_hURF2mS~06XoI$BhxX`zj_8EW=z^~3h7fc|5A;MY^hO`_ML&e1KL%hR24OIU zU?_%RI7VP3MqxC@U@XRAJSJcwCSfwBU@E3zI%Z%dW??qwU@qoiJ{Djh7GW`#U@4Yi zIaXjLR$(>PU@g{RJvLw?HeoZiU@Nv^J9c0vc40U6U@!JzKMvp^4&gA4;3$saI8NXs zPT@4p;4IGJJTBlOF5xn+;3}@+I&R=5Zs9iW;4bdrJ|5s99^o;b;3=NrIbPr;Ug0&~ zgz?UpFWBx6w)=wuL4lw^P#`D}6bK3g1%d+qnF9apc7HH0_-7Ae1V1e(5EKXs1O&xo#5Gm b0zrYGKu{nk5EKXs1O sz; - size_t m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 0, false, "test failed"); - sz.push_back(1); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 1, false, "test failed"); - sz.push_back(10); - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 5, false, "test failed"); - - sz.clear(); - sz.resize(3); - sz[0] = 0; - sz[1] = 9; - sz[2] = 3; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 3, false, "test failed"); - - sz.clear(); - sz.resize(4); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 41, false, "test failed"); - - - - sz.clear(); - sz.resize(5); - sz[0] = 77; - sz[1] = 9; - sz[2] = 22; - sz[3] = 60; - sz[4] = 11; - m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 22, false, "test failed"); - return true; - } - } -} - diff --git a/src/contrib/epee/tests/src/net/test_net.h b/src/contrib/epee/tests/src/net/test_net.h deleted file mode 100644 index ddcae6d..0000000 --- a/src/contrib/epee/tests/src/net/test_net.h +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include - -#include "net/levin_server_cp2.h" -#include "storages/abstract_invoke.h" - -namespace epee -{ -namespace StorageNamed -{ - typedef CInMemStorage DefaultStorageType; -} -namespace tests -{ - struct some_subdata - { - - std::string str1; - std::list array_of_id; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(str1) - SERIALIZE_STL_CONTAINER_POD(array_of_id) - END_NAMED_SERIALIZE_MAP() - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_EXAMPLE_1 - { - const static int ID = 1000; - - struct request - { - - std::string example_string_data; - uint64_t example_id_data; - some_subdata sub; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(example_string_data) - SERIALIZE_POD(example_id_data) - SERIALIZE_T(sub) - END_NAMED_SERIALIZE_MAP() - }; - - - struct response - { - bool m_success; - uint64_t example_id_data; - std::list subs; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(m_success) - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_CONTAINER_T(subs) - END_NAMED_SERIALIZE_MAP() - }; - }; - - struct COMMAND_EXAMPLE_2 - { - const static int ID = 1001; - - struct request - { - std::string example_string_data2; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_STL_ANSI_STRING(example_string_data2) - END_NAMED_SERIALIZE_MAP() - }; - - struct response - { - bool m_success; - uint64_t example_id_data; - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_POD(example_id_data) - SERIALIZE_POD(m_success) - END_NAMED_SERIALIZE_MAP() - }; - }; - typedef boost::uuids::uuid uuid; - - class test_levin_server: public levin::levin_commands_handler<> - { - test_levin_server(const test_levin_server&){} - public: - test_levin_server(){} - void set_thread_prefix(const std::string& pref) - { - m_net_server.set_threads_prefix(pref); - } - template - bool connect_async(const std::string adr, const std::string& port, uint32_t conn_timeot, calback_t cb, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect_async(adr, port, conn_timeot, cb, bind_ip); - } - - bool connect(const std::string adr, const std::string& port, uint32_t conn_timeot, net_utils::connection_context_base& cn, const std::string& bind_ip = "0.0.0.0") - { - return m_net_server.connect(adr, port, conn_timeot, cn, bind_ip); - } - void close(net_utils::connection_context_base& cn) - { - m_net_server.get_config_object().close(cn.m_connection_id); - } - - template - bool invoke(uuid con_id, int command, t_request& req, t_response& resp) - { - return invoke_remote_command(con_id, command, req, resp, m_net_server.get_config_object()); - } - - template< class t_response, class t_request, class callback_t> - bool invoke_async(uuid con_id, int command, t_request& req, callback_t cb) - { - return async_invoke_remote_command(con_id, command, req, m_net_server.get_config_object(), cb); - } - - bool init(const std::string& bind_port = "", const std::string& bind_ip = "0.0.0.0") - { - m_net_server.get_config_object().m_pcommands_handler = this; - m_net_server.get_config_object().m_invoke_timeout = 1000; - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); - return m_net_server.init_server(bind_port, bind_ip); - } - - bool run() - { - //here you can set worker threads count - int thrds_count = 4; - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - bool deinit() - { - return m_net_server.deinit_server(); - } - - bool send_stop_signal() - { - m_net_server.send_stop_signal(); - return true; - } - - uint32_t get_binded_port() - { - return m_net_server.get_binded_port(); - } - private: - - - CHAIN_LEVIN_INVOKE_TO_MAP(); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_TO_STUB(); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP(test_levin_server) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_1, &test_levin_server::handle_1) - HANDLE_INVOKE_T(COMMAND_EXAMPLE_2, &test_levin_server::handle_2) - END_INVOKE_MAP() - - //----------------- commands handlers ---------------------------------------------- - int handle_1(int command, COMMAND_EXAMPLE_1::request& arg, COMMAND_EXAMPLE_1::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "---->>"); - COMMAND_EXAMPLE_2::request arg_ = AUTO_VAL_INIT(arg_); - arg_.example_id_data = arg.example_id_data; - COMMAND_EXAMPLE_2::response rsp_ = AUTO_VAL_INIT(rsp_); - invoke_async(context.m_connection_id, COMMAND_EXAMPLE_2::ID, arg_, [](int code, const COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - if(code < 0) - {LOG_PRINT_RED_L0("on_command_1: command_2 failed to invoke");} - else - {LOG_PRINT_L0("on_command_1: command_2 response " << rsp.example_id_data);} - }); - rsp.example_id_data = arg.example_id_data; - LOG_PRINT_L0("on_command_1: id " << arg.example_id_data << "<<----"); - return true; - } - int handle_2(int command, COMMAND_EXAMPLE_2::request& arg, COMMAND_EXAMPLE_2::response& rsp, const net_utils::connection_context_base& context) - { - LOG_PRINT_L0("on_command_2: id "<< arg.example_id_data); - rsp.example_id_data = arg.example_id_data; - //misc_utils::sleep_no_w(6000); - return true; - } - //---------------------------------------------------------------------------------- - net_utils::boosted_levin_async_server m_net_server; - }; - - - inline - bool do_run_test_server() - { - - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread th1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread th2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initalized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - net_utils::connection_context_base cntxt_1; - bool r = srv1.connect("127.0.0.1", string_tools::num_to_string_fast(port2), 5000, cntxt_1); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - net_utils::connection_context_base cntxt_2; - r = srv2.connect("127.0.0.1", string_tools::num_to_string_fast(port1), 5000, cntxt_2); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); - - while(true) - { - LOG_PRINT_L0("Invoking from A to B..."); - int r = srv1.invoke(cntxt_1.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke A to B"); - break; - } - - LOG_PRINT_L0("Invoking from B to A..."); - r = srv2.invoke(cntxt_2.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, resp); - if(r<=0) - { - LOG_ERROR("Failed tp invoke B to A"); - break; - } - } - srv1.send_stop_signal(); - srv2.send_stop_signal(); - th1.join(); - th1.join(); - - return true; - } - - - - inline bool do_test2_work_with_srv(test_levin_server& srv, int port) - { - uint64_t i = 0; - boost::mutex wait_event; - CRITICAL_SECTION_LOCK(wait_event); - while(true) - { - net_utils::connection_context_base cntxt_local = AUTO_VAL_INIT(cntxt_local); - bool r = srv.connect_async("127.0.0.1", string_tools::num_to_string_fast(port), 5000, [&srv, &port, &wait_event, &i, &cntxt_local](const net_utils::connection_context_base& cntxt, const boost::system::error_code& ec) - { - CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " << ec.message() ); - cntxt_local = cntxt; - LOG_PRINT_L0("Invoking command 1 to " << port); - COMMAND_EXAMPLE_1::request arg = AUTO_VAL_INIT(arg); - arg.example_id_data = i; - /*vc2010 workaround*/ - int port_ = port; - boost::mutex& wait_event_ = wait_event; - int r = srv.invoke_async(cntxt.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, [port_, &wait_event_](int code, const COMMAND_EXAMPLE_1::request& rsp, const net_utils::connection_context_base& cntxt) - { - CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke"); - LOG_PRINT_L0("command 1 invoke to " << port_ << " OK."); - CRITICAL_SECTION_UNLOCK(wait_event_); - }); - }); - CRITICAL_SECTION_LOCK(wait_event); - srv.close(cntxt_local); - ++i; - } - return true; - } - - inline - bool do_run_test_server_async_connect() - { - test_levin_server srv1, srv2; - - - std::string bind_param = "0.0.0.0"; - std::string port = ""; - - if(!srv1.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - if(!srv2.init(port, bind_param)) - { - LOG_ERROR("Failed to initialize srv!"); - return 1; - } - - srv1.set_thread_prefix("SRV_A"); - srv2.set_thread_prefix("SRV_B"); - - boost::thread thmain1( boost::bind(&test_levin_server::run, &srv1)); - boost::thread thmain2( boost::bind(&test_levin_server::run, &srv2)); - - LOG_PRINT_L0("Initalized servers, waiting for worker threads started..."); - misc_utils::sleep_no_w(1000); - - - LOG_PRINT_L0("Connecting to each other..."); - uint32_t port1 = srv1.get_binded_port(); - uint32_t port2 = srv2.get_binded_port(); - - COMMAND_EXAMPLE_1::request arg; - COMMAND_EXAMPLE_1::request resp; - - - boost::thread work_1( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_2( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_3( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_4( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_5( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_6( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - boost::thread work_7( boost::bind(do_test2_work_with_srv, boost::ref(srv1), port2)); - boost::thread work_8( boost::bind(do_test2_work_with_srv, boost::ref(srv2), port1)); - - - work_1.join(); - work_2.join(); - srv1.send_stop_signal(); - srv2.send_stop_signal(); - thmain1.join(); - thmain2.join(); - - return true; - } - -} -} \ No newline at end of file diff --git a/src/contrib/epee/tests/src/storages/portable_storages_test.h b/src/contrib/epee/tests/src/storages/portable_storages_test.h deleted file mode 100644 index ecded8d..0000000 --- a/src/contrib/epee/tests/src/storages/portable_storages_test.h +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include -#include -#include "storages/serializeble_struct_helper.h" -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage.h" -#include "storages/portable_storage_template_helper.h" - -namespace epee -{ - namespace tests - { - - struct port_test_struct_sub - { - std::string m_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - END_KV_SERIALIZE_MAP() - }; - -#pragma pack (push, 1) - struct some_pod_struct - { - uint64_t a; - int32_t b; - }; -#pragma pack(pop) - - struct port_test_struct - { - std::string m_str; - uint64_t m_uint64; - uint32_t m_uint32; - uint16_t m_uint16; - uint8_t m_uint8; - int64_t m_int64; - int32_t m_int32; - int16_t m_int16; - int8_t m_int8; - double m_double; - bool m_bool; - some_pod_struct m_pod; - std::list m_list_of_str; - std::list m_list_of_uint64_t; - std::list m_list_of_uint32_t; - std::list m_list_of_uint16_t; - std::list m_list_of_uint8_t; - std::list m_list_of_int64_t; - std::list m_list_of_int32_t; - std::list m_list_of_int16_t; - std::list m_list_of_int8_t; - std::list m_list_of_double; - std::list m_list_of_bool; - port_test_struct_sub m_subobj; - std::list m_list_of_self; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL(m_str) - KV_SERIALIZE_VAL(m_uint64) - KV_SERIALIZE_VAL(m_uint32) - KV_SERIALIZE_VAL(m_uint16) - KV_SERIALIZE_VAL(m_uint8) - KV_SERIALIZE_VAL(m_int64) - KV_SERIALIZE_VAL(m_int32) - KV_SERIALIZE_VAL(m_int16) - KV_SERIALIZE_VAL(m_int8) - KV_SERIALIZE_VAL(m_double) - KV_SERIALIZE_VAL(m_bool) - KV_SERIALIZE_VAL_POD_AS_BLOB(m_pod) - KV_SERIALIZE_OBJ(m_subobj) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_str) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_uint8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int64_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int32_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int16_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_int8_t) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_double) - KV_SERIALIZE_CONTAINER_VAL(m_list_of_bool) - KV_SERIALIZE_CONTAINER_OBJ(m_list_of_self) - END_KV_SERIALIZE_MAP() - }; - - bool operator != (const port_test_struct_sub& a, const port_test_struct_sub& b) - { - return b.m_str != a.m_str; - } - - bool operator == (const port_test_struct& a, const port_test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint64 != a.m_uint64 - || b.m_uint32 != a.m_uint32 - || b.m_uint16 != a.m_uint16 - || b.m_uint8 != a.m_uint8 - || b.m_int64 != a.m_int64 - || b.m_int32 != a.m_int32 - || b.m_int16 != a.m_int16 - || b.m_int8 != a.m_int8 - || b.m_double != a.m_double - || b.m_bool != a.m_bool - || b.m_pod.a != a.m_pod.a - || b.m_pod.b != a.m_pod.b - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_uint64_t != a.m_list_of_uint64_t - || b.m_list_of_uint32_t != a.m_list_of_uint32_t - || b.m_list_of_uint16_t != a.m_list_of_uint16_t - || b.m_list_of_uint8_t != a.m_list_of_uint8_t - || b.m_list_of_int64_t != a.m_list_of_int64_t - || b.m_list_of_int32_t != a.m_list_of_int32_t - || b.m_list_of_int16_t != a.m_list_of_int16_t - || b.m_list_of_int8_t != a.m_list_of_int8_t - || b.m_list_of_double != a.m_list_of_double - || b.m_list_of_bool != a.m_list_of_bool - || b.m_subobj != a.m_subobj - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - void fill_struct_with_test_values(port_test_struct& s) - { - s.m_str = "zuzuzuzuzuz"; - s.m_uint64 = 111111111111111; - s.m_uint32 = 2222222; - s.m_uint16 = 2222; - s.m_uint8 = 22; - s.m_int64 = -111111111111111; - s.m_int32 = -2222222; - s.m_int16 = -2222; - s.m_int8 = -24; - s.m_double = 0.11111; - s.m_bool = true; - s.m_pod.a = 32342342342342; - s.m_pod.b = -342342; - s.m_list_of_str.push_back("1112121"); - s.m_list_of_uint64_t.push_back(1111111111); - s.m_list_of_uint64_t.push_back(2222222222); - s.m_list_of_uint32_t.push_back(1111111); - s.m_list_of_uint32_t.push_back(2222222); - s.m_list_of_uint16_t.push_back(1111); - s.m_list_of_uint16_t.push_back(2222); - s.m_list_of_uint8_t.push_back(11); - s.m_list_of_uint8_t.push_back(22); - - - s.m_list_of_int64_t.push_back(-1111111111); - s.m_list_of_int64_t.push_back(-222222222); - s.m_list_of_int32_t.push_back(-1111111); - s.m_list_of_int32_t.push_back(-2222222); - s.m_list_of_int16_t.push_back(-1111); - s.m_list_of_int16_t.push_back(-2222); - s.m_list_of_int8_t.push_back(-11); - s.m_list_of_int8_t.push_back(-22); - - s.m_list_of_double.push_back(0.11111); - s.m_list_of_double.push_back(0.22222); - s.m_list_of_bool.push_back(true); - s.m_list_of_bool.push_back(false); - - s.m_subobj.m_str = "subszzzzzzzz"; - s.m_list_of_self.push_back(s); - } - - bool test_portable_storages(const std::string& tests_folder) - { - serialization::portable_storage ps, ps2; - port_test_struct s1, s2; - fill_struct_with_test_values(s1); - - s1.store(ps); - std::string binbuf; - bool r = ps.store_to_binary(binbuf); - - ps2.load_from_binary(binbuf); - s2.load(ps2); - if(!(s1 == s2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - - port_test_struct ss1, ss2; - fill_struct_with_test_values(ss1); - std::string json_buff = epee::serialization::store_t_to_json(ss1); - epee::serialization::load_t_from_json(ss2, json_buff); - if(!(ss1 == ss2)) - { - LOG_ERROR("Portable storage test failed!"); - return false; - } - - return true; - } - - } -} \ No newline at end of file diff --git a/src/contrib/epee/tests/src/storages/storage_tests.h b/src/contrib/epee/tests/src/storages/storage_tests.h deleted file mode 100644 index 522e589..0000000 --- a/src/contrib/epee/tests/src/storages/storage_tests.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the Andrey N. Sabelnikov nor the -// names of its contributors may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - - - -#pragma once - -#include "storages/serializeble_struct_helper.h" -#include "storages/portable_storage.h" - -namespace epee -{ - namespace tests - { - - - struct test_struct - { - - std::string m_str; - unsigned int m_uint; - bool m_bool; - std::list m_list_of_str; - std::list m_list_of_int; - std::list m_list_of_self; - - - BEGIN_NAMED_SERIALIZE_MAP() - SERIALIZE_STL_ANSI_STRING(m_str) - SERIALIZE_POD(m_uint) - SERIALIZE_POD(m_bool) - SERIALIZE_STL_CONTAINER_ANSII_STRING(m_list_of_str) - SERIALIZE_STL_CONTAINER_POD(m_list_of_int) - SERIALIZE_STL_CONTAINER_T(m_list_of_self) - END_NAMED_SERIALIZE_MAP() - - }; - - - bool operator == (const test_struct& a, const test_struct& b) - { - if( b.m_str != a.m_str - || b.m_uint != a.m_uint - || b.m_bool != a.m_bool - || b.m_list_of_str != a.m_list_of_str - || b.m_list_of_int != a.m_list_of_int - || b.m_list_of_self != a.m_list_of_self - ) - return false; - return true; - } - - inline test_struct get_test_struct() - { - test_struct t = boost::value_initialized(); - t.m_bool = true; - t.m_str = "ackamdc'kmecemcececmacmecmcm[aicm[oeicm[oeicm[qaicm[qoe"; - t.m_uint = 233242; - for(int i = 0; i!=500; i++) - t.m_list_of_int.push_back(i); - - for(int i = 0; i!=500; i++) - t.m_list_of_str.push_back("ssccd"); - - for(int i = 0; i!=5; i++) - { - t.m_list_of_self.push_back(t); - } - return t; - } - - bool test_storages(const std::string& tests_folder) - { - - epee::serialization::portable_storage ps; - auto s = ps.open_section("zzz", nullptr); - uint64_t i = 0; - ps.get_value("afdsdf", i, s); - - - LOG_PRINT_L0("Generating test struct..."); - boost::filesystem::path storage_folder = tests_folder; - storage_folder /= "storages"; - - - test_struct t = get_test_struct(); - - LOG_PRINT_L0("Loading test struct from storage..."); - test_struct t2; - bool res = epee::StorageNamed::load_struct_from_storage_file(t2, (storage_folder /+ "valid_storage.bin").string()); - CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin"); - - LOG_PRINT_L0("Comparing generated and loaded test struct..."); - if(!(t == t2)) - return false; - - LOG_PRINT_L0("Loading broken archive 1..."); - test_struct t3; - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_1.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not "); - - - LOG_PRINT_L0("Loading broken archive 2..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_2.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 3..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_3.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - LOG_PRINT_L0("Loading broken archive 4..."); - res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder /+ "invalid_storage_4.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); - - return true; - } - } -} - diff --git a/src/contrib/epee/tests/src/tests.cpp b/src/contrib/epee/tests/src/tests.cpp deleted file mode 100644 index ed045d8..0000000 --- a/src/contrib/epee/tests/src/tests.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "include_base_utils.h" -#include "storages/storage_tests.h" -#include "misc/test_math.h" -#include "storages/portable_storages_test.h" -#include "net/test_net.h" - -using namespace epee; - -int main(int argc, char* argv[]) -{ - - string_tools::set_module_name_and_folder(argv[0]); - - //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); - - - string_tools::command_line_params_a start_params; - string_tools::parse_commandline(start_params, argc, argv); - std::string tests_data_path; - string_tools::get_xparam_from_command_line(start_params, std::string("/tests_folder"), tests_data_path); - - if(string_tools::have_in_command_line(start_params, std::string("/run_net_tests"))) - { - if(!tests::do_run_test_server()) - { - LOG_ERROR("net tests failed"); - return 1; - } - if(!tests::do_run_test_server_async_connect() ) - { - LOG_ERROR("net tests failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_unit_tests"))) - { - if(!tests::test_median()) - { - LOG_ERROR("median test failed"); - return 1; - } - - - if(!tests::test_storages(tests_data_path)) - { - LOG_ERROR("storage test failed"); - return 1; - } - }else if(string_tools::have_in_command_line(start_params, std::string("/run_portable_storage_test"))) - { - tests::test_portable_storages(tests_data_path); - } - return 1; -} \ No newline at end of file diff --git a/src/contrib/ethereum/CMakeLists.txt b/src/contrib/ethereum/CMakeLists.txt deleted file mode 100644 index 359ad19..0000000 --- a/src/contrib/ethereum/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_subdirectory(libethash) - -set_property(TARGET ethash PROPERTY FOLDER "contrib") - -if(MSVC) - target_compile_options(ethash PRIVATE /wd4477 /wd4267) -else() - target_compile_options(ethash PRIVATE -Wno-format -Wno-aggregate-return -Wno-empty-body) -endif() - diff --git a/src/contrib/ethereum/libethash/CMakeLists.txt b/src/contrib/ethereum/libethash/CMakeLists.txt deleted file mode 100644 index 8205079..0000000 --- a/src/contrib/ethereum/libethash/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -# Copyright 2018 Pawel Bylica. -# Licensed under the Apache License, Version 2.0. See the LICENSE file. - -# set(include_dir ${PROJECT_SOURCE_DIR}/include) - - -add_library( - ethash - bit_manipulation.h - builtins.h - endianness.hpp - ethash/ethash.h - ethash/ethash.hpp - ethash-internal.hpp - ethash.cpp - ethash/hash_types.h - managed.cpp - ethash/keccak.h - ethash/keccak.hpp - keccak.c - keccakf800.c - keccakf1600.c - kiss99.hpp - primes.h - primes.c - ethash/progpow.hpp - progpow.cpp -) - - - - diff --git a/src/contrib/ethereum/libethash/bit_manipulation.h b/src/contrib/ethereum/libethash/bit_manipulation.h deleted file mode 100644 index 5c7baa7..0000000 --- a/src/contrib/ethereum/libethash/bit_manipulation.h +++ /dev/null @@ -1,82 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include "builtins.h" -#include "support/attributes.h" - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -static inline uint32_t rotl32(uint32_t n, unsigned int c) -{ - const unsigned int mask = 31; - - c &= mask; - unsigned int neg_c = (unsigned int)(-(int)c); - return (n << c) | (n >> (neg_c & mask)); -} - -static inline uint32_t rotr32(uint32_t n, unsigned int c) -{ - const unsigned int mask = 31; - - c &= mask; - unsigned int neg_c = (unsigned int)(-(int)c); - return (n >> c) | (n << (neg_c & mask)); -} - -static inline uint32_t clz32(uint32_t x) -{ - return x ? (uint32_t)__builtin_clz(x) : 32; -} - -static inline uint32_t popcount32(uint32_t x) -{ - return std::bitset<32>(x).count(); -} - -static inline uint32_t mul_hi32(uint32_t x, uint32_t y) -{ - return (uint32_t)(((uint64_t)x * (uint64_t)y) >> 32); -} - - -/** FNV 32-bit prime. */ -static const uint32_t fnv_prime = 0x01000193; - -/** FNV 32-bit offset basis. */ -static const uint32_t fnv_offset_basis = 0x811c9dc5; - -/** - * The implementation of FNV-1 hash. - * - * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1_hash. - */ -NO_SANITIZE("unsigned-integer-overflow") -static inline uint32_t fnv1(uint32_t u, uint32_t v) noexcept -{ - return (u * fnv_prime) ^ v; -} - -/** - * The implementation of FNV-1a hash. - * - * See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash. - */ -NO_SANITIZE("unsigned-integer-overflow") -static inline uint32_t fnv1a(uint32_t u, uint32_t v) noexcept -{ - return (u ^ v) * fnv_prime; -} - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/ethereum/libethash/builtins.h b/src/contrib/ethereum/libethash/builtins.h deleted file mode 100644 index 6cf6a28..0000000 --- a/src/contrib/ethereum/libethash/builtins.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -/** - * @file - * Implementation of GCC/clang builtins for MSVC compiler. - */ - -#pragma once - -#ifdef _MSC_VER -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Returns the number of leading 0-bits in `x`, starting at the most significant bit position. - * If `x` is 0, the result is undefined. - */ -static inline int __builtin_clz(unsigned int x) -{ - unsigned long most_significant_bit; - _BitScanReverse(&most_significant_bit, x); - return 31 - (int)most_significant_bit; -} - -/** - * Returns the number of 1-bits in `x`. - */ -static inline int __builtin_popcount(unsigned int x) -{ - return (int)__popcnt(x); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/ethereum/libethash/endianness.hpp b/src/contrib/ethereum/libethash/endianness.hpp deleted file mode 100644 index 3472477..0000000 --- a/src/contrib/ethereum/libethash/endianness.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -/// @file -/// This file contains helper functions to handle big-endian architectures. -/// The Ethash algorithm is naturally defined for little-endian architectures -/// so for those the helpers are just no-op empty functions. -/// For big-endian architectures we need 32-bit and 64-bit byte swapping in -/// some places. - -#pragma once - -#include - -#if _WIN32 - -#include - -#define bswap32 _byteswap_ulong -#define bswap64 _byteswap_uint64 - -// On Windows assume little endian. -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN - -#elif __APPLE__ - -#include - -#define bswap32 __builtin_bswap32 -#define bswap64 __builtin_bswap64 - -#else - -#include - -#define bswap32 __builtin_bswap32 -#define bswap64 __builtin_bswap64 - -#endif - -namespace ethash -{ -#if __BYTE_ORDER == __LITTLE_ENDIAN - -struct le -{ - static uint32_t uint32(uint32_t x) noexcept { return x; } - static uint64_t uint64(uint64_t x) noexcept { return x; } - - static const hash1024& uint32s(const hash1024& h) noexcept { return h; } - static const hash512& uint32s(const hash512& h) noexcept { return h; } - static const hash256& uint32s(const hash256& h) noexcept { return h; } -}; - -struct be -{ - static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); } -}; - - -#elif __BYTE_ORDER == __BIG_ENDIAN - -struct le -{ - static uint32_t uint32(uint32_t x) noexcept { return bswap32(x); } - static uint64_t uint64(uint64_t x) noexcept { return bswap64(x); } - - static hash1024 uint32s(hash1024 h) noexcept - { - for (auto& w : h.word32s) - w = uint32(w); - return h; - } - - static hash512 uint32s(hash512 h) noexcept - { - for (auto& w : h.word32s) - w = uint32(w); - return h; - } - - static hash256 uint32s(hash256 h) noexcept - { - for (auto& w : h.word32s) - w = uint32(w); - return h; - } -}; - -struct be -{ - static uint64_t uint64(uint64_t x) noexcept { return x; } -}; - -#endif -} // namespace ethash \ No newline at end of file diff --git a/src/contrib/ethereum/libethash/ethash-internal.hpp b/src/contrib/ethereum/libethash/ethash-internal.hpp deleted file mode 100644 index 96209bd..0000000 --- a/src/contrib/ethereum/libethash/ethash-internal.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -/// @file -/// Contains declarations of internal ethash functions to allow them to be -/// unit-tested. - -#pragma once - -#include - -#include "endianness.hpp" - -#include -#include - -extern "C" struct ethash_epoch_context_full : ethash_epoch_context -{ - ethash_hash1024* full_dataset; - - constexpr ethash_epoch_context_full(int epoch_number, int light_cache_num_items, - const ethash_hash512* light_cache, const uint32_t* l1_cache, int full_dataset_num_items, - ethash_hash1024* full_dataset) noexcept - : ethash_epoch_context{epoch_number, light_cache_num_items, light_cache, l1_cache, - full_dataset_num_items}, - full_dataset{full_dataset} - {} -}; - -namespace ethash -{ -inline bool is_less_or_equal(const hash256& a, const hash256& b) noexcept -{ - for (size_t i = 0; i < (sizeof(a) / sizeof(a.word64s[0])); ++i) - { - if (be::uint64(a.word64s[i]) > be::uint64(b.word64s[i])) - return false; - if (be::uint64(a.word64s[i]) < be::uint64(b.word64s[i])) - return true; - } - return true; -} - -inline bool is_equal(const hash256& a, const hash256& b) noexcept -{ - return std::memcmp(a.bytes, b.bytes, sizeof(a)) == 0; -} - -void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept; - -hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept; -hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept; -hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept; - -namespace generic -{ -using hash_fn_512 = hash512 (*)(const uint8_t* data, size_t size); -using build_light_cache_fn = void (*)(hash512 cache[], int num_items, const hash256& seed); - -void build_light_cache( - hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept; - -epoch_context_full* create_epoch_context( - build_light_cache_fn build_fn, int epoch_number, bool full) noexcept; - -} // namespace generic - -} // namespace ethash diff --git a/src/contrib/ethereum/libethash/ethash.cpp b/src/contrib/ethereum/libethash/ethash.cpp deleted file mode 100644 index b631523..0000000 --- a/src/contrib/ethereum/libethash/ethash.cpp +++ /dev/null @@ -1,474 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -#include "ethash-internal.hpp" - -#include "bit_manipulation.h" -#include "endianness.hpp" -#include "primes.h" -#include "support/attributes.h" -#include -#include - -#include -#include -#include -#include - -namespace ethash -{ -// Internal constants: -constexpr static int light_cache_init_size = 1 << 24; -constexpr static int light_cache_growth = 1 << 17; -constexpr static int light_cache_rounds = 3; -constexpr static int full_dataset_init_size = 1 << 30; -constexpr static int full_dataset_growth = 1 << 23; -constexpr static int full_dataset_item_parents = 256; - -// Verify constants: -static_assert(sizeof(hash512) == ETHASH_LIGHT_CACHE_ITEM_SIZE, ""); -static_assert(sizeof(hash1024) == ETHASH_FULL_DATASET_ITEM_SIZE, ""); -static_assert(light_cache_item_size == ETHASH_LIGHT_CACHE_ITEM_SIZE, ""); -static_assert(full_dataset_item_size == ETHASH_FULL_DATASET_ITEM_SIZE, ""); - - -namespace -{ -using ::fnv1; - -inline hash512 fnv1(const hash512& u, const hash512& v) noexcept -{ - hash512 r; - for (size_t i = 0; i < sizeof(r) / sizeof(r.word32s[0]); ++i) - r.word32s[i] = fnv1(u.word32s[i], v.word32s[i]); - return r; -} - -inline hash512 bitwise_xor(const hash512& x, const hash512& y) noexcept -{ - hash512 z; - for (size_t i = 0; i < sizeof(z) / sizeof(z.word64s[0]); ++i) - z.word64s[i] = x.word64s[i] ^ y.word64s[i]; - return z; -} -} // namespace - -int find_epoch_number(const hash256& seed) noexcept -{ - static constexpr int num_tries = 30000; // Divisible by 16. - - // Thread-local cache of the last search. - static thread_local int cached_epoch_number = 0; - static thread_local hash256 cached_seed = {}; - - // Load from memory once (memory will be clobbered by keccak256()). - const uint32_t seed_part = seed.word32s[0]; - const int e = cached_epoch_number; - hash256 s = cached_seed; - - if (s.word32s[0] == seed_part) - return e; - - // Try the next seed, will match for sequential epoch access. - s = keccak256(s); - if (s.word32s[0] == seed_part) - { - cached_seed = s; - cached_epoch_number = e + 1; - return e + 1; - } - - // Search for matching seed starting from epoch 0. - s = {}; - for (int i = 0; i < num_tries; ++i) - { - if (s.word32s[0] == seed_part) - { - cached_seed = s; - cached_epoch_number = i; - return i; - } - - s = keccak256(s); - } - - return -1; -} - -namespace generic -{ -void build_light_cache( - hash_fn_512 hash_fn, hash512 cache[], int num_items, const hash256& seed) noexcept -{ - hash512 item = hash_fn(seed.bytes, sizeof(seed)); - cache[0] = item; - for (int i = 1; i < num_items; ++i) - { - item = hash_fn(item.bytes, sizeof(item)); - cache[i] = item; - } - - for (int q = 0; q < light_cache_rounds; ++q) - { - for (int i = 0; i < num_items; ++i) - { - const uint32_t index_limit = static_cast(num_items); - - // Fist index: 4 first bytes of the item as little-endian integer. - const uint32_t t = le::uint32(cache[i].word32s[0]); - const uint32_t v = t % index_limit; - - // Second index. - const uint32_t w = static_cast(num_items + (i - 1)) % index_limit; - - const hash512 x = bitwise_xor(cache[v], cache[w]); - cache[i] = hash_fn(x.bytes, sizeof(x)); - } - } -} - -epoch_context_full* create_epoch_context( - build_light_cache_fn build_fn, int epoch_number, bool full) noexcept -{ - static_assert(sizeof(epoch_context_full) < sizeof(hash512), "epoch_context too big"); - static constexpr size_t context_alloc_size = sizeof(hash512); - - const int light_cache_num_items = calculate_light_cache_num_items(epoch_number); - const int full_dataset_num_items = calculate_full_dataset_num_items(epoch_number); - const size_t light_cache_size = get_light_cache_size(light_cache_num_items); - const size_t full_dataset_size = - full ? static_cast(full_dataset_num_items) * sizeof(hash1024) : - progpow::l1_cache_size; - - const size_t alloc_size = context_alloc_size + light_cache_size + full_dataset_size; - - char* const alloc_data = static_cast(std::calloc(1, alloc_size)); - if (!alloc_data) - { - LOG_CUSTOM_WITH_CALLSTACK("CRITICAL: std::calloc(" << alloc_size << ") failed in create_epoch_context()", 0); - return nullptr; // Signal out-of-memory by returning null pointer. - } - LOG_CUSTOM("context for epoch " << epoch_number << " allocated, size: " << alloc_size << " bytes, full dataset size: " << full_dataset_size << " bytes", 0); - - hash512* const light_cache = reinterpret_cast(alloc_data + context_alloc_size); - const hash256 epoch_seed = calculate_epoch_seed(epoch_number); - build_fn(light_cache, light_cache_num_items, epoch_seed); - - uint32_t* const l1_cache = - reinterpret_cast(alloc_data + context_alloc_size + light_cache_size); - - hash1024* full_dataset = full ? reinterpret_cast(l1_cache) : nullptr; - - epoch_context_full* const context = new (alloc_data) epoch_context_full{ - epoch_number, - light_cache_num_items, - light_cache, - l1_cache, - full_dataset_num_items, - full_dataset, - }; - - auto* full_dataset_2048 = reinterpret_cast(l1_cache); - for (uint32_t i = 0; i < progpow::l1_cache_size / sizeof(full_dataset_2048[0]); ++i) - full_dataset_2048[i] = calculate_dataset_item_2048(*context, i); - return context; -} -} // namespace generic - -void build_light_cache(hash512 cache[], int num_items, const hash256& seed) noexcept -{ - return generic::build_light_cache(keccak512, cache, num_items, seed); -} - -struct item_state -{ - const hash512* const cache; - const int64_t num_cache_items; - const uint32_t seed; - - hash512 mix; - - ALWAYS_INLINE item_state(const epoch_context& context, int64_t index) noexcept - : cache{context.light_cache}, - num_cache_items{context.light_cache_num_items}, - seed{static_cast(index)} - { - mix = cache[index % num_cache_items]; - mix.word32s[0] ^= le::uint32(seed); - mix = le::uint32s(keccak512(mix)); - } - - ALWAYS_INLINE void update(uint32_t round) noexcept - { - static constexpr size_t num_words = sizeof(mix) / sizeof(uint32_t); - const uint32_t t = fnv1(seed ^ round, mix.word32s[round % num_words]); - const int64_t parent_index = t % num_cache_items; - mix = fnv1(mix, le::uint32s(cache[parent_index])); - } - - ALWAYS_INLINE hash512 final() noexcept { return keccak512(le::uint32s(mix)); } -}; - -hash512 calculate_dataset_item_512(const epoch_context& context, int64_t index) noexcept -{ - item_state item0{context, index}; - for (uint32_t j = 0; j < full_dataset_item_parents; ++j) - item0.update(j); - return item0.final(); -} - -/// Calculates a full dataset item -/// -/// This consist of two 512-bit items produced by calculate_dataset_item_partial(). -/// Here the computation is done interleaved for better performance. -hash1024 calculate_dataset_item_1024(const epoch_context& context, uint32_t index) noexcept -{ - item_state item0{context, int64_t(index) * 2}; - item_state item1{context, int64_t(index) * 2 + 1}; - - for (uint32_t j = 0; j < full_dataset_item_parents; ++j) - { - item0.update(j); - item1.update(j); - } - - return hash1024{{item0.final(), item1.final()}}; -} - -hash2048 calculate_dataset_item_2048(const epoch_context& context, uint32_t index) noexcept -{ - item_state item0{context, int64_t(index) * 4}; - item_state item1{context, int64_t(index) * 4 + 1}; - item_state item2{context, int64_t(index) * 4 + 2}; - item_state item3{context, int64_t(index) * 4 + 3}; - - for (uint32_t j = 0; j < full_dataset_item_parents; ++j) - { - item0.update(j); - item1.update(j); - item2.update(j); - item3.update(j); - } - - return hash2048{{item0.final(), item1.final(), item2.final(), item3.final()}}; -} - -namespace -{ -using lookup_fn = hash1024 (*)(const epoch_context&, uint32_t); - -inline hash512 hash_seed(const hash256& header_hash, uint64_t nonce) noexcept -{ - nonce = le::uint64(nonce); - uint8_t init_data[sizeof(header_hash) + sizeof(nonce)]; - std::memcpy(&init_data[0], &header_hash, sizeof(header_hash)); - std::memcpy(&init_data[sizeof(header_hash)], &nonce, sizeof(nonce)); - - return keccak512(init_data, sizeof(init_data)); -} - -inline hash256 hash_final(const hash512& seed, const hash256& mix_hash) -{ - uint8_t final_data[sizeof(seed) + sizeof(mix_hash)]; - std::memcpy(&final_data[0], seed.bytes, sizeof(seed)); - std::memcpy(&final_data[sizeof(seed)], mix_hash.bytes, sizeof(mix_hash)); - return keccak256(final_data, sizeof(final_data)); -} - -inline hash256 hash_kernel( - const epoch_context& context, const hash512& seed, lookup_fn lookup) noexcept -{ - static constexpr size_t num_words = sizeof(hash1024) / sizeof(uint32_t); - const uint32_t index_limit = static_cast(context.full_dataset_num_items); - const uint32_t seed_init = le::uint32(seed.word32s[0]); - - hash1024 mix{{le::uint32s(seed), le::uint32s(seed)}}; - - for (uint32_t i = 0; i < num_dataset_accesses; ++i) - { - const uint32_t p = fnv1(i ^ seed_init, mix.word32s[i % num_words]) % index_limit; - const hash1024 newdata = le::uint32s(lookup(context, p)); - - for (size_t j = 0; j < num_words; ++j) - mix.word32s[j] = fnv1(mix.word32s[j], newdata.word32s[j]); - } - - hash256 mix_hash; - for (size_t i = 0; i < num_words; i += 4) - { - const uint32_t h1 = fnv1(mix.word32s[i], mix.word32s[i + 1]); - const uint32_t h2 = fnv1(h1, mix.word32s[i + 2]); - const uint32_t h3 = fnv1(h2, mix.word32s[i + 3]); - mix_hash.word32s[i / 4] = h3; - } - - return le::uint32s(mix_hash); -} -} // namespace - -result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept -{ - const hash512 seed = hash_seed(header_hash, nonce); - const hash256 mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024); - return {hash_final(seed, mix_hash), mix_hash}; -} - -result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept -{ - static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept - { - auto full_dataset = static_cast(context).full_dataset; - hash1024& item = full_dataset[index]; - if (item.word64s[0] == 0) - { - // TODO: Copy elision here makes it thread-safe? - item = calculate_dataset_item_1024(context, index); - } - - return item; - }; - - const hash512 seed = hash_seed(header_hash, nonce); - const hash256 mix_hash = hash_kernel(context, seed, lazy_lookup); - return {hash_final(seed, mix_hash), mix_hash}; -} - -bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce, - const hash256& boundary) noexcept -{ - const hash512 seed = hash_seed(header_hash, nonce); - return is_less_or_equal(hash_final(seed, mix_hash), boundary); -} - -bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash, - uint64_t nonce, const hash256& boundary) noexcept -{ - const hash512 seed = hash_seed(header_hash, nonce); - if (!is_less_or_equal(hash_final(seed, mix_hash), boundary)) - return false; - - const hash256 expected_mix_hash = hash_kernel(context, seed, calculate_dataset_item_1024); - return is_equal(expected_mix_hash, mix_hash); -} - -search_result search_light(const epoch_context& context, const hash256& header_hash, - const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept -{ - const uint64_t end_nonce = start_nonce + iterations; - for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) - { - result r = hash(context, header_hash, nonce); - if (is_less_or_equal(r.final_hash, boundary)) - return {r, nonce}; - } - return {}; -} - -search_result search(const epoch_context_full& context, const hash256& header_hash, - const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept -{ - const uint64_t end_nonce = start_nonce + iterations; - for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) - { - result r = hash(context, header_hash, nonce); - if (is_less_or_equal(r.final_hash, boundary)) - return {r, nonce}; - } - return {}; -} - -custom_log_level_function*& access_custom_log_level_function() -{ - static custom_log_level_function* p_custom_log_level_function = nullptr; - return p_custom_log_level_function; -} - -custom_log_function*& access_custom_log_function() -{ - static custom_log_function* p_custom_log_function = nullptr; - return p_custom_log_function; -} - -int get_custom_log_level() -{ - if (access_custom_log_level_function() != nullptr) - return access_custom_log_level_function()(); - return -1; -} - -void custom_log(const std::string& m, bool add_callstack) -{ - if (access_custom_log_function() != nullptr) - access_custom_log_function()(m, add_callstack); -} - - -} // namespace ethash - -using namespace ethash; - -extern "C" { - -ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) noexcept -{ - ethash_hash256 epoch_seed = {}; - for (int i = 0; i < epoch_number; ++i) - epoch_seed = ethash_keccak256_32(epoch_seed.bytes); - return epoch_seed; -} - -int ethash_calculate_light_cache_num_items(int epoch_number) noexcept -{ - static constexpr int item_size = sizeof(hash512); - static constexpr int num_items_init = light_cache_init_size / item_size; - static constexpr int num_items_growth = light_cache_growth / item_size; - static_assert( - light_cache_init_size % item_size == 0, "light_cache_init_size not multiple of item size"); - static_assert( - light_cache_growth % item_size == 0, "light_cache_growth not multiple of item size"); - - int num_items_upper_bound = num_items_init + epoch_number * num_items_growth; - int num_items = ethash_find_largest_prime(num_items_upper_bound); - return num_items; -} - -int ethash_calculate_full_dataset_num_items(int epoch_number) noexcept -{ - static constexpr int item_size = sizeof(hash1024); - static constexpr int num_items_init = full_dataset_init_size / item_size; - static constexpr int num_items_growth = full_dataset_growth / item_size; - static_assert(full_dataset_init_size % item_size == 0, - "full_dataset_init_size not multiple of item size"); - static_assert( - full_dataset_growth % item_size == 0, "full_dataset_growth not multiple of item size"); - - int num_items_upper_bound = num_items_init + epoch_number * num_items_growth; - int num_items = ethash_find_largest_prime(num_items_upper_bound); - return num_items; -} - -epoch_context* ethash_create_epoch_context(int epoch_number) noexcept -{ - return generic::create_epoch_context(build_light_cache, epoch_number, false); -} - -epoch_context_full* ethash_create_epoch_context_full(int epoch_number) noexcept -{ - return generic::create_epoch_context(build_light_cache, epoch_number, true); -} - -void ethash_destroy_epoch_context_full(epoch_context_full* context) noexcept -{ - ethash_destroy_epoch_context(context); -} - -void ethash_destroy_epoch_context(epoch_context* context) noexcept -{ - LOG_CUSTOM("context for epoch " << context->epoch_number << " is about to be freed", 0); - - context->~epoch_context(); - std::free(context); -} - -} // extern "C" diff --git a/src/contrib/ethereum/libethash/ethash/ethash.h b/src/contrib/ethereum/libethash/ethash/ethash.h deleted file mode 100644 index b12f1aa..0000000 --- a/src/contrib/ethereum/libethash/ethash/ethash.h +++ /dev/null @@ -1,99 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include - -#include - -#ifdef __cplusplus -#define NOEXCEPT noexcept -#else -#define NOEXCEPT -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The Ethash algorithm revision implemented as specified in the Ethash spec - * https://github.com/ethereum/wiki/wiki/Ethash. - */ -#define ETHASH_REVISION "23" - -#define ETHASH_EPOCH_LENGTH 30000 -#define ETHASH_LIGHT_CACHE_ITEM_SIZE 64 -#define ETHASH_FULL_DATASET_ITEM_SIZE 128 -#define ETHASH_NUM_DATASET_ACCESSES 64 - - -struct ethash_epoch_context -{ - const int epoch_number; - const int light_cache_num_items; - const union ethash_hash512* const light_cache; - const uint32_t* const l1_cache; - const int full_dataset_num_items; -}; - - -struct ethash_epoch_context_full; - - -/** - * Calculates the number of items in the light cache for given epoch. - * - * This function will search for a prime number matching the criteria given - * by the Ethash so the execution time is not constant. It takes ~ 0.01 ms. - * - * @param epoch_number The epoch number. - * @return The number items in the light cache. - */ -int ethash_calculate_light_cache_num_items(int epoch_number) NOEXCEPT; - - -/** - * Calculates the number of items in the full dataset for given epoch. - * - * This function will search for a prime number matching the criteria given - * by the Ethash so the execution time is not constant. It takes ~ 0.05 ms. - * - * @param epoch_number The epoch number. - * @return The number items in the full dataset. - */ -int ethash_calculate_full_dataset_num_items(int epoch_number) NOEXCEPT; - -/** - * Calculates the epoch seed hash. - * @param epoch_number The epoch number. - * @return The epoch seed hash. - */ -union ethash_hash256 ethash_calculate_epoch_seed(int epoch_number) NOEXCEPT; - - -struct ethash_epoch_context* ethash_create_epoch_context(int epoch_number) NOEXCEPT; - -/** - * Creates the epoch context with the full dataset initialized. - * - * The memory for the full dataset is only allocated and marked as "not-generated". - * The items of the full dataset are generated on the fly when hit for the first time. - * - * The memory allocated in the context MUST be freed with ethash_destroy_epoch_context_full(). - * - * @param epoch_number The epoch number. - * @return Pointer to the context or null in case of memory allocation failure. - */ -struct ethash_epoch_context_full* ethash_create_epoch_context_full(int epoch_number) NOEXCEPT; - -void ethash_destroy_epoch_context(struct ethash_epoch_context* context) NOEXCEPT; - -void ethash_destroy_epoch_context_full(struct ethash_epoch_context_full* context) NOEXCEPT; - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/ethereum/libethash/ethash/ethash.hpp b/src/contrib/ethereum/libethash/ethash/ethash.hpp deleted file mode 100644 index 0f2962a..0000000 --- a/src/contrib/ethereum/libethash/ethash/ethash.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -/// @file -/// -/// API design decisions: -/// -/// 1. Signed integer type is used whenever the size of the type is not -/// restricted by the Ethash specification. -/// See http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf. -/// See https://stackoverflow.com/questions/10168079/why-is-size-t-unsigned/. -/// See https://github.com/Microsoft/GSL/issues/171. - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -namespace ethash -{ -constexpr auto revision = ETHASH_REVISION; - -static constexpr int epoch_length = ETHASH_EPOCH_LENGTH; -static constexpr int light_cache_item_size = ETHASH_LIGHT_CACHE_ITEM_SIZE; -static constexpr int full_dataset_item_size = ETHASH_FULL_DATASET_ITEM_SIZE; -static constexpr int num_dataset_accesses = ETHASH_NUM_DATASET_ACCESSES; - -using epoch_context = ethash_epoch_context; -using epoch_context_full = ethash_epoch_context_full; - -/// Constructs a 256-bit hash from an array of bytes. -/// -/// @param bytes A pointer to array of at least 32 bytes. -/// @return The constructed hash. -inline hash256 hash256_from_bytes(const uint8_t bytes[32]) noexcept -{ - hash256 h; - std::memcpy(&h, bytes, sizeof(h)); - return h; -} - -struct result -{ - hash256 final_hash; - hash256 mix_hash; -}; - -struct search_result -{ - bool solution_found = false; - uint64_t nonce = 0; - hash256 final_hash = {}; - hash256 mix_hash = {}; - - search_result() noexcept = default; - - search_result(result res, uint64_t nonce) noexcept - : solution_found(true), nonce(nonce), final_hash(res.final_hash), mix_hash(res.mix_hash) - {} -}; - - -/// Alias for ethash_calculate_light_cache_num_items(). -static constexpr auto calculate_light_cache_num_items = ethash_calculate_light_cache_num_items; - -/// Alias for ethash_calculate_full_dataset_num_items(). -static constexpr auto calculate_full_dataset_num_items = ethash_calculate_full_dataset_num_items; - -/// Alias for ethash_calculate_epoch_seed(). -static constexpr auto calculate_epoch_seed = ethash_calculate_epoch_seed; - - -/// Calculates the epoch number out of the block number. -inline constexpr int get_epoch_number(int block_number) noexcept -{ - return block_number / epoch_length; -} - -/** - * Coverts the number of items of a light cache to size in bytes. - * - * @param num_items The number of items in the light cache. - * @return The size of the light cache in bytes. - */ -inline constexpr size_t get_light_cache_size(int num_items) noexcept -{ - return static_cast(num_items) * light_cache_item_size; -} - -/** - * Coverts the number of items of a full dataset to size in bytes. - * - * @param num_items The number of items in the full dataset. - * @return The size of the full dataset in bytes. - */ -inline constexpr uint64_t get_full_dataset_size(int num_items) noexcept -{ - return static_cast(num_items) * full_dataset_item_size; -} - -/// Owned unique pointer to an epoch context. -using epoch_context_ptr = std::unique_ptr; - -using epoch_context_full_ptr = - std::unique_ptr; - -/// Creates Ethash epoch context. -/// -/// This is a wrapper for ethash_create_epoch_number C function that returns -/// the context as a smart pointer which handles the destruction of the context. -inline epoch_context_ptr create_epoch_context(int epoch_number) noexcept -{ - return {ethash_create_epoch_context(epoch_number), ethash_destroy_epoch_context}; -} - -inline epoch_context_full_ptr create_epoch_context_full(int epoch_number) noexcept -{ - return {ethash_create_epoch_context_full(epoch_number), ethash_destroy_epoch_context_full}; -} - - -result hash(const epoch_context& context, const hash256& header_hash, uint64_t nonce) noexcept; - -result hash(const epoch_context_full& context, const hash256& header_hash, uint64_t nonce) noexcept; - -bool verify_final_hash(const hash256& header_hash, const hash256& mix_hash, uint64_t nonce, - const hash256& boundary) noexcept; - -bool verify(const epoch_context& context, const hash256& header_hash, const hash256& mix_hash, - uint64_t nonce, const hash256& boundary) noexcept; - -search_result search_light(const epoch_context& context, const hash256& header_hash, - const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept; - -search_result search(const epoch_context_full& context, const hash256& header_hash, - const hash256& boundary, uint64_t start_nonce, size_t iterations) noexcept; - - -/// Tries to find the epoch number matching the given seed hash. -/// -/// Mining pool protocols (many variants of stratum and "getwork") send out -/// seed hash instead of epoch number to workers. This function tries to recover -/// the epoch number from this seed hash. -/// -/// @param seed Ethash seed hash. -/// @return The epoch number or -1 if not found. -int find_epoch_number(const hash256& seed) noexcept; - - -/// Get global shared epoch context. -const epoch_context& get_global_epoch_context(int epoch_number); - -/// Get global shared epoch context with full dataset initialized. -std::shared_ptr get_global_epoch_context_full(int epoch_number); - -typedef int (custom_log_level_function)(); -typedef void (custom_log_function)(const std::string& m, bool add_callstack); - -custom_log_level_function*& access_custom_log_level_function(); -custom_log_function*& access_custom_log_function(); -int get_custom_log_level(); -void custom_log(const std::string& m, bool add_callstack); - -#define LOG_CUSTOM(msg, level) \ -{ \ - if (level <= ethash::get_custom_log_level()) \ - { \ - std::stringstream ss; \ - ss << msg << std::endl; \ - ethash::custom_log(ss.str(), false); \ - } \ -} - -#define LOG_CUSTOM_WITH_CALLSTACK(msg, level) \ -{ \ - if (level <= ethash::get_custom_log_level()) \ - { \ - std::stringstream ss; \ - ss << msg << std::endl; \ - ethash::custom_log(ss.str(), true); \ - } \ -} - -} // namespace ethash diff --git a/src/contrib/ethereum/libethash/ethash/hash_types.h b/src/contrib/ethereum/libethash/ethash/hash_types.h deleted file mode 100644 index 108e141..0000000 --- a/src/contrib/ethereum/libethash/ethash/hash_types.h +++ /dev/null @@ -1,46 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -union ethash_hash256 -{ - uint64_t word64s[4]; - uint32_t word32s[8]; - uint8_t bytes[32]; -}; - -union ethash_hash512 -{ - uint64_t word64s[8]; - uint32_t word32s[16]; - uint8_t bytes[64]; -}; - -union ethash_hash1024 -{ - union ethash_hash512 hash512s[2]; - uint64_t word64s[16]; - uint32_t word32s[32]; - uint8_t bytes[128]; -}; - -union ethash_hash2048 -{ - union ethash_hash512 hash512s[4]; - uint64_t word64s[32]; - uint32_t word32s[64]; - uint8_t bytes[256]; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/ethereum/libethash/ethash/hash_types.hpp b/src/contrib/ethereum/libethash/ethash/hash_types.hpp deleted file mode 100644 index cb9c3f1..0000000 --- a/src/contrib/ethereum/libethash/ethash/hash_types.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -#pragma once - -#include - -namespace ethash -{ -using hash256 = ethash_hash256; -using hash512 = ethash_hash512; -using hash1024 = ethash_hash1024; -using hash2048 = ethash_hash2048; -} // namespace ethash diff --git a/src/contrib/ethereum/libethash/ethash/keccak.h b/src/contrib/ethereum/libethash/ethash/keccak.h deleted file mode 100644 index e1414b8..0000000 --- a/src/contrib/ethereum/libethash/ethash/keccak.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include - -#include - -#ifdef __cplusplus -#define NOEXCEPT noexcept -#else -#define NOEXCEPT -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The Keccak-f[1600] function. - * - * The implementation of the Keccak-f function with 1600-bit width of the permutation (b). - * The size of the state is also 1600 bit what gives 25 64-bit words. - * - * @param state The state of 25 64-bit words on which the permutation is to be performed. - */ -void ethash_keccakf1600(uint64_t state[25]) NOEXCEPT; - -/** - * The Keccak-f[800] function. - * - * The implementation of the Keccak-f function with 800-bit width of the permutation (b). - * The size of the state is also 800 bit what gives 25 32-bit words. - * - * @param state The state of 25 32-bit words on which the permutation is to be performed. - */ -void ethash_keccakf800(uint32_t state[25]) NOEXCEPT; - -union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) NOEXCEPT; -union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) NOEXCEPT; -union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) NOEXCEPT; -union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) NOEXCEPT; - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/ethereum/libethash/ethash/keccak.hpp b/src/contrib/ethereum/libethash/ethash/keccak.hpp deleted file mode 100644 index 9dbc6aa..0000000 --- a/src/contrib/ethereum/libethash/ethash/keccak.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -#pragma once - -#include -#include - -namespace ethash -{ -inline hash256 keccak256(const uint8_t* data, size_t size) noexcept -{ - return ethash_keccak256(data, size); -} - -inline hash256 keccak256(const hash256& input) noexcept -{ - return ethash_keccak256_32(input.bytes); -} - -inline hash512 keccak512(const uint8_t* data, size_t size) noexcept -{ - return ethash_keccak512(data, size); -} - -inline hash512 keccak512(const hash512& input) noexcept -{ - return ethash_keccak512_64(input.bytes); -} - -static constexpr auto keccak256_32 = ethash_keccak256_32; -static constexpr auto keccak512_64 = ethash_keccak512_64; - -} // namespace ethash diff --git a/src/contrib/ethereum/libethash/ethash/progpow.hpp b/src/contrib/ethereum/libethash/ethash/progpow.hpp deleted file mode 100644 index 81e6dba..0000000 --- a/src/contrib/ethereum/libethash/ethash/progpow.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -/// @file -/// -/// ProgPoW API -/// -/// This file provides the public API for ProgPoW as the Ethash API extension. - -#include - -namespace progpow -{ -using namespace ethash; // Include ethash namespace. - - -/// The ProgPoW algorithm revision implemented as specified in the spec -/// https://github.com/ifdefelse/ProgPOW#change-history. -constexpr auto revision = "0.9.2"; - -constexpr int period_length = 50; -constexpr uint32_t num_regs = 32; -constexpr size_t num_lanes = 16; -constexpr int num_cache_accesses = 12; -constexpr int num_math_operations = 20; -constexpr size_t l1_cache_size = 16 * 1024; -constexpr size_t l1_cache_num_items = l1_cache_size / sizeof(uint32_t); - -result hash(const epoch_context& context, int block_number, const hash256& header_hash, - uint64_t nonce) noexcept; - -result hash(const epoch_context_full& context, int block_number, const hash256& header_hash, - uint64_t nonce) noexcept; - -bool verify(const epoch_context& context, int block_number, const hash256& header_hash, - const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept; - -search_result search_light(const epoch_context& context, int block_number, - const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, - size_t iterations) noexcept; - -search_result search(const epoch_context_full& context, int block_number, - const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, - size_t iterations) noexcept; - -} // namespace progpow diff --git a/src/contrib/ethereum/libethash/ethash/version.h b/src/contrib/ethereum/libethash/ethash/version.h deleted file mode 100644 index f0372b0..0000000 --- a/src/contrib/ethereum/libethash/ethash/version.h +++ /dev/null @@ -1,18 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2019 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. - */ - -#pragma once - -/** The ethash library version. */ -#define ETHASH_VERSION "0.4.3" - -#ifdef __cplusplus -namespace ethash -{ -/// The ethash library version. -constexpr auto version = ETHASH_VERSION; - -} // namespace ethash -#endif diff --git a/src/contrib/ethereum/libethash/keccak.c b/src/contrib/ethereum/libethash/keccak.c deleted file mode 100644 index 4c0b4ca..0000000 --- a/src/contrib/ethereum/libethash/keccak.c +++ /dev/null @@ -1,123 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#include - -#include "support/attributes.h" -#include - -#if _WIN32 -/* On Windows assume little endian. */ -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN -#elif __APPLE__ -#include -#else -#include -#endif - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define to_le64(X) X -#else -#define to_le64(X) __builtin_bswap64(X) -#endif - - -/** Loads 64-bit integer from given memory location as little-endian number. */ -static INLINE ALWAYS_INLINE uint64_t load_le(const uint8_t* data) -{ - /* memcpy is the best way of expressing the intention. Every compiler will - optimize is to single load instruction if the target architecture - supports unaligned memory access (GCC and clang even in O0). - This is great trick because we are violating C/C++ memory alignment - restrictions with no performance penalty. */ - uint64_t word; - memcpy(&word, data, sizeof(word)); - return to_le64(word); -} - -static INLINE ALWAYS_INLINE void keccak( - uint64_t* out, size_t bits, const uint8_t* data, size_t size) -{ - static const size_t word_size = sizeof(uint64_t); - const size_t hash_size = bits / 8; - const size_t block_size = (1600 - bits * 2) / 8; - - size_t i; - uint64_t* state_iter; - uint64_t last_word = 0; - uint8_t* last_word_iter = (uint8_t*)&last_word; - - uint64_t state[25] = {0}; - - while (size >= block_size) - { - for (i = 0; i < (block_size / word_size); ++i) - { - state[i] ^= load_le(data); - data += word_size; - } - - ethash_keccakf1600(state); - - size -= block_size; - } - - state_iter = state; - - while (size >= word_size) - { - *state_iter ^= load_le(data); - ++state_iter; - data += word_size; - size -= word_size; - } - - while (size > 0) - { - *last_word_iter = *data; - ++last_word_iter; - ++data; - --size; - } - *last_word_iter = 0x01; - *state_iter ^= to_le64(last_word); - - state[(block_size / word_size) - 1] ^= 0x8000000000000000; - - ethash_keccakf1600(state); - - for (i = 0; i < (hash_size / word_size); ++i) - out[i] = to_le64(state[i]); -} - -union ethash_hash256 ethash_keccak256(const uint8_t* data, size_t size) -{ - union ethash_hash256 hash; - keccak(hash.word64s, 256, data, size); - return hash; -} - -union ethash_hash256 ethash_keccak256_32(const uint8_t data[32]) -{ - union ethash_hash256 hash; - keccak(hash.word64s, 256, data, 32); - return hash; -} - -union ethash_hash512 ethash_keccak512(const uint8_t* data, size_t size) -{ - union ethash_hash512 hash; - keccak(hash.word64s, 512, data, size); - return hash; -} - -union ethash_hash512 ethash_keccak512_64(const uint8_t data[64]) -{ - union ethash_hash512 hash; - keccak(hash.word64s, 512, data, 64); - return hash; -} diff --git a/src/contrib/ethereum/libethash/keccakf1600.c b/src/contrib/ethereum/libethash/keccakf1600.c deleted file mode 100644 index 271fe76..0000000 --- a/src/contrib/ethereum/libethash/keccakf1600.c +++ /dev/null @@ -1,255 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#include - -static uint64_t rol(uint64_t x, unsigned s) -{ - return (x << s) | (x >> (64 - s)); -} - -static const uint64_t round_constants[24] = { - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808a, - 0x8000000080008000, - 0x000000000000808b, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008a, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000a, - 0x000000008000808b, - 0x800000000000008b, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800a, - 0x800000008000000a, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -}; - -void ethash_keccakf1600(uint64_t state[25]) -{ - /* The implementation based on the "simple" implementation by Ronny Van Keer. */ - - int round; - - uint64_t Aba, Abe, Abi, Abo, Abu; - uint64_t Aga, Age, Agi, Ago, Agu; - uint64_t Aka, Ake, Aki, Ako, Aku; - uint64_t Ama, Ame, Ami, Amo, Amu; - uint64_t Asa, Ase, Asi, Aso, Asu; - - uint64_t Eba, Ebe, Ebi, Ebo, Ebu; - uint64_t Ega, Ege, Egi, Ego, Egu; - uint64_t Eka, Eke, Eki, Eko, Eku; - uint64_t Ema, Eme, Emi, Emo, Emu; - uint64_t Esa, Ese, Esi, Eso, Esu; - - uint64_t Ba, Be, Bi, Bo, Bu; - - uint64_t Da, De, Di, Do, Du; - - Aba = state[0]; - Abe = state[1]; - Abi = state[2]; - Abo = state[3]; - Abu = state[4]; - Aga = state[5]; - Age = state[6]; - Agi = state[7]; - Ago = state[8]; - Agu = state[9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for (round = 0; round < 24; round += 2) - { - /* Round (round + 0): Axx -> Exx */ - - Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; - Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; - Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; - Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; - Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; - - Da = Bu ^ rol(Be, 1); - De = Ba ^ rol(Bi, 1); - Di = Be ^ rol(Bo, 1); - Do = Bi ^ rol(Bu, 1); - Du = Bo ^ rol(Ba, 1); - - Ba = Aba ^ Da; - Be = rol(Age ^ De, 44); - Bi = rol(Aki ^ Di, 43); - Bo = rol(Amo ^ Do, 21); - Bu = rol(Asu ^ Du, 14); - Eba = Ba ^ (~Be & Bi) ^ round_constants[round]; - Ebe = Be ^ (~Bi & Bo); - Ebi = Bi ^ (~Bo & Bu); - Ebo = Bo ^ (~Bu & Ba); - Ebu = Bu ^ (~Ba & Be); - - Ba = rol(Abo ^ Do, 28); - Be = rol(Agu ^ Du, 20); - Bi = rol(Aka ^ Da, 3); - Bo = rol(Ame ^ De, 45); - Bu = rol(Asi ^ Di, 61); - Ega = Ba ^ (~Be & Bi); - Ege = Be ^ (~Bi & Bo); - Egi = Bi ^ (~Bo & Bu); - Ego = Bo ^ (~Bu & Ba); - Egu = Bu ^ (~Ba & Be); - - Ba = rol(Abe ^ De, 1); - Be = rol(Agi ^ Di, 6); - Bi = rol(Ako ^ Do, 25); - Bo = rol(Amu ^ Du, 8); - Bu = rol(Asa ^ Da, 18); - Eka = Ba ^ (~Be & Bi); - Eke = Be ^ (~Bi & Bo); - Eki = Bi ^ (~Bo & Bu); - Eko = Bo ^ (~Bu & Ba); - Eku = Bu ^ (~Ba & Be); - - Ba = rol(Abu ^ Du, 27); - Be = rol(Aga ^ Da, 36); - Bi = rol(Ake ^ De, 10); - Bo = rol(Ami ^ Di, 15); - Bu = rol(Aso ^ Do, 56); - Ema = Ba ^ (~Be & Bi); - Eme = Be ^ (~Bi & Bo); - Emi = Bi ^ (~Bo & Bu); - Emo = Bo ^ (~Bu & Ba); - Emu = Bu ^ (~Ba & Be); - - Ba = rol(Abi ^ Di, 62); - Be = rol(Ago ^ Do, 55); - Bi = rol(Aku ^ Du, 39); - Bo = rol(Ama ^ Da, 41); - Bu = rol(Ase ^ De, 2); - Esa = Ba ^ (~Be & Bi); - Ese = Be ^ (~Bi & Bo); - Esi = Bi ^ (~Bo & Bu); - Eso = Bo ^ (~Bu & Ba); - Esu = Bu ^ (~Ba & Be); - - - /* Round (round + 1): Exx -> Axx */ - - Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; - Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; - Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; - Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; - Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; - - Da = Bu ^ rol(Be, 1); - De = Ba ^ rol(Bi, 1); - Di = Be ^ rol(Bo, 1); - Do = Bi ^ rol(Bu, 1); - Du = Bo ^ rol(Ba, 1); - - Ba = Eba ^ Da; - Be = rol(Ege ^ De, 44); - Bi = rol(Eki ^ Di, 43); - Bo = rol(Emo ^ Do, 21); - Bu = rol(Esu ^ Du, 14); - Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1]; - Abe = Be ^ (~Bi & Bo); - Abi = Bi ^ (~Bo & Bu); - Abo = Bo ^ (~Bu & Ba); - Abu = Bu ^ (~Ba & Be); - - Ba = rol(Ebo ^ Do, 28); - Be = rol(Egu ^ Du, 20); - Bi = rol(Eka ^ Da, 3); - Bo = rol(Eme ^ De, 45); - Bu = rol(Esi ^ Di, 61); - Aga = Ba ^ (~Be & Bi); - Age = Be ^ (~Bi & Bo); - Agi = Bi ^ (~Bo & Bu); - Ago = Bo ^ (~Bu & Ba); - Agu = Bu ^ (~Ba & Be); - - Ba = rol(Ebe ^ De, 1); - Be = rol(Egi ^ Di, 6); - Bi = rol(Eko ^ Do, 25); - Bo = rol(Emu ^ Du, 8); - Bu = rol(Esa ^ Da, 18); - Aka = Ba ^ (~Be & Bi); - Ake = Be ^ (~Bi & Bo); - Aki = Bi ^ (~Bo & Bu); - Ako = Bo ^ (~Bu & Ba); - Aku = Bu ^ (~Ba & Be); - - Ba = rol(Ebu ^ Du, 27); - Be = rol(Ega ^ Da, 36); - Bi = rol(Eke ^ De, 10); - Bo = rol(Emi ^ Di, 15); - Bu = rol(Eso ^ Do, 56); - Ama = Ba ^ (~Be & Bi); - Ame = Be ^ (~Bi & Bo); - Ami = Bi ^ (~Bo & Bu); - Amo = Bo ^ (~Bu & Ba); - Amu = Bu ^ (~Ba & Be); - - Ba = rol(Ebi ^ Di, 62); - Be = rol(Ego ^ Do, 55); - Bi = rol(Eku ^ Du, 39); - Bo = rol(Ema ^ Da, 41); - Bu = rol(Ese ^ De, 2); - Asa = Ba ^ (~Be & Bi); - Ase = Be ^ (~Bi & Bo); - Asi = Bi ^ (~Bo & Bu); - Aso = Bo ^ (~Bu & Ba); - Asu = Bu ^ (~Ba & Be); - } - - state[0] = Aba; - state[1] = Abe; - state[2] = Abi; - state[3] = Abo; - state[4] = Abu; - state[5] = Aga; - state[6] = Age; - state[7] = Agi; - state[8] = Ago; - state[9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} diff --git a/src/contrib/ethereum/libethash/keccakf800.c b/src/contrib/ethereum/libethash/keccakf800.c deleted file mode 100644 index aa7ccee..0000000 --- a/src/contrib/ethereum/libethash/keccakf800.c +++ /dev/null @@ -1,253 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#include - -static uint32_t rol(uint32_t x, unsigned s) -{ - return (x << s) | (x >> (32 - s)); -} - -static const uint32_t round_constants[22] = { - 0x00000001, - 0x00008082, - 0x0000808A, - 0x80008000, - 0x0000808B, - 0x80000001, - 0x80008081, - 0x00008009, - 0x0000008A, - 0x00000088, - 0x80008009, - 0x8000000A, - 0x8000808B, - 0x0000008B, - 0x00008089, - 0x00008003, - 0x00008002, - 0x00000080, - 0x0000800A, - 0x8000000A, - 0x80008081, - 0x00008080, -}; - -void ethash_keccakf800(uint32_t state[25]) -{ - /* The implementation directly translated from ethash_keccakf1600. */ - - int round; - - uint32_t Aba, Abe, Abi, Abo, Abu; - uint32_t Aga, Age, Agi, Ago, Agu; - uint32_t Aka, Ake, Aki, Ako, Aku; - uint32_t Ama, Ame, Ami, Amo, Amu; - uint32_t Asa, Ase, Asi, Aso, Asu; - - uint32_t Eba, Ebe, Ebi, Ebo, Ebu; - uint32_t Ega, Ege, Egi, Ego, Egu; - uint32_t Eka, Eke, Eki, Eko, Eku; - uint32_t Ema, Eme, Emi, Emo, Emu; - uint32_t Esa, Ese, Esi, Eso, Esu; - - uint32_t Ba, Be, Bi, Bo, Bu; - - uint32_t Da, De, Di, Do, Du; - - Aba = state[0]; - Abe = state[1]; - Abi = state[2]; - Abo = state[3]; - Abu = state[4]; - Aga = state[5]; - Age = state[6]; - Agi = state[7]; - Ago = state[8]; - Agu = state[9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for (round = 0; round < 22; round += 2) - { - /* Round (round + 0): Axx -> Exx */ - - Ba = Aba ^ Aga ^ Aka ^ Ama ^ Asa; - Be = Abe ^ Age ^ Ake ^ Ame ^ Ase; - Bi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; - Bo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; - Bu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; - - Da = Bu ^ rol(Be, 1); - De = Ba ^ rol(Bi, 1); - Di = Be ^ rol(Bo, 1); - Do = Bi ^ rol(Bu, 1); - Du = Bo ^ rol(Ba, 1); - - Ba = Aba ^ Da; - Be = rol(Age ^ De, 12); - Bi = rol(Aki ^ Di, 11); - Bo = rol(Amo ^ Do, 21); - Bu = rol(Asu ^ Du, 14); - Eba = Ba ^ (~Be & Bi) ^ round_constants[round]; - Ebe = Be ^ (~Bi & Bo); - Ebi = Bi ^ (~Bo & Bu); - Ebo = Bo ^ (~Bu & Ba); - Ebu = Bu ^ (~Ba & Be); - - Ba = rol(Abo ^ Do, 28); - Be = rol(Agu ^ Du, 20); - Bi = rol(Aka ^ Da, 3); - Bo = rol(Ame ^ De, 13); - Bu = rol(Asi ^ Di, 29); - Ega = Ba ^ (~Be & Bi); - Ege = Be ^ (~Bi & Bo); - Egi = Bi ^ (~Bo & Bu); - Ego = Bo ^ (~Bu & Ba); - Egu = Bu ^ (~Ba & Be); - - Ba = rol(Abe ^ De, 1); - Be = rol(Agi ^ Di, 6); - Bi = rol(Ako ^ Do, 25); - Bo = rol(Amu ^ Du, 8); - Bu = rol(Asa ^ Da, 18); - Eka = Ba ^ (~Be & Bi); - Eke = Be ^ (~Bi & Bo); - Eki = Bi ^ (~Bo & Bu); - Eko = Bo ^ (~Bu & Ba); - Eku = Bu ^ (~Ba & Be); - - Ba = rol(Abu ^ Du, 27); - Be = rol(Aga ^ Da, 4); - Bi = rol(Ake ^ De, 10); - Bo = rol(Ami ^ Di, 15); - Bu = rol(Aso ^ Do, 24); - Ema = Ba ^ (~Be & Bi); - Eme = Be ^ (~Bi & Bo); - Emi = Bi ^ (~Bo & Bu); - Emo = Bo ^ (~Bu & Ba); - Emu = Bu ^ (~Ba & Be); - - Ba = rol(Abi ^ Di, 30); - Be = rol(Ago ^ Do, 23); - Bi = rol(Aku ^ Du, 7); - Bo = rol(Ama ^ Da, 9); - Bu = rol(Ase ^ De, 2); - Esa = Ba ^ (~Be & Bi); - Ese = Be ^ (~Bi & Bo); - Esi = Bi ^ (~Bo & Bu); - Eso = Bo ^ (~Bu & Ba); - Esu = Bu ^ (~Ba & Be); - - - /* Round (round + 1): Exx -> Axx */ - - Ba = Eba ^ Ega ^ Eka ^ Ema ^ Esa; - Be = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; - Bi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; - Bo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; - Bu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; - - Da = Bu ^ rol(Be, 1); - De = Ba ^ rol(Bi, 1); - Di = Be ^ rol(Bo, 1); - Do = Bi ^ rol(Bu, 1); - Du = Bo ^ rol(Ba, 1); - - Ba = Eba ^ Da; - Be = rol(Ege ^ De, 12); - Bi = rol(Eki ^ Di, 11); - Bo = rol(Emo ^ Do, 21); - Bu = rol(Esu ^ Du, 14); - Aba = Ba ^ (~Be & Bi) ^ round_constants[round + 1]; - Abe = Be ^ (~Bi & Bo); - Abi = Bi ^ (~Bo & Bu); - Abo = Bo ^ (~Bu & Ba); - Abu = Bu ^ (~Ba & Be); - - Ba = rol(Ebo ^ Do, 28); - Be = rol(Egu ^ Du, 20); - Bi = rol(Eka ^ Da, 3); - Bo = rol(Eme ^ De, 13); - Bu = rol(Esi ^ Di, 29); - Aga = Ba ^ (~Be & Bi); - Age = Be ^ (~Bi & Bo); - Agi = Bi ^ (~Bo & Bu); - Ago = Bo ^ (~Bu & Ba); - Agu = Bu ^ (~Ba & Be); - - Ba = rol(Ebe ^ De, 1); - Be = rol(Egi ^ Di, 6); - Bi = rol(Eko ^ Do, 25); - Bo = rol(Emu ^ Du, 8); - Bu = rol(Esa ^ Da, 18); - Aka = Ba ^ (~Be & Bi); - Ake = Be ^ (~Bi & Bo); - Aki = Bi ^ (~Bo & Bu); - Ako = Bo ^ (~Bu & Ba); - Aku = Bu ^ (~Ba & Be); - - Ba = rol(Ebu ^ Du, 27); - Be = rol(Ega ^ Da, 4); - Bi = rol(Eke ^ De, 10); - Bo = rol(Emi ^ Di, 15); - Bu = rol(Eso ^ Do, 24); - Ama = Ba ^ (~Be & Bi); - Ame = Be ^ (~Bi & Bo); - Ami = Bi ^ (~Bo & Bu); - Amo = Bo ^ (~Bu & Ba); - Amu = Bu ^ (~Ba & Be); - - Ba = rol(Ebi ^ Di, 30); - Be = rol(Ego ^ Do, 23); - Bi = rol(Eku ^ Du, 7); - Bo = rol(Ema ^ Da, 9); - Bu = rol(Ese ^ De, 2); - Asa = Ba ^ (~Be & Bi); - Ase = Be ^ (~Bi & Bo); - Asi = Bi ^ (~Bo & Bu); - Aso = Bo ^ (~Bu & Ba); - Asu = Bu ^ (~Ba & Be); - } - - state[0] = Aba; - state[1] = Abe; - state[2] = Abi; - state[3] = Abo; - state[4] = Abu; - state[5] = Aga; - state[6] = Age; - state[7] = Agi; - state[8] = Ago; - state[9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} diff --git a/src/contrib/ethereum/libethash/kiss99.hpp b/src/contrib/ethereum/libethash/kiss99.hpp deleted file mode 100644 index 8550b82..0000000 --- a/src/contrib/ethereum/libethash/kiss99.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include "support/attributes.h" -#include - -/** - * KISS PRNG by the spec from 1999. - * - * The implementation of KISS pseudo-random number generator - * by the specification published on 21 Jan 1999 in - * http://www.cse.yorku.ca/~oz/marsaglia-rng.html. - * The KISS is not versioned so here we are using `kiss99` prefix to indicate - * the version from 1999. - * - * The specification uses `unsigned long` type with the intention for 32-bit - * values. Because in GCC/clang for 64-bit architectures `unsigned long` is - * 64-bit size type, here the explicit `uint32_t` type is used. - * - * @defgroup kiss99 KISS99 - * @{ - */ - -/** - * The KISS generator. - */ -class kiss99 -{ - uint32_t z = 362436069; - uint32_t w = 521288629; - uint32_t jsr = 123456789; - uint32_t jcong = 380116160; - -public: - /** Creates KISS generator state with default values provided by the specification. */ - kiss99() noexcept = default; - - /** Creates KISS generator state with provided init values.*/ - kiss99(uint32_t z, uint32_t w, uint32_t jsr, uint32_t jcong) noexcept - : z{z}, w{w}, jsr{jsr}, jcong{jcong} - {} - - /** Generates next number from the KISS generator. */ - NO_SANITIZE("unsigned-integer-overflow") - uint32_t operator()() noexcept - { - z = 36969 * (z & 0xffff) + (z >> 16); - w = 18000 * (w & 0xffff) + (w >> 16); - - jcong = 69069 * jcong + 1234567; - - jsr ^= (jsr << 17); - jsr ^= (jsr >> 13); - jsr ^= (jsr << 5); - - return (((z << 16) + w) ^ jcong) + jsr; - } -}; - -/** @} */ diff --git a/src/contrib/ethereum/libethash/managed.cpp b/src/contrib/ethereum/libethash/managed.cpp deleted file mode 100644 index 82ff69b..0000000 --- a/src/contrib/ethereum/libethash/managed.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -#include "ethash-internal.hpp" - -#include -#include - -#if !defined(__has_cpp_attribute) -#define __has_cpp_attribute(x) 0 -#endif - -#if __has_cpp_attribute(gnu::noinline) -#define ATTRIBUTE_NOINLINE [[gnu::noinline]] -#elif _MSC_VER -#define ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define ATTRIBUTE_NOINLINE -#endif - -namespace ethash -{ -namespace -{ -std::mutex shared_context_mutex; -std::shared_ptr shared_context; -thread_local std::shared_ptr thread_local_context; - -std::mutex shared_context_full_mutex; -std::shared_ptr shared_context_full; -thread_local std::shared_ptr thread_local_context_full; - -/// Update thread local epoch context. -/// -/// This function is on the slow path. It's separated to allow inlining the fast -/// path. -/// -/// @todo: Redesign to guarantee deallocation before new allocation. -ATTRIBUTE_NOINLINE -void update_local_context(int epoch_number) -{ - // Release the shared pointer of the obsoleted context. - thread_local_context.reset(); - - // Local context invalid, check the shared context. - std::lock_guard lock{shared_context_mutex}; - - if (!shared_context || shared_context->epoch_number != epoch_number) - { - // Release the shared pointer of the obsoleted context. - shared_context.reset(); - - // Build new context. - shared_context = create_epoch_context(epoch_number); - } - - thread_local_context = shared_context; -} - -ATTRIBUTE_NOINLINE -void update_local_context_full(int epoch_number) -{ - // Release the shared pointer of the obsoleted context. - thread_local_context_full.reset(); - - // Local context invalid, check the shared context. - std::lock_guard lock{shared_context_full_mutex}; - - if (!shared_context_full || shared_context_full->epoch_number != epoch_number) - { - // Release the shared pointer of the obsoleted context. - shared_context_full.reset(); - - // Build new context. - shared_context_full = create_epoch_context_full(epoch_number); - } - - thread_local_context_full = shared_context_full; -} -} // namespace - -const epoch_context& get_global_epoch_context(int epoch_number) -{ - // Check if local context matches epoch number. - if (!thread_local_context || thread_local_context->epoch_number != epoch_number) - update_local_context(epoch_number); - - return *thread_local_context; -} - -std::shared_ptr get_global_epoch_context_full(int epoch_number) -{ - // Check if local context matches epoch number. - if (!thread_local_context_full || thread_local_context_full->epoch_number != epoch_number) - update_local_context_full(epoch_number); - - return thread_local_context_full; -} -} // namespace ethash diff --git a/src/contrib/ethereum/libethash/primes.c b/src/contrib/ethereum/libethash/primes.c deleted file mode 100644 index 2d58874..0000000 --- a/src/contrib/ethereum/libethash/primes.c +++ /dev/null @@ -1,43 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#include "primes.h" - -/** Checks if the number is prime. Requires the number to be > 2 and odd. */ -static int is_odd_prime(int number) -{ - int d; - - /* Check factors up to sqrt(number). - To avoid computing sqrt, compare d*d <= number with 64-bit precision. */ - for (d = 3; (int64_t)d * (int64_t)d <= (int64_t)number; d += 2) - { - if (number % d == 0) - return 0; - } - - return 1; -} - -int ethash_find_largest_prime(int upper_bound) -{ - int n = upper_bound; - - if (n < 2) - return 0; - - if (n == 2) - return 2; - - /* If even number, skip it. */ - if (n % 2 == 0) - --n; - - /* Test descending odd numbers. */ - while (!is_odd_prime(n)) - n -= 2; - - return n; -} diff --git a/src/contrib/ethereum/libethash/primes.h b/src/contrib/ethereum/libethash/primes.h deleted file mode 100644 index cf923b0..0000000 --- a/src/contrib/ethereum/libethash/primes.h +++ /dev/null @@ -1,25 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Finds the largest prime number not greater than the provided upper bound. - * - * @param upper_bound The upper bound. SHOULD be greater than 1. - * @return The largest prime number `p` such `p <= upper_bound`. - * In case `upper_bound <= 1`, returns 0. - */ -int ethash_find_largest_prime(int upper_bound) NOEXCEPT; - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/ethereum/libethash/progpow.cpp b/src/contrib/ethereum/libethash/progpow.cpp deleted file mode 100644 index d74c874..0000000 --- a/src/contrib/ethereum/libethash/progpow.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. -// Copyright 2018 Pawel Bylica. -// Licensed under the Apache License, Version 2.0. See the LICENSE file. - -#include - -#include "bit_manipulation.h" -#include "endianness.hpp" -#include "ethash-internal.hpp" -#include "kiss99.hpp" -#include - -#include - -namespace progpow -{ -namespace -{ -/// A variant of Keccak hash function for ProgPoW. -/// -/// This Keccak hash function uses 800-bit permutation (Keccak-f[800]) with 576 bitrate. -/// It take exactly 576 bits of input (split across 3 arguments) and adds no padding. -/// -/// @param header_hash The 256-bit header hash. -/// @param nonce The 64-bit nonce. -/// @param mix_hash Additional 256-bits of data. -/// @return The 256-bit output of the hash function. -hash256 keccak_progpow_256( - const hash256& header_hash, uint64_t nonce, const hash256& mix_hash) noexcept -{ - static constexpr size_t num_words = - sizeof(header_hash.word32s) / sizeof(header_hash.word32s[0]); - - uint32_t state[25] = {}; - - size_t i; - for (i = 0; i < num_words; ++i) - state[i] = le::uint32(header_hash.word32s[i]); - - state[i++] = static_cast(nonce); - state[i++] = static_cast(nonce >> 32); - - for (uint32_t mix_word : mix_hash.word32s) - state[i++] = le::uint32(mix_word); - - ethash_keccakf800(state); - - hash256 output; - for (i = 0; i < num_words; ++i) - output.word32s[i] = le::uint32(state[i]); - return output; -} - -/// The same as keccak_progpow_256() but uses null mix -/// and returns top 64 bits of the output being a big-endian prefix of the 256-bit hash. -inline uint64_t keccak_progpow_64(const hash256& header_hash, uint64_t nonce) noexcept -{ - const hash256 h = keccak_progpow_256(header_hash, nonce, {}); - return be::uint64(h.word64s[0]); -} - - -/// ProgPoW mix RNG state. -/// -/// Encapsulates the state of the random number generator used in computing ProgPoW mix. -/// This includes the state of the KISS99 RNG and the precomputed random permutation of the -/// sequence of mix item indexes. -class mix_rng_state -{ -public: - inline explicit mix_rng_state(uint64_t seed) noexcept; - - uint32_t next_dst() noexcept { return dst_seq[(dst_counter++) % num_regs]; } - uint32_t next_src() noexcept { return src_seq[(src_counter++) % num_regs]; } - - kiss99 rng; - -private: - size_t dst_counter = 0; - std::array dst_seq; - size_t src_counter = 0; - std::array src_seq; -}; - -mix_rng_state::mix_rng_state(uint64_t seed) noexcept -{ - const auto seed_lo = static_cast(seed); - const auto seed_hi = static_cast(seed >> 32); - - const auto z = fnv1a(fnv_offset_basis, seed_lo); - const auto w = fnv1a(z, seed_hi); - const auto jsr = fnv1a(w, seed_lo); - const auto jcong = fnv1a(jsr, seed_hi); - - rng = kiss99{z, w, jsr, jcong}; - - // Create random permutations of mix destinations / sources. - // Uses Fisher-Yates shuffle. - for (uint32_t i = 0; i < num_regs; ++i) - { - dst_seq[i] = i; - src_seq[i] = i; - } - - for (uint32_t i = num_regs; i > 1; --i) - { - std::swap(dst_seq[i - 1], dst_seq[rng() % i]); - std::swap(src_seq[i - 1], src_seq[rng() % i]); - } -} - - -NO_SANITIZE("unsigned-integer-overflow") -inline uint32_t random_math(uint32_t a, uint32_t b, uint32_t selector) noexcept -{ - switch (selector % 11) - { - default: - case 2: - return a + b; - case 3: - return a * b; - case 4: - return mul_hi32(a, b); - case 5: - return std::min(a, b); - case 6: - return rotl32(a, b); - case 7: - return rotr32(a, b); - case 8: - return a & b; - case 9: - return a | b; - case 10: - return a ^ b; - case 0: - return clz32(a) + clz32(b); - case 1: - return popcount32(a) + popcount32(b); - } -} - -/// Merge data from `b` and `a`. -/// Assuming `a` has high entropy, only do ops that retain entropy even if `b` -/// has low entropy (i.e. do not do `a & b`). -NO_SANITIZE("unsigned-integer-overflow") -inline void random_merge(uint32_t& a, uint32_t b, uint32_t selector) noexcept -{ - const auto x = (selector >> 16) % 31 + 1; // Additional non-zero selector from higher bits. - switch (selector % 4) - { - case 0: - a = (a * 33) + b; - break; - case 1: - a = (a ^ b) * 33; - break; - case 2: - a = rotl32(a, x) ^ b; - break; - case 3: - a = rotr32(a, x) ^ b; - break; - } -} - -using lookup_fn = hash2048 (*)(const epoch_context&, uint32_t); - -using mix_array = std::array, num_lanes>; - -void round( - const epoch_context& context, uint32_t r, mix_array& mix, mix_rng_state state, lookup_fn lookup) -{ - const uint32_t num_items = static_cast(context.full_dataset_num_items / 2); - const uint32_t item_index = mix[r % num_lanes][0] % num_items; - const hash2048 item = lookup(context, item_index); - - constexpr size_t num_words_per_lane = sizeof(item) / (sizeof(uint32_t) * num_lanes); - constexpr int max_operations = - num_cache_accesses > num_math_operations ? num_cache_accesses : num_math_operations; - - // Process lanes. - for (int i = 0; i < max_operations; ++i) - { - if (i < num_cache_accesses) // Random access to cached memory. - { - const auto src = state.next_src(); - const auto dst = state.next_dst(); - const auto sel = state.rng(); - - for (size_t l = 0; l < num_lanes; ++l) - { - const size_t offset = mix[l][src] % l1_cache_num_items; - random_merge(mix[l][dst], le::uint32(context.l1_cache[offset]), sel); - } - } - if (i < num_math_operations) // Random math. - { - // Generate 2 unique source indexes. - const auto src_rnd = state.rng() % (num_regs * (num_regs - 1)); - const auto src1 = src_rnd % num_regs; // O <= src1 < num_regs - auto src2 = src_rnd / num_regs; // 0 <= src2 < num_regs - 1 - if (src2 >= src1) - ++src2; - - const auto sel1 = state.rng(); - const auto dst = state.next_dst(); - const auto sel2 = state.rng(); - - for (size_t l = 0; l < num_lanes; ++l) - { - const uint32_t data = random_math(mix[l][src1], mix[l][src2], sel1); - random_merge(mix[l][dst], data, sel2); - } - } - } - - // DAG access pattern. - uint32_t dsts[num_words_per_lane]; - uint32_t sels[num_words_per_lane]; - for (size_t i = 0; i < num_words_per_lane; ++i) - { - dsts[i] = i == 0 ? 0 : state.next_dst(); - sels[i] = state.rng(); - } - - // DAG access. - for (size_t l = 0; l < num_lanes; ++l) - { - const auto offset = ((l ^ r) % num_lanes) * num_words_per_lane; - for (size_t i = 0; i < num_words_per_lane; ++i) - { - const auto word = le::uint32(item.word32s[offset + i]); - random_merge(mix[l][dsts[i]], word, sels[i]); - } - } -} - -mix_array init_mix(uint64_t seed) -{ - const uint32_t z = fnv1a(fnv_offset_basis, static_cast(seed)); - const uint32_t w = fnv1a(z, static_cast(seed >> 32)); - - mix_array mix; - for (uint32_t l = 0; l < mix.size(); ++l) - { - const uint32_t jsr = fnv1a(w, l); - const uint32_t jcong = fnv1a(jsr, l); - kiss99 rng{z, w, jsr, jcong}; - - for (auto& row : mix[l]) - row = rng(); - } - return mix; -} - -hash256 hash_mix( - const epoch_context& context, int block_number, uint64_t seed, lookup_fn lookup) noexcept -{ - auto mix = init_mix(seed); - mix_rng_state state{uint64_t(block_number / period_length)}; - - for (uint32_t i = 0; i < 64; ++i) - round(context, i, mix, state, lookup); - - // Reduce mix data to a single per-lane result. - uint32_t lane_hash[num_lanes]; - for (size_t l = 0; l < num_lanes; ++l) - { - lane_hash[l] = fnv_offset_basis; - for (uint32_t i = 0; i < num_regs; ++i) - lane_hash[l] = fnv1a(lane_hash[l], mix[l][i]); - } - - // Reduce all lanes to a single 256-bit result. - static constexpr size_t num_words = sizeof(hash256) / sizeof(uint32_t); - hash256 mix_hash; - for (uint32_t& w : mix_hash.word32s) - w = fnv_offset_basis; - for (size_t l = 0; l < num_lanes; ++l) - mix_hash.word32s[l % num_words] = fnv1a(mix_hash.word32s[l % num_words], lane_hash[l]); - return le::uint32s(mix_hash); -} -} // namespace - -result hash(const epoch_context& context, int block_number, const hash256& header_hash, - uint64_t nonce) noexcept -{ - const uint64_t seed = keccak_progpow_64(header_hash, nonce); - const hash256 mix_hash = hash_mix(context, block_number, seed, calculate_dataset_item_2048); - const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash); - return {final_hash, mix_hash}; -} - -result hash(const epoch_context_full& context, int block_number, const hash256& header_hash, - uint64_t nonce) noexcept -{ - static const auto lazy_lookup = [](const epoch_context& context, uint32_t index) noexcept - { - auto* full_dataset_1024 = static_cast(context).full_dataset; - auto* full_dataset_2048 = reinterpret_cast(full_dataset_1024); - hash2048& item = full_dataset_2048[index]; - if (item.word64s[0] == 0) - { - // TODO: Copy elision here makes it thread-safe? - item = calculate_dataset_item_2048(context, index); - } - - return item; - }; - - const uint64_t seed = keccak_progpow_64(header_hash, nonce); - const hash256 mix_hash = hash_mix(context, block_number, seed, lazy_lookup); - const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash); - return {final_hash, mix_hash}; -} - -bool verify(const epoch_context& context, int block_number, const hash256& header_hash, - const hash256& mix_hash, uint64_t nonce, const hash256& boundary) noexcept -{ - const uint64_t seed = keccak_progpow_64(header_hash, nonce); - const hash256 final_hash = keccak_progpow_256(header_hash, seed, mix_hash); - if (!is_less_or_equal(final_hash, boundary)) - return false; - - const hash256 expected_mix_hash = - hash_mix(context, block_number, seed, calculate_dataset_item_2048); - return is_equal(expected_mix_hash, mix_hash); -} - -search_result search_light(const epoch_context& context, int block_number, - const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, - size_t iterations) noexcept -{ - const uint64_t end_nonce = start_nonce + iterations; - for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) - { - result r = hash(context, block_number, header_hash, nonce); - if (is_less_or_equal(r.final_hash, boundary)) - return {r, nonce}; - } - return {}; -} - -search_result search(const epoch_context_full& context, int block_number, - const hash256& header_hash, const hash256& boundary, uint64_t start_nonce, - size_t iterations) noexcept -{ - const uint64_t end_nonce = start_nonce + iterations; - for (uint64_t nonce = start_nonce; nonce < end_nonce; ++nonce) - { - result r = hash(context, block_number, header_hash, nonce); - if (is_less_or_equal(r.final_hash, boundary)) - return {r, nonce}; - } - return {}; -} - -} // namespace progpow diff --git a/src/contrib/ethereum/libethash/support/attributes.h b/src/contrib/ethereum/libethash/support/attributes.h deleted file mode 100644 index bb62b8d..0000000 --- a/src/contrib/ethereum/libethash/support/attributes.h +++ /dev/null @@ -1,33 +0,0 @@ -/* ethash: C/C++ implementation of Ethash, the Ethereum Proof of Work algorithm. - * Copyright 2018 Pawel Bylica. - * Licensed under the Apache License, Version 2.0. See the LICENSE file. - */ - -#pragma once - -/** inline */ -#if _MSC_VER || __STDC_VERSION__ -#define INLINE inline -#else -#define INLINE -#endif - -/** [[always_inline]] */ -#if _MSC_VER -#define ALWAYS_INLINE __forceinline -#elif defined(__has_attribute) && __STDC_VERSION__ -#if __has_attribute(always_inline) -#define ALWAYS_INLINE __attribute__((always_inline)) -#endif -#endif -#if !defined(ALWAYS_INLINE) -#define ALWAYS_INLINE -#endif - -/** [[no_sanitize()]] */ -#if __clang__ -#define NO_SANITIZE(sanitizer) \ - __attribute__((no_sanitize(sanitizer))) -#else -#define NO_SANITIZE(sanitizer) -#endif diff --git a/src/contrib/miniupnp/.travis.yml b/src/contrib/miniupnp/.travis.yml deleted file mode 100644 index 56395eb..0000000 --- a/src/contrib/miniupnp/.travis.yml +++ /dev/null @@ -1,49 +0,0 @@ -language: c - -os: - - linux - - osx - -addons: - apt: - packages: - # packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise - - iptables-dev - - libevent-dev - - libnfnetlink-dev - - uuid-dev - -# container-based builds -sudo: false - -env: - - 'PROJECT=minissdpd' - - 'PROJECT=miniupnpc' - - 'PROJECT=miniupnpc-async' - - 'PROJECT=miniupnpc-libevent' - - 'PROJECT=miniupnpd' - -matrix: - exclude: - - os: osx - env: PROJECT=miniupnpd - - os: osx - compiler: gcc - -compiler: - - gcc - - clang - -before_install: - - 'if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$CC" == "gcc" ] ; then CC=gcc-4.9; fi' - -script: - - 'cd $TRAVIS_BUILD_DIR && cd $PROJECT' - - 'MAKEFILE=Makefile && if [ -f Makefile.linux -a "$TRAVIS_OS_NAME" = "linux" ]; then MAKEFILE=Makefile.linux; elif [ -f Makefile.macosx -a "$TRAVIS_OS_NAME" = "osx" ]; then MAKEFILE=Makefile.macosx; fi' - - 'if [ "$MAKEFILE" = "Makefile.macosx" ]; then make -f $MAKEFILE depend; fi' - - 'CONFIG_OPTIONS="--ipv6 --igd2" make -f $MAKEFILE -j3' - - 'if [ "$PROJECT" = "miniupnpc" -o "$PROJECT" = "minissdpd" -o "$PROJECT" = "miniupnpd" ]; then make -f $MAKEFILE check; fi' - - 'if [ "$PROJECT" = "miniupnpc" ]; then INSTALLPREFIX="$HOME/_pythonmodule" make -f $MAKEFILE pythonmodule; fi' - -after_success: - - 'INSTALLPREFIX="$HOME/$PROJECT" make -f $MAKEFILE install' diff --git a/src/contrib/miniupnp/CODE_OF_CONDUCT b/src/contrib/miniupnp/CODE_OF_CONDUCT deleted file mode 100644 index 9684f77..0000000 --- a/src/contrib/miniupnp/CODE_OF_CONDUCT +++ /dev/null @@ -1 +0,0 @@ -behave diff --git a/src/contrib/miniupnp/CONTRIBUTING b/src/contrib/miniupnp/CONTRIBUTING deleted file mode 100644 index 88372e8..0000000 --- a/src/contrib/miniupnp/CONTRIBUTING +++ /dev/null @@ -1,11 +0,0 @@ -MiniUPnP Project - -Before reporting a bug, please test using the latest development sources -available on github : https://github.com/miniupnp/miniupnp/ -Have a look at existing bug reports on github -https://github.com/miniupnp/miniupnp/issues -and on the forum https://miniupnp.tuxfamily.org/forum/ - -Please prefer the github repository to report bugs, send patches, etc. - -Thomas Bernard diff --git a/src/contrib/miniupnp/LICENSE b/src/contrib/miniupnp/LICENSE deleted file mode 100644 index a37fdac..0000000 --- a/src/contrib/miniupnp/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -MiniUPnP Project -Copyright (c) 2005-2017, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/src/contrib/miniupnp/README b/src/contrib/miniupnp/README deleted file mode 100644 index 301e742..0000000 --- a/src/contrib/miniupnp/README +++ /dev/null @@ -1,61 +0,0 @@ - -= MiniUPnP project =- - -Main author : Thomas BERNARD -Web site : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ -Github : https://github.com/miniupnp/miniupnp/ -Travis CI : https://travis-ci.org/miniupnp/miniupnp -Appveyor : https://ci.appveyor.com/project/miniupnp/miniupnp - -miniupnpc/ : MiniUPnP client - an UPnP IGD control point -miniupnpd/ : MiniUPnP daemon - an implementation of a UPnP IGD - + NAT-PMP / PCP gateway -minissdpd/ : SSDP managing daemon. Designed to work with miniupnpc, - miniupnpd, ReadyMedia (formerly MiniDLNA), etc. -miniupnpc-async/ : Proof of concept for a UPnP IGD control point using - asynchronous (non blocking) sockets. -miniupnpc-libevent/ : UPnP IGD control point using libevent2 - http://libevent.org/ - -Thanks to : - * Ryan Wagoner - * João Paulo Barraca - * Craig Kadziolka - * Seth Mos - * Rick Richard - * Michael van Tellingen - * Julien Wajsberg - * Jeremy Collake - * Matthew Sporleder - * Greg Hazel - * Rico Huber - * Jelle Huitema - * Xavier Martin - * Thomas Goirand - * Darren Reed - * Robbie Hanson - * Nikos Mavrogiannopoulos - * Elsö András - * Justin Maggard - * David Wu - * Michael Trebilcock - * Soren Dreijer - * Colin McFarlane - * Daniel Dickinson - * Guillaume Habault - * Alexey Osipov - * Alexey Kuznetsov - * Chiaki Ishikawa - * David Kerr - * Jardel Weyrich - * Leah X. Schmidt - * Peter Tatrai - * Leo Moll - * Daniel Becker - * Yonetani Tomokazu - * Markus Stenberg - * Tomofumi Hayashi - * Konstantin Tokarev - * Mike Tzou - * Nevo Hed - * Salva Peiró - * Stephan Zeisberg diff --git a/src/contrib/miniupnp/appveyor.yml b/src/contrib/miniupnp/appveyor.yml deleted file mode 100644 index b4fb414..0000000 --- a/src/contrib/miniupnp/appveyor.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '2.1.{build}' - -install: - - set PATH=%PATH%;C:\msys64\mingw32\bin - -build_script: - - cd miniupnpc - - appveyor AddCompilationMessage "Building miniupnpc" - - mingw32-make -f Makefile.mingw - - mingw32-make -f Makefile.mingw pythonmodule PYTHON=C:\Python27\python -# - upnpc-static.exe -l - -after_build: - - 7z a ..\miniupnpc-%APPVEYOR_BUILD_VERSION%.zip *.exe *.dll *.a *.lib - - 7z a ..\miniupnpc-python-%APPVEYOR_BUILD_VERSION%.zip build\ dist\ - -artifacts: - - path: miniupnpc-$(appveyor_build_version).zip - name: miniupnpc binaries - - path: miniupnpc-python-$(appveyor_build_version).zip - name: miniupnpc python module diff --git a/src/contrib/miniupnp/minissdpd/.gitignore b/src/contrib/miniupnp/minissdpd/.gitignore deleted file mode 100644 index 4ce115e..0000000 --- a/src/contrib/miniupnp/minissdpd/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.o -minissdpd -testcodelength -testminissdpd -listifaces -Makefile.bak -validateminissdpd -validatecodelength -showminissdpdnotif diff --git a/src/contrib/miniupnp/minissdpd/Changelog.txt b/src/contrib/miniupnp/minissdpd/Changelog.txt deleted file mode 100644 index 049c561..0000000 --- a/src/contrib/miniupnp/minissdpd/Changelog.txt +++ /dev/null @@ -1,158 +0,0 @@ -$Id: Changelog.txt,v 1.49 2018/02/23 13:01:23 nanard Exp $ - -2018/02/23: - Fix build with IPv6 disabled and SSDP_LISTEN_ON_SPECIFIC_ADDR enabled - -2018/02/03: - Properly parse several requests read() at once - Ignore the version of devices while answering to requests - -2016/11/11: - Fix for Solaris build - -2016/03/01: - Fix broken overflow test (p+l > buf+n) thanks to Salva Peiro - -VERSION 1.5: - -2016/01/13: - add "notification" mode (command 5) - -2015/08/06: - disable multicast loop - add -f command line option to filter for a specific device type - -VERSION 1.4: - -2015/08/06: - added command 0 (version) - -2015/07/21: - set multicast TTL to 2 by default and configurable - -2015/05/27: - support larger buffer size (useful for type 3 requests) - -VERSION 1.3: - -2014/12/05: - clean up select call() - fix non blocking write to sockets - -2014/12/04: - Fixes removing of devices on ssdp:byebye - handle ssdp:update messages - -2014/11/28: - revert "listen on only 1 IPv4 if only 1 interface is specified" - because it prevents broadcast messages to be received - Change the list of LAN addresses/interfaces (code taken from miniupnpd) - Check that the peer is from a LAN for each SSDP packet - -2014/11/06: - listen on only 1 IPv4 if only 1 interface is specified - also when ENABLE_IPV6 is not defined - -2014/09/06: - freebsd-glue for Debian/kFreeBSD - use LDFLAGS when linking binary - -2014/05/01: - listen on only 1 IPv4 if only 1 interface is specified - -2014/02/03: - silently ignore EAGAIN, EWOULDBLOCK, EINTR of recv calls - Discover devices on the network at startup - -2013/08/19: - Translate README in english - -2012/09/27: - Rename all include guards to not clash with C99 - (7.1.3 Reserved identifiers). - -VERSION 1.2: - -2012/05/21: - Clean signal handling - Set sockets non blocking - -2012/05/18: - Improve ProcessInterfaceWatch() under BSD. - -2012/05/15: - Improve ProcessInterfaceWatch() under linux. - -2012/05/02: - Clean CLFAGS in Makefile. - Remove a few signed/unsigned compares - -2012/04/09: - Added -ansi to compilation flags. - Handle ssdp:update messages and update logging - -2012/01/02: - Install manpage. Fix installation under Mac OS X. - -2011/10/07: - unlink unix socket before binding. - set SO_REUSEADDR on SSDP socket. - daemonize after init - -VERSION 1.1: - -2011/07/30: - fixes. More overflow checks - -2011/07/29: - added a lot of buffer overflow checks. Check malloc() failure, etc. - Better cleanup in case of crash at start. - network interface watch to add/drop multicast membership when the interface get live. - -2011/06/18: - Starting to add support for UPnP Device Architecture v1.1 - -2011/05/23: - Added IPv6 support. - -i option now understands interface names as well as addresses. - -VERSION 1.0: - -2008/10/07: - added codelength.h - Fixing response to M-SEARCH - Doc update - -2008/10/06: - UPnP server support (answering M-SEARCH) - -2008/10/04: - listening on several interfaces. - -2008/10/01: - use of daemon() instead of home made daemonize. - -2007/12/19: - added uuid in responses - 3 types of requests supported. - preventing buffer overflow - -2007/12/18: - It is now possible to change the location of both pid file and - unix socket. - -2007/10/08: - Added a man page - -2007/09/27: - Support for install in different location $ PREFIX=... make install - -2007/09/23: - added a script for use in /etc/init.d - improved Makefile - creating /var/run/minissdpd.pid - adding synthetic messages for new devices/removed devices - -2007/09/19: - Take SSDP announce packets lifetime into account. - diff --git a/src/contrib/miniupnp/minissdpd/LICENSE b/src/contrib/miniupnp/minissdpd/LICENSE deleted file mode 100644 index d994f14..0000000 --- a/src/contrib/miniupnp/minissdpd/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2007-2016, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/contrib/miniupnp/minissdpd/Makefile b/src/contrib/miniupnp/minissdpd/Makefile deleted file mode 100644 index 2380e79..0000000 --- a/src/contrib/miniupnp/minissdpd/Makefile +++ /dev/null @@ -1,127 +0,0 @@ -# $Id: Makefile,v 1.30 2018/02/23 13:59:44 nanard Exp $ -# MiniUPnP project -# author: Thomas Bernard -# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# for use with GNU Make (gmake) -# install with : -# $ PREFIX=/tmp/dummylocation make install -# or -# $ INSTALLPREFIX=/usr/local make install -# or -# make install (miniupnpd will be put in /usr/sbin) -# -# install target is made for linux... sorry BSD users... -#CFLAGS = -g -O0 -CFLAGS ?= -Os -CFLAGS += -Wall -CFLAGS += -W -Wstrict-prototypes -CFLAGS += -fno-strict-aliasing -fno-common -CFLAGS += -D_GNU_SOURCE -#CFLAGS += -ansi -CC ?= gcc -RM = rm -f -INSTALL = install -OS = $(shell $(CC) -dumpmachine) - -ifneq (, $(findstring linux, $(OS))) - LDLIBS += -lnfnetlink -endif -ifeq ($(DEB_HOST_ARCH_OS), kfreebsd) - LDLIBS += -lfreebsd-glue -else -ifneq (, $(findstring sun, $(OS))) - CFLAGS += -D_XOPEN_SOURCE - CFLAGS += -D_XOPEN_SOURCE_EXTENDED=1 - CFLAGS += -D__EXTENSIONS__ - LDFLAGS += -lsocket -lnsl -lresolv -endif -endif - -#EXECUTABLES = minissdpd testminissdpd listifaces -EXECUTABLES = minissdpd testminissdpd testcodelength \ - showminissdpdnotif -MINISSDPDOBJS = minissdpd.o openssdpsocket.o daemonize.o upnputils.o \ - ifacewatch.o getroute.o getifaddr.o asyncsendto.o -TESTMINISSDPDOBJS = testminissdpd.o printresponse.o -SHOWMINISSDPDNOTIFOBJS = showminissdpdnotif.o printresponse.o - -ALLOBJS = $(MINISSDPDOBJS) $(TESTMINISSDPDOBJS) \ - $(SHOWMINISSDPDNOTIFOBJS) \ - testcodelength.o - -INSTALLPREFIX ?= $(PREFIX)/usr -SBININSTALLDIR = $(INSTALLPREFIX)/sbin -MANINSTALLDIR = $(INSTALLPREFIX)/share/man - - -.PHONY: all clean install depend check test - -all: $(EXECUTABLES) - -test: check - -clean: - $(RM) $(ALLOBJS) $(EXECUTABLES) - -install: minissdpd - $(INSTALL) -d $(SBININSTALLDIR) - $(INSTALL) minissdpd $(SBININSTALLDIR) - $(INSTALL) -d $(MANINSTALLDIR)/man1 - $(INSTALL) minissdpd.1 $(MANINSTALLDIR)/man1/minissdpd.1 -ifeq (, $(findstring darwin, $(OS))) - $(INSTALL) -d $(PREFIX)/etc/init.d - $(INSTALL) minissdpd.init.d.script $(PREFIX)/etc/init.d/minissdpd -endif - -check: validateminissdpd validatecodelength - -validateminissdpd: testminissdpd minissdpd - ./testminissdpd.sh - touch $@ - -validatecodelength: testcodelength - ./testcodelength - touch $@ - -minissdpd: $(MINISSDPDOBJS) - -testminissdpd: $(TESTMINISSDPDOBJS) - -showminissdpdnotif: $(SHOWMINISSDPDNOTIFOBJS) - -testcodelength: testcodelength.o - -listifaces: listifaces.o upnputils.o - -config.h: VERSION - @tmp=`grep -n MINISSDPD_VERSION $@` ; \ - line=`echo $$tmp | cut -d: -f1` ; \ - old_version=`echo $$tmp | cut -d\\" -f2` ; \ - new_version=`cat VERSION` ; \ - if [ "$$new_version" != "$$old_version" ] ; then \ - echo "updating VERSION in $@ from $$old_version to $$new_version"; \ - sed "$${line}s/$${old_version}/$${new_version}/" $@ > $@.temp ; \ - mv $@.temp $@ ; \ - fi - -depend: - makedepend -f$(MAKEFILE_LIST) -Y \ - $(ALLOBJS:.o=.c) 2>/dev/null - -# DO NOT DELETE - -minissdpd.o: config.h getifaddr.h upnputils.h openssdpsocket.h -minissdpd.o: minissdpdtypes.h daemonize.h codelength.h ifacewatch.h -minissdpd.o: asyncsendto.h -openssdpsocket.o: config.h openssdpsocket.h minissdpdtypes.h upnputils.h -daemonize.o: daemonize.h config.h -upnputils.o: config.h upnputils.h getroute.h minissdpdtypes.h -ifacewatch.o: config.h openssdpsocket.h minissdpdtypes.h upnputils.h -getroute.o: getroute.h upnputils.h -getifaddr.o: config.h getifaddr.h -asyncsendto.o: asyncsendto.h upnputils.h -testminissdpd.o: codelength.h printresponse.h -printresponse.o: codelength.h -showminissdpdnotif.o: codelength.h printresponse.h -printresponse.o: codelength.h -testcodelength.o: codelength.h diff --git a/src/contrib/miniupnp/minissdpd/README b/src/contrib/miniupnp/minissdpd/README deleted file mode 100644 index 3712ff6..0000000 --- a/src/contrib/miniupnp/minissdpd/README +++ /dev/null @@ -1,70 +0,0 @@ - * MiniSSDPd - SSDP daemon - -(c) Thomas Bernard -http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ -https://github.com/miniupnp/miniupnp/ - -MiniSSDPd is a daemon that : -1 - keeps track of all UPnP devices announcing themselves on the network. -its database can be queried by local processes using a protocol based on -a unix socket. That enables local processes to quickly discover UPnP devices -without broadcasting SSDP message and waiting several seconds for a response. -2 - keeps a database of local UPnP devices hosted on the machine and -answering SSDP searchs on their behalf. It enables to run several UPnP devices, -like an IGD and a MediaServer, on the same machine. - -to build, use GNU Make. - - -* protocol : - -Connect to the unix socket. -Sent request, get response. -close unix socket connection. - -* Request format : -1st byte : request type - 0 - version - 1 - type - 2 - USN (unique id) - 3 - everything - 4 - submit service (see below) - 5 - switch connection to notification mode -n bytes : string length : 1 byte if < 128 else the upper bit indicate that -one additional byte should be read, etc. (see codelength.h) -n bytes = string - -Response format : - -request type 0 (version) : -n bytes string length -n bytes = version string - -request type 1 / 2 / 3 / 5 : -1st byte : number of services/devices, from 0 to 254. - 255 is a special value, see below -For each service/device : -URL : - n bytes string length - n bytes = Location string -ST: - n bytes string length - n bytes = type string -USN: - n bytes string length - n bytes = identifier string - -if the 1st byte is 255, the format is as follows : -1st byte = 255 -2nd byte = notification type (1=NEW, 2=UPDATE, 3=REMOVE) -3rd byte = number of services/devices, from 0 to 255. - - -request type 4 = submit service -1st byte = 4 -(k,n) bytes : length and string "ST" (service type) -(k,n) bytes : length and string "USN" -(k,n) bytes : length and string "Server" -(k,n) bytes : length and string "Location" -No answer - diff --git a/src/contrib/miniupnp/minissdpd/README.fr b/src/contrib/miniupnp/minissdpd/README.fr deleted file mode 100644 index d94ee54..0000000 --- a/src/contrib/miniupnp/minissdpd/README.fr +++ /dev/null @@ -1,49 +0,0 @@ -protocole : - -connection à la socket unix. -envoie d'une requete, retour d'une reponse. -fermeture de la connexion. - -format de requete : -1 octet : type de la requete - 0 - version - 1 - type - 2 - USN (id unique) - 3 - tout -n octets longueur de la chaine : 1 octet si < 128 sinon le bit haut -indique s'il existe un octet suplementaire, etc... -n octets = chaine - -format reponse : -1 octet : nombre de reponses (de 0 à 254) -pour chaque rep : -URL : - n octets longueur de la chaine - n octets = chaine Location -ST: - n octets longueur de la chaine - n octets = chaine type -USN: - n octets longueur de la chaine - n octets = chaine identifiant - -si le 1er octet est 255, alors le format est le suivant : -1 octet : 255 -1 octet : type de notification - 1 = NOTIF_NEW, 2 = NOTIF_NEW, 3 = NOTIF_REMOVE -1 octet : nombre de reponses (0 à 255) -puis comme ci dessus pour chaque réponse - - - -* Type de requete 4 = submit service -1 octet = 4 -(k,n) octets : longueur et chaine "ST" (service type) -(k,n) octets : longueur et chaine "USN" -(k,n) octets : longueur et chaine "Server" -(k,n) octets : longueur et chaine "Location" -Pas de reponse - -* Type de requete 5 = mode notification -Reste connecté et reçoit au fur et à mesure les nouvelles connections -réponses au format normal diff --git a/src/contrib/miniupnp/minissdpd/VERSION b/src/contrib/miniupnp/minissdpd/VERSION deleted file mode 100644 index c239c60..0000000 --- a/src/contrib/miniupnp/minissdpd/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.5 diff --git a/src/contrib/miniupnp/minissdpd/asyncsendto.c b/src/contrib/miniupnp/minissdpd/asyncsendto.c deleted file mode 100644 index 5689f0b..0000000 --- a/src/contrib/miniupnp/minissdpd/asyncsendto.c +++ /dev/null @@ -1,348 +0,0 @@ -/* $Id: asyncsendto.c,v 1.8 2017/05/24 22:51:57 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "asyncsendto.h" -#include "upnputils.h" - -/* state diagram for a packet : - * - * | - * V - * -> ESCHEDULED -> ESENDNOW -> sent - * ^ | - * | V - * EWAITREADY -> sent - */ -struct scheduled_send { - LIST_ENTRY(scheduled_send) entries; - struct timeval ts; - enum {ESCHEDULED=1, EWAITREADY=2, ESENDNOW=3} state; - int sockfd; - const void * buf; - size_t len; - int flags; - const struct sockaddr *dest_addr; - socklen_t addrlen; - const struct sockaddr_in6 *src_addr; - char data[]; -}; - -static LIST_HEAD(listhead, scheduled_send) send_list = { NULL }; - -/* - * ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, - * const struct sockaddr *dest_addr, socklen_t addrlen); - */ -static ssize_t -send_from_to(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr_in6 *src_addr, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ -#ifdef IPV6_PKTINFO - if(src_addr) { - struct iovec iov; - struct in6_pktinfo ipi6; - uint8_t c[CMSG_SPACE(sizeof(ipi6))]; - struct msghdr msg; - struct cmsghdr* cmsg; - - iov.iov_base = (void *)buf; - iov.iov_len = len; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - ipi6.ipi6_addr = src_addr->sin6_addr; - ipi6.ipi6_ifindex = src_addr->sin6_scope_id; - msg.msg_control = c; - msg.msg_controllen = sizeof(c); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(ipi6)); - memcpy(CMSG_DATA(cmsg), &ipi6, sizeof(ipi6)); - msg.msg_name = (void *)dest_addr; - msg.msg_namelen = addrlen; - return sendmsg(sockfd, &msg, flags); - } else { -#endif /* IPV6_PKTINFO */ - return sendto(sockfd, buf, len, flags, dest_addr, addrlen); -#ifdef IPV6_PKTINFO - } -#endif /* IPV6_PKTINFO */ -} - -/* delay = milli seconds */ -ssize_t -sendto_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr, - unsigned int delay) -{ - enum {ESCHEDULED, EWAITREADY, ESENDNOW} state; - ssize_t n; - size_t alloc_len; - struct timeval tv; - struct scheduled_send * elt; - - if(delay == 0) { - /* first try to send at once */ - n = send_from_to(sockfd, buf, len, flags, src_addr, dest_addr, addrlen); - if(n >= 0) - return n; - else if(errno == EAGAIN || errno == EWOULDBLOCK) { - /* use select() on this socket */ - state = EWAITREADY; - } else if(errno == EINTR) { - state = ESENDNOW; - } else { - /* uncatched error */ - return n; - } - } else { - state = ESCHEDULED; - } - - /* schedule */ - if(gettimeofday(&tv, 0) < 0) { - return -1; - } - /* allocate enough space for structure + buffers */ - alloc_len = sizeof(struct scheduled_send) + len + addrlen; - if(src_addr) - alloc_len += sizeof(struct sockaddr_in6); - elt = malloc(alloc_len); - if(elt == NULL) { - syslog(LOG_ERR, "malloc failed to allocate %u bytes", - (unsigned)alloc_len); - return -1; - } - elt->state = state; - /* time the packet should be sent */ - elt->ts.tv_sec = tv.tv_sec + (delay / 1000); - elt->ts.tv_usec = tv.tv_usec + (delay % 1000) * 1000; - if(elt->ts.tv_usec > 1000000) { - elt->ts.tv_sec++; - elt->ts.tv_usec -= 1000000; - } - elt->sockfd = sockfd; - elt->flags = flags; - memcpy(elt->data, dest_addr, addrlen); - elt->dest_addr = (struct sockaddr *)elt->data; - elt->addrlen = addrlen; - if(src_addr) { - elt->src_addr = (struct sockaddr_in6 *)(elt->data + addrlen); - memcpy((void *)elt->src_addr, src_addr, sizeof(struct sockaddr_in6)); - elt->buf = (void *)(elt->data + addrlen + sizeof(struct sockaddr_in6)); - } else { - elt->src_addr = NULL; - elt->buf = (void *)(elt->data + addrlen); - } - elt->len = len; - memcpy((void *)elt->buf, buf, len); - /* insert */ - LIST_INSERT_HEAD( &send_list, elt, entries); - return 0; -} - -/* try to send at once, and queue the packet if needed */ -ssize_t -sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ - return sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, NULL, 0); -} - -ssize_t -sendto_or_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr) -{ - return sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, src_addr, 0); -} - -/* get_next_scheduled_send() return number of scheduled send in list */ -int get_next_scheduled_send(struct timeval * next_send) -{ - int n = 0; - struct scheduled_send * elt; - if(next_send == NULL) - return -1; - for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { - if(n == 0 || (elt->ts.tv_sec < next_send->tv_sec) || - (elt->ts.tv_sec == next_send->tv_sec && elt->ts.tv_usec < next_send->tv_usec)) { - next_send->tv_sec = elt->ts.tv_sec; - next_send->tv_usec = elt->ts.tv_usec; - } - n++; - } - return n; -} - -/* update writefds for select() call - * return the number of packets to try to send at once */ -int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now) -{ - int n = 0; - struct scheduled_send * elt; - for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { - if(elt->state == EWAITREADY) { - /* last sendto() call returned EAGAIN/EWOULDBLOCK */ - FD_SET(elt->sockfd, writefds); - if(elt->sockfd > *max_fd) - *max_fd = elt->sockfd; - n++; - } else if((elt->ts.tv_sec < now->tv_sec) || - (elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) { - /* we waited long enough, now send ! */ - elt->state = ESENDNOW; - n++; - } - } - return n; -} - -/* executed sendto() when needed */ -int try_sendto(fd_set * writefds) -{ - int ret = 0; - ssize_t n; - struct scheduled_send * elt; - struct scheduled_send * next; - for(elt = send_list.lh_first; elt != NULL; elt = next) { - next = elt->entries.le_next; - if((elt->state == ESENDNOW) || - (elt->state == EWAITREADY && FD_ISSET(elt->sockfd, writefds))) { -#ifdef DEBUG - syslog(LOG_DEBUG, "%s: %d bytes on socket %d", - "try_sendto", (int)elt->len, elt->sockfd); -#endif - n = send_from_to(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->src_addr, elt->dest_addr, elt->addrlen); - /*n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->dest_addr, elt->addrlen);*/ - if(n < 0) { - if(errno == EINTR) { - /* retry at once */ - elt->state = ESENDNOW; - continue; - } else if(errno == EAGAIN || errno == EWOULDBLOCK) { - /* retry once the socket is ready for writing */ - elt->state = EWAITREADY; - continue; - } else { - char addr_str[64]; - /* uncatched error */ - if(sockaddr_to_string(elt->dest_addr, addr_str, sizeof(addr_str)) <= 0) - addr_str[0] = '\0'; - syslog(LOG_ERR, "%s(sock=%d, len=%u, dest=%s): sendto: %m", - "try_sendto", elt->sockfd, (unsigned)elt->len, - addr_str); - ret--; - } - } else if((int)n != (int)elt->len) { - syslog(LOG_WARNING, "%s: %d bytes sent out of %d", - "try_sendto", (int)n, (int)elt->len); - } - /* remove from the list */ - LIST_REMOVE(elt, entries); - free(elt); - } - } - return ret; -} - -/* maximum execution time for finalize_sendto() in milliseconds */ -#define FINALIZE_SENDTO_DELAY (500) - -/* empty the list */ -void finalize_sendto(void) -{ - ssize_t n; - struct scheduled_send * elt; - struct scheduled_send * next; - fd_set writefds; - struct timeval deadline; - struct timeval now; - struct timeval timeout; - int max_fd; - - if(gettimeofday(&deadline, NULL) < 0) { - syslog(LOG_ERR, "gettimeofday: %m"); - return; - } - deadline.tv_usec += FINALIZE_SENDTO_DELAY*1000; - if(deadline.tv_usec > 1000000) { - deadline.tv_sec++; - deadline.tv_usec -= 1000000; - } - while(send_list.lh_first) { - FD_ZERO(&writefds); - max_fd = -1; - for(elt = send_list.lh_first; elt != NULL; elt = next) { - next = elt->entries.le_next; - syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d", - (int)elt->len, elt->sockfd); - n = send_from_to(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->src_addr, elt->dest_addr, elt->addrlen); - /*n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->dest_addr, elt->addrlen);*/ - if(n < 0) { - if(errno==EAGAIN || errno==EWOULDBLOCK) { - FD_SET(elt->sockfd, &writefds); - if(elt->sockfd > max_fd) - max_fd = elt->sockfd; - continue; - } - syslog(LOG_WARNING, "finalize_sendto(): socket=%d sendto: %m", elt->sockfd); - } - /* remove from the list */ - LIST_REMOVE(elt, entries); - free(elt); - } - /* check deadline */ - if(gettimeofday(&now, NULL) < 0) { - syslog(LOG_ERR, "gettimeofday: %m"); - return; - } - if(now.tv_sec > deadline.tv_sec || - (now.tv_sec == deadline.tv_sec && now.tv_usec > deadline.tv_usec)) { - /* deadline ! */ - while((elt = send_list.lh_first) != NULL) { - LIST_REMOVE(elt, entries); - free(elt); - } - return; - } - /* compute timeout value */ - timeout.tv_sec = deadline.tv_sec - now.tv_sec; - timeout.tv_usec = deadline.tv_usec - now.tv_usec; - if(timeout.tv_usec < 0) { - timeout.tv_sec--; - timeout.tv_usec += 1000000; - } - if(max_fd >= 0) { - if(select(max_fd + 1, NULL, &writefds, NULL, &timeout) < 0) { - syslog(LOG_ERR, "select: %m"); - return; - } - } - } -} - diff --git a/src/contrib/miniupnp/minissdpd/asyncsendto.h b/src/contrib/miniupnp/minissdpd/asyncsendto.h deleted file mode 100644 index ef670c2..0000000 --- a/src/contrib/miniupnp/minissdpd/asyncsendto.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $Id: asyncsendto.h,v 1.3 2017/11/02 15:48:29 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef ASYNCSENDTO_H_INCLUDED -#define ASYNCSENDTO_H_INCLUDED -/* for fd_set */ -#include - -/* sendto_schedule() : see sendto(2) - * schedule sendto() call after delay (milliseconds) */ -ssize_t -sendto_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr, - unsigned int delay); - -#define sendto_schedule(sockfd, buf, len, flags, dest_addr, addrlen, delay) \ - sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, NULL, delay) - -/* sendto_schedule() : see sendto(2) - * try sendto() at once and schedule if EINTR/EAGAIN/EWOULDBLOCK */ -ssize_t -sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen); - -/* same as sendto_schedule() except it will try to set source address - * (for IPV6 only) */ -ssize_t -sendto_or_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr); - -/* get_next_scheduled_send() - * return number of scheduled sendto - * set next_send to timestamp to send next packet */ -int get_next_scheduled_send(struct timeval * next_send); - -/* execute sendto() for needed packets */ -int try_sendto(fd_set * writefds); - -/* set writefds before select() */ -int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now); - -/* empty the list */ -void finalize_sendto(void); - -#endif diff --git a/src/contrib/miniupnp/minissdpd/codelength.h b/src/contrib/miniupnp/minissdpd/codelength.h deleted file mode 100644 index f5f8e30..0000000 --- a/src/contrib/miniupnp/minissdpd/codelength.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2005-2015 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef CODELENGTH_H_INCLUDED -#define CODELENGTH_H_INCLUDED - -/* Encode length by using 7bit per Byte : - * Most significant bit of each byte specifies that the - * following byte is part of the code */ - -/* n : unsigned - * p : unsigned char * - */ -#define DECODELENGTH(n, p) n = 0; \ - do { n = (n << 7) | (*p & 0x7f); } \ - while((*(p++)&0x80) && (n<(1<<25))); - -/* n : unsigned - * READ : function/macro to read one byte (unsigned char) - */ -#define DECODELENGTH_READ(n, READ) \ - n = 0; \ - do { \ - unsigned char c; \ - READ(c); \ - n = (n << 7) | (c & 0x07f); \ - if(!(c&0x80)) break; \ - } while(n<(1<<25)); - -/* n : unsigned - * p : unsigned char * - * p_limit : unsigned char * - */ -#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ - n = 0; \ - do { \ - if((p) >= (p_limit)) break; \ - n = (n << 7) | (*(p) & 0x7f); \ - } while((*((p)++)&0x80) && (n<(1<<25))); - - -/* n : unsigned - * p : unsigned char * - */ -#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ - if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ - if(n>=16384) *(p++) = (n >> 14) | 0x80; \ - if(n>=128) *(p++) = (n >> 7) | 0x80; \ - *(p++) = n & 0x7f; - -#endif /* CODELENGTH_H_INCLUDED */ diff --git a/src/contrib/miniupnp/minissdpd/config.h b/src/contrib/miniupnp/minissdpd/config.h deleted file mode 100644 index 5288426..0000000 --- a/src/contrib/miniupnp/minissdpd/config.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $Id: config.h,v 1.10 2018/02/23 13:58:14 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef CONFIG_H_INCLUDED -#define CONFIG_H_INCLUDED - -#define MINISSDPD_VERSION "1.5" - -/* use BSD daemon() ? */ -#define USE_DAEMON - -/* set the syslog facility to use. See man syslog(3) and syslog.conf(5). */ -#define LOG_MINISSDPD LOG_DAEMON - -/* enable IPv6 */ -#define ENABLE_IPV6 - -/* The size of unix socket response buffer */ -#define RESPONSE_BUFFER_SIZE (1024 * 4) - -/* Uncomment the following line in order to make minissdpd - * listen on 1.2.3.4:1900 instead of *:1900 - * FOR TESTING PURPOSE ONLY - * Note : it prevents multicast packets to be received, - * at least with linux - * As miniSSDPd needs to receive SSDP packets both multicasted - * and unicasted, we cannot bind to 239.255.255.250 neither */ -/*#define SSDP_LISTEN_ON_SPECIFIC_ADDR*/ - -#endif diff --git a/src/contrib/miniupnp/minissdpd/daemonize.c b/src/contrib/miniupnp/minissdpd/daemonize.c deleted file mode 100644 index 4c5909d..0000000 --- a/src/contrib/miniupnp/minissdpd/daemonize.c +++ /dev/null @@ -1,129 +0,0 @@ -/* $Id: daemonize.c,v 1.12 2011/05/27 09:35:02 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "daemonize.h" -#include "config.h" - -#ifndef USE_DAEMON - -int -daemonize(void) -{ - int pid, i; - - switch(fork()) - { - /* fork error */ - case -1: - perror("fork()"); - exit(1); - - /* child process */ - case 0: - /* obtain a new process group */ - if( (pid = setsid()) < 0) - { - perror("setsid()"); - exit(1); - } - - /* close all descriptors */ - for (i=getdtablesize();i>=0;--i) close(i); - - i = open("/dev/null", O_RDWR); /* open stdin */ - dup(i); /* stdout */ - dup(i); /* stderr */ - - umask(027); - chdir("/"); /* chdir to /tmp ? */ - - return pid; - - /* parent process */ - default: - exit(0); - } -} -#endif - -int -writepidfile(const char * fname, int pid) -{ - char pidstring[16]; - int pidstringlen; - int pidfile; - - if(!fname || fname[0] == '\0') - return -1; - - if( (pidfile = open(fname, O_WRONLY|O_CREAT, 0644)) < 0) - { - syslog(LOG_ERR, "Unable to open pidfile for writing %s: %m", fname); - return -1; - } - - pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid); - if(pidstringlen <= 0) - { - syslog(LOG_ERR, - "Unable to write to pidfile %s: snprintf(): FAILED", fname); - close(pidfile); - return -1; - } - else - { - if(write(pidfile, pidstring, pidstringlen) < 0) - syslog(LOG_ERR, "Unable to write to pidfile %s: %m", fname); - } - - close(pidfile); - - return 0; -} - -int -checkforrunning(const char * fname) -{ - char buffer[64]; - int pidfile; - pid_t pid; - - if(!fname || fname[0] == '\0') - return -1; - - if( (pidfile = open(fname, O_RDONLY)) < 0) - return 0; - - memset(buffer, 0, 64); - - if(read(pidfile, buffer, 63)) - { - if( (pid = atol(buffer)) > 0) - { - if(!kill(pid, 0)) - { - close(pidfile); - return -2; - } - } - } - - close(pidfile); - - return 0; -} - diff --git a/src/contrib/miniupnp/minissdpd/daemonize.h b/src/contrib/miniupnp/minissdpd/daemonize.h deleted file mode 100644 index 818ce73..0000000 --- a/src/contrib/miniupnp/minissdpd/daemonize.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: daemonize.h,v 1.6 2008/01/29 13:04:46 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef DAEMONIZE_H_INCLUDED -#define DAEMONIZE_H_INCLUDED - -#include "config.h" - -#ifndef USE_DAEMON -/* daemonize() - * "fork" to background, detach from terminal, etc... - * returns: pid of the daemon, exits upon failure */ -int -daemonize(void); -#endif - -/* writepidfile() - * write the pid to a file */ -int -writepidfile(const char * fname, int pid); - -/* checkforrunning() - * check for another instance running - * returns: 0 only instance - * -1 invalid filename - * -2 another instance running */ -int -checkforrunning(const char * fname); - -#endif - diff --git a/src/contrib/miniupnp/minissdpd/getifaddr.c b/src/contrib/miniupnp/minissdpd/getifaddr.c deleted file mode 100644 index 3febe64..0000000 --- a/src/contrib/miniupnp/minissdpd/getifaddr.c +++ /dev/null @@ -1,261 +0,0 @@ -/* $Id: getifaddr.c,v 1.24 2015/07/09 12:27:26 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(sun) -#include -#endif - -#include "config.h" -#include "getifaddr.h" -#if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) || defined(ENABLE_PCP) -#include -#endif - -int -getifaddr(const char * ifname, char * buf, int len, - struct in_addr * addr, struct in_addr * mask) -{ -#ifndef USE_GETIFADDRS - /* use ioctl SIOCGIFADDR. Works only for ip v4 */ - /* SIOCGIFADDR struct ifreq * */ - int s; - struct ifreq ifr; - int ifrlen; - struct sockaddr_in * ifaddr; - ifrlen = sizeof(ifr); - - if(!ifname || ifname[0]=='\0') - return -1; - s = socket(PF_INET, SOCK_DGRAM, 0); - if(s < 0) - { - syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m"); - return -1; - } - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ-1] = '\0'; - if(ioctl(s, SIOCGIFFLAGS, &ifr, &ifrlen) < 0) - { - syslog(LOG_DEBUG, "ioctl(s, SIOCGIFFLAGS, ...): %m"); - close(s); - return -1; - } - if ((ifr.ifr_flags & IFF_UP) == 0) - { - syslog(LOG_DEBUG, "network interface %s is down", ifname); - close(s); - return -1; - } - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0) - { - syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m"); - close(s); - return -1; - } - ifaddr = (struct sockaddr_in *)&ifr.ifr_addr; - if(addr) *addr = ifaddr->sin_addr; - if(buf) - { - if(!inet_ntop(AF_INET, &ifaddr->sin_addr, buf, len)) - { - syslog(LOG_ERR, "inet_ntop(): %m"); - close(s); - return -1; - } - } - if(mask) - { - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0) - { - syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m"); - close(s); - return -1; - } -#ifdef ifr_netmask - *mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr; -#else - *mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; -#endif - } - close(s); -#else /* ifndef USE_GETIFADDRS */ - /* Works for all address families (both ip v4 and ip v6) */ - struct ifaddrs * ifap; - struct ifaddrs * ife; - - if(!ifname || ifname[0]=='\0') - return -1; - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - switch(ife->ifa_addr->sa_family) - { - case AF_INET: - if(buf) - { - inet_ntop(ife->ifa_addr->sa_family, - &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, - buf, len); - } - if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr; - if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr; - break; -/* - case AF_INET6: - inet_ntop(ife->ifa_addr->sa_family, - &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, - buf, len); -*/ - } - } - freeifaddrs(ifap); -#endif - return 0; -} - -#ifdef ENABLE_PCP - -int getifaddr_in6(const char * ifname, int af, struct in6_addr * addr) -{ -#if defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) - struct ifaddrs * ifap; - struct ifaddrs * ife; -#ifdef ENABLE_IPV6 - const struct sockaddr_in6 * tmpaddr; -#endif /* ENABLE_IPV6 */ - int found = 0; - - if(!ifname || ifname[0]=='\0') - return -1; - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife && !found; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - if (ife->ifa_addr->sa_family != af) - continue; - switch(ife->ifa_addr->sa_family) - { - case AF_INET: - /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */ - memset(addr->s6_addr, 0, 10); - addr->s6_addr[10] = 0xff; - addr->s6_addr[11] = 0xff; - memcpy(addr->s6_addr + 12, - &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr), - 4); - found = 1; - break; - -#ifdef ENABLE_IPV6 - case AF_INET6: - tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr; - if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr) - && !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr)) - { - memcpy(addr->s6_addr, - &tmpaddr->sin6_addr, - 16); - found = 1; - } - break; -#endif /* ENABLE_IPV6 */ - } - } - freeifaddrs(ifap); - return (found ? 0 : -1); -#else /* defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) */ - /* IPv4 only */ - struct in_addr addr4; - if(af != AF_INET) - return -1; - if(getifaddr(ifname, NULL, 0, &addr4, NULL) < 0) - return -1; - /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */ - memset(addr->s6_addr, 0, 10); - addr->s6_addr[10] = 0xff; - addr->s6_addr[11] = 0xff; - memcpy(addr->s6_addr + 12, &addr4.s_addr, 4); - return 0; -#endif -} -#endif /* ENABLE_PCP */ - -#ifdef ENABLE_IPV6 -int -find_ipv6_addr(const char * ifname, - char * dst, int n) -{ - struct ifaddrs * ifap; - struct ifaddrs * ife; - const struct sockaddr_in6 * addr; - char buf[64]; - int r = 0; - - if(!dst) - return -1; - - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - if(ife->ifa_addr->sa_family == AF_INET6) - { - addr = (const struct sockaddr_in6 *)ife->ifa_addr; - if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr) - && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) - { - inet_ntop(ife->ifa_addr->sa_family, - &addr->sin6_addr, - buf, sizeof(buf)); - /* add brackets */ - snprintf(dst, n, "[%s]", buf); - r = 1; - } - } - } - freeifaddrs(ifap); - return r; -} -#endif - diff --git a/src/contrib/miniupnp/minissdpd/getifaddr.h b/src/contrib/miniupnp/minissdpd/getifaddr.h deleted file mode 100644 index 9dcfb02..0000000 --- a/src/contrib/miniupnp/minissdpd/getifaddr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id: getifaddr.h,v 1.10 2014/05/06 14:40:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETIFADDR_H_INCLUDED -#define GETIFADDR_H_INCLUDED - -struct in_addr; -struct in6_addr; - -/* getifaddr() - * take a network interface name and write the - * ip v4 address as text in the buffer - * returns: 0 success, -1 failure */ -int -getifaddr(const char * ifname, char * buf, int len, - struct in_addr * addr, struct in_addr * mask); - -int -getifaddr_in6(const char * ifname, int af, struct in6_addr* addr); - -/* find a non link local IP v6 address for the interface. - * if ifname is NULL, look for all interfaces */ -int -find_ipv6_addr(const char * ifname, - char * dst, int n); - -#endif - diff --git a/src/contrib/miniupnp/minissdpd/getroute.c b/src/contrib/miniupnp/minissdpd/getroute.c deleted file mode 100644 index 90b9933..0000000 --- a/src/contrib/miniupnp/minissdpd/getroute.c +++ /dev/null @@ -1,282 +0,0 @@ -/* $Id: getroute.c,v 1.4 2014/12/01 09:07:17 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -/*#include */ -#include -#include -#include -#else /* __linux__ */ -#include -#include -#include -#ifdef AF_LINK -#include -#endif /* AF_LINK */ -#endif /* __linux__ */ - -#include "getroute.h" -#include "upnputils.h" -#include "config.h" - -/* get_src_for_route_to() function is only called in code - * enabled with ENABLE_IPV6 */ -#ifdef ENABLE_IPV6 - -int -get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len, - int * index) -{ -#if __linux__ - int fd = -1; - struct nlmsghdr *h; - int status; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - struct sockaddr_nl nladdr; - struct iovec iov = { - .iov_base = (void*) &req.n, - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - const struct sockaddr_in * dst4; - const struct sockaddr_in6 * dst6; - - memset(&req, 0, sizeof(req)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_GETROUTE; - req.r.rtm_family = dst->sa_family; - req.r.rtm_table = 0; - req.r.rtm_protocol = 0; - req.r.rtm_scope = 0; - req.r.rtm_type = 0; - req.r.rtm_src_len = 0; - req.r.rtm_dst_len = 0; - req.r.rtm_tos = 0; - - { - char dst_str[128]; - sockaddr_to_string(dst, dst_str, sizeof(dst_str)); - syslog(LOG_DEBUG, "get_src_for_route_to (%s)", dst_str); - } - /* add address */ - if(dst->sa_family == AF_INET) { - dst4 = (const struct sockaddr_in *)dst; - nfnl_addattr_l(&req.n, sizeof(req), RTA_DST, &dst4->sin_addr, 4); - req.r.rtm_dst_len = 32; - } else { - dst6 = (const struct sockaddr_in6 *)dst; - nfnl_addattr_l(&req.n, sizeof(req), RTA_DST, &dst6->sin6_addr, 16); - req.r.rtm_dst_len = 128; - } - - fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (fd < 0) { - syslog(LOG_ERR, "socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) : %m"); - return -1; - } - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - req.n.nlmsg_seq = 1; - iov.iov_len = req.n.nlmsg_len; - - status = sendmsg(fd, &msg, 0); - - if (status < 0) { - syslog(LOG_ERR, "sendmsg(rtnetlink) : %m"); - goto error; - } - - memset(&req, 0, sizeof(req)); - - for(;;) { - iov.iov_len = sizeof(req); - status = recvmsg(fd, &msg, 0); - if(status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - syslog(LOG_ERR, "recvmsg(rtnetlink) %m"); - goto error; - } - if(status == 0) { - syslog(LOG_ERR, "recvmsg(rtnetlink) EOF"); - goto error; - } - for (h = (struct nlmsghdr*)&req.n; status >= (int)sizeof(*h); ) { - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - syslog(LOG_ERR, "Truncated message"); - } - syslog(LOG_ERR, "malformed message: len=%d", len); - goto error; - } - - if(nladdr.nl_pid != 0 || h->nlmsg_seq != 1/*seq*/) { - syslog(LOG_ERR, "wrong seq = %d\n", h->nlmsg_seq); - /* Don't forget to skip that message. */ - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - continue; - } - - if(h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - syslog(LOG_ERR, "NLMSG_ERROR %d : %s", err->error, strerror(-err->error)); - goto error; - } - if(h->nlmsg_type == RTM_NEWROUTE) { - struct rtattr * rta; - int len = h->nlmsg_len; - len -= NLMSG_LENGTH(sizeof(struct rtmsg)); - for(rta = RTM_RTA(NLMSG_DATA((h))); RTA_OK(rta, len); rta = RTA_NEXT(rta,len)) { - unsigned char * data = RTA_DATA(rta); - if(rta->rta_type == RTA_PREFSRC) { - if(src_len && src) { - if(*src_len < RTA_PAYLOAD(rta)) { - syslog(LOG_WARNING, "cannot copy src: %u<%lu", - (unsigned)*src_len, (unsigned long)RTA_PAYLOAD(rta)); - goto error; - } - *src_len = RTA_PAYLOAD(rta); - memcpy(src, data, RTA_PAYLOAD(rta)); - } - } else if(rta->rta_type == RTA_OIF) { - if(index) - memcpy(index, data, sizeof(int)); - } - } - close(fd); - return 0; - } - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - } - syslog(LOG_WARNING, "get_src_for_route_to() : src not found"); -error: - if(fd >= 0) - close(fd); - return -1; -#else /* __linux__ */ - int found = 0; - int s; - int l, i; - char * p; - struct sockaddr * sa; - struct { - struct rt_msghdr m_rtm; - char m_space[512]; - } m_rtmsg; -#define rtm m_rtmsg.m_rtm - - if(dst == NULL) - return -1; -#ifdef __APPLE__ - if(dst->sa_family == AF_INET6) { - syslog(LOG_ERR, "Sorry, get_src_for_route_to() is known to fail with IPV6 on OS X..."); - return -1; - } -#endif - s = socket(PF_ROUTE, SOCK_RAW, dst->sa_family); - if(s < 0) { - syslog(LOG_ERR, "socket(PF_ROUTE) failed : %m"); - return -1; - } - memset(&rtm, 0, sizeof(rtm)); - rtm.rtm_type = RTM_GET; - rtm.rtm_flags = RTF_UP; - rtm.rtm_version = RTM_VERSION; - rtm.rtm_seq = 1; - rtm.rtm_addrs = RTA_DST; /* destination address */ - memcpy(m_rtmsg.m_space, dst, sizeof(struct sockaddr)); - rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr); - if(write(s, &m_rtmsg, rtm.rtm_msglen) < 0) { - syslog(LOG_ERR, "write: %m"); - close(s); - return -1; - } - - do { - l = read(s, &m_rtmsg, sizeof(m_rtmsg)); - if(l<0) { - syslog(LOG_ERR, "read: %m"); - close(s); - return -1; - } - syslog(LOG_DEBUG, "read l=%d seq=%d pid=%d", - l, rtm.rtm_seq, rtm.rtm_pid); - } while(l > 0 && (rtm.rtm_pid != getpid() || rtm.rtm_seq != 1)); - close(s); - p = m_rtmsg.m_space; - if(rtm.rtm_addrs) { - for(i=1; i<0x8000; i <<= 1) { - if(i & rtm.rtm_addrs) { - char tmp[256] = { 0 }; - sa = (struct sockaddr *)p; - sockaddr_to_string(sa, tmp, sizeof(tmp)); - syslog(LOG_DEBUG, "type=%d sa_len=%d sa_family=%d %s", - i, SA_LEN(sa), sa->sa_family, tmp); - if((i == RTA_DST || i == RTA_GATEWAY) && - (src_len && src)) { - size_t len = 0; - void * paddr = NULL; - if(sa->sa_family == AF_INET) { - paddr = &((struct sockaddr_in *)sa)->sin_addr; - len = sizeof(struct in_addr); - } else if(sa->sa_family == AF_INET6) { - paddr = &((struct sockaddr_in6 *)sa)->sin6_addr; - len = sizeof(struct in6_addr); - } - if(paddr) { - if(*src_len < len) { - syslog(LOG_WARNING, "cannot copy src. %u<%u", - (unsigned)*src_len, (unsigned)len); - return -1; - } - memcpy(src, paddr, len); - *src_len = len; - found = 1; - } - } -#ifdef AF_LINK - if(sa->sa_family == AF_LINK) { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa; - if(index) - *index = sdl->sdl_index; - } -#endif - p += SA_LEN(sa); - } - } - } - return found ? 0 : -1; -#endif /* __linux__ */ -} - -#endif /* ENABLE_IPV6 */ diff --git a/src/contrib/miniupnp/minissdpd/getroute.h b/src/contrib/miniupnp/minissdpd/getroute.h deleted file mode 100644 index 86d0496..0000000 --- a/src/contrib/miniupnp/minissdpd/getroute.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id: getroute.h,v 1.3 2013/02/06 10:50:04 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETROUTE_H_INCLUDED -#define GETROUTE_H_INCLUDED - -int -get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len, - int * index); - -#endif - diff --git a/src/contrib/miniupnp/minissdpd/ifacewatch.c b/src/contrib/miniupnp/minissdpd/ifacewatch.c deleted file mode 100644 index c73450a..0000000 --- a/src/contrib/miniupnp/minissdpd/ifacewatch.c +++ /dev/null @@ -1,345 +0,0 @@ -/* $Id: ifacewatch.c,v 1.16 2015/09/03 18:31:25 nanard Exp $ */ -/* MiniUPnP project - * (c) 2011-2018 Thomas Bernard - * website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#include -#else /* __linux__ */ -#include -#ifdef AF_LINK -#include -#endif -#endif /* __linux__ */ -#include -#include - -#include "config.h" -#include "openssdpsocket.h" -#include "upnputils.h" -#include "minissdpdtypes.h" - -extern struct lan_addr_list lan_addrs; - -#ifndef __linux__ -#if defined(__OpenBSD__) || defined(__FreeBSD__) -#define SALIGN (sizeof(long) - 1) -#else -#define SALIGN (sizeof(int32_t) - 1) -#endif -#define SA_RLEN(sa) (SA_LEN(sa) ? ((SA_LEN(sa) + SALIGN) & ~SALIGN) : (SALIGN + 1)) -#endif - -int -OpenAndConfInterfaceWatchSocket(void) -{ - int s; -#ifdef __linux__ - struct sockaddr_nl addr; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); -#else /* __linux__*/ - /*s = socket(PF_ROUTE, SOCK_RAW, AF_INET);*/ - s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); -/* The family parameter may be AF_UNSPEC which will provide routing informa- - * tion for all address families, or can be restricted to a specific address - * family by specifying which one is desired. There can be more than one - * routing socket open per system. */ -#endif - if(s < 0) { - syslog(LOG_ERR, "%s socket: %m", - "OpenAndConfInterfaceWatchSocket"); - return -1; - } - if(!set_non_blocking(s)) { - syslog(LOG_WARNING, "%s failed to set socket non blocking : %m", - "OpenAndConfInterfaceWatchSocket"); - } -#ifdef __linux__ - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; - - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - syslog(LOG_ERR, "bind(netlink): %m"); - close(s); - return -1; - } -#endif - return s; -} - -/** - * Process the message and add/drop multicast membership if needed - */ -int -ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6) -{ - struct lan_addr_s * lan_addr; - ssize_t len; - char buffer[4096]; -#ifdef __linux__ - struct iovec iov; - struct msghdr hdr; - struct nlmsghdr *nlhdr; - struct ifaddrmsg *ifa; - struct rtattr *rta; - int ifa_len; - -#ifndef ENABLE_IPV6 - (void)s_ssdp6; -#endif - iov.iov_base = buffer; - iov.iov_len = sizeof(buffer); - - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - - len = recvmsg(s, &hdr, 0); - if(len < 0) { - syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m"); - return -1; - } - - for(nlhdr = (struct nlmsghdr *)buffer; - NLMSG_OK(nlhdr, len); - nlhdr = NLMSG_NEXT(nlhdr, len)) { - int is_del = 0; - char address[48]; - char ifname[IFNAMSIZ]; - address[0] = '\0'; - ifname[0] = '\0'; - if(nlhdr->nlmsg_type == NLMSG_DONE) - break; - switch(nlhdr->nlmsg_type) { - /* case RTM_NEWLINK: */ - /* case RTM_DELLINK: */ - case RTM_DELADDR: - is_del = 1; - case RTM_NEWADDR: - /* http://linux-hacks.blogspot.fr/2009/01/sample-code-to-learn-netlink.html */ - ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr); - rta = (struct rtattr *)IFA_RTA(ifa); - ifa_len = IFA_PAYLOAD(nlhdr); - syslog(LOG_DEBUG, "%s %s index=%d fam=%d prefixlen=%d flags=%d scope=%d", - "ProcessInterfaceWatchNotify", is_del ? "RTM_DELADDR" : "RTM_NEWADDR", - ifa->ifa_index, ifa->ifa_family, ifa->ifa_prefixlen, - ifa->ifa_flags, ifa->ifa_scope); - for(;RTA_OK(rta, ifa_len); rta = RTA_NEXT(rta, ifa_len)) { - /*RTA_DATA(rta)*/ - /*rta_type : IFA_ADDRESS, IFA_LOCAL, etc. */ - char tmp[128]; - memset(tmp, 0, sizeof(tmp)); - switch(rta->rta_type) { - case IFA_ADDRESS: - case IFA_LOCAL: - case IFA_BROADCAST: - case IFA_ANYCAST: - inet_ntop(ifa->ifa_family, RTA_DATA(rta), tmp, sizeof(tmp)); - if(rta->rta_type == IFA_ADDRESS) - strncpy(address, tmp, sizeof(address)); - break; - case IFA_LABEL: - strncpy(tmp, RTA_DATA(rta), sizeof(tmp)); - strncpy(ifname, tmp, sizeof(ifname)); - break; - case IFA_CACHEINFO: - { - struct ifa_cacheinfo *cache_info; - cache_info = RTA_DATA(rta); - snprintf(tmp, sizeof(tmp), "valid=%u preferred=%u", - cache_info->ifa_valid, cache_info->ifa_prefered); - } - break; - default: - strncpy(tmp, "*unknown*", sizeof(tmp)); - } - syslog(LOG_DEBUG, " rta_len=%d rta_type=%d '%s'", rta->rta_len, rta->rta_type, tmp); - } - syslog(LOG_INFO, "%s: %s/%d %s", - is_del ? "RTM_DELADDR" : "RTM_NEWADDR", - address, ifa->ifa_prefixlen, ifname); - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { -#ifdef ENABLE_IPV6 - if((0 == strcmp(address, lan_addr->str)) || - (0 == strcmp(ifname, lan_addr->ifname)) || - (ifa->ifa_index == lan_addr->index)) { -#else - if((0 == strcmp(address, lan_addr->str)) || - (0 == strcmp(ifname, lan_addr->ifname))) { -#endif - if(ifa->ifa_family == AF_INET) - AddDropMulticastMembership(s_ssdp, lan_addr, 0, is_del); -#ifdef ENABLE_IPV6 - else if(ifa->ifa_family == AF_INET6) - AddDropMulticastMembership(s_ssdp6, lan_addr, 1, is_del); -#endif - break; - } - } - break; - default: - syslog(LOG_DEBUG, "unknown nlmsg_type=%d", nlhdr->nlmsg_type); - } - } -#else /* __linux__ */ - struct rt_msghdr * rtm; - struct ifa_msghdr * ifam; - int is_del = 0; - char tmp[64]; - char * p; - struct sockaddr * sa; - int addr; - char address[48]; - char ifname[IFNAMSIZ]; - int family = AF_UNSPEC; - int prefixlen = 0; - -#ifndef ENABLE_IPV6 - (void)s_ssdp6; -#endif - address[0] = '\0'; - ifname[0] = '\0'; - - len = recv(s, buffer, sizeof(buffer), 0); - if(len < 0) { - syslog(LOG_ERR, "%s recv: %m", "ProcessInterfaceWatchNotify"); - return -1; - } - rtm = (struct rt_msghdr *)buffer; - switch(rtm->rtm_type) { - case RTM_DELADDR: - is_del = 1; - case RTM_NEWADDR: - ifam = (struct ifa_msghdr *)buffer; - syslog(LOG_DEBUG, "%s %s len=%d/%hu index=%hu addrs=%x flags=%x", - "ProcessInterfaceWatchNotify", is_del?"RTM_DELADDR":"RTM_NEWADDR", - (int)len, ifam->ifam_msglen, - ifam->ifam_index, ifam->ifam_addrs, ifam->ifam_flags); - p = buffer + sizeof(struct ifa_msghdr); - addr = 1; - while(p < buffer + len) { - sa = (struct sockaddr *)p; - while(!(addr & ifam->ifam_addrs) && (addr <= ifam->ifam_addrs)) - addr = addr << 1; - sockaddr_to_string(sa, tmp, sizeof(tmp)); - syslog(LOG_DEBUG, " %s", tmp); - switch(addr) { - case RTA_DST: - case RTA_GATEWAY: - break; - case RTA_NETMASK: - if(sa->sa_family == AF_INET -#if defined(__OpenBSD__) - || (sa->sa_family == 0 && - sa->sa_len <= sizeof(struct sockaddr_in)) -#endif - ) { - uint32_t sin_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); - while((prefixlen < 32) && - ((sin_addr & (1 << (31 - prefixlen))) != 0)) - prefixlen++; - } else if(sa->sa_family == AF_INET6 -#if defined(__OpenBSD__) - || (sa->sa_family == 0 && - sa->sa_len == sizeof(struct sockaddr_in6)) -#endif - ) { - int i = 0; - uint8_t * q = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; - while((*q == 0xff) && (i < 16)) { - prefixlen += 8; - q++; i++; - } - if(i < 16) { - i = 0; - while((i < 8) && - ((*q & (1 << (7 - i))) != 0)) - i++; - prefixlen += i; - } - } - break; - case RTA_GENMASK: - break; - case RTA_IFP: -#ifdef AF_LINK - if(sa->sa_family == AF_LINK) { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa; - memset(ifname, 0, sizeof(ifname)); - memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen); - } -#endif - break; - case RTA_IFA: - family = sa->sa_family; - if(sa->sa_family == AF_INET) { - inet_ntop(sa->sa_family, - &((struct sockaddr_in *)sa)->sin_addr, - address, sizeof(address)); - } else if(sa->sa_family == AF_INET6) { - inet_ntop(sa->sa_family, - &((struct sockaddr_in6 *)sa)->sin6_addr, - address, sizeof(address)); - } - break; - case RTA_AUTHOR: - break; - case RTA_BRD: - break; - } -#if 0 - syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x", - (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3], - (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]); - syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x", - (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7], - (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7]); -#endif - p += SA_RLEN(sa); - addr = addr << 1; - } - syslog(LOG_INFO, "%s: %s/%d %s", - is_del ? "RTM_DELADDR" : "RTM_NEWADDR", - address, prefixlen, ifname); - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { -#ifdef ENABLE_IPV6 - if((0 == strcmp(address, lan_addr->str)) || - (0 == strcmp(ifname, lan_addr->ifname)) || - (ifam->ifam_index == lan_addr->index)) { -#else - if((0 == strcmp(address, lan_addr->str)) || - (0 == strcmp(ifname, lan_addr->ifname))) { -#endif - if(family == AF_INET) - AddDropMulticastMembership(s_ssdp, lan_addr, 0, is_del); -#ifdef ENABLE_IPV6 - else if(family == AF_INET6) - AddDropMulticastMembership(s_ssdp6, lan_addr, 1, is_del); -#endif - break; - } - } - break; - default: - syslog(LOG_DEBUG, "Unknown RTM message : rtm->rtm_type=%d len=%d", - rtm->rtm_type, (int)len); - } -#endif - return 0; -} - diff --git a/src/contrib/miniupnp/minissdpd/ifacewatch.h b/src/contrib/miniupnp/minissdpd/ifacewatch.h deleted file mode 100644 index 4b4f28f..0000000 --- a/src/contrib/miniupnp/minissdpd/ifacewatch.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id: ifacewatch.h,v 1.4 2014/11/28 16:20:57 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef IFACEWATCH_H_INCLUDED -#define IFACEWATCH_H_INCLUDED - -int -OpenAndConfInterfaceWatchSocket(void); - -int -ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6); - -#endif diff --git a/src/contrib/miniupnp/minissdpd/listifaces.c b/src/contrib/miniupnp/minissdpd/listifaces.c deleted file mode 100644 index 190ee21..0000000 --- a/src/contrib/miniupnp/minissdpd/listifaces.c +++ /dev/null @@ -1,120 +0,0 @@ -/* $Id: listifaces.c,v 1.7 2015/02/08 08:51:54 nanard Exp $ */ -/* (c) 2006-2015 Thomas BERNARD - * http://miniupnp.free.fr/ http://miniupnp.tuxfamily.org/ - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "upnputils.h" - -/* hexdump */ -void printhex(const unsigned char * p, int n) -{ - int i; - while(n>0) - { - for(i=0; i<16; i++) - printf("%02x ", p[i]); - printf("| "); - for(i=0; i<16; i++) - { - putchar((p[i]>=32 && p[i]<127)?p[i]:'.'); - } - printf("\n"); - p+=16; - n -= 16; - } -} - -/* List network interfaces */ -void listifaces(void) -{ - struct ifconf ifc; - char * buf = NULL; - int buflen; - int s, i; - int j; - char saddr[256/*INET_ADDRSTRLEN*/]; -#ifdef __linux__ - buflen = sizeof(struct ifreq)*10; -#else - buflen = 0; -#endif - /*s = socket(PF_INET, SOCK_DGRAM, 0);*/ - s = socket(AF_INET, SOCK_DGRAM, 0); - do { - char * tmp; -#ifdef __linux__ - buflen += buflen; -#endif - if(buflen > 0) { - tmp = realloc(buf, buflen); - if(!tmp) { - fprintf(stderr, "error allocating %d bytes.\n", buflen); - close(f); - free(buf); - return; - } - buf = tmp; - } - ifc.ifc_len = buflen; - ifc.ifc_buf = (caddr_t)buf; - if(ioctl(s, SIOCGIFCONF, &ifc) < 0) - { - perror("ioctl"); - close(s); - free(buf); - return; - } - printf("buffer length=%d - buffer used=%d - sizeof(struct ifreq)=%d\n", - buflen, ifc.ifc_len, (int)sizeof(struct ifreq)); - printf("IFNAMSIZ=%d ", IFNAMSIZ); - printf("sizeof(struct sockaddr)=%d sizeof(struct sockaddr_in)=%d\n", - (int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) ); -#ifndef __linux__ - if(buflen == 0) - buflen = ifc.ifc_len; - else - break; - } while(1); -#else - } while(buflen <= ifc.ifc_len); -#endif - printhex((const unsigned char *)ifc.ifc_buf, ifc.ifc_len); - printf("off index fam name address\n"); - for(i = 0, j = 0; iifr_addr))->sin_addr), saddr, sizeof(saddr));*/ - saddr[0] = '\0'; - /* inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr)); */ - sockaddr_to_string(&ifrp->ifr_addr, saddr, sizeof(saddr)); - printf("0x%03x %2d %2d %-16s %s\n", i, j, ifrp->ifr_addr.sa_family, ifrp->ifr_name, saddr); - /*ifrp->ifr_addr.sa_len is only available on BSD */ -#ifdef __linux__ - i += sizeof(struct ifreq); -#else - if(ifrp->ifr_addr.sa_len == 0) - break; - i += IFNAMSIZ + ifrp->ifr_addr.sa_len; -#endif - } - free(buf); - close(s); -} - -int main(int argc, char * * argv) -{ - (void)argc; - (void)argv; - listifaces(); - return 0; -} - diff --git a/src/contrib/miniupnp/minissdpd/minissdpd.1 b/src/contrib/miniupnp/minissdpd/minissdpd.1 deleted file mode 100644 index f898b9e..0000000 --- a/src/contrib/miniupnp/minissdpd/minissdpd.1 +++ /dev/null @@ -1,43 +0,0 @@ -.TH "minissdpd" 1 -.SH NAME -minissdpd \- daemon keeping track of UPnP devices up -.SH SYNOPSIS -.B minissdpd -.RB [ -d "] [" -6 "] [" "-s \fIsocket" "] [" "-p \fIpidfile" "] [" "-t \fITTL" "] [" "-f \fIdevice" ] " -i \fR<\fIinterface\fR> " [ "-i \fR<\fIinterface2\fR>" "] ..." -.SH DESCRIPTION -minissdpd listen for SSDP traffic and keeps track -of what are the UPnP devices up on the network. -The list of the UPnP devices is accessed by programs -looking for devices, skipping the UPnP discovery process. -.SH OPTIONS -.TP -.B \-d -debug : do not go to background, output messages to console -and do not filter out low priority messages. -.TP -.B \-6 -IPv6 : Enable IPv6 in addition to IPv4. -.TP -.BI \-s " socket" -path of the unix socket open for communicating with other processes. -By default /var/run/minissdpd.sock is used. -.TP -.BI \-p " pidfile" -path of the file where pid is written at startup. -By default /var/run/minissdpd.pid is used. -.TP -.BI \-t " TTL" -TTL of the package. -By default 2 is used according to UDA. -.TP -.BI \-f " device" -search/filter a specific device type. -.TP -.BI \-i " interface" -name or IP address of the interface used to listen to SSDP packets -coming on port 1900, multicast address 239.255.255.250. -.SH "SEE ALSO" -miniupnpd(1) miniupnpc(3) -.SH BUGS -No known bugs. - diff --git a/src/contrib/miniupnp/minissdpd/minissdpd.c b/src/contrib/miniupnp/minissdpd/minissdpd.c deleted file mode 100644 index 8a815ca..0000000 --- a/src/contrib/miniupnp/minissdpd/minissdpd.c +++ /dev/null @@ -1,1646 +0,0 @@ -/* $Id: minissdpd.c,v 1.53 2016/03/01 18:06:46 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * (c) 2007-2018 Thomas Bernard - * website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* for chmod : */ -#include -/* unix sockets */ -#include -/* for getpwnam() and getgrnam() */ -#if 0 -#include -#include -#endif - -/* LOG_PERROR does not exist on Solaris */ -#ifndef LOG_PERROR -#define LOG_PERROR 0 -#endif /* LOG_PERROR */ - -#include "getifaddr.h" -#include "upnputils.h" -#include "openssdpsocket.h" -#include "daemonize.h" -#include "codelength.h" -#include "ifacewatch.h" -#include "minissdpdtypes.h" -#include "asyncsendto.h" - -#define SET_MAX(max, x) if((x) > (max)) (max) = (x) -#ifndef MIN -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif - -/* current request management structure */ -struct reqelem { - int socket; - int is_notify; /* has subscribed to notifications */ - LIST_ENTRY(reqelem) entries; - unsigned char * output_buffer; - int output_buffer_offset; - int output_buffer_len; -}; - -/* device data structures */ -struct header { - const char * p; /* string pointer */ - int l; /* string length */ -}; - -#define HEADER_NT 0 -#define HEADER_USN 1 -#define HEADER_LOCATION 2 - -struct device { - struct device * next; - time_t t; /* validity time */ - struct header headers[3]; /* NT, USN and LOCATION headers */ - char data[]; -}; - -/* Services stored for answering to M-SEARCH */ -struct service { - char * st; /* Service type */ - char * usn; /* Unique identifier */ - char * server; /* Server string */ - char * location; /* URL */ - LIST_ENTRY(service) entries; -}; -LIST_HEAD(servicehead, service) servicelisthead; - -#define NTS_SSDP_ALIVE 1 -#define NTS_SSDP_BYEBYE 2 -#define NTS_SSDP_UPDATE 3 - -/* request types */ -enum request_type { - MINISSDPD_GET_VERSION = 0, - MINISSDPD_SEARCH_TYPE = 1, - MINISSDPD_SEARCH_USN = 2, - MINISSDPD_SEARCH_ALL = 3, - MINISSDPD_SUBMIT = 4, - MINISSDPD_NOTIF = 5 -}; - -/* discovered device list kept in memory */ -struct device * devlist = 0; - -/* bootid and configid */ -unsigned int upnp_bootid = 1; -unsigned int upnp_configid = 1337; - -/* LAN interfaces/addresses */ -struct lan_addr_list lan_addrs; - -/* connected clients */ -LIST_HEAD(reqstructhead, reqelem) reqlisthead; - -/* functions prototypes */ - -#define NOTIF_NEW 1 -#define NOTIF_UPDATE 2 -#define NOTIF_REMOVE 3 -static void -sendNotifications(int notif_type, const struct device * dev, const struct service * serv); - -/* functions */ - -/* parselanaddr() - * parse address with mask - * ex: 192.168.1.1/24 or 192.168.1.1/255.255.255.0 - * - * Can also use the interface name (ie eth0) - * - * return value : - * 0 : ok - * -1 : error */ -static int -parselanaddr(struct lan_addr_s * lan_addr, const char * str) -{ - const char * p; - int n; - char tmp[16]; - - memset(lan_addr, 0, sizeof(struct lan_addr_s)); - p = str; - while(*p && *p != '/' && !isspace(*p)) - p++; - n = p - str; - if(!isdigit(str[0]) && n < (int)sizeof(lan_addr->ifname)) { - /* not starting with a digit : suppose it is an interface name */ - memcpy(lan_addr->ifname, str, n); - lan_addr->ifname[n] = '\0'; - if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str), - &lan_addr->addr, &lan_addr->mask) < 0) - goto parselan_error; - /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/ - } else { - if(n>15) - goto parselan_error; - memcpy(lan_addr->str, str, n); - lan_addr->str[n] = '\0'; - if(!inet_aton(lan_addr->str, &lan_addr->addr)) - goto parselan_error; - } - if(*p == '/') { - const char * q = ++p; - while(*p && isdigit(*p)) - p++; - if(*p=='.') { - /* parse mask in /255.255.255.0 format */ - while(*p && (*p=='.' || isdigit(*p))) - p++; - n = p - q; - if(n>15) - goto parselan_error; - memcpy(tmp, q, n); - tmp[n] = '\0'; - if(!inet_aton(tmp, &lan_addr->mask)) - goto parselan_error; - } else { - /* it is a /24 format */ - int nbits = atoi(q); - if(nbits > 32 || nbits < 0) - goto parselan_error; - lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0); - } - } else if(lan_addr->mask.s_addr == 0) { - /* by default, networks are /24 */ - lan_addr->mask.s_addr = htonl(0xffffff00u); - } -#ifdef ENABLE_IPV6 - if(lan_addr->ifname[0] != '\0') { - lan_addr->index = if_nametoindex(lan_addr->ifname); - if(lan_addr->index == 0) - fprintf(stderr, "Cannot get index for network interface %s", - lan_addr->ifname); - } else { - fprintf(stderr, - "Error: please specify LAN network interface by name instead of IPv4 address : %s\n", - str); - return -1; - } -#endif /* ENABLE_IPV6 */ - return 0; -parselan_error: - fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n", - str); - return -1; -} - -static int -write_buffer(struct reqelem * req) -{ - if(req->output_buffer && req->output_buffer_len > 0) { - int n = write(req->socket, - req->output_buffer + req->output_buffer_offset, - req->output_buffer_len); - if(n >= 0) { - req->output_buffer_offset += n; - req->output_buffer_len -= n; - } else if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { - return 0; - } - return n; - } else { - return 0; - } -} - -static int -add_to_buffer(struct reqelem * req, const unsigned char * data, int len) -{ - unsigned char * tmp; - if(req->output_buffer_offset > 0) { - memmove(req->output_buffer, req->output_buffer + req->output_buffer_offset, req->output_buffer_len); - req->output_buffer_offset = 0; - } - tmp = realloc(req->output_buffer, req->output_buffer_len + len); - if(tmp == NULL) { - syslog(LOG_ERR, "%s: failed to allocate %d bytes", - __func__, req->output_buffer_len + len); - return -1; - } - req->output_buffer = tmp; - memcpy(req->output_buffer + req->output_buffer_len, data, len); - req->output_buffer_len += len; - return len; -} - -static int -write_or_buffer(struct reqelem * req, const unsigned char * data, int len) -{ - if(write_buffer(req) < 0) - return -1; - if(req->output_buffer && req->output_buffer_len > 0) { - return add_to_buffer(req, data, len); - } else { - int n = write(req->socket, data, len); - if(n == len) - return len; - if(n < 0) { - if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { - n = add_to_buffer(req, data, len); - if(n < 0) return n; - } else { - return n; - } - } else { - n = add_to_buffer(req, data + n, len - n); - if(n < 0) return n; - } - } - return len; -} - -static const char * -nts_to_str(int nts) -{ - switch(nts) - { - case NTS_SSDP_ALIVE: - return "ssdp:alive"; - case NTS_SSDP_BYEBYE: - return "ssdp:byebye"; - case NTS_SSDP_UPDATE: - return "ssdp:update"; - } - return "unknown"; -} - -/* updateDevice() : - * adds or updates the device to the list. - * return value : - * 0 : the device was updated (or nothing done) - * 1 : the device was new */ -static int -updateDevice(const struct header * headers, time_t t) -{ - struct device ** pp = &devlist; - struct device * p = *pp; /* = devlist; */ - while(p) - { - if( p->headers[HEADER_NT].l == headers[HEADER_NT].l - && (0==memcmp(p->headers[HEADER_NT].p, headers[HEADER_NT].p, headers[HEADER_NT].l)) - && p->headers[HEADER_USN].l == headers[HEADER_USN].l - && (0==memcmp(p->headers[HEADER_USN].p, headers[HEADER_USN].p, headers[HEADER_USN].l)) ) - { - /*printf("found! %d\n", (int)(t - p->t));*/ - syslog(LOG_DEBUG, "device updated : %.*s", headers[HEADER_USN].l, headers[HEADER_USN].p); - p->t = t; - /* update Location ! */ - if(headers[HEADER_LOCATION].l > p->headers[HEADER_LOCATION].l) - { - struct device * tmp; - tmp = realloc(p, sizeof(struct device) - + headers[0].l+headers[1].l+headers[2].l); - if(!tmp) /* allocation error */ - { - syslog(LOG_ERR, "updateDevice() : memory allocation error"); - free(p); - return 0; - } - p = tmp; - *pp = p; - } - memcpy(p->data + p->headers[0].l + p->headers[1].l, - headers[2].p, headers[2].l); - /* TODO : check p->headers[HEADER_LOCATION].l */ - return 0; - } - pp = &p->next; - p = *pp; /* p = p->next; */ - } - syslog(LOG_INFO, "new device discovered : %.*s", - headers[HEADER_USN].l, headers[HEADER_USN].p); - /* add */ - { - char * pc; - int i; - p = malloc( sizeof(struct device) - + headers[0].l+headers[1].l+headers[2].l ); - if(!p) { - syslog(LOG_ERR, "updateDevice(): cannot allocate memory"); - return -1; - } - p->next = devlist; - p->t = t; - pc = p->data; - for(i = 0; i < 3; i++) - { - p->headers[i].p = pc; - p->headers[i].l = headers[i].l; - memcpy(pc, headers[i].p, headers[i].l); - pc += headers[i].l; - } - devlist = p; - sendNotifications(NOTIF_NEW, p, NULL); - } - return 1; -} - -/* removeDevice() : - * remove a device from the list - * return value : - * 0 : no device removed - * -1 : device removed */ -static int -removeDevice(const struct header * headers) -{ - struct device ** pp = &devlist; - struct device * p = *pp; /* = devlist */ - while(p) - { - if( p->headers[HEADER_NT].l == headers[HEADER_NT].l - && (0==memcmp(p->headers[HEADER_NT].p, headers[HEADER_NT].p, headers[HEADER_NT].l)) - && p->headers[HEADER_USN].l == headers[HEADER_USN].l - && (0==memcmp(p->headers[HEADER_USN].p, headers[HEADER_USN].p, headers[HEADER_USN].l)) ) - { - syslog(LOG_INFO, "remove device : %.*s", headers[HEADER_USN].l, headers[HEADER_USN].p); - sendNotifications(NOTIF_REMOVE, p, NULL); - *pp = p->next; - free(p); - return -1; - } - pp = &p->next; - p = *pp; /* p = p->next; */ - } - syslog(LOG_WARNING, "device not found for removing : %.*s", headers[HEADER_USN].l, headers[HEADER_USN].p); - return 0; -} - -/* sent notifications to client having subscribed */ -static void -sendNotifications(int notif_type, const struct device * dev, const struct service * serv) -{ - struct reqelem * req; - unsigned int m; - unsigned char rbuf[RESPONSE_BUFFER_SIZE]; - unsigned char * rp; - - for(req = reqlisthead.lh_first; req; req = req->entries.le_next) { - if(!req->is_notify) continue; - rbuf[0] = '\xff'; /* special code for notifications */ - rbuf[1] = (unsigned char)notif_type; - rbuf[2] = 0; - rp = rbuf + 3; - if(dev) { - /* response : - * 1 - Location - * 2 - NT (device/service type) - * 3 - usn */ - m = dev->headers[HEADER_LOCATION].l; - CODELENGTH(m, rp); - memcpy(rp, dev->headers[HEADER_LOCATION].p, dev->headers[HEADER_LOCATION].l); - rp += dev->headers[HEADER_LOCATION].l; - m = dev->headers[HEADER_NT].l; - CODELENGTH(m, rp); - memcpy(rp, dev->headers[HEADER_NT].p, dev->headers[HEADER_NT].l); - rp += dev->headers[HEADER_NT].l; - m = dev->headers[HEADER_USN].l; - CODELENGTH(m, rp); - memcpy(rp, dev->headers[HEADER_USN].p, dev->headers[HEADER_USN].l); - rp += dev->headers[HEADER_USN].l; - rbuf[2]++; - } - if(serv) { - /* response : - * 1 - Location - * 2 - NT (device/service type) - * 3 - usn */ - m = strlen(serv->location); - CODELENGTH(m, rp); - memcpy(rp, serv->location, m); - rp += m; - m = strlen(serv->st); - CODELENGTH(m, rp); - memcpy(rp, serv->st, m); - rp += m; - m = strlen(serv->usn); - CODELENGTH(m, rp); - memcpy(rp, serv->usn, m); - rp += m; - rbuf[2]++; - } - if(rbuf[2] > 0) { - if(write_or_buffer(req, rbuf, rp - rbuf) < 0) { - syslog(LOG_ERR, "(s=%d) write: %m", req->socket); - /*goto error;*/ - } - } - } -} - -/* SendSSDPMSEARCHResponse() : - * build and send response to M-SEARCH SSDP packets. */ -static void -SendSSDPMSEARCHResponse(int s, const struct sockaddr * sockname, - const char * st, size_t st_len, const char * usn, - const char * server, const char * location) -{ - int l, n; - char buf[1024]; - socklen_t sockname_len; - /* - * follow guideline from document "UPnP Device Architecture 1.0" - * uppercase is recommended. - * DATE: is recommended - * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0 - * - check what to put in the 'Cache-Control' header - * - * have a look at the document "UPnP Device Architecture v1.1 */ - l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=120\r\n" - /*"DATE: ...\r\n"*/ - "ST: %.*s\r\n" - "USN: %s\r\n" - "EXT:\r\n" - "SERVER: %s\r\n" - "LOCATION: %s\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */ - "01-NLS: %u\r\n" /* same as BOOTID. UDA v1.1 */ - "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "\r\n", - (int)st_len, st, usn, - server, location, - upnp_bootid, upnp_bootid, upnp_configid); -#ifdef ENABLE_IPV6 - sockname_len = (sockname->sa_family == PF_INET6) - ? sizeof(struct sockaddr_in6) - : sizeof(struct sockaddr_in); -#else /* ENABLE_IPV6 */ - sockname_len = sizeof(struct sockaddr_in); -#endif /* ENABLE_IPV6 */ - n = sendto_or_schedule(s, buf, l, 0, sockname, sockname_len); - if(n < 0) { - syslog(LOG_ERR, "%s: sendto(udp): %m", __func__); - } -} - -/* Process M-SEARCH requests */ -static void -processMSEARCH(int s, const char * st, size_t st_len, - const struct sockaddr * addr) -{ - struct service * serv; -#ifdef ENABLE_IPV6 - char buf[64]; -#endif /* ENABLE_IPV6 */ - - if(!st || st_len==0) - return; -#ifdef ENABLE_IPV6 - sockaddr_to_string(addr, buf, sizeof(buf)); - syslog(LOG_INFO, "SSDP M-SEARCH from %s ST:%.*s", - buf, (int)st_len, st); -#else /* ENABLE_IPV6 */ - syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s", - inet_ntoa(((const struct sockaddr_in *)addr)->sin_addr), - ntohs(((const struct sockaddr_in *)addr)->sin_port), - (int)st_len, st); -#endif /* ENABLE_IPV6 */ - if(st_len==8 && (0==memcmp(st, "ssdp:all", 8))) { - /* send a response for all services */ - for(serv = servicelisthead.lh_first; - serv; - serv = serv->entries.le_next) { - SendSSDPMSEARCHResponse(s, addr, - serv->st, strlen(serv->st), serv->usn, - serv->server, serv->location); - } - } else if(st_len > 5 && (0==memcmp(st, "uuid:", 5))) { - /* find a matching UUID value */ - for(serv = servicelisthead.lh_first; - serv; - serv = serv->entries.le_next) { - if(0 == strncmp(serv->usn, st, st_len)) { - SendSSDPMSEARCHResponse(s, addr, - serv->st, strlen(serv->st), serv->usn, - serv->server, serv->location); - } - } - } else { - size_t l; - int st_ver = 0; - char atoi_buffer[8]; - - /* remove version at the end of the ST string */ - for (l = st_len; l > 0; l--) { - if (st[l-1] == ':') { - memset(atoi_buffer, 0, sizeof(atoi_buffer)); - memcpy(atoi_buffer, st + l, MIN((sizeof(atoi_buffer) - 1), st_len - l)); - st_ver = atoi(atoi_buffer); - break; - } - } - if (l == 0) - l = st_len; - /* answer for each matching service */ - /* From UPnP Device Architecture v1.1 : - * 1.3.2 [...] Updated versions of device and service types - * are REQUIRED to be full backward compatible with - * previous versions. Devices MUST respond to M-SEARCH - * requests for any supported version. For example, if a - * device implements “urn:schemas-upnporg:service:xyz:2â€, - * it MUST respond to search requests for both that type - * and “urn:schemas-upnp-org:service:xyz:1â€. The response - * MUST specify the same version as was contained in the - * search request. [...] */ - for(serv = servicelisthead.lh_first; - serv; - serv = serv->entries.le_next) { - if(0 == strncmp(serv->st, st, l)) { - syslog(LOG_DEBUG, "Found matching service : %s %s", serv->st, serv->location); - SendSSDPMSEARCHResponse(s, addr, - st, st_len, serv->usn, - serv->server, serv->location); - } - } - } -} - -/** - * helper function. - * reject any non ASCII or non printable character. - */ -static int -containsForbiddenChars(const unsigned char * p, int len) -{ - while(len > 0) { - if(*p < ' ' || *p >= '\x7f') - return 1; - p++; - len--; - } - return 0; -} - -#define METHOD_MSEARCH 1 -#define METHOD_NOTIFY 2 - -/* ParseSSDPPacket() : - * parse a received SSDP Packet and call - * updateDevice() or removeDevice() as needed - * return value : - * -1 : a device was removed - * 0 : no device removed nor added - * 1 : a device was added. */ -static int -ParseSSDPPacket(int s, const char * p, ssize_t n, - const struct sockaddr * addr, - const char * searched_device) -{ - const char * linestart; - const char * lineend; - const char * nameend; - const char * valuestart; - struct header headers[3]; - int i, r = 0; - int methodlen; - int nts = -1; - int method = -1; - unsigned int lifetime = 180; /* 3 minutes by default */ - const char * st = NULL; - int st_len = 0; - - /* first check from what subnet is the sender */ - if(get_lan_for_peer(addr) == NULL) { - char addr_str[64]; - sockaddr_to_string(addr, addr_str, sizeof(addr_str)); - syslog(LOG_WARNING, "peer %s is not from a LAN", - addr_str); - return 0; - } - - /* do the parsing */ - memset(headers, 0, sizeof(headers)); - for(methodlen = 0; - methodlen < n && (isalpha(p[methodlen]) || p[methodlen]=='-'); - methodlen++); - if(methodlen==8 && 0==memcmp(p, "M-SEARCH", 8)) - method = METHOD_MSEARCH; - else if(methodlen==6 && 0==memcmp(p, "NOTIFY", 6)) - method = METHOD_NOTIFY; - else if(methodlen==4 && 0==memcmp(p, "HTTP", 4)) { - /* answer to a M-SEARCH => process it as a NOTIFY - * with NTS: ssdp:alive */ - method = METHOD_NOTIFY; - nts = NTS_SSDP_ALIVE; - } - linestart = p; - while(linestart < p + n - 2) { - /* start parsing the line : detect line end */ - lineend = linestart; - while(lineend < p + n && *lineend != '\n' && *lineend != '\r') - lineend++; - /*printf("line: '%.*s'\n", lineend - linestart, linestart);*/ - /* detect name end : ':' character */ - nameend = linestart; - while(nameend < lineend && *nameend != ':') - nameend++; - /* detect value */ - if(nameend < lineend) - valuestart = nameend + 1; - else - valuestart = nameend; - /* trim spaces */ - while(valuestart < lineend && isspace(*valuestart)) - valuestart++; - /* suppress leading " if needed */ - if(valuestart < lineend && *valuestart=='\"') - valuestart++; - if(nameend > linestart && valuestart < lineend) { - int l = nameend - linestart; /* header name length */ - int m = lineend - valuestart; /* header value length */ - /* suppress tailing spaces */ - while(m>0 && isspace(valuestart[m-1])) - m--; - /* suppress tailing ' if needed */ - if(m>0 && valuestart[m-1] == '\"') - m--; - i = -1; - /*printf("--%.*s: (%d)%.*s--\n", l, linestart, - m, m, valuestart);*/ - if(l==2 && 0==strncasecmp(linestart, "nt", 2)) - i = HEADER_NT; - else if(l==3 && 0==strncasecmp(linestart, "usn", 3)) - i = HEADER_USN; - else if(l==3 && 0==strncasecmp(linestart, "nts", 3)) { - if(m==10 && 0==strncasecmp(valuestart, "ssdp:alive", 10)) - nts = NTS_SSDP_ALIVE; - else if(m==11 && 0==strncasecmp(valuestart, "ssdp:byebye", 11)) - nts = NTS_SSDP_BYEBYE; - else if(m==11 && 0==strncasecmp(valuestart, "ssdp:update", 11)) - nts = NTS_SSDP_UPDATE; - } - else if(l==8 && 0==strncasecmp(linestart, "location", 8)) - i = HEADER_LOCATION; - else if(l==13 && 0==strncasecmp(linestart, "cache-control", 13)) { - /* parse "name1=value1, name_alone, name2=value2" string */ - const char * name = valuestart; /* name */ - const char * val; /* value */ - int rem = m; /* remaining bytes to process */ - while(rem > 0) { - val = name; - while(val < name + rem && *val != '=' && *val != ',') - val++; - if(val >= name + rem) - break; - if(*val == '=') { - while(val < name + rem && (*val == '=' || isspace(*val))) - val++; - if(val >= name + rem) - break; - if(0==strncasecmp(name, "max-age", 7)) - lifetime = (unsigned int)strtoul(val, 0, 0); - /* move to the next name=value pair */ - while(rem > 0 && *name != ',') { - rem--; - name++; - } - /* skip spaces */ - while(rem > 0 && (*name == ',' || isspace(*name))) { - rem--; - name++; - } - } else { - rem -= (val - name); - name = val; - while(rem > 0 && (*name == ',' || isspace(*name))) { - rem--; - name++; - } - } - } - /*syslog(LOG_DEBUG, "**%.*s**%u", m, valuestart, lifetime);*/ - } else if(l==2 && 0==strncasecmp(linestart, "st", 2)) { - st = valuestart; - st_len = m; - if(method == METHOD_NOTIFY) - i = HEADER_NT; /* it was a M-SEARCH response */ - } - if(i>=0) { - headers[i].p = valuestart; - headers[i].l = m; - } - } - linestart = lineend; - while((*linestart == '\n' || *linestart == '\r') && linestart < p + n) - linestart++; - } -#if 0 - printf("NTS=%d\n", nts); - for(i=0; i<3; i++) { - if(headers[i].p) - printf("%d-'%.*s'\n", i, headers[i].l, headers[i].p); - } -#endif - syslog(LOG_DEBUG,"SSDP request: '%.*s' (%d) %s %s=%.*s", - methodlen, p, method, nts_to_str(nts), - (method==METHOD_NOTIFY)?"nt":"st", - (method==METHOD_NOTIFY)?headers[HEADER_NT].l:st_len, - (method==METHOD_NOTIFY)?headers[HEADER_NT].p:st); - switch(method) { - case METHOD_NOTIFY: - if(nts==NTS_SSDP_ALIVE || nts==NTS_SSDP_UPDATE) { - if(headers[HEADER_NT].p && headers[HEADER_USN].p && headers[HEADER_LOCATION].p) { - /* filter if needed */ - if(searched_device && - 0 != memcmp(headers[HEADER_NT].p, searched_device, headers[HEADER_NT].l)) - break; - r = updateDevice(headers, time(NULL) + lifetime); - } else { - syslog(LOG_WARNING, "missing header nt=%p usn=%p location=%p", - headers[HEADER_NT].p, headers[HEADER_USN].p, - headers[HEADER_LOCATION].p); - } - } else if(nts==NTS_SSDP_BYEBYE) { - if(headers[HEADER_NT].p && headers[HEADER_USN].p) { - r = removeDevice(headers); - } else { - syslog(LOG_WARNING, "missing header nt=%p usn=%p", - headers[HEADER_NT].p, headers[HEADER_USN].p); - } - } - break; - case METHOD_MSEARCH: - processMSEARCH(s, st, st_len, addr); - break; - default: - { - char addr_str[64]; - sockaddr_to_string(addr, addr_str, sizeof(addr_str)); - syslog(LOG_WARNING, "method %.*s, don't know what to do (from %s)", - methodlen, p, addr_str); - } - } - return r; -} - -/* OpenUnixSocket() - * open the unix socket and call bind() and listen() - * return -1 in case of error */ -static int -OpenUnixSocket(const char * path) -{ - struct sockaddr_un addr; - int s; - int rv; - s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s < 0) - { - syslog(LOG_ERR, "socket(AF_UNIX): %m"); - return -1; - } - /* unlink the socket pseudo file before binding */ - rv = unlink(path); - if(rv < 0 && errno != ENOENT) - { - syslog(LOG_ERR, "unlink(unixsocket, \"%s\"): %m", path); - close(s); - return -1; - } - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path)); - if(bind(s, (struct sockaddr *)&addr, - sizeof(struct sockaddr_un)) < 0) - { - syslog(LOG_ERR, "bind(unixsocket, \"%s\"): %m", path); - close(s); - return -1; - } - else if(listen(s, 5) < 0) - { - syslog(LOG_ERR, "listen(unixsocket): %m"); - close(s); - return -1; - } - /* Change rights so everyone can communicate with us */ - if(chmod(path, 0666) < 0) - { - syslog(LOG_WARNING, "chmod(\"%s\"): %m", path); - } - return s; -} - -static ssize_t processRequestSub(struct reqelem * req, const unsigned char * buf, ssize_t n); - -/* processRequest() : - * process the request coming from a unix socket */ -void processRequest(struct reqelem * req) -{ - ssize_t n, r; - unsigned char buf[2048]; - const unsigned char * p; - - n = read(req->socket, buf, sizeof(buf)); - if(n<0) { - if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) - return; /* try again later */ - syslog(LOG_ERR, "(s=%d) processRequest(): read(): %m", req->socket); - goto error; - } - if(n==0) { - syslog(LOG_INFO, "(s=%d) request connection closed", req->socket); - goto error; - } - p = buf; - while (n > 0) - { - r = processRequestSub(req, p, n); - if (r < 0) - goto error; - p += r; - n -= r; - } - return; -error: - close(req->socket); - req->socket = -1; -} - -static ssize_t processRequestSub(struct reqelem * req, const unsigned char * buf, ssize_t n) -{ - unsigned int l, m; - unsigned int baselen; /* without the version */ - const unsigned char * p; - enum request_type type; - struct device * d = devlist; - unsigned char rbuf[RESPONSE_BUFFER_SIZE]; - unsigned char * rp; - unsigned char nrep = 0; - time_t t; - struct service * newserv = NULL; - struct service * serv; - - t = time(NULL); - type = buf[0]; - p = buf + 1; - DECODELENGTH_CHECKLIMIT(l, p, buf + n); - if(l > (unsigned)(buf+n-p)) { - syslog(LOG_WARNING, "bad request (length encoding l=%u n=%u)", - l, (unsigned)n); - goto error; - } - if(l == 0 && type != MINISSDPD_SEARCH_ALL - && type != MINISSDPD_GET_VERSION && type != MINISSDPD_NOTIF) { - syslog(LOG_WARNING, "bad request (length=0, type=%d)", type); - goto error; - } - syslog(LOG_INFO, "(s=%d) request type=%d str='%.*s'", - req->socket, type, l, p); - switch(type) { - case MINISSDPD_GET_VERSION: - rp = rbuf; - CODELENGTH((sizeof(MINISSDPD_VERSION) - 1), rp); - memcpy(rp, MINISSDPD_VERSION, sizeof(MINISSDPD_VERSION) - 1); - rp += (sizeof(MINISSDPD_VERSION) - 1); - if(write_or_buffer(req, rbuf, rp - rbuf) < 0) { - syslog(LOG_ERR, "(s=%d) write: %m", req->socket); - goto error; - } - p += l; - break; - case MINISSDPD_SEARCH_TYPE: /* request by type */ - case MINISSDPD_SEARCH_USN: /* request by USN (unique id) */ - case MINISSDPD_SEARCH_ALL: /* everything */ - rp = rbuf+1; - /* From UPnP Device Architecture v1.1 : - * 1.3.2 [...] Updated versions of device and service types - * are REQUIRED to be full backward compatible with - * previous versions. Devices MUST respond to M-SEARCH - * requests for any supported version. For example, if a - * device implements “urn:schemas-upnporg:service:xyz:2â€, - * it MUST respond to search requests for both that type - * and “urn:schemas-upnp-org:service:xyz:1â€. The response - * MUST specify the same version as was contained in the - * search request. [...] */ - baselen = l; /* remove the version */ - while(baselen > 0) { - if(p[baselen-1] == ':') - break; - if(!(p[baselen-1] >= '0' && p[baselen-1] <= '9')) - break; - baselen--; - } - while(d && (nrep < 255)) { - if(d->t < t) { - syslog(LOG_INFO, "outdated device"); - } else { - /* test if we can put more responses in the buffer */ - if(d->headers[HEADER_LOCATION].l + d->headers[HEADER_NT].l - + d->headers[HEADER_USN].l + 6 - + (rp - rbuf) >= (int)sizeof(rbuf)) - break; - if( (type==MINISSDPD_SEARCH_TYPE && 0==memcmp(d->headers[HEADER_NT].p, p, baselen)) - ||(type==MINISSDPD_SEARCH_USN && 0==memcmp(d->headers[HEADER_USN].p, p, l)) - ||(type==MINISSDPD_SEARCH_ALL) ) { - /* response : - * 1 - Location - * 2 - NT (device/service type) - * 3 - usn */ - m = d->headers[HEADER_LOCATION].l; - CODELENGTH(m, rp); - memcpy(rp, d->headers[HEADER_LOCATION].p, d->headers[HEADER_LOCATION].l); - rp += d->headers[HEADER_LOCATION].l; - m = d->headers[HEADER_NT].l; - CODELENGTH(m, rp); - memcpy(rp, d->headers[HEADER_NT].p, d->headers[HEADER_NT].l); - rp += d->headers[HEADER_NT].l; - m = d->headers[HEADER_USN].l; - CODELENGTH(m, rp); - memcpy(rp, d->headers[HEADER_USN].p, d->headers[HEADER_USN].l); - rp += d->headers[HEADER_USN].l; - nrep++; - } - } - d = d->next; - } - /* Also look in service list */ - for(serv = servicelisthead.lh_first; - serv && (nrep < 255); - serv = serv->entries.le_next) { - /* test if we can put more responses in the buffer */ - if(strlen(serv->location) + strlen(serv->st) - + strlen(serv->usn) + 6 + (rp - rbuf) >= sizeof(rbuf)) - break; - if( (type==MINISSDPD_SEARCH_TYPE && 0==strncmp(serv->st, (const char *)p, l)) - ||(type==MINISSDPD_SEARCH_USN && 0==strncmp(serv->usn, (const char *)p, l)) - ||(type==MINISSDPD_SEARCH_ALL) ) { - /* response : - * 1 - Location - * 2 - NT (device/service type) - * 3 - usn */ - m = strlen(serv->location); - CODELENGTH(m, rp); - memcpy(rp, serv->location, m); - rp += m; - m = strlen(serv->st); - CODELENGTH(m, rp); - memcpy(rp, serv->st, m); - rp += m; - m = strlen(serv->usn); - CODELENGTH(m, rp); - memcpy(rp, serv->usn, m); - rp += m; - nrep++; - } - } - rbuf[0] = nrep; - syslog(LOG_DEBUG, "(s=%d) response : %d device%s", - req->socket, nrep, (nrep > 1) ? "s" : ""); - if(write_or_buffer(req, rbuf, rp - rbuf) < 0) { - syslog(LOG_ERR, "(s=%d) write: %m", req->socket); - goto error; - } - p += l; - break; - case MINISSDPD_SUBMIT: /* submit service */ - newserv = malloc(sizeof(struct service)); - if(!newserv) { - syslog(LOG_ERR, "cannot allocate memory"); - goto error; - } - memset(newserv, 0, sizeof(struct service)); /* set pointers to NULL */ - if(containsForbiddenChars(p, l)) { - syslog(LOG_ERR, "bad request (st contains forbidden chars)"); - goto error; - } - newserv->st = malloc(l + 1); - if(!newserv->st) { - syslog(LOG_ERR, "cannot allocate memory"); - goto error; - } - memcpy(newserv->st, p, l); - newserv->st[l] = '\0'; - p += l; - if(p >= buf + n) { - syslog(LOG_WARNING, "bad request (missing usn)"); - goto error; - } - DECODELENGTH_CHECKLIMIT(l, p, buf + n); - if(l > (unsigned)(buf+n-p)) { - syslog(LOG_WARNING, "bad request (length encoding)"); - goto error; - } - if(containsForbiddenChars(p, l)) { - syslog(LOG_ERR, "bad request (usn contains forbidden chars)"); - goto error; - } - syslog(LOG_INFO, "usn='%.*s'", l, p); - newserv->usn = malloc(l + 1); - if(!newserv->usn) { - syslog(LOG_ERR, "cannot allocate memory"); - goto error; - } - memcpy(newserv->usn, p, l); - newserv->usn[l] = '\0'; - p += l; - DECODELENGTH_CHECKLIMIT(l, p, buf + n); - if(l > (unsigned)(buf+n-p)) { - syslog(LOG_WARNING, "bad request (length encoding)"); - goto error; - } - if(containsForbiddenChars(p, l)) { - syslog(LOG_ERR, "bad request (server contains forbidden chars)"); - goto error; - } - syslog(LOG_INFO, "server='%.*s'", l, p); - newserv->server = malloc(l + 1); - if(!newserv->server) { - syslog(LOG_ERR, "cannot allocate memory"); - goto error; - } - memcpy(newserv->server, p, l); - newserv->server[l] = '\0'; - p += l; - DECODELENGTH_CHECKLIMIT(l, p, buf + n); - if(l > (unsigned)(buf+n-p)) { - syslog(LOG_WARNING, "bad request (length encoding)"); - goto error; - } - if(containsForbiddenChars(p, l)) { - syslog(LOG_ERR, "bad request (location contains forbidden chars)"); - goto error; - } - syslog(LOG_INFO, "location='%.*s'", l, p); - newserv->location = malloc(l + 1); - if(!newserv->location) { - syslog(LOG_ERR, "cannot allocate memory"); - goto error; - } - memcpy(newserv->location, p, l); - newserv->location[l] = '\0'; - p += l; - /* look in service list for duplicate */ - for(serv = servicelisthead.lh_first; - serv; - serv = serv->entries.le_next) { - if(0 == strcmp(newserv->usn, serv->usn) - && 0 == strcmp(newserv->st, serv->st)) { - syslog(LOG_INFO, "Service already in the list. Updating..."); - free(newserv->st); - free(newserv->usn); - free(serv->server); - serv->server = newserv->server; - free(serv->location); - serv->location = newserv->location; - free(newserv); - newserv = NULL; - return (p - buf); - } - } - /* Inserting new service */ - LIST_INSERT_HEAD(&servicelisthead, newserv, entries); - sendNotifications(NOTIF_NEW, NULL, newserv); - newserv = NULL; - break; - case MINISSDPD_NOTIF: /* switch socket to notify */ - rbuf[0] = '\0'; - if(write_or_buffer(req, rbuf, 1) < 0) { - syslog(LOG_ERR, "(s=%d) write: %m", req->socket); - goto error; - } - req->is_notify = 1; - p += l; - break; - default: - syslog(LOG_WARNING, "Unknown request type %d", type); - rbuf[0] = '\0'; - if(write_or_buffer(req, rbuf, 1) < 0) { - syslog(LOG_ERR, "(s=%d) write: %m", req->socket); - goto error; - } - } - return (p - buf); -error: - if(newserv) { - free(newserv->st); - free(newserv->usn); - free(newserv->server); - free(newserv->location); - free(newserv); - newserv = NULL; - } - return -1; -} - -static volatile sig_atomic_t quitting = 0; -/* SIGTERM signal handler */ -static void -sigterm(int sig) -{ - (void)sig; - /*int save_errno = errno;*/ - /*signal(sig, SIG_IGN);*/ -#if 0 - /* calling syslog() is forbidden in a signal handler according to - * signal(3) */ - syslog(LOG_NOTICE, "received signal %d, good-bye", sig); -#endif - quitting = 1; - /*errno = save_errno;*/ -} - -#define PORT 1900 -#define XSTR(s) STR(s) -#define STR(s) #s -#define UPNP_MCAST_ADDR "239.255.255.250" -/* for IPv6 */ -#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */ -#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */ - -/* send the M-SEARCH request for devices - * either all devices (third argument is NULL or "*") or a specific one */ -static void ssdpDiscover(int s, int ipv6, const char * search) -{ - static const char MSearchMsgFmt[] = - "M-SEARCH * HTTP/1.1\r\n" - "HOST: %s:" XSTR(PORT) "\r\n" - "ST: %s\r\n" - "MAN: \"ssdp:discover\"\r\n" - "MX: %u\r\n" - "\r\n"; - char bufr[512]; - int n; - int mx = 3; - int linklocal = 1; - struct sockaddr_storage sockudp_w; - - { - n = snprintf(bufr, sizeof(bufr), - MSearchMsgFmt, - ipv6 ? - (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") - : UPNP_MCAST_ADDR, - (search ? search : "ssdp:all"), mx); - memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); - if(ipv6) { - struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; - p->sin6_family = AF_INET6; - p->sin6_port = htons(PORT); - inet_pton(AF_INET6, - linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, - &(p->sin6_addr)); - } else { - struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; - p->sin_family = AF_INET; - p->sin_port = htons(PORT); - p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); - } - - n = sendto_or_schedule(s, bufr, n, 0, (const struct sockaddr *)&sockudp_w, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - if (n < 0) { - syslog(LOG_ERR, "%s: sendto: %m", __func__); - } - } -} - -/* main(): program entry point */ -int main(int argc, char * * argv) -{ - int ret = 0; - int pid; - struct sigaction sa; - char buf[1500]; - ssize_t n; - int s_ssdp = -1; /* udp socket receiving ssdp packets */ -#ifdef ENABLE_IPV6 - int s_ssdp6 = -1; /* udp socket receiving ssdp packets IPv6*/ -#else /* ENABLE_IPV6 */ -#define s_ssdp6 (-1) -#endif /* ENABLE_IPV6 */ - int s_unix = -1; /* unix socket communicating with clients */ - int s_ifacewatch = -1; /* socket to receive Route / network interface config changes */ - struct reqelem * req; - struct reqelem * reqnext; - fd_set readfds; - fd_set writefds; - struct timeval now; - int max_fd; - struct lan_addr_s * lan_addr; - int i; - const char * sockpath = "/var/run/minissdpd.sock"; - const char * pidfilename = "/var/run/minissdpd.pid"; - int debug_flag = 0; -#ifdef ENABLE_IPV6 - int ipv6 = 0; -#endif /* ENABLE_IPV6 */ - int deltadev = 0; - struct sockaddr_in sendername; - socklen_t sendername_len; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 sendername6; - socklen_t sendername6_len; -#endif /* ENABLE_IPV6 */ - unsigned char ttl = 2; /* UDA says it should default to 2 */ - const char * searched_device = NULL; /* if not NULL, search/filter a specific device type */ - - LIST_INIT(&reqlisthead); - LIST_INIT(&servicelisthead); - LIST_INIT(&lan_addrs); - /* process command line */ - for(i=1; i= argc) { - fprintf(stderr, "option %s needs an argument.\n", argv[i]); - break; - } - if(0==strcmp(argv[i], "-i")) { - lan_addr = malloc(sizeof(struct lan_addr_s)); - if(lan_addr == NULL) { - fprintf(stderr, "malloc(%d) FAILED\n", (int)sizeof(struct lan_addr_s)); - break; - } - if(parselanaddr(lan_addr, argv[++i]) != 0) { - fprintf(stderr, "can't parse \"%s\" as a valid address or interface name\n", argv[i]); - free(lan_addr); - } else { - LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); - } - } else if(0==strcmp(argv[i], "-s")) - sockpath = argv[++i]; - else if(0==strcmp(argv[i], "-p")) - pidfilename = argv[++i]; - else if(0==strcmp(argv[i], "-t")) - ttl = (unsigned char)atoi(argv[++i]); - else if(0==strcmp(argv[i], "-f")) - searched_device = argv[++i]; - else - fprintf(stderr, "unknown commandline option %s.\n", argv[i]); - } - } - if(lan_addrs.lh_first == NULL) - { - fprintf(stderr, - "Usage: %s [-d] " -#ifdef ENABLE_IPV6 - "[-6] " -#endif /* ENABLE_IPV6 */ - "[-s socket] [-p pidfile] [-t TTL] " - "[-f device] " - "-i [-i ] ...\n", - argv[0]); - fprintf(stderr, - "\n is either an IPv4 address with mask such as\n" - " 192.168.1.42/255.255.255.0, or an interface name such as eth0.\n"); - fprintf(stderr, - "\n By default, socket will be open as %s\n" - " and pid written to file %s\n", - sockpath, pidfilename); - return 1; - } - - /* open log */ - openlog("minissdpd", - LOG_CONS|LOG_PID|(debug_flag?LOG_PERROR:0), - LOG_MINISSDPD); - if(!debug_flag) /* speed things up and ignore LOG_INFO and LOG_DEBUG */ - setlogmask(LOG_UPTO(LOG_NOTICE)); - - if(checkforrunning(pidfilename) < 0) - { - syslog(LOG_ERR, "MiniSSDPd is already running. EXITING"); - return 1; - } - - upnp_bootid = (unsigned int)time(NULL); - - /* set signal handlers */ - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = sigterm; - if(sigaction(SIGTERM, &sa, NULL)) - { - syslog(LOG_ERR, "Failed to set SIGTERM handler. EXITING"); - ret = 1; - goto quit; - } - if(sigaction(SIGINT, &sa, NULL)) - { - syslog(LOG_ERR, "Failed to set SIGINT handler. EXITING"); - ret = 1; - goto quit; - } - /* open route/interface config changes socket */ - s_ifacewatch = OpenAndConfInterfaceWatchSocket(); - /* open UDP socket(s) for receiving SSDP packets */ - s_ssdp = OpenAndConfSSDPReceiveSocket(0, ttl); - if(s_ssdp < 0) - { - syslog(LOG_ERR, "Cannot open socket for receiving SSDP messages, exiting"); - ret = 1; - goto quit; - } -#ifdef ENABLE_IPV6 - if(ipv6) { - s_ssdp6 = OpenAndConfSSDPReceiveSocket(1, ttl); - if(s_ssdp6 < 0) - { - syslog(LOG_ERR, "Cannot open socket for receiving SSDP messages (IPv6), exiting"); - ret = 1; - goto quit; - } - } -#endif /* ENABLE_IPV6 */ - /* Open Unix socket to communicate with other programs on - * the same machine */ - s_unix = OpenUnixSocket(sockpath); - if(s_unix < 0) - { - syslog(LOG_ERR, "Cannot open unix socket for communicating with clients. Exiting"); - ret = 1; - goto quit; - } - - /* drop privileges */ -#if 0 - /* if we drop privileges, how to unlink(/var/run/minissdpd.sock) ? */ - if(getuid() == 0) { - struct passwd * user; - struct group * group; - user = getpwnam("nobody"); - if(!user) { - syslog(LOG_ERR, "getpwnam(\"%s\") : %m", "nobody"); - ret = 1; - goto quit; - } - group = getgrnam("nogroup"); - if(!group) { - syslog(LOG_ERR, "getgrnam(\"%s\") : %m", "nogroup"); - ret = 1; - goto quit; - } - if(setgid(group->gr_gid) < 0) { - syslog(LOG_ERR, "setgit(%d) : %m", group->gr_gid); - ret = 1; - goto quit; - } - if(setuid(user->pw_uid) < 0) { - syslog(LOG_ERR, "setuid(%d) : %m", user->pw_uid); - ret = 1; - goto quit; - } - } -#endif - - /* daemonize or in any case get pid ! */ - if(debug_flag) - pid = getpid(); - else { -#ifdef USE_DAEMON - if(daemon(0, 0) < 0) - perror("daemon()"); - pid = getpid(); -#else /* USE_DAEMON */ - pid = daemonize(); -#endif /* USE_DAEMON */ - } - - writepidfile(pidfilename, pid); - - /* send M-SEARCH ssdp:all Requests */ - if(s_ssdp >= 0) - ssdpDiscover(s_ssdp, 0, searched_device); - if(s_ssdp6 >= 0) - ssdpDiscover(s_ssdp6, 1, searched_device); - - /* Main loop */ - while(!quitting) { - /* fill readfds fd_set */ - FD_ZERO(&readfds); - FD_ZERO(&writefds); - - FD_SET(s_unix, &readfds); - max_fd = s_unix; - if(s_ssdp >= 0) { - FD_SET(s_ssdp, &readfds); - SET_MAX(max_fd, s_ssdp); - } -#ifdef ENABLE_IPV6 - if(s_ssdp6 >= 0) { - FD_SET(s_ssdp6, &readfds); - SET_MAX(max_fd, s_ssdp6); - } -#endif /* ENABLE_IPV6 */ - if(s_ifacewatch >= 0) { - FD_SET(s_ifacewatch, &readfds); - SET_MAX(max_fd, s_ifacewatch); - } - for(req = reqlisthead.lh_first; req; req = req->entries.le_next) { - if(req->socket >= 0) { - FD_SET(req->socket, &readfds); - SET_MAX(max_fd, req->socket); - } - if(req->output_buffer_len > 0) { - FD_SET(req->socket, &writefds); - SET_MAX(max_fd, req->socket); - } - } - gettimeofday(&now, NULL); - i = get_sendto_fds(&writefds, &max_fd, &now); - /* select call */ - if(select(max_fd + 1, &readfds, &writefds, 0, 0) < 0) { - if(errno != EINTR) { - syslog(LOG_ERR, "select: %m"); - break; /* quit */ - } - continue; /* try again */ - } - if(try_sendto(&writefds) < 0) { - syslog(LOG_ERR, "try_sendto: %m"); - break; - } -#ifdef ENABLE_IPV6 - if((s_ssdp6 >= 0) && FD_ISSET(s_ssdp6, &readfds)) - { - sendername6_len = sizeof(struct sockaddr_in6); - n = recvfrom(s_ssdp6, buf, sizeof(buf), 0, - (struct sockaddr *)&sendername6, &sendername6_len); - if(n<0) - { - /* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time) - * other errors : log to LOG_ERR */ - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - syslog(LOG_ERR, "recvfrom: %m"); - } - else - { - /* Parse and process the packet received */ - /*printf("%.*s", n, buf);*/ - i = ParseSSDPPacket(s_ssdp6, buf, n, - (struct sockaddr *)&sendername6, searched_device); - syslog(LOG_DEBUG, "** i=%d deltadev=%d **", i, deltadev); - if(i==0 || (i*deltadev < 0)) - { - if(deltadev > 0) - syslog(LOG_NOTICE, "%d new devices added", deltadev); - else if(deltadev < 0) - syslog(LOG_NOTICE, "%d devices removed (good-bye!)", -deltadev); - deltadev = i; - } - else if((i*deltadev) >= 0) - { - deltadev += i; - } - } - } -#endif /* ENABLE_IPV6 */ - if((s_ssdp >= 0) && FD_ISSET(s_ssdp, &readfds)) - { - sendername_len = sizeof(struct sockaddr_in); - n = recvfrom(s_ssdp, buf, sizeof(buf), 0, - (struct sockaddr *)&sendername, &sendername_len); - if(n<0) - { - /* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time) - * other errors : log to LOG_ERR */ - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - syslog(LOG_ERR, "recvfrom: %m"); - } - else - { - /* Parse and process the packet received */ - /*printf("%.*s", n, buf);*/ - i = ParseSSDPPacket(s_ssdp, buf, n, - (struct sockaddr *)&sendername, searched_device); - syslog(LOG_DEBUG, "** i=%d deltadev=%d **", i, deltadev); - if(i==0 || (i*deltadev < 0)) - { - if(deltadev > 0) - syslog(LOG_NOTICE, "%d new devices added", deltadev); - else if(deltadev < 0) - syslog(LOG_NOTICE, "%d devices removed (good-bye!)", -deltadev); - deltadev = i; - } - else if((i*deltadev) >= 0) - { - deltadev += i; - } - } - } - /* processing unix socket requests */ - for(req = reqlisthead.lh_first; req;) { - reqnext = req->entries.le_next; - if((req->socket >= 0) && FD_ISSET(req->socket, &readfds)) { - processRequest(req); - } - if((req->socket >= 0) && FD_ISSET(req->socket, &writefds)) { - write_buffer(req); - } - if(req->socket < 0) { - LIST_REMOVE(req, entries); - free(req->output_buffer); - free(req); - } - req = reqnext; - } - /* processing new requests */ - if(FD_ISSET(s_unix, &readfds)) - { - struct reqelem * tmp; - int s = accept(s_unix, NULL, NULL); - if(s < 0) { - syslog(LOG_ERR, "accept(s_unix): %m"); - } else { - syslog(LOG_INFO, "(s=%d) new request connection", s); - if(!set_non_blocking(s)) - syslog(LOG_WARNING, "Failed to set new socket non blocking : %m"); - tmp = malloc(sizeof(struct reqelem)); - if(!tmp) { - syslog(LOG_ERR, "cannot allocate memory for request"); - close(s); - } else { - memset(tmp, 0, sizeof(struct reqelem)); - tmp->socket = s; - LIST_INSERT_HEAD(&reqlisthead, tmp, entries); - } - } - } - /* processing route/network interface config changes */ - if((s_ifacewatch >= 0) && FD_ISSET(s_ifacewatch, &readfds)) { - ProcessInterfaceWatch(s_ifacewatch, s_ssdp, s_ssdp6); - } - } - syslog(LOG_DEBUG, "quitting..."); - finalize_sendto(); - - /* closing and cleaning everything */ -quit: - if(s_ssdp >= 0) { - close(s_ssdp); - s_ssdp = -1; - } -#ifdef ENABLE_IPV6 - if(s_ssdp6 >= 0) { - close(s_ssdp6); - s_ssdp6 = -1; - } -#endif /* ENABLE_IPV6 */ - if(s_unix >= 0) { - close(s_unix); - s_unix = -1; - if(unlink(sockpath) < 0) - syslog(LOG_ERR, "unlink(%s): %m", sockpath); - } - if(s_ifacewatch >= 0) { - close(s_ifacewatch); - s_ifacewatch = -1; - } - /* empty LAN interface/address list */ - while(lan_addrs.lh_first != NULL) { - lan_addr = lan_addrs.lh_first; - LIST_REMOVE(lan_addrs.lh_first, list); - free(lan_addr); - } - /* empty device list */ - while(devlist != NULL) { - struct device * next = devlist->next; - free(devlist); - devlist = next; - } - /* empty service list */ - while(servicelisthead.lh_first != NULL) { - struct service * serv = servicelisthead.lh_first; - LIST_REMOVE(servicelisthead.lh_first, entries); - free(serv->st); - free(serv->usn); - free(serv->server); - free(serv->location); - free(serv); - } - if(unlink(pidfilename) < 0) - syslog(LOG_ERR, "unlink(%s): %m", pidfilename); - closelog(); - return ret; -} - diff --git a/src/contrib/miniupnp/minissdpd/minissdpd.init.d.script b/src/contrib/miniupnp/minissdpd/minissdpd.init.d.script deleted file mode 100644 index 8b0631b..0000000 --- a/src/contrib/miniupnp/minissdpd/minissdpd.init.d.script +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# $Id: minissdpd.init.d.script,v 1.2 2007/09/23 17:46:57 nanard Exp $ -# MiniUPnP project -# author: Thomas Bernard -# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - -MINISSDPD=/usr/sbin/minissdpd -PIDFILE=/var/run/minissdpd.pid -# get default interface -IF=`route | grep default |awk -- '{ print $8 }'` -ARGS="-i $IF" - -test -f $MINISSDPD || exit 0 - -. /lib/lsb/init-functions - -case "$1" in -start) log_daemon_msg "Starting minissdpd" "minissdpd" - start-stop-daemon --start --quiet --pidfile $PIDFILE \ - --exec $MINISSDPD -- $ARGS $LSBNAMES - log_end_msg $? - ;; -stop) log_daemon_msg "Stopping minissdpd" "minissdpd" - start-stop-daemon --stop --quiet --pidfile $PIDFILE - log_end_msg $? - ;; -restart|reload|force-reload) - log_daemon_msg "Restarting minissdpd" "minissdpd" - start-stop-daemon --stop --retry 5 --quiet --pidfile $PIDFILE - start-stop-daemon --start --quiet --pidfile $PIDFILE \ - --exec $MINISSDPD -- $ARGS $LSBNAMES - log_end_msg $? - ;; -*) log_action_msg "Usage: /etc/init.d/minissdpd {start|stop|restart|reload|force-reload}" - exit 2 - ;; -esac -exit 0 - diff --git a/src/contrib/miniupnp/minissdpd/minissdpdtypes.h b/src/contrib/miniupnp/minissdpd/minissdpdtypes.h deleted file mode 100644 index daf18e3..0000000 --- a/src/contrib/miniupnp/minissdpd/minissdpdtypes.h +++ /dev/null @@ -1,28 +0,0 @@ -/* $Id: minissdpdtypes.h,v 1.1 2014/11/28 16:20:58 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef MINISSDPDTYPES_H_INCLUDED -#define MINISSDPDTYPES_H_INCLUDED - -#include "config.h" -#include -#include -#include - -/* structure and list for storing lan addresses - * with ascii representation and mask */ -struct lan_addr_s { - char ifname[IFNAMSIZ]; /* example: eth0 */ -#ifdef ENABLE_IPV6 - unsigned int index; /* use if_nametoindex() */ -#endif /* ENABLE_IPV6 */ - char str[16]; /* example: 192.168.0.1 */ - struct in_addr addr, mask; /* ip/mask */ - LIST_ENTRY(lan_addr_s) list; -}; -LIST_HEAD(lan_addr_list, lan_addr_s); - -#endif /* MINISSDPDTYPES_H_INCLUDED */ diff --git a/src/contrib/miniupnp/minissdpd/openssdpsocket.c b/src/contrib/miniupnp/minissdpd/openssdpsocket.c deleted file mode 100644 index 702856d..0000000 --- a/src/contrib/miniupnp/minissdpd/openssdpsocket.c +++ /dev/null @@ -1,233 +0,0 @@ -/* $Id: openssdpsocket.c,v 1.17 2015/08/06 14:05:37 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "openssdpsocket.h" -#include "upnputils.h" -#include "minissdpdtypes.h" - -extern struct lan_addr_list lan_addrs; - -/* SSDP ip/port */ -#define SSDP_PORT (1900) -#define SSDP_MCAST_ADDR ("239.255.255.250") -/* Link Local and Site Local SSDP IPv6 multicast addresses */ -#define LL_SSDP_MCAST_ADDR ("FF02::C") -#define SL_SSDP_MCAST_ADDR ("FF05::C") - -/** - * Add the multicast membership for SSDP on the interface - * @param s the socket - * @param ifaddr the IPv4 address or interface name - * @param ipv6 IPv6 or IPv4 - * return -1 on error, 0 on success */ -int -AddDropMulticastMembership(int s, struct lan_addr_s * lan_addr, int ipv6, int drop) -{ - struct ip_mreq imr; /* Ip multicast membership */ -#ifdef ENABLE_IPV6 - struct ipv6_mreq mr; -#else /* ENABLE_IPV6 */ - (void)ipv6; -#endif /* ENABLE_IPV6 */ - - if(s <= 0) - return -1; /* nothing to do */ -#ifdef ENABLE_IPV6 - if(ipv6) - { - memset(&mr, 0, sizeof(mr)); - inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr); - mr.ipv6mr_interface = lan_addr->index; - if(setsockopt(s, IPPROTO_IPV6, drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP, - &mr, sizeof(struct ipv6_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, %s)(%s, %s): %m", - drop ? "IPV6_LEAVE_GROUP" : "IPV6_JOIN_GROUP", - LL_SSDP_MCAST_ADDR, - lan_addr->ifname); - return -1; - } - inet_pton(AF_INET6, SL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr); - if(setsockopt(s, IPPROTO_IPV6, drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP, - &mr, sizeof(struct ipv6_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, %s)(%s, %s): %m", - drop ? "IPV6_LEAVE_GROUP" : "IPV6_JOIN_GROUP", - SL_SSDP_MCAST_ADDR, - lan_addr->ifname); - return -1; - } - } - else - { -#endif /* ENABLE_IPV6 */ - /* setting up imr structure */ - imr.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDR); - imr.imr_interface.s_addr = lan_addr->addr.s_addr; - if(imr.imr_interface.s_addr == INADDR_NONE) - { - syslog(LOG_ERR, "no IPv4 address for interface %s", - lan_addr->ifname); - return -1; - } - - if (setsockopt(s, IPPROTO_IP, drop ? IP_DROP_MEMBERSHIP : IP_ADD_MEMBERSHIP, - (void *)&imr, sizeof(struct ip_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, %s)(%s): %m", - drop ? "IP_DROP_MEMBERSHIP" : "IP_ADD_MEMBERSHIP", - lan_addr->ifname); - return -1; - } -#ifdef ENABLE_IPV6 - } -#endif /* ENABLE_IPV6 */ - - return 0; -} - -int -OpenAndConfSSDPReceiveSocket(int ipv6, unsigned char ttl) -{ - int s; - int opt = 1; - unsigned char loopchar = 0; -#ifdef ENABLE_IPV6 - struct sockaddr_storage sockname; -#else /* ENABLE_IPV6 */ - struct sockaddr_in sockname; -#endif /* ENABLE_IPV6 */ - socklen_t sockname_len; - struct lan_addr_s * lan_addr; - -#ifndef ENABLE_IPV6 - if(ipv6) { - syslog(LOG_ERR, "%s: please compile with ENABLE_IPV6 to allow ipv6=1", __func__); - return -1; - } -#endif /* ENABLE_IPV6 */ - -#ifdef ENABLE_IPV6 - if( (s = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0)) < 0) -#else /* ENABLE_IPV6 */ - if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) -#endif /* ENABLE_IPV6 */ - { - syslog(LOG_ERR, "socket(udp): %m"); - return -1; - } - - if(!set_non_blocking(s)) { - syslog(LOG_WARNING, "Failed to set SSDP socket non blocking : %m"); - } - -#ifdef ENABLE_IPV6 - memset(&sockname, 0, sizeof(struct sockaddr_storage)); - if(ipv6) - { -#ifdef IPV6_V6ONLY - if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - (char *)&opt, sizeof(opt)) < 0) - { - syslog(LOG_WARNING, "setsockopt(IPV6_V6ONLY): %m"); - } -#endif /* IPV6_V6ONLY */ - struct sockaddr_in6 * sa = (struct sockaddr_in6 *)&sockname; - sa->sin6_family = AF_INET6; - sa->sin6_port = htons(SSDP_PORT); - sa->sin6_addr = in6addr_any; - sockname_len = sizeof(struct sockaddr_in6); - } - else - { - struct sockaddr_in * sa = (struct sockaddr_in *)&sockname; - sa->sin_family = AF_INET; - sa->sin_port = htons(SSDP_PORT); -#ifdef SSDP_LISTEN_ON_SPECIFIC_ADDR - if(lan_addrs.lh_first != NULL && lan_addrs.lh_first->list.le_next == NULL) - { - sa->sin_addr.s_addr = lan_addrs.lh_first->addr.s_addr; - if(sa->sin_addr.s_addr == INADDR_NONE) - { - syslog(LOG_ERR, "no IPv4 address for interface %s", - lan_addrs.lh_first->ifname); - close(s); - return -1; - } - } - else -#endif /* SSDP_LISTEN_ON_SPECIFIC_ADDR */ - sa->sin_addr.s_addr = htonl(INADDR_ANY); - sockname_len = sizeof(struct sockaddr_in); - } -#else /* ENABLE_IPV6 */ - memset(&sockname, 0, sizeof(struct sockaddr_in)); - sockname.sin_family = AF_INET; - sockname.sin_port = htons(SSDP_PORT); -#ifdef SSDP_LISTEN_ON_SPECIFIC_ADDR - if(lan_addrs.lh_first != NULL && lan_addrs.lh_first->list.le_next == NULL) - { - sockname.sin_addr.s_addr = lan_addrs.lh_first->addr.s_addr; - if(sockname.sin_addr.s_addr == INADDR_NONE) - { - syslog(LOG_ERR, "no IPv4 address for interface %s", - lan_addrs.lh_first->ifname); - close(s); - return -1; - } - } - else -#endif /* SSDP_LISTEN_ON_SPECIFIC_ADDR */ - sockname.sin_addr.s_addr = htonl(INADDR_ANY); - sockname_len = sizeof(struct sockaddr_in); -#endif /* ENABLE_IPV6 */ - - if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0) - { - syslog(LOG_WARNING, "setsockopt(IP_MULTICAST_LOOP): %m"); - } - - if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) - { - syslog(LOG_WARNING, "setsockopt(IP_MULTICAST_TTL): %m"); - } - - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) - { - syslog(LOG_WARNING, "setsockopt(SO_REUSEADDR): %m"); - } - - if(bind(s, (struct sockaddr *)&sockname, sockname_len) < 0) - { - syslog(LOG_ERR, "bind(udp%s): %m", ipv6 ? "6" : ""); - close(s); - return -1; - } - - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - { - if(AddDropMulticastMembership(s, lan_addr, ipv6, 0) < 0) - { - syslog(LOG_WARNING, "Failed to add IPv%d multicast membership for interface %s.", - ipv6 ? 6 : 4, - lan_addr->ifname); - } - } - - return s; -} diff --git a/src/contrib/miniupnp/minissdpd/openssdpsocket.h b/src/contrib/miniupnp/minissdpd/openssdpsocket.h deleted file mode 100644 index 957a928..0000000 --- a/src/contrib/miniupnp/minissdpd/openssdpsocket.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $Id: openssdpsocket.h,v 1.7 2015/07/21 15:39:38 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef OPENSSDPSOCKET_H_INCLUDED -#define OPENSSDPSOCKET_H_INCLUDED - -#include "minissdpdtypes.h" - -/** - * Open a socket and configure it for receiving SSDP packets - * - * @param ipv6 open INET6 or INET socket - * @param ttl multicast TTL - * @return socket - */ -int -OpenAndConfSSDPReceiveSocket(int ipv6, unsigned char ttl); - -/** - * Add or Drop the multicast membership for SSDP on the interface - * @param s the socket - * @param lan_addr the LAN address or interface name - * @param ipv6 IPv6 or IPv4 - * @param drop 0 to add, 1 to drop - * return -1 on error, 0 on success */ -int -AddDropMulticastMembership(int s, struct lan_addr_s * lan_addr, int ipv6, int drop); - -#endif - diff --git a/src/contrib/miniupnp/minissdpd/printresponse.c b/src/contrib/miniupnp/minissdpd/printresponse.c deleted file mode 100644 index 270c91f..0000000 --- a/src/contrib/miniupnp/minissdpd/printresponse.c +++ /dev/null @@ -1,90 +0,0 @@ -/* $Id: $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas BERNARD - * copyright (c) 2005-2016 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ - -#include -#include "codelength.h" - -#define NOTIF_NEW 1 -#define NOTIF_UPDATE 2 -#define NOTIF_REMOVE 3 - -void printresponse(const unsigned char * resp, int n) -{ - int i, l; - int notif_type; - unsigned int nresp; - const unsigned char * p; - - if(n == 0) - return; - /* first, hexdump the response : */ - for(i = 0; i < n; i += 16) { - printf("%06x | ", i); - for(l = i; l < n && l < (i + 16); l++) - printf("%02x ", resp[l]); - while(l < (i + 16)) { - printf(" "); - l++; - } - printf("| "); - for(l = i; l < n && l < (i + 16); l++) - putchar((resp[l] >= ' ' && resp[l] < 128) ? resp[l] : '.'); - putchar('\n'); - } - for(p = resp; p < resp + n; ) { - /* now parse and display all devices of response */ - nresp = p[0]; /* 1st byte : number of devices in response */ - if(nresp == 0xff) { - /* notification */ - notif_type = p[1]; - nresp = p[2]; - printf("Notification : "); - switch(notif_type) { - case NOTIF_NEW: printf("new\n"); break; - case NOTIF_UPDATE: printf("update\n"); break; - case NOTIF_REMOVE: printf("remove\n"); break; - default: printf("**UNKNOWN**\n"); - } - p += 3; - } else { - p++; - } - for(i = 0; i < (int)nresp; i++) { - if(p >= resp + n) - goto error; - /*l = *(p++);*/ - DECODELENGTH(l, p); - if(p + l > resp + n) - goto error; - printf("%d - %.*s\n", i, l, p); /* URL */ - p += l; - if(p >= resp + n) - goto error; - /*l = *(p++);*/ - DECODELENGTH(l, p); - if(p + l > resp + n) - goto error; - printf(" %.*s\n", l, p); /* ST */ - p += l; - if(p >= resp + n) - goto error; - /*l = *(p++);*/ - DECODELENGTH(l, p); - if(p + l > resp + n) - goto error; - printf(" %.*s\n", l, p); /* USN */ - p += l; - } - } - return; -error: - printf("*** WARNING : TRUNCATED RESPONSE ***\n"); -} - - diff --git a/src/contrib/miniupnp/minissdpd/printresponse.h b/src/contrib/miniupnp/minissdpd/printresponse.h deleted file mode 100644 index f0cf613..0000000 --- a/src/contrib/miniupnp/minissdpd/printresponse.h +++ /dev/null @@ -1,12 +0,0 @@ -/* $Id: $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2016 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef PRINTRESPONSE_H_INCLUDED -#define PRINTRESPONSE_H_INCLUDED - -void printresponse(const unsigned char * resp, int n); - -#endif /* PRINTRESPONSE_H_INCLUDED */ diff --git a/src/contrib/miniupnp/minissdpd/showminissdpdnotif.c b/src/contrib/miniupnp/minissdpd/showminissdpdnotif.c deleted file mode 100644 index c64c830..0000000 --- a/src/contrib/miniupnp/minissdpd/showminissdpdnotif.c +++ /dev/null @@ -1,85 +0,0 @@ -/* $Id: $ */ -/* vim: shiftwidth=4 tabstop=4 noexpandtab - * MiniUPnP project - * (c) 2016 Thomas Bernard - * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "codelength.h" -#include "printresponse.h" - -static volatile sig_atomic_t quitting = 0; - -static void sighandler(int sig) -{ - (void)sig; - quitting = 1; -} - -int main(int argc, char * * argv) -{ - int i; - int s; - struct sockaddr_un addr; - const char * sockpath = "/var/run/minissdpd.sock"; - unsigned char buffer[4096]; - ssize_t n; - const char command5[] = { 0x05, 0x00 }; - struct sigaction sa; - - for(i=0; i -#include "codelength.h" - -int main(int argc, char * * argv) -{ - unsigned char buf[256]; - unsigned char * p; - long i, j; - (void)argc; (void)argv; - - for(i = 1; i < 1000000000; i *= 2) { - /* encode i, decode to j */ - printf("%ld ", i); - p = buf; - CODELENGTH(i, p); - p = buf; - DECODELENGTH(j, p); - if(i != j) { - fprintf(stderr, "Error ! encoded %ld, decoded %ld.\n", i, j); - return 1; - } - } - printf("Test successful\n"); - return 0; -} diff --git a/src/contrib/miniupnp/minissdpd/testminissdpd.c b/src/contrib/miniupnp/minissdpd/testminissdpd.c deleted file mode 100644 index 05ddfd6..0000000 --- a/src/contrib/miniupnp/minissdpd/testminissdpd.c +++ /dev/null @@ -1,196 +0,0 @@ -/* $Id: testminissdpd.c,v 1.14 2016/03/01 17:49:51 nanard Exp $ */ -/* Project : miniupnp - * website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * Author : Thomas BERNARD - * copyright (c) 2005-2018 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "codelength.h" -#include "printresponse.h" - -void printversion(const unsigned char * resp, int n) -{ - int l; - const unsigned char * p; - - p = resp; - DECODELENGTH(l, p); - if(resp + n < p + l) { - printf("get version error\n"); - } - printf("MiniSSDPd version : %.*s\n", l, p); -} - -#define SENDCOMMAND(command, size) write(s, command, size); \ - printf("Command written type=%u\n", (unsigned char)command[0]); - -int connect_unix_socket(const char * sockpath) -{ - int s; - struct sockaddr_un addr; - - s = socket(AF_UNIX, SOCK_STREAM, 0); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path)); - if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { - fprintf(stderr, "connecting to %s : ", addr.sun_path); - perror("connect"); - exit(1); - } - printf("Connected to %s\n", addr.sun_path); - return s; -} - -/* test program for minissdpd */ -int -main(int argc, char * * argv) -{ - const unsigned char command0[] = { 0x00, 0x00 }; - char command1[] = "\x01\x00urn:schemas-upnp-org:device:InternetGatewayDevice"; - char command2[] = "\x02\x00uuid:fc4ec57e-b051-11db-88f8-0060085db3f6::upnp:rootdevice"; - const unsigned char command3[] = { 0x03, 0x00 }; - /* old versions of minissdpd would reject a command with - * a zero length string argument */ - char command3compat[] = "\x03\x00ssdp:all"; - char command4[] = "\x04\x00test:test:test"; - const unsigned char bad_command[] = { 0xff, 0xff }; - const unsigned char overflow[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - const unsigned char command5[] = { 0x05, 0x00 }; - const unsigned char bad_command4[] = { 0x04, 0x01, 0x60, 0x8f, 0xff, 0xff, 0xff, 0x7f}; - int s; - int i; - void * tmp; - unsigned char * resp = NULL; - size_t respsize = 0; - unsigned char buf[4096]; - ssize_t n; - int total = 0; - const char * sockpath = "/var/run/minissdpd.sock"; - - for(i=0; i 0) { - printversion(buf, n); - } else { - printf("Command 0 (get version) not supported\n"); - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(command1, sizeof(command1) - 1); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(command2, sizeof(command2) - 1); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - buf[0] = 0; /* Slight hack for printing num devices when 0 */ - n = SENDCOMMAND(command3, sizeof(command3)); - n = read(s, buf, sizeof(buf)); - if(n == 0) { - printf("command3 failed, testing compatible one\n"); - close(s); - s = connect_unix_socket(sockpath); - n = SENDCOMMAND(command3compat, sizeof(command3compat) - 1); - n = read(s, buf, sizeof(buf)); - } - printf("Response received %d bytes\n", (int)n); - printf("Number of devices %d\n", (int)buf[0]); - while(n > 0) { - tmp = realloc(resp, respsize + n); - if(tmp == NULL) { - fprintf(stderr, "memory allocation error\n"); - break; - } - resp = tmp; - respsize += n; - if (n > 0) { - memcpy(resp + total, buf, n); - total += n; - } - if (n < (ssize_t)sizeof(buf)) { - break; - } - - n = read(s, buf, sizeof(buf)); - printf("response received %d bytes\n", (int)n); - } - if(resp != NULL) { - printresponse(resp, total); - free(resp); - resp = NULL; - } - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(command4, sizeof(command4)); - /* no response for request type 4 */ - - n = SENDCOMMAND(bad_command, sizeof(bad_command)); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(overflow, sizeof(overflow)); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(command5, sizeof(command5)); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - if(n == 0) { - close(s); - s = connect_unix_socket(sockpath); - } - - n = SENDCOMMAND(bad_command4, sizeof(bad_command4)); - n = read(s, buf, sizeof(buf)); - printf("Response received %d bytes\n", (int)n); - printresponse(buf, n); - - close(s); - return 0; -} diff --git a/src/contrib/miniupnp/minissdpd/testminissdpd.sh b/src/contrib/miniupnp/minissdpd/testminissdpd.sh deleted file mode 100644 index 66b41fc..0000000 --- a/src/contrib/miniupnp/minissdpd/testminissdpd.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# $Id: testminissdpd.sh,v 1.8 2017/04/21 11:57:59 nanard Exp $ -# (c) 2017 Thomas Bernard - -OS=`uname -s` -IF=lo -if [ "$OS" = "Darwin" ] || [ "$OS" = "OpenBSD" ] || [ "$OS" = "SunOS" ] || [ "$OS" = "FreeBSD" ] ; then - IF=lo0 -fi -# if set, 1st argument is network interface -if [ -n "$1" ] ; then - IF=$1 -fi -SOCKET=`mktemp -t minissdpdsocketXXXXXX` -PID="${SOCKET}.pid" -./minissdpd -s $SOCKET -p $PID -i $IF || exit 1 -./testminissdpd -s $SOCKET || exit 2 -kill `cat $PID` diff --git a/src/contrib/miniupnp/minissdpd/testminissdpdnotif.sh b/src/contrib/miniupnp/minissdpd/testminissdpdnotif.sh deleted file mode 100644 index 2099ea6..0000000 --- a/src/contrib/miniupnp/minissdpd/testminissdpdnotif.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# $Id: $ -# (c) 2016 Thomas Bernard - -OS=`uname -s` -IF=lo -if [ "$OS" = "Darwin" ] || [ "$OS" = "SunOS" ] ; then - IF=lo0 -fi -# if set, 1st argument is network interface -if [ -n "$1" ] ; then - IF=$1 -fi - -# trap sigint in the script so CTRL-C interrupts the running program, -# not the script -trap 'echo SIGINT' INT - -SOCKET=`mktemp -t minissdpdsocketXXXXXX` -PID="${SOCKET}.pid" -./minissdpd -s $SOCKET -p $PID -i $IF || exit 1 -sleep .5 -echo "minissdpd process id `cat $PID`" -./showminissdpdnotif -s $SOCKET -echo "showminissdpdnotif returned $?" -kill `cat $PID` diff --git a/src/contrib/miniupnp/minissdpd/upnputils.c b/src/contrib/miniupnp/minissdpd/upnputils.c deleted file mode 100644 index a207cc2..0000000 --- a/src/contrib/miniupnp/minissdpd/upnputils.c +++ /dev/null @@ -1,172 +0,0 @@ -/* $Id: upnputils.c,v 1.2 2014/11/28 16:20:58 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef AF_LINK -#include -#endif - -#include "upnputils.h" -#include "getroute.h" -#include "minissdpdtypes.h" - -extern struct lan_addr_list lan_addrs; - -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size) -{ - char buffer[64]; - unsigned short port = 0; - int n = -1; - - switch(addr->sa_family) - { - case AF_INET6: - inet_ntop(addr->sa_family, - &((struct sockaddr_in6 *)addr)->sin6_addr, - buffer, sizeof(buffer)); - port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - n = snprintf(str, size, "[%s]:%hu", buffer, port); - break; - case AF_INET: - inet_ntop(addr->sa_family, - &((struct sockaddr_in *)addr)->sin_addr, - buffer, sizeof(buffer)); - port = ntohs(((struct sockaddr_in *)addr)->sin_port); - n = snprintf(str, size, "%s:%hu", buffer, port); - break; -#ifdef AF_LINK -#if defined(__sun) - /* solaris does not seem to have link_ntoa */ - /* #define link_ntoa _link_ntoa */ -#define link_ntoa(x) "dummy-link_ntoa" -#endif - case AF_LINK: - { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)addr; - n = snprintf(str, size, "index=%hu type=%d %s", - sdl->sdl_index, sdl->sdl_type, - link_ntoa(sdl)); - } - break; -#endif - default: - n = snprintf(str, size, "unknown address family %d", addr->sa_family); -#if 0 - n = snprintf(str, size, "unknown address family %d " - "%02x %02x %02x %02x %02x %02x %02x %02x", - addr->sa_family, - addr->sa_data[0], addr->sa_data[1], (unsigned)addr->sa_data[2], addr->sa_data[3], - addr->sa_data[4], addr->sa_data[5], (unsigned)addr->sa_data[6], addr->sa_data[7]); -#endif - } - return n; -} - - -int -set_non_blocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if(flags < 0) - return 0; - if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) - return 0; - return 1; -} - -struct lan_addr_s * -get_lan_for_peer(const struct sockaddr * peer) -{ - struct lan_addr_s * lan_addr = NULL; -#ifdef DEBUG - char dbg_str[64]; -#endif /* DEBUG */ - -#ifdef ENABLE_IPV6 - if(peer->sa_family == AF_INET6) - { - struct sockaddr_in6 * peer6 = (struct sockaddr_in6 *)peer; - if(IN6_IS_ADDR_V4MAPPED(&peer6->sin6_addr)) - { - struct in_addr peer_addr; - memcpy(&peer_addr, &peer6->sin6_addr.s6_addr[12], 4); - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - if( (peer_addr.s_addr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) - break; - } - } - else - { - int index = -1; - if(peer6->sin6_scope_id > 0) - index = (int)peer6->sin6_scope_id; - else - { - if(get_src_for_route_to(peer, NULL, NULL, &index) < 0) - return NULL; - } - syslog(LOG_DEBUG, "%s looking for LAN interface index=%d", - "get_lan_for_peer()", index); - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - syslog(LOG_DEBUG, - "ifname=%s index=%u str=%s addr=%08x mask=%08x", - lan_addr->ifname, lan_addr->index, - lan_addr->str, - ntohl(lan_addr->addr.s_addr), - ntohl(lan_addr->mask.s_addr)); - if(index == (int)lan_addr->index) - break; - } - } - } - else if(peer->sa_family == AF_INET) - { -#endif /* ENABLE_IPV6 */ - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - if( (((const struct sockaddr_in *)peer)->sin_addr.s_addr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) - break; - } -#ifdef ENABLE_IPV6 - } -#endif /* ENABLE_IPV6 */ - -#ifdef DEBUG - sockaddr_to_string(peer, dbg_str, sizeof(dbg_str)); - if(lan_addr) { - syslog(LOG_DEBUG, "%s: %s found in LAN %s %s", - "get_lan_for_peer()", dbg_str, - lan_addr->ifname, lan_addr->str); - } else { - syslog(LOG_DEBUG, "%s: %s not found !", "get_lan_for_peer()", - dbg_str); - } -#endif /* DEBUG */ - return lan_addr; -} - diff --git a/src/contrib/miniupnp/minissdpd/upnputils.h b/src/contrib/miniupnp/minissdpd/upnputils.h deleted file mode 100644 index 4072eb0..0000000 --- a/src/contrib/miniupnp/minissdpd/upnputils.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $Id: upnputils.h,v 1.2 2014/11/28 16:20:07 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPUTILS_H_INCLUDED -#define UPNPUTILS_H_INCLUDED - -/** - * convert a struct sockaddr to a human readable string. - * [ipv6]:port or ipv4:port - * return the number of characters used (as snprintf) - */ -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size); - -/** - * set the file description as non blocking - * return 0 in case of failure, 1 in case of success - */ -int -set_non_blocking(int fd); - -/** - * get the LAN which the peer belongs to - */ -struct lan_addr_s * -get_lan_for_peer(const struct sockaddr * peer); - -/** - * define portability macros - */ -#if defined(__sun) -static __inline size_t _sa_len(const struct sockaddr *addr) -{ - if (addr->sa_family == AF_INET) - return (sizeof(struct sockaddr_in)); - else if (addr->sa_family == AF_INET6) - return (sizeof(struct sockaddr_in6)); - else - return (sizeof(struct sockaddr)); -} -# define SA_LEN(sa) (_sa_len(sa)) -#else -#if !defined(SA_LEN) -# define SA_LEN(sa) ((sa)->sa_len) -#endif -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnp.podspec b/src/contrib/miniupnp/miniupnp.podspec deleted file mode 100644 index 1a8bd71..0000000 --- a/src/contrib/miniupnp/miniupnp.podspec +++ /dev/null @@ -1,54 +0,0 @@ -Pod::Spec.new do |spec| - spec.name = "miniupnp" - spec.summary = "Mini UPnP client" - spec.homepage = 'http://miniupnp.free.fr/' - spec.authors = "The MiniUPnP Authors" - spec.license = { type: "BSD", file: "miniupnpc/LICENSE" } - - spec.version = "2.0.0.2" - spec.source = { - git: 'https://github.com/cpp-ethereum-ios/miniupnp.git', - tag: "v#{spec.version}" - } - - spec.platform = :ios - spec.ios.deployment_target = '8.0' - - spec.prepare_command = <<-CMD - build_for_ios() { - build_for_architecture iphoneos armv7 arm-apple-darwin - build_for_architecture iphonesimulator i386 i386-apple-darwin - build_for_architecture iphoneos arm64 arm-apple-darwin - build_for_architecture iphonesimulator x86_64 x86_64-apple-darwin - create_universal_library - } - - build_for_architecture() { - PLATFORM=$1 - ARCH=$2 - HOST=$3 - SDKPATH=`xcrun -sdk $PLATFORM --show-sdk-path` - PREFIX="build-ios/$ARCH" - mkdir -p "$PREFIX" - xcrun -sdk $PLATFORM make clean - xcrun -sdk $PLATFORM make -j 16 install \ - PREFIX="$PREFIX" \ - CC=`xcrun -sdk $PLATFORM -find cc` \ - CFLAGS="-arch $ARCH -isysroot $SDKPATH" \ - LIBTOOL=`xcrun -sdk $PLATFORM -find libtool` \ - LDFLAGS="-arch $ARCH -headerpad_max_install_names" - } - - create_universal_library() { - lipo -create -output libminiupnpc.dylib \ - build-ios/{armv7,arm64,i386,x86_64}/usr/lib/libminiupnpc.dylib - install_name_tool -id "@rpath/libminiupnpc.dylib" libminiupnpc.dylib - } - - cd miniupnpc - build_for_ios - CMD - - spec.source_files = "miniupnpc/build-ios/armv7/usr/include/**/*.h" - spec.ios.vendored_libraries = "miniupnpc/libminiupnpc.dylib" -end diff --git a/src/contrib/miniupnp/miniupnpc-async/.gitignore b/src/contrib/miniupnp/miniupnpc-async/.gitignore deleted file mode 100644 index 7a67161..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.a -*.o -testasync diff --git a/src/contrib/miniupnp/miniupnpc-async/Changelog.txt b/src/contrib/miniupnp/miniupnpc-async/Changelog.txt deleted file mode 100644 index 649a120..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/Changelog.txt +++ /dev/null @@ -1,4 +0,0 @@ -$Id: Changelog.txt,v 1.1 2009/11/12 14:04:33 nanard Exp $ - -initial version... - diff --git a/src/contrib/miniupnp/miniupnpc-async/Makefile b/src/contrib/miniupnp/miniupnpc-async/Makefile deleted file mode 100644 index ee75a58..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/Makefile +++ /dev/null @@ -1,115 +0,0 @@ -# $Id: Makefile,v 1.12 2017/05/26 11:01:37 nanard Exp $ -# MiniUPnP Project -# http://miniupnp.free.fr/ -# (c) 2005-2017 Thomas Bernard -# to install use : -# $ PREFIX=/tmp/dummylocation make install -# or -# $ INSTALLPREFIX=/usr/local make install -# or -# make install (will go to /usr/bin, /usr/lib, etc...) -OS = $(shell $(CC) -dumpmachine) - -CC ?= gcc -#AR = gar -CFLAGS = -O0 -g -DDEBUG -#CFLAGS = -O -CFLAGS += -fPIC -CFLAGS += -ansi -CFLAGS += -Wall -W -CFLAGS += -D_BSD_SOURCE -ifeq (, $(findstring darwin, $(OS))$(findstring freebsd, $(OS))) -#CFLAGS += -D_POSIX_C_SOURCE=200112L -CFLAGS += -D_XOPEN_SOURCE=600 -endif -CFLAGS += -DUPNPC_USE_SELECT -INSTALL = install - -#following libs are needed on Solaris -ifneq (, $(findstring sun, $(OS))) - LDLIBS += -lsocket -lnsl -lresolv - CFLAGS += -D__EXTENSIONS__ -endif - -# APIVERSION is used to build SONAME -APIVERSION = 0 - -SRCS = miniupnpc-async.c parsessdpreply.c \ - upnputils.c igd_desc_parse.c minixml.c \ - upnpreplyparse.c \ - testasync.c - -LIBOBJS = miniupnpc-async.o parsessdpreply.o \ - upnputils.o igd_desc_parse.o minixml.o \ - upnpreplyparse.o - -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -# HEADERS to install -HEADERS = miniupnpc-async.h -LIBRARY = libminiupnpc-async.a -SHAREDLIBRARY = libminiupnpc-async.so -SONAME = $(SHAREDLIBRARY).$(APIVERSION) -EXECUTABLES = testasync - -INSTALLPREFIX ?= $(PREFIX)/usr -INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc -INSTALLDIRLIB = $(INSTALLPREFIX)/lib -INSTALLDIRBIN = $(INSTALLPREFIX)/bin - -.PHONY: install clean depend all installpythonmodule - -all: $(LIBRARY) $(EXECUTABLES) - -pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py - python setup.py build - touch $@ - -installpythonmodule: pythonmodule - python setup.py install - -clean: - $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) - # clean python stuff - $(RM) pythonmodule - $(RM) -r build/ dist/ - #python setup.py clean - -install: $(LIBRARY) $(SHAREDLIBRARY) - $(INSTALL) -d $(INSTALLDIRINC) - $(INSTALL) -m 644 $(HEADERS) $(INSTALLDIRINC) - $(INSTALL) -d $(INSTALLDIRLIB) - $(INSTALL) -m 644 $(LIBRARY) $(INSTALLDIRLIB) - $(INSTALL) -m 644 $(SHAREDLIBRARY) $(INSTALLDIRLIB)/$(SONAME) - $(INSTALL) -d $(INSTALLDIRBIN) - $(INSTALL) -m 755 $(EXECUTABLES) $(INSTALLDIRBIN) - ln -fs $(SONAME) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) - -cleaninstall: - $(RM) -r $(INSTALLDIRINC) - $(RM) $(INSTALLDIRLIB)/$(LIBRARY) - $(RM) $(INSTALLDIRLIB)/$(SHAREDLIBRARY) - -depend: - makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null - -$(LIBRARY): $(LIBOBJS) - $(AR) crs $@ $? - -$(SHAREDLIBRARY): $(LIBOBJS) - $(CC) -shared -Wl,-soname,$(SONAME) -o $@ $^ - -upnpc-static: upnpc.o $(LIBRARY) - $(CC) -o $@ $^ - -upnpc-shared: upnpc.o $(SHAREDLIBRARY) - $(CC) -o $@ $^ - -testasync: testasync.o libminiupnpc-async.a -#testasync: testasync.o -lminiupnpc-async - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -miniupnpc-async.o: miniupnpc-async.h declspec.h parsessdpreply.h upnputils.h -parsessdpreply.o: parsessdpreply.h -testasync.o: miniupnpc-async.h declspec.h diff --git a/src/contrib/miniupnp/miniupnpc-async/README b/src/contrib/miniupnp/miniupnpc-async/README deleted file mode 100644 index 6b097e2..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/README +++ /dev/null @@ -1,10 +0,0 @@ -(c) 2014 Thomas BERNARD -http://miniupnp.free.fr/ -https://github.com/miniupnp/miniupnp - -miniupnpc-async : - proof of concept of a UPnP IGD client using asynchronous socket calls - (ie non blocking sockets) - - To be reimplemented using libevent2 (http://libevent.org/) - diff --git a/src/contrib/miniupnp/miniupnpc-async/config.h b/src/contrib/miniupnp/miniupnpc-async/config.h deleted file mode 100644 index 020ac6e..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/config.h +++ /dev/null @@ -1,5 +0,0 @@ -/* $Id: config.h,v 1.1 2012/05/20 14:58:50 nanard Exp $ */ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ - -#endif diff --git a/src/contrib/miniupnp/miniupnpc-async/declspec.h b/src/contrib/miniupnp/miniupnpc-async/declspec.h deleted file mode 100644 index b804247..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/declspec.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __DECLSPEC_H__ -#define __DECLSPEC_H__ - -#if defined(WIN32) && !defined(STATICLIB) - #ifdef MINIUPNP_EXPORTS - #define LIBSPEC __declspec(dllexport) - #else - #define LIBSPEC __declspec(dllimport) - #endif -#else - #define LIBSPEC -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.c b/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.c deleted file mode 100644 index d2999ad..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include "igd_desc_parse.h" -#include -#include - -/* Start element handler : - * update nesting level counter and copy element name */ -void IGDstartelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - if(l >= MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(datas->cureltname, name, l); - datas->cureltname[l] = '\0'; - datas->level++; - if( (l==7) && !memcmp(name, "service", l) ) { - datas->tmp.controlurl[0] = '\0'; - datas->tmp.eventsuburl[0] = '\0'; - datas->tmp.scpdurl[0] = '\0'; - datas->tmp.servicetype[0] = '\0'; - } -} - -#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) - -/* End element handler : - * update nesting level counter and update parser state if - * service element is parsed */ -void IGDendelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - datas->level--; - /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ - if( (l==7) && !memcmp(name, "service", l) ) - { - if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { - memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) { - memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPConnection:") - || COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANPPPConnection:") ) { - if(datas->first.servicetype[0] == '\0') { - memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); - } else { - memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); - } - } - } -} - -/* Data handler : - * copy data depending on the current element name and state */ -void IGDdata(void * d, const char * data, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - char * dstmember = 0; - /*printf("%2d %s : %.*s\n", - datas->level, datas->cureltname, l, data); */ - if( !strcmp(datas->cureltname, "URLBase") ) - dstmember = datas->urlbase; - else if( !strcmp(datas->cureltname, "presentationURL") ) - dstmember = datas->presentationurl; - else if( !strcmp(datas->cureltname, "serviceType") ) - dstmember = datas->tmp.servicetype; - else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->tmp.controlurl; - else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->tmp.eventsuburl; - else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->tmp.scpdurl; -/* else if( !strcmp(datas->cureltname, "deviceType") ) - dstmember = datas->devicetype_tmp;*/ - if(dstmember) - { - if(l>=MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(dstmember, data, l); - dstmember[l] = '\0'; - } -} - -#ifdef DEBUG -void printIGD(struct IGDdatas * d) -{ - printf("urlbase = '%s'\n", d->urlbase); - printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ - printf(" serviceType = '%s'\n", d->CIF.servicetype); - printf(" controlURL = '%s'\n", d->CIF.controlurl); - printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); - printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); - printf("primary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ - printf(" servicetype = '%s'\n", d->first.servicetype); - printf(" controlURL = '%s'\n", d->first.controlurl); - printf(" eventSubURL = '%s'\n", d->first.eventsuburl); - printf(" SCPDURL = '%s'\n", d->first.scpdurl); - printf("secondary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ - printf(" servicetype = '%s'\n", d->second.servicetype); - printf(" controlURL = '%s'\n", d->second.controlurl); - printf(" eventSubURL = '%s'\n", d->second.eventsuburl); - printf(" SCPDURL = '%s'\n", d->second.scpdurl); - printf("WAN IPv6 Firewall Control :\n"); - /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ - printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); - printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); - printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); - printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.h b/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.h deleted file mode 100644 index 0de546b..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/igd_desc_parse.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef IGD_DESC_PARSE_H_INCLUDED -#define IGD_DESC_PARSE_H_INCLUDED - -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ -#define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas_service { - char controlurl[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl[MINIUPNPC_URL_MAXSIZE]; - char scpdurl[MINIUPNPC_URL_MAXSIZE]; - char servicetype[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ -}; - -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - char presentationurl[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ - struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ - struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ - struct IGDdatas_service IPv6FC; - /* tmp */ - struct IGDdatas_service tmp; -}; - -void IGDstartelt(void *, const char *, int); -void IGDendelt(void *, const char *, int); -void IGDdata(void *, const char *, int); -#ifdef DEBUG -void printIGD(struct IGDdatas *); -#endif /* DEBUG */ - -#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.c b/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.c deleted file mode 100644 index 3d9af3c..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* $Id: miniupnpc-async.c,v 1.19 2014/11/07 12:05:40 nanard Exp $ */ -/* miniupnpc-async - * Copyright (c) 2008-2017, Thomas BERNARD - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef WIN32 -#include -#include -#include -#define PRINT_SOCKET_ERROR printf -#define SOCKET_ERROR GetWSALastError() -#define WOULDBLOCK(err) (err == WSAEWOULDBLOCK) -#else -#include -#include -#define closesocket close -#define PRINT_SOCKET_ERROR perror -#define SOCKET_ERROR errno -#define WOULDBLOCK(err) (err == EAGAIN || err == EWOULDBLOCK) -#endif -#include "miniupnpc-async.h" -#include "parsessdpreply.h" -#include "upnputils.h" -#include "minixml.h" -#include "igd_desc_parse.h" -#include "upnpreplyparse.h" - -#ifndef MIN -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif /* MIN */ - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif /* MAXHOSTNAMELEN */ - -#define SSDP_PORT 1900 -#define SSDP_MCAST_ADDR "239.255.255.250" -#define XSTR(s) STR(s) -#define STR(s) #s - -#ifdef DEBUG -#define debug_printf(...) fprintf(stderr, __VA_ARGS__) -#else -#define debug_printf(...) -#endif - -/* stuctures */ - -struct upnp_args { - const char * elt; - const char * val; -}; - -/* private functions */ - -static int upnpc_connect(upnpc_device_t * p, const char * url); -static int upnpc_send_request(upnpc_device_t * p); - - -/* parse_msearch_reply() - * the last 4 arguments are filled during the parsing : - * - location/locationsize : "location:" field of the SSDP reply packet - * - st/stsize : "st:" field of the SSDP reply packet. - * The strings are NOT null terminated */ -static void -parse_msearch_reply(const char * reply, int size, - const char * * location, unsigned int * locationsize, - const char * * st, unsigned int * stsize) -{ - int a, b, i; - i = 0; /* current character index */ - a = i; /* start of the line */ - b = 0; /* end of the "header" (position of the colon) */ - while(issdp_socket, bufr, n, 0, - (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - if (n < 0) { - int err = SOCKET_ERROR; - if(err == EINTR || WOULDBLOCK(err)) { - debug_printf("upnpc_send_ssdp_msearch: should try again"); - p->state = EUPnPSendSSDP; - return 0; - } - PRINT_SOCKET_ERROR("sendto"); - return -1; - } - p->state = EUPnPReceiveSSDP; - return 0; -} - -static int upnpc_set_root_desc_location(upnpc_device_t * d, const char * location, int locationsize) -{ - char * tmp; - tmp = realloc(d->root_desc_location, locationsize + 1); - if(tmp == 0) { - return -1; - } - memcpy(tmp, location, locationsize); - tmp[locationsize] = '\0'; - d->root_desc_location = tmp; - return 0; -} - -static int upnpc_receive_and_parse_ssdp(upnpc_t * p) -{ - int n; - char bufr[1024]; - n = recv(p->ssdp_socket, bufr, sizeof(bufr), 0); - if (n<0) { - PRINT_SOCKET_ERROR("recv"); - } else if (n==0) { - debug_printf("empty packet received\n"); - } else { - const char * location = NULL; - unsigned int locationsize; - const char * st = NULL; - unsigned int stsize; - debug_printf("%.*s", n, bufr); - parse_msearch_reply(bufr, n, &location, &locationsize, &st, &stsize); - debug_printf("location = '%.*s'\n", locationsize, location); - debug_printf("st = '%.*s'\n", stsize, st); - if(location != NULL) { - upnpc_device_t * dev = p->device_list; - while(dev != NULL) { - if(dev->root_desc_location != NULL - && strlen(dev->root_desc_location) == locationsize - && memcmp(dev->root_desc_location, location, locationsize) == 0) { - debug_printf("device already in list (location='%s')\n", dev->root_desc_location); - return -1; - } - dev = dev->next; - } - dev = calloc(1, sizeof(upnpc_device_t)); - if(dev == NULL) { - p->state = EUPnPError; - return -1; - } - if(upnpc_set_root_desc_location(dev, location, locationsize) < 0) { - free(dev); - p->state = EUPnPError; - return -1; - } - dev->next = p->device_list; - p->device_list = dev; - dev->state = EDevGetDescConnect; - upnpc_connect(dev, dev->root_desc_location); - } else { - /* or do nothing ? */ - p->state = EUPnPError; - } - } - return 0; -} - -static int -parseURL(const char * url, - char * hostname, unsigned short * port, - char * * path, unsigned int * scope_id) -{ - char * p1, *p2, *p3; - if(!url) - return 0; - p1 = strstr(url, "://"); - if(!p1) - return 0; - p1 += 3; - if( (url[0]!='h') || (url[1]!='t') - ||(url[2]!='t') || (url[3]!='p')) - return 0; - memset(hostname, 0, MAXHOSTNAMELEN + 1); - if(*p1 == '[') { - /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ - char * scope; - scope = strchr(p1, '%'); - p2 = strchr(p1, ']'); - if(p2 && scope && scope < p2 && scope_id) { - /* parse scope */ -#ifdef IF_NAMESIZE - char tmp[IF_NAMESIZE]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= IF_NAMESIZE) - l = IF_NAMESIZE - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = if_nametoindex(tmp); - if(*scope_id == 0) { - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); - } -#else - /* under windows, scope is numerical */ - char tmp[8]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= (int)sizeof(tmp)) - l = sizeof(tmp) - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); -#endif - } - p3 = strchr(p1, '/'); - if(p2 && p3) { - p2++; - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - if(*p2 == ':') { - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } else { - *port = 80; - } - *path = p3; - return 1; - } - } - p2 = strchr(p1, ':'); - p3 = strchr(p1, '/'); - if(!p3) - return 0; - if(!p2 || (p2>p3)) { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); - *port = 80; - } else { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - *path = p3; - return 1; -} - -static int upnpc_connect(upnpc_device_t * p, const char * url) -{ - int r; - char hostname[MAXHOSTNAMELEN+1]; - unsigned short port; - char * path; - unsigned int scope_id; - struct sockaddr_in addr; - socklen_t addrlen; - - /*if(p->root_desc_location == 0) { - p->state = EError; - return -1; - }*/ - if(!parseURL(url/*p->root_desc_location*/, hostname, &port, - &path, &scope_id)) { - p->state = EDevError; - return -1; - } - p->http_socket = socket(PF_INET, SOCK_STREAM, 0); - if(p->http_socket < 0) { - PRINT_SOCKET_ERROR("socket"); - p->state = EDevError; - return -1; - } - if(!set_non_blocking(p->http_socket)) { - /* TODO : ERROR */ - } - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - inet_pton(AF_INET, hostname, &(addr.sin_addr)); - addr.sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - do { - r = connect(p->http_socket, (struct sockaddr *)&addr, addrlen); - if(r < 0) { - if(errno == EINPROGRESS) { - /*p->state = EGetDescConnect;*/ - return 0; - } else if(errno != EINTR) { - PRINT_SOCKET_ERROR("connect"); - p->state = EDevError; - return -1; - } - } - } while(r < 0 && errno == EINTR); - if(p->state == EDevGetDescConnect) { - p->state = EDevGetDescRequest; - } else { - p->state = EDevSoapRequest; - } - upnpc_send_request(p); - return 0; -} - -static int upnpc_complete_connect(upnpc_device_t * p) -{ - socklen_t len; - int err; - len = sizeof(err); - if(getsockopt(p->http_socket, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - p->state = EDevError; - return -1; - } - if(err != 0) { - debug_printf("connect failed %d\n", err); - p->state = EDevError; - return -1; - } - if(p->state == EDevGetDescConnect) - p->state = EDevGetDescRequest; - else - p->state = EDevSoapRequest; - upnpc_send_request(p); - return 0; -} - -static int upnpc_send_request(upnpc_device_t * p) -{ - ssize_t n; - static const char reqfmt[] = "GET %s HTTP/1.1\r\n" - "Host: %s:%hu\r\n" - "Connection: Close\r\n" - "User-Agent: MiniUPnPc-async\r\n" - "\r\n"; - - /* retrieve "our" IP address used to connect to the UPnP device */ - p->selfaddrlen = sizeof(struct sockaddr_storage); - if(getsockname(p->http_socket, (struct sockaddr *)&p->selfaddr, &p->selfaddrlen) < 0) { - PRINT_SOCKET_ERROR("getsockname()"); - } - - if(p->http_request == NULL) { - char hostname[MAXHOSTNAMELEN+1]; - unsigned short port; - char * path; - unsigned int scope_id; - int len; - if(!parseURL(p->root_desc_location, hostname, &port, - &path, &scope_id)) { - p->state = EDevError; - return -1; - } - len = snprintf(NULL, 0, reqfmt, path, hostname, port); - p->http_request = malloc(len + 1); - if(p->http_request == NULL) { - p->state = EDevError; - return -1; - } - p->http_request_len = snprintf(p->http_request, len + 1, - reqfmt, path, hostname, port); - p->http_request_sent = 0; - } - n = send(p->http_socket, p->http_request + p->http_request_sent, - p->http_request_len - p->http_request_sent, 0/* flags */); - if(n < 0) { - PRINT_SOCKET_ERROR("send"); - p->state = EDevError; - return -1; - } else { - debug_printf("sent %d bytes\n", (int)n); - /*if(n == 0) { - p->state = EError; - return -1; - }*/ - p->http_request_sent += n; - if(p->http_request_sent >= p->http_request_len) { - /* all bytes sent */ -#if 0 - shutdown(p->http_socket, SHUT_WR); /* some routers don't like that */ -#endif - free(p->http_request); - p->http_request = NULL; - p->http_request_len = 0; - if(p->state == EDevGetDescRequest) - p->state = EDevGetDescResponse; - else - p->state = EDevSoapResponse; - free(p->http_response); - p->http_response = NULL; - p->http_response_received = 0; - p->http_response_end_of_headers = 0; - /* get response */ - } - } - return 0; -} - -static int upnpc_parse_headers(upnpc_device_t * p) -{ - /* search for CR LF CR LF (end of headers) - * recognize also LF LF */ - int i = 0; - while(i < (p->http_response_received-1) && - p->http_response_end_of_headers == 0) { - if(p->http_response[i] == '\r') { - i++; - if(p->http_response[i] == '\n') { - i++; - if(i < p->http_response_received && p->http_response[i] == '\r') { - i++; - if(i < p->http_response_received && p->http_response[i] == '\n') { - p->http_response_end_of_headers = i + 1; - } - } - } - } else if(p->http_response[i] == '\n') { - i++; - if(p->http_response[i] == '\n') { - p->http_response_end_of_headers = i + 1; - } - } - i++; - } - if(p->http_response_end_of_headers != 0) { - int colon = 0; - int linestart = 0; - int valuestart = 0; - p->http_response_code = -1; - for(i = 0; i < p->http_response_end_of_headers - 1; i++) { - if(linestart == 0) { - /* reading HTTP response code on the 1st line */ - if(p->http_response[i] == ' ' && p->http_response_code < 0) - p->http_response_code = 0; - else if(p->http_response[i] >= '0' && p->http_response[i] <= '9') { - p->http_response_code = p->http_response_code * 10 + (p->http_response[i] - '0'); - } else if(p->http_response[i] == ' ') - linestart = 1; - } - if(colon <= linestart && p->http_response[i] == ':') { - colon = i; - while(i < p->http_response_end_of_headers - 1 && - (p->http_response[i+1] == ' ' || p->http_response[i+1] == '\t')) - i++; - valuestart = i + 1; - } else if(p->http_response[i + 1] == '\r' || - p->http_response[i + 1] == '\n') { - if(colon > linestart && valuestart > colon) { - debug_printf("header='%.*s', value='%.*s'\n", - colon-linestart, p->http_response+linestart, - i+1-valuestart, p->http_response+valuestart); - if(0==strncasecmp(p->http_response+linestart, "content-length", colon-linestart)) { - p->http_response_content_length = atoi(p->http_response + valuestart); - debug_printf("Content-Length: %d\n", p->http_response_content_length); - if(p->http_response_content_length < 0) { - debug_printf("Content-Length overflow ? setting to 0\n"); - p->http_response_content_length = 0; - } - } else if(0==strncasecmp(p->http_response+linestart, "transfer-encoding", colon-linestart) - && 0==strncasecmp(p->http_response+valuestart, "chunked", 7)) { - debug_printf("Chunked transfer-encoding !\n"); - p->http_response_chunked = 1; - } - } - /* find next line */ - while((i < p->http_response_received) && - (p->http_response[i]=='\r' || p->http_response[i] == '\n')) - i++; - linestart = i; - colon = linestart; - valuestart = 0; - } - } - } - return 0; -} - -static char * build_url_string(const char * urlbase, const char * root_desc_url, const char * controlurl) -{ - int l, n; - char * s; - const char * base; - char * p; - /* if controlurl is an absolute url, return it */ - if(0 == memcmp("http://", controlurl, 7)) - return strdup(controlurl); - base = (urlbase[0] == '\0') ? root_desc_url : urlbase; - n = strlen(base); - if(n > 7) { - p = strchr(base + 7, '/'); - if(p) - n = p - base; - } - l = n + strlen(controlurl) + 1; - if(controlurl[0] != '/') - l++; - s = malloc(l); - if(s == NULL) return NULL; - memcpy(s, base, n); - if(controlurl[0] != '/') - s[n++] = '/'; - memcpy(s + n, controlurl, l - n); - return s; -} - -static int upnpc_get_response(upnpc_device_t * p) -{ - ssize_t n; - ssize_t count; - char buffer[2048]; - if(p->http_response_content_length > 0) { - count = p->http_response_content_length - + p->http_response_end_of_headers - - p->http_response_received; - if(count > (ssize_t)sizeof(buffer)) count = sizeof(buffer); - } else { - count = sizeof(buffer); - } - debug_printf("recv(..., %d)\n", (int)count); - n = recv(p->http_socket, buffer, count, 0/* flags */); - if(n < 0) { - if(errno == EINTR || WOULDBLOCK(errno)) - return 0; /* try again later */ - PRINT_SOCKET_ERROR("read"); - p->state = EDevError; - return -1; - } else if(n == 0) { - /* receiving finished */ - debug_printf("%.*s\n", p->http_response_received, p->http_response); - close(p->http_socket); - p->http_socket = -1; - /* parse */ - if(p->http_response_end_of_headers == 0) { - upnpc_parse_headers(p); - } - /* TODO : decode chunked transfer-encoding */ - /* parse xml */ - if(p->state == EDevGetDescResponse) { - struct IGDdatas igd; - struct xmlparser parser; - memset(&igd, 0, sizeof(struct IGDdatas)); - memset(&parser, 0, sizeof(struct xmlparser)); - parser.xmlstart = p->http_response + p->http_response_end_of_headers; - parser.xmlsize = p->http_response_received - p->http_response_end_of_headers; - parser.data = &igd; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parsexml(&parser); -#ifdef DEBUG - printIGD(&igd); -#endif /* DEBUG */ - p->control_conn_url = build_url_string(igd.urlbase, p->root_desc_location, igd.first.controlurl); - p->control_cif_url = build_url_string(igd.urlbase, p->root_desc_location, igd.CIF.controlurl); - debug_printf("control_conn_url='%s'\n", p->control_conn_url); - debug_printf("control_cif_url='%s'\n", p->control_cif_url); - } else { - ClearNameValueList(&p->soap_response_data); - ParseNameValue(p->http_response + p->http_response_end_of_headers, - p->http_response_received - p->http_response_end_of_headers, - &p->soap_response_data); - } - free(p->http_response); - p->http_response = NULL; - p->http_response_received = 0; - p->http_response_end_of_headers = 0; - p->state = EDevReady; - } else { - /* receiving in progress */ - debug_printf("received %d bytes:\n%.*s\n", (int)n, (int)n, buffer); - if(p->http_response == NULL) { - p->http_response = malloc(n); - if(p->http_response == NULL) { - debug_printf("failed to malloc %d bytes\n", (int)n); - p->state = EDevError; - return -1; - } - p->http_response_received = n; - memcpy(p->http_response, buffer, n); - } else { - char * tmp = realloc(p->http_response, p->http_response_received + n); - if(tmp == NULL) { - debug_printf("failed to realloc %d bytes\n", (int)(p->http_response_received + n)); - p->state = EDevError; - return -1; - } - p->http_response = tmp; - memcpy(p->http_response + p->http_response_received, buffer, n); - p->http_response_received += n; - } - if(p->http_response_end_of_headers == 0) { - upnpc_parse_headers(p); - } - } - return 0; -} - -#define SOAPPREFIX "s" -#define SERVICEPREFIX "u" -#define SERVICEPREFIX2 'u' - -static int upnpc_build_soap_request(upnpc_device_t * p, const char * url, - const char * service, - const char * action, - const struct upnp_args * args, int arg_count) -{ - char * body; - const char fmt_soap[] = - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" - "%s" - "" - "" - "\r\n"; - int body_len; - const char fmt_http[] = - "POST %s HTTP/1.1\r\n" - "Host: %s%s\r\n" - "User-Agent: MiniUPnPc-async\r\n" - "Content-Length: %d\r\n" - "Content-Type: text/xml\r\n" - "SOAPAction: \"%s#%s\"\r\n" - "Connection: Close\r\n" - "Cache-Control: no-cache\r\n" /* ??? */ - "Pragma: no-cache\r\n" - "\r\n" - "%s"; - char hostname[MAXHOSTNAMELEN+1]; - unsigned short port; - char * path; - unsigned int scope_id; - char portstr[8]; - char * args_xml = NULL; - - if(arg_count > 0) { - int i; - size_t l, n; - for(i = 0, l = 0; i < arg_count; i++) { - /* VAL */ - l += strlen(args[i].elt) * 2 + strlen(args[i].val) + 5; - } - args_xml = malloc(++l); - if(args_xml == NULL) { - p->state = EDevError; - return -1; - } - for(i = 0, n = 0; i < arg_count && n < l; i++) { - /* VAL */ - n += snprintf(args_xml + n, l - n, "<%s>%s", - args[i].elt, args[i].val, args[i].elt); - } - } - - body_len = snprintf(NULL, 0, fmt_soap, action, service, args_xml?args_xml:"", action); - body = malloc(body_len + 1); - if(body == NULL) { - p->state = EDevError; - free(args_xml); - return -1; - } - if(snprintf(body, body_len + 1, fmt_soap, action, service, args_xml?args_xml:"", action) != body_len) { - debug_printf("snprintf() returned strange value...\n"); - } - free(args_xml); - args_xml = NULL; - if(!parseURL(url, hostname, &port, &path, &scope_id)) { - p->state = EDevError; - free(body); - return -1; - } - if(port != 80) - snprintf(portstr, sizeof(portstr), ":%hu", port); - else - portstr[0] = '\0'; - p->http_request_len = snprintf(NULL, 0, fmt_http, - path/*url*/, hostname, portstr, body_len, service, action, body); - free(p->http_request); - p->http_request = malloc(p->http_request_len + 1); - if(snprintf(p->http_request, p->http_request_len + 1, fmt_http, - path/*url*/, hostname, portstr, body_len, service, action, body) != p->http_request_len) { - debug_printf("snprintf() returned strange value...\n"); - } - free(body); - debug_printf("%s", p->http_request); - p->http_request_sent = 0; - return 0; -} - -/* public functions */ -int upnpc_init(upnpc_t * p, const char * multicastif) -{ - int opt = 1; - struct sockaddr_in addr; - if(!p) - return UPNPC_ERR_INVALID_ARGS; - p->state = EUPnPError; - memset(p, 0, sizeof(upnpc_t)); /* clean everything */ - /* open the socket for SSDP */ - p->ssdp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(p->ssdp_socket < 0) { - return UPNPC_ERR_SOCKET_FAILED; - } - /* set REUSEADDR */ -#ifdef WIN32 - if(setsockopt(p->ssdp_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) < 0) { -#else - if(setsockopt(p->ssdp_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { -#endif - /* non fatal error ! */ - } - if(!set_non_blocking(p->ssdp_socket)) { - /* TODO log error */ - } - - /* receive address */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - /*addr.sin_port = htons(SSDP_PORT);*/ - - if(multicastif) { - struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); - addr.sin_addr.s_addr = mc_if.s_addr; - if(setsockopt(p->ssdp_socket, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { - PRINT_SOCKET_ERROR("setsockopt"); - /* non fatal error ! */ - } - } - - /* bind the socket to the ssdp address in order to receive responses */ - if(bind(p->ssdp_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0) { - close(p->ssdp_socket); - return UPNPC_ERR_BIND_FAILED; - } - - p->state = EUPnPInit; - return UPNPC_OK; -} - -int upnpc_finalize(upnpc_t * p) -{ - if(!p) return UPNPC_ERR_INVALID_ARGS; - if(p->ssdp_socket >= 0) { - close(p->ssdp_socket); - p->ssdp_socket = -1; - } - while(p->device_list) { - upnpc_device_t * next = p->device_list->next; - free(p->device_list->root_desc_location); - p->device_list->root_desc_location = NULL; - free(p->device_list->http_request); - p->device_list->http_request = NULL; - free(p->device_list->http_response); - p->device_list->http_response = NULL; - free(p->device_list->control_cif_url); - p->device_list->control_cif_url = NULL; - free(p->device_list->control_conn_url); - p->device_list->control_conn_url = NULL; - if(p->device_list->http_socket >= 0) { - close(p->device_list->http_socket); - p->device_list->http_socket = -1; - } - ClearNameValueList(&p->device_list->soap_response_data); - free(p->device_list); - p->device_list = next; - } - p->state = EUPnPFinalized; - return UPNPC_OK; -} - -int upnpc_get_external_ip_address(upnpc_device_t * p) -{ - upnpc_build_soap_request(p, p->control_conn_url, - "urn:schemas-upnp-org:service:WANIPConnection:1", - "GetExternalIPAddress", NULL, 0); - p->state = EDevSoapConnect; - upnpc_connect(p, p->control_conn_url); - return 0; -} - -int upnpc_get_link_layer_max_rate(upnpc_device_t * p) -{ - upnpc_build_soap_request(p, p->control_cif_url, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", - "GetCommonLinkProperties", NULL, 0); - p->state = EDevSoapConnect; - upnpc_connect(p, p->control_conn_url); - return 0; -} - -int upnpc_add_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - unsigned short int_port, const char * int_client, - const char * proto, const char * description, - unsigned int lease_duration) -{ - struct upnp_args args[8]; - char lease_duration_str[16]; - char int_port_str[8]; - char ext_port_str[8]; - - if(int_client == NULL || int_port == 0 || ext_port == 0 || proto == NULL) - return UPNPC_ERR_INVALID_ARGS; - snprintf(lease_duration_str, sizeof(lease_duration_str), "%u", lease_duration); - snprintf(int_port_str, sizeof(int_port_str), "%hu", int_port); - snprintf(ext_port_str, sizeof(ext_port_str), "%hu", ext_port); - args[0].elt = "NewRemoteHost"; - args[0].val = remote_host?remote_host:""; - args[1].elt = "NewExternalPort"; - args[1].val = ext_port_str; - args[2].elt = "NewProtocol"; - args[2].val = proto; - args[3].elt = "NewInternalPort"; - args[3].val = int_port_str; - args[4].elt = "NewInternalClient"; - args[4].val = int_client; - args[5].elt = "NewEnabled"; - args[5].val = "1"; - args[6].elt = "NewPortMappingDescription"; - args[6].val = description?description:"miniupnpc-async"; - args[7].elt = "NewLeaseDuration"; - args[7].val = lease_duration_str; - upnpc_build_soap_request(p, p->control_conn_url, - "urn:schemas-upnp-org:service:WANIPConnection:1", - "AddPortMapping", - args, 8); - p->state = EDevSoapConnect; - upnpc_connect(p, p->control_conn_url); - return 0; -} - -#ifdef UPNPC_USE_SELECT -int upnpc_select_fds(upnpc_t * p, int * nfds, fd_set * readfds, fd_set * writefds) -{ - upnpc_device_t * d; - int n = 0; - if(!p) return UPNPC_ERR_INVALID_ARGS; - for(d = p->device_list; d != NULL; d = d->next) { - switch(d->state) { - case EDevGetDescConnect: - case EDevGetDescRequest: - case EDevSoapConnect: - case EDevSoapRequest: - FD_SET(d->http_socket, writefds); - if(*nfds < d->http_socket) - *nfds = d->http_socket; - n++; - break; - case EDevGetDescResponse: - case EDevSoapResponse: - FD_SET(d->http_socket, readfds); - if(*nfds < d->http_socket) - *nfds = d->http_socket; - n++; - break; - default: - break; - } - } - - switch(p->state) { - case EUPnPSendSSDP: - FD_SET(p->ssdp_socket, writefds); - if(*nfds < p->ssdp_socket) - *nfds = p->ssdp_socket; - n++; - break; - case EUPnPReceiveSSDP: - default: - /* still receive SSDP responses when processing Description, etc. */ - FD_SET(p->ssdp_socket, readfds); - if(*nfds < p->ssdp_socket) - *nfds = p->ssdp_socket; - n++; - break; - } - return n; -} - -void upnpc_check_select_fds(upnpc_t * p, const fd_set * readfds, const fd_set * writefds) -{ - upnpc_device_t * d; - - p->socket_flags = 0; - if(FD_ISSET(p->ssdp_socket, readfds)) - p->socket_flags = UPNPC_SSDP_READABLE; - if(FD_ISSET(p->ssdp_socket, writefds)) - p->socket_flags = UPNPC_SSDP_WRITEABLE; - - for(d = p->device_list; d != NULL; d = d->next) { - d->socket_flags = 0; - if(FD_ISSET(d->http_socket, readfds)) - d->socket_flags = UPNPC_HTTP_READABLE; - if(FD_ISSET(d->http_socket, writefds)) - d->socket_flags = UPNPC_HTTP_WRITEABLE; - } -} -#endif - -static const char * devices_to_search[] = { - "urn:schemas-upnp-org:device:InternetGatewayDevice:1", - "urn:schemas-upnp-org:service:WANIPConnection:1", - "urn:schemas-upnp-org:service:WANPPPConnection:1", - "upnp:rootdevice", - 0 -}; - -int upnpc_process(upnpc_t * p) -{ - upnpc_device_t * d; -/* -1) Envoyer les paquets de discovery SSDP -2) Recevoir et traiter les reponses -3) recup les descriptions -4) tester les etats -TODO : translate comments to English -*/ - if(!p) return UPNPC_ERR_INVALID_ARGS; - debug_printf("state=%d socket_flags=0x%04x\n", (int)p->state, p->socket_flags); - - for(d = p->device_list; d != NULL; d = d->next) { - switch(d->state) { - case EDevGetDescConnect: - case EDevSoapConnect: - upnpc_complete_connect(d); - break; - case EDevGetDescRequest: - case EDevSoapRequest: - upnpc_send_request(d); - break; - case EDevGetDescResponse: - case EDevSoapResponse: - upnpc_get_response(d); - break; - default: - break; - } - } - /* all devices ready => ready */ - if(p->device_list != NULL) { - d = p->device_list; - while(d && d->state == EDevReady) d = d->next; - p->state = (d == NULL) ? EUPnPReady : EUPnPProcessing; - } - - if(p->socket_flags & UPNPC_SSDP_READABLE) { - upnpc_receive_and_parse_ssdp(p); - } - switch(p->state) { - case EUPnPInit: - upnpc_send_ssdp_msearch(p, devices_to_search[0], 2); - break; - case EUPnPSendSSDP: - upnpc_send_ssdp_msearch(p, devices_to_search[0], 2); - break; - case EUPnPReceiveSSDP: - /*upnpc_receive_and_parse_ssdp(p);*/ - break; - /*case EGetDesc: - upnpc_connect(p); - break;*/ - case EUPnPReady: - case EUPnPProcessing: - break; - default: - return UPNPC_ERR_UNKNOWN_STATE; - } - return UPNPC_OK; -} - diff --git a/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.h b/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.h deleted file mode 100644 index 53b433c..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/miniupnpc-async.h +++ /dev/null @@ -1,118 +0,0 @@ -/* $Id: miniupnpc-async.h,v 1.13 2014/11/07 11:25:52 nanard Exp $ */ -/* miniupnpc-async - * Copyright (c) 2008-2017, Thomas BERNARD - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef MINIUPNPC_ASYNC_H_INCLUDED -#define MINIUPNPC_ASYNC_H_INCLUDED - -/* for struct sockaddr_storage */ -#include -/* for fd_set */ -#include - -#include "declspec.h" -#include "upnpreplyparse.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UPNPC_OK 0 -#define UPNPC_ERR_INVALID_ARGS (-1) -#define UPNPC_ERR_SOCKET_FAILED (-2) -#define UPNPC_ERR_BIND_FAILED (-3) -#define UPNPC_ERR_UNKNOWN_STATE (-4) - -#define UPNPC_SSDP_READABLE 0x0001 -#define UPNPC_SSDP_WRITEABLE 0x0100 -#define UPNPC_HTTP_READABLE 0x0002 -#define UPNPC_HTTP_WRITEABLE 0x0200 - -typedef struct upnpc_device { - struct upnpc_device * next; - enum { - EDevInit = 1, - EDevGetDescConnect, - EDevGetDescRequest, - EDevGetDescResponse, - EDevReady, - EDevSoapConnect, - EDevSoapRequest, - EDevSoapResponse, - EDevFinalized = 99, - EDevError = 1000 - } state; - char * root_desc_location; - char * control_cif_url; - char * control_conn_url; - int http_socket; - int socket_flags; /* see UPNPC_*_READABLE, etc. */ - char * http_request; - int http_request_len; - int http_request_sent; - char * http_response; - int http_response_received; - int http_response_end_of_headers; - int http_response_content_length; - int http_response_chunked; - int http_response_code; - struct NameValueParserData soap_response_data; - struct sockaddr_storage selfaddr; - socklen_t selfaddrlen; -} upnpc_device_t; - -typedef struct { - enum { - EUPnPInit = 1, - EUPnPSendSSDP, - EUPnPReceiveSSDP, - EUPnPGetDesc, - EUPnPReady, - EUPnPProcessing, - EUPnPFinalized = 99, - EUPnPError = 1000 - } state; - int socket_flags; /* see UPNPC_*_READABLE, etc. */ - int ssdp_socket; - upnpc_device_t * device_list; -} upnpc_t; - -int upnpc_init(upnpc_t * p, const char * multicastif); - -int upnpc_finalize(upnpc_t * p); - -int upnpc_get_external_ip_address(upnpc_device_t * p); - -int upnpc_get_link_layer_max_rate(upnpc_device_t * p); - -int upnpc_add_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - unsigned short int_port, const char * int_client, - const char * proto, const char * description, - unsigned int lease_duration); - -#ifdef UPNPC_USE_SELECT -int upnpc_select_fds(upnpc_t * p, int * nfds, fd_set * readfds, fd_set * writefds); -void upnpc_check_select_fds(upnpc_t * p, const fd_set * readfds, const fd_set * writefds); -#endif /* UPNPC_USE_SELECT */ - -int upnpc_process(upnpc_t * p); - -#ifdef __cplusplus -} -#endif - -#endif /* MINIUPNPC_ASYNC_H_INCLUDED */ - diff --git a/src/contrib/miniupnp/miniupnpc-async/minixml.c b/src/contrib/miniupnp/miniupnpc-async/minixml.c deleted file mode 100644 index 3e201ec..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/minixml.c +++ /dev/null @@ -1,229 +0,0 @@ -/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ -/* minixml.c : the minimum size a xml parser can be ! */ -/* Project : miniupnp - * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - -Copyright (c) 2005-2014, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -#include -#include "minixml.h" - -/* parseatt : used to parse the argument list - * return 0 (false) in case of success and -1 (true) if the end - * of the xmlbuffer is reached. */ -static int parseatt(struct xmlparser * p) -{ - const char * attname; - int attnamelen; - const char * attvalue; - int attvaluelen; - while(p->xml < p->xmlend) - { - if(*p->xml=='/' || *p->xml=='>') - return 0; - if( !IS_WHITE_SPACE(*p->xml) ) - { - char sep; - attname = p->xml; - attnamelen = 0; - while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) - { - attnamelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - while(*(p->xml++) != '=') - { - if(p->xml >= p->xmlend) - return -1; - } - while(IS_WHITE_SPACE(*p->xml)) - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - sep = *p->xml; - if(sep=='\'' || sep=='\"') - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - attvalue = p->xml; - attvaluelen = 0; - while(*p->xml != sep) - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - else - { - attvalue = p->xml; - attvaluelen = 0; - while( !IS_WHITE_SPACE(*p->xml) - && *p->xml != '>' && *p->xml != '/') - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - /*printf("%.*s='%.*s'\n", - attnamelen, attname, attvaluelen, attvalue);*/ - if(p->attfunc) - p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); - } - p->xml++; - } - return -1; -} - -/* parseelt parse the xml stream and - * call the callback functions when needed... */ -static void parseelt(struct xmlparser * p) -{ - int i; - const char * elementname; - while(p->xml < (p->xmlend - 1)) - { - if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); - p->xml += 3; - } - else if((p->xml)[0]=='<' && (p->xml)[1]!='?') - { - i = 0; elementname = ++p->xml; - while( !IS_WHITE_SPACE(*p->xml) - && (*p->xml!='>') && (*p->xml!='/') - ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - /* to ignore namespace : */ - if(*p->xml==':') - { - i = 0; - elementname = ++p->xml; - } - } - if(i>0) - { - if(p->starteltfunc) - p->starteltfunc(p->data, elementname, i); - if(parseatt(p)) - return; - if(*p->xml!='/') - { - const char * data; - i = 0; data = ++p->xml; - if (p->xml >= p->xmlend) - return; - while( IS_WHITE_SPACE(*p->xml) ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(memcmp(p->xml, "xml += 9; - data = p->xml; - i = 0; - while(memcmp(p->xml, "]]>", 3) != 0) - { - i++; p->xml++; - if ((p->xml + 3) >= p->xmlend) - return; - } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); - while(*p->xml!='<') - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - } - else - { - while(*p->xml!='<') - { - i++; p->xml++; - if ((p->xml + 1) >= p->xmlend) - return; - } - if(i>0 && p->datafunc && *(p->xml + 1) == '/') - p->datafunc(p->data, data, i); - } - } - } - else if(*p->xml == '/') - { - i = 0; elementname = ++p->xml; - if (p->xml >= p->xmlend) - return; - while((*p->xml != '>')) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(p->endeltfunc) - p->endeltfunc(p->data, elementname, i); - p->xml++; - } - } - else - { - p->xml++; - } - } -} - -/* the parser must be initialized before calling this function */ -void parsexml(struct xmlparser * parser) -{ - parser->xml = parser->xmlstart; - parser->xmlend = parser->xmlstart + parser->xmlsize; - parseelt(parser); -} - - diff --git a/src/contrib/miniupnp/miniupnpc-async/minixml.h b/src/contrib/miniupnp/miniupnpc-async/minixml.h deleted file mode 100644 index 9f43aa4..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc-async/parsessdpreply.c b/src/contrib/miniupnp/miniupnpc-async/parsessdpreply.c deleted file mode 100644 index 05fda36..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/parsessdpreply.c +++ /dev/null @@ -1,80 +0,0 @@ -/* $Id: parsessdpreply.c,v 1.2 2009/11/14 10:37:55 nanard Exp $ */ -/* Project : miniupnp - * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - * copyright (c) 2005-2009 Thomas Bernard - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include "parsessdpreply.h" - -/* parseMSEARCHReply() - * the last 4 arguments are filled during the parsing : - * - location/locationsize : "location:" field of the SSDP reply packet - * - st/stsize : "st:" field of the SSDP reply packet. - * The strings are NOT null terminated */ -void -parseMSEARCHReply(const char * reply, int size, - const char * * location, int * locationsize, - const char * * st, int * stsize) -{ - int a, b, i; - i = 0; - a = i; /* start of the line */ - b = 0; - while(i - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -/* for getnameinfo() : */ -#include -#include -#include -/* compile with -DUPNPC_USE_SELECT to enable upnpc_select_fds() function */ -#include "miniupnpc-async.h" -#include "upnpreplyparse.h" - -enum methods { - EGetExternalIP, - EGetRates, - EAddPortMapping, - ENothing -}; - -int main(int argc, char * * argv) -{ - char ip_address[64]; - int r, n; - upnpc_t upnp; - upnpc_device_t * device = NULL; - const char * multicastif = NULL; - enum methods next_method_to_call = EGetExternalIP; - enum methods last_method = ENothing; - if(argc>1) - multicastif = argv[1]; - if((r = upnpc_init(&upnp, multicastif)) < 0) { - fprintf(stderr, "upnpc_init failed : %d", r); - return 1; - } - r = upnpc_process(&upnp); - printf("upnpc_process returned %d\n", r); - while(upnp.state != EUPnPError) { - int nfds; - fd_set readfds; - fd_set writefds; - /*struct timeval timeout;*/ - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - nfds = 0; - n = upnpc_select_fds(&upnp, &nfds, &readfds, &writefds); - if(n <= 0) { - printf("nothing to select()...\n"); - break; - } -#if 0 - timeout.tv_sec = 0; - timeout.tv_usec = 0; -#endif -#if DEBUG - printf("select(%d, ...);\n", nfds+1); -#endif /* DEBUG */ - if(select(nfds+1, &readfds, &writefds, NULL, NULL/*&timeout*/) < 0) { - perror("select"); - return 1; - } - upnpc_check_select_fds(&upnp, &readfds, &writefds); - r = upnpc_process(&upnp); -#if DEBUG - printf("upnpc_process returned %d\n", r); -#endif /* DEBUG */ - if(r < 0) - break; - if(upnp.state == EUPnPReady) { - char * p; - if(device == NULL) { - /* select one device */ - device = upnp.device_list; /* pick up the first one */ - } - printf("Process UPnP IGD Method results : HTTP %d\n", device->http_response_code); - if(device->http_response_code == 200) { - switch(last_method) { - case EGetExternalIP: - p = GetValueFromNameValueList(&device->soap_response_data, "NewExternalIPAddress"); - printf("ExternalIPAddress = %s\n", p); - /* p = GetValueFromNameValueList(&pdata, "errorCode");*/ - break; - case EGetRates: - p = GetValueFromNameValueList(&device->soap_response_data, "NewLayer1DownstreamMaxBitRate"); - printf("DownStream MaxBitRate = %s\t", p); - p = GetValueFromNameValueList(&device->soap_response_data, "NewLayer1UpstreamMaxBitRate"); - printf("UpStream MaxBitRate = %s\n", p); - break; - case EAddPortMapping: - printf("OK\n"); - break; - case ENothing: - break; - } - } else { - printf("SOAP error :\n"); - printf(" faultcode='%s'\n", GetValueFromNameValueList(&device->soap_response_data, "faultcode")); - printf(" faultstring='%s'\n", GetValueFromNameValueList(&device->soap_response_data, "faultstring")); - printf(" errorCode=%s\n", GetValueFromNameValueList(&device->soap_response_data, "errorCode")); - printf(" errorDescription='%s'\n", GetValueFromNameValueList(&device->soap_response_data, "errorDescription")); - } - if(next_method_to_call == ENothing) - break; - printf("Ready to call UPnP IGD methods\n"); - last_method = next_method_to_call; - switch(next_method_to_call) { - case EGetExternalIP: - printf("GetExternalIPAddress\n"); - upnpc_get_external_ip_address(device); - next_method_to_call = EGetRates; - break; - case EGetRates: - printf("GetCommonLinkProperties\n"); - upnpc_get_link_layer_max_rate(device); - next_method_to_call = EAddPortMapping; - break; - case EAddPortMapping: - if(getnameinfo((struct sockaddr *)&device->selfaddr, device->selfaddrlen, - ip_address, sizeof(ip_address), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV) < 0) { - fprintf(stderr, "getnameinfo() failed\n"); - } - printf("our IP address is %s\n", ip_address); - printf("AddPortMapping\n"); - upnpc_add_port_mapping(device, - NULL /* remote_host */, 40002 /* ext_port */, - 42042 /* int_port */, ip_address /* int_client */, - "TCP" /* proto */, "this is a test" /* description */, - 0 /* lease duration */); - next_method_to_call = ENothing; - case ENothing: - break; - } - } - } - upnpc_finalize(&upnp); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.c b/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.c deleted file mode 100644 index 5de5796..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "upnpreplyparse.h" -#include "minixml.h" - -static void -NameValueParserStartElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - data->topelt = 1; - if(l>63) - l = 63; - memcpy(data->curelt, name, l); - data->curelt[l] = '\0'; - data->cdata = NULL; - data->cdatalen = 0; -} - -static void -NameValueParserEndElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - (void)name; - (void)l; - if(!data->topelt) - return; - if(strcmp(data->curelt, "NewPortListing") != 0) - { - int l; - /* standard case. Limited to n chars strings */ - l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); - if(nv == NULL) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserEndElt"); -#endif /* DEBUG */ - return; - } - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - if(data->cdata != NULL) - { - memcpy(nv->value, data->cdata, l); - nv->value[l] = '\0'; - } - else - { - nv->value[0] = '\0'; - } - nv->l_next = data->l_head; /* insert in list */ - data->l_head = nv; - } - data->cdata = NULL; - data->cdatalen = 0; - data->topelt = 0; -} - -static void -NameValueParserGetData(void * d, const char * datas, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - if(strcmp(data->curelt, "NewPortListing") == 0) - { - /* specific case for NewPortListing which is a XML Document */ - data->portListing = malloc(l + 1); - if(!data->portListing) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserGetData"); -#endif /* DEBUG */ - return; - } - memcpy(data->portListing, datas, l); - data->portListing[l] = '\0'; - data->portListingLength = l; - } - else - { - /* standard case. */ - data->cdata = datas; - data->cdatalen = l; - } -} - -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) -{ - struct xmlparser parser; - data->l_head = NULL; - data->portListing = NULL; - data->portListingLength = 0; - /* init xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = NameValueParserEndElt; - parser.datafunc = NameValueParserGetData; - parser.attfunc = 0; - parsexml(&parser); -} - -void -ClearNameValueList(struct NameValueParserData * pdata) -{ - struct NameValue * nv; - if(pdata->portListing) - { - free(pdata->portListing); - pdata->portListing = NULL; - pdata->portListingLength = 0; - } - while((nv = pdata->l_head) != NULL) - { - pdata->l_head = nv->l_next; - free(nv); - } -} - -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - for(nv = pdata->l_head; - (nv != NULL) && (p == NULL); - nv = nv->l_next) - { - if(strcmp(nv->name, Name) == 0) - p = nv->value; - } - return p; -} - -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - -/* debug all-in-one function - * do parsing then display to stdout */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize) -{ - struct NameValueParserData pdata; - struct NameValue * nv; - ParseNameValue(buffer, bufsize, &pdata); - for(nv = pdata.l_head; - nv != NULL; - nv = nv->l_next) - { - printf("%s = %s\n", nv->name, nv->value); - } - ClearNameValueList(&pdata); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.h b/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.h deleted file mode 100644 index 6badd15..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/upnpreplyparse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - struct NameValue * l_head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc-async/upnputils.c b/src/contrib/miniupnp/miniupnpc-async/upnputils.c deleted file mode 100644 index 8519da9..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/upnputils.c +++ /dev/null @@ -1,87 +0,0 @@ -/* $Id: upnputils.c,v 1.1 2013/09/07 06:45:39 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef AF_LINK -#include -#endif - -#include "upnputils.h" - -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size) -{ - char buffer[64]; - unsigned short port = 0; - int n = -1; - - switch(addr->sa_family) - { - case AF_INET6: - inet_ntop(addr->sa_family, - &((struct sockaddr_in6 *)addr)->sin6_addr, - buffer, sizeof(buffer)); - port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - n = snprintf(str, size, "[%s]:%hu", buffer, port); - break; - case AF_INET: - inet_ntop(addr->sa_family, - &((struct sockaddr_in *)addr)->sin_addr, - buffer, sizeof(buffer)); - port = ntohs(((struct sockaddr_in *)addr)->sin_port); - n = snprintf(str, size, "%s:%hu", buffer, port); - break; -#ifdef AF_LINK -#if defined(__sun) - /* solaris does not seem to have link_ntoa */ - /* #define link_ntoa _link_ntoa */ -#define link_ntoa(x) "dummy-link_ntoa" -#endif - case AF_LINK: - { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)addr; - n = snprintf(str, size, "index=%hu type=%d %s", - sdl->sdl_index, sdl->sdl_type, - link_ntoa(sdl)); - } - break; -#endif - default: - n = snprintf(str, size, "unknown address family %d", addr->sa_family); -#if 0 - n = snprintf(str, size, "unknown address family %d " - "%02x %02x %02x %02x %02x %02x %02x %02x", - addr->sa_family, - addr->sa_data[0], addr->sa_data[1], (unsigned)addr->sa_data[2], addr->sa_data[3], - addr->sa_data[4], addr->sa_data[5], (unsigned)addr->sa_data[6], addr->sa_data[7]); -#endif - } - return n; -} - - -int -set_non_blocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if(flags < 0) - return 0; - if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) - return 0; - return 1; -} - diff --git a/src/contrib/miniupnp/miniupnpc-async/upnputils.h b/src/contrib/miniupnp/miniupnpc-async/upnputils.h deleted file mode 100644 index adf387f..0000000 --- a/src/contrib/miniupnp/miniupnpc-async/upnputils.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: upnputils.h,v 1.1 2013/09/07 06:45:39 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPUTILS_H_INCLUDED -#define UPNPUTILS_H_INCLUDED - -/** - * convert a struct sockaddr to a human readable string. - * [ipv6]:port or ipv4:port - * return the number of characters used (as snprintf) - */ -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size); - -/** - * set the file description as non blocking - * return 0 in case of failure, 1 in case of success - */ -int -set_non_blocking(int fd); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/.gitignore b/src/contrib/miniupnp/miniupnpc-libevent/.gitignore deleted file mode 100644 index b845178..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.o -*.a -upnpc-libevent diff --git a/src/contrib/miniupnp/miniupnpc-libevent/Makefile b/src/contrib/miniupnp/miniupnpc-libevent/Makefile deleted file mode 100644 index 29abc4a..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# $Id: Makefile,v 1.7 2014/11/28 13:14:19 nanard Exp $ - -OS = $(shell $(CC) -dumpmachine) -PKG_CONFIG ?= pkg-config - -CFLAGS = -O0 -g -DDEBUG -# libevent debug -CFLAGS += -DUSE_DEBUG - -CFLAGS += -fPIC -CFLAGS += -ansi -CFLAGS += -Wall -W -CFLAGS += -D_BSD_SOURCE -ifeq (, $(findstring darwin, $(OS))$(findstring freebsd, $(OS))) -CFLAGS += -D_POSIX_C_SOURCE=200112L -endif -#CFLAGS += -I/usr/local/include -CFLAGS += $(shell $(PKG_CONFIG) --cflags libevent) - -#CFLAGS += -DENABLE_UPNP_EVENTS - -#LDLIBS = -levent -LDLIBS = $(shell $(PKG_CONFIG) --libs-only-l libevent) -#LDFLAGS += -L/usr/local/lib -LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libevent) - -ifneq (, $(findstring darwin, $(OS))) -CFLAGS += -D_DARWIN_C_SOURCE -#CFLAGS += -I/opt/local/include -#LDFLAGS += -L/opt/local/lib -endif - -LIB = libminiupnpc-ev.a - -LIB_SRCS = miniupnpc-libevent.c minixml.c igd_desc_parse.c upnpreplyparse.c - -SRCS = $(LIB_SRCS) upnpc-libevent.c - -LIB_OBJS = $(patsubst %.c,%.o,$(LIB_SRCS)) - -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -EXECUTABLE = upnpc-libevent - -.PHONY: all clean depend - -all: $(EXECUTABLE) - -clean: - $(RM) $(OBJS) - $(RM) $(EXECUTABLE) - $(RM) $(LIB) - -upnpc-libevent: upnpc-libevent.o $(LIB) - -$(LIB): $(LIB_OBJS) - $(AR) crs $@ $? - -depend: - makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -miniupnpc-libevent.o: miniupnpc-libevent.h declspec.h upnpreplyparse.h -miniupnpc-libevent.o: minixml.h igd_desc_parse.h -minixml.o: minixml.h -igd_desc_parse.o: igd_desc_parse.h -upnpreplyparse.o: upnpreplyparse.h minixml.h -upnpc-libevent.o: miniupnpc-libevent.h declspec.h upnpreplyparse.h diff --git a/src/contrib/miniupnp/miniupnpc-libevent/README b/src/contrib/miniupnp/miniupnpc-libevent/README deleted file mode 100644 index b102fcb..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/README +++ /dev/null @@ -1,13 +0,0 @@ -miniupnpc-libevent : - -UPnP IGD control point (ie client) using libevent - -http://libevent.org -https://github.com/libevent/libevent - -The UPnP Event code needs SUBSCRIBE / UNSUBSCRIBE / NOTIFY HTTP methods. -Implementation is in progress in libevent HTTP code : -https://github.com/libevent/libevent/pull/327 - - -TODO : improve error handling / reporting diff --git a/src/contrib/miniupnp/miniupnpc-libevent/declspec.h b/src/contrib/miniupnp/miniupnpc-libevent/declspec.h deleted file mode 100644 index 16be781..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/declspec.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DECLSPEC_H_DEFINED -#define DECLSPEC_H_DEFINED - -#if defined(_WIN32) && !defined(STATICLIB) - #ifdef MINIUPNP_EXPORTS - #define LIBSPEC __declspec(dllexport) - #else - #define LIBSPEC __declspec(dllimport) - #endif -#else - #define LIBSPEC -#endif - -#endif /* DECLSPEC_H_DEFINED */ - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.c b/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.c deleted file mode 100644 index d2999ad..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include "igd_desc_parse.h" -#include -#include - -/* Start element handler : - * update nesting level counter and copy element name */ -void IGDstartelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - if(l >= MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(datas->cureltname, name, l); - datas->cureltname[l] = '\0'; - datas->level++; - if( (l==7) && !memcmp(name, "service", l) ) { - datas->tmp.controlurl[0] = '\0'; - datas->tmp.eventsuburl[0] = '\0'; - datas->tmp.scpdurl[0] = '\0'; - datas->tmp.servicetype[0] = '\0'; - } -} - -#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) - -/* End element handler : - * update nesting level counter and update parser state if - * service element is parsed */ -void IGDendelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - datas->level--; - /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ - if( (l==7) && !memcmp(name, "service", l) ) - { - if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { - memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) { - memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPConnection:") - || COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANPPPConnection:") ) { - if(datas->first.servicetype[0] == '\0') { - memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); - } else { - memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); - } - } - } -} - -/* Data handler : - * copy data depending on the current element name and state */ -void IGDdata(void * d, const char * data, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - char * dstmember = 0; - /*printf("%2d %s : %.*s\n", - datas->level, datas->cureltname, l, data); */ - if( !strcmp(datas->cureltname, "URLBase") ) - dstmember = datas->urlbase; - else if( !strcmp(datas->cureltname, "presentationURL") ) - dstmember = datas->presentationurl; - else if( !strcmp(datas->cureltname, "serviceType") ) - dstmember = datas->tmp.servicetype; - else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->tmp.controlurl; - else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->tmp.eventsuburl; - else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->tmp.scpdurl; -/* else if( !strcmp(datas->cureltname, "deviceType") ) - dstmember = datas->devicetype_tmp;*/ - if(dstmember) - { - if(l>=MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(dstmember, data, l); - dstmember[l] = '\0'; - } -} - -#ifdef DEBUG -void printIGD(struct IGDdatas * d) -{ - printf("urlbase = '%s'\n", d->urlbase); - printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ - printf(" serviceType = '%s'\n", d->CIF.servicetype); - printf(" controlURL = '%s'\n", d->CIF.controlurl); - printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); - printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); - printf("primary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ - printf(" servicetype = '%s'\n", d->first.servicetype); - printf(" controlURL = '%s'\n", d->first.controlurl); - printf(" eventSubURL = '%s'\n", d->first.eventsuburl); - printf(" SCPDURL = '%s'\n", d->first.scpdurl); - printf("secondary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ - printf(" servicetype = '%s'\n", d->second.servicetype); - printf(" controlURL = '%s'\n", d->second.controlurl); - printf(" eventSubURL = '%s'\n", d->second.eventsuburl); - printf(" SCPDURL = '%s'\n", d->second.scpdurl); - printf("WAN IPv6 Firewall Control :\n"); - /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ - printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); - printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); - printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); - printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.h b/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.h deleted file mode 100644 index 0de546b..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/igd_desc_parse.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef IGD_DESC_PARSE_H_INCLUDED -#define IGD_DESC_PARSE_H_INCLUDED - -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ -#define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas_service { - char controlurl[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl[MINIUPNPC_URL_MAXSIZE]; - char scpdurl[MINIUPNPC_URL_MAXSIZE]; - char servicetype[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ -}; - -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - char presentationurl[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ - struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ - struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ - struct IGDdatas_service IPv6FC; - /* tmp */ - struct IGDdatas_service tmp; -}; - -void IGDstartelt(void *, const char *, int); -void IGDendelt(void *, const char *, int); -void IGDdata(void *, const char *, int); -#ifdef DEBUG -void printIGD(struct IGDdatas *); -#endif /* DEBUG */ - -#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.c b/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.c deleted file mode 100644 index a454cb4..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* $Id: miniupnpc-libevent.c,v 1.27 2015/07/22 13:51:09 nanard Exp $ */ -/* miniupnpc-libevent - * Copyright (c) 2008-2016, Thomas BERNARD - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#ifdef _WIN32 -#include -#include -#include -#define PRINT_SOCKET_ERROR printf -#define SOCKET_ERROR GetWSALastError() -#define WOULDBLOCK(err) (err == WSAEWOULDBLOCK) -#else /* _WIN32 */ -#include -#include -#define closesocket close -#define PRINT_SOCKET_ERROR perror -#define SOCKET_ERROR errno -#define WOULDBLOCK(err) (err == EAGAIN || err == EWOULDBLOCK) -#endif /* _WIN32 */ -#include "miniupnpc-libevent.h" -#include "minixml.h" -#include "igd_desc_parse.h" -#include "upnpreplyparse.h" - -#ifndef MIN -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif /* MIN */ - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif /* MAXHOSTNAMELEN */ - -#define SSDP_PORT 1900 -#define SSDP_MCAST_ADDR "239.255.255.250" -#define XSTR(s) STR(s) -#define STR(s) #s - -#ifdef DEBUG -#define debug_printf(...) fprintf(stderr, __VA_ARGS__) -#else -#define debug_printf(...) (void)0 -#endif - -/* compare the beginning of a string with a constant string */ -#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) - -/* stuctures */ - -struct upnp_args { - const char * elt; - const char * val; -}; - -/* private functions */ - -static int upnpc_get_desc(upnpc_device_t * p, const char * url); -static char * build_url_string(const char * urlbase, const char * root_desc_url, const char * controlurl); - -/* data */ -static const char * devices_to_search[] = { - "urn:schemas-upnp-org:device:InternetGatewayDevice:1", - "urn:schemas-upnp-org:service:WANIPConnection:1", - "urn:schemas-upnp-org:service:WANPPPConnection:1", - "upnp:rootdevice", - 0 -}; - -#ifdef DEBUG -static void upnpc_conn_close_cb(struct evhttp_connection * conn, void * data) -{ - upnpc_device_t * d = (upnpc_device_t *)data; - debug_printf("%s %p %p\n", __func__, conn, d); -} -#endif /* DEBUG */ - -/* parse_msearch_reply() - * the last 4 arguments are filled during the parsing : - * - location/locationsize : "location:" field of the SSDP reply packet - * - st/stsize : "st:" field of the SSDP reply packet. - * The strings are NOT null terminated */ -static void -parse_msearch_reply(const char * reply, int size, - const char * * location, int * locationsize, - const char * * st, int * stsize) -{ - int a, b, i; - i = 0; /* current character index */ - a = i; /* start of the line */ - b = 0; /* end of the "header" (position of the colon) */ - while(idiscover_device_index++], mx); - debug_printf("%s: %s", __func__, bufr); - n = sendto(s, bufr, n, 0, - (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - if (n < 0) { - PRINT_SOCKET_ERROR("sendto"); - } -} - -static int upnpc_set_root_desc_location(upnpc_device_t * d, const char * location, int locationsize) -{ - char * tmp; - tmp = realloc(d->root_desc_location, locationsize + 1); - if(tmp == NULL) { - return -1; - } - memcpy(tmp, location, locationsize); - tmp[locationsize] = '\0'; - d->root_desc_location = tmp; - return 0; -} - -static upnpc_device_t * upnpc_find_device_with_location(upnpc_t * p, const char * location, int locationsize) -{ - upnpc_device_t * d; - for(d = p->devices; d != NULL; d = d->next) { - if(d->root_desc_location - && ((int)strlen(d->root_desc_location) == locationsize) - && (0 == memcmp(location, d->root_desc_location, locationsize))) - return d; - } - return NULL; -} - -static void upnpc_receive_and_parse_ssdp(evutil_socket_t s, short events, upnpc_t * p) -{ - char bufr[2048]; - ssize_t len; - - if(events == EV_TIMEOUT) { - /* nothing received ... */ - debug_printf("%s() TIMEOUT\n", __func__); - if(!devices_to_search[p->discover_device_index]) { - debug_printf("*** NO MORE DEVICES TO SEARCH ***\n"); - event_del(p->ev_ssdp_recv); - /* no device found : report error */ - p->ready_cb(UPNPC_ERR_NO_DEVICE_FOUND, p, NULL, p->cb_data); - } else { - /* send another SSDP M-SEARCH packet */ - if(event_add(p->ev_ssdp_writable, NULL)) { - debug_printf("event_add FAILED\n"); - } - } - return; - } - len = recv(s, bufr, sizeof(bufr), 0); - debug_printf("input %d bytes\n", (int)len); - if(len < 0) { - PRINT_SOCKET_ERROR("recv"); - } else if(len == 0) { - debug_printf("SSDP socket closed ?\n"); - } else { - const char * location = NULL; - int locationsize = 0; - const char * st = NULL; - int stsize = 0; - debug_printf("%.*s", (int)len, bufr); - parse_msearch_reply(bufr, len, &location, &locationsize, &st, &stsize); - debug_printf("location = '%.*s'\n", locationsize, location); - debug_printf("st = '%.*s'\n", stsize, st); - if(location != NULL) { - upnpc_device_t * device; - device = upnpc_find_device_with_location(p, location, locationsize); - if(device) { - debug_printf("device already known\n"); - } else { - device = malloc(sizeof(upnpc_device_t)); - if(device == NULL) { - debug_printf("Memory allocation error\n"); - return; - } - memset(device, 0, sizeof(upnpc_device_t)); - device->parent = p; - device->next = p->devices; - p->devices = device; - if(upnpc_set_root_desc_location(device, location, locationsize) < 0) { - return; - } - if(upnpc_get_desc(device, device->root_desc_location)) { - debug_printf("FAILED to request device root description\n"); - } - } -#if 0 - event_del(p->ev_ssdp_recv); /* stop receiving SSDP responses */ -#endif - } else { - /* or do nothing ? */ - debug_printf("no location\n"); - } - } -} - -static int -parseURL(const char * url, - char * hostname, unsigned short * port, - char * * path, unsigned int * scope_id) -{ - char * p1, *p2, *p3; - if(!url) - return 0; - p1 = strstr(url, "://"); - if(!p1) - return 0; - p1 += 3; - if( (url[0]!='h') || (url[1]!='t') - ||(url[2]!='t') || (url[3]!='p')) - return 0; - memset(hostname, 0, MAXHOSTNAMELEN + 1); - if(*p1 == '[') { - /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ - char * scope; - scope = strchr(p1, '%'); - p2 = strchr(p1, ']'); - if(p2 && scope && scope < p2 && scope_id) { - /* parse scope */ -#ifdef IF_NAMESIZE - char tmp[IF_NAMESIZE]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= IF_NAMESIZE) - l = IF_NAMESIZE - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = if_nametoindex(tmp); - if(*scope_id == 0) { - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); - } -#else /* IF_NAMESIZE */ - /* under windows, scope is numerical */ - char tmp[8]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= (int)sizeof(tmp)) - l = sizeof(tmp) - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); -#endif /* IF_NAMESIZE */ - } - p3 = strchr(p1, '/'); - if(p2 && p3) { - p2++; - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - if(*p2 == ':') { - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } else { - *port = 80; - } - *path = p3; - return 1; - } - } - p2 = strchr(p1, ':'); - p3 = strchr(p1, '/'); - if(!p3) - return 0; - if(!p2 || (p2>p3)) { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); - *port = 80; - } else { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - *path = p3; - return 1; -} - -static void upnpc_desc_received(struct evhttp_request * req, void * pvoid) -{ - size_t len; - unsigned char * data; - struct evbuffer * input_buffer; - struct IGDdatas igd; - struct xmlparser parser; - upnpc_device_t * d = (upnpc_device_t *)pvoid; - - if(req == NULL) { - debug_printf("%s(%p, %p) NULL argument !\n", __func__, req, pvoid); - return; - } - input_buffer = evhttp_request_get_input_buffer(req); - len = evbuffer_get_length(input_buffer); - data = evbuffer_pullup(input_buffer, len); - debug_printf("%s %d (%d bytes)\n", __func__, evhttp_request_get_response_code(req), (int)len); - if(evhttp_request_get_response_code(req) != HTTP_OK) { - d->parent->ready_cb(evhttp_request_get_response_code(req), d->parent, d, d->parent->cb_data); - return; - } - if(data == NULL) { - d->parent->ready_cb(UPNPC_ERR_ROOT_DESC_ERROR, d->parent, d, d->parent->cb_data); - return; - } - debug_printf("%.*s\n", (int)len, (char *)data); - - memset(&igd, 0, sizeof(struct IGDdatas)); - memset(&parser, 0, sizeof(struct xmlparser)); - parser.xmlstart = (char *)data; - parser.xmlsize = len; - parser.data = &igd; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parsexml(&parser); -#ifdef DEBUG - printIGD(&igd); -#endif /* DEBUG */ - d->control_conn_url = build_url_string(igd.urlbase, d->root_desc_location, igd.first.controlurl); - d->event_conn_url = build_url_string(igd.urlbase, d->root_desc_location, igd.first.eventsuburl); - d->conn_service_type = strdup(igd.first.servicetype); - d->control_cif_url = build_url_string(igd.urlbase, d->root_desc_location, igd.CIF.controlurl); - d->event_cif_url = build_url_string(igd.urlbase, d->root_desc_location, igd.CIF.eventsuburl); - d->cif_service_type = strdup(igd.CIF.servicetype); - debug_printf("control_conn_url='%s'\n (service_type='%s')\n", - d->control_conn_url, d->conn_service_type); - debug_printf("event_conn_url='%s'\n", d->event_conn_url); - debug_printf("control_cif_url='%s'\n (service_type='%s')\n", - d->control_cif_url, d->cif_service_type); - - if((d->cif_service_type == NULL) - || (d->cif_service_type[0] == '\0') - || (!COMPARE(d->cif_service_type, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))) { - d->parent->ready_cb(UPNPC_ERR_NOT_IGD, d->parent, d, d->parent->cb_data); - } else { - d->state |= UPNPC_DEVICE_GETSTATUS; - upnpc_get_status_info(d); - } -} - -#ifdef ENABLE_UPNP_EVENTS -static void upnpc_subscribe_response(struct evhttp_request * req, void * pvoid) -{ - size_t len; - unsigned char * data; - struct evbuffer * input_buffer; - upnpc_device_t * d = (upnpc_device_t *)pvoid; - - if(req == NULL) { - debug_printf("%s(%p, %p) NULL argument !\n", __func__, req, pvoid); - return; - } - input_buffer = evhttp_request_get_input_buffer(req); - len = evbuffer_get_length(input_buffer); - data = evbuffer_pullup(input_buffer, len); - debug_printf("%s %d (%d bytes)\n", __func__, evhttp_request_get_response_code(req), (int)len); - d->state &= ~UPNPC_DEVICE_SOAP_REQ; - if(evhttp_request_get_response_code(req) != HTTP_OK) { - /* TODO ERROR */ - } else { - const char * sid; - struct evkeyvalq * headers = evhttp_request_get_input_headers(req); - sid = evhttp_find_header(headers, "sid"); - debug_printf("SID=%s\n", sid); - if(sid) { - if(d->event_conn_sid) - free(d->event_conn_sid); - d->event_conn_sid = strdup(sid); - } - } -} -#endif /* ENABLE_UPNP_EVENTS */ - -static void upnpc_soap_response(struct evhttp_request * req, void * pvoid) -{ - size_t len; - unsigned char * data; - struct evbuffer * input_buffer; - upnpc_device_t * d = (upnpc_device_t *)pvoid; - int code; - - if(req == NULL) { - debug_printf("%s(%p, %p) NULL argument !\n", __func__, req, pvoid); - return; - } - code = evhttp_request_get_response_code(req); - input_buffer = evhttp_request_get_input_buffer(req); - len = evbuffer_get_length(input_buffer); - data = evbuffer_pullup(input_buffer, len); - debug_printf("%s %d (%d bytes)\n", __func__, code, (int)len); - debug_printf("%.*s\n", (int)len, (char *)data); - if(data == NULL) - return; - - ClearNameValueList(&d->soap_response_data); - ParseNameValue((char *)data, (int)len, - &d->soap_response_data); - d->state &= ~UPNPC_DEVICE_SOAP_REQ; - if(d->state & UPNPC_DEVICE_READY) { - d->parent->soap_cb(code, d->parent, d, d->parent->cb_data); - } else if(d->state & UPNPC_DEVICE_GETSTATUS) { - const char * connection_status; - d->state &= ~UPNPC_DEVICE_GETSTATUS; - connection_status = GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus"); - d->state |= UPNPC_DEVICE_READY; - if((code == 200) && connection_status && (0 == strcmp("Connected", connection_status))) { - d->parent->ready_cb(code, d->parent, d, d->parent->cb_data); - d->state |= UPNPC_DEVICE_CONNECTED; - event_del(d->parent->ev_ssdp_recv); - } else { - d->parent->ready_cb(UPNPC_ERR_NOT_CONNECTED, d->parent, d, d->parent->cb_data); - } - } -} - -static int upnpc_get_desc(upnpc_device_t * d, const char * url) -{ - char hostname[MAXHOSTNAMELEN+1]; - char hostname_port[MAXHOSTNAMELEN+1+6]; - unsigned short port; - char * path; - unsigned int scope_id; - struct evhttp_request * req; - struct evkeyvalq * headers; - - /* if(d->root_desc_location == NULL) { - return -1; - } */ - if(!parseURL(url/*d->root_desc_location*/, hostname, &port, - &path, &scope_id)) { - return -1; - } - if(port != 80) - snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); - else - strncpy(hostname_port, hostname, sizeof(hostname_port)); - if(d->desc_conn == NULL) { - d->desc_conn = evhttp_connection_base_new(d->parent->base, NULL, hostname, port); - } -#ifdef DEBUG - evhttp_connection_set_closecb(d->desc_conn, upnpc_conn_close_cb, d); -#endif /* DEBUG */ - /*evhttp_connection_set_timeout(p->desc_conn, 600);*/ - req = evhttp_request_new(upnpc_desc_received/*callback*/, d); - headers = evhttp_request_get_output_headers(req); - evhttp_add_header(headers, "Host", hostname_port); - evhttp_add_header(headers, "Connection", "close"); - /*evhttp_add_header(headers, "User-Agent", "***");*/ - return evhttp_make_request(d->desc_conn, req, EVHTTP_REQ_GET, path); -} - -static char * build_url_string(const char * urlbase, const char * root_desc_url, const char * controlurl) -{ - int l, n; - char * s; - const char * base; - char * p; - /* if controlurl is an absolute url, return it */ - if(0 == memcmp("http://", controlurl, 7)) - return strdup(controlurl); - base = (urlbase[0] == '\0') ? root_desc_url : urlbase; - n = strlen(base); - if(n > 7) { - p = strchr(base + 7, '/'); - if(p) - n = p - base; - } - l = n + strlen(controlurl) + 1; - if(controlurl[0] != '/') - l++; - s = malloc(l); - if(s == NULL) return NULL; - memcpy(s, base, n); - if(controlurl[0] != '/') - s[n++] = '/'; - memcpy(s + n, controlurl, l - n); - return s; -} - -#define SOAPPREFIX "s" -#define SERVICEPREFIX "u" -#define SERVICEPREFIX2 'u' - -static int upnpc_send_soap_request(upnpc_device_t * p, const char * url, - const char * service, - const char * method, - const struct upnp_args * args, int arg_count) -{ - char action[128]; - char * body; - const char fmt_soap[] = - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" - "%s" - "" - "" - "\r\n"; - int body_len; - char hostname[MAXHOSTNAMELEN+1]; - char hostname_port[MAXHOSTNAMELEN+1+6]; - unsigned short port; - char * path; - unsigned int scope_id; - char * args_xml = NULL; - struct evhttp_request * req; - struct evkeyvalq * headers; - struct evbuffer * buffer; - - if(p->state & UPNPC_DEVICE_SOAP_REQ) { - debug_printf("%s: another SOAP request in progress\n", __func__); - return UPNPC_ERR_REQ_IN_PROGRESS; - } - - if(arg_count > 0) { - int i; - size_t l, n; - for(i = 0, l = 0; i < arg_count; i++) { - /* VAL */ - l += strlen(args[i].elt) * 2 + strlen(args[i].val) + 5; - } - args_xml = malloc(++l); - if(args_xml == NULL) { - return -1; - } - for(i = 0, n = 0; i < arg_count && n < l; i++) { - /* VAL */ - n += snprintf(args_xml + n, l - n, "<%s>%s", - args[i].elt, args[i].val, args[i].elt); - } - } - - body_len = snprintf(NULL, 0, fmt_soap, method, service, args_xml?args_xml:"", method); - body = malloc(body_len + 1); - if(body == NULL) { - free(args_xml); - return -1; - } - if(snprintf(body, body_len + 1, fmt_soap, method, service, args_xml?args_xml:"", method) != body_len) { - debug_printf("%s: snprintf() returned strange value...\n", __func__); - } - free(args_xml); - args_xml = NULL; - if(!parseURL(url, hostname, &port, &path, &scope_id)) { - free(body); - return -1; - } - if(port != 80) - snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); - else - strncpy(hostname_port, hostname, sizeof(hostname_port)); - snprintf(action, sizeof(action), "\"%s#%s\"", service, method); - if(p->soap_conn == NULL) { - p->soap_conn = evhttp_connection_base_new(p->parent->base, NULL, hostname, port); - } - req = evhttp_request_new(upnpc_soap_response, p); - headers = evhttp_request_get_output_headers(req); - buffer = evhttp_request_get_output_buffer(req); - evhttp_add_header(headers, "Host", hostname_port); - evhttp_add_header(headers, "SOAPAction", action); - evhttp_add_header(headers, "Content-Type", "text/xml"); - /*evhttp_add_header(headers, "User-Agent", "***");*/ - /*evhttp_add_header(headers, "Cache-Control", "no-cache");*/ - /*evhttp_add_header(headers, "Pragma", "no-cache");*/ - evbuffer_add(buffer, body, body_len); - evhttp_make_request(p->soap_conn, req, EVHTTP_REQ_POST, path); - free(body); - p->state |= UPNPC_DEVICE_SOAP_REQ; - return 0; -} - -#ifdef ENABLE_UPNP_EVENTS -#define EVHTTP_REQ_NOTIFY ((EVHTTP_REQ_MAX) << 1) -#define EVHTTP_REQ_SUBSCRIBE ((EVHTTP_REQ_NOTIFY) << 1) -static const struct evhttp_extended_method ext_methods[] = { - {"NOTIFY", EVHTTP_REQ_NOTIFY, EVHTTP_METHOD_HAS_BODY}, - {"SUBSCRIBE", EVHTTP_REQ_SUBSCRIBE, EVHTTP_METHOD_HAS_BODY}, - {NULL, 0, 0} -}; - -void upnpc_event_conn_req(struct evhttp_request * req, void * data) -{ - size_t len; - char * xml_data; - struct evbuffer * input_buffer; - struct evkeyvalq * headers; - const char * sid; - const char * nts; - const char * nt; - const char * seq; - struct NameValueParserData parsed_data; - struct NameValue * nv; - upnpc_device_t * d = (upnpc_device_t *)data; - - debug_printf("%s(%p, %p)\n", __func__, req, d); - headers = evhttp_request_get_input_headers(req); - input_buffer = evhttp_request_get_input_buffer(req); - len = evbuffer_get_length(input_buffer); - sid = evhttp_find_header(headers, "sid"); - nts = evhttp_find_header(headers, "nts"); - nt = evhttp_find_header(headers, "nt"); - seq = evhttp_find_header(headers, "seq"); - if(len == 0 || nts == NULL || nt == NULL) { - /* 400 Bad request : - * The NT or NTS header field is missing - * or the request is malformed. */ - evhttp_send_reply(req, 400, "Bad Request", NULL); - return; - } - debug_printf("SID=%s NTS=%s SEQ=%s\n", sid, nts, seq); - if(sid == NULL || 0 != strcmp(sid, d->event_conn_sid) - || 0 != strcmp(nt, "upnp:event") || 0 != strcmp(nts, "upnp:propchange")) { - /* 412 Precondition Failed : - * An SID does not correspond to a known, un-expired subscription - * or the NT header field does not equal upnp:event - * or the NTS header field does not equal upnp:propchange - * or the SID header field is missing or empty. */ - evhttp_send_reply(req, 412, "Precondition Failed", NULL); - return; - } - xml_data = (char *)evbuffer_pullup(input_buffer, len); - /*debug_printf("%.*s\n", len, xml_data);*/ - ParseNameValue(xml_data, len, &parsed_data); - for(nv = parsed_data.l_head; nv != NULL; nv = nv->l_next) { - if(d->parent->value_changed_cb) { - d->parent->value_changed_cb(d->parent, d, d->parent->cb_data, d->conn_service_type, nv->name, nv->value); - } else { - debug_printf("%s=%s\n", nv->name, nv->value); - } - } - ClearNameValueList(&parsed_data); - /* response : 200 OK */ - evhttp_send_reply(req, 200, "OK", NULL); -} -#endif /* ENABLE_UPNP_EVENTS */ - -/* public functions */ -int upnpc_init(upnpc_t * p, struct event_base * base, const char * multicastif, - upnpc_callback_fn ready_cb, upnpc_callback_fn soap_cb, void * cb_data) -{ - int opt = 1; - struct sockaddr_in addr; - - if(p == NULL || base == NULL) - return UPNPC_ERR_INVALID_ARGS; - memset(p, 0, sizeof(upnpc_t)); /* clean everything */ - p->base = base; - p->ready_cb = ready_cb; - p->soap_cb = soap_cb; - p->cb_data = cb_data; - p->ttl = 2; - /* open the socket for SSDP */ - p->ssdp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(p->ssdp_socket < 0) { - return UPNPC_ERR_SOCKET_FAILED; - } - /* set multicast TTL */ - if(setsockopt(p->ssdp_socket, IPPROTO_IP, IP_MULTICAST_TTL, &p->ttl, sizeof(p->ttl)) < 0) - { - /* not a fatal error */ - debug_printf("setsockopt(%d, ..., IP_MULTICAST_TTL, ...) FAILED\n", p->ssdp_socket); - } - /* set REUSEADDR */ -#ifdef _WIN32 - if(setsockopt(p->ssdp_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) < 0) { -#else /* _WIN32 */ - if(setsockopt(p->ssdp_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { -#endif /* _WIN32 */ - /* non fatal error ! */ - debug_printf("setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ...) FAILED\n", p->ssdp_socket); - } - if(evutil_make_socket_nonblocking(p->ssdp_socket) < 0) { - debug_printf("evutil_make_socket_nonblocking FAILED\n"); - } - - /* receive address */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - /*addr.sin_port = htons(SSDP_PORT);*/ - - if(multicastif) { - struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); - addr.sin_addr.s_addr = mc_if.s_addr; - if(setsockopt(p->ssdp_socket, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { - PRINT_SOCKET_ERROR("setsockopt"); - /* non fatal error ! */ - } - } - - /* bind the socket to the ssdp address in order to receive responses */ - if(bind(p->ssdp_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0) { - close(p->ssdp_socket); - return UPNPC_ERR_BIND_FAILED; - } - return UPNPC_OK; -} - -int upnpc_start(upnpc_t * p) -{ - struct timeval timeout; - if(p == NULL || p->base == NULL) - return UPNPC_ERR_INVALID_ARGS; - /* event on SSDP */ - p->ev_ssdp_recv = event_new(p->base, p->ssdp_socket, - EV_READ|EV_PERSIST, - (event_callback_fn)upnpc_receive_and_parse_ssdp, p); - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(event_add(p->ev_ssdp_recv, &timeout)) { - debug_printf("event_add FAILED\n"); - } - p->ev_ssdp_writable = event_new(p->base, p->ssdp_socket, - EV_WRITE, - (event_callback_fn)upnpc_send_ssdp_msearch, p); - if(event_add(p->ev_ssdp_writable, NULL)) { - debug_printf("event_add FAILED\n"); - } - return UPNPC_OK; -} - -int upnpc_set_local_address(upnpc_t * p, const char * address, uint16_t port) -{ - if(!p || !address) return UPNPC_ERR_INVALID_ARGS; - p->local_address = strdup(address); /* TODO check error */ - p->local_port = port; - return UPNPC_OK; -} - -#ifdef ENABLE_UPNP_EVENTS -int upnpc_set_event_callback(upnpc_t * p, upnpc_event_callback_fn cb) -{ - if(!p || !cb) return UPNPC_ERR_INVALID_ARGS; - p->value_changed_cb = cb; - return UPNPC_OK; -} -#endif /* ENABLE_UPNP_EVENTS */ - -static void upnpc_device_finalize(upnpc_device_t * d) -{ - d->state = 0; - free(d->root_desc_location); - d->root_desc_location = NULL; - free(d->control_cif_url); - d->control_cif_url = NULL; - free(d->event_cif_url); - d->event_cif_url = NULL; - free(d->cif_service_type); - d->cif_service_type = NULL; - free(d->control_conn_url); - d->control_conn_url = NULL; - free(d->event_conn_url); - d->event_conn_url = NULL; - free(d->conn_service_type); - d->conn_service_type = NULL; - if(d->desc_conn) { - evhttp_connection_free(d->desc_conn); - d->desc_conn = NULL; - } - if(d->soap_conn) { - evhttp_connection_free(d->soap_conn); - d->soap_conn = NULL; - } - ClearNameValueList(&d->soap_response_data); -#ifdef ENABLE_UPNP_EVENTS - free(d->event_conn_sid); - d->event_conn_sid = NULL; -#endif /* ENABLE_UPNP_EVENTS */ -} - -int upnpc_finalize(upnpc_t * p) -{ - if(!p) return UPNPC_ERR_INVALID_ARGS; - p->discover_device_index = 0; - if(p->ssdp_socket >= 0) { - close(p->ssdp_socket); - p->ssdp_socket = -1; - } - if(p->ev_ssdp_recv) { - event_free(p->ev_ssdp_recv); - p->ev_ssdp_recv = NULL; - } - if(p->ev_ssdp_writable) { - event_free(p->ev_ssdp_writable); - p->ev_ssdp_writable = NULL; - } - while(p->devices != NULL) { - upnpc_device_t * d = p->devices; - upnpc_device_finalize(d); - p->devices = d->next; - free(d); - } - free(p->local_address); - p->local_address = NULL; -#ifdef ENABLE_UPNP_EVENTS - if(p->http_server) { - evhttp_free(p->http_server); - p->http_server = NULL; - } -#endif /* ENABLE_UPNP_EVENTS */ - return UPNPC_OK; -} - -#ifdef ENABLE_UPNP_EVENTS -int upnpc_event_subscribe(upnpc_device_t * p) -{ - char hostname[MAXHOSTNAMELEN+1]; - char hostname_port[MAXHOSTNAMELEN+1+6]; - unsigned short port; - char * path; - unsigned int scope_id; - struct evhttp_request * req; - struct evkeyvalq * headers; - char callback_header[7+15+1+5+9+2+1]; - - if(p->parent->http_server == NULL) { - /* HTTP server to receive event notifications */ - p->parent->http_server = evhttp_new(p->parent->base); - if(p->parent->http_server == NULL) { - debug_printf("evhttp_new() FAILED\n"); - return -1; - } - evhttp_set_extended_methods(p->parent->http_server, ext_methods); - evhttp_set_allowed_methods(p->parent->http_server, EVHTTP_REQ_NOTIFY); - evhttp_set_cb(p->parent->http_server, "/evt_conn", upnpc_event_conn_req, p); - if(evhttp_bind_socket(p->parent->http_server, p->parent->local_address, p->parent->local_port) < 0) { - debug_printf("evhttp_bind_socket() FAILED\n"); - return -1; - } - } - /*if(!parseURL(p->event_cif_url, hostname, &port, &path, &scope_id)) {*/ - if(!parseURL(p->event_conn_url, hostname, &port, &path, &scope_id)) { - return -1; - } - if(port != 80) - snprintf(hostname_port, sizeof(hostname_port), "%s:%hu", hostname, port); - else - strncpy(hostname_port, hostname, sizeof(hostname_port)); - if(p->soap_conn == NULL) { - p->soap_conn = evhttp_connection_base_new(p->parent->base, NULL, hostname, port); - } - evhttp_connection_set_extended_methods(p->soap_conn, ext_methods); - req = evhttp_request_new(upnpc_subscribe_response, p); - headers = evhttp_request_get_output_headers(req); - /*buffer = evhttp_request_get_output_buffer(req);*/ - evhttp_add_header(headers, "Host", hostname_port); - /*evhttp_add_header(headers, "User-Agent", "***");*/ - snprintf(callback_header, sizeof(callback_header), "", p->parent->local_address, p->parent->local_port); - evhttp_add_header(headers, "Callback", callback_header); - evhttp_add_header(headers, "NT", "upnp:event"); - /*evhttp_add_header(headers, "NTS", "");*/ - evhttp_add_header(headers, "Timeout", "3600"); - /*evbuffer_add(buffer, body, body_len);*/ - evhttp_make_request(p->soap_conn, req, EVHTTP_REQ_SUBSCRIBE, path); - p->state |= UPNPC_DEVICE_SOAP_REQ; - return 0; -} -#endif /* ENABLE_UPNP_EVENTS */ - -int upnpc_get_external_ip_address(upnpc_device_t * p) -{ - return upnpc_send_soap_request(p, p->control_conn_url, - p->conn_service_type/*"urn:schemas-upnp-org:service:WANIPConnection:1"*/, - "GetExternalIPAddress", NULL, 0); -} - -int upnpc_get_link_layer_max_rate(upnpc_device_t * p) -{ - return upnpc_send_soap_request(p, p->control_cif_url, - p->cif_service_type/*"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"*/, - "GetCommonLinkProperties", NULL, 0); -} - -int upnpc_delete_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - const char * proto) -{ - struct upnp_args args[3]; - char ext_port_str[8]; - - if(proto == NULL || ext_port == 0) - return UPNPC_ERR_INVALID_ARGS; - snprintf(ext_port_str, sizeof(ext_port_str), "%hu", ext_port); - args[0].elt = "NewRemoteHost"; - args[0].val = remote_host?remote_host:""; - args[1].elt = "NewExternalPort"; - args[1].val = ext_port_str; - args[2].elt = "NewProtocol"; - args[2].val = proto; - return upnpc_send_soap_request(p, p->control_conn_url, - p->conn_service_type,/*"urn:schemas-upnp-org:service:WANIPConnection:1",*/ - "DeletePortMapping", - args, 3); -} - -int upnpc_add_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - unsigned short int_port, const char * int_client, - const char * proto, const char * description, - unsigned int lease_duration) -{ - struct upnp_args args[8]; - char lease_duration_str[16]; - char int_port_str[8]; - char ext_port_str[8]; - - if(int_client == NULL || int_port == 0 || ext_port == 0 || proto == NULL) - return UPNPC_ERR_INVALID_ARGS; - snprintf(lease_duration_str, sizeof(lease_duration_str), "%u", lease_duration); - snprintf(int_port_str, sizeof(int_port_str), "%hu", int_port); - snprintf(ext_port_str, sizeof(ext_port_str), "%hu", ext_port); - args[0].elt = "NewRemoteHost"; - args[0].val = remote_host?remote_host:""; - args[1].elt = "NewExternalPort"; - args[1].val = ext_port_str; - args[2].elt = "NewProtocol"; - args[2].val = proto; - args[3].elt = "NewInternalPort"; - args[3].val = int_port_str; - args[4].elt = "NewInternalClient"; - args[4].val = int_client; - args[5].elt = "NewEnabled"; - args[5].val = "1"; - args[6].elt = "NewPortMappingDescription"; - args[6].val = description?description:"miniupnpc-libevent"; - args[7].elt = "NewLeaseDuration"; - args[7].val = lease_duration_str; - return upnpc_send_soap_request(p, p->control_conn_url, - p->conn_service_type/*"urn:schemas-upnp-org:service:WANIPConnection:1"*/, - "AddPortMapping", - args, 8); -} - -int upnpc_get_status_info(upnpc_device_t * p) -{ - return upnpc_send_soap_request(p, p->control_conn_url, - p->conn_service_type/*"urn:schemas-upnp-org:service:WANIPConnection:1"*/, - "GetStatusInfo", NULL, 0); -} diff --git a/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.h b/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.h deleted file mode 100644 index 47bc896..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/miniupnpc-libevent.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id: miniupnpc-libevent.h,v 1.13 2015/07/22 13:48:37 nanard Exp $ */ -/* miniupnpc-libevent - * Copyright (c) 2008-2015, Thomas BERNARD - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef MINIUPNPC_LIBEVENT_H_INCLUDED -#define MINIUPNPC_LIBEVENT_H_INCLUDED - -#include - -#include "declspec.h" -#include "upnpreplyparse.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MINIUPNPC_LIBEVENT_API_VERSION 1 - -#define UPNPC_OK 0 -#define UPNPC_ERR_INVALID_ARGS (-1) -#define UPNPC_ERR_SOCKET_FAILED (-2) -#define UPNPC_ERR_BIND_FAILED (-3) -#define UPNPC_ERR_REQ_IN_PROGRESS (-4) - -#define UPNPC_ERR_NO_DEVICE_FOUND (-100) -#define UPNPC_ERR_ROOT_DESC_ERROR (-101) -#define UPNPC_ERR_NOT_IGD (-102) -#define UPNPC_ERR_NOT_CONNECTED (-103) - -/* device->state masks */ -#define UPNPC_DEVICE_SOAP_REQ (0x0001) -#define UPNPC_DEVICE_GETSTATUS (0x0002) -#define UPNPC_DEVICE_CONNECTED (0x4000) -#define UPNPC_DEVICE_READY (0x8000) - -typedef struct upnpc_device upnpc_device_t; -typedef struct upnpc upnpc_t; - -typedef void(* upnpc_callback_fn)(int, upnpc_t *, upnpc_device_t *, void *); -#ifdef ENABLE_UPNP_EVENTS -typedef void(* upnpc_event_callback_fn)(upnpc_t *, upnpc_device_t *, void *, const char *, const char *, const char *); -#endif /* ENABLE_UPNP_EVENTS */ - -struct upnpc_device { - upnpc_t * parent; - upnpc_device_t * next; - char * root_desc_location; - struct evhttp_connection * desc_conn; - char * control_cif_url; - char * event_cif_url; - char * cif_service_type; - char * control_conn_url; - char * event_conn_url; - char * conn_service_type; - struct evhttp_connection * soap_conn; - struct NameValueParserData soap_response_data; - unsigned int state; -#ifdef ENABLE_UPNP_EVENTS - char * event_conn_sid; -#endif /* ENABLE_UPNP_EVENTS */ -}; - -struct upnpc { - struct event_base * base; - evutil_socket_t ssdp_socket; - struct event * ev_ssdp_recv; - struct event * ev_ssdp_writable; - int discover_device_index; - upnpc_device_t * devices; - upnpc_callback_fn ready_cb; - upnpc_callback_fn soap_cb; - void * cb_data; -#ifdef ENABLE_UPNP_EVENTS - struct evhttp * http_server; - upnpc_event_callback_fn value_changed_cb; -#endif /* ENABLE_UPNP_EVENTS */ - char * local_address; - uint16_t local_port; - unsigned char ttl; -}; - -int upnpc_init(upnpc_t * p, struct event_base * base, const char * multicastif, - upnpc_callback_fn ready_cb, upnpc_callback_fn soap_cb, void * cb_data); - -int upnpc_set_local_address(upnpc_t * p, const char * address, uint16_t port); - -#ifdef ENABLE_UPNP_EVENTS -int upnpc_set_event_callback(upnpc_t * p, upnpc_event_callback_fn cb); -#endif /* ENABLE_UPNP_EVENTS */ - -int upnpc_start(upnpc_t * p); - -int upnpc_finalize(upnpc_t * p); - -#ifdef ENABLE_UPNP_EVENTS -int upnpc_event_subscribe(upnpc_device_t * p); -#endif /* ENABLE_UPNP_EVENTS */ - -int upnpc_get_external_ip_address(upnpc_device_t * p); - -int upnpc_get_link_layer_max_rate(upnpc_device_t * p); - -int upnpc_add_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - unsigned short int_port, const char * int_client, - const char * proto, const char * description, - unsigned int lease_duration); - -int upnpc_delete_port_mapping(upnpc_device_t * p, - const char * remote_host, unsigned short ext_port, - const char * proto); - -int upnpc_get_status_info(upnpc_device_t * p); - -#ifdef __cplusplus -} -#endif - -#endif /* MINIUPNPC_LIBEVENT_H_INCLUDED */ - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/minixml.c b/src/contrib/miniupnp/miniupnpc-libevent/minixml.c deleted file mode 100644 index 3e201ec..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/minixml.c +++ /dev/null @@ -1,229 +0,0 @@ -/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ -/* minixml.c : the minimum size a xml parser can be ! */ -/* Project : miniupnp - * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - -Copyright (c) 2005-2014, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -#include -#include "minixml.h" - -/* parseatt : used to parse the argument list - * return 0 (false) in case of success and -1 (true) if the end - * of the xmlbuffer is reached. */ -static int parseatt(struct xmlparser * p) -{ - const char * attname; - int attnamelen; - const char * attvalue; - int attvaluelen; - while(p->xml < p->xmlend) - { - if(*p->xml=='/' || *p->xml=='>') - return 0; - if( !IS_WHITE_SPACE(*p->xml) ) - { - char sep; - attname = p->xml; - attnamelen = 0; - while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) - { - attnamelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - while(*(p->xml++) != '=') - { - if(p->xml >= p->xmlend) - return -1; - } - while(IS_WHITE_SPACE(*p->xml)) - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - sep = *p->xml; - if(sep=='\'' || sep=='\"') - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - attvalue = p->xml; - attvaluelen = 0; - while(*p->xml != sep) - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - else - { - attvalue = p->xml; - attvaluelen = 0; - while( !IS_WHITE_SPACE(*p->xml) - && *p->xml != '>' && *p->xml != '/') - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - /*printf("%.*s='%.*s'\n", - attnamelen, attname, attvaluelen, attvalue);*/ - if(p->attfunc) - p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); - } - p->xml++; - } - return -1; -} - -/* parseelt parse the xml stream and - * call the callback functions when needed... */ -static void parseelt(struct xmlparser * p) -{ - int i; - const char * elementname; - while(p->xml < (p->xmlend - 1)) - { - if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); - p->xml += 3; - } - else if((p->xml)[0]=='<' && (p->xml)[1]!='?') - { - i = 0; elementname = ++p->xml; - while( !IS_WHITE_SPACE(*p->xml) - && (*p->xml!='>') && (*p->xml!='/') - ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - /* to ignore namespace : */ - if(*p->xml==':') - { - i = 0; - elementname = ++p->xml; - } - } - if(i>0) - { - if(p->starteltfunc) - p->starteltfunc(p->data, elementname, i); - if(parseatt(p)) - return; - if(*p->xml!='/') - { - const char * data; - i = 0; data = ++p->xml; - if (p->xml >= p->xmlend) - return; - while( IS_WHITE_SPACE(*p->xml) ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(memcmp(p->xml, "xml += 9; - data = p->xml; - i = 0; - while(memcmp(p->xml, "]]>", 3) != 0) - { - i++; p->xml++; - if ((p->xml + 3) >= p->xmlend) - return; - } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); - while(*p->xml!='<') - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - } - else - { - while(*p->xml!='<') - { - i++; p->xml++; - if ((p->xml + 1) >= p->xmlend) - return; - } - if(i>0 && p->datafunc && *(p->xml + 1) == '/') - p->datafunc(p->data, data, i); - } - } - } - else if(*p->xml == '/') - { - i = 0; elementname = ++p->xml; - if (p->xml >= p->xmlend) - return; - while((*p->xml != '>')) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(p->endeltfunc) - p->endeltfunc(p->data, elementname, i); - p->xml++; - } - } - else - { - p->xml++; - } - } -} - -/* the parser must be initialized before calling this function */ -void parsexml(struct xmlparser * parser) -{ - parser->xml = parser->xmlstart; - parser->xmlend = parser->xmlstart + parser->xmlsize; - parseelt(parser); -} - - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/minixml.h b/src/contrib/miniupnp/miniupnpc-libevent/minixml.h deleted file mode 100644 index 9f43aa4..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/upnpc-libevent.c b/src/contrib/miniupnp/miniupnpc-libevent/upnpc-libevent.c deleted file mode 100644 index ce6ec4a..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/upnpc-libevent.c +++ /dev/null @@ -1,252 +0,0 @@ -/* $Id: upnpc-libevent.c,v 1.11 2014/12/02 13:33:42 nanard Exp $ */ -/* miniupnpc-libevent - * Copyright (c) 2008-2014, Thomas BERNARD - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "miniupnpc-libevent.h" - -static struct event_base *base = NULL; -static char local_address[32]; - -static void sighandler(int signal) -{ - (void)signal; - /*printf("signal %d\n", signal);*/ - if(base != NULL) - event_base_loopbreak(base); -} - -/* ready callback */ -static void ready(int code, upnpc_t * p, upnpc_device_t * d, void * data) -{ - (void)data; (void)p; - - if(code == 200) { - printf("READY ! %d\n", code); - printf(" root_desc_location='%s'\n", d->root_desc_location); - /* 1st request */ -#ifdef ENABLE_UPNP_EVENTS - upnpc_event_subscribe(d); -#else - upnpc_get_status_info(d); -#endif /* ENABLE_UPNP_EVENTS */ - } else { - printf("DISCOVER ERROR : %d\n", code); - switch(code) { - case UPNPC_ERR_NO_DEVICE_FOUND: - printf("UPNPC_ERR_NO_DEVICE_FOUND\n"); - break; - case UPNPC_ERR_ROOT_DESC_ERROR: - printf("UPNPC_ERR_ROOT_DESC_ERROR\n"); - break; - case 404: - printf("Root desc not found (404)\n"); - break; - default: - printf("unknown error\n"); - } - } -} - -static enum { - EGetStatusInfo = 0, - EGetExtIp, - EGetMaxRate, - EAddPortMapping, - EDeletePortMapping, - EFinished - } state = EGetStatusInfo; - -/* soap callback */ -static void soap(int code, upnpc_t * p, upnpc_device_t * d, void * data) -{ - (void)data; (void)p; - - printf("SOAP ! %d\n", code); - if(code == 200) { - switch(state) { - case EGetStatusInfo: - printf("ConnectionStatus=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus")); - printf("LastConnectionError=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLastConnectionError")); - printf("Uptime=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewUptime")); - upnpc_get_external_ip_address(d); - state = EGetExtIp; - break; - case EGetExtIp: - printf("ExternalIpAddress=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewExternalIPAddress")); - upnpc_get_link_layer_max_rate(d); - state = EGetMaxRate; - break; - case EGetMaxRate: - printf("DownStream MaxBitRate = %s\t", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1DownstreamMaxBitRate")); - upnpc_add_port_mapping(d, NULL, 60001, 60002, local_address, "TCP", "test port mapping", 0); - printf("UpStream MaxBitRate = %s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1UpstreamMaxBitRate")); - state = EAddPortMapping; - break; - case EAddPortMapping: - printf("AddPortMapping OK!\n"); - upnpc_delete_port_mapping(d, NULL, 60001, "TCP"); - state = EDeletePortMapping; - break; - case EDeletePortMapping: - printf("DeletePortMapping OK!\n"); - state = EFinished; - break; - default: - printf("EFinished : breaking\n"); - event_base_loopbreak(base); - } - } else { - printf("SOAP error :\n"); - printf(" faultcode='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultcode")); - printf(" faultstring='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultstring")); - printf(" errorCode=%s\n", GetValueFromNameValueList(&d->soap_response_data, "errorCode")); - printf(" errorDescription='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "errorDescription")); - event_base_loopbreak(base); - } -} - -#ifdef ENABLE_UPNP_EVENTS -/* event callback */ -static void event_callback(upnpc_t * p, upnpc_device_t * d, void * data, - const char * service_id, const char * property_name, const char * property_value) -{ - (void)p; (void)d; (void)data; - printf("PROPERTY VALUE CHANGE (service=%s): %s=%s\n", service_id, property_name, property_value); -} -#endif /* ENABLE_UPNP_EVENTS */ - -/* use a UDP "connection" to 8.8.8.8 - * to retrieve local address */ -int find_local_address(void) -{ - int s; - struct sockaddr_in local, remote; - socklen_t len; - - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(s < 0) { - perror("socket"); - return -1; - } - - memset(&local, 0, sizeof(local)); - memset(&remote, 0, sizeof(remote)); - /* bind to local port 4567 */ - local.sin_family = AF_INET; - local.sin_port = htons(4567); - local.sin_addr.s_addr = htonl(INADDR_ANY); - if(bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) { - perror("bind"); - return -1; - } - /* "connect" google's DNS server at 8.8.8.8 port 4567 */ - remote.sin_family = AF_INET; - remote.sin_port = htons(4567); - remote.sin_addr.s_addr = inet_addr("8.8.8.8"); - if(connect(s, (struct sockaddr *)&remote, sizeof(remote)) < 0) { - perror("connect"); - return -1; - } - len = sizeof(local); - if(getsockname(s, (struct sockaddr *)&local, &len) < 0) { - perror("getsockname"); - return -1; - } - if(inet_ntop(AF_INET, &(local.sin_addr), local_address, sizeof(local_address)) == NULL) { - perror("inet_ntop"); - return -1; - } - printf("local address : %s\n", local_address); - close(s); - return 0; -} - -/* program entry point */ - -int main(int argc, char * * argv) -{ - struct sigaction sa; - upnpc_t upnp; - char * multicast_if = NULL; - - if(argc > 1) { - multicast_if = argv[1]; - } - - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = sighandler; - if(sigaction(SIGINT, &sa, NULL) < 0) { - perror("sigaction"); - } - - if(find_local_address() < 0) { - fprintf(stderr, "failed to get local address\n"); - return 1; - } -#ifdef DEBUG - event_enable_debug_mode(); -#if LIBEVENT_VERSION_NUMBER >= 0x02010100 - event_enable_debug_logging(EVENT_DBG_ALL); /* Libevent 2.1.1 */ -#endif /* LIBEVENT_VERSION_NUMBER >= 0x02010100 */ -#endif /* DEBUG */ - printf("Using libevent %s\n", event_get_version()); - if(LIBEVENT_VERSION_NUMBER != event_get_version_number()) { - fprintf(stderr, "WARNING build using libevent %s", LIBEVENT_VERSION); - } - - base = event_base_new(); - if(base == NULL) { - fprintf(stderr, "event_base_new() failed\n"); - return 1; - } -#ifdef DEBUG - printf("Using Libevent with backend method %s.\n", - event_base_get_method(base)); -#endif /* DEBUG */ - - if(upnpc_init(&upnp, base, multicast_if, ready, soap, &upnp) != UPNPC_OK) { - fprintf(stderr, "upnpc_init() failed\n"); - return 1; - } - upnpc_set_local_address(&upnp, local_address, 50000); -#ifdef ENABLE_UPNP_EVENTS - upnpc_set_event_callback(&upnp, event_callback); -#endif /* ENABLE_UPNP_EVENTS */ - if(upnpc_start(&upnp) != UPNPC_OK) { - fprintf(stderr, "upnp_start() failed\n"); - return 1; - } - - event_base_dispatch(base); /* TODO : check return value */ - printf("finishing...\n"); - - upnpc_finalize(&upnp); - event_base_free(base); - -#if LIBEVENT_VERSION_NUMBER >= 0x02010100 - libevent_global_shutdown(); /* Libevent 2.1.1 */ -#endif - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.c b/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.c deleted file mode 100644 index 5de5796..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "upnpreplyparse.h" -#include "minixml.h" - -static void -NameValueParserStartElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - data->topelt = 1; - if(l>63) - l = 63; - memcpy(data->curelt, name, l); - data->curelt[l] = '\0'; - data->cdata = NULL; - data->cdatalen = 0; -} - -static void -NameValueParserEndElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - (void)name; - (void)l; - if(!data->topelt) - return; - if(strcmp(data->curelt, "NewPortListing") != 0) - { - int l; - /* standard case. Limited to n chars strings */ - l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); - if(nv == NULL) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserEndElt"); -#endif /* DEBUG */ - return; - } - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - if(data->cdata != NULL) - { - memcpy(nv->value, data->cdata, l); - nv->value[l] = '\0'; - } - else - { - nv->value[0] = '\0'; - } - nv->l_next = data->l_head; /* insert in list */ - data->l_head = nv; - } - data->cdata = NULL; - data->cdatalen = 0; - data->topelt = 0; -} - -static void -NameValueParserGetData(void * d, const char * datas, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - if(strcmp(data->curelt, "NewPortListing") == 0) - { - /* specific case for NewPortListing which is a XML Document */ - data->portListing = malloc(l + 1); - if(!data->portListing) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserGetData"); -#endif /* DEBUG */ - return; - } - memcpy(data->portListing, datas, l); - data->portListing[l] = '\0'; - data->portListingLength = l; - } - else - { - /* standard case. */ - data->cdata = datas; - data->cdatalen = l; - } -} - -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) -{ - struct xmlparser parser; - data->l_head = NULL; - data->portListing = NULL; - data->portListingLength = 0; - /* init xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = NameValueParserEndElt; - parser.datafunc = NameValueParserGetData; - parser.attfunc = 0; - parsexml(&parser); -} - -void -ClearNameValueList(struct NameValueParserData * pdata) -{ - struct NameValue * nv; - if(pdata->portListing) - { - free(pdata->portListing); - pdata->portListing = NULL; - pdata->portListingLength = 0; - } - while((nv = pdata->l_head) != NULL) - { - pdata->l_head = nv->l_next; - free(nv); - } -} - -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - for(nv = pdata->l_head; - (nv != NULL) && (p == NULL); - nv = nv->l_next) - { - if(strcmp(nv->name, Name) == 0) - p = nv->value; - } - return p; -} - -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - -/* debug all-in-one function - * do parsing then display to stdout */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize) -{ - struct NameValueParserData pdata; - struct NameValue * nv; - ParseNameValue(buffer, bufsize, &pdata); - for(nv = pdata.l_head; - nv != NULL; - nv = nv->l_next) - { - printf("%s = %s\n", nv->name, nv->value); - } - ClearNameValueList(&pdata); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.h b/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.h deleted file mode 100644 index 6badd15..0000000 --- a/src/contrib/miniupnp/miniupnpc-libevent/upnpreplyparse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - struct NameValue * l_head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/.gitignore b/src/contrib/miniupnp/miniupnpc/.gitignore deleted file mode 100644 index ba06bcc..0000000 --- a/src/contrib/miniupnp/miniupnpc/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -deb_dist/ -build/ -*.o -*.a -*.so -*.dll -*.dll.def -*.exe -*.lib -*.dylib -Makefile.bak -miniupnpcstrings.h -pythonmodule -pythonmodule3 -upnpc-shared -upnpc-static -minihttptestserver -minixmlvalid -testminiwget -validateminiwget -validateminixml -java/miniupnpc_*.jar -_jnaerator.* -out.errors.txt -jnaerator-*.jar -miniupnpc.h.bak -testupnpreplyparse -validateupnpreplyparse -testportlistingparse -validateportlistingparse -listdevices -testigddescparse -validateigddescparse -dist/ -miniupnpc.egg-info/ -init -miniupnpc.pc diff --git a/src/contrib/miniupnp/miniupnpc/CMakeLists.txt b/src/contrib/miniupnp/miniupnpc/CMakeLists.txt deleted file mode 100644 index c1061b1..0000000 --- a/src/contrib/miniupnp/miniupnpc/CMakeLists.txt +++ /dev/null @@ -1,190 +0,0 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -project (miniupnpc C) - -set (MINIUPNPC_VERSION 2.1) -set (MINIUPNPC_API_VERSION 17) - -option (UPNPC_BUILD_STATIC "Build static library" TRUE) -option (UPNPC_BUILD_SHARED "Build shared library" TRUE) -option (UPNPC_BUILD_TESTS "Build test executables" TRUE) -option (UPNPC_BUILD_SAMPLE "Build sample executables" TRUE) -option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE) - -if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) - message (FATAL "Both shared and static libraries are disabled!") -endif () - -# Interface library for compile definitions, flags and option -add_library(miniupnpc-private INTERFACE) - -if (NO_GETADDRINFO) - target_compile_definitions(miniupnpc-private INTERFACE NO_GETADDRINFO) -endif () - -if (NOT WIN32) - target_compile_definitions(miniupnpc-private INTERFACE - MINIUPNPC_SET_SOCKET_TIMEOUT - _BSD_SOURCE _DEFAULT_SOURCE) - if (NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") - # add_definitions (-D_POSIX_C_SOURCE=200112L) - target_compile_definitions(miniupnpc-private INTERFACE _XOPEN_SOURCE=600) - endif () -else () - target_compile_definitions(miniupnpc-private INTERFACE _WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends -endif () - -if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_compile_definitions(miniupnpc-private INTERFACE _DARWIN_C_SOURCE) -endif () - -# Set compiler specific build flags -if (CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - target_compile_options(miniupnpc-private INTERFACE -Wall) -endif () - -# Suppress noise warnings -if (MSVC) - target_compile_definitions(miniupnpc-private INTERFACE _CRT_SECURE_NO_WARNINGS) -endif() - -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/miniupnpcstrings.h) -target_include_directories(miniupnpc-private INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) - -set (MINIUPNPC_SOURCES - igd_desc_parse.c - miniupnpc.c - minixml.c - minisoap.c - minissdpc.c - miniwget.c - upnpcommands.c - upnpdev.c - upnpreplyparse.c - upnperrors.c - connecthostport.c - portlistingparse.c - receivedata.c - connecthostport.h - igd_desc_parse.h - minisoap.h - minissdpc.h - miniupnpc.h - miniupnpctypes.h - miniwget.h - minixml.h - portlistingparse.h - receivedata.h - upnpcommands.h - upnpdev.h - upnperrors.h - upnpreplyparse.h - ${CMAKE_CURRENT_BINARY_DIR}/miniupnpcstrings.h -) - -if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c) -endif () - -if (WIN32) - target_link_libraries(miniupnpc-private INTERFACE ws2_32 iphlpapi) -#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris") -# find_library (SOCKET_LIBRARY NAMES socket) -# find_library (NSL_LIBRARY NAMES nsl) -# find_library (RESOLV_LIBRARY NAMES resolv) -# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS}) -endif () - - -if (UPNPC_BUILD_STATIC) - add_library (libminiupnpc-static STATIC ${MINIUPNPC_SOURCES}) - set_target_properties (libminiupnpc-static PROPERTIES OUTPUT_NAME "miniupnpc") - target_link_libraries (libminiupnpc-static PRIVATE miniupnpc-private) - target_include_directories(libminiupnpc-static INTERFACE ../${CMAKE_CURRENT_SOURCE_DIR}) - target_compile_definitions(libminiupnpc-static PUBLIC MINIUPNP_STATICLIB) - - install (TARGETS libminiupnpc-static - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - - if (UPNPC_BUILD_SAMPLE) - add_executable (upnpc-static upnpc.c) - target_link_libraries (upnpc-static PRIVATE libminiupnpc-static) - target_include_directories(upnpc-static PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) - endif () -endif () - -if (UPNPC_BUILD_SHARED) - add_library (libminiupnpc-shared SHARED ${MINIUPNPC_SOURCES}) - set_target_properties (libminiupnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc") - set_target_properties (libminiupnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION}) - set_target_properties (libminiupnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION}) - target_link_libraries (libminiupnpc-shared PRIVATE miniupnpc-private) - target_compile_definitions(libminiupnpc-shared PRIVATE MINIUPNP_EXPORTS) - - target_include_directories(libminiupnpc-static INTERFACE ../${CMAKE_CURRENT_SOURCE_DIR}) - if (WIN32) - target_link_libraries(libminiupnpc-shared INTERFACE ws2_32 iphlpapi) - endif() - - install (TARGETS libminiupnpc-shared - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - - if (UPNPC_BUILD_SAMPLE) - add_executable (upnpc-shared upnpc.c) - target_link_libraries (upnpc-shared PRIVATE libminiupnpc-shared) - target_include_directories(upnpc-shared PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) - endif () -endif () - -if (UPNPC_BUILD_TESTS) - add_library(miniupnpc-tests INTERFACE) - target_link_libraries(miniupnpc-tests INTERFACE miniupnpc-private) - target_compile_definitions(miniupnpc-tests INTERFACE MINIUPNP_STATICLIB) - - add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c) - target_link_libraries (testminixml PRIVATE miniupnpc-tests) - - add_executable (minixmlvalid minixmlvalid.c minixml.c) - target_link_libraries (minixmlvalid PRIVATE miniupnpc-tests) - - add_executable (testupnpreplyparse testupnpreplyparse.c - minixml.c upnpreplyparse.c) - target_link_libraries (testupnpreplyparse PRIVATE miniupnpc-tests) - - add_executable (testigddescparse testigddescparse.c - igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c - upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c - portlistingparse.c receivedata.c - ) - target_link_libraries (testigddescparse PRIVATE miniupnpc-tests) - - add_executable (testminiwget testminiwget.c - miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c - upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c - portlistingparse.c receivedata.c - ) - target_link_libraries (testminiwget PRIVATE miniupnpc-tests) - -# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget) -endif () - -install (FILES - miniupnpc.h - miniwget.h - upnpcommands.h - igd_desc_parse.h - upnpreplyparse.h - upnperrors.h - upnpdev.h - miniupnpctypes.h - portlistingparse.h - miniupnpc_declspec.h - DESTINATION include/miniupnpc -) - -# vim: ts=2:sw=2 diff --git a/src/contrib/miniupnp/miniupnpc/Changelog.txt b/src/contrib/miniupnp/miniupnpc/Changelog.txt deleted file mode 100644 index bb2c042..0000000 --- a/src/contrib/miniupnp/miniupnpc/Changelog.txt +++ /dev/null @@ -1,711 +0,0 @@ -$Id: Changelog.txt,v 1.235 2018/05/07 11:05:16 nanard Exp $ -miniUPnP client Changelog. - -VERSION 2.1 : released 2018/05/07 - -2018/05/07: - CMake Modernize and cleanup CMakeLists.txt - Update MS Visual Studio projects - -2018/04/30: - listdevices: show devices sorted by XML desc URL - -2018/04/26: - Small fix in miniupnpcmodule.c (python module) - Support cross compiling in Makefile.mingw - -2018/04/06: - Use SOCKET type instead of int (for Win64 compilation) - Increments API_VERSION to 17 - -2018/02/22: - Disable usage of MiniSSDPd when using -m option - -2017/12/11: - Fix buffer over run in minixml.c - Fix uninitialized variable access in upnpreplyparse.c - -2017/05/05: - Fix CVE-2017-8798 Thanks to tin/Team OSTStrom - -2016/11/11: - check strlen before memcmp in XML parsing portlistingparse.c - fix build under SOLARIS and CYGWIN - -2016/10/11: - Add python 3 compatibility to IGD test - -VERSION 2.0 : released 2016/04/19 - -2016/01/24: - change miniwget to return HTTP status code - increments API_VERSION to 16 - -2016/01/22: - Improve UPNPIGD_IsConnected() to check if WAN address is not private. - parse HTTP response status line in miniwget.c - -2015/10/26: - snprintf() overflow check. check overflow in simpleUPnPcommand2() - -2015/10/25: - fix compilation with old macs - fix compilation with mingw32 (for Appveyor) - fix python module for python <= 2.3 - -2015/10/08: - Change sameport to localport - see https://github.com/miniupnp/miniupnp/pull/120 - increments API_VERSION to 15 - -2015/09/15: - Fix buffer overflow in igd_desc_parse.c/IGDstartelt() - Discovered by Aleksandar Nikolic of Cisco Talos - -2015/08/28: - move ssdpDiscoverDevices() to minissdpc.c - -2015/08/27: - avoid unix socket leak in getDevicesFromMiniSSDPD() - -2015/08/16: - Also accept "Up" as ConnectionStatus value - -2015/07/23: - split getDevicesFromMiniSSDPD - add ttl argument to upnpDiscover() functions - increments API_VERSION to 14 - -2015/07/22: - Read USN from SSDP messages. - -2015/07/15: - Check malloc/calloc - -2015/06/16: - update getDevicesFromMiniSSDPD() to process longer minissdpd - responses - -2015/05/22: - add searchalltypes param to upnpDiscoverDevices() - increments API_VERSION to 13 - -2015/04/30: - upnpc: output version on the terminal - -2015/04/27: - _BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE - fix CMakeLists.txt COMPILE_DEFINITIONS - fix getDevicesFromMiniSSDPD() not setting scope_id - improve -r command of upnpc command line tool - -2014/11/17: - search all : - upnpDiscoverDevices() / upnpDiscoverAll() functions - listdevices executable - increment API_VERSION to 12 - validate igd_desc_parse - -2014/11/13: - increment API_VERSION to 11 - -2014/11/05: - simplified function GetUPNPUrls() - -2014/09/11: - use remoteHost arg of DeletePortMapping - -2014/09/06: - Fix python3 build - -2014/07/01: - Fix parsing of IGD2 root descriptions - -2014/06/10: - rename LIBSPEC to MINIUPNP_LIBSPEC - -2014/05/15: - Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange - -2014/02/05: - handle EINPROGRESS after connect() - -2014/02/03: - minixml now handle XML comments - -VERSION 1.9 : released 2014/01/31 - -2014/01/31: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - increment API_VERSION to 10 - -2013/12/09: - --help and -h arguments in upnpc.c - -2013/10/07: - fixed potential buffer overrun in miniwget.c - Modified UPNP_GetValidIGD() to check for ExternalIpAddress - -2013/08/01: - define MAXHOSTNAMELEN if not already done - -2013/06/06: - update upnpreplyparse to allow larger values (128 chars instead of 64) - -2013/05/14: - Update upnpreplyparse to take into account "empty" elements - validate upnpreplyparse.c code with "make check" - -2013/05/03: - Fix Solaris build thanks to Maciej MaÅ‚ecki - -2013/04/27: - Fix testminiwget.sh for BSD - -2013/03/23: - Fixed Makefile for *BSD - -2013/03/11: - Update Makefile to use JNAerator version 0.11 - -2013/02/11: - Fix testminiwget.sh for use with dash - Use $(DESTDIR) in Makefile - -VERSION 1.8 : released 2013/02/06 - -2012/10/16: - fix testminiwget with no IPv6 support - -2012/09/27: - Rename all include guards to not clash with C99 - (7.1.3 Reserved identifiers). - -2012/08/30: - Added -e option to upnpc program (set description for port mappings) - -2012/08/29: - Python 3 support (thanks to Christopher Foo) - -2012/08/11: - Fix a memory link in UPNP_GetValidIGD() - Try to handle scope id in link local IPv6 URL under MS Windows - -2012/07/20: - Disable HAS_IP_MREQN on DragonFly BSD - -2012/06/28: - GetUPNPUrls() now inserts scope into link-local IPv6 addresses - -2012/06/23: - More error return checks in upnpc.c - #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id - parseURL() now parses IPv6 addresses scope - new parameter for miniwget() : IPv6 address scope - increment API_VERSION to 9 - -2012/06/20: - fixed CMakeLists.txt - -2012/05/29 - Improvements in testminiwget.sh - -VERSION 1.7 : released 2012/05/24 - -2012/05/01: - Cleanup settings of CFLAGS in Makefile - Fix signed/unsigned integer comparaisons - -2012/04/20: - Allow to specify protocol with TCP or UDP for -A option - -2012/04/09: - Only try to fetch XML description once in UPNP_GetValidIGD() - Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. - -2012/04/05: - minor improvements to minihttptestserver.c - -2012/03/15: - upnperrors.c returns valid error string for unrecognized error codes - -2012/03/08: - make minihttptestserver listen on loopback interface instead of 0.0.0.0 - -2012/01/25: - Maven installation thanks to Alexey Kuznetsov - -2012/01/21: - Replace WIN32 macro by _WIN32 - -2012/01/19: - Fixes in java wrappers thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc - Make and install .deb packages (python) thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc - -2012/01/07: - The multicast interface can now be specified by name with IPv4. - -2012/01/02: - Install man page - -2011/11/25: - added header to Port Mappings list in upnpc.c - -2011/10/09: - Makefile : make clean now removes jnaerator generated files. - MINIUPNPC_VERSION in miniupnpc.h (updated by make) - -2011/09/12: - added rootdescURL to UPNPUrls structure. - -VERSION 1.6 : released 2011/07/25 - -2011/07/25: - Update doc for version 1.6 release - -2011/06/18: - Fix for windows in miniwget.c - -2011/06/04: - display remote host in port mapping listing - -2011/06/03: - Fix in make install : there were missing headers - -2011/05/26: - Fix the socket leak in miniwget thanks to Richard Marsh. - Permit to add leaseduration in -a command. Display lease duration. - -2011/05/15: - Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 - -2011/05/09: - add a test in testminiwget.sh. - more error checking in miniwget.c - -2011/05/06: - Adding some tool to test and validate miniwget.c - simplified and debugged miniwget.c - -2011/04/11: - moving ReceiveData() to a receivedata.c file. - parsing presentation url - adding IGD v2 WANIPv6FirewallControl commands - -2011/04/10: - update of miniupnpcmodule.c - comments in miniwget.c, update in testminiwget - Adding errors codes from IGD v2 - new functions in upnpc.c for IGD v2 - -2011/04/09: - Support for litteral ip v6 address in miniwget - -2011/04/08: - Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - Updating APIVERSION - Supporting IPV6 in upnpDiscover() - Adding a -6 option to upnpc command line tool - -2011/03/18: - miniwget/parseURL() : return an error when url param is null. - fixing GetListOfPortMappings() - -2011/03/14: - upnpDiscover() now reporting an error code. - improvements in comments. - -2011/03/11: - adding miniupnpcstrings.h.cmake and CMakeLists.txt files. - -2011/02/15: - Implementation of GetListOfPortMappings() - -2011/02/07: - updates to minixml to support character data starting with spaces - minixml now support CDATA - upnpreplyparse treats specificaly - change in simpleUPnPcommand to return the buffer (simplification) - -2011/02/06: - Added leaseDuration argument to AddPortMapping() - Starting to implement GetListOfPortMappings() - -2011/01/11: - updating wingenminiupnpcstrings.c - -2011/01/04: - improving updateminiupnpcstrings.sh - -VERSION 1.5 : released 2011/01/01 - -2010/12/21: - use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo - -2010/12/11: - Improvements on getHTTPResponse() code. - -2010/12/09: - new code for miniwget that handle Chunked transfer encoding - using getHTTPResponse() in SOAP call code - Adding MANIFEST.in for 'python setup.py bdist_rpm' - -2010/11/25: - changes to minissdpc.c to compile under Win32. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 - -2010/09/17: - Various improvement to Makefile from MichaÅ‚ Górny - -2010/08/05: - Adding the script "external-ip.sh" from Reuben Hawkins - -2010/06/09: - update to python module to match modification made on 2010/04/05 - update to Java test code to match modification made on 2010/04/05 - all UPNP_* function now return an error if the SOAP request failed - at HTTP level. - -2010/04/17: - Using GetBestRoute() under win32 in order to find the - right interface to use. - -2010/04/12: - Retrying with HTTP/1.1 if HTTP/1.0 failed. see - http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 - -2010/04/07: - avoid returning duplicates in upnpDiscover() - -2010/04/05: - Create a connecthostport.h/.c with connecthostport() function - and use it in miniwget and miniupnpc. - Use getnameinfo() instead of inet_ntop or inet_ntoa - Work to make miniupnpc IPV6 compatible... - Add java test code. - Big changes in order to support device having both WANIPConnection - and WANPPPConnection. - -2010/04/04: - Use getaddrinfo() instead of gethostbyname() in miniwget. - -2010/01/06: - #define _DARWIN_C_SOURCE for Mac OS X - -2009/12/19: - Improve MinGW32 build - -2009/12/11: - adding a MSVC9 project to build the static library and executable - -2009/12/10: - Fixing some compilation stuff for Windows/MinGW - -2009/12/07: - adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS - some fixes for Windows when using virtual ethernet adapters (it is the - case with VMWare installed). - -2009/12/04: - some fixes for AmigaOS compilation - Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked - transfer encoding) - -2009/12/03: - updating printIDG and testigddescparse.c for debug. - modifications to compile under AmigaOS - adding a testminiwget program - Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked - transfer encoding - -2009/11/26: - fixing updateminiupnpcstrings.sh to take into account - which command that does not return an error code. - -VERSION 1.4 : released 2009/10/30 - -2009/10/16: - using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. - -2009/10/10: - Some fixes for compilation under Solaris - compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 - -2009/09/21: - fixing the code to ignore EINTR during connect() calls. - -2009/08/07: - Set socket timeout for connect() - Some cleanup in miniwget.c - -2009/08/04: - remove multiple redirections with -d in upnpc.c - Print textual error code in upnpc.c - Ignore EINTR during the connect() and poll() calls. - -2009/07/29: - fix in updateminiupnpcstrings.sh if OS name contains "/" - Sending a correct value for MX: field in SSDP request - -2009/07/20: - Change the Makefile to compile under Mac OS X - Fixed a stackoverflow in getDevicesFromMiniSSDPD() - -2009/07/09: - Compile under Haiku - generate miniupnpcstrings.h.in from miniupnpcstrings.h - -2009/06/04: - patching to compile under CygWin and cross compile for minGW - -VERSION 1.3 : - -2009/04/17: - updating python module - Use strtoull() when using C99 - -2009/02/28: - Fixed miniwget.c for compiling under sun - -2008/12/18: - cleanup in Makefile (thanks to Paul de Weerd) - minissdpc.c : win32 compatibility - miniupnpc.c : changed xmlns prefix from 'm' to 'u' - Removed NDEBUG (using DEBUG) - -2008/10/14: - Added the ExternalHost argument to DeletePortMapping() - -2008/10/11: - Added the ExternalHost argument to AddPortMapping() - Put a correct User-Agent: header in HTTP requests. - -VERSION 1.2 : - -2008/10/07: - Update docs - -2008/09/25: - Integrated sameport patch from Dario Meloni : Added a "sameport" - argument to upnpDiscover(). - -2008/07/18: - small modif to make Clang happy :) - -2008/07/17: - #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... - -2008/07/14: - include declspec.h in installation (to /usr/include/miniupnpc) - -VERSION 1.1 : - -2008/07/04: - standard options for install/ln instead of gnu-specific stuff. - -2008/07/03: - now builds a .dll and .lib with win32. (mingw32) - -2008/04/28: - make install now install the binary of the upnpc tool - -2008/04/27: - added testupnpigd.py - added error strings for miniupnpc "internal" errors - improved python module error/exception reporting. - -2008/04/23: - Completely rewrite igd_desc_parse.c in order to be compatible with - Linksys WAG200G - Added testigddescparse - updated python module - -VERSION 1.0 : - -2008/02/21: - put some #ifdef DEBUG around DisplayNameValueList() - -2008/02/18: - Improved error reporting in upnpcommands.c - UPNP_GetStatusInfo() returns LastConnectionError - -2008/02/16: - better error handling in minisoap.c - improving display of "valid IGD found" in upnpc.c - -2008/02/03: - Fixing UPNP_GetValidIGD() - improved make install :) - -2007/12/22: - Adding upnperrors.c/h to provide a strupnperror() function - used to translate UPnP error codes to string. - -2007/12/19: - Fixing getDevicesFromMiniSSDPD() - improved error reporting of UPnP functions - -2007/12/18: - It is now possible to specify a different location for MiniSSDPd socket. - working with MiniSSDPd is now more efficient. - python module improved. - -2007/12/16: - improving error reporting - -2007/12/13: - Try to improve compatibility by using HTTP/1.0 instead of 1.1 and - XML a bit different for SOAP. - -2007/11/25: - fixed select() call for linux - -2007/11/15: - Added -fPIC to CFLAG for better shared library code. - -2007/11/02: - Fixed a potential socket leak in miniwget2() - -2007/10/16: - added a parameter to upnpDiscover() in order to allow the use of another - interface than the default multicast interface. - -2007/10/12: - Fixed the creation of symbolic link in Makefile - -2007/10/08: - Added man page - -2007/10/02: - fixed memory bug in GetUPNPUrls() - -2007/10/01: - fixes in the Makefile - Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. - Added SONAME in the shared library to please debian :) - fixed MS Windows compilation (minissdpd is not available under MS Windows). - -2007/09/25: - small change to Makefile to be able to install in a different location - (default is /usr) - -2007/09/24: - now compiling both shared and static library - -2007/09/19: - Cosmetic changes on upnpc.c - -2007/09/02: - adapting to new miniSSDPd (release version ?) - -2007/08/31: - Usage of miniSSDPd to skip discovery process. - -2007/08/27: - fixed python module to allow compilation with Python older than Python 2.4 - -2007/06/12: - Added a python module. - -2007/05/19: - Fixed compilation under MinGW - -2007/05/15: - fixed a memory leak in AddPortMapping() - Added testupnpreplyparse executable to check the parsing of - upnp soap messages - minixml now ignore namespace prefixes. - -2007/04/26: - upnpc now displays external ip address with -s or -l - -2007/04/11: - changed MINIUPNPC_URL_MAXSIZE to 128 to accommodate the "BT Voyager 210" - -2007/03/19: - cleanup in miniwget.c - -2007/03/01: - Small typo fix... - -2007/01/30: - Now parsing the HTTP header from SOAP responses in order to - get content-length value. - -2007/01/29: - Fixed the Soap Query to speedup the HTTP request. - added some Win32 DLL stuff... - -2007/01/27: - Fixed some WIN32 compatibility issues - -2006/12/14: - Added UPNPIGD_IsConnected() function in miniupnp.c/.h - Added UPNP_GetValidIGD() in miniupnp.c/.h - cleaned upnpc.c main(). now using UPNP_GetValidIGD() - -2006/12/07: - Version 1.0-RC1 released - -2006/12/03: - Minor changes to compile under SunOS/Solaris - -2006/11/30: - made a minixml parser validator program - updated minixml to handle attributes correctly - -2006/11/22: - Added a -r option to the upnpc sample thanks to Alexander Hubmann. - -2006/11/19: - Cleanup code to make it more ANSI C compliant - -2006/11/10: - detect and display local lan address. - -2006/11/04: - Packets and Bytes Sent/Received are now unsigned int. - -2006/11/01: - Bug fix thanks to Giuseppe D'Angelo - -2006/10/31: - C++ compatibility for .h files. - Added a way to get ip Address on the LAN used to reach the IGD. - -2006/10/25: - Added M-SEARCH to the services in the discovery process. - -2006/10/22: - updated the Makefile to use makedepend, added a "make install" - update Makefile - -2006/10/20: - fixing the description url parsing thanks to patch sent by - Wayne Dawe. - Fixed/translated some comments. - Implemented a better discover process, first looking - for IGD then for root devices (as some devices only reply to - M-SEARCH for root devices). - -2006/09/02: - added freeUPNPDevlist() function. - -2006/08/04: - More command line arguments checking - -2006/08/01: - Added the .bat file to compile under Win32 with minGW32 - -2006/07/31: - Fixed the rootdesc parser (igd_desc_parse.c) - -2006/07/20: - parseMSEARCHReply() is now returning the ST: line as well - starting changes to detect several UPnP devices on the network - -2006/07/19: - using GetCommonLinkProperties to get down/upload bitrate - diff --git a/src/contrib/miniupnp/miniupnpc/LICENSE b/src/contrib/miniupnp/miniupnpc/LICENSE deleted file mode 100644 index 0816733..0000000 --- a/src/contrib/miniupnp/miniupnpc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -MiniUPnPc -Copyright (c) 2005-2016, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/contrib/miniupnp/miniupnpc/MANIFEST.in b/src/contrib/miniupnp/miniupnpc/MANIFEST.in deleted file mode 100644 index a0ebe2a..0000000 --- a/src/contrib/miniupnp/miniupnpc/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include README -include VERSION -include LICENSE -include miniupnpcmodule.c -include setup.py -include Makefile -include *.[ch] -include *.h.in -include *.sh diff --git a/src/contrib/miniupnp/miniupnpc/Makefile b/src/contrib/miniupnp/miniupnpc/Makefile deleted file mode 100644 index 0102f3b..0000000 --- a/src/contrib/miniupnp/miniupnpc/Makefile +++ /dev/null @@ -1,404 +0,0 @@ -# $Id: Makefile,v 1.134 2016/10/07 09:04:36 nanard Exp $ -# MiniUPnP Project -# http://miniupnp.free.fr/ -# http://miniupnp.tuxfamily.org/ -# https://github.com/miniupnp/miniupnp -# (c) 2005-2018 Thomas Bernard -# to install use : -# $ make DESTDIR=/tmp/dummylocation install -# or -# $ INSTALLPREFIX=/usr/local make install -# or -# $ make install (default INSTALLPREFIX is /usr) -OS = $(shell $(CC) -dumpmachine) -VERSION = $(shell cat VERSION) - -ifneq (, $(findstring darwin, $(OS))) -JARSUFFIX=mac -LIBTOOL ?= $(shell which libtool) -endif -ifneq (, $(findstring linux, $(OS))) -JARSUFFIX=linux -endif -ifneq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS))) -JARSUFFIX=win32 -endif - -HAVE_IPV6 ?= yes -export HAVE_IPV6 - -CC ?= gcc -#AR = gar -#CFLAGS = -O -g -DDEBUG -CFLAGS ?= -O -CFLAGS += -Wall -CFLAGS += -W -Wstrict-prototypes -CFLAGS += -fno-common -CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT -CFLAGS += -DMINIUPNPC_GET_SRC_ADDR -CFLAGS += -D_BSD_SOURCE -CFLAGS += -D_DEFAULT_SOURCE -ifneq (, $(findstring netbsd, $(OS))) -CFLAGS += -D_NETBSD_SOURCE -endif -ifeq (, $(findstring freebsd, $(OS))$(findstring darwin, $(OS))) -#CFLAGS += -D_POSIX_C_SOURCE=200112L -CFLAGS += -D_XOPEN_SOURCE=600 -endif -#CFLAGS += -ansi -#CFLAGS += -DNO_GETADDRINFO -INSTALL = install -SH = /bin/sh -JAVA = java -# see http://code.google.com/p/jnaerator/ -#JNAERATOR = jnaerator-0.9.7.jar -#JNAERATOR = jnaerator-0.9.8-shaded.jar -#JNAERATORARGS = -library miniupnpc -#JNAERATOR = jnaerator-0.10-shaded.jar -#JNAERATOR = jnaerator-0.11-shaded.jar -# https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12/jnaerator-0.12-shaded.jar -JNAERATOR = jnaerator-0.12-shaded.jar -JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc -#JNAERATORBASEURL = http://jnaerator.googlecode.com/files/ -JNAERATORBASEURL = https://repo1.maven.org/maven2/com/nativelibs4java/jnaerator/0.12 - -ifneq (, $(findstring sun, $(OS))) - LDLIBS=-lsocket -lnsl -lresolv - CFLAGS += -D__EXTENSIONS__ - CFLAGS += -std=c99 -endif - -# APIVERSION is used to build SONAME -APIVERSION = 17 - -SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ - upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ - minixmlvalid.c testupnpreplyparse.c minissdpc.c \ - upnperrors.c testigddescparse.c testminiwget.c \ - connecthostport.c portlistingparse.c receivedata.c \ - upnpdev.c testportlistingparse.c miniupnpcmodule.c \ - minihttptestserver.c \ - listdevices.c - -LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ - miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ - connecthostport.o portlistingparse.o receivedata.o upnpdev.o - -ifeq (, $(findstring amiga, $(OS))) -ifeq (, $(findstring mingw, $(OS))$(findstring cygwin, $(OS))$(findstring msys, $(OS))) -CFLAGS := -fPIC $(CFLAGS) -endif -LIBOBJS := $(LIBOBJS) minissdpc.o -endif - -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -# HEADERS to install -HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ - upnpreplyparse.h upnperrors.h miniupnpctypes.h \ - portlistingparse.h \ - upnpdev.h \ - miniupnpc_declspec.h - -# library names -LIBRARY = libminiupnpc.a -ifneq (, $(findstring darwin, $(OS))) - SHAREDLIBRARY = libminiupnpc.dylib - SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib - CFLAGS := -D_DARWIN_C_SOURCE $(CFLAGS) -else -ifeq ($(JARSUFFIX), win32) - SHAREDLIBRARY = miniupnpc.dll -else - # Linux/BSD/etc. - SHAREDLIBRARY = libminiupnpc.so - SONAME = $(SHAREDLIBRARY).$(APIVERSION) -endif -endif - -EXECUTABLES = upnpc-static listdevices -EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ - testigddescparse testminiwget testportlistingparse - -TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o - -TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o - -TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o - -TESTPORTLISTINGPARSE = testportlistingparse.o minixml.o portlistingparse.o - -TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ - miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ - minisoap.o connecthostport.o receivedata.o \ - portlistingparse.o - -ifeq (, $(findstring amiga, $(OS))) -EXECUTABLES := $(EXECUTABLES) upnpc-shared -TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o -TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o -endif - -LIBDIR ?= lib -# install directories -ifeq ($(strip $(PREFIX)),) -INSTALLPREFIX ?= /usr -else -INSTALLPREFIX ?= $(PREFIX) -endif -INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc -INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR) -INSTALLDIRBIN = $(INSTALLPREFIX)/bin -INSTALLDIRMAN = $(INSTALLPREFIX)/share/man -PKGCONFIGDIR = $(INSTALLDIRLIB)/pkgconfig - -FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES) -ifeq (, $(findstring amiga, $(OS))) -FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY) miniupnpc.pc -endif - - -.PHONY: install clean depend all check test everything \ - installpythonmodule updateversion -# validateminixml validateminiwget - -all: $(LIBRARY) $(EXECUTABLES) - -test: check - -check: validateminixml validateminiwget validateupnpreplyparse \ - validateportlistingparse validateigddescparse - -everything: all $(EXECUTABLES_ADDTESTS) - -pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py - MAKE=$(MAKE) python setup.py build - touch $@ - -installpythonmodule: pythonmodule - MAKE=$(MAKE) python setup.py install - -pythonmodule3: $(LIBRARY) miniupnpcmodule.c setup.py - MAKE=$(MAKE) python3 setup.py build - touch $@ - -installpythonmodule3: pythonmodule3 - MAKE=$(MAKE) python3 setup.py install - -validateminixml: minixmlvalid - @echo "minixml validation test" - ./minixmlvalid - touch $@ - -validateminiwget: testminiwget minihttptestserver testminiwget.sh - @echo "miniwget validation test" - ./testminiwget.sh - touch $@ - -validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh - @echo "upnpreplyparse validation test" - ./testupnpreplyparse.sh - touch $@ - -validateportlistingparse: testportlistingparse - @echo "portlistingparse validation test" - ./testportlistingparse - touch $@ - -validateigddescparse: testigddescparse - @echo "igd desc parse validation test" - ./testigddescparse testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values - ./testigddescparse testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values - touch $@ - -clean: - $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h - $(RM) $(EXECUTABLES_ADDTESTS) - # clean python stuff - $(RM) pythonmodule pythonmodule3 - $(RM) validateminixml validateminiwget validateupnpreplyparse - $(RM) validateigddescparse - $(RM) minihttptestserver - $(RM) -r build/ dist/ - #python setup.py clean - # clean jnaerator stuff - $(RM) _jnaerator.* java/miniupnpc_$(OS).jar - -distclean: clean - $(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt - -updateversion: miniupnpc.h - cp miniupnpc.h miniupnpc.h.bak - sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h - -install: updateversion $(FILESTOINSTALL) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) - $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) -ifeq (, $(findstring amiga, $(OS))) - $(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME) - ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) - $(INSTALL) -d $(DESTDIR)$(PKGCONFIGDIR) - $(INSTALL) -m 644 miniupnpc.pc $(DESTDIR)$(PKGCONFIGDIR) -endif - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) -ifneq (, $(findstring amiga, $(OS))) - $(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc -else - $(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc -endif - $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip -ifeq (, $(findstring amiga, $(OS))) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3 - $(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 -ifneq (, $(findstring linux, $(OS))) - gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 -endif -endif - -install-static: updateversion $(FILESTOINSTALL) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) - $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) - $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip - -cleaninstall: - $(RM) -r $(DESTDIR)$(INSTALLDIRINC) - $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY) - $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) - -miniupnpc.pc: VERSION - $(RM) $@ - echo "prefix=$(INSTALLPREFIX)" >> $@ - echo "exec_prefix=\$${prefix}" >> $@ - echo "libdir=\$${exec_prefix}/$(LIBDIR)" >> $@ - echo "includedir=\$${prefix}/include/miniupnpc" >> $@ - echo "" >> $@ - echo "Name: miniUPnPc" >> $@ - echo "Description: UPnP IGD client lightweight library" >> $@ - echo "Version: $(VERSION)" >> $@ - echo "Libs: -L\$${libdir} -lminiupnpc" >> $@ - echo "Cflags: -I\$${includedir}" >> $@ - -depend: - makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null - -$(LIBRARY): $(LIBOBJS) -ifneq (, $(findstring darwin, $(OS))) - $(LIBTOOL) -static -o $@ $? -else - $(AR) crs $@ $? -endif - -$(SHAREDLIBRARY): $(LIBOBJS) -ifneq (, $(findstring darwin, $(OS))) -# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^ - $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^ -else - $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ -endif - -upnpc-static: upnpc.o $(LIBRARY) - $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) - -upnpc-shared: upnpc.o $(SHAREDLIBRARY) - $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) - -listdevices: listdevices.o $(LIBRARY) - -testminixml: $(TESTMINIXMLOBJS) - -testminiwget: $(TESTMINIWGETOBJS) - -minixmlvalid: minixml.o minixmlvalid.o - -testupnpreplyparse: $(TESTUPNPREPLYPARSE) - -testigddescparse: $(TESTIGDDESCPARSE) - -testportlistingparse: $(TESTPORTLISTINGPARSE) - -miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION - $(SH) updateminiupnpcstrings.sh - -# ftp tool supplied with OpenBSD can download files from http. -jnaerator-%.jar: - wget $(JNAERATORBASEURL)/$@ || \ - curl -o $@ $(JNAERATORBASEURL)/$@ || \ - ftp $(JNAERATORBASEURL)/$@ - -jar: $(SHAREDLIBRARY) $(JNAERATOR) - $(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \ - miniupnpc.h miniupnpc_declspec.h upnpcommands.h upnpreplyparse.h \ - igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \ - -package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v - -mvn_install: - mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \ - -DgroupId=com.github \ - -DartifactId=miniupnp \ - -Dversion=$(VERSION) \ - -Dpackaging=jar \ - -Dclassifier=$(JARSUFFIX) \ - -DgeneratePom=true \ - -DcreateChecksum=true - -# make .deb packages -deb: /usr/share/pyshared/stdeb all - (python setup.py --command-packages=stdeb.command bdist_deb) - -# install .deb packages -ideb: - (sudo dpkg -i deb_dist/*.deb) - -/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev - (sudo apt-get install python-stdeb) - -/usr/share/doc/python-all-dev: - (sudo apt-get install python-all-dev) - -minihttptestserver: minihttptestserver.o - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -igd_desc_parse.o: igd_desc_parse.h -miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h -miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h -miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h -miniupnpc.o: connecthostport.h -minixml.o: minixml.h -minisoap.o: minisoap.h miniupnpcstrings.h -miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h -miniwget.o: connecthostport.h receivedata.h -upnpc.o: miniwget.h miniupnpc_declspec.h miniupnpc.h igd_desc_parse.h -upnpc.o: upnpdev.h upnpcommands.h upnpreplyparse.h portlistingparse.h -upnpc.o: miniupnpctypes.h upnperrors.h miniupnpcstrings.h -upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h -upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h -upnpcommands.o: igd_desc_parse.h upnpdev.h -upnpreplyparse.o: upnpreplyparse.h minixml.h -testminixml.o: minixml.h igd_desc_parse.h -minixmlvalid.o: minixml.h -testupnpreplyparse.o: upnpreplyparse.h -minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h -minissdpc.o: igd_desc_parse.h receivedata.h codelength.h -upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h -upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h -upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h -testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h -testigddescparse.o: miniupnpc_declspec.h upnpdev.h -testminiwget.o: miniwget.h miniupnpc_declspec.h -connecthostport.o: connecthostport.h -portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h -portlistingparse.o: minixml.h -receivedata.o: receivedata.h -upnpdev.o: upnpdev.h miniupnpc_declspec.h -testportlistingparse.o: portlistingparse.h miniupnpc_declspec.h -testportlistingparse.o: miniupnpctypes.h -miniupnpcmodule.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h -miniupnpcmodule.o: upnpdev.h upnpcommands.h upnpreplyparse.h -miniupnpcmodule.o: portlistingparse.h miniupnpctypes.h upnperrors.h -listdevices.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h diff --git a/src/contrib/miniupnp/miniupnpc/Makefile.mingw b/src/contrib/miniupnp/miniupnpc/Makefile.mingw deleted file mode 100644 index a63c6f4..0000000 --- a/src/contrib/miniupnp/miniupnpc/Makefile.mingw +++ /dev/null @@ -1,121 +0,0 @@ -# $Id: Makefile.mingw,v 1.21 2015/09/18 12:45:16 nanard Exp $ -# Miniupnp project. -# http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ -# (c) 2005-2018 Thomas Bernard -# This Makefile is made for MinGW -# -# To cross compile on a *nix machine : -# make -f Makefile.mingw DLLWRAP=mingw32-dllwrap CC=mingw32-gcc AR=mingw32-ar -# -CC ?= gcc -DLLWRAP = dllwrap -SH = /bin/sh -ifeq ($(OS),Windows_NT) -RM = del -else -RM = rm -f -endif -#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501 -CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 -LDLIBS = -lws2_32 -liphlpapi -# -lwsock32 -# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable() -PYTHON=\utils\python25\python -OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ - minissdpc.o \ - miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ - connecthostport.o portlistingparse.o receivedata.o \ - upnpdev.o -OBJSDLL=$(addprefix dll/, $(OBJS)) - -all: init upnpc-static upnpc-shared testminixml libminiupnpc.a \ - miniupnpc.dll listdevices - -init: - mkdir dll - echo init > init - -clean: - $(RM) upnpc testminixml *.o - $(RM) dll\*.o - $(RM) *.exe - $(RM) miniupnpc.dll - $(RM) libminiupnpc.a - -libminiupnpc.a: $(OBJS) - $(AR) cr $@ $? - -pythonmodule: libminiupnpc.a - $(PYTHON) setupmingw32.py build --compiler=mingw32 - $(PYTHON) setupmingw32.py install --skip-build - -miniupnpc.dll: libminiupnpc.a $(OBJSDLL) - $(DLLWRAP) -k --driver-name $(CC) \ - --def miniupnpc.def \ - --output-def miniupnpc.dll.def \ - --implib miniupnpc.lib -o $@ \ - $(OBJSDLL) $(LDLIBS) - -miniupnpc.lib: miniupnpc.dll -# echo $@ generated with $< - -dll/upnpc.o: upnpc.o -# echo $@ generated with $< - -.c.o: - $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< - $(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $< - -upnpc.o: upnpc.c - $(CC) $(CFLAGS) -DMINIUPNP_STATICLIB -c -o $@ $< - $(CC) $(CFLAGS) -c -o dll/$@ $< - -# --enable-stdcall-fixup -upnpc-static: upnpc.o libminiupnpc.a - $(CC) -o $@ $^ $(LDLIBS) - -upnpc-shared: dll/upnpc.o miniupnpc.lib - $(CC) -o $@ $^ $(LDLIBS) - -listdevices: listdevices.o libminiupnpc.a - $(CC) -o $@ $^ $(LDLIBS) - -wingenminiupnpcstrings: wingenminiupnpcstrings.o - -wingenminiupnpcstrings.o: wingenminiupnpcstrings.c - -# To make miniupnpcstrings.h from miniupnpcstrings.h.in we either -# use a custom executable (if running make under windows) or use -# sed (if cross compiling from another platform). -ifeq ($(OS),Windows_NT) -miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings - wingenminiupnpcstrings $< $@ -else -miniupnpcstrings.h: miniupnpcstrings.h.in VERSION - sed 's|OS_STRING ".*"|OS_STRING "Windows/Mingw32"|' $< | \ - sed 's|MINIUPNPC_VERSION_STRING ".*"|MINIUPNPC_VERSION_STRING "$(shell cat VERSION)"|' > $@ -endif - -minixml.o: minixml.c minixml.h - -upnpc.o: miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h -upnpc.o: upnpreplyparse.h upnpcommands.h upnperrors.h miniupnpcstrings.h - -miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h - -minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h - -miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h - -igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h - -testminixml: minixml.o igd_desc_parse.o testminixml.c - -upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h - -upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h - -minissdpc.o: minissdpc.c minissdpc.h receivedata.h - -upnpdev.o: upnpdev.c upnpdev.h - diff --git a/src/contrib/miniupnp/miniupnpc/README b/src/contrib/miniupnp/miniupnpc/README deleted file mode 100644 index 0d3b805..0000000 --- a/src/contrib/miniupnp/miniupnpc/README +++ /dev/null @@ -1,63 +0,0 @@ -Project: miniupnp -Project web page: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ -github: https://github.com/miniupnp/miniupnp -Author: Thomas Bernard -Copyright (c) 2005-2017 Thomas Bernard -This software is subject to the conditions detailed in the -LICENSE file provided within this distribution. - - -* miniUPnP Client - miniUPnPc * - -To compile, simply run 'gmake' (could be 'make' on your system). -Under win32, to compile with MinGW, type "mingw32make.bat". -MS Visual C solution and project files are supplied in the msvc/ subdirectory. - -The compilation is known to work under linux, FreeBSD, -OpenBSD, MacOS X, AmigaOS and cygwin. -The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. -upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. - -To install the library and headers on the system use : -> su -> make install -> exit - -alternatively, to install into a specific location, use : -> INSTALLPREFIX=/usr/local make install - -upnpc.c is a sample client using the libminiupnpc. -To use the libminiupnpc in your application, link it with -libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, -upnpcommands.h and miniwget.h : -- upnpDiscover() -- UPNP_GetValidIGD() -- miniwget() -- parserootdesc() -- GetUPNPUrls() -- UPNP_* (calling UPNP methods) - -Note : use #include etc... for the includes -and -lminiupnpc for the link - -Discovery process is speeded up when MiniSSDPd is running on the machine. - - -* Python module * - -you can build a python module with 'make pythonmodule' -and install it with 'make installpythonmodule'. -setup.py (and setupmingw32.py) are included in the distribution. - - -Feel free to contact me if you have any problem : -e-mail : miniupnp@free.fr - -If you are using libminiupnpc in your application, please -send me an email ! - -For any question, you can use the web forum : -https://miniupnp.tuxfamily.org/forum/ - -Bugs should be reported on github : -https://github.com/miniupnp/miniupnp/issues diff --git a/src/contrib/miniupnp/miniupnpc/VERSION b/src/contrib/miniupnp/miniupnpc/VERSION deleted file mode 100644 index 879b416..0000000 --- a/src/contrib/miniupnp/miniupnpc/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.1 diff --git a/src/contrib/miniupnp/miniupnpc/apiversions.txt b/src/contrib/miniupnp/miniupnpc/apiversions.txt deleted file mode 100644 index 90d169b..0000000 --- a/src/contrib/miniupnp/miniupnpc/apiversions.txt +++ /dev/null @@ -1,178 +0,0 @@ -$Id: apiversions.txt,v 1.9 2016/01/24 17:24:36 nanard Exp $ - -Differences in API between miniUPnPc versions - -API version 17 - change struct UPNPDev - move getHTTPResponse() to miniwget_private.h - updated macro : - #define MINIUPNPC_API_VERSION 17 - -API version 16 - added "status_code" argument to getHTTPResponse(), miniwget() and miniwget_getaddr() - updated macro : - #define MINIUPNPC_API_VERSION 16 - -API version 15 - changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() - to "localport". When 0 or 1, behaviour is not changed, but it can take - any other value between 2 and 65535 - Existing programs should be compatible - updated macro : - #define MINIUPNPC_API_VERSION 15 - -API version 14 -miniupnpc.h - add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice() - upnpDiscoverDevices() - getDevicesFromMiniSSDPD() : - connectToMiniSSDPD() / disconnectFromMiniSSDPD() - requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD() - updated macro : - #define MINIUPNPC_API_VERSION 14 - -API version 13 -miniupnpc.h: - add searchalltype param to upnpDiscoverDevices() function - updated macro : - #define MINIUPNPC_API_VERSION 13 - -API version 12 -miniupnpc.h : - add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices() - functions - updated macros : - #define MINIUPNPC_API_VERSION 12 - -API version 11 - -upnpreplyparse.h / portlistingparse.h : - removed usage of sys/queue.h / bsdqueue.h - -miniupnpc.h: - updated macros : - #define MINIUPNPC_API_VERSION 11 - -====================== miniUPnPc version 1.9 ====================== -API version 10 - -upnpcommands.h: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - -miniupnpc.h: - updated macros : - #define MINIUPNPC_VERSION "1.9" - #define MINIUPNPC_API_VERSION 10 - -====================== miniUPnPc version 1.8 ====================== -API version 9 - -miniupnpc.h: - updated macros : - #define MINIUPNPC_VERSION "1.8" - #define MINIUPNPC_API_VERSION 9 - added "unsigned int scope_id;" to struct UPNPDev - added scope_id argument to GetUPNPUrls() - - - -====================== miniUPnPc version 1.7 ====================== -API version 8 - -miniupnpc.h : - add new macros : - #define MINIUPNPC_VERSION "1.7" - #define MINIUPNPC_API_VERSION 8 - add rootdescURL to struct UPNPUrls - - - -====================== miniUPnPc version 1.6 ====================== -API version 8 - -Adding support for IPv6. -igd_desc_parse.h : - struct IGDdatas_service : - add char presentationurl[MINIUPNPC_URL_MAXSIZE]; - struct IGDdatas : - add struct IGDdatas_service IPv6FC; -miniupnpc.h : - new macros : - #define UPNPDISCOVER_SUCCESS (0) - #define UPNPDISCOVER_UNKNOWN_ERROR (-1) - #define UPNPDISCOVER_SOCKET_ERROR (-101) - #define UPNPDISCOVER_MEMORY_ERROR (-102) - simpleUPnPcommand() prototype changed (but is normaly not used by API users) - add arguments ipv6 and error to upnpDiscover() : - struct UPNPDev * - upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); - add controlURL_6FC member to struct UPNPUrls : - struct UPNPUrls { - char * controlURL; - char * ipcondescURL; - char * controlURL_CIF; - char * controlURL_6FC; - }; - -upnpcommands.h : - add leaseDuration argument to UPNP_AddPortMapping() - add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry() - add UPNP_GetListOfPortMappings() function (IGDv2) - add IGDv2 IPv6 related functions : - UPNP_GetFirewallStatus() - UPNP_GetOutboundPinholeTimeout() - UPNP_AddPinhole() - UPNP_UpdatePinhole() - UPNP_DeletePinhole() - UPNP_CheckPinholeWorking() - UPNP_GetPinholePackets() - - - -====================== miniUPnPc version 1.5 ====================== -API version 5 - -new function : -int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); -new macro in upnpcommands.h : -#define UPNPCOMMAND_HTTP_ERROR - -====================== miniUPnPc version 1.4 ====================== -Same API as version 1.3 - -====================== miniUPnPc version 1.3 ====================== -API version 4 - -Use UNSIGNED_INTEGER type for -UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(), -UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived() -Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping() - -====================== miniUPnPc version 1.2 ====================== -API version 3 - -added sameport argument to upnpDiscover() -struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport); - -====================== miniUPnPc Version 1.1 ====================== -Same API as 1.0 - - -====================== miniUPnPc Version 1.0 ====================== -API version 2 - - -struct UPNPDev { - struct UPNPDev * pNext; - char * descURL; - char * st; - char buffer[2]; -}; -struct UPNPDev * upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock); - diff --git a/src/contrib/miniupnp/miniupnpc/codelength.h b/src/contrib/miniupnp/miniupnpc/codelength.h deleted file mode 100644 index ea0b005..0000000 --- a/src/contrib/miniupnp/miniupnpc/codelength.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2005-2015 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef CODELENGTH_H_INCLUDED -#define CODELENGTH_H_INCLUDED - -/* Encode length by using 7bit per Byte : - * Most significant bit of each byte specifies that the - * following byte is part of the code */ - -/* n : unsigned - * p : unsigned char * - */ -#define DECODELENGTH(n, p) n = 0; \ - do { n = (n << 7) | (*p & 0x7f); } \ - while((*(p++)&0x80) && (n<(1<<25))); - -/* n : unsigned - * READ : function/macro to read one byte (unsigned char) - */ -#define DECODELENGTH_READ(n, READ) \ - n = 0; \ - do { \ - unsigned char c; \ - READ(c); \ - n = (n << 7) | (c & 0x07f); \ - if(!(c&0x80)) break; \ - } while(n<(1<<25)); - -/* n : unsigned - * p : unsigned char * - * p_limit : unsigned char * - */ -#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ - n = 0; \ - do { \ - if((p) >= (p_limit)) break; \ - n = (n << 7) | (*(p) & 0x7f); \ - } while((*((p)++)&0x80) && (n<(1<<25))); - - -/* n : unsigned - * p : unsigned char * - */ -#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ - if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ - if(n>=16384) *(p++) = (n >> 14) | 0x80; \ - if(n>=128) *(p++) = (n >> 7) | 0x80; \ - *(p++) = n & 0x7f; - -#endif /* CODELENGTH_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc/connecthostport.c b/src/contrib/miniupnp/miniupnpc/connecthostport.c deleted file mode 100644 index ea6e4e5..0000000 --- a/src/contrib/miniupnp/miniupnpc/connecthostport.c +++ /dev/null @@ -1,264 +0,0 @@ -/* $Id: connecthostport.c,v 1.15 2015/10/09 16:26:19 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2010-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -/* use getaddrinfo() or gethostbyname() - * uncomment the following line in order to use gethostbyname() */ -#ifdef NO_GETADDRINFO -#define USE_GETHOSTBYNAME -#endif - -#include -#include -#ifdef _WIN32 -#include -#include -#include -#define MAXHOSTNAMELEN 64 -#define snprintf _snprintf -#define herror -#define socklen_t int -#else /* #ifdef _WIN32 */ -#include -#include -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT -#include -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ -#include -#include -#include -#define closesocket close -#include -#include -/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions - * during the connect() call */ -#define MINIUPNPC_IGNORE_EINTR -#include -#include -#endif /* #else _WIN32 */ - -/* definition of PRINT_SOCKET_ERROR */ -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -#if defined(__amigaos__) || defined(__amigaos4__) -#define herror(A) printf("%s\n", A) -#endif - -#include "connecthostport.h" - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* connecthostport() - * return a socket connected (TCP) to the host and port - * or -1 in case of error */ -SOCKET connecthostport(const char * host, unsigned short port, - unsigned int scope_id) -{ - SOCKET s; - int n; -#ifdef USE_GETHOSTBYNAME - struct sockaddr_in dest; - struct hostent *hp; -#else /* #ifdef USE_GETHOSTBYNAME */ - char tmp_host[MAXHOSTNAMELEN+1]; - char port_str[8]; - struct addrinfo *ai, *p; - struct addrinfo hints; -#endif /* #ifdef USE_GETHOSTBYNAME */ -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - -#ifdef USE_GETHOSTBYNAME - hp = gethostbyname(host); - if(hp == NULL) - { - herror(host); - return INVALID_SOCKET; - } - memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); - memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); - s = socket(PF_INET, SOCK_STREAM, 0); - if(ISINVALID(s)) - { - PRINT_SOCKET_ERROR("socket"); - return INVALID_SOCKET; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO"); - } -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); -#ifdef MINIUPNPC_IGNORE_EINTR - /* EINTR The system call was interrupted by a signal that was caught - * EINPROGRESS The socket is nonblocking and the connection cannot - * be completed immediately. */ - while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - return INVALID_SOCKET; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ - if(n<0) - { - PRINT_SOCKET_ERROR("connect"); - closesocket(s); - return INVALID_SOCKET; - } -#else /* #ifdef USE_GETHOSTBYNAME */ - /* use getaddrinfo() instead of gethostbyname() */ - memset(&hints, 0, sizeof(hints)); - /* hints.ai_flags = AI_ADDRCONFIG; */ -#ifdef AI_NUMERICSERV - hints.ai_flags = AI_NUMERICSERV; -#endif - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ - /* hints.ai_protocol = IPPROTO_TCP; */ - snprintf(port_str, sizeof(port_str), "%hu", port); - if(host[0] == '[') - { - /* literal ip v6 address */ - int i, j; - for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) - { - tmp_host[i] = host[j]; - if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ - j+=2; /* skip "25" */ - } - tmp_host[i] = '\0'; - } - else - { - strncpy(tmp_host, host, MAXHOSTNAMELEN); - } - tmp_host[MAXHOSTNAMELEN] = '\0'; - n = getaddrinfo(tmp_host, port_str, &hints, &ai); - if(n != 0) - { -#ifdef _WIN32 - fprintf(stderr, "getaddrinfo() error : %d\n", n); -#else - fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); -#endif - return INVALID_SOCKET; - } - s = -1; - for(p = ai; p; p = p->ai_next) - { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if(ISINVALID(s)) - continue; - if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { - struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; - addr6->sin6_scope_id = scope_id; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - n = connect(s, p->ai_addr, p->ai_addrlen); -#ifdef MINIUPNPC_IGNORE_EINTR - /* EINTR The system call was interrupted by a signal that was caught - * EINPROGRESS The socket is nonblocking and the connection cannot - * be completed immediately. */ - while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - freeaddrinfo(ai); - return INVALID_SOCKET; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ - if(n < 0) - { - closesocket(s); - continue; - } - else - { - break; - } - } - freeaddrinfo(ai); - if(ISINVALID(s)) - { - PRINT_SOCKET_ERROR("socket"); - return INVALID_SOCKET; - } - if(n < 0) - { - PRINT_SOCKET_ERROR("connect"); - return INVALID_SOCKET; - } -#endif /* #ifdef USE_GETHOSTBYNAME */ - return s; -} - diff --git a/src/contrib/miniupnp/miniupnpc/connecthostport.h b/src/contrib/miniupnp/miniupnpc/connecthostport.h deleted file mode 100644 index 701816b..0000000 --- a/src/contrib/miniupnp/miniupnpc/connecthostport.h +++ /dev/null @@ -1,20 +0,0 @@ -/* $Id: connecthostport.h,v 1.2 2012/06/23 22:32:33 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2010-2018 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef CONNECTHOSTPORT_H_INCLUDED -#define CONNECTHOSTPORT_H_INCLUDED - -#include "miniupnpc_socketdef.h" - -/* connecthostport() - * return a socket connected (TCP) to the host and port - * or INVALID_SOCKET in case of error */ -SOCKET connecthostport(const char * host, unsigned short port, - unsigned int scope_id); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/external-ip.sh b/src/contrib/miniupnp/miniupnpc/external-ip.sh deleted file mode 100644 index 6fd82df..0000000 --- a/src/contrib/miniupnp/miniupnpc/external-ip.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ -# (c) 2010 Reuben Hawkins -upnpc -s | sed -n -e 's/^ExternalIPAddress = \([0-9.]*\)$/\1/p' diff --git a/src/contrib/miniupnp/miniupnpc/igd_desc_parse.c b/src/contrib/miniupnp/miniupnpc/igd_desc_parse.c deleted file mode 100644 index d2999ad..0000000 --- a/src/contrib/miniupnp/miniupnpc/igd_desc_parse.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include "igd_desc_parse.h" -#include -#include - -/* Start element handler : - * update nesting level counter and copy element name */ -void IGDstartelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - if(l >= MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(datas->cureltname, name, l); - datas->cureltname[l] = '\0'; - datas->level++; - if( (l==7) && !memcmp(name, "service", l) ) { - datas->tmp.controlurl[0] = '\0'; - datas->tmp.eventsuburl[0] = '\0'; - datas->tmp.scpdurl[0] = '\0'; - datas->tmp.servicetype[0] = '\0'; - } -} - -#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) - -/* End element handler : - * update nesting level counter and update parser state if - * service element is parsed */ -void IGDendelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - datas->level--; - /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ - if( (l==7) && !memcmp(name, "service", l) ) - { - if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) { - memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) { - memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPConnection:") - || COMPARE(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANPPPConnection:") ) { - if(datas->first.servicetype[0] == '\0') { - memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); - } else { - memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); - } - } - } -} - -/* Data handler : - * copy data depending on the current element name and state */ -void IGDdata(void * d, const char * data, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - char * dstmember = 0; - /*printf("%2d %s : %.*s\n", - datas->level, datas->cureltname, l, data); */ - if( !strcmp(datas->cureltname, "URLBase") ) - dstmember = datas->urlbase; - else if( !strcmp(datas->cureltname, "presentationURL") ) - dstmember = datas->presentationurl; - else if( !strcmp(datas->cureltname, "serviceType") ) - dstmember = datas->tmp.servicetype; - else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->tmp.controlurl; - else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->tmp.eventsuburl; - else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->tmp.scpdurl; -/* else if( !strcmp(datas->cureltname, "deviceType") ) - dstmember = datas->devicetype_tmp;*/ - if(dstmember) - { - if(l>=MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(dstmember, data, l); - dstmember[l] = '\0'; - } -} - -#ifdef DEBUG -void printIGD(struct IGDdatas * d) -{ - printf("urlbase = '%s'\n", d->urlbase); - printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ - printf(" serviceType = '%s'\n", d->CIF.servicetype); - printf(" controlURL = '%s'\n", d->CIF.controlurl); - printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); - printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); - printf("primary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ - printf(" servicetype = '%s'\n", d->first.servicetype); - printf(" controlURL = '%s'\n", d->first.controlurl); - printf(" eventSubURL = '%s'\n", d->first.eventsuburl); - printf(" SCPDURL = '%s'\n", d->first.scpdurl); - printf("secondary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ - printf(" servicetype = '%s'\n", d->second.servicetype); - printf(" controlURL = '%s'\n", d->second.controlurl); - printf(" eventSubURL = '%s'\n", d->second.eventsuburl); - printf(" SCPDURL = '%s'\n", d->second.scpdurl); - printf("WAN IPv6 Firewall Control :\n"); - /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ - printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); - printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); - printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); - printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc/igd_desc_parse.h b/src/contrib/miniupnp/miniupnpc/igd_desc_parse.h deleted file mode 100644 index 0de546b..0000000 --- a/src/contrib/miniupnp/miniupnpc/igd_desc_parse.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef IGD_DESC_PARSE_H_INCLUDED -#define IGD_DESC_PARSE_H_INCLUDED - -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ -#define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas_service { - char controlurl[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl[MINIUPNPC_URL_MAXSIZE]; - char scpdurl[MINIUPNPC_URL_MAXSIZE]; - char servicetype[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ -}; - -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - char presentationurl[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ - struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ - struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ - struct IGDdatas_service IPv6FC; - /* tmp */ - struct IGDdatas_service tmp; -}; - -void IGDstartelt(void *, const char *, int); -void IGDendelt(void *, const char *, int); -void IGDdata(void *, const char *, int); -#ifdef DEBUG -void printIGD(struct IGDdatas *); -#endif /* DEBUG */ - -#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc/java/.gitignore b/src/contrib/miniupnp/miniupnpc/java/.gitignore deleted file mode 100644 index 8e9e794..0000000 --- a/src/contrib/miniupnp/miniupnpc/java/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.class -*.jar diff --git a/src/contrib/miniupnp/miniupnpc/java/JavaBridgeTest.java b/src/contrib/miniupnp/miniupnpc/java/JavaBridgeTest.java deleted file mode 100644 index c658c59..0000000 --- a/src/contrib/miniupnp/miniupnpc/java/JavaBridgeTest.java +++ /dev/null @@ -1,97 +0,0 @@ -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import fr.free.miniupnp.*; - -/** - * - * @author syuu - */ -public class JavaBridgeTest { - public static void main(String[] args) { - int UPNP_DELAY = 2000; - MiniupnpcLibrary miniupnpc = MiniupnpcLibrary.INSTANCE; - UPNPDev devlist = null; - UPNPUrls urls = new UPNPUrls(); - IGDdatas data = new IGDdatas(); - ByteBuffer lanaddr = ByteBuffer.allocate(16); - ByteBuffer intClient = ByteBuffer.allocate(16); - ByteBuffer intPort = ByteBuffer.allocate(6); - ByteBuffer desc = ByteBuffer.allocate(80); - ByteBuffer enabled = ByteBuffer.allocate(4); - ByteBuffer leaseDuration = ByteBuffer.allocate(16); - int ret; - int i; - - if(args.length < 2) { - System.err.println("Usage : java [...] JavaBridgeTest port protocol"); - System.out.println(" port is numeric, protocol is TCP or UDP"); - return; - } - - devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, (byte)2, IntBuffer.allocate(1)); - if (devlist != null) { - System.out.println("List of UPNP devices found on the network :"); - for (UPNPDev device = devlist; device != null; device = device.pNext) { - System.out.println("desc: " + device.descURL.getString(0) + " st: " + device.st.getString(0)); - } - if ((i = miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16)) != 0) { - switch (i) { - case 1: - System.out.println("Found valid IGD : " + urls.controlURL.getString(0)); - break; - case 2: - System.out.println("Found a (not connected?) IGD : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - break; - case 3: - System.out.println("UPnP device found. Is it an IGD ? : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - break; - default: - System.out.println("Found device (igd ?) : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - - } - System.out.println("Local LAN ip address : " + new String(lanaddr.array())); - ByteBuffer externalAddress = ByteBuffer.allocate(16); - miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0), - new String(data.first.servicetype), externalAddress); - System.out.println("ExternalIPAddress = " + new String(externalAddress.array())); - ret = miniupnpc.UPNP_AddPortMapping( - urls.controlURL.getString(0), // controlURL - new String(data.first.servicetype), // servicetype - args[0], // external Port - args[0], // internal Port - new String(lanaddr.array()), // internal client - "added via miniupnpc/JAVA !", // description - args[1], // protocol UDP or TCP - null, // remote host (useless) - "0"); // leaseDuration - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("AddPortMapping() failed with code " + ret); - ret = miniupnpc.UPNP_GetSpecificPortMappingEntry( - urls.controlURL.getString(0), new String(data.first.servicetype), - args[0], args[1], null, intClient, intPort, - desc, enabled, leaseDuration); - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("GetSpecificPortMappingEntry() failed with code " + ret); - System.out.println("InternalIP:Port = " + - new String(intClient.array()) + ":" + new String(intPort.array()) + - " (" + new String(desc.array()) + ")"); - ret = miniupnpc.UPNP_DeletePortMapping( - urls.controlURL.getString(0), - new String(data.first.servicetype), - args[0], args[1], null); - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("DelPortMapping() failed with code " + ret); - miniupnpc.FreeUPNPUrls(urls); - } else { - System.out.println("No valid UPNP Internet Gateway Device found."); - } - miniupnpc.freeUPNPDevlist(devlist); - } else { - System.out.println("No IGD UPnP Device found on the network !\n"); - } - } -} diff --git a/src/contrib/miniupnp/miniupnpc/java/testjava.bat b/src/contrib/miniupnp/miniupnpc/java/testjava.bat deleted file mode 100644 index b836da1..0000000 --- a/src/contrib/miniupnp/miniupnpc/java/testjava.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -set JAVA=java -set JAVAC=javac -REM notice the semicolon for Windows. Write once, run ... oh nevermind -set CP=miniupnpc_win32.jar;. - -%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1 -%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1 diff --git a/src/contrib/miniupnp/miniupnpc/java/testjava.sh b/src/contrib/miniupnp/miniupnpc/java/testjava.sh deleted file mode 100644 index 9880523..0000000 --- a/src/contrib/miniupnp/miniupnpc/java/testjava.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -JAVA=java -JAVAC=javac -CP=$(for i in *.jar; do echo -n $i:; done). - -$JAVAC -cp $CP JavaBridgeTest.java || exit 1 -$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1 diff --git a/src/contrib/miniupnp/miniupnpc/listdevices.c b/src/contrib/miniupnp/miniupnpc/listdevices.c deleted file mode 100644 index bd9ba57..0000000 --- a/src/contrib/miniupnp/miniupnpc/listdevices.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2013-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#include -#ifdef _WIN32 -#include -#endif /* _WIN32 */ -#include "miniupnpc.h" - -struct upnp_dev_list { - struct upnp_dev_list * next; - char * descURL; - struct UPNPDev * * array; - size_t count; - size_t allocated_count; -}; - -#define ADD_DEVICE_COUNT_STEP 16 - -void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev) -{ - struct upnp_dev_list * elt; - size_t i; - - if(dev == NULL) - return; - for(elt = *list_head; elt != NULL; elt = elt->next) { - if(strcmp(elt->descURL, dev->descURL) == 0) { - for(i = 0; i < elt->count; i++) { - if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) { - return; /* already found */ - } - } - if(elt->count >= elt->allocated_count) { - struct UPNPDev * * tmp; - elt->allocated_count += ADD_DEVICE_COUNT_STEP; - tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *)); - if(tmp == NULL) { - fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *))); - return; - } - elt->array = tmp; - } - elt->array[elt->count++] = dev; - return; - } - } - elt = malloc(sizeof(struct upnp_dev_list)); - if(elt == NULL) { - fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list)); - return; - } - elt->next = *list_head; - elt->descURL = strdup(dev->descURL); - if(elt->descURL == NULL) { - fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL); - free(elt); - return; - } - elt->allocated_count = ADD_DEVICE_COUNT_STEP; - elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)); - if(elt->array == NULL) { - fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *))); - free(elt->descURL); - free(elt); - return; - } - elt->array[0] = dev; - elt->count = 1; - *list_head = elt; -} - -void free_device(struct upnp_dev_list * elt) -{ - free(elt->descURL); - free(elt->array); - free(elt); -} - -int main(int argc, char * * argv) -{ - const char * searched_device = NULL; - const char * * searched_devices = NULL; - const char * multicastif = 0; - const char * minissdpdpath = 0; - int ipv6 = 0; - unsigned char ttl = 2; - int error = 0; - struct UPNPDev * devlist = 0; - struct UPNPDev * dev; - struct upnp_dev_list * sorted_list = NULL; - struct upnp_dev_list * dev_array; - int i; - -#ifdef _WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - - for(i = 1; i < argc; i++) { - if(strcmp(argv[i], "-6") == 0) - ipv6 = 1; - else if(strcmp(argv[i], "-d") == 0) { - if(++i >= argc) { - fprintf(stderr, "%s option needs one argument\n", "-d"); - return 1; - } - searched_device = argv[i]; - } else if(strcmp(argv[i], "-t") == 0) { - if(++i >= argc) { - fprintf(stderr, "%s option needs one argument\n", "-t"); - return 1; - } - ttl = (unsigned char)atoi(argv[i]); - } else if(strcmp(argv[i], "-l") == 0) { - if(++i >= argc) { - fprintf(stderr, "-l option needs at least one argument\n"); - return 1; - } - searched_devices = (const char * *)(argv + i); - break; - } else if(strcmp(argv[i], "-m") == 0) { - if(++i >= argc) { - fprintf(stderr, "-m option needs one argument\n"); - return 1; - } - multicastif = argv[i]; - } else { - printf("usage : %s [options] [-l ...]\n", argv[0]); - printf("options :\n"); - printf(" -6 : use IPv6\n"); - printf(" -m address/ifname : network interface to use for multicast\n"); - printf(" -d : search only for this type of device\n"); - printf(" -l ... : search only for theses types of device\n"); - printf(" -t ttl : set multicast TTL. Default value is 2.\n"); - printf(" -h : this help\n"); - return 1; - } - } - - if(searched_device) { - printf("searching UPnP device type %s\n", searched_device); - devlist = upnpDiscoverDevice(searched_device, - 2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error); - } else if(searched_devices) { - printf("searching UPnP device types :\n"); - for(i = 0; searched_devices[i]; i++) - printf("\t%s\n", searched_devices[i]); - devlist = upnpDiscoverDevices(searched_devices, - 2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error, 1); - } else { - printf("searching all UPnP devices\n"); - devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error); - } - if(devlist) { - for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) { - printf("%3d: %-48s\n", i, dev->st); - printf(" %s\n", dev->descURL); - printf(" %s\n", dev->usn); - add_device(&sorted_list, dev); - } - putchar('\n'); - for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) { - printf("%s :\n", dev_array->descURL); - for(i = 0; (unsigned)i < dev_array->count; i++) { - printf("%2d: %s\n", i+1, dev_array->array[i]->st); - printf(" %s\n", dev_array->array[i]->usn); - } - putchar('\n'); - } - freeUPNPDevlist(devlist); - while(sorted_list != NULL) { - dev_array = sorted_list; - sorted_list = sorted_list->next; - free_device(dev_array); - } - } else { - printf("no device found.\n"); - } - - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpc/man3/miniupnpc.3 b/src/contrib/miniupnp/miniupnpc/man3/miniupnpc.3 deleted file mode 100644 index e5c3ec8..0000000 --- a/src/contrib/miniupnp/miniupnpc/man3/miniupnpc.3 +++ /dev/null @@ -1,55 +0,0 @@ -.TH MINIUPNPC 3 -.SH NAME -miniupnpc \- UPnP client library -.SH SYNOPSIS -.SH DESCRIPTION -The miniupnpc library implement the UPnP protocol defined -to dialog with Internet Gateway Devices. It also has -the ability to use data gathered by minissdpd(1) about -UPnP devices up on the network in order to skip the -long UPnP device discovery process. -.PP -At first, upnpDiscover(3) has to be used to discover UPnP IGD present -on the network. Then UPNP_GetValidIGD(3) to select the right one. -Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery -process if the root description url of the device to use is known. -Then all the UPNP_* functions can be used, such as -UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc... -.SH "HEADER FILES" -.IP miniupnpc.h -That's the main header file for the miniupnpc library API. -It contains all the functions and structures related to device discovery. -.IP upnpcommands.h -This header file contain the UPnP IGD methods that are accessible -through the miniupnpc API. The name of the C functions are matching -the UPnP methods names. ie: GetGenericPortMappingEntry is -UPNP_GetGenericPortMappingEntry. -.SH "API FUNCTIONS" -.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int localport, int ipv6, int * error);" -execute the discovery process. -delay (in millisecond) is the maximum time for waiting any device response. -If available, device list will be obtained from MiniSSDPd. -Default path for minissdpd socket will be used if minissdpdsock argument is NULL. -If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets. -If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent -from the source port 1900 (same as destination port), if set to -UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will -be attempted as the source port. -If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process. -.IP "void freeUPNPDevlist(struct UPNPDev * devlist);" -free the list returned by upnpDiscover(). -.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" -browse the list of device returned by upnpDiscover(), find -a live UPnP internet gateway device and fill structures passed as arguments -with data used for UPNP methods invocation. -.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" -permit one to bypass the upnpDiscover() call if the xml root description -URL of the UPnP IGD is known. -Fill structures passed as arguments -with data used for UPNP methods invocation. -.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);" -.IP "void FreeUPNPUrls(struct UPNPUrls *);" - -.SH "SEE ALSO" -minissdpd(1) -.SH BUGS diff --git a/src/contrib/miniupnp/miniupnpc/mingw32make.bat b/src/contrib/miniupnp/miniupnpc/mingw32make.bat deleted file mode 100644 index c5d3cc4..0000000 --- a/src/contrib/miniupnp/miniupnpc/mingw32make.bat +++ /dev/null @@ -1,8 +0,0 @@ -@mingw32-make -f Makefile.mingw %1 -@if errorlevel 1 goto end -@if not exist upnpc-static.exe goto end -@strip upnpc-static.exe -@upx --best upnpc-static.exe -@strip upnpc-shared.exe -@upx --best upnpc-shared.exe -:end diff --git a/src/contrib/miniupnp/miniupnpc/minihttptestserver.c b/src/contrib/miniupnp/miniupnpc/minihttptestserver.c deleted file mode 100644 index a252cd4..0000000 --- a/src/contrib/miniupnp/miniupnpc/minihttptestserver.c +++ /dev/null @@ -1,675 +0,0 @@ -/* $Id: minihttptestserver.c,v 1.23 2018/01/15 16:20:07 nanard Exp $ */ -/* Project : miniUPnP - * Author : Thomas Bernard - * Copyright (c) 2011-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK 0x7f000001 -#endif - -#define CRAP_LENGTH (2048) - -static int server(unsigned short port, const char * expected_file_name, int ipv6); - -volatile sig_atomic_t quit = 0; -volatile sig_atomic_t child_to_wait_for = 0; - -/** - * signal handler for SIGCHLD (child status has changed) - */ -void handle_signal_chld(int sig) -{ - (void)sig; - /* printf("handle_signal_chld(%d)\n", sig); */ - ++child_to_wait_for; -} - -/** - * signal handler for SIGINT (CRTL C) - */ -void handle_signal_int(int sig) -{ - (void)sig; - /* printf("handle_signal_int(%d)\n", sig); */ - quit = 1; -} - -/** - * build a text/plain content of the specified length - */ -void build_content(char * p, size_t n) -{ - char line_buffer[80]; - int k; - int i = 0; - - while(n > 0) { - k = snprintf(line_buffer, sizeof(line_buffer), - "%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n", - i, i); - if(k != 64) { - fprintf(stderr, "snprintf() returned %d in build_content()\n", k); - } - ++i; - if(n >= 64) { - memcpy(p, line_buffer, 64); - p += 64; - n -= 64; - } else { - memcpy(p, line_buffer, n); - p += n; - n = 0; - } - } -} - -/** - * build crappy content - */ -void build_crap(char * p, size_t n) -{ - static const char crap[] = "_CRAP_\r\n"; - size_t i; - - while(n > 0) { - i = sizeof(crap) - 1; - if(i > n) - i = n; - memcpy(p, crap, i); - p += i; - n -= i; - } -} - -/** - * build chunked response. - * return a malloc'ed buffer - */ -char * build_chunked_response(size_t content_length, size_t * response_len) -{ - char * response_buffer; - char * content_buffer; - size_t buffer_length; - size_t i; - unsigned int n; - - /* allocate to have some margin */ - buffer_length = 256 + content_length + (content_length >> 4); - response_buffer = malloc(buffer_length); - if(response_buffer == NULL) - return NULL; - *response_len = snprintf(response_buffer, buffer_length, - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n"); - - /* build the content */ - content_buffer = malloc(content_length); - if(content_buffer == NULL) { - free(response_buffer); - return NULL; - } - build_content(content_buffer, content_length); - - /* chunk it */ - i = 0; - while(i < content_length) { - n = (rand() % 199) + 1; - if(i + n > content_length) { - n = content_length - i; - } - /* TODO : check buffer size ! */ - *response_len += snprintf(response_buffer + *response_len, - buffer_length - *response_len, - "%x\r\n", n); - memcpy(response_buffer + *response_len, content_buffer + i, n); - *response_len += n; - i += n; - response_buffer[(*response_len)++] = '\r'; - response_buffer[(*response_len)++] = '\n'; - } - /* the last chunk : "0\r\n" a empty body and then - * the final "\r\n" */ - memcpy(response_buffer + *response_len, "0\r\n\r\n", 5); - *response_len += 5; - free(content_buffer); - - printf("resp_length=%lu buffer_length=%lu content_length=%lu\n", - *response_len, buffer_length, content_length); - return response_buffer; -} - -/* favicon.ico generator */ -#ifdef OLD_HEADER -#define FAVICON_LENGTH (6 + 16 + 12 + 8 + 32 * 4) -#else -#define FAVICON_LENGTH (6 + 16 + 40 + 8 + 32 * 4) -#endif -void build_favicon_content(unsigned char * p, size_t n) -{ - int i; - if(n < FAVICON_LENGTH) - return; - /* header : 6 bytes */ - *p++ = 0; - *p++ = 0; - *p++ = 1; /* type : ICO */ - *p++ = 0; - *p++ = 1; /* number of images in file */ - *p++ = 0; - /* image directory (1 entry) : 16 bytes */ - *p++ = 16; /* width */ - *p++ = 16; /* height */ - *p++ = 2; /* number of colors in the palette. 0 = no palette */ - *p++ = 0; /* reserved */ - *p++ = 1; /* color planes */ - *p++ = 0; /* " */ - *p++ = 1; /* bpp */ - *p++ = 0; /* " */ -#ifdef OLD_HEADER - *p++ = 12 + 8 + 32 * 4; /* bmp size */ -#else - *p++ = 40 + 8 + 32 * 4; /* bmp size */ -#endif - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 6 + 16; /* bmp offset */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - /* BMP */ -#ifdef OLD_HEADER - /* BITMAPCOREHEADER */ - *p++ = 12; /* size of this header */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 16; /* width */ - *p++ = 0; /* " */ - *p++ = 16 * 2; /* height x 2 ! */ - *p++ = 0; /* " */ - *p++ = 1; /* color planes */ - *p++ = 0; /* " */ - *p++ = 1; /* bpp */ - *p++ = 0; /* " */ -#else - /* BITMAPINFOHEADER */ - *p++ = 40; /* size of this header */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 16; /* width */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 16 * 2; /* height x 2 ! */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 0; /* " */ - *p++ = 1; /* color planes */ - *p++ = 0; /* " */ - *p++ = 1; /* bpp */ - *p++ = 0; /* " */ - /* compression method, image size, ppm x, ppm y */ - /* colors in the palette ? */ - /* important colors */ - for(i = 4 * 6; i > 0; --i) - *p++ = 0; -#endif - /* palette */ - *p++ = 0; /* b */ - *p++ = 0; /* g */ - *p++ = 0; /* r */ - *p++ = 0; /* reserved */ - *p++ = 255; /* b */ - *p++ = 255; /* g */ - *p++ = 255; /* r */ - *p++ = 0; /* reserved */ - /* pixel data */ - for(i = 16; i > 0; --i) { - if(i & 1) { - *p++ = 0125; - *p++ = 0125; - } else { - *p++ = 0252; - *p++ = 0252; - } - *p++ = 0; - *p++ = 0; - } - /* Opacity MASK */ - for(i = 16 * 4; i > 0; --i) { - *p++ = 0; - } -} - -enum modes { - MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL, MODE_FAVICON -}; - -const struct { - const enum modes mode; - const char * text; -} modes_array[] = { - {MODE_CHUNKED, "chunked"}, - {MODE_ADDCRAP, "addcrap"}, - {MODE_NORMAL, "normal"}, - {MODE_FAVICON, "favicon.ico"}, - {MODE_INVALID, NULL} -}; - -/** - * write the response with random behaviour ! - */ -void send_response(int c, const char * buffer, size_t len) -{ - ssize_t n; - while(len > 0) { - n = (rand() % 99) + 1; - if((size_t)n > len) - n = len; - n = write(c, buffer, n); - if(n < 0) { - if(errno != EINTR) { - perror("write"); - return; - } - /* if errno == EINTR, try again */ - } else { - len -= n; - buffer += n; - usleep(10000); /* 10ms */ - } - } -} - -/** - * handle the HTTP connection - */ -void handle_http_connection(int c) -{ - char request_buffer[2048]; - size_t request_len = 0; - int headers_found = 0; - ssize_t n, m; - size_t i; - char request_method[16]; - char request_uri[256]; - char http_version[16]; - char * p; - char * response_buffer; - size_t response_len; - enum modes mode; - size_t content_length = 16*1024; - - /* read the request */ - while(request_len < sizeof(request_buffer) && !headers_found) { - n = read(c, - request_buffer + request_len, - sizeof(request_buffer) - request_len); - if(n < 0) { - if(errno == EINTR) - continue; - perror("read"); - return; - } else if(n==0) { - /* remote host closed the connection */ - break; - } else { - request_len += n; - for(i = 0; i < request_len - 3; i++) { - if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) { - /* found the end of headers */ - headers_found = 1; - break; - } - } - } - } - if(!headers_found) { - /* error */ - printf("no HTTP header found in the request\n"); - return; - } - printf("headers :\n%.*s", (int)request_len, request_buffer); - /* the request have been received, now parse the request line */ - p = request_buffer; - for(i = 0; i < sizeof(request_method) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - request_method[i] = *p; - ++p; - } - request_method[i] = '\0'; - while(*p == ' ') - p++; - for(i = 0; i < (int)sizeof(request_uri) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - request_uri[i] = *p; - ++p; - } - request_uri[i] = '\0'; - while(*p == ' ') - p++; - for(i = 0; i < (int)sizeof(http_version) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - http_version[i] = *p; - ++p; - } - http_version[i] = '\0'; - printf("Method = %s, URI = %s, %s\n", - request_method, request_uri, http_version); - /* check if the request method is allowed */ - if(0 != strcmp(request_method, "GET")) { - const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n" - "Allow: GET\r\n\r\n"; - const char * pc; - /* 405 Method Not Allowed */ - /* The response MUST include an Allow header containing a list - * of valid methods for the requested resource. */ - n = sizeof(response405) - 1; - pc = response405; - while(n > 0) { - m = write(c, pc, n); - if(m<0) { - if(errno != EINTR) { - perror("write"); - return; - } - } else { - n -= m; - pc += m; - } - } - return; - } - - mode = MODE_INVALID; - /* use the request URI to know what to do */ - for(i = 0; modes_array[i].mode != MODE_INVALID; i++) { - if(strstr(request_uri, modes_array[i].text)) { - mode = modes_array[i].mode; /* found */ - break; - } - } - - switch(mode) { - case MODE_CHUNKED: - response_buffer = build_chunked_response(content_length, &response_len); - break; - case MODE_ADDCRAP: - response_len = content_length+256; - response_buffer = malloc(response_len); - if(!response_buffer) - break; - n = snprintf(response_buffer, response_len, - "HTTP/1.1 200 OK\r\n" - "Server: minihttptestserver\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: %lu\r\n" - "\r\n", content_length); - response_len = content_length+n+CRAP_LENGTH; - p = realloc(response_buffer, response_len); - if(p == NULL) { - /* error 500 */ - free(response_buffer); - response_buffer = NULL; - break; - } - response_buffer = p; - build_content(response_buffer + n, content_length); - build_crap(response_buffer + n + content_length, CRAP_LENGTH); - break; - case MODE_FAVICON: - content_length = FAVICON_LENGTH; - response_len = content_length + 256; - response_buffer = malloc(response_len); - if(!response_buffer) - break; - n = snprintf(response_buffer, response_len, - "HTTP/1.1 200 OK\r\n" - "Server: minihttptestserver\r\n" - "Content-Type: image/vnd.microsoft.icon\r\n" - "Content-Length: %lu\r\n" - "\r\n", content_length); - /* image/x-icon */ - build_favicon_content((unsigned char *)(response_buffer + n), content_length); - response_len = content_length + n; - break; - default: - response_len = content_length+256; - response_buffer = malloc(response_len); - if(!response_buffer) - break; - n = snprintf(response_buffer, response_len, - "HTTP/1.1 200 OK\r\n" - "Server: minihttptestserver\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - response_len = content_length+n; - p = realloc(response_buffer, response_len); - if(p == NULL) { - /* Error 500 */ - free(response_buffer); - response_buffer = NULL; - break; - } - response_buffer = p; - build_content(response_buffer + n, response_len - n); - } - - if(response_buffer) { - send_response(c, response_buffer, response_len); - free(response_buffer); - } else { - /* Error 500 */ - } -} - -/** - */ -int main(int argc, char * * argv) { - int ipv6 = 0; - int r, i; - unsigned short port = 0; - const char * expected_file_name = NULL; - - for(i = 1; i < argc; i++) { - if(argv[i][0] == '-') { - switch(argv[i][1]) { - case '6': - ipv6 = 1; - break; - case 'e': - /* write expected file ! */ - expected_file_name = argv[++i]; - break; - case 'p': - /* port */ - if(++i < argc) { - port = (unsigned short)atoi(argv[i]); - } - break; - default: - fprintf(stderr, "unknown command line switch '%s'\n", argv[i]); - } - } else { - fprintf(stderr, "unknown command line argument '%s'\n", argv[i]); - } - } - - srand(time(NULL)); - - r = server(port, expected_file_name, ipv6); - if(r != 0) { - printf("*** ERROR ***\n"); - } - return r; -} - -static int server(unsigned short port, const char * expected_file_name, int ipv6) -{ - int s, c; - int i; - struct sockaddr_storage server_addr; - socklen_t server_addrlen; - struct sockaddr_storage client_addr; - socklen_t client_addrlen; - pid_t pid; - int child = 0; - int status; - struct sigaction sa; - - memset(&sa, 0, sizeof(struct sigaction)); - - /*signal(SIGCHLD, handle_signal_chld);*/ - sa.sa_handler = handle_signal_chld; - if(sigaction(SIGCHLD, &sa, NULL) < 0) { - perror("sigaction"); - return 1; - } - /*signal(SIGINT, handle_signal_int);*/ - sa.sa_handler = handle_signal_int; - if(sigaction(SIGINT, &sa, NULL) < 0) { - perror("sigaction"); - return 1; - } - - s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); - if(s < 0) { - perror("socket"); - return 1; - } - memset(&server_addr, 0, sizeof(struct sockaddr_storage)); - memset(&client_addr, 0, sizeof(struct sockaddr_storage)); - if(ipv6) { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; - addr->sin6_family = AF_INET6; - addr->sin6_port = htons(port); - addr->sin6_addr = in6addr_loopback; - } else { - struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; - addr->sin_family = AF_INET; - addr->sin_port = htons(port); - addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - if(bind(s, (struct sockaddr *)&server_addr, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) { - perror("bind"); - return 1; - } - if(listen(s, 5) < 0) { - perror("listen"); - } - if(port == 0) { - server_addrlen = sizeof(struct sockaddr_storage); - if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) { - perror("getsockname"); - return 1; - } - if(ipv6) { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; - port = ntohs(addr->sin6_port); - } else { - struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; - port = ntohs(addr->sin_port); - } - printf("Listening on port %hu\n", port); - fflush(stdout); - } - - /* write expected file */ - if(expected_file_name) { - FILE * f; - f = fopen(expected_file_name, "wb"); - if(f) { - char * buffer; - buffer = malloc(16*1024); - if(buffer == NULL) { - fprintf(stderr, "memory allocation error\n"); - } else { - build_content(buffer, 16*1024); - i = fwrite(buffer, 1, 16*1024, f); - if(i != 16*1024) { - fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024); - } - free(buffer); - } - fclose(f); - } else { - fprintf(stderr, "error opening file %s for writing\n", expected_file_name); - } - } - - /* fork() loop */ - while(!child && !quit) { - while(child_to_wait_for > 0) { - pid = wait(&status); - if(pid < 0) { - perror("wait"); - } else { - printf("child(%d) terminated with status %d\n", (int)pid, status); - } - --child_to_wait_for; - } - client_addrlen = sizeof(struct sockaddr_storage); - c = accept(s, (struct sockaddr *)&client_addr, - &client_addrlen); - if(c < 0) { - if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - continue; - perror("accept"); - return 1; - } - printf("accept...\n"); - pid = fork(); - if(pid < 0) { - perror("fork"); - return 1; - } else if(pid == 0) { - /* child */ - child = 1; - close(s); - s = -1; - handle_http_connection(c); - } - close(c); - } - if(s >= 0) { - close(s); - s = -1; - } - if(!child) { - while(child_to_wait_for > 0) { - pid = wait(&status); - if(pid < 0) { - perror("wait"); - } else { - printf("child(%d) terminated with status %d\n", (int)pid, status); - } - --child_to_wait_for; - } - printf("Bye...\n"); - } - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpc/minisoap.c b/src/contrib/miniupnp/miniupnpc/minisoap.c deleted file mode 100644 index 520c930..0000000 --- a/src/contrib/miniupnp/miniupnpc/minisoap.c +++ /dev/null @@ -1,124 +0,0 @@ -/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * - * Minimal SOAP implementation for UPnP protocol. - */ -#include -#include -#ifdef _WIN32 -#include -#include -#define snprintf _snprintf -#else -#include -#include -#include -#endif -#include "minisoap.h" -#include "miniupnpcstrings.h" - -/* only for malloc */ -#include - -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -/* httpWrite sends the headers and the body to the socket - * and returns the number of bytes sent */ -static int -httpWrite(SOCKET fd, const char * body, int bodysize, - const char * headers, int headerssize) -{ - int n = 0; - /*n = write(fd, headers, headerssize);*/ - /*if(bodysize>0) - n += write(fd, body, bodysize);*/ - /* Note : my old linksys router only took into account - * soap request that are sent into only one packet */ - char * p; - /* TODO: AVOID MALLOC, we could use writev() for that */ - p = malloc(headerssize+bodysize); - if(!p) - return -1; - memcpy(p, headers, headerssize); - memcpy(p+headerssize, body, bodysize); - /*n = write(fd, p, headerssize+bodysize);*/ - n = send(fd, p, headerssize+bodysize, 0); - if(n<0) { - PRINT_SOCKET_ERROR("send"); - } - /* disable send on the socket */ - /* draytek routers don't seem to like that... */ -#if 0 -#ifdef _WIN32 - if(shutdown(fd, SD_SEND)<0) { -#else - if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ -#endif - PRINT_SOCKET_ERROR("shutdown"); - } -#endif - free(p); - return n; -} - -/* self explanatory */ -int soapPostSubmit(SOCKET fd, - const char * url, - const char * host, - unsigned short port, - const char * action, - const char * body, - const char * httpversion) -{ - int bodysize; - char headerbuf[512]; - int headerssize; - char portstr[8]; - bodysize = (int)strlen(body); - /* We are not using keep-alive HTTP connections. - * HTTP/1.1 needs the header Connection: close to do that. - * This is the default with HTTP/1.0 - * Using HTTP/1.1 means we need to support chunked transfer-encoding : - * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked - * transfer encoding. */ - /* Connection: Close is normally there only in HTTP/1.1 but who knows */ - portstr[0] = '\0'; - if(port != 80) - snprintf(portstr, sizeof(portstr), ":%hu", port); - headerssize = snprintf(headerbuf, sizeof(headerbuf), - "POST %s HTTP/%s\r\n" - "Host: %s%s\r\n" - "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" - "Content-Length: %d\r\n" - "Content-Type: text/xml\r\n" - "SOAPAction: \"%s\"\r\n" - "Connection: Close\r\n" - "Cache-Control: no-cache\r\n" /* ??? */ - "Pragma: no-cache\r\n" - "\r\n", - url, httpversion, host, portstr, bodysize, action); - if ((unsigned int)headerssize >= sizeof(headerbuf)) - return -1; -#ifdef DEBUG - /*printf("SOAP request : headersize=%d bodysize=%d\n", - headerssize, bodysize); - */ - printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", - url, httpversion, host, portstr); - printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); - printf("Headers :\n%s", headerbuf); - printf("Body :\n%s\n", body); -#endif - return httpWrite(fd, body, bodysize, headerbuf, headerssize); -} - - diff --git a/src/contrib/miniupnp/miniupnpc/minisoap.h b/src/contrib/miniupnp/miniupnpc/minisoap.h deleted file mode 100644 index d6a45d0..0000000 --- a/src/contrib/miniupnp/miniupnpc/minisoap.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ -#ifndef MINISOAP_H_INCLUDED -#define MINISOAP_H_INCLUDED - -#include "miniupnpc_socketdef.h" - -/*int httpWrite(int, const char *, int, const char *);*/ -int soapPostSubmit(SOCKET, const char *, const char *, unsigned short, - const char *, const char *, const char *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/minissdpc.c b/src/contrib/miniupnp/miniupnpc/minissdpc.c deleted file mode 100644 index d76b242..0000000 --- a/src/contrib/miniupnp/miniupnpc/minissdpc.c +++ /dev/null @@ -1,888 +0,0 @@ -/* $Id: minissdpc.c,v 1.32 2016/10/07 09:04:36 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2018 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -/*#include */ -#include -#include -#include -#include -#if defined (__NetBSD__) -#include -#endif -#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) -#ifdef _WIN32 -#include -#include -#include -#include -#define snprintf _snprintf -#if !defined(_MSC_VER) -#include -#else /* !defined(_MSC_VER) */ -typedef unsigned short uint16_t; -#endif /* !defined(_MSC_VER) */ -#ifndef strncasecmp -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define strncasecmp _memicmp -#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#define strncasecmp memicmp -#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#endif /* #ifndef strncasecmp */ -#endif /* _WIN32 */ -#if defined(__amigaos__) || defined(__amigaos4__) -#include -#endif /* defined(__amigaos__) || defined(__amigaos4__) */ -#if defined(__amigaos__) -#define uint16_t unsigned short -#endif /* defined(__amigaos__) */ -/* Hack */ -#define UNIX_PATH_LEN 108 -struct sockaddr_un { - uint16_t sun_family; - char sun_path[UNIX_PATH_LEN]; -}; -#else /* defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define closesocket close -#endif - -#include "miniupnpc_socketdef.h" - -#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) -#define HAS_IP_MREQN -#endif - -#if !defined(HAS_IP_MREQN) && !defined(_WIN32) -#include -#if defined(__sun) -#include -#endif -#endif - -#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) -/* Several versions of glibc don't define this structure, - * define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ -struct ip_mreqn -{ - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_address; /* local IP address of interface */ - int imr_ifindex; /* Interface index */ -}; -#endif - -#if defined(__amigaos__) || defined(__amigaos4__) -/* Amiga OS specific stuff */ -#define TIMEVAL struct timeval -#endif - -#include "minissdpc.h" -#include "miniupnpc.h" -#include "receivedata.h" - -#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) - -#include "codelength.h" - -struct UPNPDev * -getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error) -{ - struct UPNPDev * devlist = NULL; - int s; - int res; - - s = connectToMiniSSDPD(socketpath); - if (s < 0) { - if (error) - *error = s; - return NULL; - } - res = requestDevicesFromMiniSSDPD(s, devtype); - if (res < 0) { - if (error) - *error = res; - } else { - devlist = receiveDevicesFromMiniSSDPD(s, error); - } - disconnectFromMiniSSDPD(s); - return devlist; -} - -/* macros used to read from unix socket */ -#define READ_BYTE_BUFFER(c) \ - if((int)bufferindex >= n) { \ - n = read(s, buffer, sizeof(buffer)); \ - if(n<=0) break; \ - bufferindex = 0; \ - } \ - c = buffer[bufferindex++]; - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif /* MIN */ - -#define READ_COPY_BUFFER(dst, len) \ - for(l = len, p = (unsigned char *)dst; l > 0; ) { \ - unsigned int lcopy; \ - if((int)bufferindex >= n) { \ - n = read(s, buffer, sizeof(buffer)); \ - if(n<=0) break; \ - bufferindex = 0; \ - } \ - lcopy = MIN(l, (n - bufferindex)); \ - memcpy(p, buffer + bufferindex, lcopy); \ - l -= lcopy; \ - p += lcopy; \ - bufferindex += lcopy; \ - } - -#define READ_DISCARD_BUFFER(len) \ - for(l = len; l > 0; ) { \ - unsigned int lcopy; \ - if(bufferindex >= n) { \ - n = read(s, buffer, sizeof(buffer)); \ - if(n<=0) break; \ - bufferindex = 0; \ - } \ - lcopy = MIN(l, (n - bufferindex)); \ - l -= lcopy; \ - bufferindex += lcopy; \ - } - -int -connectToMiniSSDPD(const char * socketpath) -{ - int s; - struct sockaddr_un addr; -#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) - struct timeval timeout; -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s < 0) - { - /*syslog(LOG_ERR, "socket(unix): %m");*/ - perror("socket(unix)"); - return MINISSDPC_SOCKET_ERROR; - } -#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun) - /* setting a 3 seconds timeout */ - /* not supported for AF_UNIX sockets under Solaris */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt SO_RCVTIMEO unix"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - perror("setsockopt SO_SNDTIMEO unix"); - } -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - if(!socketpath) - socketpath = "/var/run/minissdpd.sock"; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); - /* TODO : check if we need to handle the EINTR */ - if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) - { - /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ - close(s); - return MINISSDPC_SOCKET_ERROR; - } - return s; -} - -int -disconnectFromMiniSSDPD(int s) -{ - if (close(s) < 0) - return MINISSDPC_SOCKET_ERROR; - return MINISSDPC_SUCCESS; -} - -int -requestDevicesFromMiniSSDPD(int s, const char * devtype) -{ - unsigned char buffer[256]; - unsigned char * p; - unsigned int stsize, l; - - stsize = strlen(devtype); - if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8)) - { - buffer[0] = 3; /* request type 3 : everything */ - } - else - { - buffer[0] = 1; /* request type 1 : request devices/services by type */ - } - p = buffer + 1; - l = stsize; CODELENGTH(l, p); - if(p + stsize > buffer + sizeof(buffer)) - { - /* devtype is too long ! */ -#ifdef DEBUG - fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n", - stsize, (unsigned)sizeof(buffer)); -#endif /* DEBUG */ - return MINISSDPC_INVALID_INPUT; - } - memcpy(p, devtype, stsize); - p += stsize; - if(write(s, buffer, p - buffer) < 0) - { - /*syslog(LOG_ERR, "write(): %m");*/ - perror("minissdpc.c: write()"); - return MINISSDPC_SOCKET_ERROR; - } - return MINISSDPC_SUCCESS; -} - -struct UPNPDev * -receiveDevicesFromMiniSSDPD(int s, int * error) -{ - struct UPNPDev * tmp; - struct UPNPDev * devlist = NULL; - unsigned char buffer[256]; - ssize_t n; - unsigned char * p; - unsigned char * url; - unsigned char * st; - unsigned int bufferindex; - unsigned int i, ndev; - unsigned int urlsize, stsize, usnsize, l; - - n = read(s, buffer, sizeof(buffer)); - if(n<=0) - { - perror("minissdpc.c: read()"); - if (error) - *error = MINISSDPC_SOCKET_ERROR; - return NULL; - } - ndev = buffer[0]; - bufferindex = 1; - for(i = 0; i < ndev; i++) - { - DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - return devlist; - } -#ifdef DEBUG - printf(" urlsize=%u", urlsize); -#endif /* DEBUG */ - url = malloc(urlsize); - if(url == NULL) { - if (error) - *error = MINISSDPC_MEMORY_ERROR; - return devlist; - } - READ_COPY_BUFFER(url, urlsize); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - goto free_url_and_return; - } - DECODELENGTH_READ(stsize, READ_BYTE_BUFFER); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - goto free_url_and_return; - } -#ifdef DEBUG - printf(" stsize=%u", stsize); -#endif /* DEBUG */ - st = malloc(stsize); - if (st == NULL) { - if (error) - *error = MINISSDPC_MEMORY_ERROR; - goto free_url_and_return; - } - READ_COPY_BUFFER(st, stsize); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - goto free_url_and_st_and_return; - } - DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - goto free_url_and_st_and_return; - } -#ifdef DEBUG - printf(" usnsize=%u\n", usnsize); -#endif /* DEBUG */ - tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); - if(tmp == NULL) { - if (error) - *error = MINISSDPC_MEMORY_ERROR; - goto free_url_and_st_and_return; - } - tmp->pNext = devlist; - tmp->descURL = tmp->buffer; - tmp->st = tmp->buffer + 1 + urlsize; - memcpy(tmp->buffer, url, urlsize); - tmp->buffer[urlsize] = '\0'; - memcpy(tmp->st, st, stsize); - tmp->buffer[urlsize+1+stsize] = '\0'; - free(url); - free(st); - url = NULL; - st = NULL; - tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize; - READ_COPY_BUFFER(tmp->usn, usnsize); - if(n<=0) { - if (error) - *error = MINISSDPC_INVALID_SERVER_REPLY; - goto free_tmp_and_return; - } - tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; - tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */ - devlist = tmp; - } - if (error) - *error = MINISSDPC_SUCCESS; - return devlist; - -free_url_and_st_and_return: - free(st); -free_url_and_return: - free(url); - return devlist; - -free_tmp_and_return: - free(tmp); - return devlist; -} - -#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ - -/* parseMSEARCHReply() - * the last 4 arguments are filled during the parsing : - * - location/locationsize : "location:" field of the SSDP reply packet - * - st/stsize : "st:" field of the SSDP reply packet. - * The strings are NOT null terminated */ -static void -parseMSEARCHReply(const char * reply, int size, - const char * * location, int * locationsize, - const char * * st, int * stsize, - const char * * usn, int * usnsize) -{ - int a, b, i; - i = 0; - a = i; /* start of the line */ - b = 0; /* end of the "header" (position of the colon) */ - while(isin6_family = AF_INET6; - if(localport > 0 && localport < 65536) - p->sin6_port = htons((unsigned short)localport); - p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ - } else { - struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; - p->sin_family = AF_INET; - if(localport > 0 && localport < 65536) - p->sin_port = htons((unsigned short)localport); - p->sin_addr.s_addr = INADDR_ANY; - } -#ifdef _WIN32 -/* This code could help us to use the right Network interface for - * SSDP multicast traffic */ -/* Get IP associated with the index given in the ip_forward struct - * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ - if(!ipv6 - && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { - DWORD dwRetVal = 0; - PMIB_IPADDRTABLE pIPAddrTable; - DWORD dwSize = 0; -#ifdef DEBUG - IN_ADDR IPAddr; -#endif - int i; -#ifdef DEBUG - printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); -#endif - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); - if(pIPAddrTable) { - if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { - free(pIPAddrTable); - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); - } - } - if(pIPAddrTable) { - dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); - if (dwRetVal == NO_ERROR) { -#ifdef DEBUG - printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); -#endif - for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { -#ifdef DEBUG - printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; - printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; - printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; - printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); - printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); - printf("\tType and State[%d]:", i); - printf("\n"); -#endif - if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { - /* Set the address of this interface to be used */ - struct in_addr mc_if; - memset(&mc_if, 0, sizeof(mc_if)); - mc_if.s_addr = pIPAddrTable->table[i].dwAddr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { - PRINT_SOCKET_ERROR("setsockopt"); - } - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; -#ifndef DEBUG - break; -#endif - } - } - } - free(pIPAddrTable); - pIPAddrTable = NULL; - } - } -#endif /* _WIN32 */ - -#ifdef _WIN32 - if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) -#else - if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) -#endif - { - if(error) - *error = MINISSDPC_SOCKET_ERROR; - PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)"); - return NULL; - } - - if(ipv6) { -#ifdef _WIN32 - DWORD mcastHops = ttl; - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0) -#else /* _WIN32 */ - int mcastHops = ttl; - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0) -#endif /* _WIN32 */ - { - PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)"); - } - } else { -#ifdef _WIN32 - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0) -#else /* _WIN32 */ - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) -#endif /* _WIN32 */ - { - /* not a fatal error */ - PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); - } - } - - if(multicastif) - { - if(ipv6) { -#if !defined(_WIN32) - /* according to MSDN, if_nametoindex() is supported since - * MS Windows Vista and MS Windows Server 2008. - * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ - unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF"); - } -#else -#ifdef DEBUG - printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); -#endif -#endif - } else { - struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ - if(mc_if.s_addr != INADDR_NONE) - { - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); - } - } else { -#ifdef HAS_IP_MREQN - /* was not an ip address, try with an interface name */ - struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ - memset(&reqn, 0, sizeof(struct ip_mreqn)); - reqn.imr_ifindex = if_nametoindex(multicastif); - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); - } -#elif !defined(_WIN32) - struct ifreq ifr; - int ifrlen = sizeof(ifr); - strncpy(ifr.ifr_name, multicastif, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ-1] = '\0'; - if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0) - { - PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)"); - } - mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); - } -#else /* _WIN32 */ -#ifdef DEBUG - printf("Setting of multicast interface not supported with interface name.\n"); -#endif -#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */ - } - } - } - - /* Before sending the packed, we first "bind" in order to be able - * to receive the response */ - if (bind(sudp, (const struct sockaddr *)&sockudp_r, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) - { - if(error) - *error = MINISSDPC_SOCKET_ERROR; - PRINT_SOCKET_ERROR("bind"); - closesocket(sudp); - return NULL; - } - - if(error) - *error = MINISSDPC_SUCCESS; - /* Calculating maximum response time in seconds */ - mx = ((unsigned int)delay) / 1000u; - if(mx == 0) { - mx = 1; - delay = 1000; - } - /* receiving SSDP response packet */ - for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { - sentok = 0; - /* sending the SSDP M-SEARCH packet */ - n = snprintf(bufr, sizeof(bufr), - MSearchMsgFmt, - ipv6 ? - (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") - : UPNP_MCAST_ADDR, - deviceTypes[deviceIndex], mx); - if ((unsigned int)n >= sizeof(bufr)) { - if(error) - *error = MINISSDPC_MEMORY_ERROR; - goto error; - } -#ifdef DEBUG - /*printf("Sending %s", bufr);*/ - printf("Sending M-SEARCH request to %s with ST: %s\n", - ipv6 ? - (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") - : UPNP_MCAST_ADDR, - deviceTypes[deviceIndex]); -#endif -#ifdef NO_GETADDRINFO - /* the following code is not using getaddrinfo */ - /* emission */ - memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); - if(ipv6) { - struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; - p->sin6_family = AF_INET6; - p->sin6_port = htons(SSDP_PORT); - inet_pton(AF_INET6, - linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, - &(p->sin6_addr)); - } else { - struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; - p->sin_family = AF_INET; - p->sin_port = htons(SSDP_PORT); - p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); - } - n = sendto(sudp, bufr, n, 0, &sockudp_w, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - if (n < 0) { - if(error) - *error = MINISSDPC_SOCKET_ERROR; - PRINT_SOCKET_ERROR("sendto"); - } else { - sentok = 1; - } -#else /* #ifdef NO_GETADDRINFO */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ - hints.ai_socktype = SOCK_DGRAM; - /*hints.ai_flags = */ - if ((rv = getaddrinfo(ipv6 - ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) - : UPNP_MCAST_ADDR, - XSTR(SSDP_PORT), &hints, &servinfo)) != 0) { - if(error) - *error = MINISSDPC_SOCKET_ERROR; -#ifdef _WIN32 - fprintf(stderr, "getaddrinfo() failed: %d\n", rv); -#else - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); -#endif - break; - } - for(p = servinfo; p; p = p->ai_next) { - n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); - if (n < 0) { -#ifdef DEBUG - char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; - if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, - sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { - fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); - } -#endif - PRINT_SOCKET_ERROR("sendto"); - continue; - } else { - sentok = 1; - } - } - freeaddrinfo(servinfo); - if(!sentok) { - if(error) - *error = MINISSDPC_SOCKET_ERROR; - } -#endif /* #ifdef NO_GETADDRINFO */ - /* Waiting for SSDP REPLY packet to M-SEARCH - * if searchalltypes is set, enter the loop only - * when the last deviceType is reached */ - if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do { - n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); - if (n < 0) { - /* error */ - if(error) - *error = MINISSDPC_SOCKET_ERROR; - goto error; - } else if (n == 0) { - /* no data or Time Out */ -#ifdef DEBUG - printf("NODATA or TIMEOUT\n"); -#endif /* DEBUG */ - if (devlist && !searchalltypes) { - /* found some devices, stop now*/ - if(error) - *error = MINISSDPC_SUCCESS; - goto error; - } - } else { - const char * descURL=NULL; - int urlsize=0; - const char * st=NULL; - int stsize=0; - const char * usn=NULL; - int usnsize=0; - parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); - if(st&&descURL) { -#ifdef DEBUG - printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", - stsize, st, usnsize, (usn?usn:""), urlsize, descURL); -#endif /* DEBUG */ - for(tmp=devlist; tmp; tmp = tmp->pNext) { - if(memcmp(tmp->descURL, descURL, urlsize) == 0 && - tmp->descURL[urlsize] == '\0' && - memcmp(tmp->st, st, stsize) == 0 && - tmp->st[stsize] == '\0' && - (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) && - tmp->usn[usnsize] == '\0') - break; - } - /* at the exit of the loop above, tmp is null if - * no duplicate device was found */ - if(tmp) - continue; - tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); - if(!tmp) { - /* memory allocation error */ - if(error) - *error = MINISSDPC_MEMORY_ERROR; - goto error; - } - tmp->pNext = devlist; - tmp->descURL = tmp->buffer; - tmp->st = tmp->buffer + 1 + urlsize; - tmp->usn = tmp->st + 1 + stsize; - memcpy(tmp->buffer, descURL, urlsize); - tmp->buffer[urlsize] = '\0'; - memcpy(tmp->st, st, stsize); - tmp->buffer[urlsize+1+stsize] = '\0'; - if(usn != NULL) - memcpy(tmp->usn, usn, usnsize); - tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; - tmp->scope_id = scope_id; - devlist = tmp; - } - } - } while(n > 0); - if(ipv6) { - /* switch linklocal flag */ - if(linklocal) { - linklocal = 0; - --deviceIndex; - } else { - linklocal = 1; - } - } - } -error: - closesocket(sudp); - return devlist; -} - diff --git a/src/contrib/miniupnp/miniupnpc/minissdpc.h b/src/contrib/miniupnp/miniupnpc/minissdpc.h deleted file mode 100644 index 167d897..0000000 --- a/src/contrib/miniupnp/miniupnpc/minissdpc.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $Id: minissdpc.h,v 1.6 2015/09/18 12:45:16 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINISSDPC_H_INCLUDED -#define MINISSDPC_H_INCLUDED - -#include "miniupnpc_declspec.h" -#include "upnpdev.h" - -/* error codes : */ -#define MINISSDPC_SUCCESS (0) -#define MINISSDPC_UNKNOWN_ERROR (-1) -#define MINISSDPC_SOCKET_ERROR (-101) -#define MINISSDPC_MEMORY_ERROR (-102) -#define MINISSDPC_INVALID_INPUT (-103) -#define MINISSDPC_INVALID_SERVER_REPLY (-104) - -#ifdef __cplusplus -extern "C" { -#endif - -#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) - -MINIUPNP_LIBSPEC struct UPNPDev * -getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error); - -MINIUPNP_LIBSPEC int -connectToMiniSSDPD(const char * socketpath); - -MINIUPNP_LIBSPEC int -disconnectFromMiniSSDPD(int fd); - -MINIUPNP_LIBSPEC int -requestDevicesFromMiniSSDPD(int fd, const char * devtype); - -MINIUPNP_LIBSPEC struct UPNPDev * -receiveDevicesFromMiniSSDPD(int fd, int * error); - -#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */ - -MINIUPNP_LIBSPEC struct UPNPDev * -ssdpDiscoverDevices(const char * const deviceTypes[], - int delay, const char * multicastif, - int localport, - int ipv6, unsigned char ttl, - int * error, - int searchalltypes); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpc.c b/src/contrib/miniupnp/miniupnpc/miniupnpc.c deleted file mode 100644 index 5d93ef9..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpc.c +++ /dev/null @@ -1,727 +0,0 @@ -/* $Id: miniupnpc.c,v 1.149 2016/02/09 09:50:46 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2018 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENSE file. */ -#include -#include -#include -#ifdef _WIN32 -/* Win32 Specific includes and defines */ -#include -#include -#include -#include -#define snprintf _snprintf -#define strdup _strdup -#ifndef strncasecmp -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define strncasecmp _memicmp -#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#define strncasecmp memicmp -#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#endif /* #ifndef strncasecmp */ -#define MAXHOSTNAMELEN 64 -#else /* #ifdef _WIN32 */ -/* Standard POSIX includes */ -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -/* Amiga OS 3 specific stuff */ -#define socklen_t int -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if !defined(__amigaos__) && !defined(__amigaos4__) -#include -#endif -#include -#include -#define closesocket close -#endif /* #else _WIN32 */ -#ifdef __GNU__ -#define MAXHOSTNAMELEN 64 -#endif - - -#include "miniupnpc.h" -#include "minissdpc.h" -#include "miniwget.h" -#include "miniwget_private.h" -#include "minisoap.h" -#include "minixml.h" -#include "upnpcommands.h" -#include "connecthostport.h" - -/* compare the beginning of a string with a constant string */ -#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1)) - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define SOAPPREFIX "s" -#define SERVICEPREFIX "u" -#define SERVICEPREFIX2 'u' - -/* check if an ip address is a private (LAN) address - * see https://tools.ietf.org/html/rfc1918 */ -static int is_rfc1918addr(const char * addr) -{ - /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ - if(COMPARE(addr, "192.168.")) - return 1; - /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ - if(COMPARE(addr, "10.")) - return 1; - /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ - if(COMPARE(addr, "172.")) { - int i = atoi(addr + 4); - if((16 <= i) && (i <= 31)) - return 1; - } - return 0; -} - -/* root description parsing */ -MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) -{ - struct xmlparser parser; - /* xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parser.attfunc = 0; - parsexml(&parser); -#ifdef DEBUG - printIGD(data); -#endif -} - -/* simpleUPnPcommand2 : - * not so simple ! - * return values : - * pointer - OK - * NULL - error */ -static char * -simpleUPnPcommand2(SOCKET s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize, const char * httpversion) -{ - char hostname[MAXHOSTNAMELEN+1]; - unsigned short port = 0; - char * path; - char soapact[128]; - char soapbody[2048]; - int soapbodylen; - char * buf; - int n; - int status_code; - - *bufsize = 0; - snprintf(soapact, sizeof(soapact), "%s#%s", service, action); - if(args==NULL) - { - soapbodylen = snprintf(soapbody, sizeof(soapbody), - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" - "" - "" - "\r\n", action, service, action); - if ((unsigned int)soapbodylen >= sizeof(soapbody)) - return NULL; - } - else - { - char * p; - const char * pe, * pv; - const char * const pend = soapbody + sizeof(soapbody); - soapbodylen = snprintf(soapbody, sizeof(soapbody), - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">", - action, service); - if ((unsigned int)soapbodylen >= sizeof(soapbody)) - return NULL; - p = soapbody + soapbodylen; - while(args->elt) - { - if(p >= pend) /* check for space to write next byte */ - return NULL; - *(p++) = '<'; - - pe = args->elt; - while(p < pend && *pe) - *(p++) = *(pe++); - - if(p >= pend) /* check for space to write next byte */ - return NULL; - *(p++) = '>'; - - if((pv = args->val)) - { - while(p < pend && *pv) - *(p++) = *(pv++); - } - - if((p+2) > pend) /* check for space to write next 2 bytes */ - return NULL; - *(p++) = '<'; - *(p++) = '/'; - - pe = args->elt; - while(p < pend && *pe) - *(p++) = *(pe++); - - if(p >= pend) /* check for space to write next byte */ - return NULL; - *(p++) = '>'; - - args++; - } - if((p+4) > pend) /* check for space to write next 4 bytes */ - return NULL; - *(p++) = '<'; - *(p++) = '/'; - *(p++) = SERVICEPREFIX2; - *(p++) = ':'; - - pe = action; - while(p < pend && *pe) - *(p++) = *(pe++); - - strncpy(p, ">\r\n", - pend - p); - if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */ - return NULL; - } - if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; - if(ISINVALID(s)) { - s = connecthostport(hostname, port, 0); - if(ISINVALID(s)) { - /* failed to connect */ - return NULL; - } - } - - n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); - if(n<=0) { -#ifdef DEBUG - printf("Error sending SOAP request\n"); -#endif - closesocket(s); - return NULL; - } - - buf = getHTTPResponse(s, bufsize, &status_code); -#ifdef DEBUG - if(*bufsize > 0 && buf) - { - printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf); - } - else - { - printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize); - } -#endif - closesocket(s); - return buf; -} - -/* simpleUPnPcommand : - * not so simple ! - * return values : - * pointer - OK - * NULL - error */ -char * -simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize) -{ - char * buf; - -#if 1 - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); -#else - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0"); - if (!buf || *bufsize == 0) - { -#if DEBUG - printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); -#endif - buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1"); - } -#endif - return buf; -} - -/* upnpDiscoverDevices() : - * return a chained list of all devices found or NULL if - * no devices was found. - * It is up to the caller to free the chained list - * delay is in millisecond (poll). - * UDA v1.1 says : - * The TTL for the IP packet SHOULD default to 2 and - * SHOULD be configurable. */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevices(const char * const deviceTypes[], - int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error, - int searchalltypes) -{ - struct UPNPDev * tmp; - struct UPNPDev * devlist = 0; -#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) - int deviceIndex; -#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ - - if(error) - *error = UPNPDISCOVER_UNKNOWN_ERROR; -#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) - /* first try to get infos from minissdpd ! */ - if(!minissdpdsock) - minissdpdsock = "/var/run/minissdpd.sock"; - if(minissdpdsock[0] != '\0') { - for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { - struct UPNPDev * minissdpd_devlist; - int only_rootdevice = 1; - minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex], - minissdpdsock, 0); - if(minissdpd_devlist) { -#ifdef DEBUG - printf("returned by MiniSSDPD: %s\t%s\n", - minissdpd_devlist->st, minissdpd_devlist->descURL); -#endif /* DEBUG */ - if(!strstr(minissdpd_devlist->st, "rootdevice")) - only_rootdevice = 0; - for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) { -#ifdef DEBUG - printf("returned by MiniSSDPD: %s\t%s\n", - tmp->pNext->st, tmp->pNext->descURL); -#endif /* DEBUG */ - if(!strstr(tmp->st, "rootdevice")) - only_rootdevice = 0; - } - tmp->pNext = devlist; - devlist = minissdpd_devlist; - if(!searchalltypes && !only_rootdevice) - break; - } - } - } - for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) { - /* We return what we have found if it was not only a rootdevice */ - if(!strstr(tmp->st, "rootdevice")) { - if(error) - *error = UPNPDISCOVER_SUCCESS; - return devlist; - } - } -#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ - - /* direct discovery if minissdpd responses are not sufficient */ - { - struct UPNPDev * discovered_devlist; - discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport, - ipv6, ttl, error, searchalltypes); - if(devlist == NULL) - devlist = discovered_devlist; - else { - for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext); - tmp->pNext = discovered_devlist; - } - } - return devlist; -} - -/* upnpDiscover() Discover IGD device */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error) -{ - static const char * const deviceList[] = { -#if 0 - "urn:schemas-upnp-org:device:InternetGatewayDevice:2", - "urn:schemas-upnp-org:service:WANIPConnection:2", -#endif - "urn:schemas-upnp-org:device:InternetGatewayDevice:1", - "urn:schemas-upnp-org:service:WANIPConnection:1", - "urn:schemas-upnp-org:service:WANPPPConnection:1", - "upnp:rootdevice", - /*"ssdp:all",*/ - 0 - }; - return upnpDiscoverDevices(deviceList, - delay, multicastif, minissdpdsock, localport, - ipv6, ttl, error, 0); -} - -/* upnpDiscoverAll() Discover all UPnP devices */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverAll(int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error) -{ - static const char * const deviceList[] = { - /*"upnp:rootdevice",*/ - "ssdp:all", - 0 - }; - return upnpDiscoverDevices(deviceList, - delay, multicastif, minissdpdsock, localport, - ipv6, ttl, error, 0); -} - -/* upnpDiscoverDevice() Discover a specific device */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevice(const char * device, int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error) -{ - const char * const deviceList[] = { - device, - 0 - }; - return upnpDiscoverDevices(deviceList, - delay, multicastif, minissdpdsock, localport, - ipv6, ttl, error, 0); -} - -static char * -build_absolute_url(const char * baseurl, const char * descURL, - const char * url, unsigned int scope_id) -{ - int l, n; - char * s; - const char * base; - char * p; -#if defined(IF_NAMESIZE) && !defined(_WIN32) - char ifname[IF_NAMESIZE]; -#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - char scope_str[8]; -#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - - if( (url[0] == 'h') - &&(url[1] == 't') - &&(url[2] == 't') - &&(url[3] == 'p') - &&(url[4] == ':') - &&(url[5] == '/') - &&(url[6] == '/')) - return strdup(url); - base = (baseurl[0] == '\0') ? descURL : baseurl; - n = strlen(base); - if(n > 7) { - p = strchr(base + 7, '/'); - if(p) - n = p - base; - } - l = n + strlen(url) + 1; - if(url[0] != '/') - l++; - if(scope_id != 0) { -#if defined(IF_NAMESIZE) && !defined(_WIN32) - if(if_indextoname(scope_id, ifname)) { - l += 3 + strlen(ifname); /* 3 == strlen(%25) */ - } -#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - /* under windows, scope is numerical */ - l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); -#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - } - s = malloc(l); - if(s == NULL) return NULL; - memcpy(s, base, n); - if(scope_id != 0) { - s[n] = '\0'; - if(0 == memcmp(s, "http://[fe80:", 13)) { - /* this is a linklocal IPv6 address */ - p = strchr(s, ']'); - if(p) { - /* insert %25 into URL */ -#if defined(IF_NAMESIZE) && !defined(_WIN32) - memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); - memcpy(p, "%25", 3); - memcpy(p + 3, ifname, strlen(ifname)); - n += 3 + strlen(ifname); -#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); - memcpy(p, "%25", 3); - memcpy(p + 3, scope_str, strlen(scope_str)); - n += 3 + strlen(scope_str); -#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ - } - } - } - if(url[0] != '/') - s[n++] = '/'; - memcpy(s + n, url, l - n); - return s; -} - -/* Prepare the Urls for usage... - */ -MINIUPNP_LIBSPEC void -GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, - const char * descURL, unsigned int scope_id) -{ - /* strdup descURL */ - urls->rootdescURL = strdup(descURL); - - /* get description of WANIPConnection */ - urls->ipcondescURL = build_absolute_url(data->urlbase, descURL, - data->first.scpdurl, scope_id); - urls->controlURL = build_absolute_url(data->urlbase, descURL, - data->first.controlurl, scope_id); - urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL, - data->CIF.controlurl, scope_id); - urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL, - data->IPv6FC.controlurl, scope_id); - -#ifdef DEBUG - printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL); - printf("urls->controlURL='%s'\n", urls->controlURL); - printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF); - printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC); -#endif -} - -MINIUPNP_LIBSPEC void -FreeUPNPUrls(struct UPNPUrls * urls) -{ - if(!urls) - return; - free(urls->controlURL); - urls->controlURL = 0; - free(urls->ipcondescURL); - urls->ipcondescURL = 0; - free(urls->controlURL_CIF); - urls->controlURL_CIF = 0; - free(urls->controlURL_6FC); - urls->controlURL_6FC = 0; - free(urls->rootdescURL); - urls->rootdescURL = 0; -} - -int -UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) -{ - char status[64]; - unsigned int uptime; - status[0] = '\0'; - UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, - status, &uptime, NULL); - if(0 == strcmp("Connected", status)) - return 1; - else if(0 == strcmp("Up", status)) /* Also accept "Up" */ - return 1; - else - return 0; -} - - -/* UPNP_GetValidIGD() : - * return values : - * -1 = Internal error - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as - * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD - * - * In any positive non zero return case, the urls and data structures - * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to - * free allocated memory. - */ -MINIUPNP_LIBSPEC int -UPNP_GetValidIGD(struct UPNPDev * devlist, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) -{ - struct xml_desc { - char * xml; - int size; - int is_igd; - } * desc = NULL; - struct UPNPDev * dev; - int ndev = 0; - int i; - int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ - int n_igd = 0; - char extIpAddr[16]; - char myLanAddr[40]; - int status_code = -1; - - if(!devlist) - { -#ifdef DEBUG - printf("Empty devlist\n"); -#endif - return 0; - } - /* counting total number of devices in the list */ - for(dev = devlist; dev; dev = dev->pNext) - ndev++; - if(ndev > 0) - { - desc = calloc(ndev, sizeof(struct xml_desc)); - if(!desc) - return -1; /* memory allocation error */ - } - /* Step 1 : downloading descriptions and testing type */ - for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) - { - /* we should choose an internet gateway device. - * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ - desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), - myLanAddr, sizeof(myLanAddr), - dev->scope_id, &status_code); -#ifdef DEBUG - if(!desc[i].xml) - { - printf("error getting XML description %s\n", dev->descURL); - } -#endif - if(desc[i].xml) - { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(desc[i].xml, desc[i].size, data); - if(COMPARE(data->CIF.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) - { - desc[i].is_igd = 1; - n_igd++; - if(lanaddr) - strncpy(lanaddr, myLanAddr, lanaddrlen); - } - } - } - /* iterate the list to find a device depending on state */ - for(state = 1; state <= 3; state++) - { - for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) - { - if(desc[i].xml) - { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(desc[i].xml, desc[i].size, data); - if(desc[i].is_igd || state >= 3 ) - { - int is_connected; - - GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - - /* in state 2 and 3 we don't test if device is connected ! */ - if(state >= 2) - goto free_and_return; - is_connected = UPNPIGD_IsConnected(urls, data); -#ifdef DEBUG - printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, is_connected); -#endif - /* checks that status is connected AND there is a external IP address assigned */ - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) - goto free_and_return; - } - FreeUPNPUrls(urls); - if(data->second.servicetype[0] != '\0') { -#ifdef DEBUG - printf("We tried %s, now we try %s !\n", - data->first.servicetype, data->second.servicetype); -#endif - /* swaping WANPPPConnection and WANIPConnection ! */ - memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); - memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); - memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); - GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - is_connected = UPNPIGD_IsConnected(urls, data); -#ifdef DEBUG - printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, is_connected); -#endif - if(is_connected && - (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) - goto free_and_return; - } - FreeUPNPUrls(urls); - } - } - memset(data, 0, sizeof(struct IGDdatas)); - } - } - } - state = 0; -free_and_return: - if(desc) { - for(i = 0; i < ndev; i++) { - if(desc[i].xml) { - free(desc[i].xml); - } - } - free(desc); - } - return state; -} - -/* UPNP_GetIGDFromUrl() - * Used when skipping the discovery process. - * return value : - * 0 - Not ok - * 1 - OK */ -int -UPNP_GetIGDFromUrl(const char * rootdescurl, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) -{ - char * descXML; - int descXMLsize = 0; - - descXML = miniwget_getaddr(rootdescurl, &descXMLsize, - lanaddr, lanaddrlen, 0, NULL); - if(descXML) { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(descXML, descXMLsize, data); - free(descXML); - descXML = NULL; - GetUPNPUrls(urls, data, rootdescurl, 0); - return 1; - } else { - return 0; - } -} - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpc.def b/src/contrib/miniupnp/miniupnpc/miniupnpc.def deleted file mode 100644 index 60e0bbe..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpc.def +++ /dev/null @@ -1,45 +0,0 @@ -LIBRARY -; miniupnpc library - miniupnpc - -EXPORTS -; miniupnpc - upnpDiscover - freeUPNPDevlist - parserootdesc - UPNP_GetValidIGD - UPNP_GetIGDFromUrl - GetUPNPUrls - FreeUPNPUrls -; miniwget - miniwget - miniwget_getaddr -; upnpcommands - UPNP_GetTotalBytesSent - UPNP_GetTotalBytesReceived - UPNP_GetTotalPacketsSent - UPNP_GetTotalPacketsReceived - UPNP_GetStatusInfo - UPNP_GetConnectionTypeInfo - UPNP_GetExternalIPAddress - UPNP_GetLinkLayerMaxBitRates - UPNP_AddPortMapping - UPNP_AddAnyPortMapping - UPNP_DeletePortMapping - UPNP_DeletePortMappingRange - UPNP_GetPortMappingNumberOfEntries - UPNP_GetSpecificPortMappingEntry - UPNP_GetGenericPortMappingEntry - UPNP_GetListOfPortMappings - UPNP_AddPinhole - UPNP_CheckPinholeWorking - UPNP_UpdatePinhole - UPNP_GetPinholePackets - UPNP_DeletePinhole - UPNP_GetFirewallStatus - UPNP_GetOutboundPinholeTimeout -; upnperrors - strupnperror -; portlistingparse - ParsePortListing - FreePortListing diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpc.h b/src/contrib/miniupnp/miniupnpc/miniupnpc.h deleted file mode 100644 index 8ddc282..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpc.h +++ /dev/null @@ -1,153 +0,0 @@ -/* $Id: miniupnpc.h,v 1.53 2018/05/07 11:05:16 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPC_H_INCLUDED -#define MINIUPNPC_H_INCLUDED - -#include "miniupnpc_declspec.h" -#include "igd_desc_parse.h" -#include "upnpdev.h" - -/* error codes : */ -#define UPNPDISCOVER_SUCCESS (0) -#define UPNPDISCOVER_UNKNOWN_ERROR (-1) -#define UPNPDISCOVER_SOCKET_ERROR (-101) -#define UPNPDISCOVER_MEMORY_ERROR (-102) - -/* versions : */ -#define MINIUPNPC_VERSION "2.1" -#define MINIUPNPC_API_VERSION 17 - -/* Source port: - Using "1" as an alias for 1900 for backwards compatibility - (presuming one would have used that for the "sameport" parameter) */ -#define UPNP_LOCAL_PORT_ANY 0 -#define UPNP_LOCAL_PORT_SAME 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structures definitions : */ -struct UPNParg { const char * elt; const char * val; }; - -char * -simpleUPnPcommand(int, const char *, const char *, - const char *, struct UPNParg *, - int *); - -/* upnpDiscover() - * discover UPnP devices on the network. - * The discovered devices are returned as a chained list. - * It is up to the caller to free the list with freeUPNPDevlist(). - * delay (in millisecond) is the maximum time for waiting any device - * response. - * If available, device list will be obtained from MiniSSDPd. - * Default path for minissdpd socket will be used if minissdpdsock argument - * is NULL. - * If multicastif is not NULL, it will be used instead of the default - * multicast interface for sending SSDP discover packets. - * If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent - * from the source port 1900 (same as destination port), if set to - * UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will - * be attempted as the source port. - * "searchalltypes" parameter is useful when searching several types, - * if 0, the discovery will stop with the first type returning results. - * TTL should default to 2. */ -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverAll(int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevice(const char * device, int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error); - -MINIUPNP_LIBSPEC struct UPNPDev * -upnpDiscoverDevices(const char * const deviceTypes[], - int delay, const char * multicastif, - const char * minissdpdsock, int localport, - int ipv6, unsigned char ttl, - int * error, - int searchalltypes); - -/* parserootdesc() : - * parse root XML description of a UPnP device and fill the IGDdatas - * structure. */ -MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); - -/* structure used to get fast access to urls - * controlURL: controlURL of the WANIPConnection - * ipcondescURL: url of the description of the WANIPConnection - * controlURL_CIF: controlURL of the WANCommonInterfaceConfig - * controlURL_6FC: controlURL of the WANIPv6FirewallControl - */ -struct UPNPUrls { - char * controlURL; - char * ipcondescURL; - char * controlURL_CIF; - char * controlURL_6FC; - char * rootdescURL; -}; - -/* UPNP_GetValidIGD() : - * return values : - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as - * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD - * - * In any non zero return case, the urls and data structures - * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to - * free allocated memory. - */ -MINIUPNP_LIBSPEC int -UPNP_GetValidIGD(struct UPNPDev * devlist, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -/* UPNP_GetIGDFromUrl() - * Used when skipping the discovery process. - * When succeding, urls, data, and lanaddr arguments are set. - * return value : - * 0 - Not ok - * 1 - OK */ -MINIUPNP_LIBSPEC int -UPNP_GetIGDFromUrl(const char * rootdescurl, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -MINIUPNP_LIBSPEC void -GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, - const char *, unsigned int); - -MINIUPNP_LIBSPEC void -FreeUPNPUrls(struct UPNPUrls *); - -/* return 0 or 1 */ -MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpc_declspec.h b/src/contrib/miniupnp/miniupnpc/miniupnpc_declspec.h deleted file mode 100644 index 40adb92..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpc_declspec.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED -#define MINIUPNPC_DECLSPEC_H_INCLUDED - -#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) - /* for windows dll */ - #ifdef MINIUPNP_EXPORTS - #define MINIUPNP_LIBSPEC __declspec(dllexport) - #else - #define MINIUPNP_LIBSPEC __declspec(dllimport) - #endif -#else - #if defined(__GNUC__) && __GNUC__ >= 4 - /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ - #define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default"))) - #else - #define MINIUPNP_LIBSPEC - #endif -#endif - -#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpc_socketdef.h b/src/contrib/miniupnp/miniupnpc/miniupnpc_socketdef.h deleted file mode 100644 index 965d915..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpc_socketdef.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: miniupnpc_socketdef.h,v 1.1 2018/03/13 23:44:10 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - * Copyright (c) 2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED -#define MINIUPNPC_SOCKETDEF_H_INCLUDED - -#ifdef _MSC_VER - -#define ISINVALID(s) (INVALID_SOCKET==(s)) - -#else - -#ifndef SOCKET -#define SOCKET int -#endif -#ifndef SSIZE_T -#define SSIZE_T ssize_t -#endif -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (-1) -#endif -#ifndef ISINVALID -#define ISINVALID(s) ((s)<0) -#endif - -#endif - -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) fprintf(stderr, "Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -#endif /* MINIUPNPC_SOCKETDEF_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpcmodule.c b/src/contrib/miniupnp/miniupnpc/miniupnpcmodule.c deleted file mode 100644 index 8657a0e..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpcmodule.c +++ /dev/null @@ -1,703 +0,0 @@ -/* $Id: miniupnpcmodule.c,v 1.24 2014/06/10 09:48:11 nanard Exp $*/ -/* Project : miniupnp - * Author : Thomas BERNARD - * website : https://miniupnp.tuxfamily.org/ - * copyright (c) 2007-2018 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include -#define MINIUPNP_STATICLIB -#include "structmember.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "upnperrors.h" - -#ifdef _WIN32 -#include -#endif - -/* for compatibility with Python < 2.4 */ -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None -#endif - -#ifndef Py_RETURN_TRUE -#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True -#endif - -#ifndef Py_RETURN_FALSE -#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False -#endif - -/* for compatibility with Python < 3.0 */ -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -#ifndef Py_TYPE -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif - -typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ - struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; - unsigned int discoverdelay; /* value passed to upnpDiscover() */ - unsigned int localport; /* value passed to upnpDiscover() */ - char lanaddr[40]; /* our ip address on the LAN */ - char * multicastif; - char * minissdpdsocket; -} UPnPObject; - -static PyMemberDef UPnP_members[] = { - {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr), - READONLY, "ip address on the LAN" - }, - {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay), - 0/*READWRITE*/, "value in ms used to wait for SSDP responses" - }, - {"localport", T_UINT, offsetof(UPnPObject, localport), - 0/*READWRITE*/, - "If localport is set to UPNP_LOCAL_PORT_SAME(1) " - "SSDP packets will be sent from the source port " - "1900 (same as destination port), if set to " - "UPNP_LOCAL_PORT_ANY(0) system assign a source " - "port, any other value will be attempted as the " - "source port" - }, - /* T_STRING is allways readonly :( */ - {"multicastif", T_STRING, offsetof(UPnPObject, multicastif), - 0, "IP of the network interface to be used for multicast operations" - }, - {"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket), - 0, "path of the MiniSSDPd unix socket" - }, - {NULL} -}; - - -static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds) -{ - char* multicastif = NULL; - char* minissdpdsocket = NULL; - static char *kwlist[] = { - "multicastif", "minissdpdsocket", "discoverdelay", - "localport", NULL - }; - - if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist, - &multicastif, - &minissdpdsocket, - &self->discoverdelay, - &self->localport)) - return -1; - - if(self->localport>1 && - (self->localport>65534||self->localport<1024)) { - PyErr_SetString(PyExc_Exception, "Invalid localport value"); - return -1; - } - if(multicastif) - self->multicastif = strdup(multicastif); - if(minissdpdsocket) - self->minissdpdsocket = strdup(minissdpdsocket); - - return 0; -} - -static void -UPnPObject_dealloc(UPnPObject *self) -{ - freeUPNPDevlist(self->devlist); - FreeUPNPUrls(&self->urls); - free(self->multicastif); - free(self->minissdpdsocket); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -UPnP_discover(UPnPObject *self) -{ - struct UPNPDev * dev; - int i; - PyObject *res = NULL; - if(self->devlist) - { - freeUPNPDevlist(self->devlist); - self->devlist = 0; - } - Py_BEGIN_ALLOW_THREADS - self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/, - self->multicastif, - self->minissdpdsocket, - (int)self->localport, - 0/*ip v6*/, - 2/* TTL */, - 0/*error */); - Py_END_ALLOW_THREADS - /* Py_RETURN_NONE ??? */ - for(dev = self->devlist, i = 0; dev; dev = dev->pNext) - i++; - res = Py_BuildValue("i", i); - return res; -} - -static PyObject * -UPnP_selectigd(UPnPObject *self) -{ - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data, - self->lanaddr, sizeof(self->lanaddr)); -Py_END_ALLOW_THREADS - if(r) - { - return Py_BuildValue("s", self->urls.controlURL); - } - else - { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, "No UPnP device discovered"); - return NULL; - } -} - -static PyObject * -UPnP_totalbytesent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalbytereceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalpacketsent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalpacketreceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_statusinfo(UPnPObject *self) -{ - char status[64]; - char lastconnerror[64]; - unsigned int uptime = 0; - int r; - status[0] = '\0'; - lastconnerror[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype, - status, &uptime, lastconnerror); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror); -#else - return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror); -#endif - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_connectiontype(UPnPObject *self) -{ - char connectionType[64]; - int r; - connectionType[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetConnectionTypeInfo(self->urls.controlURL, - self->data.first.servicetype, - connectionType); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", connectionType); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_externalipaddress(UPnPObject *self) -{ - char externalIPAddress[40]; - int r; - externalIPAddress[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetExternalIPAddress(self->urls.controlURL, - self->data.first.servicetype, - externalIPAddress); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", externalIPAddress); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc, - * remoteHost) - * protocol is 'UDP' or 'TCP' */ -static PyObject * -UPnP_addportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - char inPort[6]; - unsigned short iPort; - const char * proto; - const char * host; - const char * desc; - const char * remoteHost; - const char * leaseDuration = "0"; - int r; - if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, - &host, &iPort, &desc, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - sprintf(inPort, "%hu", iPort); - r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, inPort, host, desc, proto, - remoteHost, leaseDuration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - Py_RETURN_TRUE; - } - else - { - // TODO: RAISE an Exception. See upnpcommands.h for errors codes. - // upnperrors.c - //Py_RETURN_FALSE; - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc, - * remoteHost) - * protocol is 'UDP' or 'TCP' */ -static PyObject * -UPnP_addanyportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - char inPort[6]; - unsigned short iPort; - char reservedPort[6]; - const char * proto; - const char * host; - const char * desc; - const char * remoteHost; - const char * leaseDuration = "0"; - int r; - if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - sprintf(inPort, "%hu", iPort); - r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, inPort, host, desc, proto, - remoteHost, leaseDuration, reservedPort); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("i", atoi(reservedPort)); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - - -/* DeletePortMapping(extPort, proto, removeHost='') - * proto = 'UDP', 'TCP' */ -static PyObject * -UPnP_deleteportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - int r; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, proto, remoteHost); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - Py_RETURN_TRUE; - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* DeletePortMappingRange(extPort, proto, removeHost='') - * proto = 'UDP', 'TCP' */ -static PyObject * -UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args) -{ - char extPortStart[6]; - unsigned short ePortStart; - char extPortEnd[6]; - unsigned short ePortEnd; - const char * proto; - unsigned char manage; - char manageStr[6]; - int r; - if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPortStart, "%hu", ePortStart); - sprintf(extPortEnd, "%hu", ePortEnd); - sprintf(manageStr, "%hu", (unsigned short)manage); - r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype, - extPortStart, extPortEnd, proto, manageStr); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - Py_RETURN_TRUE; - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_getportmappingnumberofentries(UPnPObject *self) -{ - unsigned int n = 0; - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL, - self->data.first.servicetype, - &n); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", n); -#else - return Py_BuildValue("i", (int)n); -#endif - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* GetSpecificPortMapping(ePort, proto, remoteHost='') - * proto = 'UDP' or 'TCP' */ -static PyObject * -UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char desc[80]; - char enabled[4]; - char leaseDuration[16]; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; - extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0'; - desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - UPNP_GetSpecificPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - extPort, proto, remoteHost, - intClient, intPort, - desc, enabled, leaseDuration); -Py_END_ALLOW_THREADS - if(intClient[0]) - { - iPort = (unsigned short)atoi(intPort); - return Py_BuildValue("(s,H,s,O,i)", - intClient, iPort, desc, - PyBool_FromLong(atoi(enabled)), - atoi(leaseDuration)); - } - else - { - Py_RETURN_NONE; - } -} - -/* GetGenericPortMapping(index) */ -static PyObject * -UPnP_getgenericportmapping(UPnPObject *self, PyObject *args) -{ - int i, r; - char index[8]; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char extPort[6]; - unsigned short ePort; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; /* lease duration */ - unsigned int dur; - if(!PyArg_ParseTuple(args, "i", &i)) - return NULL; -Py_BEGIN_ALLOW_THREADS - snprintf(index, sizeof(index), "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, rHost, - duration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - ePort = (unsigned short)atoi(extPort); - iPort = (unsigned short)atoi(intPort); - dur = (unsigned int)strtoul(duration, 0, 0); -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("(H,s,(s,H),s,s,s,I)", - ePort, protocol, intClient, iPort, - desc, enabled, rHost, dur); -#else - return Py_BuildValue("(i,s,(s,i),s,s,s,i)", - (int)ePort, protocol, intClient, (int)iPort, - desc, enabled, rHost, (int)dur); -#endif - } - else - { - Py_RETURN_NONE; - } -} - -/* miniupnpc.UPnP object Method Table */ -static PyMethodDef UPnP_methods[] = { - {"discover", (PyCFunction)UPnP_discover, METH_NOARGS, - "discover UPnP IGD devices on the network" - }, - {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS, - "select a valid UPnP IGD among discovered devices" - }, - {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS, - "return the total number of bytes sent by UPnP IGD" - }, - {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS, - "return the total number of bytes received by UPnP IGD" - }, - {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS, - "return the total number of packets sent by UPnP IGD" - }, - {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS, - "return the total number of packets received by UPnP IGD" - }, - {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS, - "return status and uptime" - }, - {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS, - "return IGD WAN connection type" - }, - {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS, - "return external IP address" - }, - {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS, - "add a port mapping" - }, - {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS, - "add a port mapping, IGD to select alternative if necessary" - }, - {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS, - "delete a port mapping" - }, - {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS, - "delete a range of port mappings" - }, - {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS, - "-- non standard --" - }, - {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS, - "get details about a specific port mapping entry" - }, - {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS, - "get all details about the port mapping at index" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject UPnPType = { - PyVarObject_HEAD_INIT(NULL, - 0) /*ob_size*/ - "miniupnpc.UPnP", /*tp_name*/ - sizeof(UPnPObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)UPnPObject_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "UPnP objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - UPnP_methods, /* tp_methods */ - UPnP_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)UPnP_init, /* tp_init */ - 0, /* tp_alloc */ -#ifndef _WIN32 - PyType_GenericNew,/*UPnP_new,*/ /* tp_new */ -#else - 0, -#endif -}; - -/* module methods */ -static PyMethodDef miniupnpc_methods[] = { - {NULL} /* Sentinel */ -}; - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "miniupnpc", /* m_name */ - "miniupnpc module.", /* m_doc */ - -1, /* m_size */ - miniupnpc_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; -#endif - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif - -PyMODINIT_FUNC -#if PY_MAJOR_VERSION >= 3 -PyInit_miniupnpc(void) -#else -initminiupnpc(void) -#endif -{ - PyObject* m; - -#ifdef _WIN32 - /* initialize Winsock. */ - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - - UPnPType.tp_new = PyType_GenericNew; -#endif - if (PyType_Ready(&UPnPType) < 0) -#if PY_MAJOR_VERSION >= 3 - return 0; -#else - return; -#endif - -#if PY_MAJOR_VERSION >= 3 - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("miniupnpc", miniupnpc_methods, - "miniupnpc module."); -#endif - - Py_INCREF(&UPnPType); - PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType); - -#if PY_MAJOR_VERSION >= 3 - return m; -#endif -} - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.cmake b/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.cmake deleted file mode 100644 index 78c8fe9..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.cmake +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "${CMAKE_SYSTEM_NAME}" -#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}" - -#if 0 -/* according to "UPnP Device Architecture 1.0" */ -#define UPNP_VERSION_STRING "UPnP/1.0" -#else -/* according to "UPnP Device Architecture 1.1" */ -#define UPNP_VERSION_STRING "UPnP/1.1" -#endif - -#endif diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.in b/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.in deleted file mode 100644 index 68bf429..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpcstrings.h.in +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "OS/version" -#define MINIUPNPC_VERSION_STRING "version" - -#if 0 -/* according to "UPnP Device Architecture 1.0" */ -#define UPNP_VERSION_STRING "UPnP/1.0" -#else -/* according to "UPnP Device Architecture 1.1" */ -#define UPNP_VERSION_STRING "UPnP/1.1" -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/miniupnpctypes.h b/src/contrib/miniupnp/miniupnpc/miniupnpctypes.h deleted file mode 100644 index 307ce39..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniupnpctypes.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org - * Author : Thomas Bernard - * Copyright (c) 2011 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef MINIUPNPCTYPES_H_INCLUDED -#define MINIUPNPCTYPES_H_INCLUDED - -#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) -#define UNSIGNED_INTEGER unsigned long long -#define STRTOUI strtoull -#else -#define UNSIGNED_INTEGER unsigned int -#define STRTOUI strtoul -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/miniwget.c b/src/contrib/miniupnp/miniupnpc/miniwget.c deleted file mode 100644 index a46ba76..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniwget.c +++ /dev/null @@ -1,662 +0,0 @@ -/* $Id: miniwget.c,v 1.78 2018/03/13 23:22:18 nanard Exp $ */ -/* Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#include -#include -#ifdef _WIN32 -#include -#include -#include -#define MAXHOSTNAMELEN 64 -#define snprintf _snprintf -#define socklen_t int -#ifndef strncasecmp -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define strncasecmp _memicmp -#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#define strncasecmp memicmp -#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#endif /* #ifndef strncasecmp */ -#else /* #ifdef _WIN32 */ -#include -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -#define socklen_t int -#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#include -#include -#include -#include -#define closesocket close -#include -#endif /* #else _WIN32 */ -#ifdef __GNU__ -#define MAXHOSTNAMELEN 64 -#endif /* __GNU__ */ - -#ifndef MIN -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif /* MIN */ - - -#include "miniupnpcstrings.h" -#include "miniwget.h" -#include "connecthostport.h" -#include "receivedata.h" - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* - * Read a HTTP response from a socket. - * Process Content-Length and Transfer-encoding headers. - * return a pointer to the content buffer, which length is saved - * to the length parameter. - */ -void * -getHTTPResponse(SOCKET s, int * size, int * status_code) -{ - char buf[2048]; - int n; - int endofheaders = 0; - int chunked = 0; - int content_length = -1; - unsigned int chunksize = 0; - unsigned int bytestocopy = 0; - /* buffers : */ - char * header_buf; - unsigned int header_buf_len = 2048; - unsigned int header_buf_used = 0; - char * content_buf; - unsigned int content_buf_len = 2048; - unsigned int content_buf_used = 0; - char chunksize_buf[32]; - unsigned int chunksize_buf_index; -#ifdef DEBUG - char * reason_phrase = NULL; - int reason_phrase_len = 0; -#endif - - if(status_code) *status_code = -1; - header_buf = malloc(header_buf_len); - if(header_buf == NULL) - { -#ifdef DEBUG - fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); -#endif /* DEBUG */ - *size = -1; - return NULL; - } - content_buf = malloc(content_buf_len); - if(content_buf == NULL) - { - free(header_buf); -#ifdef DEBUG - fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse"); -#endif /* DEBUG */ - *size = -1; - return NULL; - } - chunksize_buf[0] = '\0'; - chunksize_buf_index = 0; - - while((n = receivedata(s, buf, sizeof(buf), 5000, NULL)) > 0) - { - if(endofheaders == 0) - { - int i; - int linestart=0; - int colon=0; - int valuestart=0; - if(header_buf_used + n > header_buf_len) { - char * tmp = realloc(header_buf, header_buf_used + n); - if(tmp == NULL) { - /* memory allocation error */ - free(header_buf); - free(content_buf); - *size = -1; - return NULL; - } - header_buf = tmp; - header_buf_len = header_buf_used + n; - } - memcpy(header_buf + header_buf_used, buf, n); - header_buf_used += n; - /* search for CR LF CR LF (end of headers) - * recognize also LF LF */ - i = 0; - while(i < ((int)header_buf_used-1) && (endofheaders == 0)) { - if(header_buf[i] == '\r') { - i++; - if(header_buf[i] == '\n') { - i++; - if(i < (int)header_buf_used && header_buf[i] == '\r') { - i++; - if(i < (int)header_buf_used && header_buf[i] == '\n') { - endofheaders = i+1; - } - } - } - } else if(header_buf[i] == '\n') { - i++; - if(header_buf[i] == '\n') { - endofheaders = i+1; - } - } - i++; - } - if(endofheaders == 0) - continue; - /* parse header lines */ - for(i = 0; i < endofheaders - 1; i++) { - if(linestart > 0 && colon <= linestart && header_buf[i]==':') - { - colon = i; - while(i < (endofheaders-1) - && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t')) - i++; - valuestart = i + 1; - } - /* detecting end of line */ - else if(header_buf[i]=='\r' || header_buf[i]=='\n') - { - if(linestart == 0 && status_code) - { - /* Status line - * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ - int sp; - for(sp = 0; sp < i; sp++) - if(header_buf[sp] == ' ') - { - if(*status_code < 0) - *status_code = atoi(header_buf + sp + 1); - else - { -#ifdef DEBUG - reason_phrase = header_buf + sp + 1; - reason_phrase_len = i - sp - 1; -#endif - break; - } - } -#ifdef DEBUG - printf("HTTP status code = %d, Reason phrase = %.*s\n", - *status_code, reason_phrase_len, reason_phrase); -#endif - } - else if(colon > linestart && valuestart > colon) - { -#ifdef DEBUG - printf("header='%.*s', value='%.*s'\n", - colon-linestart, header_buf+linestart, - i-valuestart, header_buf+valuestart); -#endif - if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart)) - { - content_length = atoi(header_buf+valuestart); -#ifdef DEBUG - printf("Content-Length: %d\n", content_length); -#endif - } - else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) - && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) - { -#ifdef DEBUG - printf("chunked transfer-encoding!\n"); -#endif - chunked = 1; - } - } - while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) - i++; - linestart = i; - colon = linestart; - valuestart = 0; - } - } - /* copy the remaining of the received data back to buf */ - n = header_buf_used - endofheaders; - memcpy(buf, header_buf + endofheaders, n); - /* if(headers) */ - } - /* if we get there, endofheaders != 0. - * In the other case, there was a continue above */ - /* content */ - if(chunked) - { - int i = 0; - while(i < n) - { - if(chunksize == 0) - { - /* reading chunk size */ - if(chunksize_buf_index == 0) { - /* skipping any leading CR LF */ - if(i= '0' - && chunksize_buf[j] <= '9') - chunksize = (chunksize << 4) + (chunksize_buf[j] - '0'); - else - chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10); - } - chunksize_buf[0] = '\0'; - chunksize_buf_index = 0; - i++; - } else { - /* not finished to get chunksize */ - continue; - } -#ifdef DEBUG - printf("chunksize = %u (%x)\n", chunksize, chunksize); -#endif - if(chunksize == 0) - { -#ifdef DEBUG - printf("end of HTTP content - %d %d\n", i, n); - /*printf("'%.*s'\n", n-i, buf+i);*/ -#endif - goto end_of_stream; - } - } - /* it is guaranteed that (n >= i) */ - bytestocopy = (chunksize < (unsigned int)(n - i))?chunksize:(unsigned int)(n - i); - if((content_buf_used + bytestocopy) > content_buf_len) - { - char * tmp; - if((content_length >= 0) && ((unsigned int)content_length >= (content_buf_used + bytestocopy))) { - content_buf_len = content_length; - } else { - content_buf_len = content_buf_used + bytestocopy; - } - tmp = realloc(content_buf, content_buf_len); - if(tmp == NULL) { - /* memory allocation error */ - free(content_buf); - free(header_buf); - *size = -1; - return NULL; - } - content_buf = tmp; - } - memcpy(content_buf + content_buf_used, buf + i, bytestocopy); - content_buf_used += bytestocopy; - i += bytestocopy; - chunksize -= bytestocopy; - } - } - else - { - /* not chunked */ - if(content_length > 0 - && (content_buf_used + n) > (unsigned int)content_length) { - /* skipping additional bytes */ - n = content_length - content_buf_used; - } - if(content_buf_used + n > content_buf_len) - { - char * tmp; - if(content_length >= 0 - && (unsigned int)content_length >= (content_buf_used + n)) { - content_buf_len = content_length; - } else { - content_buf_len = content_buf_used + n; - } - tmp = realloc(content_buf, content_buf_len); - if(tmp == NULL) { - /* memory allocation error */ - free(content_buf); - free(header_buf); - *size = -1; - return NULL; - } - content_buf = tmp; - } - memcpy(content_buf + content_buf_used, buf, n); - content_buf_used += n; - } - /* use the Content-Length header value if available */ - if(content_length > 0 && content_buf_used >= (unsigned int)content_length) - { -#ifdef DEBUG - printf("End of HTTP content\n"); -#endif - break; - } - } -end_of_stream: - free(header_buf); header_buf = NULL; - *size = content_buf_used; - if(content_buf_used == 0) - { - free(content_buf); - content_buf = NULL; - } - return content_buf; -} - -/* miniwget3() : - * do all the work. - * Return NULL if something failed. */ -static void * -miniwget3(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - const char * httpversion, unsigned int scope_id, - int * status_code) -{ - char buf[2048]; - SOCKET s; - int n; - int len; - int sent; - void * content; - - *size = 0; - s = connecthostport(host, port, scope_id); - if(ISINVALID(s)) - return NULL; - - /* get address for caller ! */ - if(addr_str) - { - struct sockaddr_storage saddr; - socklen_t saddrlen; - - saddrlen = sizeof(saddr); - if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) - { - perror("getsockname"); - } - else - { -#if defined(__amigaos__) && !defined(__amigaos4__) - /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); - * But his function make a string with the port : nn.nn.nn.nn:port */ -/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), - NULL, addr_str, (DWORD *)&addr_str_len)) - { - printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); - }*/ - /* the following code is only compatible with ip v4 addresses */ - strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); -#else -#if 0 - if(saddr.sa_family == AF_INET6) { - inet_ntop(AF_INET6, - &(((struct sockaddr_in6 *)&saddr)->sin6_addr), - addr_str, addr_str_len); - } else { - inet_ntop(AF_INET, - &(((struct sockaddr_in *)&saddr)->sin_addr), - addr_str, addr_str_len); - } -#endif - /* getnameinfo return ip v6 address with the scope identifier - * such as : 2a01:e35:8b2b:7330::%4281128194 */ - n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, - addr_str, addr_str_len, - NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV); - if(n != 0) { -#ifdef _WIN32 - fprintf(stderr, "getnameinfo() failed : %d\n", n); -#else - fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); -#endif - } -#endif - } -#ifdef DEBUG - printf("address miniwget : %s\n", addr_str); -#endif - } - - len = snprintf(buf, sizeof(buf), - "GET %s HTTP/%s\r\n" - "Host: %s:%d\r\n" - "Connection: Close\r\n" - "User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" - - "\r\n", - path, httpversion, host, port); - if ((unsigned int)len >= sizeof(buf)) - { - closesocket(s); - return NULL; - } - sent = 0; - /* sending the HTTP request */ - while(sent < len) - { - n = send(s, buf+sent, len-sent, 0); - if(n < 0) - { - perror("send"); - closesocket(s); - return NULL; - } - else - { - sent += n; - } - } - content = getHTTPResponse(s, size, status_code); - closesocket(s); - return content; -} - -/* miniwget2() : - * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ -static void * -miniwget2(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - unsigned int scope_id, int * status_code) -{ - char * respbuffer; - -#if 1 - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); -#else - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.0", - scope_id, status_code); - if (*size == 0) - { -#ifdef DEBUG - printf("Retrying with HTTP/1.1\n"); -#endif - free(respbuffer); - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", - scope_id, status_code); - } -#endif - return respbuffer; -} - - - - -/* parseURL() - * arguments : - * url : source string not modified - * hostname : hostname destination string (size of MAXHOSTNAMELEN+1) - * port : port (destination) - * path : pointer to the path part of the URL - * - * Return values : - * 0 - Failure - * 1 - Success */ -int -parseURL(const char * url, - char * hostname, unsigned short * port, - char * * path, unsigned int * scope_id) -{ - char * p1, *p2, *p3; - if(!url) - return 0; - p1 = strstr(url, "://"); - if(!p1) - return 0; - p1 += 3; - if( (url[0]!='h') || (url[1]!='t') - ||(url[2]!='t') || (url[3]!='p')) - return 0; - memset(hostname, 0, MAXHOSTNAMELEN + 1); - if(*p1 == '[') - { - /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ - char * scope; - scope = strchr(p1, '%'); - p2 = strchr(p1, ']'); - if(p2 && scope && scope < p2 && scope_id) { - /* parse scope */ -#ifdef IF_NAMESIZE - char tmp[IF_NAMESIZE]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= IF_NAMESIZE) - l = IF_NAMESIZE - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = if_nametoindex(tmp); - if(*scope_id == 0) { - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); - } -#else - /* under windows, scope is numerical */ - char tmp[8]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= sizeof(tmp)) - l = sizeof(tmp) - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); -#endif - } - p3 = strchr(p1, '/'); - if(p2 && p3) - { - p2++; - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - if(*p2 == ':') - { - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) - { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - else - { - *port = 80; - } - *path = p3; - return 1; - } - } - p2 = strchr(p1, ':'); - p3 = strchr(p1, '/'); - if(!p3) - return 0; - if(!p2 || (p2>p3)) - { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); - *port = 80; - } - else - { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) - { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - *path = p3; - return 1; -} - -void * -miniwget(const char * url, int * size, - unsigned int scope_id, int * status_code) -{ - unsigned short port; - char * path; - /* protocol://host:port/chemin */ - char hostname[MAXHOSTNAMELEN+1]; - *size = 0; - if(!parseURL(url, hostname, &port, &path, &scope_id)) - return NULL; -#ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", - hostname, port, path, scope_id); -#endif - return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code); -} - -void * -miniwget_getaddr(const char * url, int * size, - char * addr, int addrlen, unsigned int scope_id, - int * status_code) -{ - unsigned short port; - char * path; - /* protocol://host:port/path */ - char hostname[MAXHOSTNAMELEN+1]; - *size = 0; - if(addr) - addr[0] = '\0'; - if(!parseURL(url, hostname, &port, &path, &scope_id)) - return NULL; -#ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", - hostname, port, path, scope_id); -#endif - return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code); -} - diff --git a/src/contrib/miniupnp/miniupnpc/miniwget.h b/src/contrib/miniupnp/miniupnpc/miniwget.h deleted file mode 100644 index f5572c2..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniwget.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: miniwget.h,v 1.12 2016/01/24 17:24:36 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2016 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIWGET_H_INCLUDED -#define MINIWGET_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *); - -MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *); - -int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/miniupnp/miniupnpc/miniwget_private.h b/src/contrib/miniupnp/miniupnpc/miniwget_private.h deleted file mode 100644 index e4eaac8..0000000 --- a/src/contrib/miniupnp/miniupnpc/miniwget_private.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: miniwget_private.h,v 1.1 2018/04/06 10:17:58 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIWGET_INTERNAL_H_INCLUDED -#define MINIWGET_INTERNAL_H_INCLUDED - -#include "miniupnpc_socketdef.h" - -void * getHTTPResponse(SOCKET s, int * size, int * status_code); - -#endif diff --git a/src/contrib/miniupnp/miniupnpc/minixml.c b/src/contrib/miniupnp/miniupnpc/minixml.c deleted file mode 100644 index ed2d3c7..0000000 --- a/src/contrib/miniupnp/miniupnpc/minixml.c +++ /dev/null @@ -1,231 +0,0 @@ -/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * minixml.c : the minimum size a xml parser can be ! */ -/* Project : miniupnp - * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - -Copyright (c) 2005-2017, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -#include -#include "minixml.h" - -/* parseatt : used to parse the argument list - * return 0 (false) in case of success and -1 (true) if the end - * of the xmlbuffer is reached. */ -static int parseatt(struct xmlparser * p) -{ - const char * attname; - int attnamelen; - const char * attvalue; - int attvaluelen; - while(p->xml < p->xmlend) - { - if(*p->xml=='/' || *p->xml=='>') - return 0; - if( !IS_WHITE_SPACE(*p->xml) ) - { - char sep; - attname = p->xml; - attnamelen = 0; - while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) - { - attnamelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - while(*(p->xml++) != '=') - { - if(p->xml >= p->xmlend) - return -1; - } - while(IS_WHITE_SPACE(*p->xml)) - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - sep = *p->xml; - if(sep=='\'' || sep=='\"') - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - attvalue = p->xml; - attvaluelen = 0; - while(*p->xml != sep) - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - else - { - attvalue = p->xml; - attvaluelen = 0; - while( !IS_WHITE_SPACE(*p->xml) - && *p->xml != '>' && *p->xml != '/') - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - /*printf("%.*s='%.*s'\n", - attnamelen, attname, attvaluelen, attvalue);*/ - if(p->attfunc) - p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); - } - p->xml++; - } - return -1; -} - -/* parseelt parse the xml stream and - * call the callback functions when needed... */ -static void parseelt(struct xmlparser * p) -{ - int i; - const char * elementname; - while(p->xml < (p->xmlend - 1)) - { - if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); - p->xml += 3; - } - else if((p->xml)[0]=='<' && (p->xml)[1]!='?') - { - i = 0; elementname = ++p->xml; - while( !IS_WHITE_SPACE(*p->xml) - && (*p->xml!='>') && (*p->xml!='/') - ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - /* to ignore namespace : */ - if(*p->xml==':') - { - i = 0; - elementname = ++p->xml; - } - } - if(i>0) - { - if(p->starteltfunc) - p->starteltfunc(p->data, elementname, i); - if(parseatt(p)) - return; - if(*p->xml!='/') - { - const char * data; - i = 0; data = ++p->xml; - if (p->xml >= p->xmlend) - return; - while( IS_WHITE_SPACE(*p->xml) ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - /* CDATA are at least 9 + 3 characters long : */ - if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "xml += 9; - data = p->xml; - i = 0; - while(memcmp(p->xml, "]]>", 3) != 0) - { - i++; p->xml++; - if ((p->xml + 3) >= p->xmlend) - return; - } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); - while(*p->xml!='<') - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - } - else - { - while(*p->xml!='<') - { - i++; p->xml++; - if ((p->xml + 1) >= p->xmlend) - return; - } - if(i>0 && p->datafunc && *(p->xml + 1) == '/') - p->datafunc(p->data, data, i); - } - } - } - else if(*p->xml == '/') - { - i = 0; elementname = ++p->xml; - if (p->xml >= p->xmlend) - return; - while((*p->xml != '>')) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(p->endeltfunc) - p->endeltfunc(p->data, elementname, i); - p->xml++; - } - } - else - { - p->xml++; - } - } -} - -/* the parser must be initialized before calling this function */ -void parsexml(struct xmlparser * parser) -{ - parser->xml = parser->xmlstart; - parser->xmlend = parser->xmlstart + parser->xmlsize; - parseelt(parser); -} - - diff --git a/src/contrib/miniupnp/miniupnpc/minixml.h b/src/contrib/miniupnp/miniupnpc/minixml.h deleted file mode 100644 index 19e6f51..0000000 --- a/src/contrib/miniupnp/miniupnpc/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/minixmlvalid.c b/src/contrib/miniupnp/miniupnpc/minixmlvalid.c deleted file mode 100644 index dad1488..0000000 --- a/src/contrib/miniupnp/miniupnpc/minixmlvalid.c +++ /dev/null @@ -1,163 +0,0 @@ -/* $Id: minixmlvalid.c,v 1.7 2015/07/15 12:41:15 nanard Exp $ */ -/* MiniUPnP Project - * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ - * minixmlvalid.c : - * validation program for the minixml parser - * - * (c) 2006-2011 Thomas Bernard */ - -#include -#include -#include -#include "minixml.h" - -/* xml event structure */ -struct event { - enum { ELTSTART, ELTEND, ATT, CHARDATA } type; - const char * data; - int len; -}; - -struct eventlist { - int n; - struct event * events; -}; - -/* compare 2 xml event lists - * return 0 if the two lists are equals */ -int evtlistcmp(struct eventlist * a, struct eventlist * b) -{ - int i; - struct event * ae, * be; - if(a->n != b->n) - { - printf("event number not matching : %d != %d\n", a->n, b->n); - /*return 1;*/ - } - for(i=0; in; i++) - { - ae = a->events + i; - be = b->events + i; - if( (ae->type != be->type) - ||(ae->len != be->len) - ||memcmp(ae->data, be->data, ae->len)) - { - printf("Found a difference : %d '%.*s' != %d '%.*s'\n", - ae->type, ae->len, ae->data, - be->type, be->len, be->data); - return 1; - } - } - return 0; -} - -/* Test data */ -static const char xmldata[] = -"\n" -" " -"character data" -" \n \t" -"" -"\nstuff !\n ]]> \n\n" -" \tchardata1 chardata2 " -""; - -static const struct event evtref[] = -{ - {ELTSTART, "xmlroot", 7}, - {ELTSTART, "elt1", 4}, - /* attributes */ - {CHARDATA, "character data", 14}, - {ELTEND, "elt1", 4}, - {ELTSTART, "elt1b", 5}, - {ELTSTART, "elt1", 4}, - {CHARDATA, " stuff !\n ", 16}, - {ELTEND, "elt1", 4}, - {ELTSTART, "elt2a", 5}, - {ELTSTART, "elt2b", 5}, - {CHARDATA, "chardata1", 9}, - {ELTEND, "elt2b", 5}, - {ELTSTART, "elt2b", 5}, - {CHARDATA, " chardata2 ", 11}, - {ELTEND, "elt2b", 5}, - {ELTEND, "elt2a", 5}, - {ELTEND, "xmlroot", 7} -}; - -void startelt(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("startelt : %.*s\n", l, p);*/ - evt->type = ELTSTART; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -void endelt(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("endelt : %.*s\n", l, p);*/ - evt->type = ELTEND; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -void chardata(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("chardata : '%.*s'\n", l, p);*/ - evt->type = CHARDATA; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -int testxmlparser(const char * xml, int size) -{ - int r; - struct eventlist evtlist; - struct eventlist evtlistref; - struct xmlparser parser; - evtlist.n = 0; - evtlist.events = malloc(sizeof(struct event)*100); - if(evtlist.events == NULL) - { - fprintf(stderr, "Memory allocation error.\n"); - return -1; - } - memset(&parser, 0, sizeof(parser)); - parser.xmlstart = xml; - parser.xmlsize = size; - parser.data = &evtlist; - parser.starteltfunc = startelt; - parser.endeltfunc = endelt; - parser.datafunc = chardata; - parsexml(&parser); - printf("%d events\n", evtlist.n); - /* compare */ - evtlistref.n = sizeof(evtref)/sizeof(struct event); - evtlistref.events = (struct event *)evtref; - r = evtlistcmp(&evtlistref, &evtlist); - free(evtlist.events); - return r; -} - -int main(int argc, char * * argv) -{ - int r; - (void)argc; (void)argv; - - r = testxmlparser(xmldata, sizeof(xmldata)-1); - if(r) - printf("minixml validation test failed\n"); - return r; -} - diff --git a/src/contrib/miniupnp/miniupnpc/msvc/.gitignore b/src/contrib/miniupnp/miniupnpc/msvc/.gitignore deleted file mode 100644 index ec67f23..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.db -.vs -Debug/ -Release/ -*.user -*.suo -*.sdf -ipch/ diff --git a/src/contrib/miniupnp/miniupnpc/msvc/genminiupnpcstrings.vbs b/src/contrib/miniupnp/miniupnpc/msvc/genminiupnpcstrings.vbs deleted file mode 100644 index c1f4a58..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/genminiupnpcstrings.vbs +++ /dev/null @@ -1,53 +0,0 @@ -' VBScript to generate miniupnpcstrings.h -' Copyright 2018 Thomas Bernard -'Set WshShell = CreateObject("WScript.Shell") -Set FSO = CreateObject("Scripting.FileSystemObject") -versionfile = "..\version" -infile = "..\miniupnpcstrings.h.in" -outfile = "..\miniupnpcstrings.h" - -On Error Resume Next - -'Wscript.Echo revision - -Err.Clear -Set f = FSO.OpenTextFile(versionfile, 1, False) ' 1 = Read -If Err.Number = 0 Then - version = f.ReadLine - f.Close -Else - ' Exit error - WScript.Quit 1 -End If - -os_version = "0.0.0" -strComputer = "." -Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") -Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem") -For Each objOperatingSystem in colOperatingSystems - 'Wscript.Echo objOperatingSystem.Caption & " -- " - os_version = objOperatingSystem.Version -Next - -Dim array - -Set f_in = FSO.OpenTextFile(infile, 1, False) -If Err.Number = 0 Then - Set f_out = FSO.OpenTextFile(outfile, 2, True) ' 2 = Write - Do Until f_in.AtEndOfStream - line = f_in.ReadLine - If Len(line) > 0 Then - array = Split(line, " ") - If UBound(array) >= 2 And array(0) = "#define" Then - If array(1) = "OS_STRING" Then - line = "#define OS_STRING " & Chr(34) & "MSWindows/" & os_version & Chr(34) - ElseIf array(1) = "MINIUPNPC_VERSION_STRING" Then - line = "#define MINIUPNPC_VERSION_STRING " & Chr(34) & version & Chr(34) - End if - End if - End If - f_out.WriteLine line - Loop - f_in.Close - f_out.Close -End If diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.sln b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.sln deleted file mode 100644 index b3da191..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" - ProjectSection(ProjectDependencies) = postProject - {D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcproj b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcproj deleted file mode 100644 index fb301e3..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcproj +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj deleted file mode 100644 index a1569bf..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {D28CE435-CB33-4BAE-8A52-C6EF915956F5} - miniupnpc - Win32Proj - - - - StaticLibrary - v140 - Unicode - true - - - StaticLibrary - v140 - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>14.0.25123.0 - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - - - - Disabled - _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - Level3 - EditAndContinue - - - genminiupnpcstrings.vbs - - - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - Level3 - ProgramDatabase - - - genminiupnpcstrings.vbs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj.filters b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj.filters deleted file mode 100644 index 01a4dbe..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc.vcxproj.filters +++ /dev/null @@ -1,108 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - Fichiers sources - - - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.sln b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.sln deleted file mode 100644 index 65a8734..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc_vs2010.vcxproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static_vs2010.vcxproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj deleted file mode 100644 index 7f83cab..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {D28CE435-CB33-4BAE-8A52-C6EF915956F5} - miniupnpc - Win32Proj - - - - StaticLibrary - Unicode - true - - - StaticLibrary - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - miniupnpc - miniupnpc - - - - Disabled - _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - - - genminiupnpcstrings.vbs - - - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level3 - ProgramDatabase - - - genminiupnpcstrings.vbs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj.filters b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj.filters deleted file mode 100644 index 9a75e57..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2010.vcxproj.filters +++ /dev/null @@ -1,111 +0,0 @@ - - - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - sources - - - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - headers - - - - - {f2cbd46b-f63f-412e-80e5-b7c9048a1add} - - - {2b3996de-1bc4-418b-8a83-a5f34fdf0df5} - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2015.sln b/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2015.sln deleted file mode 100644 index 27a43f6..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/miniupnpc_vs2015.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcxproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcxproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcproj b/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcproj deleted file mode 100644 index c88c9a6..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj b/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj deleted file mode 100644 index 44dea81..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj +++ /dev/null @@ -1,103 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1} - upnpcstatic - Win32Proj - - - - Application - v140 - Unicode - true - - - Application - v140 - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>14.0.25123.0 - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - - - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - - - - Disabled - _DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - Level3 - EditAndContinue - - - ws2_32.lib;IPHlpApi.Lib;Debug\miniupnpc.lib;%(AdditionalDependencies) - true - Console - MachineX86 - - - - - MaxSpeed - true - NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - Level3 - ProgramDatabase - - - ws2_32.lib;IPHlpApi.Lib;Release\miniupnpc.lib;%(AdditionalDependencies) - true - Console - true - true - MachineX86 - - - - - - - - {d28ce435-cb33-4bae-8a52-c6ef915956f5} - false - - - - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj.filters b/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj.filters deleted file mode 100644 index 2e75de0..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Fichiers sources - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static_vs2010.vcxproj b/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static_vs2010.vcxproj deleted file mode 100644 index e815024..0000000 --- a/src/contrib/miniupnp/miniupnpc/msvc/upnpc-static_vs2010.vcxproj +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1} - upnpcstatic - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - upnpc-static - upnpc-static - - - - Disabled - _DEBUG;_CONSOLE;MINIUPNP_STATICLIB;DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - - - ws2_32.lib;IPHlpApi.Lib;Debug\miniupnpc.lib;%(AdditionalDependencies) - true - Console - MachineX86 - - - - - MaxSpeed - true - NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level3 - ProgramDatabase - - - ws2_32.lib;IPHlpApi.Lib;Release\miniupnpc.lib;%(AdditionalDependencies) - true - Console - true - true - MachineX86 - - - - - - - - {d28ce435-cb33-4bae-8a52-c6ef915956f5} - false - - - - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/portlistingparse.c b/src/contrib/miniupnp/miniupnpc/portlistingparse.c deleted file mode 100644 index 55859f2..0000000 --- a/src/contrib/miniupnp/miniupnpc/portlistingparse.c +++ /dev/null @@ -1,172 +0,0 @@ -/* $Id: portlistingparse.c,v 1.9 2015/07/15 12:41:13 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#ifdef DEBUG -#include -#endif /* DEBUG */ -#include "portlistingparse.h" -#include "minixml.h" - -/* list of the elements */ -static const struct { - const portMappingElt code; - const char * const str; -} elements[] = { - { PortMappingEntry, "PortMappingEntry"}, - { NewRemoteHost, "NewRemoteHost"}, - { NewExternalPort, "NewExternalPort"}, - { NewProtocol, "NewProtocol"}, - { NewInternalPort, "NewInternalPort"}, - { NewInternalClient, "NewInternalClient"}, - { NewEnabled, "NewEnabled"}, - { NewDescription, "NewDescription"}, - { NewLeaseTime, "NewLeaseTime"}, - { PortMappingEltNone, NULL} -}; - -/* Helper function */ -static UNSIGNED_INTEGER -atoui(const char * p, int l) -{ - UNSIGNED_INTEGER r = 0; - while(l > 0 && *p) - { - if(*p >= '0' && *p <= '9') - r = r*10 + (*p - '0'); - else - break; - p++; - l--; - } - return r; -} - -/* Start element handler */ -static void -startelt(void * d, const char * name, int l) -{ - int i; - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - pdata->curelt = PortMappingEltNone; - for(i = 0; elements[i].str; i++) - { - if(strlen(elements[i].str) == (size_t)l && memcmp(name, elements[i].str, l) == 0) - { - pdata->curelt = elements[i].code; - break; - } - } - if(pdata->curelt == PortMappingEntry) - { - struct PortMapping * pm; - pm = calloc(1, sizeof(struct PortMapping)); - if(pm == NULL) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "startelt"); -#endif /* DEBUG */ - return; - } - pm->l_next = pdata->l_head; /* insert in list */ - pdata->l_head = pm; - } -} - -/* End element handler */ -static void -endelt(void * d, const char * name, int l) -{ - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - (void)name; - (void)l; - pdata->curelt = PortMappingEltNone; -} - -/* Data handler */ -static void -data(void * d, const char * data, int l) -{ - struct PortMapping * pm; - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - pm = pdata->l_head; - if(!pm) - return; - if(l > 63) - l = 63; - switch(pdata->curelt) - { - case NewRemoteHost: - memcpy(pm->remoteHost, data, l); - pm->remoteHost[l] = '\0'; - break; - case NewExternalPort: - pm->externalPort = (unsigned short)atoui(data, l); - break; - case NewProtocol: - if(l > 3) - l = 3; - memcpy(pm->protocol, data, l); - pm->protocol[l] = '\0'; - break; - case NewInternalPort: - pm->internalPort = (unsigned short)atoui(data, l); - break; - case NewInternalClient: - memcpy(pm->internalClient, data, l); - pm->internalClient[l] = '\0'; - break; - case NewEnabled: - pm->enabled = (unsigned char)atoui(data, l); - break; - case NewDescription: - memcpy(pm->description, data, l); - pm->description[l] = '\0'; - break; - case NewLeaseTime: - pm->leaseTime = atoui(data, l); - break; - default: - break; - } -} - - -/* Parse the PortMappingList XML document for IGD version 2 - */ -void -ParsePortListing(const char * buffer, int bufsize, - struct PortMappingParserData * pdata) -{ - struct xmlparser parser; - - memset(pdata, 0, sizeof(struct PortMappingParserData)); - /* init xmlparser */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = pdata; - parser.starteltfunc = startelt; - parser.endeltfunc = endelt; - parser.datafunc = data; - parser.attfunc = 0; - parsexml(&parser); -} - -void -FreePortListing(struct PortMappingParserData * pdata) -{ - struct PortMapping * pm; - while((pm = pdata->l_head) != NULL) - { - /* remove from list */ - pdata->l_head = pm->l_next; - free(pm); - } -} - diff --git a/src/contrib/miniupnp/miniupnpc/portlistingparse.h b/src/contrib/miniupnp/miniupnpc/portlistingparse.h deleted file mode 100644 index e3957a3..0000000 --- a/src/contrib/miniupnp/miniupnpc/portlistingparse.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id: portlistingparse.h,v 1.10 2014/11/01 10:37:32 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef PORTLISTINGPARSE_H_INCLUDED -#define PORTLISTINGPARSE_H_INCLUDED - -#include "miniupnpc_declspec.h" -/* for the definition of UNSIGNED_INTEGER */ -#include "miniupnpctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* sample of PortMappingEntry : - - 202.233.2.1 - 2345 - TCP - 2345 - 192.168.1.137 - 1 - dooom - 345 - - */ -typedef enum { PortMappingEltNone, - PortMappingEntry, NewRemoteHost, - NewExternalPort, NewProtocol, - NewInternalPort, NewInternalClient, - NewEnabled, NewDescription, - NewLeaseTime } portMappingElt; - -struct PortMapping { - struct PortMapping * l_next; /* list next element */ - UNSIGNED_INTEGER leaseTime; - unsigned short externalPort; - unsigned short internalPort; - char remoteHost[64]; - char internalClient[64]; - char description[64]; - char protocol[4]; - unsigned char enabled; -}; - -struct PortMappingParserData { - struct PortMapping * l_head; /* list head */ - portMappingElt curelt; -}; - -MINIUPNP_LIBSPEC void -ParsePortListing(const char * buffer, int bufsize, - struct PortMappingParserData * pdata); - -MINIUPNP_LIBSPEC void -FreePortListing(struct PortMappingParserData * pdata); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/miniupnp/miniupnpc/pymoduletest.py b/src/contrib/miniupnp/miniupnpc/pymoduletest.py deleted file mode 100644 index 9de14a6..0000000 --- a/src/contrib/miniupnp/miniupnpc/pymoduletest.py +++ /dev/null @@ -1,88 +0,0 @@ -#! /usr/bin/python -# vim: tabstop=2 shiftwidth=2 expandtab -# MiniUPnP project -# Author : Thomas Bernard -# This Sample code is public domain. -# website : https://miniupnp.tuxfamily.org/ - -# import the python miniupnpc module -import miniupnpc -import sys - -try: - import argparse - parser = argparse.ArgumentParser() - parser.add_argument('-m', '--multicastif') - parser.add_argument('-p', '--minissdpdsocket') - parser.add_argument('-d', '--discoverdelay', type=int, default=200) - parser.add_argument('-z', '--localport', type=int, default=0) - # create the object - u = miniupnpc.UPnP(**vars(parser.parse_args())) -except: - print 'argparse not available' - i = 1 - multicastif = None - minissdpdsocket = None - discoverdelay = 200 - localport = 0 - while i < len(sys.argv): - print sys.argv[i] - if sys.argv[i] == '-m' or sys.argv[i] == '--multicastif': - multicastif = sys.argv[i+1] - elif sys.argv[i] == '-p' or sys.argv[i] == '--minissdpdsocket': - minissdpdsocket = sys.argv[i+1] - elif sys.argv[i] == '-d' or sys.argv[i] == '--discoverdelay': - discoverdelay = int(sys.argv[i+1]) - elif sys.argv[i] == '-z' or sys.argv[i] == '--localport': - localport = int(sys.argv[i+1]) - else: - raise Exception('invalid argument %s' % sys.argv[i]) - i += 2 - # create the object - u = miniupnpc.UPnP(multicastif, minissdpdsocket, discoverdelay, localport) - -print 'inital(default) values :' -print ' discoverdelay', u.discoverdelay -print ' lanaddr', u.lanaddr -print ' multicastif', u.multicastif -print ' minissdpdsocket', u.minissdpdsocket -#u.minissdpdsocket = '../minissdpd/minissdpd.sock' -# discovery process, it usually takes several seconds (2 seconds or more) -print 'Discovering... delay=%ums' % u.discoverdelay -print u.discover(), 'device(s) detected' -# select an igd -try: - u.selectigd() -except Exception, e: - print 'Exception :', e - sys.exit(1) -# display information about the IGD and the internet connection -print 'local ip address :', u.lanaddr -print 'external ip address :', u.externalipaddress() -print u.statusinfo(), u.connectiontype() -print 'total bytes : sent', u.totalbytesent(), 'received', u.totalbytereceived() -print 'total packets : sent', u.totalpacketsent(), 'received', u.totalpacketreceived() - -#print u.addportmapping(64000, 'TCP', -# '192.168.1.166', 63000, 'port mapping test', '') -#print u.deleteportmapping(64000, 'TCP') - -port = 0 -proto = 'UDP' -# list the redirections : -i = 0 -while True: - p = u.getgenericportmapping(i) - if p==None: - break - print i, p - (port, proto, (ihost,iport), desc, c, d, e) = p - #print port, desc - i = i + 1 - -print u.getspecificportmapping(port, proto) -try: - print u.getportmappingnumberofentries() -except Exception, e: - print 'GetPortMappingNumberOfEntries() is not supported :', e - diff --git a/src/contrib/miniupnp/miniupnpc/pymoduletest3.py b/src/contrib/miniupnp/miniupnpc/pymoduletest3.py deleted file mode 100644 index 1fcab4e..0000000 --- a/src/contrib/miniupnp/miniupnpc/pymoduletest3.py +++ /dev/null @@ -1,52 +0,0 @@ -#! /usr/bin/python3 -# MiniUPnP project -# Author : Thomas Bernard -# This Sample code is public domain. -# website : http://miniupnp.tuxfamily.org/ - -# import the python miniupnpc module -import miniupnpc -import sys - -# create the object -u = miniupnpc.UPnP() -print('inital(default) values :') -print(' discoverdelay', u.discoverdelay) -print(' lanaddr', u.lanaddr) -print(' multicastif', u.multicastif) -print(' minissdpdsocket', u.minissdpdsocket) -u.discoverdelay = 200; -#u.minissdpdsocket = '../minissdpd/minissdpd.sock' -# discovery process, it usually takes several seconds (2 seconds or more) -print('Discovering... delay=%ums' % u.discoverdelay) -print(u.discover(), 'device(s) detected') -# select an igd -try: - u.selectigd() -except Exception as e: - print('Exception :', e) - sys.exit(1) -# display information about the IGD and the internet connection -print('local ip address :', u.lanaddr) -print('external ip address :', u.externalipaddress()) -print(u.statusinfo(), u.connectiontype()) - -#print u.addportmapping(64000, 'TCP', -# '192.168.1.166', 63000, 'port mapping test', '') -#print u.deleteportmapping(64000, 'TCP') - -port = 0 -proto = 'UDP' -# list the redirections : -i = 0 -while True: - p = u.getgenericportmapping(i) - if p==None: - break - print(i, p) - (port, proto, (ihost,iport), desc, c, d, e) = p - #print port, desc - i = i + 1 - -print(u.getspecificportmapping(port, proto)) - diff --git a/src/contrib/miniupnp/miniupnpc/receivedata.c b/src/contrib/miniupnp/miniupnpc/receivedata.c deleted file mode 100644 index 7b9cc5b..0000000 --- a/src/contrib/miniupnp/miniupnpc/receivedata.c +++ /dev/null @@ -1,99 +0,0 @@ -/* $Id: receivedata.c,v 1.7 2015/11/09 21:51:41 nanard Exp $ */ -/* Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2011-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#ifdef _WIN32 -#include -#include -#else /* _WIN32 */ -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -#define socklen_t int -#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#include -#if !defined(__amigaos__) && !defined(__amigaos4__) -#include -#endif /* !defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#define MINIUPNPC_IGNORE_EINTR -#endif /* _WIN32 */ - -#include "receivedata.h" - -int -receivedata(SOCKET socket, - char * data, int length, - int timeout, unsigned int * scope_id) -{ -#ifdef MINIUPNPC_GET_SRC_ADDR - struct sockaddr_storage src_addr; - socklen_t src_addr_len = sizeof(src_addr); -#endif /* MINIUPNPC_GET_SRC_ADDR */ - int n; -#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) - /* using poll */ - struct pollfd fds[1]; /* for the poll */ -#ifdef MINIUPNPC_IGNORE_EINTR - do { -#endif /* MINIUPNPC_IGNORE_EINTR */ - fds[0].fd = socket; - fds[0].events = POLLIN; - n = poll(fds, 1, timeout); -#ifdef MINIUPNPC_IGNORE_EINTR - } while(n < 0 && errno == EINTR); -#endif /* MINIUPNPC_IGNORE_EINTR */ - if(n < 0) { - PRINT_SOCKET_ERROR("poll"); - return -1; - } else if(n == 0) { - /* timeout */ - return 0; - } -#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ - /* using select under _WIN32 and amigaos */ - fd_set socketSet; - TIMEVAL timeval; - FD_ZERO(&socketSet); - FD_SET(socket, &socketSet); - timeval.tv_sec = timeout / 1000; - timeval.tv_usec = (timeout % 1000) * 1000; - n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); - if(n < 0) { - PRINT_SOCKET_ERROR("select"); - return -1; - } else if(n == 0) { - return 0; - } -#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ -#ifdef MINIUPNPC_GET_SRC_ADDR - memset(&src_addr, 0, sizeof(src_addr)); - n = recvfrom(socket, data, length, 0, - (struct sockaddr *)&src_addr, &src_addr_len); -#else /* MINIUPNPC_GET_SRC_ADDR */ - n = recv(socket, data, length, 0); -#endif /* MINIUPNPC_GET_SRC_ADDR */ - if(n<0) { - PRINT_SOCKET_ERROR("recv"); - } -#ifdef MINIUPNPC_GET_SRC_ADDR - if (src_addr.ss_family == AF_INET6) { - const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; -#ifdef DEBUG - printf("scope_id=%u\n", src_addr6->sin6_scope_id); -#endif /* DEBUG */ - if(scope_id) - *scope_id = src_addr6->sin6_scope_id; - } -#endif /* MINIUPNPC_GET_SRC_ADDR */ - return n; -} - diff --git a/src/contrib/miniupnp/miniupnpc/receivedata.h b/src/contrib/miniupnp/miniupnpc/receivedata.h deleted file mode 100644 index c9fdc56..0000000 --- a/src/contrib/miniupnp/miniupnpc/receivedata.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id: receivedata.h,v 1.3 2012/06/23 22:34:47 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2011-2018 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef RECEIVEDATA_H_INCLUDED -#define RECEIVEDATA_H_INCLUDED - -#include "miniupnpc_socketdef.h" - -/* Reads data from the specified socket. - * Returns the number of bytes read if successful, zero if no bytes were - * read or if we timed out. Returns negative if there was an error. */ -int receivedata(SOCKET socket, - char * data, int length, - int timeout, unsigned int * scope_id); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/setup.py b/src/contrib/miniupnp/miniupnpc/setup.py deleted file mode 100644 index 24a676d..0000000 --- a/src/contrib/miniupnp/miniupnpc/setup.py +++ /dev/null @@ -1,35 +0,0 @@ -#! /usr/bin/python -# vim: tabstop=8 shiftwidth=8 expandtab -# $Id: setup.py,v 1.9 2012/05/23 08:50:10 nanard Exp $ -# the MiniUPnP Project (c) 2007-2017 Thomas Bernard -# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ -# -# python script to build the miniupnpc module under unix -# -# Uses MAKE environment variable (defaulting to 'make') - -from setuptools import setup, Extension -from setuptools.command import build_ext -import subprocess -import os - -EXT = ['libminiupnpc.a'] - -class make_then_build_ext(build_ext.build_ext): - def run(self): - subprocess.check_call([os.environ.get('MAKE', 'make')] + EXT) - build_ext.build_ext.run(self) - -setup(name="miniupnpc", - version=open('VERSION').read().strip(), - author='Thomas BERNARD', - author_email='miniupnp@free.fr', - license=open('LICENSE').read(), - url='http://miniupnp.free.fr/', - description='miniUPnP client', - cmdclass={'build_ext': make_then_build_ext}, - ext_modules=[ - Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], - extra_objects=EXT) - ]) - diff --git a/src/contrib/miniupnp/miniupnpc/setupmingw32.py b/src/contrib/miniupnp/miniupnpc/setupmingw32.py deleted file mode 100644 index 7e3c382..0000000 --- a/src/contrib/miniupnp/miniupnpc/setupmingw32.py +++ /dev/null @@ -1,28 +0,0 @@ -#! /usr/bin/python -# vim: tabstop=8 shiftwidth=8 expandtab -# $Id: setupmingw32.py,v 1.8 2012/05/23 08:50:10 nanard Exp $ -# the MiniUPnP Project (c) 2007-2014 Thomas Bernard -# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ -# -# python script to build the miniupnpc module under windows (using mingw32) -# -try: - from setuptools import setup, Extension -except ImportError: - from distutils.core import setup, Extension -from distutils import sysconfig -sysconfig.get_config_vars()["OPT"] = '' -sysconfig.get_config_vars()["CFLAGS"] = '' -setup(name="miniupnpc", - version=open('VERSION').read().strip(), - author='Thomas BERNARD', - author_email='miniupnp@free.fr', - license=open('LICENSE').read(), - url='http://miniupnp.free.fr/', - description='miniUPnP client', - ext_modules=[ - Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], - libraries=["ws2_32", "iphlpapi"], - extra_objects=["libminiupnpc.a"]) - ]) - diff --git a/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.values b/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.values deleted file mode 100644 index cf42221..0000000 --- a/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.values +++ /dev/null @@ -1,14 +0,0 @@ -# values for linksys_WAG200G_desc.xml - -CIF: - servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 - controlurl = /upnp/control/WANCommonIFC1 - eventsuburl = /upnp/event/WANCommonIFC1 - scpdurl = /cmnicfg.xml - -first: - servicetype = urn:schemas-upnp-org:service:WANPPPConnection:1 - controlurl = /upnp/control/WANPPPConn1 - eventsuburl = /upnp/event/WANPPPConn1 - scpdurl = /pppcfg.xml - diff --git a/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.xml b/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.xml deleted file mode 100644 index d428d73..0000000 --- a/src/contrib/miniupnp/miniupnpc/testdesc/linksys_WAG200G_desc.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - -1 -0 - -http://192.168.1.1:49152 - -urn:schemas-upnp-org:device:InternetGatewayDevice:1 -LINKSYS WAG200G Gateway -LINKSYS -http://www.linksys.com -LINKSYS WAG200G Gateway -Wireless-G ADSL Home Gateway -WAG200G -http://www.linksys.com -123456789 -uuid:8ca2eb37-1dd2-11b2-86f1-001a709b5aa8 -WAG200G - - -urn:schemas-upnp-org:service:Layer3Forwarding:1 -urn:upnp-org:serviceId:L3Forwarding1 -/upnp/control/L3Forwarding1 -/upnp/event/L3Forwarding1 -/l3frwd.xml - - - - -urn:schemas-upnp-org:device:WANDevice:1 -WANDevice -LINKSYS -http://www.linksys.com/ -Residential Gateway -Internet Connection Sharing -1 -http://www.linksys.com/ -0000001 -uuid:8ca2eb36-1dd2-11b2-86f1-001a709b5aa8 -WAG200G - - -urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 -urn:upnp-org:serviceId:WANCommonIFC1 -/upnp/control/WANCommonIFC1 -/upnp/event/WANCommonIFC1 -/cmnicfg.xml - - - - -urn:schemas-upnp-org:device:WANConnectionDevice:1 -WANConnectionDevice -LINKSYS -http://www.linksys.com/ -Residential Gateway -Internet Connection Sharing -1 -http://www.linksys.com/ -0000001 -uuid:8ca2eb37-1dd2-11b2-86f0-001a709b5aa8 -WAG200G - - -urn:schemas-upnp-org:service:WANEthernetLinkConfig:1 -urn:upnp-org:serviceId:WANEthLinkC1 -/upnp/control/WANEthLinkC1 -/upnp/event/WANEthLinkC1 -/wanelcfg.xml - - -urn:schemas-upnp-org:service:WANPPPConnection:1 -urn:upnp-org:serviceId:WANPPPConn1 -/upnp/control/WANPPPConn1 -/upnp/event/WANPPPConn1 -/pppcfg.xml - - - - - - -urn:schemas-upnp-org:device:LANDevice:1 -LANDevice -LINKSYS -http://www.linksys.com/ -Residential Gateway -Residential Gateway -1 -http://www.linksys.com/ -0000001 -uuid:8ca2eb36-1dd2-11b2-86f0-001a709b5aa -8 -WAG200G - - -urn:schemas-upnp-org:service:LANHostConfigManagement:1 -urn:upnp-org:serviceId:LANHostCfg1 -/upnp/control/LANHostCfg1 -/upnp/event/LANHostCfg1 -/lanhostc.xml - - - - -http://192.168.1.1/index.htm - - - diff --git a/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.values b/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.values deleted file mode 100644 index c55552e..0000000 --- a/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.values +++ /dev/null @@ -1,20 +0,0 @@ -# values for new_LiveBox_desc.xml - -CIF: - servicetype = urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 - controlurl = /87895a19/upnp/control/WANCommonIFC1 - eventsuburl = /87895a19/upnp/control/WANCommonIFC1 - scpdurl = /87895a19/gateicfgSCPD.xml - -first: - servicetype = urn:schemas-upnp-org:service:WANPPPConnection:2 - controlurl = /87895a19/upnp/control/WANIPConn1 - eventsuburl = /87895a19/upnp/control/WANIPConn1 - scpdurl = /87895a19/gateconnSCPD_PPP.xml - -IPv6FC: - servicetype = urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - controlurl = /87895a19/upnp/control/WANIPv6FwCtrl1 - eventsuburl = /87895a19/upnp/control/WANIPv6FwCtrl1 - scpdurl = /87895a19/wanipv6fwctrlSCPD.xml - diff --git a/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.xml b/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.xml deleted file mode 100644 index 3e522df..0000000 --- a/src/contrib/miniupnp/miniupnpc/testdesc/new_LiveBox_desc.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - 1 - 0 - - - VEN_0129&DEV_0000&SUBSYS_03&REV_250417 - GenericUmPass - NetworkInfrastructure.Gateway - Network.Gateway - urn:schemas-upnp-org:device:InternetGatewayDevice:2 - Orange Livebox - Sagemcom - http://www.sagemcom.com/ - Residential Livebox,(DSL,WAN Ethernet) - uuid:87895a19-50f9-3736-a87f-115c230155f8 - Sagemcom,fr,SG30_sip-fr-4.28.35.1 - 3 - LK14129DP441489 - http://192.168.1.1 - - - - image/png - 16 - 16 - 8 - /87895a19/ligd.png - - - - - urn:schemas-upnp-org:device:WANDevice:2 - WANDevice - Sagemcom - http://www.sagemcom.com/ - WAN Device on Sagemcom,fr,SG30_sip-fr-4.28.35.1 - Residential Livebox,(DSL,WAN Ethernet) - 3 - http://www.sagemcom.com/ - LK14129DP441489 - http://192.168.1.1 - uuid:e2397374-53d8-3fc6-8306-593ba1a34625 - - - - urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 - urn:upnp-org:serviceId:WANCommonIFC1 - /87895a19/upnp/control/WANCommonIFC1 - /87895a19/upnp/control/WANCommonIFC1 - /87895a19/gateicfgSCPD.xml - - - - - urn:schemas-upnp-org:device:WANConnectionDevice:2 - WANConnectionDevice - Sagemcom - http://www.sagemcom.com/ - WanConnectionDevice on Sagemcom,fr,SG30_sip-fr-4.28.35.1 - Residential Livebox,(DSL,WAN Ethernet) - 3 - http://www.sagemcom.com/ - LK14129DP441489 - http://192.168.1.1 - uuid:44598a08-288e-32c9-8a4d-d3c008ede331 - - - - urn:schemas-upnp-org:service:WANPPPConnection:2 - urn:upnp-org:serviceId:WANIPConn1 - /87895a19/upnp/control/WANIPConn1 - /87895a19/upnp/control/WANIPConn1 - /87895a19/gateconnSCPD_PPP.xml - - - urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - urn:upnp-org:serviceId:WANIPv6FwCtrl1 - /87895a19/upnp/control/WANIPv6FwCtrl1 - /87895a19/upnp/control/WANIPv6FwCtrl1 - /87895a19/wanipv6fwctrlSCPD.xml - - - - - - - - \ No newline at end of file diff --git a/src/contrib/miniupnp/miniupnpc/testigddescparse.c b/src/contrib/miniupnp/miniupnpc/testigddescparse.c deleted file mode 100644 index cb7e94a..0000000 --- a/src/contrib/miniupnp/miniupnpc/testigddescparse.c +++ /dev/null @@ -1,187 +0,0 @@ -/* $Id: testigddescparse.c,v 1.8 2015/02/08 08:46:06 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2008-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include -#include "igd_desc_parse.h" -#include "minixml.h" -#include "miniupnpc.h" - -/* count number of differences */ -int compare_service(struct IGDdatas_service * s, FILE * f) -{ - int n = 0; - char line[1024]; - - while(fgets(line, sizeof(line), f)) { - char * value; - char * equal; - char * name; - char * parsedvalue; - int l; - l = strlen(line); - while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n') || (line[l-1] == ' '))) - line[--l] = '\0'; - if(l == 0) - break; /* end on blank line */ - if(line[0] == '#') - continue; /* skip comments */ - equal = strchr(line, '='); - if(equal == NULL) { - fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); - continue; - } - *equal = '\0'; - name = line; - while(*name == ' ' || *name == '\t') - name++; - l = strlen(name); - while((l > 0) && (name[l-1] == ' ' || name[l-1] == '\t')) - name[--l] = '\0'; - value = equal + 1; - while(*value == ' ' || *value == '\t') - value++; - if(strcmp(name, "controlurl") == 0) - parsedvalue = s->controlurl; - else if(strcmp(name, "eventsuburl") == 0) - parsedvalue = s->eventsuburl; - else if(strcmp(name, "scpdurl") == 0) - parsedvalue = s->scpdurl; - else if(strcmp(name, "servicetype") == 0) - parsedvalue = s->servicetype; - else { - fprintf(stderr, "unknown field '%s'\n", name); - continue; - } - if(0 != strcmp(parsedvalue, value)) { - fprintf(stderr, "difference : '%s' != '%s'\n", parsedvalue, value); - n++; - } - } - return n; -} - -int compare_igd(struct IGDdatas * p, FILE * f) -{ - int n = 0; - char line[1024]; - struct IGDdatas_service * s; - - while(fgets(line, sizeof(line), f)) { - char * colon; - int l = (int)strlen(line); - while((l > 0) && (line[l-1] == '\r' || (line[l-1] == '\n'))) - line[--l] = '\0'; - if(l == 0 || line[0] == '#') - continue; /* skip blank lines and comments */ - colon = strchr(line, ':'); - if(colon == NULL) { - fprintf(stderr, "Warning, no ':' : %s\n", line); - continue; - } - s = NULL; - *colon = '\0'; - if(strcmp(line, "CIF") == 0) - s = &p->CIF; - else if(strcmp(line, "first") == 0) - s = &p->first; - else if(strcmp(line, "second") == 0) - s = &p->second; - else if(strcmp(line, "IPv6FC") == 0) - s = &p->IPv6FC; - else { - s = NULL; - fprintf(stderr, "*** unknown service '%s' ***\n", line); - n++; - continue; - } - n += compare_service(s, f); - } - if(n > 0) - fprintf(stderr, "*** %d difference%s ***\n", n, (n > 1) ? "s" : ""); - return n; -} - -int test_igd_desc_parse(char * buffer, int len, FILE * f) -{ - int n; - struct IGDdatas igd; - struct xmlparser parser; - struct UPNPUrls urls; - - memset(&igd, 0, sizeof(struct IGDdatas)); - memset(&parser, 0, sizeof(struct xmlparser)); - parser.xmlstart = buffer; - parser.xmlsize = len; - parser.data = &igd; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parsexml(&parser); -#ifdef DEBUG - printIGD(&igd); -#endif /* DEBUG */ - GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); - printf("ipcondescURL='%s'\n", urls.ipcondescURL); - printf("controlURL='%s'\n", urls.controlURL); - printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); - n = f ? compare_igd(&igd, f) : 0; - FreeUPNPUrls(&urls); - return n; -} - -int main(int argc, char * * argv) -{ - FILE * f; - char * buffer; - int len; - int r; - if(argc<2) { - fprintf(stderr, "Usage: %s file.xml [file.values]\n", argv[0]); - return 1; - } - f = fopen(argv[1], "r"); - if(!f) { - fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); - return 1; - } - fseek(f, 0, SEEK_END); - len = ftell(f); - fseek(f, 0, SEEK_SET); - buffer = malloc(len); - if(!buffer) { - fprintf(stderr, "Memory allocation error.\n"); - fclose(f); - return 1; - } - r = (int)fread(buffer, 1, len, f); - if(r != len) { - fprintf(stderr, "Failed to read file %s. %d out of %d bytes.\n", - argv[1], r, len); - fclose(f); - free(buffer); - return 1; - } - fclose(f); - f = NULL; - if(argc > 2) { - f = fopen(argv[2], "r"); - if(!f) { - fprintf(stderr, "Cannot open %s for reading.\n", argv[2]); - free(buffer); - return 1; - } - } - r = test_igd_desc_parse(buffer, len, f); - free(buffer); - if(f) - fclose(f); - return r; -} - diff --git a/src/contrib/miniupnp/miniupnpc/testminiwget.c b/src/contrib/miniupnp/miniupnpc/testminiwget.c deleted file mode 100644 index fba39d5..0000000 --- a/src/contrib/miniupnp/miniupnpc/testminiwget.c +++ /dev/null @@ -1,56 +0,0 @@ -/* $Id: testminiwget.c,v 1.6 2017/11/02 16:52:37 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include "miniwget.h" - -/** - * This program uses the miniwget / miniwget_getaddr function - * from miniwget.c in order to retrieve a web ressource using - * a GET HTTP method, and store it in a file. - */ -int main(int argc, char * * argv) -{ - void * data; - int size, writtensize; - FILE *f; - char addr[64]; - int status_code = -1; - - if(argc < 3) { - fprintf(stderr, "Usage:\t%s url file\n", argv[0]); - fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]); - return 1; - } - data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0, &status_code); - if(!data || (status_code != 200)) { - if(data) free(data); - fprintf(stderr, "Error %d fetching %s\n", status_code, argv[1]); - return 1; - } - printf("local address : %s\n", addr); - printf("got %d bytes\n", size); - f = fopen(argv[2], "wb"); - if(!f) { - fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); - free(data); - return 1; - } - writtensize = fwrite(data, 1, size, f); - if(writtensize != size) { - fprintf(stderr, "Could only write %d bytes out of %d to %s\n", - writtensize, size, argv[2]); - } else { - printf("%d bytes written to %s\n", writtensize, argv[2]); - } - fclose(f); - free(data); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpc/testminiwget.sh b/src/contrib/miniupnp/miniupnpc/testminiwget.sh deleted file mode 100644 index 32154e0..0000000 --- a/src/contrib/miniupnp/miniupnpc/testminiwget.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/sh -# $Id: testminiwget.sh,v 1.15 2017/11/02 17:36:26 nanard Exp $ -# vim: tabstop=4 shiftwidth=4 noexpandtab -# project miniupnp : http://miniupnp.free.fr/ -# (c) 2011-2018 Thomas Bernard -# -# test program for miniwget.c -# is usually invoked by "make check" -# -# This test program : -# 1 - launches a local HTTP server (minihttptestserver) -# 2 - uses testminiwget to retrieve data from this server -# 3 - compares served and received data -# 4 - kills the local HTTP server and exits -# -# The script was tested and works with ksh, bash -# it should now also run with dash - -TMPD=`mktemp -d -t miniwgetXXXXXXXXXX` -HTTPSERVEROUT="${TMPD}/httpserverout" -EXPECTEDFILE="${TMPD}/expectedfile" -DOWNLOADEDFILE="${TMPD}/downloadedfile" -PORT= -RET=0 -IPCONFIG=$(which ifconfig) -if [ -z "$IPCONFIG" ] ; then - IPCONFIG="/sbin/ifconfig" -fi - -if ! $IPCONFIG -a | grep inet6 ; then - HAVE_IPV6=no -fi - -case "$HAVE_IPV6" in - n|no|0) - ADDR=localhost - SERVERARGS="" - ;; - *) - ADDR="[::1]" - SERVERARGS="-6" - ;; - -esac - -#make minihttptestserver -#make testminiwget - -# launching the test HTTP server -./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT & -SERVERPID=$! -while [ -z "$PORT" ]; do - sleep 1 - PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` -done -if [ "$PORT" = "*** ERROR ***" ]; then - echo "HTTP test server error" - echo "Network config :" - $IPCONFIG -a - exit 2 -fi -echo "Test HTTP server is listening on $PORT" - -URL1="http://$ADDR:$PORT/index.html" -URL2="http://$ADDR:$PORT/chunked" -URL3="http://$ADDR:$PORT/addcrap" - -echo "standard test ..." -./testminiwget $URL1 "${DOWNLOADEDFILE}.1" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then - echo "ok" -else - echo "standard test FAILED" - RET=1 -fi - -echo "chunked transfert encoding test ..." -./testminiwget $URL2 "${DOWNLOADEDFILE}.2" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then - echo "ok" -else - echo "chunked transfert encoding test FAILED" - RET=1 -fi - -echo "response too long test ..." -./testminiwget $URL3 "${DOWNLOADEDFILE}.3" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then - echo "ok" -else - echo "response too long test FAILED" - RET=1 -fi - -# kill the test HTTP server -kill $SERVERPID -wait $SERVERPID - -# remove temporary files (for success cases) -if [ $RET -eq 0 ]; then - rm -f "${DOWNLOADEDFILE}.1" - rm -f "${DOWNLOADEDFILE}.2" - rm -f "${DOWNLOADEDFILE}.3" - rm -f $EXPECTEDFILE $HTTPSERVEROUT - rmdir ${TMPD} -else - echo "at least one of the test FAILED" - echo "directory ${TMPD} is left intact" -fi -exit $RET - diff --git a/src/contrib/miniupnp/miniupnpc/testminixml.c b/src/contrib/miniupnp/miniupnpc/testminixml.c deleted file mode 100644 index 57c4a85..0000000 --- a/src/contrib/miniupnp/miniupnpc/testminixml.c +++ /dev/null @@ -1,89 +0,0 @@ -/* $Id: testminixml.c,v 1.10 2014/11/17 17:19:13 nanard Exp $ - * MiniUPnP project - * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard. - * Copyright (c) 2005-2014 Thomas Bernard - * - * testminixml.c - * test program for the "minixml" functions. - */ -#include -#include -#include -#include "minixml.h" -#include "igd_desc_parse.h" - -/* ---------------------------------------------------------------------- */ -void printeltname1(void * d, const char * name, int l) -{ - int i; - (void)d; - printf("element "); - for(i=0;i -#include -#include "portlistingparse.h" - -struct port_mapping { - unsigned int leasetime; - unsigned short externalport; - unsigned short internalport; - const char * remotehost; - const char * client; - const char * proto; - const char * desc; - unsigned char enabled; -}; - -/* return the number of differences */ -int test(const char * portListingXml, int portListingXmlLen, - const struct port_mapping * ref, int count) -{ - int i; - int r = 0; - struct PortMappingParserData data; - struct PortMapping * pm; - - memset(&data, 0, sizeof(data)); - ParsePortListing(portListingXml, portListingXmlLen, &data); - for(i = 0, pm = data.l_head; - (pm != NULL) && (i < count); - i++, pm = pm->l_next) { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - if(0 != strcmp(pm->protocol, ref[i].proto)) { - printf("protocol : '%s' != '%s'\n", pm->protocol, ref[i].proto); - r++; - } - if(pm->externalPort != ref[i].externalport) { - printf("externalPort : %hu != %hu\n", - pm->externalPort, ref[i].externalport); - r++; - } - if(0 != strcmp(pm->internalClient, ref[i].client)) { - printf("client : '%s' != '%s'\n", - pm->internalClient, ref[i].client); - r++; - } - if(pm->internalPort != ref[i].internalport) { - printf("internalPort : %hu != %hu\n", - pm->internalPort, ref[i].internalport); - r++; - } - if(0 != strcmp(pm->description, ref[i].desc)) { - printf("description : '%s' != '%s'\n", - pm->description, ref[i].desc); - r++; - } - if(0 != strcmp(pm->remoteHost, ref[i].remotehost)) { - printf("remoteHost : '%s' != '%s'\n", - pm->remoteHost, ref[i].remotehost); - r++; - } - if((unsigned)pm->leaseTime != ref[i].leasetime) { - printf("leaseTime : %u != %u\n", - (unsigned)pm->leaseTime, ref[i].leasetime); - r++; - } - if(pm->enabled != ref[i].enabled) { - printf("enabled : %d != %d\n", - (int)pm->enabled, (int)ref[i].enabled); - r++; - } - } - if((i != count) || (pm != NULL)) { - printf("count mismatch : i=%d count=%d pm=%p\n", i, count, pm); - r++; - } - FreePortListing(&data); - return r; -} - -const char test_document[] = -"\n" -"\n" -" \n" -" \n" -" 5002\n" -" UDP\n" -" 4001\n" -" 192.168.1.123\n" -" 1\n" -" xxx\n" -" 0\n" -" \n" -" \n" -" 202.233.2.1\n" -" 2345\n" -" TCP\n" -" 2349\n" -" 192.168.1.137\n" -" 1\n" -" dooom\n" -" 346\n" -" \n" -" \n" -" 134.231.2.11\n" -" 12345\n" -" TCP\n" -" 12345\n" -" 192.168.1.137\n" -" 1\n" -" dooom A\n" -" 347\n" -" \n" -""; - -#define PORT_MAPPINGS_COUNT 3 -const struct port_mapping port_mappings[PORT_MAPPINGS_COUNT] = { -{347, 12345, 12345, "134.231.2.11", "192.168.1.137", "TCP", "dooom A", 1}, -{346, 2345, 2349, "202.233.2.1", "192.168.1.137", "TCP", "dooom", 1}, -{0, 5002, 4001, "", "192.168.1.123", "UDP", "xxx", 1} -}; - -/* --- main --- */ -int main(void) -{ - int r; - r = test(test_document, sizeof(test_document) - 1, - port_mappings, PORT_MAPPINGS_COUNT); - if(r == 0) { - printf("test of portlistingparse OK\n"); - return 0; - } else { - printf("test FAILED (%d differences counted)\n", r); - return 1; - } -} - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.namevalue b/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.namevalue deleted file mode 100644 index 48ca0cc..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.namevalue +++ /dev/null @@ -1,3 +0,0 @@ -NewRemoteHost= -NewExternalPort=123 -NewProtocol=TCP diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.xml b/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.xml deleted file mode 100644 index a955c53..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/DeletePortMapping.xml +++ /dev/null @@ -1,6 +0,0 @@ - -123 -TCP - - - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue deleted file mode 100644 index 5aa75f8..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue +++ /dev/null @@ -1,2 +0,0 @@ -NewExternalIPAddress=1.2.3.4 - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.xml b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.xml deleted file mode 100644 index db7ec1f..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetExternalIPAddress.xml +++ /dev/null @@ -1,2 +0,0 @@ -1.2.3.4 - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue deleted file mode 100644 index 26b169c..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue +++ /dev/null @@ -1,3 +0,0 @@ -NewProtocol=UDP -NewExternalPort=12345 -NewRemoteHost= diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml deleted file mode 100644 index bbb540e..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml +++ /dev/null @@ -1,3 +0,0 @@ - -12345UDP - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue deleted file mode 100644 index 2189789..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue +++ /dev/null @@ -1,5 +0,0 @@ -NewInternalPort=12345 -NewInternalClient=192.168.10.110 -NewEnabled=1 -NewPortMappingDescription=libminiupnpc -NewLeaseDuration=0 diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml deleted file mode 100644 index 77e8d9c..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml +++ /dev/null @@ -1,2 +0,0 @@ -12345192.168.10.1101libminiupnpc0 - diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue b/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue deleted file mode 100644 index f78c7e2..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue +++ /dev/null @@ -1 +0,0 @@ -NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.xml b/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.xml deleted file mode 100644 index ac04c07..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/SetDefaultConnectionService.xml +++ /dev/null @@ -1 +0,0 @@ -uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/src/contrib/miniupnp/miniupnpc/testreplyparse/readme.txt b/src/contrib/miniupnp/miniupnpc/testreplyparse/readme.txt deleted file mode 100644 index 3eb1f01..0000000 --- a/src/contrib/miniupnp/miniupnpc/testreplyparse/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -This directory contains files used for validation of upnpreplyparse.c code. - -Each .xml file to parse should give the results which are in the .namevalue -file. - -A .namevalue file contain name=value lines. - diff --git a/src/contrib/miniupnp/miniupnpc/testupnpigd.py b/src/contrib/miniupnp/miniupnpc/testupnpigd.py deleted file mode 100644 index 33019bd..0000000 --- a/src/contrib/miniupnp/miniupnpc/testupnpigd.py +++ /dev/null @@ -1,88 +0,0 @@ -#! /usr/bin/python -# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $ -# MiniUPnP project -# Author : Thomas Bernard -# This Sample code is public domain. -# website : http://miniupnp.tuxfamily.org/ - -# import the python miniupnpc module -import miniupnpc -import socket - -try: - from http.server import BaseHTTPRequestHandler, HTTPServer -except ImportError: - from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer - -# function definition -def list_redirections(): - i = 0 - while True: - p = u.getgenericportmapping(i) - if p==None: - break - print(i, p) - i = i + 1 - -#define the handler class for HTTP connections -class handler_class(BaseHTTPRequestHandler): - def do_GET(self): - self.send_response(200) - self.end_headers() - self.wfile.write("OK MON GARS") - -# create the object -u = miniupnpc.UPnP() -#print 'inital(default) values :' -#print ' discoverdelay', u.discoverdelay -#print ' lanaddr', u.lanaddr -#print ' multicastif', u.multicastif -#print ' minissdpdsocket', u.minissdpdsocket -u.discoverdelay = 200; - -try: - print('Discovering... delay=%ums' % u.discoverdelay) - ndevices = u.discover() - print(ndevices, 'device(s) detected') - - # select an igd - u.selectigd() - # display information about the IGD and the internet connection - print('local ip address :', u.lanaddr) - externalipaddress = u.externalipaddress() - print('external ip address :', externalipaddress) - print(u.statusinfo(), u.connectiontype()) - - #instanciate a HTTPd object. The port is assigned by the system. - httpd = HTTPServer((u.lanaddr, 0), handler_class) - eport = httpd.server_port - - # find a free port for the redirection - r = u.getspecificportmapping(eport, 'TCP') - while r != None and eport < 65536: - eport = eport + 1 - r = u.getspecificportmapping(eport, 'TCP') - - print('trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port)) - - b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port, - 'UPnP IGD Tester port %u' % eport, '') - if b: - print('Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport)) - try: - httpd.handle_request() - httpd.server_close() - except KeyboardInterrupt as details: - print("CTRL-C exception!", details) - b = u.deleteportmapping(eport, 'TCP') - if b: - print('Successfully deleted port mapping') - else: - print('Failed to remove port mapping') - else: - print('Failed') - - httpd.server_close() - -except Exception as e: - print('Exception :', e) diff --git a/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.c b/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.c deleted file mode 100644 index bfe5f0d..0000000 --- a/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.c +++ /dev/null @@ -1,115 +0,0 @@ -/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include "upnpreplyparse.h" - -int -test_parsing(const char * buf, int len, FILE * f) -{ - char line[1024]; - struct NameValueParserData pdata; - int ok = 1; - ParseNameValue(buf, len, &pdata); - /* check result */ - if(f != NULL) - { - while(fgets(line, sizeof(line), f)) - { - char * value; - char * equal; - char * parsedvalue; - int l; - l = strlen(line); - while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n'))) - line[--l] = '\0'; - /* skip empty lines */ - if(l == 0) - continue; - equal = strchr(line, '='); - if(equal == NULL) - { - fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); - continue; - } - *equal = '\0'; - value = equal + 1; - parsedvalue = GetValueFromNameValueList(&pdata, line); - if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0)) - { - fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n", - line, value, parsedvalue ? parsedvalue : ""); - ok = 0; - } - } - } - ClearNameValueList(&pdata); - return ok; -} - -int main(int argc, char * * argv) -{ - FILE * f; - char * buffer; - long l; - int ok; - - if(argc<2) - { - fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]); - return 1; - } - f = fopen(argv[1], "r"); - if(!f) - { - fprintf(stderr, "Error : can not open file %s\n", argv[1]); - return 2; - } - if(fseek(f, 0, SEEK_END) < 0) { - perror("fseek"); - return 1; - } - l = (int)ftell(f); - if(l < 0) { - perror("ftell"); - return 1; - } - if(fseek(f, 0, SEEK_SET) < 0) { - perror("fseek"); - return 1; - } - buffer = malloc(l + 1); - if(buffer == NULL) { - fprintf(stderr, "Error: failed to allocate %ld bytes\n", l+1); - return 1; - } - l = fread(buffer, 1, l, f); - fclose(f); - f = NULL; - buffer[l] = '\0'; - if(argc > 2) - { - f = fopen(argv[2], "r"); - if(!f) - { - fprintf(stderr, "Error : can not open file %s\n", argv[2]); - return 2; - } - } -#ifdef DEBUG - DisplayNameValueList(buffer, l); -#endif - ok = test_parsing(buffer, l, f); - if(f) - { - fclose(f); - } - free(buffer); - return ok ? 0 : 3; -} - diff --git a/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.sh b/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.sh deleted file mode 100644 index 992930b..0000000 --- a/src/contrib/miniupnp/miniupnpc/testupnpreplyparse.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -for f in testreplyparse/*.xml ; do - bf="`dirname $f`/`basename $f .xml`" - if ./testupnpreplyparse $f $bf.namevalue ; then - echo "$f : passed" - else - echo "$f : FAILED" - exit 1 - fi -done - -exit 0 - diff --git a/src/contrib/miniupnp/miniupnpc/updateminiupnpcstrings.sh b/src/contrib/miniupnp/miniupnpc/updateminiupnpcstrings.sh deleted file mode 100644 index dde4354..0000000 --- a/src/contrib/miniupnp/miniupnpc/updateminiupnpcstrings.sh +++ /dev/null @@ -1,53 +0,0 @@ -#! /bin/sh -# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $ -# project miniupnp : http://miniupnp.free.fr/ -# (c) 2009 Thomas Bernard - -FILE=miniupnpcstrings.h -TMPFILE=miniupnpcstrings.h.tmp -TEMPLATE_FILE=${FILE}.in - -# detecting the OS name and version -OS_NAME=`uname -s` -OS_VERSION=`uname -r` -if [ -f /etc/debian_version ]; then - OS_NAME=Debian - OS_VERSION=`cat /etc/debian_version` -fi -# use lsb_release (Linux Standard Base) when available -LSB_RELEASE=`which lsb_release` -if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then - OS_NAME=`${LSB_RELEASE} -i -s` - OS_VERSION=`${LSB_RELEASE} -r -s` - case $OS_NAME in - Debian) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - Ubuntu) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - esac -fi - -# on AmigaOS 3, uname -r returns "unknown", so we use uname -v -if [ "$OS_NAME" = "AmigaOS" ]; then - if [ "$OS_VERSION" = "unknown" ]; then - OS_VERSION=`uname -v` - fi -fi - -echo "Detected OS [$OS_NAME] version [$OS_VERSION]" -MINIUPNPC_VERSION=`cat VERSION` -echo "MiniUPnPc version [${MINIUPNPC_VERSION}]" - -EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|" -#echo $EXPR -test -f ${FILE}.in -echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE." -sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE - -EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|" -echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE." -sed -e "$EXPR" < $TMPFILE > $FILE -rm $TMPFILE - diff --git a/src/contrib/miniupnp/miniupnpc/upnpc.c b/src/contrib/miniupnp/miniupnpc/upnpc.c deleted file mode 100644 index 0c65cbe..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpc.c +++ /dev/null @@ -1,861 +0,0 @@ -/* $Id: upnpc.c,v 1.119 2018/03/13 23:34:46 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#include -#include -#ifdef _WIN32 -#include -#define snprintf _snprintf -#else -/* for IPPROTO_TCP / IPPROTO_UDP */ -#include -#endif -#include -#include "miniwget.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "portlistingparse.h" -#include "upnperrors.h" -#include "miniupnpcstrings.h" - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto) -{ - static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; - static const char proto_udp[4] = { 'U', 'D', 'P', 0}; - int i, b; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_tcp[i]) - || (proto[i] == (proto_tcp[i] | 32)) ); - if(b) - return proto_tcp; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_udp[i]) - || (proto[i] == (proto_udp[i] | 32)) ); - if(b) - return proto_udp; - return 0; -} - -/* is_int() checks if parameter is an integer or not - * 1 for integer - * 0 for not an integer */ -int is_int(char const* s) -{ - if(s == NULL) - return 0; - while(*s) { - /* #define isdigit(c) ((c) >= '0' && (c) <= '9') */ - if(!isdigit(*s)) - return 0; - s++; - } - return 1; -} - -static void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - char externalIPAddress[40]; - char connectionType[64]; - char status[64]; - char lastconnerr[64]; - unsigned int uptime = 0; - unsigned int brUp, brDown; - time_t timenow, timestarted; - int r; - if(UPNP_GetConnectionTypeInfo(urls->controlURL, - data->first.servicetype, - connectionType) != UPNPCOMMAND_SUCCESS) - printf("GetConnectionTypeInfo failed.\n"); - else - printf("Connection Type : %s\n", connectionType); - if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, - status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) - printf("GetStatusInfo failed.\n"); - else - printf("Status : %s, uptime=%us, LastConnectionError : %s\n", - status, uptime, lastconnerr); - if(uptime > 0) { - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); - } - if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, - &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { - printf("GetLinkLayerMaxBitRates failed.\n"); - } else { - printf("MaxBitRateDown : %u bps", brDown); - if(brDown >= 1000000) { - printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); - } else if(brDown >= 1000) { - printf(" (%u Kbps)", brDown / 1000); - } - printf(" MaxBitRateUp %u bps", brUp); - if(brUp >= 1000000) { - printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); - } else if(brUp >= 1000) { - printf(" (%u Kbps)", brUp / 1000); - } - printf("\n"); - } - r = UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) { - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - } else { - printf("ExternalIPAddress = %s\n", externalIPAddress); - } -} - -static void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - DisplayInfos(urls, data); - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -static void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - char index[6]; - char intClient[40]; - char intPort[6]; - char extPort[6]; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; - /*unsigned int num=0; - UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); - printf("PortMappingNumberOfEntries : %u\n", num);*/ - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - do { - snprintf(index, 6, "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(urls->controlURL, - data->first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, - rHost, duration); - if(r==0) - /* - printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" - " desc='%s' rHost='%s'\n", - i, protocol, extPort, intClient, intPort, - enabled, duration, - desc, rHost); - */ - printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", - i, protocol, extPort, intClient, intPort, - desc, rHost, duration); - else - printf("GetGenericPortMappingEntry() returned %d (%s)\n", - r, strupnperror(r)); - i++; - } while(r==0); -} - -static void NewListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - struct PortMappingParserData pdata; - struct PortMapping * pm; - - memset(&pdata, 0, sizeof(struct PortMappingParserData)); - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "TCP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "UDP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } -} - -/* Test function - * 1 - get connection type - * 2 - get extenal ip address - * 3 - Add port mapping - * 4 - get this port mapping from the IGD */ -static int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char * leaseDuration, - const char * description, - int addAny) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char reservedPort[6]; - char duration[16]; - int r; - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return -1; - } - - r = UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetExternalIPAddress failed.\n"); - else - printf("ExternalIPAddress = %s\n", externalIPAddress); - - if (addAny) { - r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration, reservedPort); - if(r==UPNPCOMMAND_SUCCESS) - eport = reservedPort; - else - printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - } else { - r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - return -2; - } - } - - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - return -2; - } else { - printf("InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - return 0; -} - -static int -RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto, - const char * remoteHost) -{ - int r; - if(!proto || !eport) - { - fprintf(stderr, "invalid arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return -1; - } - r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMapping() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMapping() returned : %d\n", r); - } - return 0; -} - -static int -RemoveRedirectRange(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * ePortStart, char const * ePortEnd, - const char * proto, const char * manage) -{ - int r; - - if (!manage) - manage = "0"; - - if(!proto || !ePortStart || !ePortEnd) - { - fprintf(stderr, "invalid arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return -1; - } - r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMappingRange() returned : %d\n", r); - } - return 0; -} - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - int firewallEnabled = 0, inboundPinholeAllowed = 0; - - UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); - printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); - printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); - - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -/* Test function - * 1 - Add pinhole - * 2 - Check if pinhole is working from the IGD side */ -static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto, const char * lease_time) -{ - char uniqueID[8]; - /*int isWorking = 0;*/ - int r; - char proto_tmp[8]; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - if(atoi(proto) == 0) - { - const char * protocol; - protocol = protofix(proto); - if(protocol && (strcmp("TCP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP); - proto = proto_tmp; - } - else if(protocol && (strcmp("UDP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP); - proto = proto_tmp; - } - else - { - fprintf(stderr, "invalid protocol\n"); - return; - } - } - r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); - if(r!=UPNPCOMMAND_SUCCESS) - printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - remoteaddr, eport, intaddr, iport, r, strupnperror(r)); - else - { - printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", - remoteaddr, eport, intaddr, iport, uniqueID); - /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ - } -} - -/* Test function - * 1 - Check if pinhole is working from the IGD side - * 2 - Update pinhole */ -static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, - const char * uniqueID, const char * lease_time) -{ - int isWorking = 0; - int r; - - if(!uniqueID || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - if(isWorking || r==709) - { - r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); - printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); - if(r!=UPNPCOMMAND_SUCCESS) - printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); - } -} - -/* Test function - * Get pinhole timeout - */ -static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto) -{ - int timeout = 0; - int r; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - - r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - intaddr, iport, remoteaddr, eport, r, strupnperror(r)); - else - printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); -} - -static void -GetPinholePackets(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, pinholePackets = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); -} - -static void -CheckPinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, isWorking = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); -} - -static void -RemovePinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); - printf("UPNP_DeletePinhole() returned : %d\n", r); -} - - -/* sample upnp client program */ -int main(int argc, char ** argv) -{ - char command = 0; - char ** commandargv = 0; - int commandargc = 0; - struct UPNPDev * devlist = 0; - char lanaddr[64] = "unset"; /* my ip address on the LAN */ - int i; - const char * rootdescurl = 0; - const char * multicastif = 0; - const char * minissdpdpath = 0; - int localport = UPNP_LOCAL_PORT_ANY; - int retcode = 0; - int error = 0; - int ipv6 = 0; - unsigned char ttl = 2; /* defaulting to 2 */ - const char * description = 0; - -#ifdef _WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING); - printf(" (c) 2005-2018 Thomas Bernard.\n"); - printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n" - "for more information.\n"); - /* command line processing */ - for(i=1; i65535 || - (localport >1 && localport < 1024)) - { - fprintf(stderr, "Invalid localport '%s'\n", argv[i]); - localport = UPNP_LOCAL_PORT_ANY; - break; - } - } - else if(argv[i][1] == 'p') - minissdpdpath = argv[++i]; - else if(argv[i][1] == '6') - ipv6 = 1; - else if(argv[i][1] == 'e') - description = argv[++i]; - else if(argv[i][1] == 't') - ttl = (unsigned char)atoi(argv[++i]); - else - { - command = argv[i][1]; - i++; - commandargv = argv + i; - commandargc = argc - i; - break; - } - } - else - { - fprintf(stderr, "option '%s' invalid\n", argv[i]); - } - } - - if(!command - || (command == 'a' && commandargc<4) - || (command == 'd' && argc<2) - || (command == 'r' && argc<2) - || (command == 'A' && commandargc<6) - || (command == 'U' && commandargc<2) - || (command == 'D' && commandargc<1)) - { - fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]); - fprintf(stderr, " \t%s [options] -d external_port protocol \n\t\tDelete port redirection\n", argv[0]); - fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); - fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); - fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); - fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); - fprintf(stderr, "\nprotocol is UDP or TCP\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -e description : set description for port mapping.\n"); - fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); - fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); - fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); - fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n"); - fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); - fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n"); - return 1; - } - - if( rootdescurl - || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, - localport, ipv6, ttl, &error))) - { - struct UPNPDev * device; - struct UPNPUrls urls; - struct IGDdatas data; - if(devlist) - { - printf("List of UPNP devices found on the network :\n"); - for(device = devlist; device; device = device->pNext) - { - printf(" desc: %s\n st: %s\n\n", - device->descURL, device->st); - } - } - else if(!rootdescurl) - { - printf("upnpDiscover() error code=%d\n", error); - } - i = 1; - if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) - || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) - { - switch(i) { - case 1: - printf("Found valid IGD : %s\n", urls.controlURL); - break; - case 2: - printf("Found a (not connected?) IGD : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - case 3: - printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - default: - printf("Found device (igd ?) : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - } - printf("Local LAN ip address : %s\n", lanaddr); - #if 0 - printf("getting \"%s\"\n", urls.ipcondescURL); - descXML = miniwget(urls.ipcondescURL, &descXMLsize); - if(descXML) - { - /*fwrite(descXML, 1, descXMLsize, stdout);*/ - free(descXML); descXML = NULL; - } - #endif - - switch(command) - { - case 'l': - DisplayInfos(&urls, &data); - ListRedirections(&urls, &data); - break; - case 'L': - NewListRedirections(&urls, &data); - break; - case 'a': - if (SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)?commandargv[4]:"0", - description, 0) < 0) - retcode = 2; - break; - case 'd': - if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], - commandargc > 2 ? commandargv[2] : NULL) < 0) - retcode = 2; - break; - case 'n': /* aNy */ - if (SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)?commandargv[4]:"0", - description, 1) < 0) - retcode = 2; - break; - case 'N': - if (commandargc < 3) - fprintf(stderr, "too few arguments\n"); - - if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], - commandargc > 3 ? commandargv[3] : NULL) < 0) - retcode = 2; - break; - case 's': - GetConnectionStatus(&urls, &data); - break; - case 'r': - i = 0; - while(i */ - if (SetRedirectAndTest(&urls, &data, - lanaddr, commandargv[i], - commandargv[i+1], commandargv[i+2], "0", - description, 0) < 0) - retcode = 2; - i+=3; /* 3 parameters parsed */ - } else { - /* 2nd parameter not an integer : */ - if (SetRedirectAndTest(&urls, &data, - lanaddr, commandargv[i], - commandargv[i], commandargv[i+1], "0", - description, 0) < 0) - retcode = 2; - i+=2; /* 2 parameters parsed */ - } - } - break; - case 'A': - SetPinholeAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - commandargv[4], commandargv[5]); - break; - case 'U': - GetPinholeAndUpdate(&urls, &data, - commandargv[0], commandargv[1]); - break; - case 'C': - for(i=0; i -#include -#include -#include "upnpcommands.h" -#include "miniupnpc.h" -#include "portlistingparse.h" -#include "upnpreplyparse.h" - -static UNSIGNED_INTEGER -my_atoui(const char * s) -{ - return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0; -} - -/* - * */ -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesSent(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalBytesSent", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesReceived(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalBytesReceived", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsSent(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalPacketsSent", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsReceived(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalPacketsReceived", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* UPNP_GetStatusInfo() call the corresponding UPNP method - * returns the current status and uptime */ -MINIUPNP_LIBSPEC int -UPNP_GetStatusInfo(const char * controlURL, - const char * servicetype, - char * status, - unsigned int * uptime, - char * lastconnerror) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - char * up; - char * err; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!status && !uptime) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetStatusInfo", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - up = GetValueFromNameValueList(&pdata, "NewUptime"); - p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); - err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); - if(p && up) - ret = UPNPCOMMAND_SUCCESS; - - if(status) { - if(p){ - strncpy(status, p, 64 ); - status[63] = '\0'; - }else - status[0]= '\0'; - } - - if(uptime) { - if(up) - sscanf(up,"%u",uptime); - else - *uptime = 0; - } - - if(lastconnerror) { - if(err) { - strncpy(lastconnerror, err, 64 ); - lastconnerror[63] = '\0'; - } else - lastconnerror[0] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method - * returns the connection type */ -MINIUPNP_LIBSPEC int -UPNP_GetConnectionTypeInfo(const char * controlURL, - const char * servicetype, - char * connectionType) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!connectionType) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetConnectionTypeInfo", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewConnectionType"); - /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ - /* PossibleConnectionTypes will have several values.... */ - if(p) { - strncpy(connectionType, p, 64 ); - connectionType[63] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - connectionType[0] = '\0'; - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method. - * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth. - * One of the values can be null - * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only - * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ -MINIUPNP_LIBSPEC int -UPNP_GetLinkLayerMaxBitRates(const char * controlURL, - const char * servicetype, - unsigned int * bitrateDown, - unsigned int * bitrateUp) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - char * down; - char * up; - char * p; - - if(!bitrateDown && !bitrateUp) - return UPNPCOMMAND_INVALID_ARGS; - - /* shouldn't we use GetCommonLinkProperties ? */ - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetCommonLinkProperties", 0, &bufsize))) { - /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/ - /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/ - down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate"); - up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate"); - /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/ - /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/ - if(down && up) - ret = UPNPCOMMAND_SUCCESS; - - if(bitrateDown) { - if(down) - sscanf(down,"%u",bitrateDown); - else - *bitrateDown = 0; - } - - if(bitrateUp) { - if(up) - sscanf(up,"%u",bitrateUp); - else - *bitrateUp = 0; - } - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - - -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - */ -MINIUPNP_LIBSPEC int -UPNP_GetExternalIPAddress(const char * controlURL, - const char * servicetype, - char * extIpAdd) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!extIpAdd || !controlURL || !servicetype) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetExternalIPAddress", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ - p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); - if(p) { - strncpy(extIpAdd, p, 16 ); - extIpAdd[15] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - extIpAdd[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration) -{ - struct UPNParg * AddPortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!inPort || !inClient || !proto || !extPort) - return UPNPCOMMAND_INVALID_ARGS; - - AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); - if(AddPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - AddPortMappingArgs[0].elt = "NewRemoteHost"; - AddPortMappingArgs[0].val = remoteHost; - AddPortMappingArgs[1].elt = "NewExternalPort"; - AddPortMappingArgs[1].val = extPort; - AddPortMappingArgs[2].elt = "NewProtocol"; - AddPortMappingArgs[2].val = proto; - AddPortMappingArgs[3].elt = "NewInternalPort"; - AddPortMappingArgs[3].val = inPort; - AddPortMappingArgs[4].elt = "NewInternalClient"; - AddPortMappingArgs[4].val = inClient; - AddPortMappingArgs[5].elt = "NewEnabled"; - AddPortMappingArgs[5].val = "1"; - AddPortMappingArgs[6].elt = "NewPortMappingDescription"; - AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; - AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddPortMapping", AddPortMappingArgs, - &bufsize); - free(AddPortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - /*buffer[bufsize] = '\0';*/ - /*puts(buffer);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration, - char * reservedPort) -{ - struct UPNParg * AddPortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!inPort || !inClient || !proto || !extPort) - return UPNPCOMMAND_INVALID_ARGS; - - AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); - if(AddPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - AddPortMappingArgs[0].elt = "NewRemoteHost"; - AddPortMappingArgs[0].val = remoteHost; - AddPortMappingArgs[1].elt = "NewExternalPort"; - AddPortMappingArgs[1].val = extPort; - AddPortMappingArgs[2].elt = "NewProtocol"; - AddPortMappingArgs[2].val = proto; - AddPortMappingArgs[3].elt = "NewInternalPort"; - AddPortMappingArgs[3].val = inPort; - AddPortMappingArgs[4].elt = "NewInternalClient"; - AddPortMappingArgs[4].val = inClient; - AddPortMappingArgs[5].elt = "NewEnabled"; - AddPortMappingArgs[5].val = "1"; - AddPortMappingArgs[6].elt = "NewPortMappingDescription"; - AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; - AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddAnyPortMapping", AddPortMappingArgs, - &bufsize); - free(AddPortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - char *p; - - p = GetValueFromNameValueList(&pdata, "NewReservedPort"); - if(p) { - strncpy(reservedPort, p, 6); - reservedPort[5] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else { - ret = UPNPCOMMAND_INVALID_RESPONSE; - } - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost) -{ - /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!extPort || !proto) - return UPNPCOMMAND_INVALID_ARGS; - - DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); - if(DeletePortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePortMappingArgs[0].elt = "NewRemoteHost"; - DeletePortMappingArgs[0].val = remoteHost; - DeletePortMappingArgs[1].elt = "NewExternalPort"; - DeletePortMappingArgs[1].val = extPort; - DeletePortMappingArgs[2].elt = "NewProtocol"; - DeletePortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMapping", - DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, - const char * extPortStart, const char * extPortEnd, - const char * proto, - const char * manage) -{ - struct UPNParg * DeletePortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!extPortStart || !extPortEnd || !proto || !manage) - return UPNPCOMMAND_INVALID_ARGS; - - DeletePortMappingArgs = calloc(5, sizeof(struct UPNParg)); - if(DeletePortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePortMappingArgs[0].elt = "NewStartPort"; - DeletePortMappingArgs[0].val = extPortStart; - DeletePortMappingArgs[1].elt = "NewEndPort"; - DeletePortMappingArgs[1].val = extPortEnd; - DeletePortMappingArgs[2].elt = "NewProtocol"; - DeletePortMappingArgs[2].val = proto; - DeletePortMappingArgs[3].elt = "NewManage"; - DeletePortMappingArgs[3].val = manage; - - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMappingRange", - DeletePortMappingArgs, &bufsize); - free(DeletePortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_GetGenericPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; - char * buffer; - int bufsize; - char * p; - int r = UPNPCOMMAND_UNKNOWN_ERROR; - if(!index) - return UPNPCOMMAND_INVALID_ARGS; - intClient[0] = '\0'; - intPort[0] = '\0'; - GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); - if(GetPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPortMappingArgs[0].elt = "NewPortMappingIndex"; - GetPortMappingArgs[0].val = index; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetGenericPortMappingEntry", - GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); - if(p && rHost) - { - strncpy(rHost, p, 64); - rHost[63] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewExternalPort"); - if(p && extPort) - { - strncpy(extPort, p, 6); - extPort[5] = '\0'; - r = UPNPCOMMAND_SUCCESS; - } - p = GetValueFromNameValueList(&pdata, "NewProtocol"); - if(p && protocol) - { - strncpy(protocol, p, 4); - protocol[3] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewInternalClient"); - if(p) - { - strncpy(intClient, p, 16); - intClient[15] = '\0'; - r = 0; - } - p = GetValueFromNameValueList(&pdata, "NewInternalPort"); - if(p) - { - strncpy(intPort, p, 6); - intPort[5] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewEnabled"); - if(p && enabled) - { - strncpy(enabled, p, 4); - enabled[3] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); - if(p && desc) - { - strncpy(desc, p, 80); - desc[79] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); - if(p && duration) - { - strncpy(duration, p, 16); - duration[15] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - r = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &r); - } - ClearNameValueList(&pdata); - return r; -} - -MINIUPNP_LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char * controlURL, - const char * servicetype, - unsigned int * numEntries) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char* p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetPortMappingNumberOfEntries", 0, - &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } -#ifdef DEBUG - DisplayNameValueList(buffer, bufsize); -#endif - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); - if(numEntries && p) { - *numEntries = 0; - sscanf(p, "%u", numEntries); - ret = UPNPCOMMAND_SUCCESS; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping - * the result is returned in the intClient and intPort strings - * please provide 16 and 6 bytes of data */ -MINIUPNP_LIBSPEC int -UPNP_GetSpecificPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * extPort, - const char * proto, - const char * remoteHost, - char * intClient, - char * intPort, - char * desc, - char * enabled, - char * leaseDuration) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!intPort || !intClient || !extPort || !proto) - return UPNPCOMMAND_INVALID_ARGS; - - GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); - if(GetPortMappingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPortMappingArgs[0].elt = "NewRemoteHost"; - GetPortMappingArgs[0].val = remoteHost; - GetPortMappingArgs[1].elt = "NewExternalPort"; - GetPortMappingArgs[1].val = extPort; - GetPortMappingArgs[2].elt = "NewProtocol"; - GetPortMappingArgs[2].val = proto; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetSpecificPortMappingEntry", - GetPortMappingArgs, &bufsize); - free(GetPortMappingArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewInternalClient"); - if(p) { - strncpy(intClient, p, 16); - intClient[15] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - intClient[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "NewInternalPort"); - if(p) { - strncpy(intPort, p, 6); - intPort[5] = '\0'; - } else - intPort[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "NewEnabled"); - if(p && enabled) { - strncpy(enabled, p, 4); - enabled[3] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); - if(p && desc) { - strncpy(desc, p, 80); - desc[79] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); - if(p && leaseDuration) - { - strncpy(leaseDuration, p, 16); - leaseDuration[15] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetListOfPortMappings() - * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. - */ -MINIUPNP_LIBSPEC int -UPNP_GetListOfPortMappings(const char * controlURL, - const char * servicetype, - const char * startPort, - const char * endPort, - const char * protocol, - const char * numberOfPorts, - struct PortMappingParserData * data) -{ - struct NameValueParserData pdata; - struct UPNParg * GetListOfPortMappingsArgs; - const char * p; - char * buffer; - int bufsize; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!startPort || !endPort || !protocol) - return UPNPCOMMAND_INVALID_ARGS; - - GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); - if(GetListOfPortMappingsArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetListOfPortMappingsArgs[0].elt = "NewStartPort"; - GetListOfPortMappingsArgs[0].val = startPort; - GetListOfPortMappingsArgs[1].elt = "NewEndPort"; - GetListOfPortMappingsArgs[1].val = endPort; - GetListOfPortMappingsArgs[2].elt = "NewProtocol"; - GetListOfPortMappingsArgs[2].val = protocol; - GetListOfPortMappingsArgs[3].elt = "NewManage"; - GetListOfPortMappingsArgs[3].val = "1"; - GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; - GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; - - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetListOfPortMappings", - GetListOfPortMappingsArgs, &bufsize); - free(GetListOfPortMappingsArgs); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ - /*if(p) { - printf("NewPortListing : %s\n", p); - }*/ - /*printf("NewPortListing(%d chars) : %s\n", - pdata.portListingLength, pdata.portListing);*/ - if(pdata.portListing) - { - /*struct PortMapping * pm; - int i = 0;*/ - ParsePortListing(pdata.portListing, pdata.portListingLength, - data); - ret = UPNPCOMMAND_SUCCESS; - /* - for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost); - i++; - } - */ - /*FreePortListing(&data);*/ - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - - /*printf("%.*s", bufsize, buffer);*/ - - return ret; -} - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -MINIUPNP_LIBSPEC int -UPNP_GetFirewallStatus(const char * controlURL, - const char * servicetype, - int * firewallEnabled, - int * inboundPinholeAllowed) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * fe, *ipa, *p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!firewallEnabled || !inboundPinholeAllowed) - return UPNPCOMMAND_INVALID_ARGS; - - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetFirewallStatus", 0, &bufsize); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - fe = GetValueFromNameValueList(&pdata, "FirewallEnabled"); - ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed"); - if(ipa && fe) - ret = UPNPCOMMAND_SUCCESS; - if(fe) - *firewallEnabled = my_atoui(fe); - /*else - *firewallEnabled = 0;*/ - if(ipa) - *inboundPinholeAllowed = my_atoui(ipa); - /*else - *inboundPinholeAllowed = 0;*/ - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - int * opTimeout) -{ - struct UPNParg * GetOutboundPinholeTimeoutArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - char * p; - int ret; - - if(!intPort || !intClient || !proto || !remotePort || !remoteHost) - return UPNPCOMMAND_INVALID_ARGS; - - GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); - if(GetOutboundPinholeTimeoutArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; - GetOutboundPinholeTimeoutArgs[0].val = remoteHost; - GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; - GetOutboundPinholeTimeoutArgs[1].val = remotePort; - GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; - GetOutboundPinholeTimeoutArgs[2].val = proto; - GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; - GetOutboundPinholeTimeoutArgs[3].val = intPort; - GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; - GetOutboundPinholeTimeoutArgs[4].val = intClient; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); - free(GetOutboundPinholeTimeoutArgs); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout"); - if(p) - *opTimeout = my_atoui(p); - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_AddPinhole(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - const char * leaseTime, - char * uniqueID) -{ - struct UPNParg * AddPinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - char * p; - int ret; - - if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) - return UPNPCOMMAND_INVALID_ARGS; - - AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); - if(AddPinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - /* RemoteHost can be wilcarded */ - if(strncmp(remoteHost, "empty", 5)==0) - { - AddPinholeArgs[0].elt = "RemoteHost"; - AddPinholeArgs[0].val = ""; - } - else - { - AddPinholeArgs[0].elt = "RemoteHost"; - AddPinholeArgs[0].val = remoteHost; - } - AddPinholeArgs[1].elt = "RemotePort"; - AddPinholeArgs[1].val = remotePort; - AddPinholeArgs[2].elt = "Protocol"; - AddPinholeArgs[2].val = proto; - AddPinholeArgs[3].elt = "InternalPort"; - AddPinholeArgs[3].val = intPort; - if(strncmp(intClient, "empty", 5)==0) - { - AddPinholeArgs[4].elt = "InternalClient"; - AddPinholeArgs[4].val = ""; - } - else - { - AddPinholeArgs[4].elt = "InternalClient"; - AddPinholeArgs[4].val = intClient; - } - AddPinholeArgs[5].elt = "LeaseTime"; - AddPinholeArgs[5].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddPinhole", AddPinholeArgs, &bufsize); - free(AddPinholeArgs); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "UniqueID"); - if(p) - { - strncpy(uniqueID, p, 8); - uniqueID[7] = '\0'; - } - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, - const char * uniqueID, - const char * leaseTime) -{ - struct UPNParg * UpdatePinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!uniqueID || !leaseTime) - return UPNPCOMMAND_INVALID_ARGS; - - UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); - if(UpdatePinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - UpdatePinholeArgs[0].elt = "UniqueID"; - UpdatePinholeArgs[0].val = uniqueID; - UpdatePinholeArgs[1].elt = "NewLeaseTime"; - UpdatePinholeArgs[1].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "UpdatePinhole", UpdatePinholeArgs, &bufsize); - free(UpdatePinholeArgs); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) -{ - /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); - if(DeletePinholeArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - DeletePinholeArgs[0].elt = "UniqueID"; - DeletePinholeArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePinhole", DeletePinholeArgs, &bufsize); - free(DeletePinholeArgs); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, - const char * uniqueID, int * isWorking) -{ - struct NameValueParserData pdata; - struct UPNParg * CheckPinholeWorkingArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); - if(CheckPinholeWorkingArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - CheckPinholeWorkingArgs[0].elt = "UniqueID"; - CheckPinholeWorkingArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); - free(CheckPinholeWorkingArgs); - if(!buffer) - { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "IsWorking"); - if(p) - { - *isWorking=my_atoui(p); - ret = UPNPCOMMAND_SUCCESS; - } - else - *isWorking = 0; - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -MINIUPNP_LIBSPEC int -UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, - const char * uniqueID, int * packets) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPinholePacketsArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); - if(GetPinholePacketsArgs == NULL) - return UPNPCOMMAND_MEM_ALLOC_ERROR; - GetPinholePacketsArgs[0].elt = "UniqueID"; - GetPinholePacketsArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetPinholePackets", GetPinholePacketsArgs, &bufsize); - free(GetPinholePacketsArgs); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "PinholePackets"); - if(p) - { - *packets=my_atoui(p); - ret = UPNPCOMMAND_SUCCESS; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - - diff --git a/src/contrib/miniupnp/miniupnpc/upnpcommands.h b/src/contrib/miniupnp/miniupnpc/upnpcommands.h deleted file mode 100644 index 0c6d501..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpcommands.h +++ /dev/null @@ -1,348 +0,0 @@ -/* $Id: upnpcommands.h,v 1.32 2018/03/13 23:34:47 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef UPNPCOMMANDS_H_INCLUDED -#define UPNPCOMMANDS_H_INCLUDED - -#include "miniupnpc_declspec.h" -#include "miniupnpctypes.h" - -/* MiniUPnPc return codes : */ -#define UPNPCOMMAND_SUCCESS (0) -#define UPNPCOMMAND_UNKNOWN_ERROR (-1) -#define UPNPCOMMAND_INVALID_ARGS (-2) -#define UPNPCOMMAND_HTTP_ERROR (-3) -#define UPNPCOMMAND_INVALID_RESPONSE (-4) -#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) - -#ifdef __cplusplus -extern "C" { -#endif - -struct PortMappingParserData; - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesSent(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesReceived(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsSent(const char * controlURL, - const char * servicetype); - -MINIUPNP_LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsReceived(const char * controlURL, - const char * servicetype); - -/* UPNP_GetStatusInfo() - * status and lastconnerror are 64 byte buffers - * Return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -MINIUPNP_LIBSPEC int -UPNP_GetStatusInfo(const char * controlURL, - const char * servicetype, - char * status, - unsigned int * uptime, - char * lastconnerror); - -/* UPNP_GetConnectionTypeInfo() - * argument connectionType is a 64 character buffer - * Return Values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -MINIUPNP_LIBSPEC int -UPNP_GetConnectionTypeInfo(const char * controlURL, - const char * servicetype, - char * connectionType); - -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * - * possible UPnP Errors : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. */ -MINIUPNP_LIBSPEC int -UPNP_GetExternalIPAddress(const char * controlURL, - const char * servicetype, - char * extIpAdd); - -/* UPNP_GetLinkLayerMaxBitRates() - * call WANCommonInterfaceConfig:1#GetCommonLinkProperties - * - * return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ -MINIUPNP_LIBSPEC int -UPNP_GetLinkLayerMaxBitRates(const char* controlURL, - const char* servicetype, - unsigned int * bitrateDown, - unsigned int * bitrateUp); - -/* UPNP_AddPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * - * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 718 ConflictInMappingEntry - The port mapping entry specified conflicts - * with a mapping assigned previously to another client - * 724 SamePortValuesRequired - Internal and External port values - * must be the same - * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports - * permanent lease times on port mappings - * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard - * and cannot be a specific IP address or DNS name - * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded - */ -MINIUPNP_LIBSPEC int -UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration); - -/* UPNP_AddAnyPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * - * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded - */ -MINIUPNP_LIBSPEC int -UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration, - char * reservedPort); - -/* UPNP_DeletePortMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. - * - * List of possible UPnP errors for DeletePortMapping : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array */ -MINIUPNP_LIBSPEC int -UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost); - -/* UPNP_DeletePortRangeMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. - * - * List of possible UPnP errors for DeletePortMapping : - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 730 PortMappingNotFound - This error message is returned if no port - * mapping is found in the specified range. - * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ -MINIUPNP_LIBSPEC int -UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, - const char * extPortStart, const char * extPortEnd, - const char * proto, - const char * manage); - -/* UPNP_GetPortMappingNumberOfEntries() - * not supported by all routers */ -MINIUPNP_LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char* controlURL, - const char* servicetype, - unsigned int * num); - -/* UPNP_GetSpecificPortMappingEntry() - * retrieves an existing port mapping - * params : - * in extPort - * in proto - * in remoteHost - * out intClient (16 bytes) - * out intPort (6 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out leaseDuration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * List of possible UPnP errors for _GetSpecificPortMappingEntry : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array. - */ -MINIUPNP_LIBSPEC int -UPNP_GetSpecificPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * extPort, - const char * proto, - const char * remoteHost, - char * intClient, - char * intPort, - char * desc, - char * enabled, - char * leaseDuration); - -/* UPNP_GetGenericPortMappingEntry() - * params : - * in index - * out extPort (6 bytes) - * out intClient (16 bytes) - * out intPort (6 bytes) - * out protocol (4 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out rHost (64 bytes) - * out duration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * Possible UPNP Error codes : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds - */ -MINIUPNP_LIBSPEC int -UPNP_GetGenericPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration); - -/* UPNP_GetListOfPortMappings() Available in IGD v2 - * - * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. - */ -MINIUPNP_LIBSPEC int -UPNP_GetListOfPortMappings(const char * controlURL, - const char * servicetype, - const char * startPort, - const char * endPort, - const char * protocol, - const char * numberOfPorts, - struct PortMappingParserData * data); - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -MINIUPNP_LIBSPEC int -UPNP_GetFirewallStatus(const char * controlURL, - const char * servicetype, - int * firewallEnabled, - int * inboundPinholeAllowed); - -MINIUPNP_LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - int * opTimeout); - -MINIUPNP_LIBSPEC int -UPNP_AddPinhole(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - const char * leaseTime, - char * uniqueID); - -MINIUPNP_LIBSPEC int -UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, - const char * uniqueID, - const char * leaseTime); - -MINIUPNP_LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); - -MINIUPNP_LIBSPEC int -UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, - const char * uniqueID, int * isWorking); - -MINIUPNP_LIBSPEC int -UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, - const char * uniqueID, int * packets); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/upnpdev.c b/src/contrib/miniupnp/miniupnpc/upnpdev.c deleted file mode 100644 index d89a993..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpdev.c +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: upnpdev.c,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ -/* Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2015 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENSE file. */ -#include -#include "upnpdev.h" - -/* freeUPNPDevlist() should be used to - * free the chained list returned by upnpDiscover() */ -void freeUPNPDevlist(struct UPNPDev * devlist) -{ - struct UPNPDev * next; - while(devlist) - { - next = devlist->pNext; - free(devlist); - devlist = next; - } -} - diff --git a/src/contrib/miniupnp/miniupnpc/upnpdev.h b/src/contrib/miniupnp/miniupnpc/upnpdev.h deleted file mode 100644 index f4ae174..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpdev.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ -/* Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2018 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENSE file. */ -#ifndef UPNPDEV_H_INCLUDED -#define UPNPDEV_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct UPNPDev { - struct UPNPDev * pNext; - char * descURL; - char * st; - char * usn; - unsigned int scope_id; - char buffer[3]; -}; - -/* freeUPNPDevlist() - * free list returned by upnpDiscover() */ -MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); - - -#ifdef __cplusplus -} -#endif - - -#endif /* UPNPDEV_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpc/upnperrors.c b/src/contrib/miniupnp/miniupnpc/upnperrors.c deleted file mode 100644 index 40a2e78..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnperrors.c +++ /dev/null @@ -1,107 +0,0 @@ -/* $Id: upnperrors.c,v 1.5 2011/04/10 11:19:36 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2007 Thomas Bernard - * All Right reserved. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include -#include "upnperrors.h" -#include "upnpcommands.h" -#include "miniupnpc.h" - -const char * strupnperror(int err) -{ - const char * s = NULL; - switch(err) { - case UPNPCOMMAND_SUCCESS: - s = "Success"; - break; - case UPNPCOMMAND_UNKNOWN_ERROR: - s = "Miniupnpc Unknown Error"; - break; - case UPNPCOMMAND_INVALID_ARGS: - s = "Miniupnpc Invalid Arguments"; - break; - case UPNPCOMMAND_INVALID_RESPONSE: - s = "Miniupnpc Invalid response"; - break; - case UPNPDISCOVER_SOCKET_ERROR: - s = "Miniupnpc Socket error"; - break; - case UPNPDISCOVER_MEMORY_ERROR: - s = "Miniupnpc Memory allocation error"; - break; - case 401: - s = "Invalid Action"; - break; - case 402: - s = "Invalid Args"; - break; - case 501: - s = "Action Failed"; - break; - case 606: - s = "Action not authorized"; - break; - case 701: - s = "PinholeSpaceExhausted"; - break; - case 702: - s = "FirewallDisabled"; - break; - case 703: - s = "InboundPinholeNotAllowed"; - break; - case 704: - s = "NoSuchEntry"; - break; - case 705: - s = "ProtocolNotSupported"; - break; - case 706: - s = "InternalPortWildcardingNotAllowed"; - break; - case 707: - s = "ProtocolWildcardingNotAllowed"; - break; - case 708: - s = "WildcardNotPermittedInSrcIP"; - break; - case 709: - s = "NoPacketSent"; - break; - case 713: - s = "SpecifiedArrayIndexInvalid"; - break; - case 714: - s = "NoSuchEntryInArray"; - break; - case 715: - s = "WildCardNotPermittedInSrcIP"; - break; - case 716: - s = "WildCardNotPermittedInExtPort"; - break; - case 718: - s = "ConflictInMappingEntry"; - break; - case 724: - s = "SamePortValuesRequired"; - break; - case 725: - s = "OnlyPermanentLeasesSupported"; - break; - case 726: - s = "RemoteHostOnlySupportsWildcard"; - break; - case 727: - s = "ExternalPortOnlySupportsWildcard"; - break; - default: - s = "UnknownError"; - break; - } - return s; -} diff --git a/src/contrib/miniupnp/miniupnpc/upnperrors.h b/src/contrib/miniupnp/miniupnpc/upnperrors.h deleted file mode 100644 index 8499d9a..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnperrors.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */ -/* (c) 2007-2015 Thomas Bernard - * All rights reserved. - * MiniUPnP Project. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef UPNPERRORS_H_INCLUDED -#define UPNPERRORS_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* strupnperror() - * Return a string description of the UPnP error code - * or NULL for undefinded errors */ -MINIUPNP_LIBSPEC const char * strupnperror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/miniupnp/miniupnpc/upnpreplyparse.c b/src/contrib/miniupnp/miniupnpc/upnpreplyparse.c deleted file mode 100644 index 68a47c0..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpreplyparse.c +++ /dev/null @@ -1,196 +0,0 @@ -/* $Id: upnpreplyparse.c,v 1.19 2015/07/15 10:29:11 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "upnpreplyparse.h" -#include "minixml.h" - -static void -NameValueParserStartElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - data->topelt = 1; - if(l>63) - l = 63; - memcpy(data->curelt, name, l); - data->curelt[l] = '\0'; - data->cdata = NULL; - data->cdatalen = 0; -} - -static void -NameValueParserEndElt(void * d, const char * name, int namelen) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - (void)name; - (void)namelen; - if(!data->topelt) - return; - if(strcmp(data->curelt, "NewPortListing") != 0) - { - int l; - /* standard case. Limited to n chars strings */ - l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); - if(nv == NULL) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserEndElt"); -#endif /* DEBUG */ - return; - } - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - if(data->cdata != NULL) - { - memcpy(nv->value, data->cdata, l); - nv->value[l] = '\0'; - } - else - { - nv->value[0] = '\0'; - } - nv->l_next = data->l_head; /* insert in list */ - data->l_head = nv; - } - data->cdata = NULL; - data->cdatalen = 0; - data->topelt = 0; -} - -static void -NameValueParserGetData(void * d, const char * datas, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - if(strcmp(data->curelt, "NewPortListing") == 0) - { - /* specific case for NewPortListing which is a XML Document */ - data->portListing = malloc(l + 1); - if(!data->portListing) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserGetData"); -#endif /* DEBUG */ - return; - } - memcpy(data->portListing, datas, l); - data->portListing[l] = '\0'; - data->portListingLength = l; - } - else - { - /* standard case. */ - data->cdata = datas; - data->cdatalen = l; - } -} - -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) -{ - struct xmlparser parser; - memset(data, 0, sizeof(struct NameValueParserData)); - /* init xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = NameValueParserEndElt; - parser.datafunc = NameValueParserGetData; - parser.attfunc = 0; - parsexml(&parser); -} - -void -ClearNameValueList(struct NameValueParserData * pdata) -{ - struct NameValue * nv; - if(pdata->portListing) - { - free(pdata->portListing); - pdata->portListing = NULL; - pdata->portListingLength = 0; - } - while((nv = pdata->l_head) != NULL) - { - pdata->l_head = nv->l_next; - free(nv); - } -} - -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - for(nv = pdata->l_head; - (nv != NULL) && (p == NULL); - nv = nv->l_next) - { - if(strcmp(nv->name, Name) == 0) - p = nv->value; - } - return p; -} - -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - -/* debug all-in-one function - * do parsing then display to stdout */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize) -{ - struct NameValueParserData pdata; - struct NameValue * nv; - ParseNameValue(buffer, bufsize, &pdata); - for(nv = pdata.l_head; - nv != NULL; - nv = nv->l_next) - { - printf("%s = %s\n", nv->name, nv->value); - } - ClearNameValueList(&pdata); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpc/upnpreplyparse.h b/src/contrib/miniupnp/miniupnpc/upnpreplyparse.h deleted file mode 100644 index 6badd15..0000000 --- a/src/contrib/miniupnp/miniupnpc/upnpreplyparse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - struct NameValue * l_head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpc/wingenminiupnpcstrings.c b/src/contrib/miniupnp/miniupnpc/wingenminiupnpcstrings.c deleted file mode 100644 index 50df06a..0000000 --- a/src/contrib/miniupnp/miniupnpc/wingenminiupnpcstrings.c +++ /dev/null @@ -1,83 +0,0 @@ -/* $Id: wingenminiupnpcstrings.c,v 1.4 2015/02/08 08:46:06 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2015 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENSE file provided within this distribution */ -#include -#include - -/* This program display the Windows version and is used to - * generate the miniupnpcstrings.h - * wingenminiupnpcstrings miniupnpcstrings.h.in miniupnpcstrings.h - */ -int main(int argc, char * * argv) { - char buffer[256]; - OSVERSIONINFO osvi; - FILE * fin; - FILE * fout; - int n; - char miniupnpcVersion[32]; - /* dwMajorVersion : - The major version number of the operating system. For more information, see Remarks. - dwMinorVersion : - The minor version number of the operating system. For more information, see Remarks. - dwBuildNumber : - The build number of the operating system. - dwPlatformId - The operating system platform. This member can be the following value. - szCSDVersion - A null-terminated string, such as "Service Pack 3", that indicates the - latest Service Pack installed on the system. If no Service Pack has - been installed, the string is empty. - */ - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - printf("Windows %lu.%lu Build %lu %s\n", - osvi.dwMajorVersion, osvi.dwMinorVersion, - osvi.dwBuildNumber, (const char *)&(osvi.szCSDVersion)); - - fin = fopen("VERSION", "r"); - fgets(miniupnpcVersion, sizeof(miniupnpcVersion), fin); - fclose(fin); - for(n = 0; n < sizeof(miniupnpcVersion); n++) { - if(miniupnpcVersion[n] < ' ') - miniupnpcVersion[n] = '\0'; - } - printf("MiniUPnPc version %s\n", miniupnpcVersion); - - if(argc >= 3) { - fin = fopen(argv[1], "r"); - if(!fin) { - fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); - return 1; - } - fout = fopen(argv[2], "w"); - if(!fout) { - fprintf(stderr, "Cannot open %s for writing.\n", argv[2]); - fclose(fin); - return 1; - } - n = 0; - while(fgets(buffer, sizeof(buffer), fin)) { - if(0 == memcmp(buffer, "#define OS_STRING \"OS/version\"", 30)) { - sprintf(buffer, "#define OS_STRING \"MSWindows/%ld.%ld.%ld\"\n", - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); - } else if(0 == memcmp(buffer, "#define MINIUPNPC_VERSION_STRING \"version\"", 42)) { - sprintf(buffer, "#define MINIUPNPC_VERSION_STRING \"%s\"\n", - miniupnpcVersion); - } - /*fputs(buffer, stdout);*/ - fputs(buffer, fout); - n++; - } - fclose(fin); - fclose(fout); - printf("%d lines written to %s.\n", n, argv[2]); - } - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/.gitignore b/src/contrib/miniupnp/miniupnpd/.gitignore deleted file mode 100644 index fe899b2..0000000 --- a/src/contrib/miniupnp/miniupnpd/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -*.o -*.bak -config.h -ipfw/testipfwrdr -miniupnpd -miniupnpdctl -testgetifaddr -testgetifstats -testupnpdescgen -testupnppermissions -testgetroute -testasyncsendto -testportinuse -netfilter/testiptcrdr -netfilter/testiptcrdr_dscp -netfilter/testiptcrdr_peer -testdescs -validateupnppermissions -validategetifaddr -testssdppktgen -validatessdppktgen -.depend -pf/testobsdrdr -pf/testpfpinhole -netfilter/test_nfct_get -testminissdp diff --git a/src/contrib/miniupnp/miniupnpd/Changelog.txt b/src/contrib/miniupnp/miniupnpd/Changelog.txt deleted file mode 100644 index 7dd3b02..0000000 --- a/src/contrib/miniupnp/miniupnpd/Changelog.txt +++ /dev/null @@ -1,1270 +0,0 @@ -$Id: Changelog.txt,v 1.439 2018/04/12 09:32:22 nanard Exp $ - -2018/05/02: - option to store remaining time in leasefile - -2018/04/12: - pf: set dst address in rule if use_ext_ip_addr is set - -2018/04/06: - Add options for netfilter scripts - -2018/03/13: - Use monotonic clock for timeouts, etc. - -2018/02/22: - Add option force_igd_desc_v1 to force devices and services versions - to 1 in IGD v2 mode - -2017/12/12: - Fix a few buffer overrun in SSDP and SOAP parsing - -2017/11/02: - PCP : reset epoch after address change - -2017/05/26: - merge https://github.com/miniupnp/miniupnp/tree/randomize_url branch - -2017/05/24: - get SSDP packet receiving interface index and use it to check if the - packet is from a LAN - -2017/03/13: - default to client address for AddPortMapping when - is empty - pass ext_if_name to add_pinhole() - -2016/12/23: - Fix UDA-1.2.10 Man header empty or invalid - -2016/12/16: - Do not try to open IPv6 sockets once it is disabled - -2016/12/01: - Fix "AddPinhole Twice" test - -2016/11/11: - fixes build for Solaris/SunOS - -2016/07/23: - fixes build error on DragonFly BSD - -VERSION 2.0 : released on 2016/04/19 - -2016/04/18: - linux/netfilter: fix compile time detection of iptables version >= 1.4.3 - -2016/03/08: - linux/netfilter: do not add MASQUERADE rule if ports are equals - -2016/02/19: - set IPv6 Hop limit to 10 - fix HOST: header of event notifications in IPv6 - be more compliant on 64bit machines : ui4 in [0;2^32-1] - -2016/02/16: - minor changes to follow UDA 1.1 more closely. - more argument checking in Soap methods. - -2016/02/12: - return error 729 - ConflictWithOtherMechanisms if IGD v2 is enabled. - add iptc_init() check in iptcrdr.c/init_redirect() - add update_portmapping() / update_portmapping_desc_timestamp() functions - -2016/02/11: - use Linux libuuid uuid_generate() / BSD uuid_create() API - -2016/01/28: - renamed iptables chain MINIUPNPD-PCP-PEER to MINIUPNPD-POSTROUTING - implemented "IGD2 Port Triggering" with netfilter/iptables - -2016/01/18: - fix pcpserver.c CreatePCPMap_FW() : check pinhole before adding - -2015/12/16: - improve syslog message for incoming HTTP requests - -2015/12/13: - --disable-pppconn to disable WanPPPConnection - more fixes in DeviceProtection service - -2015/12/12: - add commandline option to genconfig.sh to set UPnP (UDA) version - advertise correct service and device versions when IGDv2 is enabled - fix action arguments for DeviceProtection service - fix event subscription renewal (include SID in response) - -2015/11/16: - Fix bsd/getroute.c get_src_for_route_to() when args are NULL - -2015/11/02: - use LOG_INFO instead of LOG_ERR for PCP PEER and MAP success - -2015/10/30: - fix : properly call find_ipv6_addr() with the 1st LAN interface - use name server from query in SOAP responses (continued) - -2015/10/24: - move SSDP_PACKET_MAX_LEN definition to config.h. also set default to 1024. - -2015/09/22: - cleanup UPNP_VERSION macro / add UPNP_VERSION_MAJOR, UPNP_VERSION_MINOR - Don't use packed structs anymore to read/write PCP messages - -2015/09/15: - use name server from query in SOAP responses - -2015/09/14: - Randomize URLs to avoid http://www.filet-o-firewall.com/ - https://github.com/filetofirewall/fof - (specific branch, merged later, see above) - -2015/08/25: - better bind socket to right interface(s), - using struct ip_mreqn, SO_BINDTODEVICE - -2015/04/30: - Adding linux/nftables support - -2015/04/26: - Remove dependency to libnfnetlink - fix typos in miniupnpd.conf - -2015/03/09: - fix get_portmappings_in_range() for linux/netfilter - -2015/03/07: - don't die when IPv6 is enabled and interface has no IPv4 address - -2015/02/10: - IP wildcard for AddPinhole() is empty string - -2014/12/10: - Checking Host: HTTP request header to prevent DNS rebinding attack - configurable BOOTID.UPNP.ORG SSDP header - use time for BOOTID.UPNP.ORG value - -2014/12/09: - fix upnp_add_inboundpinhole() : check inet_pton() return - fix upnp_redirect() : check inet_aton() return - fix potential memory corruption in upnpsoap.c/GetListOfPortMappings() - fix buffer overrun in ParseHttpHeaders() if Content-Length doesn't contain any digit ! - check if BuildHeader_upnphttp() failed to allocate memory - Credits goes to Stephen Röttger of the Google Security Team for identifying - the vulnerabilities - -2014/12/04: - check "sysctl -n net.ipv6.bindv6only" for linux - -2014/11/28: - fixes ExecuteSoapAction if SoapAction value is not enclosed into - double quotes - -2014/11/07: - sockaddr_to_string() includes scope in IPv6 addresses - -VERSION 1.9 : released on 2014/10/27 - -2014/10/23: - Properly implements NAT-PMP mapping removal according to RCF6886 - -2014/10/22: - Discard NAT-PMP packets coming from the WAN - Send SSDP announces to IPv6 link-local, site-local - and global multicast addresses - -2014/10/21: - small modifications to compile with exotic C libraries - -2014/10/14: - add comments in miniupnpd.conf regarding security - -2014/09/25: - DeletePortMapping now checks for client IP in Securemode - -2014/06/xx: - Various fixes : - e->ipv6.flags |= IP6T_F_PROTO; (netfilter) - fix natpmp.c byte order conversion - add small delay before SSDP response to prevent flooding - -2014/05/22: - Add ipv6_bind_address (option "ipv6_listening_ip") - disable IPv6 when socket(PF_INTET6, ...) errors with EAFNOSUPPORT - Add IPV6 multicast membership only on selected "LAN" interfaces - -2014/05/20: - be more strict when parsing LAN addresses / interface names - -2014/05/19: - set source address for IPV6 packets sendto_schedule2() etc. - -2014/05/15: - Fix deletePortMappingRange() - -2014/04/21: - Fix PCP when request contain 0 IPv4 external address - Remove pointer casting in natpmp.c - -2014/04/15: - rewrite iptables_*.sh scripts - -2014/04/12: - Add FreeBSD support for CHECK_PORTINUSE - Add PCP support for CHECK_PORTINUSE - -2014/04/09: - Add HTTPS support and skeleton of DeviceProtection implementation - -2014/03/24: - start work to enable IPv6 PCP operations - -2014/03/14: - reject renewal of subscribtion that already timeouted - Support for multiple URL in Callback: header (SUBSCRIBE) - -2014/03/13: - fix getifaddr_in6() (used for PCP) - implement permissions with PCP Map - fix upnp_event_notify_connect() when ENABLE_IPV6 is set - -2014/03/10: - Enable PCP by default. - Work in IPv6 on system where PF_INET6 are restricted to IPv6 only - change ipv6_enabled/ipv6fc_inbound_pinhole_allowed/ipv6fc_firewall_enabled - global vars to flags in runtime_flags - -2014/03/09: - IPv6 support in testgetifaddr - -2014/03/07: - NAT-PMP search an allowed eport instead of returning an error - if the original eport is not allowed. - -2014/03/06: - Fix add_filter_rule2() for pf. - -2014/02/28: - log message when shutting down - natpmp : avoid hang when all external ports in use - -2014/02/25: - add implementation of scheduled sendto (asyncsendto) in order - to retry failed sendto() calls or schedule sending of packets - -2014/02/24: - Defaulting to SSDP_RESPOND_SAME_VERSION - -2014/02/11: - Fix PCP Map renewal - -2014/02/06: - possibility to disable ipv6 at runtime - -2014/02/03: - PCP : Add support for ANNOUNCE requests - minixml now handle XML comments - -2013/12/16: - Attempt to compile with OS X/pf - -2013/12/13: - Make all manufacturer info configurable thanks to Leo Moll - Merge PCP support (see https://github.com/miniupnp/miniupnp) - -2013/06/13: - Have 3 UUID for the 3 devices (IGD, WAN Device, WAN Connection Device) - -2013/06/06: - update upnpreplyparse to allow larger values (128 chars instead of 64) - -2013/06/05: - check Service ID in SetDefaultConnectionService method - Don't advertise WANPPPConnection in UPNP_STRICT mode - -2013/05/29: - Remove namespace from variable name elements in Events "propertyset" - to comply with UPNP DeviceArchitecture v1.1. - -2013/05/20: - Adding support for IP Filter version 5.x - -2013/05/16: - refuses non integer values - -2013/05/14: - Update upnpreplyparse to take into account "empty" elements - -2013/05/03: - Use pkg-config under linux to find libiptc. Thanks to Olivier Langlois - -2013/04/29: - Add warning message when using IPv4 address for listening_ip with IPv6 enabled - -2013/04/27: - Uses ifr_addr if ifr_netmask is not defined in struct ifreq - -2013/04/26: - Correctly handle truncated snprintf() in SSDP code - -2013/04/24: - to avoid build race conditions, genconfig.sh now uses a temporary file - -2013/04/20: - use scope in get_lan_for_peer() for IPv6 addresses - -2013/03/23: - autodetect LAN interface netmask instead of defaulting to /24 - -2013/02/11: - Use $(DESTDIR) in Makefile.linux. - see https://github.com/miniupnp/miniupnp/issues/26 - -2013/02/07: - Add DATE: header in SSDP packets - Fix SSDP packets sent with uuid as ST: header to conform to UDA - ignore SSDP packets missing the MX: header in UPNP_STRICT mode - Added Ext: header to HTTP responses to conform to UDA - Refactored SendSSDPNotifies() and SendSSDPGoodbye() and add - missing ssdp:alive and ssdp:byebye with NT uuid value. - -VERSION 1.8 : released on 2013/02/06 - -2013/02/06: - Check source address of incomining HTTP connections and SSDP - packets in order to filter out WAN SSDP and HTTP traffic. - Implement get_src_for_route_to() for *BSD - fix 2 potential memory leaks in GetListOfPortMappings() - -2013/01/29: - upnphttp.c: Fix and comment the findendheaders() function - upnphttp.c: remove strchr() call in ParseHttpHeaders() - add comments to explain how buffer is checked before calls - to ParseHttpHeaders() - -2013/01/27: - upnphttp.c: ParseHttpHeaders() now checks atoi() return - -2012/12/11: - More return value check for malloc() and realloc() - -2012/10/23: - minor modifications to linux/getroute.c and testgetroute.c - -2012/10/04: - updated DEFAULTCONNECTIONSERVICE_MAGICALVALUE for IGDv2 - increased default buffer size for HTTP response - More argument check for SOAP actions in UPNP_STRICT mode - Better error checking after connect() in upnpevent - -2012/10/03: - Fix atoi() on null pointer in upnpsoap.c - properly set service/device version in SSDP messages - fix newSubscriber() for IP6FirewallControl and DeviceProtection services - Enforce compliance for SUBSCRIBE messages (UPNP_STRICT mode) - Enforce compliance for UNSUBSCRIBE messages (UPNP_STRICT mode) - Ignore "-Wmissing-field-initializers" in upnpdescgen.c - check size of h->res_buf before building HTTP response - ENABLE_HTTP_DATE : add a Date: header to all HTTP responses - -2012/09/27: - Fixes with DISABLE_CONFIG_FILE - and UPNP_STRICT - UPC must be a 12 decimal digit code - SetDefaultConnectionService() checks its argumnents in UPNP_STRICT mode - Support for Accept-Language/Content-Language HTTP headers - Content-Type is now text/xml; charset="utf-8" to conform with UDA v1.1 - Support Expect: 100-continue for POST HTTP requests - Manage services/devices versions in minissdp.c - Rename all include guards to not clash with C99. - (7.1.3 Reserved identifiers) - -2012/09/20: - Cleaning code in ipfw (Jardel Weyrich) - -2012/09/18: - Fixing a bug in clean_pinhole_list() under linux/netfilter - -2012/09/15: - Adding an informational message at startup - -2012/08/24: - Moved man page to section 8. miniupnpd.1 => miniupnpd.8 - Added install of miniupnpd.8 man page in Makefile.linux - -2012/08/10: - improved SubmitServicesToMiniSSDPD() function fiability - -2012/07/17: - Add -A command line option to add permission rules - -2012/07/14: - Add -z command line option to change friendly name (thanks to Shawn Fisher) - -2012/07/10: - Detect port in use - patch by David Kerr - -2012/06/29: - added DISABLE_CONFIG_FILE in options.h to disable miniupnpd.conf parsing - Add command line parsing for clean_ruleset_interval option - -2012/06/28: - Only activate -L option for PF and IPF - -a option takes two arguments with MULTIPLE_EXTERNAL_IP defined - -2012/06/23: - in UPNP_STRICT mode, the literal IPv6 address in "location:" of SSDP - messages is the source address used to send the message - -2012/06/08: - Disable -ansi CFLAGS in Makefile.linux because recent iptables headers - make use of typeof keyword which is a GCC extension. - -2012/05/31: - Improvements in autodetecting firewall under (Free)BSD - -2012/05/28: - Cleanup HTTP request handling. Answer 405 when relevant - -VERSION 1.7 : released the 2012/05/28 - -2012/05/28: - clean linux/ifacewatcher.c - set natpmp socket non blocking - -2012/05/24: - More solaris fixes - -2012/05/21: - Clean signal handling - -2012/05/08: - Clean expired IPv6 pinholes correctly. and also with linux/netfilter. - -2012/05/07: - Finalizing netfilter version of get_pinhole_info() - -2012/05/01: - Move IPv6FirewallControl related code from upnpredirect.c to upnppinhole.c - Add netfilter implementation for - delete_pinhole()/update_pinhole()/get_pinhole_info() - -2012/04/30: - Clean up settings of CFLAGS in Makefile's - Remove Warnings caused by signed/unsigned integer comparaisons - Also fix a couple of integer/pointer comparaisons. - Add UNUSED(arg) macro to remove unused argument warning. - Fix error handling in upnpevents.c (was causing segfault on Solaris !) - -2012/04/26: - Started to implement add_pinhole() for netfilter (linux) - -2012/04/25: - Fixed a bug in upnphttp that happened when POST is received in several - recv() calls and realloc() is called so the buffer used is moved. - -2012/04/23: - Implement CheckPinholeWorking GetPinholePackets. WANIPv6FirewallControl - UpdatePinhole still to be done. And also netfilter/ipf/ipfw versions - -2012/04/20: - Enough WANIPv6FirewallControl is implemented on pf so that AddPinhole() and - DeletePinhole() works ! - -2012/04/19: - First working experiment of IPv6 "pinhole" with pf - -2012/04/15: - More C++ => ANSI C comments to compile with -ansi option - Add command line arguments to genconfig.sh config script. - -2012/04/12: - Set TTL on SSDP Notify sockets (IPv4). TTL is set to 2 (recommendation from - UPnP Device Architecture v1.1) - -2012/04/06: - Implementing IPv6 support : - Send SSDP NOTIFY ssdp:alive and ssdp:goodbye messages in IPv6. - Use UPnP/1.1 in SERVER: string as required in UPnP Device architecture 1.1. - Allow LAN interface to be given as interface names, instead of interface - IP addresses. It will allow IPv6 operations. - fix linux/getifstats.c when bitrate is unknown - -2012/03/31: - Only remove pidfile if one was written in the first place. - -2012/03/19: - Fix ipfilter support (thanks dhowland https://github.com/dhowland) - -2012/03/14: - Changes to miniupnpd.init.d.script by Shawn Landden - -2012/03/05: - fixed reload_from_lease_file(). - -2012/02/15: - Change parselanaddr() function to allow 192.168.1.1/255.255.255.0 in - configuration file. - Change read_permission_line() to allow 192.168.1.1/255.255.255.0 in - permission line (in configuration file). - -2012/02/12: - More syntax checks in upnppermissions.c - -2012/02/11: - Fix ipfw/Mac OS X specific source files to compile ok with -ansi flag - -2012/02/09: - Make HTTP listen socket non blocking (so accept() can't block) - Make SSDP receive sockets non blocking - use sockaddr_to_string() in SendSSDPAnnonce2 to handle IPv6 addresses - -2012/02/06: - Make HTTP (SOAP) sockets non blocking. - -2012/02/05: - Compile ok with -ansi flag. - Save a few bytes in options.c using a string repository, instead of a fixed size - buffer for each option value. - -2012/02/04: - Added friendly_name= option to config file - -2012/02/03: - Anchor name (PF) is now configurable through the config file with anchor= - Added test of presence of /lib/libip4tc.so and /lib/libip6tc.so files in - Makefile.linux in order to add -lip4tc and -lip6tc to LIBS accordingly. - -2012/02/01: - always handle EAGAIN, EWOULDBLOCK and EINTR after recv()/recvfrom() calls - -2012/01/20: - Always #include before #include (for OpenBSD) - .onrdomain field was added in pf with OpenBSD 5.0. Add PFRULE_HAS_ONRDOMAIN - -2012/01/02: - Fixing netfilter/iptables_*.sh scripts for new ifconfig output format. - getifaddr.c: added additional checks on structure returned by getifaddrs() - Fixing Mac OS X makefile for installation - -2011/11/18: - avoid infinite loop in SendResp_upnphttp() in case of error - Replaced SendResp_upnphttp() + CloseSocket_upnphttp() by - SendRespAndClose_upnphttp() - Tomato specifics in genconfig.sh - -2011/07/30: - netfilter : Added a tiny_nf_nat.h file to compile with iptables - installed headers. - include xtables.h instead of iptables.h - -VERSION 1.6 : released the 2011/07/25 - -2011/07/25: - Update doc for version 1.6 - -2011/07/15: - Fixing code with MULTIPLE_EXTERNAL_IP defined. - -2011/06/27: - IPv6 support for UPnP events. - Security checks in UPnP events. - -2011/06/22: - Remote host for GetListOfPortMappings - Remote host support for ipfw (tested on Mac OS X) - -2011/06/20: - support for iptables-1.4.11.1 - -2011/06/18: - Remote host support for pf version - -2011/06/04: - Supporting RemoteHost (mandatory in IGD v2) - -2011/06/03: - Enabling events by default - -2011/06/01: - Fixing Timeout missing in SUBSCRIBE renewal responses - (thanks to Pranesh Kulkarni) - Added comments about changes between IGD v1 and IGD v2 - -2011/05/28: - Description and leaseduration kept in ipfw version of the code. - Fixing ipfw code after testing under Mac OS X 10.6.7 (darwin 10.7.0) - -2011/05/27: - Finishing and testing LeaseDuration support under OpenBSD. - Changing NAT-PMP port mapping lifetime support to match - lease duration support. - NAT-PMP address change announce broadcasted to both port - 5350 and 5351 to be compatible with client following the - version of NAT PMP specification from 2008 or earlier. - writepidfile() Overwrite file if already existing - -2011/05/26: - fix in linux/getifstats.c. - See http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=2212 - Implementation of LeaseDuration support. - -2011/05/23: - added get_wan_connection_status_str() - -2011/05/20: - adding ifacewatcher thanks to Alexey Osipov - GET /DP.xml is now available. The description has to be completed. - -2011/05/19: - Add getconnstatus.c/.h. Don't always have ConnectionStatus to "Connected" - Events for WANIPv6FirewallControll - -2011/05/16: - patches for gentoo linux. - generation of the DeviceProtection service description. - -2011/05/15: - Making the SSDP receiving socket work in IPv6 ! - -2011/05/14: - Support for HTTP in both IPv6 and IPv4. - IPv6 for SSDP receiving socket. - -2011/05/13: - add new options in genconfig.sh (IGD_V2, ENABLE_DP_SERVICE) - add global vars ipv6fc_firewall_enabled and ipv6fc_inbound_pinhole_allowed - have MACROS for magical values in upnpdescgen.c, add eventing vars for WanIPv6FirewallControl. - applied 0001-Cosmetic-changes.patch(see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=764) - applied 0002-Remove-lan-addresses-limit-by-changing-storage-type-.patch - replaced some of the urn:schemas-upnp-org:device:* literal strings by macros. - adding some support for IP v6. #define ENABLE_IPV6 - added -fno-strict-aliasing to compile options. - -2011/05/09: - updating upnp descriptions for IGDv2 - -2011/05/07: - Adding WANIPv6FirewallContro to upnp description - -2011/04/30: - adding a UPNP_STRICT config macro. Use it now for checking RemoteHost. - ENABLE_6FC_SERVICE : add the implementations of WANIPv6FirewallControl actions - -2011/04/11: - preparing getifaddr() for IP v6 - preparing SSDP stuff for IP v6. Trying to conform to UDA v1.1 - -2011/03/09: - Some modifications thanks to Daniel Dickinson to improve OpenWRT - build. - Fixed some warnings. - -2011/03/03: - Added code to generate devices/services descriptions for IGD v2 - (to be continued) - -2011/03/02: - improved netfilter/delete_redirect_and_filter_rules() in order - to remove the right filter rule, even if it has another index than - the nat rule. - -2011/03/01: - clean up an fixes to make netfilter/testiptcrdr compile - -2011/02/21: - Make "Makefile" work under Mac OS X with bsdmake. - added get_portmappings_in_range() in ipfwrdr.c - -2011/02/07: - added get_portmappings_in_range() / upnp_get_portmappings_in_range() - -2011/02/06: - Implementation of GetListOfPortMappings - -2011/01/27: - Reverting "fixes" done in linux/iptables code the 2010/09/27. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=741 - -2011/01/04: - added MINIUPNPD_VERSION in config.h. Taken from VERSION file. - -VERSION 1.5 : released the 2011/01/01 - -2011/01/01: - Started to implement some of the new methods from WANIPConnection v2 - -2010/09/27: - Some fixes in the linux/iptables code when - miniupnpd_nat_chain <> miniupnpd_forward_chain - -2010/09/21: - Patch to support nfqueue thanks to Colin McFarlane - -2010/08/07: - Update Mac OS X / ipfw stuff from Jardel Weyrich - Fix in Makefile.linux for x86_64 - -2010/05/06: - Bugfix un CleanNATPMPRules() : see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=640 - -2010/03/14: - Fixing natpmp sockets. - -2010/03/08: - Fix Makefile.linux to compile properly under Mandriva/rh/Fedora with - Iptables >= 1.4.3 - Workaround for bad uptime when started with a bad time set. - -2010/03/07: - Tried to make a OpenBSD version 4.7 compatible code... still some - issues. - -2010/03/06: - updates to testobsdrdr - -2010/03/03: - -lip4tc in Makefile.linux. - -2010/02/15: - some more error handling in set_startup_time() - silencing some warnings - -2010/01/14: - Open Several sockets for NAT-PMP to make sure the source address - of NAT-PMP replies is right. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=609 - -2009/12/31: - miniupnpdctl now output command line arguments. - added a -h option to get help. improved help. - -2009/12/22: - using PRIu64 format to printf u_int64_t - Fixing calls to get_redirect_rule_by_index() : ifname should be initialized. - Add header lines to miniupnpdctl output - -2009/11/06: - implementing sending of ip address change notification when receiving - the signal SIGUSR1 - -VERSION 1.4 : released the 2009/10/30 - -2009/10/10: - Integrate IPfilter patch from Roy Marples. - Fix Netfilter code for old netfilter : - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=584 - trim the description string in reload_from_lease_file() - -2009/09/21: - Fixing unclosed raw sockets bug with netfilter code. - -2009/09/04: - Fixes in ipf code thanks to Roy Marples - Enable DragonFly BSD Support thanks to Roy Marples. - Allow packager to define default location of config file via CFLAGS - Respect $DESTDIR when installing - -2009/08/20: - Adding some support for MacOS X and IPFW - SO_REUSEADDR in minissdp.c for SSDP listening socket - -2009/06/05: - unlink lease file in reload_from_lease_file() - -2009/05/16: - Fixed a buffer overflow in ProcessSSDPRequest() - -2009/05/11: - improving genconfig.sh for NetBSD : detecting use of pf or ipf - -VERSION 1.3 : -2009/04/17: - working support for iptables >= 1.4.3 - -2009/04/13: - work to support iptables-1.4.3 and up - -2009/04/10: - fix in upnpevents_removeSubscriber() - -2009/02/14: - added reload_from_lease_file() - -2009/02/13: - Changes in upnpdescgen.c to allow to remove empty elements - strcasecmp instead of strcmp on path comparaisons to allow - bugged clients to work - -2009/01/29: - Some minor changes to Makefile - improving Makefile.linux in order to build with iptables not properly - installed on the system. - -2009/01/23: - Fixing upnpevents thanks to Justin Maggard - -2008/10/15: - getifstats() return -1 when supplied with bad arguments - -2008/10/11: - Fixed NAT-PMP response when IP not allocated to external interface - -2008/10/09: - adding testgetifaddr - Reporting Unconnected status when the "external interface" has - no IP address assigned. Also added some comments - -VERSION 1.2 : - -2008/10/07: - updating docs - -2008/10/06: - MiniUPnPd is now able to use MiniSSDPd to manage SSDP M-SEARCH answering - -2008/10/03: - You can now let miniupnpd choose itself the HTTP port used. - -2008/10/01: - Improvements in genconfig.sh for detecting ipf or pf (under FreeBSD) - and improve debian/ubuntu stuff. - custom chain name patch from : - http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=493 - -2008/08/24: - added USE_IFNAME_IN_RULES macro that can be disabled in order to - remove interface name from rules. - -2008/07/10: - Fixed compilation without ENABLE_L3F_SERVICE - -2008/04/27: - correct UNSUBSCRIBE processing - -2008/04/25(bis): - changed iptables_removeall.sh and iptables_init.sh in order - to remove IP from the rules - -VERSION 1.1 : - -2008/04/25: - Eventing is allmost completly implemented - -2008/04/24: - Correct event handling ? - -2008/04/08: - enabling tag in PF rules. quick can be set off. - -2008/03/13: - implementing event notify - -2008/03/11: - fixing a command line parsing error - -2008/03/09: - optimisations in upnpsoap.c - -2008/03/08: - optimizing upnpsoap.c for size - -2008/03/06: - Worked on the Eventing : generating XML event notifications - Send initial notification after subscribe - Improved pretty print of testupnpdescgen - Reduced Memory usage of upnpdescgen - fixed a small bug in the description - -2008/03/03: - Fixed miniupnpd.c for compiling without natpmp support - fixed presentationURL not there with L3F - fixing lease file creation/modification - -2008/02/25: - Rewrite of Send501() and Send404() - More work on events - genconfig.sh autodetects pf/ipf - -2008/02/24: - Started to implement UPnP Events. do NOT use it at the moment ! - -2008/02/21: - Added support for the Layer3Forwarding Service - added init_redirect() and shutdown_redirect() functions - -2008/02/20: - Removed Ext: HTTP header when useless - enabled the dummy service by default to please windows XP ! - -2008/02/07: - upnp_enable patch by Nikos Mavrogiannopoulos. - lease_file patch by Nikos Mavrogiannopoulos. - -2008/01/29: - some changes to Makefile.openwrt - use daemon() - daemonize() is still available for systems lacking daemon() - -VERSION 1.0 : -2008/01/27: - moved lan_addr to upnpglobalvars.h/.c - Adding experimental multiple external IP support. - -2008/01/22: - removed dummy service from description to improve compatibility - with emule client - Add "secure mode". put runtime flags in the same variable - -2008/01/14: - Fixed a bug in options.c for the parsing of empty lines. - -2008/01/03: - Fixed CleanExpiredNATPMP() - -2008/01/02: - Adding a queue parameter for setting ALTQ in pf - -2007/12/27: - improving some stuff with the PF_ENABLE_FILTER_RULE. - -2007/12/22: - Adding a runtime option to enable/disable NAT-PMP - -2007/12/20: - Added a cache in linux getifstats(). Please enable by editing config.h - -2007/12/14: - Updating an existing NAT-PMP mapping now works - -2007/12/13: - NAT-PMP code now remove expired mappings - TCP/UDP where swapped in NAT-PMP code - -2007/12/04: - Adding details to the error message for sendto(udp_notify) - -2007/11/27: - pf code doesn't generate filter rules by default anymore. The - #ifdef PF_ENABLE_FILTER_RULES must be uncommented in config.h. - -2007/11/02: - moved some of the prototypes common to all firewalls to commonrdr.h - Added functionalities to NAT-PMP - -2007/11/01: - Debugged NAT-PMP code - -2007/10/28: - Cleaning and improving NAT-PMP code - -2007/10/25: - improved the NAT-PMP experimental support - updated README and INSTALL files - -2007/10/24: - Adding support for NAT-PMP (from apple !) - -2007/10/11: - Checking the commandline for errors. - -2007/10/08: - Improved the BSD/Solaris Makefile - Merging last code from Darren Reed. Solaris/IPF should work now ! - added a man page. - -2007/10/07: - Adding Darren Reed code for ipf. - -2007/10/06: - Adding SunOS support thanks to Darren Reed. - Reorganizing os/firewall dependent code thanks to Darren Reed. - -2007/09/27: - linux make install support PREFIX variable - -2007/09/25: - reorganizing LAN sockets/address to improve multi LAN support. - SSDP announces are sent to all configured networks. - SSDP responses are "customized" by subnetwork. - -2007/09/24: - prototype code to remove unused rules - miniupnpdctl now display current rules - synchronised add_filter_rule2() prototype between pf and netfilter code. - -2007/09/19: - Correctly filling the Cache-control header in SSDP packets - -2007/08/28: - update PFRULE_INOUT_COUNTS detection for FreeBSD - -2007/08/27: - update version in genconfig.sh - do not error when a duplicate redirection is requested. - -2007/07/16: - really fixed the compilation bug with linux>=2.6.22 - -2007/07/04: - fixed an error in options.c that prevented to use packet_log option - -2007/07/03: - improved genconfig.sh - fixed a compilation bug with linux>=2.6.22 - -2007/06/22: - added PFRULE_INOUT_COUNTS macro to enable separate in/out packet and - bytes counts in pf for OpenBSD >= 3.8 - -2007/06/15: - removed a possible racecondition in writepidfile() - -2007/06/12: - improved genconfig.sh : no more "echo -e", use lsb_release when available - -2007/06/11: - get_redirect_rule*() functions now return some statistics about - rule usage (bytes and packets) - -2007/06/07: - Fixed the get_redirect_desc() in the linux/netfilter code - -2007/06/05: - Clean up init code in miniupnpd.c - Added a syslog message in SoapError() - -2007/06/04: - Now store redirection descriptions in the linux/netfilter code - -2007/05/21: - Answers to SSDP M-SEARCH requests with ST: ssdp:all - added make install to Makefile.linux - -2007/05/10: - Fixed a bug int the DeletePortMapping linux/netfilter implementation - It was allways the 1st rule that was deleted. - -2007/04/26: - Fixed config.h.openwrt - -2007/04/16: - added something in the INSTALL file about the FreeBSD send(udp_notify) - problem fix (allowing 239.0.0.0/8 explicitely in pf.conf) - -2007/03/30: - added setsockopt(s, SOL_SOCKET, SO_BROADCAST ...) for broadcasting - socket - -2007/03/17: - Fixed filter rule under linux : it was using wrong port ! - thanks to Wesley W. Terpstra - -2007/03/01: - Moved some of the SSDP code from miniupnpd.c to minissdp.c - -2007/02/28: - creating miniupnpdctl - -2007/02/26: - use LOG_MINIUPNPD macro for openlog() - simplify miniupndShutdown() - -2007/02/09: - improved genconfig.h - Added stuff to change the pf rule "rdr" to "rdr pass" - -2007/02/07: - Corrected Bytes per seconds to bits per second. - Ryan cleaned up comments and typos. - Ryan cleaned up daemonize stuff. - Ryan added possibility to configure model number and serial number - -2007/01/30: - ryan improved the robustness of most UPnP Soap methods - I added a target in the Makefiles to properly generate an uuid using - command line tools. - Improved configuration file parsing. - -2007/01/29: - Adding uuid option in miniupnpd.conf - -2007/01/27: - Added upnppermissions stuff : adding some security to UPnP ! - fixed XML description thanks to Ryan Wagoner - improved QueryStateVariable thanks to Ryan Wagoner - -2007/01/22: - use getifaddr() for each GetExtenalIPAddress() Call. - We can change the ip during execution without pb - -2007/01/17: - Lots of code cleanup - -2007/01/12: - Fixed a nasty bug in the linux/netfilter version of get_filter_rule() - -2007/01/11: - Improved the handling of the miniupnpd.conf file. - added -f option to choose which config file to read. - -2007/01/10: - Fixed potential bugs with ClearNameValueList() - -2007/01/08: - All by Ryan Wagoner : - - coding style and comments cleanup - - using now option file miniupnpd.conf - -2007/01/03: - changed "xx active incoming HTTP connections" msg - -2007/01/02: - Patch from Ryan Wagoner : - - no need to open sockets if we can't set the error handlers - - format the usage so it fits nicely on a standard size terminal - - fix up log_err message so they have the same format and you know what - they are related to - - use same "white space" style throughout - - on shutdown no need to continue if opening socket or setsockopt fails - -2006/12/14: - reduce amount of log lines (keeping the same information) - -2006/12/07: - Fixed Makefiles - fixed typos in logs - version 1.0-RC1 released - -2006/12/02: - moved strings from upnpdescgen.c to upnpdescstrings.h for - easier modification - Server: HTTP header now comes from a #define - added a compilation-time generated config.h - -2006/11/30: - minixml updated. should have no impact - Added support for presentationURL with -w switch - implemented getifstats() for linux. Added testgetifstats program - improved error handling in getifstats() BSD - -2006/11/26: - no need to have miniupnpc sources to compile miniupnpd. - Makefile.openwrt updated - Closing sockets on exit thanks to Ryan Wagoner - -2006/11/23: - now handling signal SIGINT - setting HTTP socket with REUSEADDR thanks to Ryan Wagoner - daemon now tested on a Linksys WRT54G device running OpenWRT ! - -2006/11/21: - disabling rtableid in pf code. - -2006/11/22: - Also responds on M-SEARCH with the uuid - -2006/11/20: - gaining some space in upnpsoap.c - -2006/11/19: - Cleaning up code to comply with ANSI C89 - -2006/11/17: - Linux version now deleting both nat and accept rules - implemented -U option under Linux - -2006/11/16: - implemented delete_redirect_rule() for linux - returning error 714 in DeletePortMapping() when needed - -2006/11/12: - The linux/netfilter version should now WORK ! - fix in the writepidfile() function. open with a mode ! - -2006/11/10: - fixing the XML description generation for big endian machines - working on the linux/netfilter port - -2006/11/09: - improved a lot the handling of HTTP error cases - -2006/11/08: - Tried to make the Makefile compatible with both BSDmake - and GNUmake. It was hard because of $^ and $< - -2006/11/07: - Makefile compatible with BSD make - make install target. - getifstats.c compatible with both OpenBSD and FreeBSD. - -2006/11/06: - added getifstats.c for openBSD. May not work under FreeBSD ? - now reports bytes/packets sent/received - reporting bitrates - possibility to report system uptime - -2006/10/29: - added a -L option to enable loggin (is off by default now). - -2006/10/28: - Patch by Ryan Wagoner to correct the XML description (was NewUpTime - instead of NewUptime) and implement uptime. - Trying to fix the memory leak. Added some comments - added a -d option for debugging purpose - Tnaks to valgrind (under linux!) I removed a small memory access error. - -2006/10/27: - Thanks to a patch sent by Michael van Tellingen, miniupnpd is - now ignoring NOTIFY packets sent by other devices and is - writing is own pid to /var/run/miniupnpd.pid - -2006/10/23: - Allways set sendEvents="no" in XML description (was causing - pb with winXP as SUBSCRIBE is not implemented) - -2006/10/22: - added translation from hostname to IP in the AddPortMapping() method - Thanks to Ryan Wagoner. - -2006/10/18: - Added an INSTALL file - -2006/10/13: - Added the possibility to change the notify interval - -2006/09/29: - Improved compliance of the XML Descriptions - pretty print for testupnpdescgen - -2006/09/25: - improved the Error 404 response. - Better serviceType and serviceId for dummy service... - -2006/09/24: - updating the XML description generator - -2006/09/18: - Thanks to Rick Richard, support for SSDP "alive" and "byebye" notifications - was added. The -u options was also added. The SSDP response are now - improved. - The -o option is now working (to force a specific external IP address). - The Soap Methods errors are correctly responded (401 Invalid Action) - -2006/09/09: - Added code to handle filter rules. Thanks to Seth Mos (pfsense.com) - storing the descriptions in the label of the rule - -2006/09/02: - improved the generation of the XML descriptions. - I still need to add allowed values to variables. - -2006/07/29: - filtering SSDP requests and responding with same ST: field - -2006/07/25: - Added a dummy description for the WANDevice - -2006/07/20: - Command line arguments processing - Added possibility to listen internally on several interfaces - diff --git a/src/contrib/miniupnp/miniupnpd/INSTALL b/src/contrib/miniupnp/miniupnpd/INSTALL deleted file mode 100644 index 6358183..0000000 --- a/src/contrib/miniupnp/miniupnpd/INSTALL +++ /dev/null @@ -1,195 +0,0 @@ -MiniUPnP project. -(c) 2006-2017 Thomas Bernard -Homepage : http://miniupnp.free.fr/ -Mirror: https://miniupnp.tuxfamily.org/ -github: https://github.com/miniupnp/miniupnp - -miniupnpd is still under developpement. This documentation is -likely to be a little outdated when you read it. So please go on the -web forum https://miniupnp.tuxfamily.org/ if you need more information. - -================================ *BSD/pf ================================= -To Build and Install : - -- use BSD make to compile. -- you can first 'make config.h' then edit config.h to your preferences and - finally 'make' - Alternatively to editing config.h, options can be passed to genconfig.sh - For more details : - > ./genconfig.sh -h -- add "rdr-anchor miniupnpd" or/and "anchor miniupnpd" lines to /etc/pf.conf - (Since OpenBSD 4.7, rdr-anchor lines are no longer used and should be - removed, leaving only the anchor lines). -- some FreeBSD users reported that it is also necessary for them - to explicitly allow udp traffic on 239.0.0.0/8 by adding the two following - lines to /etc/pf.conf : - pass out on $int_if from any to 239.0.0.0/8 keep state - pass in on $int_if from any to 239.0.0.0/8 keep state -- don't forget to " pfctl -f /etc/pf.conf " -- you can check your modifications are taken into account with - "pfctl -s nat" and "pfctl -s rule". Look for the "rdr-anchor miniupnpd" - (if applicable) and/or "anchor miniupnpd" lines. -- OpenBSD users may need to add a multicast_host= line to /etc/rc.conf.local - see $man 8 netstart -- install as root using : - # make install - or - # PREFIX=/usr/local make install -- run as root : The daemon needs rights to modify pf rules. - -=========================== *BSD,*Solaris/ipf ============================= - -genconfig.sh and the Makefile try to detect wether ipf or pf should be -used. If it fails, edit config.h and Makefile by hand. -In Makefile, the FWNAME variable value should be pf or ipf. -Installation steps are allmost the same as with pf. - -*Solaris users would be interested in reading informations from : -http://blogs.sun.com/avalon/category/IPFilter - -============================= Mac OS X/ipfw =============================== - -- To enable non standard compilation options, - > ./genconfig.sh -h - Or edit config.h after it has been generated by genconfig.sh -- use 'bsdmake' (if available) or 'make -f Makefile.macosx' to build - -============================== Mac OS X/pf ================================ - -Starting with Mac OS X 10.7 Lion, pf replaced ipfw as the OS X firewall. -also bsdmake is not available anymore. -Make sure you have installed the Xcode commande line tools (from the -Xcode Preferences menu or using 'xcode-select --install' command) - -You'll need to download xnu sources : https://github.com/opensource-apple/xnu -> INCLUDES="-I.../xnu/bsd -I.../xnu/libkern" make -f Makefile.macosx - -============================ Linux/netfilter ============================== -To Build and install : - -- make sure you have libiptc available on your system : - if you are using debian, "apt-get install iptables-dev" - Some versions of the iptables-dev package don't include the - necessary files : read "how to get libiptc with its headers on debian" below. - In anycase, libiptc is available in iptables sources packages - from http://netfilter.org -- edit and run netfilter/iptables_init.sh shell script. - This script must allways be run before the daemon - to set up initial rules and chains. -- Build and edit the config.h file - > make -f Makefile.linux config.h - > vi config.h -- Build the daemon - > make -f Makefile.linux - If not using iptables from your system, - > IPTABLESPATH=/path/to/iptables-1.4.1 make -f Makefile.linux -- install as root using : - > make -f Makefile.linux install -- A miniupnpd script should be installed to /etc/init.d - and the configuration files to /etc/miniupnpd -- anytime, you can use the netfilter/iptables_flush.sh - script to flush all rules added by the daemon. -- after killing the daemon, you can get back to - iptables initial state by running the netfilter/iptables_removeall.sh - script. Don't forget to edit the script to your convenience. - -NOTE: a /etc/init.d/miniupnpd script will be installed. - If it suits you, you can use is with start, stop or restart argument. - # /etc/init.d/miniupnpd restart - - -How to get libiptc with its headers on debian : -(Note: that should be useless now that netfilter/tiny_nf_nat.h is included) -- Use apt-get to get sources : - > apt-get source iptables - you should then have an iptables-x.x.x/ directory. -- configure and compile : - > cd iptables-x.x.x/ - > ./configure --enable-static - > make -- it is now possible to compile miniupnpd using the following command : - > IPTABLESPATH=/path/to/iptables-x.x.x make -f Makefile.linux - -======================== Linux/netfilter nftables ========================= - -work is in progress. To build : - > make -f Makefile.linux_nft - -see : -https://miniupnp.tuxfamily.org/forum/viewtopic.php?p=4370 -https://github.com/miniupnp/miniupnp/pull/114 - -=========================== Configuration ============================= -Edit the /etc/miniupnpd.conf file to set options. Almost all options are -also available through command line switches. - -A basic configuration would set : -ext_ifname : WAN network interface (interface connected to the internet) -listening_ip : LAN network interface (network where to supply NAT traversal) -enable_natpmp=yes -enable_upnp=yes -and the permission rules (see below). - -Historically, LAN had to be specified by IP/mask, such as -listening_ip=192.168.0.1/24 -but if you compiled with IPv6 support, you need to specify an interface name : -listening_ip=eth0 -The current code assumes there is only one IPv4 address assigned to LAN -interfaces. That is not the case with some CARP setup, there is then a risk -the wrong mask would be picked. You can force the mask when using interface -names : -listening_ip=eth0/24 - -Miniupnpd supports some kind of security check for allowing or disallowing -redirection to be made. The UPnP permission rules are read from the -miniupnpd.conf configuration file. -When a new redirection is requested, permission rules are evaluated in -top-down order and the first permission rule matched gives the response : -redirection allowed or denied. If no rule is matching, the redirection is -allowed, so it is a good practice to have a "catch all" deny permission -rule at the end of your permission ruleset. -Sample permission ruleset : -allow 4662-4672 192.168.1.34/32 4662-4672 -deny 0-65535 192.168.1.34/32 0-65535 -allow 1024-65535 192.168.1.0/24 1024-65535 -deny 0-65535 0.0.0.0/0 0-65535 -With this ruleset, redirections are allowed only for host on the subnet -192.168.1.0/255.255.255.0 for the ports 1024 or above. There is an exception -for the host 192.168.1.34 for which only redirections from/to port 4662 to -4672 are allowed. - -You can generate the uuid for your UPnP device with the uuidgen available -under linux. The following following OpenBSD package is also providing -a "uuid" tool : -http://www.openbsd.org/4.0_packages/i386/uuid-1.5.0.tgz-long.html -An web based uuid generator is also available : -http://kruithof.xs4all.nl/uuid/uuidgen - -On linux systems, one could also use the command -'cat /proc/sys/kernel/random/uuid' to generate an uuid. - -More simple, use the genuuid makefile target : -> make genuuid -or -> make -f Makefile.linux genuuid -This target is needed by the "install" target, so it is done automatically -during install. - -To stop the daemon use : - # kill `cat /var/run/miniupnpd.pid` -or if your linux system use /etc/init.d/ - # /etc/init.d/miniupnpd stop - - -* Signals : -miniupnpd handles the following signals : -SIGUSR1: Send public IP address change notification -SIGUSR2: Handle special actions in Tomato Firmware version - Or rewrite the lease_file -SIGINT: Close gracefully -SIGTERM: Close gracefully -SIGPIPE: Ignore - -There is code to detect change in network interfaces bsd/ifacewatcher.c and -linux/ifacewatcher.c, but if that code doesn't work for you, you may want to -send SIGUSR1 to miniupnpd if you public IP address changed. diff --git a/src/contrib/miniupnp/miniupnpd/LICENSE b/src/contrib/miniupnp/miniupnpd/LICENSE deleted file mode 100644 index c818145..0000000 --- a/src/contrib/miniupnp/miniupnpd/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -MiniUPnPd -Copyright (c) 2006-2017, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/contrib/miniupnp/miniupnpd/Makefile b/src/contrib/miniupnp/miniupnpd/Makefile deleted file mode 100644 index a9cd6b4..0000000 --- a/src/contrib/miniupnp/miniupnpd/Makefile +++ /dev/null @@ -1,274 +0,0 @@ -# $Id: Makefile,v 1.88 2016/02/10 20:32:43 nanard Exp $ -# MiniUPnP project -# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# Author: Thomas Bernard -# -# Makefile for miniupnpd (MiniUPnP daemon) -# -# This Makefile should work for *BSD and SunOS/Solaris. -# On Mac OS X, use "bsdmake" to build. -# This Makefile is NOT compatible with GNU Make. -# Linux users, please use Makefile.linux : -# make -f Makefile.linux -# -# options can be passed to genconfig.sh through CONFIG_OPTIONS : -# $ CONFIG_OPTIONS="--ipv6 --igd2" make -# - -CFLAGS ?= -pipe -Os -#CFLAGS = -pipe -O -g -DDEBUG -#CFLAGS += -ansi -CFLAGS += -Wall -CFLAGS += -W -CFLAGS += -Wstrict-prototypes -#CFLAGS += -Wdeclaration-after-statement -#CFLAGS += -Wno-missing-field-initializers -CFLAGS += -fno-common -CC ?= gcc -RM = rm -f -MV = mv -INSTALL = install -STRIP = strip - -# OSNAME and FWNAME are used for building OS or FW dependent code. -OSNAME != uname -s -ARCH != uname -m -.ifndef FWNAME -#.if exists(/usr/include/net/pfvar.h) -#FWNAME = pf -#.else -#FWNAME = ipf -#.endif - -.if $(OSNAME) == "OpenBSD" -FWNAME = pf -.endif - -# better way to find if we are using ipf or pf -.if $(OSNAME) == "FreeBSD" -.if exists(/etc/rc.subr) && exists(/etc/default/rc.conf) -FWNAME != . /etc/rc.subr; . /etc/default/rc.conf; \ - if checkyesno ipfilter_enable; then \ - echo "ipf"; elif checkyesno pf_enable; then \ - echo "pf"; elif checkyesno firewall_enable; then \ - echo "ipfw"; else echo "pf"; fi -.else -FWNAME = pf -.endif -.endif - -.if $(OSNAME) == "NetBSD" -.if exists(/etc/rc.subr) && exists(/etc/rc.conf) -FWNAME != . /etc/rc.subr; . /etc/rc.conf; \ - if checkyesno pf; then \ - echo "pf"; elif checkyesno ipfilter; then \ - echo "ipf"; else echo "pf"; fi -.else -FWNAME = pf -.endif -.endif - -.if $(OSNAME) == "DragonFly" -.if exists(/etc/rc.subr) && exists(/etc/rc.conf) -FWNAME != . /etc/rc.subr; . /etc/rc.conf; \ - if checkyesno pf; then \ - echo "pf"; elif checkyesno ipfilter; then \ - echo "ipf"; else echo "pf"; fi -.else -FWNAME = pf -.endif -.endif - -.if $(OSNAME) == "Darwin" -# Firewall is ipfw up to OS X 10.6 Snow Leopard -# and pf since OS X 10.7 Lion (Darwin 11.0) -FWNAME != [ `uname -r | cut -d. -f1` -ge 11 ] && echo "pf" || echo "ipfw" -.endif - -.endif - -# Solaris specific CFLAGS -.if $(OSNAME) == "SunOS" -CFLAGS += -DSOLARIS2=`uname -r | cut -d. -f2` -.if $(ARCH) == "amd64" -CFLAGS += -m64 -mcmodel=kernel -mno-red-zone -ffreestanding -.elif $(ARCH) == "sparc64" -CFLAGS += -m64 -mcmodel=medlow -.endif -.endif - -STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ - upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ - upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o asyncsendto.o portinuse.o -BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -MACOBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -PFOBJS = pf/obsdrdr.o pf/pfpinhole.o -IPFOBJS = ipf/ipfrdr.o -IPFWOBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o -MISCOBJS = upnpreplyparse.o minixml.o - -ALLOBJS = $(STDOBJS) $(MISCOBJS) -.if $(OSNAME) == "SunOS" -ALLOBJS += $(SUNOSOBJS) -TESTGETIFSTATSOBJS = testgetifstats.o solaris/getifstats.o -TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o -.elif $(OSNAME) == "Darwin" -ALLOBJS += $(MACOBJS) -TESTGETIFSTATSOBJS = testgetifstats.o mac/getifstats.o -TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o -.else -ALLOBJS += $(BSDOBJS) -TESTGETIFSTATSOBJS = testgetifstats.o bsd/getifstats.o -TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o -.endif - -.if $(FWNAME) == "pf" -ALLOBJS += $(PFOBJS) -.elif $(FWNAME) == "ipfw" -ALLOBJS += $(IPFWOBJS) -.else -ALLOBJS += $(IPFOBJS) -.endif - -TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o -TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o -TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o -MINIUPNPDCTLOBJS = miniupnpdctl.o -TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o -TESTPORTINUSEOBJS = testportinuse.o portinuse.o getifaddr.o -TESTMINISSDPOBJS = testminissdp.o minissdp.o upnputils.o upnpglobalvars.o \ - asyncsendto.o bsd/getroute.o - -EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ - testupnppermissions miniupnpdctl \ - testgetifaddr testgetroute testasyncsendto \ - testportinuse testssdppktgen testminissdp - -.if $(OSNAME) == "Darwin" -LIBS = -.else -LIBS = -lkvm -.endif -.if $(OSNAME) == "SunOS" -LIBS += -lsocket -lnsl -lkstat -lresolv -.endif - -LIBS += -lssl -lcrypto - -# set PREFIX variable to install in the wanted place - -INSTALLBINDIR = $(PREFIX)/sbin -INSTALLETCDIR = $(PREFIX)/etc -# INSTALLMANDIR = $(PREFIX)/man -INSTALLMANDIR = /usr/share/man - -all: $(EXECUTABLES) - -clean: - $(RM) $(STDOBJS) $(BSDOBJS) $(SUNOSOBJS) $(MACOBJS) $(EXECUTABLES) \ - testupnpdescgen.o \ - $(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \ - miniupnpdctl.o testgetifaddr.o testgetroute.o testasyncsendto.o \ - testportinuse.o \ - $(PFOBJS) $(IPFOBJS) $(IPFWOBJS) - $(RM) validateupnppermissions validategetifaddr validatessdppktgen - -install: miniupnpd genuuid - $(STRIP) miniupnpd - $(INSTALL) -d $(DESTDIR)$(INSTALLBINDIR) - $(INSTALL) -m 755 miniupnpd $(DESTDIR)$(INSTALLBINDIR) - $(INSTALL) -d $(DESTDIR)$(INSTALLETCDIR) - $(INSTALL) -b miniupnpd.conf $(DESTDIR)$(INSTALLETCDIR) - # TODO : install man page correctly -# $(INSTALL) -d $(INSTALLMANDIR) -# $(INSTALL) miniupnpd.8 $(INSTALLMANDIR)/cat8/miniupnpd.0 - -# genuuid is using the uuid cli tool available under OpenBSD 4.0 in -# the uuid-1.5.0 package -# any other cli tool returning a uuid on stdout should work. -UUID != if which uuidgen 2>&1 > /dev/null; then \ - echo `uuidgen` ; \ - elif which uuid 2>&1 > /dev/null; then \ - echo `uuid` ; \ - else echo "00000000-0000-0000-0000-000000000000"; \ - fi - -# bash or ksh -SH != which bash || which ksh - -genuuid: - $(MV) miniupnpd.conf miniupnpd.conf.before - sed -e "s/^uuid=[-0-9a-fA-F]*/uuid=$(UUID)/" miniupnpd.conf.before > miniupnpd.conf - $(RM) miniupnpd.conf.before - -check: validateupnppermissions validategetifaddr validatessdppktgen - -validateupnppermissions: testupnppermissions testupnppermissions.sh - $(SH) ./testupnppermissions.sh - touch $@ - -validategetifaddr: testgetifaddr testgetifaddr.sh - ./testgetifaddr.sh - touch $@ - -validatessdppktgen: testssdppktgen - ./testssdppktgen - touch $@ - -depend: config.h - mkdep $(ALLOBJS:.o=.c) testupnpdescgen.c testgetifstats.c \ - testupnppermissions.c miniupnpdctl.c testgetifaddr.c \ - testgetroute.c testportinuse.c testasyncsendto.c \ - testssdppktgen.c - -miniupnpd: config.h $(ALLOBJS) - $(CC) $(LDFLAGS) -o $@ $(ALLOBJS) $(LIBS) - -# BSDmake : -# $(CC) $(LDFLAGS) -o $@ $> $(LIBS) - -miniupnpdctl: config.h $(MINIUPNPDCTLOBJS) - $(CC) $(LDFLAGS) -o $@ $(MINIUPNPDCTLOBJS) - -testupnpdescgen: config.h $(TESTUPNPDESCGENOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTUPNPDESCGENOBJS) $(LIBS) - -testgetifstats: config.h $(TESTGETIFSTATSOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETIFSTATSOBJS) $(LIBS) - -testgetifaddr: config.h $(TESTGETIFADDROBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETIFADDROBJS) $(LIBS) - -testupnppermissions: config.h $(TESTUPNPPERMISSIONSOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTUPNPPERMISSIONSOBJS) $(LIBS) - -testgetroute: config.h $(TESTGETROUTEOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETROUTEOBJS) $(LIBS) - -testasyncsendto: config.h $(TESTASYNCSENDTOOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTASYNCSENDTOOBJS) - -testportinuse: config.h $(TESTPORTINUSEOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTPORTINUSEOBJS) $(LIBS) - -testminissdp: config.h $(TESTMINISSDPOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTMINISSDPOBJS) $(LIBS) - -# gmake : -# $(CC) $(CFLAGS) -o $@ $^ -# BSDmake : -# $(CC) $(CFLAGS) -o $@ $> - -config.h: genconfig.sh VERSION - ./genconfig.sh $(CONFIG_OPTIONS) - -.SUFFIXES: .o .c -.c.o: - $(CC) $(CFLAGS) -c -o $@ $< - -# $(CC) $(CFLAGS) -c -o $(.TARGET) $(.IMPSRC) - - diff --git a/src/contrib/miniupnp/miniupnpd/Makefile.linux b/src/contrib/miniupnp/miniupnpd/Makefile.linux deleted file mode 100644 index e978fd2..0000000 --- a/src/contrib/miniupnp/miniupnpd/Makefile.linux +++ /dev/null @@ -1,343 +0,0 @@ -# $Id: Makefile.linux,v 1.95 2017/12/12 11:40:14 nanard Exp $ -# MiniUPnP project -# (c) 2006-2017 Thomas Bernard -# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# Author : Thomas Bernard -# for use with GNU Make -# -# options can be passed to genconfig.sh through CONFIG_OPTIONS : -# $ CONFIG_OPTIONS="--ipv6 --igd2" make -f Makefile.linux -# -# To install use : -# $ DESTDIR=/dummyinstalldir make -f Makefile.linux install -# or : -# $ INSTALLPREFIX=/usr/local make -f Makefile.linux install -# or : -# $ make -f Makefile.linux install -# (default INSTALLPREFIX is /usr) -# -# if your system hasn't iptables libiptc headers and binary correctly -# installed, you need to get iptables sources from http://netfilter.org/ -# ./configure them and build them then miniupnpd will build using : -# $ IPTABLESPATH=/path/to/iptables-1.4.1 make -f Makefile.linux -# -#CFLAGS = -O -g -DDEBUG -CFLAGS ?= -Os -CFLAGS += -fno-strict-aliasing -CFLAGS += -fno-common -CPPFLAGS += -D_GNU_SOURCE -CFLAGS += -Wall -CFLAGS += -Wextra -Wstrict-prototypes -Wdeclaration-after-statement -#CFLAGS += -Wno-missing-field-initializers -#CFLAGS += -ansi # iptables headers does use typeof which is a gcc extension -CC ?= gcc -RM = rm -f -INSTALL = install -STRIP ?= strip -PKG_CONFIG ?= pkg-config -CP = cp - - -INSTALLPREFIX ?= $(PREFIX)/usr -SBININSTALLDIR = $(INSTALLPREFIX)/sbin -ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd -MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8 - -BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ - upnpreplyparse.o minixml.o portinuse.o \ - upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ - upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o pcplearndscp.o asyncsendto.o - -LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o -NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o netfilter/nfct_get.o - -ALLOBJS = $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS) - -PCFILE_FOUND := $(shell $(PKG_CONFIG) --exists libiptc; echo $$?) - -ifeq (${PCFILE_FOUND},0) - -IPTABLESVERSION := $(shell $(PKG_CONFIG) --modversion libiptc) -IPTVER1 := $(shell echo $(IPTABLESVERSION) | cut -d. -f1 ) -IPTVER2 := $(shell echo $(IPTABLESVERSION) | cut -d. -f2 ) -IPTVER3 := $(shell echo $(IPTABLESVERSION) | cut -d. -f3 ) -# test if iptables version >= 1.4.3 -TEST := $(shell [ $(IPTVER1) -gt 1 ] || \ - [ \( $(IPTVER1) -eq 1 \) -a \ - \( \( $(IPTVER2) -gt 4 \) -o \ - \( \( $(IPTVER2) -eq 4 \) -a \( $(IPTVER3) -ge 3 \) \) \) ] && echo 1 ) -ifeq ($(TEST), 1) -CPPFLAGS += -DIPTABLES_143 -endif - -CFLAGS += $(shell $(PKG_CONFIG) --cflags libiptc) -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libiptc) -LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libiptc) -LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-other libiptc) -else - -ifeq "$(wildcard /etc/gentoo-release )" "" -LDLIBS ?= -liptc -else # gentoo -# the following is better, at least on gentoo with iptables 1.4.6 -# see http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1618 -# and http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=2183 -LDLIBS ?= -lip4tc -CPPFLAGS := -DIPTABLES_143 $(CPPFLAGS) -endif - -ARCH ?= $(shell uname -m | grep -q "x86_64" && echo 64) -ifdef IPTABLESPATH -CPPFLAGS := $(CPPFLAGS) -I$(IPTABLESPATH)/include/ -LDFLAGS := $(LDFLAFGS) -L$(IPTABLESPATH)/libiptc/ -# get iptables version and set IPTABLES_143 macro if needed -ifeq ($(TARGET_OPENWRT),) -IPTABLESVERSION := $(shell grep "\#define VERSION" $(IPTABLESPATH)/config.h | tr -d \" |cut -d" " -f3 ) -IPTVER1 := $(shell echo $(IPTABLESVERSION) | cut -d. -f1 ) -IPTVER2 := $(shell echo $(IPTABLESVERSION) | cut -d. -f2 ) -IPTVER3 := $(shell echo $(IPTABLESVERSION) | cut -d. -f3 ) -# test if iptables version >= 1.4.3 -TEST := $(shell [ $(IPTVER1) -gt 1 ] || \ - [ \( $(IPTVER1) -eq 1 \) -a \ - \( \( $(IPTVER2) -gt 4 \) -o \ - \( \( $(IPTVER2) -eq 4 \) -a \( $(IPTVER3) -ge 3 \) \) \) ] && echo 1 ) -ifeq ($(TEST), 1) -CPPFLAGS := $(CPPFLAGS) -DIPTABLES_143 -# the following sucks, but works -LDLIBS = $(IPTABLESPATH)/libiptc/.libs/libip4tc.o -#LDLIBS = $(IPTABLESPATH)/libiptc/.libs/libiptc.a -else # ifeq ($(TEST), 1) -LDLIBS = $(IPTABLESPATH)/libiptc/libiptc.a -endif # ifeq ($(TEST), 1) -else # ($(TARGET_OPENWRT),) -# openWRT : -# check for system-wide iptables files. Test if iptables version >= 1.4.3 -# the following test has to be verified : -TEST := $(shell test -f /usr/include/iptables/internal.h && grep -q "\#define IPTABLES_VERSION" /usr/include/iptables/internal.h && echo 1) -ifeq ($(TEST), 1) -CPPFLAGS := $(CPPFLAGS) -DIPTABLES_143 -LDLIBS = -liptc -endif # ($(TEST), 1) -TEST_LIB := $(shell test -f /usr/lib$(ARCH)/libiptc.a && echo 1) -ifeq ($(TEST_LIB), 1) -LDLIBS = -liptc /usr/lib$(ARCH)/libiptc.a -endif # ($(TEST_LIB), 1) -endif # ($(TARGET_OPENWRT),) -else # ifdef IPTABLESPATH -# IPTABLESPATH not defined -# the following test has to be verified : -TEST := $(shell test -f /usr/include/xtables.h && grep -q "XTABLES_VERSION_CODE" /usr/include/xtables.h && echo 1) -ifeq ($(TEST), 1) -CPPFLAGS := $(CPPFLAGS) -DIPTABLES_143 -LDLIBS = -liptc -TESTIP4TC := $(shell test -f /lib/libip4tc.so && echo 1) -ifeq ($(TESTIP4TC), 1) -LDLIBS := $(LDLIBS) -lip4tc -endif # ($(TESTIP4TC), 1) -TESTIP6TC := $(shell test -f /lib/libip6tc.so && echo 1) -ifeq ($(TESTIP6TC), 1) -LDLIBS := $(LDLIBS) -lip6tc -endif # ($(TESTIP6TC), 1) -endif # ($(TEST), 1) -endif # ifdef IPTABLESPATH -endif # ifdef PCFILE_FOUND - -#LDLIBS += -lnfnetlink - -TEST := $(shell $(PKG_CONFIG) --atleast-version=1.0.2 libnetfilter_conntrack && $(PKG_CONFIG) --atleast-version=1.0.3 libmnl && echo 1) -ifeq ($(TEST),1) -CPPFLAGS += -DUSE_NFCT -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libmnl) -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libnetfilter_conntrack) -endif # ($(TEST),1) - -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libssl) - -TEST := $(shell $(PKG_CONFIG) --exists uuid && echo 1) -ifeq ($(TEST),1) -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l uuid) -else -$(info please install uuid-dev package / libuuid) -endif # ($(TEST),1) - -TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o - -EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ - testupnppermissions miniupnpdctl testgetifaddr \ - testgetroute testasyncsendto testportinuse \ - testssdppktgen testminissdp - -.PHONY: all clean install depend genuuid - -all: $(EXECUTABLES) - -clean: - $(RM) $(ALLOBJS) - $(RM) $(EXECUTABLES) - $(RM) testupnpdescgen.o testgetifstats.o - $(RM) testupnppermissions.o testgetifaddr.o - $(RM) testgetroute.o testasyncsendto.o - $(RM) testportinuse.o - $(RM) miniupnpdctl.o - $(RM) validateupnppermissions validategetifaddr validatessdppktgen - -install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \ - netfilter/iptables_init.sh netfilter/iptables_removeall.sh \ - netfilter/ip6tables_init.sh netfilter/ip6tables_removeall.sh \ - netfilter/miniupnpd_functions.sh \ - linux/miniupnpd.init.d.script - $(STRIP) miniupnpd - $(INSTALL) -d $(DESTDIR)$(SBININSTALLDIR) - $(INSTALL) miniupnpd $(DESTDIR)$(SBININSTALLDIR) - $(INSTALL) -d $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/iptables_init.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/iptables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/ip6tables_init.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/ip6tables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/miniupnpd_functions.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) --mode=0644 -b miniupnpd.conf $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) -d $(DESTDIR)$(PREFIX)/etc/init.d - $(INSTALL) linux/miniupnpd.init.d.script $(DESTDIR)$(PREFIX)/etc/init.d/miniupnpd - $(INSTALL) -d $(DESTDIR)$(MANINSTALLDIR) - $(INSTALL) --mode=0644 miniupnpd.8 $(DESTDIR)$(MANINSTALLDIR) - gzip -f $(DESTDIR)$(MANINSTALLDIR)/miniupnpd.8 - -# genuuid is using the uuidgen CLI tool which is part of libuuid -# from the e2fsprogs -# 'cat /proc/sys/kernel/random/uuid' could be also used -genuuid: -ifeq ($(TARGET_OPENWRT),) - sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`(genuuid||uuidgen||uuid) 2>/dev/null`/" miniupnpd.conf -else - sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`($(STAGING_DIR_HOST)/bin/genuuid||$(STAGING_DIR_HOST)/bin/uuidgen||$(STAGING_DIR_HOST)/bin/uuid) 2>/dev/null`/" miniupnpd.conf -endif - -check: validateupnppermissions validategetifaddr validatessdppktgen - -validateupnppermissions: testupnppermissions testupnppermissions.sh - ./testupnppermissions.sh - touch $@ - -validategetifaddr: testgetifaddr testgetifaddr.sh - ./testgetifaddr.sh - touch $@ - -validatessdppktgen: testssdppktgen - ./testssdppktgen - touch $@ - -miniupnpd: $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS) - -testupnpdescgen: $(TESTUPNPDESCGENOBJS) - -testgetifstats: testgetifstats.o linux/getifstats.o - -testupnppermissions: testupnppermissions.o upnppermissions.o - -testgetifaddr: testgetifaddr.o getifaddr.o - -testgetroute: testgetroute.o linux/getroute.o upnputils.o - -testssdppktgen: testssdppktgen.o - -testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \ - linux/getroute.o - -testportinuse: testportinuse.o portinuse.o getifaddr.o \ - netfilter/iptcrdr.o - -testminissdp: testminissdp.o minissdp.o upnputils.o upnpglobalvars.o \ - asyncsendto.o linux/getroute.o - - -miniupnpdctl: miniupnpdctl.o - -config.h: genconfig.sh VERSION - ./genconfig.sh $(CONFIG_OPTIONS) - -depend: config.h - makedepend -f$(MAKEFILE_LIST) -Y \ - $(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \ - testgetifstats.c testupnppermissions.c testgetifaddr.c \ - testgetroute.c testasyncsendto.c testportinuse.c \ - miniupnpdctl.c testssdppktgen.c 2>/dev/null - -# DO NOT DELETE - -miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h -miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h -miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h -miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h asyncsendto.h natpmp.h -miniupnpd.o: pcpserver.h commonrdr.h upnputils.h ifacewatcher.h -upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h -upnphttp.o: upnpevents.h upnputils.h upnpglobalvars.h upnppermissions.h -upnphttp.o: miniupnpdtypes.h -upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h -upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h -upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h -upnpsoap.o: macros.h config.h upnpglobalvars.h upnppermissions.h -upnpsoap.o: miniupnpdtypes.h upnphttp.h upnpsoap.h upnpreplyparse.h -upnpsoap.o: upnpredirect.h upnppinhole.h getifaddr.h getifstats.h -upnpsoap.o: getconnstatus.h upnpurns.h -upnpreplyparse.o: upnpreplyparse.h minixml.h -minixml.o: minixml.h -portinuse.o: macros.h config.h upnpglobalvars.h upnppermissions.h -portinuse.o: miniupnpdtypes.h getifaddr.h portinuse.h netfilter/iptcrdr.h -portinuse.o: commonrdr.h -upnpredirect.o: macros.h config.h upnpredirect.h upnpglobalvars.h -upnpredirect.o: upnppermissions.h miniupnpdtypes.h upnpevents.h portinuse.h -upnpredirect.o: netfilter/iptcrdr.h commonrdr.h -getifaddr.o: config.h getifaddr.h -daemonize.o: daemonize.h config.h -upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h -upnpglobalvars.o: miniupnpdtypes.h upnpdescstrings.h -options.o: config.h options.h upnppermissions.h upnpglobalvars.h -options.o: miniupnpdtypes.h -upnppermissions.o: config.h upnppermissions.h -minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h -minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h -minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h macros.h -natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h -natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h -natpmp.o: portinuse.h asyncsendto.h -pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h -pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h -pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h netfilter/iptcrdr.h -pcpserver.o: commonrdr.h -upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h -upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h -upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h -upnputils.o: miniupnpdtypes.h getroute.h -getconnstatus.o: getconnstatus.h getifaddr.h -upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h -upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h upnppinhole.h -upnppinhole.o: netfilter/iptpinhole.h -pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h -pcplearndscp.o: pcplearndscp.h -asyncsendto.o: asyncsendto.h upnputils.h -linux/getifstats.o: config.h getifstats.h -linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h -linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h -linux/ifacewatcher.o: upnppermissions.h natpmp.h -linux/getroute.o: getroute.h upnputils.h -netfilter/iptcrdr.o: macros.h config.h netfilter/iptcrdr.h commonrdr.h -netfilter/iptcrdr.o: config.h upnpglobalvars.h upnppermissions.h -netfilter/iptcrdr.o: miniupnpdtypes.h -netfilter/iptpinhole.o: config.h netfilter/iptpinhole.h upnpglobalvars.h -netfilter/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h -testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h -testupnpdescgen.o: getifaddr.h -upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h -upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h -upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h -testgetifstats.o: getifstats.h -testupnppermissions.o: upnppermissions.h config.h -testgetifaddr.o: config.h getifaddr.h -testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h -testgetroute.o: config.h miniupnpdtypes.h -testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h -testportinuse.o: macros.h config.h portinuse.h -miniupnpdctl.o: macros.h -testssdppktgen.o: macros.h config.h miniupnpdpath.h upnphttp.h diff --git a/src/contrib/miniupnp/miniupnpd/Makefile.linux_nft b/src/contrib/miniupnp/miniupnpd/Makefile.linux_nft deleted file mode 100644 index 0c03ca3..0000000 --- a/src/contrib/miniupnp/miniupnpd/Makefile.linux_nft +++ /dev/null @@ -1,231 +0,0 @@ -# MiniUPnP project -# (c) 2015 Tomofumi Hayashi -# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# Author : Tomofumi Hayashi -# for use with GNU Make -# -# options can be passed to genconfig.sh through CONFIG_OPTIONS : -# $ CONFIG_OPTIONS="--ipv6 --igd2" make -f Makefile.linux -# -# To install use : -# $ DESTDIR=/dummyinstalldir make -f Makefile.linux_nft install -# or : -# $ INSTALLPREFIX=/usr/local make -f Makefile.linux_nft install -# or : -# $ make -f Makefile.linux install -# (default INSTALLPREFIX is /usr) -# -# -CFLAGS = -O -g #-DDEBUG -CFLAGS ?= -Os -CFLAGS += -fno-strict-aliasing -CFLAGS += -fno-common -CPPFLAGS += -D_GNU_SOURCE -CFLAGS += -Wall -CFLAGS += -Wextra -Wstrict-prototypes -Wdeclaration-after-statement -#CFLAGS += -Wno-missing-field-initializers -CC ?= gcc -RM = rm -f -INSTALL = install -STRIP ?= strip -PKG_CONFIG ?= pkg-config -CP = cp - - -INSTALLPREFIX ?= $(PREFIX)/usr -SBININSTALLDIR = $(INSTALLPREFIX)/sbin -ETCINSTALLDIR = $(PREFIX)/etc/miniupnpd -MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8 - -BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ - upnpreplyparse.o minixml.o portinuse.o \ - upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ - upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o pcplearndscp.o asyncsendto.o - -LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o -NETFILTEROBJS = netfilter_nft/nftnlrdr.o netfilter_nft/nfct_get.o netfilter_nft/nftnlrdr_misc.o - -ALLOBJS = $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS) - -PCFILE_FOUND := $(shell $(PKG_CONFIG) --exists libnftnl; echo $$?) - -ifeq (${PCFILE_FOUND},0) - -PKG_CONFIG_LIBS = libnftnl libmnl -CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PKG_CONFIG_LIBS)) -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l $(PKG_CONFIG_LIBS)) -LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L $(PKG_CONFIG_LIBS)) -LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-other $(PKG_CONFIG_LIBS)) -else - -ARCH ?= $(shell uname -m | grep -q "x86_64" && echo 64) -endif # ifdef PCFILE_FOUND - -#LDLIBS += -lnfnetlink - -TEST := $(shell $(PKG_CONFIG) --atleast-version=1.0.2 libnetfilter_conntrack && $(PKG_CONFIG) --atleast-version=1.0.3 libmnl && echo 1) -ifeq ($(TEST),1) -CPPFLAGS += -DUSE_NFCT -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libmnl) -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libnetfilter_conntrack) -endif # ($(TEST),1) - -LDLIBS += $(shell $(PKG_CONFIG) --static --libs-only-l libssl) - -TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o - -EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ - testupnppermissions miniupnpdctl testgetifaddr \ - testgetroute testasyncsendto testportinuse - -.PHONY: all clean install depend genuuid - -all: $(EXECUTABLES) - -clean: - $(RM) $(ALLOBJS) - $(RM) $(EXECUTABLES) - $(RM) testupnpdescgen.o testgetifstats.o - $(RM) testupnppermissions.o testgetifaddr.o - $(RM) testgetroute.o testasyncsendto.o - $(RM) testportinuse.o - $(RM) miniupnpdctl.o - -install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \ - netfilter/iptables_init.sh netfilter/iptables_removeall.sh \ - netfilter/ip6tables_init.sh netfilter/ip6tables_removeall.sh \ - netfilter/miniupnpd_functions.sh \ - linux/miniupnpd.init.d.script - $(STRIP) miniupnpd - $(INSTALL) -d $(DESTDIR)$(SBININSTALLDIR) - $(INSTALL) miniupnpd $(DESTDIR)$(SBININSTALLDIR) - $(INSTALL) -d $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/iptables_init.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/iptables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/ip6tables_init.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/ip6tables_removeall.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) netfilter/miniupnpd_functions.sh $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) --mode=0644 -b miniupnpd.conf $(DESTDIR)$(ETCINSTALLDIR) - $(INSTALL) -d $(DESTDIR)$(PREFIX)/etc/init.d - $(INSTALL) linux/miniupnpd.init.d.script $(DESTDIR)$(PREFIX)/etc/init.d/miniupnpd - $(INSTALL) -d $(DESTDIR)$(MANINSTALLDIR) - $(INSTALL) --mode=0644 miniupnpd.8 $(DESTDIR)$(MANINSTALLDIR) - gzip -f $(DESTDIR)$(MANINSTALLDIR)/miniupnpd.8 - -# genuuid is using the uuidgen CLI tool which is part of libuuid -# from the e2fsprogs -# 'cat /proc/sys/kernel/random/uuid' could be also used -genuuid: -ifeq ($(TARGET_OPENWRT),) - sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`(genuuid||uuidgen||uuid) 2>/dev/null`/" miniupnpd.conf -else - sed -i -e "s/^uuid=[-0-9a-f]*/uuid=`($(STAGING_DIR_HOST)/bin/genuuid||$(STAGING_DIR_HOST)/bin/uuidgen||$(STAGING_DIR_HOST)/bin/uuid) 2>/dev/null`/" miniupnpd.conf -endif - -miniupnpd: $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS) - -testupnpdescgen: $(TESTUPNPDESCGENOBJS) - -testgetifstats: testgetifstats.o linux/getifstats.o - -testupnppermissions: testupnppermissions.o upnppermissions.o - -testgetifaddr: testgetifaddr.o getifaddr.o - -testgetroute: testgetroute.o linux/getroute.o upnputils.o - -testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \ - linux/getroute.o - -testportinuse: testportinuse.o portinuse.o getifaddr.o \ - netfilter_nft/nftnlrdr.o netfilter_nft/nftnlrdr_misc.o - -miniupnpdctl: miniupnpdctl.o - -config.h: genconfig.sh VERSION - ./genconfig.sh $(CONFIG_OPTIONS) - -depend: config.h - makedepend -f$(MAKEFILE_LIST) -Y \ - $(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \ - testgetifstats.c testupnppermissions.c testgetifaddr.c \ - testgetroute.c testasyncsendto.c testportinuse.c \ - miniupnpdctl.c 2>/dev/null - -# DO NOT DELETE - -miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h -miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h -miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h -miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h asyncsendto.h natpmp.h -miniupnpd.o: pcpserver.h commonrdr.h upnputils.h ifacewatcher.h -upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h -upnphttp.o: upnpevents.h upnputils.h -upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h -upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h -upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h -upnpsoap.o: macros.h config.h upnpglobalvars.h upnppermissions.h -upnpsoap.o: miniupnpdtypes.h upnphttp.h upnpsoap.h upnpreplyparse.h -upnpsoap.o: upnpredirect.h upnppinhole.h getifaddr.h getifstats.h -upnpsoap.o: getconnstatus.h upnpurns.h -upnpreplyparse.o: upnpreplyparse.h minixml.h -minixml.o: minixml.h -portinuse.o: macros.h config.h upnpglobalvars.h upnppermissions.h -portinuse.o: miniupnpdtypes.h getifaddr.h portinuse.h netfilter_nft/nftnlrdr.h -portinuse.o: commonrdr.h -upnpredirect.o: macros.h config.h upnpredirect.h upnpglobalvars.h -upnpredirect.o: upnppermissions.h miniupnpdtypes.h upnpevents.h portinuse.h -upnpredirect.o: netfilter_nft/nftnlrdr.h commonrdr.h -getifaddr.o: config.h getifaddr.h -daemonize.o: daemonize.h config.h -upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h -upnpglobalvars.o: miniupnpdtypes.h upnpdescstrings.h -options.o: config.h options.h upnppermissions.h upnpglobalvars.h -options.o: miniupnpdtypes.h -upnppermissions.o: config.h upnppermissions.h -minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h -minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h -minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h -natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h -natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h -natpmp.o: portinuse.h asyncsendto.h -pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h -pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h -pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h netfilter_nft/nftnlrdr.h -pcpserver.o: commonrdr.h -upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h -upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h -upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h -upnputils.o: miniupnpdtypes.h getroute.h -getconnstatus.o: getconnstatus.h getifaddr.h -upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h -upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h -#upnppinhole.o: netfilter/iptpinhole.h -pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h -pcplearndscp.o: pcplearndscp.h -asyncsendto.o: asyncsendto.h -linux/getifstats.o: config.h getifstats.h -linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h -linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h -linux/ifacewatcher.o: upnppermissions.h natpmp.h -linux/getroute.o: getroute.h upnputils.h -netfilter_nft/nftnlrdr.o: macros.h config.h netfilter_nft/nftnlrdr.h commonrdr.h -netfilter_nft/nftnlrdr.o: config.h upnpglobalvars.h upnppermissions.h -netfilter_nft/nftnlrdr.o: miniupnpdtypes.h -netfilter_nft/iptpinhole.o: config.h netfilter_nft/iptpinhole.h upnpglobalvars.h -netfilter_nft/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h -testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h -testupnpdescgen.o: getifaddr.h -upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h -upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h -upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h -testgetifstats.o: getifstats.h -testupnppermissions.o: upnppermissions.h config.h -testgetifaddr.o: config.h getifaddr.h -testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h -testgetroute.o: config.h miniupnpdtypes.h -testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h -testportinuse.o: macros.h config.h portinuse.h -miniupnpdctl.o: macros.h diff --git a/src/contrib/miniupnp/miniupnpd/Makefile.macosx b/src/contrib/miniupnp/miniupnpd/Makefile.macosx deleted file mode 100644 index 3a01f7f..0000000 --- a/src/contrib/miniupnp/miniupnpd/Makefile.macosx +++ /dev/null @@ -1,132 +0,0 @@ -# MiniUPnP project -# http://miniupnp.free.fr/ -# Author: Thomas Bernard -# This Makefile should work for MacOSX -# -# To compile with pf with OS X 10.7+, you need to specify -# path to XNU bsd sources : -# INCLUDES="-I.../xnu/bsd -I.../xnu/libkern" make -f Makefile.macosx -# -# To install use : -# $ PREFIX=/dummyinstalldir make -f Makefile.macosx install -# or : -# $ make -f Makefile.macosx install -# -CFLAGS = -Wall -O -g3 -DDEBUG -#CFLAGS = -Wall -Os -#CC = gcc #better use clang ! -RM = rm -f -MV = mv -INSTALL = install -STRIP = strip - -# OSNAME and FWNAME are used for building OS or FW dependent code. -OSNAME = $(shell uname) -ARCH = $(shell uname -p) -# Firewall is ipfw up to OS X 10.6 Snow Leopard -# and pf since OS X 10.7 Lion (Darwin 11.0) -FWNAME = $(shell [ `uname -r | cut -d. -f1` -ge 11 ] && echo "pf" || echo "ipfw" ) - -STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ - upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o \ - upnpevents.o getconnstatus.o upnputils.o \ - upnppinhole.o asyncsendto.o portinuse.o pcpserver.o -MAC_OBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -IPFW_OBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o -PF_OBJS = pf/obsdrdr.o -# pf/pfpinhole.o # SHOULD be used, but doesn't compile on e.g. OS X 10.9. -MISC_OBJS = upnpreplyparse.o minixml.o - -ALL_OBJS = $(STD_OBJS) $(MISC_OBJS) $(MAC_OBJS) -ifeq ($(FWNAME), ipfw) - ALL_OBJS += $(IPFW_OBJS) -else - ALL_OBJS += $(PF_OBJS) - CFLAGS += -DPF -endif - -TEST_UPNPDESCGEN_OBJS = testupnpdescgen.o upnpdescgen.o -TEST_GETIFSTATS_OBJS = testgetifstats.o mac/getifstats.o -TEST_UPNPPERMISSIONS_OBJS = testupnppermissions.o upnppermissions.o -TEST_GETIFADDR_OBJS = testgetifaddr.o getifaddr.o -TEST_PORTINUSE_OBJS = testportinuse.o portinuse.o getifaddr.o -TEST_ASYNCSENDTO_OBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o -MINIUPNPDCTL_OBJS = miniupnpdctl.o - -EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ - testupnppermissions miniupnpdctl \ - testgetifaddr testportinuse testasyncsendto - -LIBS = - -# set PREFIX variable to install in the wanted place - -INSTALL_BINDIR = $(PREFIX)/sbin -INSTALL_ETCDIR = $(PREFIX)/etc/miniupnpd -INSTALL_MANDIR = $(PREFIX)/share/man/man8 - -all: $(EXECUTABLES) - -clean: - $(RM) $(ALL_OBJS) $(EXECUTABLES) \ - testupnpdescgen.o testgetifstats.o testupnppermissions.o \ - miniupnpdctl.o testgetifaddr.o config.h \ - mac/org.tuxfamily.miniupnpd.plist - -install: miniupnpd genuuid genlaunchd - $(STRIP) miniupnpd - $(INSTALL) -d $(INSTALL_BINDIR) - $(INSTALL) miniupnpd $(INSTALL_BINDIR) - $(INSTALL) -d $(INSTALL_ETCDIR) - $(INSTALL) -m 0644 -b miniupnpd.conf $(INSTALL_ETCDIR) - $(INSTALL) -d $(INSTALL_MANDIR) - $(INSTALL) miniupnpd.8 $(INSTALL_MANDIR) - $(INSTALL) -d $(PREFIX)/Library/LaunchDaemons - $(INSTALL) mac/org.tuxfamily.miniupnpd.plist $(PREFIX)/Library/LaunchDaemons - #$(INSTALL) ipfw/ipfw_init.sh $(INSTALL_ETCDIR) - #$(INSTALL) ipfw/ipfw_removeall.sh $(INSTALL_ETCDIR) - -genuuid: - $(MV) miniupnpd.conf miniupnpd.conf.before - sed -e "s/^uuid=[-0-9a-fA-F]*/uuid=`uuidgen 2>/dev/null`/" miniupnpd.conf.before > miniupnpd.conf - $(RM) miniupnpd.conf.before - -genlaunchd: - sed -e "s|INSTALLPREFIX|$(PREFIX)|g" mac/org.tuxfamily.miniupnpd.plist.before > mac/org.tuxfamily.miniupnpd.plist - -depend: config.h - mkdep $(ALL_OBJS:.o=.c) testupnpdescgen.c testgetifstats.c \ - testupnppermissions.c miniupnpdctl.c testgetifaddr.c - -miniupnpd: config.h $(ALL_OBJS) - $(CC) $(CFLAGS) -o $@ $(ALL_OBJS) $(LIBS) - -miniupnpdctl: config.h $(MINIUPNPDCTL_OBJS) - $(CC) $(CFLAGS) -o $@ $(MINIUPNPDCTL_OBJS) - -testupnpdescgen: config.h $(TEST_UPNPDESCGEN_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_UPNPDESCGEN_OBJS) - -testgetifstats: config.h $(TEST_GETIFSTATS_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_GETIFSTATS_OBJS) $(LIBS) - -testgetifaddr: config.h $(TEST_GETIFADDR_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_GETIFADDR_OBJS) - -testupnppermissions: config.h $(TEST_UPNPPERMISSIONS_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_UPNPPERMISSIONS_OBJS) - -testasyncsendto: config.h $(TEST_ASYNCSENDTO_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_ASYNCSENDTO_OBJS) - -testportinuse: config.h $(TEST_PORTINUSE_OBJS) - $(CC) $(CFLAGS) -o $@ $(TEST_PORTINUSE_OBJS) - -config.h: genconfig.sh - ./genconfig.sh - -.SUFFIXES: .o .c -.c.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -# $(CC) $(CFLAGS) -c -o $(.TARGET) $(.IMPSRC) diff --git a/src/contrib/miniupnp/miniupnpd/Makefile.sunos b/src/contrib/miniupnp/miniupnpd/Makefile.sunos deleted file mode 100644 index 704d766..0000000 --- a/src/contrib/miniupnp/miniupnpd/Makefile.sunos +++ /dev/null @@ -1,202 +0,0 @@ -# $Id: Makefile,v 1.88 2016/02/10 20:32:43 nanard Exp $ -# MiniUPnP project -# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# Author: Thomas Bernard -# -# Makefile for miniupnpd (MiniUPnP daemon) -# -# This Makefile should work for SunOS/Solaris. -# This Makefile is NOT compatible with GNU Make. -# Linux users, please use Makefile.linux : -# make -f Makefile.linux -# -# options can be passed to genconfig.sh through CONFIG_OPTIONS : -# $ CONFIG_OPTIONS="--ipv6 --igd2" make -# - -CFLAGS = -pipe -Os -#CFLAGS = -pipe -O -g -DDEBUG -#CFLAGS += -ansi -CFLAGS += -Wall -CFLAGS += -W -CFLAGS += -Wstrict-prototypes -#CFLAGS += -Wdeclaration-after-statement -#CFLAGS += -Wno-missing-field-initializers -CFLAGS += -fno-common -CFLAGS += -D_XOPEN_SOURCE -CFLAGS += -D_XOPEN_SOURCE_EXTENDED=1 -CFLAGS += -D__EXTENSIONS__ -CC = gcc -RM = rm -f -MV = mv -INSTALL = install -STRIP = strip - -# OSNAME and FWNAME are used for building OS or FW dependent code. -OSNAME :sh = uname -s -ARCH :sh = uname -m - -FWNAME = ipf - -# Solaris specific CFLAGS -CFLAGS :sh += echo "-DSOLARIS2=`uname -r | cut -d. -f2`" -# "amd64" -CFLAGS += -m64 -mcmodel=kernel -mno-red-zone -ffreestanding -# "sparc64" -#CFLAGS += -m64 -mcmodel=medlow -LDFLAGS += -m64 - -STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ - upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ - upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o asyncsendto.o portinuse.o -BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -MACOBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o -PFOBJS = pf/obsdrdr.o pf/pfpinhole.o -IPFOBJS = ipf/ipfrdr.o -IPFWOBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o -MISCOBJS = upnpreplyparse.o minixml.o - -ALLOBJS = $(STDOBJS) $(MISCOBJS) -ALLOBJS += $(SUNOSOBJS) -TESTGETIFSTATSOBJS = testgetifstats.o solaris/getifstats.o -TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o - -#.if $(FWNAME) == "pf" -#ALLOBJS += $(PFOBJS) -#.elif $(FWNAME) == "ipfw" -#ALLOBJS += $(IPFWOBJS) -#.else -ALLOBJS += $(IPFOBJS) -#.endif - -TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o -TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o -TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o -MINIUPNPDCTLOBJS = miniupnpdctl.o -TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o -TESTPORTINUSEOBJS = testportinuse.o portinuse.o getifaddr.o - -EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ - testupnppermissions miniupnpdctl \ - testgetifaddr testgetroute testasyncsendto \ - testportinuse testssdppktgen - -LIBS += -lsocket -lnsl -lkstat -lresolv -LIBS += -luuid - -LIBS += -lssl -lcrypto - -# set PREFIX variable to install in the wanted place - -INSTALLBINDIR = $(PREFIX)/sbin -INSTALLETCDIR = $(PREFIX)/etc -# INSTALLMANDIR = $(PREFIX)/man -INSTALLMANDIR = /usr/share/man - -all: $(EXECUTABLES) - -clean: - $(RM) $(STDOBJS) $(BSDOBJS) $(SUNOSOBJS) $(MACOBJS) $(EXECUTABLES) \ - testupnpdescgen.o \ - $(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \ - miniupnpdctl.o testgetifaddr.o testgetroute.o testasyncsendto.o \ - testportinuse.o \ - $(PFOBJS) $(IPFOBJS) $(IPFWOBJS) - $(RM) validateupnppermissions validategetifaddr validatessdppktgen - -install: miniupnpd genuuid - $(STRIP) miniupnpd - $(INSTALL) -d $(DESTDIR)$(INSTALLBINDIR) - $(INSTALL) -m 755 miniupnpd $(DESTDIR)$(INSTALLBINDIR) - $(INSTALL) -d $(DESTDIR)$(INSTALLETCDIR) - $(INSTALL) -b miniupnpd.conf $(DESTDIR)$(INSTALLETCDIR) - # TODO : install man page correctly -# $(INSTALL) -d $(INSTALLMANDIR) -# $(INSTALL) miniupnpd.8 $(INSTALLMANDIR)/cat8/miniupnpd.0 - -# genuuid is using the uuid cli tool available under OpenBSD 4.0 in -# the uuid-1.5.0 package -# any other cli tool returning a uuid on stdout should work. -UUID :sh = if which uuidgen 2>&1 > /dev/null; then \ - echo `uuidgen` ; \ - elif which uuid 2>&1 > /dev/null; then \ - echo `uuid` ; \ - else echo "00000000-0000-0000-0000-000000000000"; \ - fi - -# bash or ksh -SH :sh = which bash || which ksh - -genuuid: - $(MV) miniupnpd.conf miniupnpd.conf.before - sed -e "s/^uuid=[-0-9a-fA-F]*/uuid=$(UUID)/" miniupnpd.conf.before > miniupnpd.conf - $(RM) miniupnpd.conf.before - -check: validateupnppermissions validategetifaddr validatessdppktgen - -validateupnppermissions: testupnppermissions testupnppermissions.sh - $(SH) ./testupnppermissions.sh - touch $@ - -validategetifaddr: testgetifaddr testgetifaddr.sh - ./testgetifaddr.sh - touch $@ - -validatessdppktgen: testssdppktgen - ./testssdppktgen - touch $@ - -depend: config.h - mkdep $(ALLOBJS:.o=.c) testupnpdescgen.c testgetifstats.c \ - testupnppermissions.c miniupnpdctl.c testgetifaddr.c \ - testgetroute.c testportinuse.c testasyncsendto.c \ - testssdppktgen.c - -miniupnpd: config.h $(ALLOBJS) - $(CC) $(LDFLAGS) -o $@ $(ALLOBJS) $(LIBS) - -# BSDmake : -# $(CC) $(LDFLAGS) -o $@ $> $(LIBS) - -miniupnpdctl: config.h $(MINIUPNPDCTLOBJS) - $(CC) $(LDFLAGS) -o $@ $(MINIUPNPDCTLOBJS) -lsocket - -testupnpdescgen: config.h $(TESTUPNPDESCGENOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTUPNPDESCGENOBJS) $(LIBS) - -testgetifstats: config.h $(TESTGETIFSTATSOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETIFSTATSOBJS) $(LIBS) - -testgetifaddr: config.h $(TESTGETIFADDROBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETIFADDROBJS) $(LIBS) - -testupnppermissions: config.h $(TESTUPNPPERMISSIONSOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTUPNPPERMISSIONSOBJS) $(LIBS) - -testgetroute: config.h $(TESTGETROUTEOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTGETROUTEOBJS) $(LIBS) - -testasyncsendto: config.h $(TESTASYNCSENDTOOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTASYNCSENDTOOBJS) -lsocket -lnsl - -testportinuse: config.h $(TESTPORTINUSEOBJS) - $(CC) $(LDFLAGS) -o $@ $(TESTPORTINUSEOBJS) $(LIBS) - -# gmake : -# $(CC) $(CFLAGS) -o $@ $^ -# BSDmake : -# $(CC) $(CFLAGS) -o $@ $> - -config.h: genconfig.sh VERSION - ./genconfig.sh $(CONFIG_OPTIONS) - -.SUFFIXES: .o .c -.c.o: - $(CC) $(CFLAGS) -c -o $@ $< - -# $(CC) $(CFLAGS) -c -o $(.TARGET) $(.IMPSRC) - - diff --git a/src/contrib/miniupnp/miniupnpd/README b/src/contrib/miniupnp/miniupnpd/README deleted file mode 100644 index 92bfdee..0000000 --- a/src/contrib/miniupnp/miniupnpd/README +++ /dev/null @@ -1,37 +0,0 @@ -MiniUPnP project -(c) 2006-2017 Thomas Bernard -webpage: http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ -github: https://github.com/miniupnp/miniupnp -freecode: http://freecode.com/projects/miniupnp -contact: miniupnp@free.fr - -This directory contain the miniUPnP daemon software, aka miniUPnPd. -This software is subject to the conditions detailed in -the LICENSE file provided with this distribution. - - -The miniUPnP daemon is an UPnP IGD (internet gateway device) -which provide NAT traversal services to any UPnP enabled client on -the network. -See http://www.upnp.org/ for more details on UPnP. -During the year 2011, support for IGD v2 has been added. -In 2012, IGD v2 WANIPv6FirewallControl has been implemented. - -IGD2 is still not enabled by default because of interoperability -issues. - -In addition to UPnP IGD, miniUPnPd supports NAT-PMP and PCP : - -See information about NAT Port Mapping Protocol (NAT-PMP) here : -http://miniupnp.free.fr/nat-pmp.html -NAT-PMP is the precursor of Port Control Protocol (PCP, RFC 6887). -In 2013, support for PCP has been added too. - -Read the INSTALL file for instructions to compile, install and -configure miniupnpd on your system. - -Report bugs to miniupnp@free.fr or on the web forum -https://miniupnp.tuxfamily.org/forum/ -or using https://github.com/miniupnp/miniupnp/issues - -Thomas Bernard diff --git a/src/contrib/miniupnp/miniupnpd/TODO b/src/contrib/miniupnp/miniupnpd/TODO deleted file mode 100644 index 3e12c63..0000000 --- a/src/contrib/miniupnp/miniupnpd/TODO +++ /dev/null @@ -1,24 +0,0 @@ -- detect and inform of IP address changes or connectivity status change - => Done (ifacewatcher 2011/05) - To be improved. -- improve logging. -- improve NAT-PMP compliance - => to be checked - -- Tomato's version used to dynamically include the local LAN IP and WAN IP as the windows icon name - if it was displayed... - -- I just enabled my lease file to save the port mappings so I don't have to recreate them every time miniupnp gets restarted but instead what happens is the lease file gets recreated and the leases erased. - => Done (2009/02/14) - -- http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1091 - -support IGD v2 : http://upnp.org/specs/gw/igd2/ - - Lease Duration support (mandatory in v2) => DONE - - WANIPv6FirewallControl - - pf : updatepinhole to do - - netfilter : ok ? - - ipfw/ipf : TODO - -implement port_in_use() for NetBSD - -- Do we need to TRIM arguments from SOAP ? diff --git a/src/contrib/miniupnp/miniupnpd/VERSION b/src/contrib/miniupnp/miniupnpd/VERSION deleted file mode 100644 index cd5ac03..0000000 --- a/src/contrib/miniupnp/miniupnpd/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.0 diff --git a/src/contrib/miniupnp/miniupnpd/asyncsendto.c b/src/contrib/miniupnp/miniupnpd/asyncsendto.c deleted file mode 100644 index 8d47ca2..0000000 --- a/src/contrib/miniupnp/miniupnpd/asyncsendto.c +++ /dev/null @@ -1,348 +0,0 @@ -/* $Id: asyncsendto.c,v 1.8 2017/05/24 22:51:57 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "asyncsendto.h" -#include "upnputils.h" - -/* state diagram for a packet : - * - * | - * V - * -> ESCHEDULED -> ESENDNOW -> sent - * ^ | - * | V - * EWAITREADY -> sent - */ -struct scheduled_send { - LIST_ENTRY(scheduled_send) entries; - struct timeval ts; - enum {ESCHEDULED=1, EWAITREADY=2, ESENDNOW=3} state; - int sockfd; - const void * buf; - size_t len; - int flags; - const struct sockaddr *dest_addr; - socklen_t addrlen; - const struct sockaddr_in6 *src_addr; - char data[]; -}; - -static LIST_HEAD(listhead, scheduled_send) send_list = { NULL }; - -/* - * ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, - * const struct sockaddr *dest_addr, socklen_t addrlen); - */ -static ssize_t -send_from_to(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr_in6 *src_addr, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ -#ifdef IPV6_PKTINFO - if(src_addr) { - struct iovec iov; - struct in6_pktinfo ipi6; - uint8_t c[CMSG_SPACE(sizeof(ipi6))]; - struct msghdr msg; - struct cmsghdr* cmsg; - - iov.iov_base = (void *)buf; - iov.iov_len = len; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - ipi6.ipi6_addr = src_addr->sin6_addr; - ipi6.ipi6_ifindex = src_addr->sin6_scope_id; - msg.msg_control = c; - msg.msg_controllen = sizeof(c); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(ipi6)); - memcpy(CMSG_DATA(cmsg), &ipi6, sizeof(ipi6)); - msg.msg_name = (void *)dest_addr; - msg.msg_namelen = addrlen; - return sendmsg(sockfd, &msg, flags); - } else { -#endif /* IPV6_PKTINFO */ - return sendto(sockfd, buf, len, flags, dest_addr, addrlen); -#ifdef IPV6_PKTINFO - } -#endif /* IPV6_PKTINFO */ -} - -/* delay = milli seconds */ -ssize_t -sendto_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr, - unsigned int delay) -{ - enum {ESCHEDULED, EWAITREADY, ESENDNOW} state; - ssize_t n; - size_t alloc_len; - struct timeval tv; - struct scheduled_send * elt; - - if(delay == 0) { - /* first try to send at once */ - n = send_from_to(sockfd, buf, len, flags, src_addr, dest_addr, addrlen); - if(n >= 0) - return n; - else if(errno == EAGAIN || errno == EWOULDBLOCK) { - /* use select() on this socket */ - state = EWAITREADY; - } else if(errno == EINTR) { - state = ESENDNOW; - } else { - /* uncatched error */ - return n; - } - } else { - state = ESCHEDULED; - } - - /* schedule */ - if(upnp_gettimeofday(&tv) < 0) { - return -1; - } - /* allocate enough space for structure + buffers */ - alloc_len = sizeof(struct scheduled_send) + len + addrlen; - if(src_addr) - alloc_len += sizeof(struct sockaddr_in6); - elt = malloc(alloc_len); - if(elt == NULL) { - syslog(LOG_ERR, "malloc failed to allocate %u bytes", - (unsigned)alloc_len); - return -1; - } - elt->state = state; - /* time the packet should be sent */ - elt->ts.tv_sec = tv.tv_sec + (delay / 1000); - elt->ts.tv_usec = tv.tv_usec + (delay % 1000) * 1000; - if(elt->ts.tv_usec > 1000000) { - elt->ts.tv_sec++; - elt->ts.tv_usec -= 1000000; - } - elt->sockfd = sockfd; - elt->flags = flags; - memcpy(elt->data, dest_addr, addrlen); - elt->dest_addr = (struct sockaddr *)elt->data; - elt->addrlen = addrlen; - if(src_addr) { - elt->src_addr = (struct sockaddr_in6 *)(elt->data + addrlen); - memcpy((void *)elt->src_addr, src_addr, sizeof(struct sockaddr_in6)); - elt->buf = (void *)(elt->data + addrlen + sizeof(struct sockaddr_in6)); - } else { - elt->src_addr = NULL; - elt->buf = (void *)(elt->data + addrlen); - } - elt->len = len; - memcpy((void *)elt->buf, buf, len); - /* insert */ - LIST_INSERT_HEAD( &send_list, elt, entries); - return 0; -} - -/* try to send at once, and queue the packet if needed */ -ssize_t -sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ - return sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, NULL, 0); -} - -ssize_t -sendto_or_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr) -{ - return sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, src_addr, 0); -} - -/* get_next_scheduled_send() return number of scheduled send in list */ -int get_next_scheduled_send(struct timeval * next_send) -{ - int n = 0; - struct scheduled_send * elt; - if(next_send == NULL) - return -1; - for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { - if(n == 0 || (elt->ts.tv_sec < next_send->tv_sec) || - (elt->ts.tv_sec == next_send->tv_sec && elt->ts.tv_usec < next_send->tv_usec)) { - next_send->tv_sec = elt->ts.tv_sec; - next_send->tv_usec = elt->ts.tv_usec; - } - n++; - } - return n; -} - -/* update writefds for select() call - * return the number of packets to try to send at once */ -int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now) -{ - int n = 0; - struct scheduled_send * elt; - for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { - if(elt->state == EWAITREADY) { - /* last sendto() call returned EAGAIN/EWOULDBLOCK */ - FD_SET(elt->sockfd, writefds); - if(elt->sockfd > *max_fd) - *max_fd = elt->sockfd; - n++; - } else if((elt->ts.tv_sec < now->tv_sec) || - (elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) { - /* we waited long enough, now send ! */ - elt->state = ESENDNOW; - n++; - } - } - return n; -} - -/* executed sendto() when needed */ -int try_sendto(fd_set * writefds) -{ - int ret = 0; - ssize_t n; - struct scheduled_send * elt; - struct scheduled_send * next; - for(elt = send_list.lh_first; elt != NULL; elt = next) { - next = elt->entries.le_next; - if((elt->state == ESENDNOW) || - (elt->state == EWAITREADY && FD_ISSET(elt->sockfd, writefds))) { -#ifdef DEBUG - syslog(LOG_DEBUG, "%s: %d bytes on socket %d", - "try_sendto", (int)elt->len, elt->sockfd); -#endif - n = send_from_to(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->src_addr, elt->dest_addr, elt->addrlen); - /*n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->dest_addr, elt->addrlen);*/ - if(n < 0) { - if(errno == EINTR) { - /* retry at once */ - elt->state = ESENDNOW; - continue; - } else if(errno == EAGAIN || errno == EWOULDBLOCK) { - /* retry once the socket is ready for writing */ - elt->state = EWAITREADY; - continue; - } else { - char addr_str[64]; - /* uncatched error */ - if(sockaddr_to_string(elt->dest_addr, addr_str, sizeof(addr_str)) <= 0) - addr_str[0] = '\0'; - syslog(LOG_ERR, "%s(sock=%d, len=%u, dest=%s): sendto: %m", - "try_sendto", elt->sockfd, (unsigned)elt->len, - addr_str); - ret--; - } - } else if((int)n != (int)elt->len) { - syslog(LOG_WARNING, "%s: %d bytes sent out of %d", - "try_sendto", (int)n, (int)elt->len); - } - /* remove from the list */ - LIST_REMOVE(elt, entries); - free(elt); - } - } - return ret; -} - -/* maximum execution time for finalize_sendto() in milliseconds */ -#define FINALIZE_SENDTO_DELAY (500) - -/* empty the list */ -void finalize_sendto(void) -{ - ssize_t n; - struct scheduled_send * elt; - struct scheduled_send * next; - fd_set writefds; - struct timeval deadline; - struct timeval now; - struct timeval timeout; - int max_fd; - - if(upnp_gettimeofday(&deadline) < 0) { - syslog(LOG_ERR, "gettimeofday: %m"); - return; - } - deadline.tv_usec += FINALIZE_SENDTO_DELAY*1000; - if(deadline.tv_usec > 1000000) { - deadline.tv_sec++; - deadline.tv_usec -= 1000000; - } - while(send_list.lh_first) { - FD_ZERO(&writefds); - max_fd = -1; - for(elt = send_list.lh_first; elt != NULL; elt = next) { - next = elt->entries.le_next; - syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d", - (int)elt->len, elt->sockfd); - n = send_from_to(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->src_addr, elt->dest_addr, elt->addrlen); - /*n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->dest_addr, elt->addrlen);*/ - if(n < 0) { - if(errno==EAGAIN || errno==EWOULDBLOCK) { - FD_SET(elt->sockfd, &writefds); - if(elt->sockfd > max_fd) - max_fd = elt->sockfd; - continue; - } - syslog(LOG_WARNING, "finalize_sendto(): socket=%d sendto: %m", elt->sockfd); - } - /* remove from the list */ - LIST_REMOVE(elt, entries); - free(elt); - } - /* check deadline */ - if(upnp_gettimeofday(&now) < 0) { - syslog(LOG_ERR, "gettimeofday: %m"); - return; - } - if(now.tv_sec > deadline.tv_sec || - (now.tv_sec == deadline.tv_sec && now.tv_usec > deadline.tv_usec)) { - /* deadline ! */ - while((elt = send_list.lh_first) != NULL) { - LIST_REMOVE(elt, entries); - free(elt); - } - return; - } - /* compute timeout value */ - timeout.tv_sec = deadline.tv_sec - now.tv_sec; - timeout.tv_usec = deadline.tv_usec - now.tv_usec; - if(timeout.tv_usec < 0) { - timeout.tv_sec--; - timeout.tv_usec += 1000000; - } - if(max_fd >= 0) { - if(select(max_fd + 1, NULL, &writefds, NULL, &timeout) < 0) { - syslog(LOG_ERR, "select: %m"); - return; - } - } - } -} - diff --git a/src/contrib/miniupnp/miniupnpd/asyncsendto.h b/src/contrib/miniupnp/miniupnpd/asyncsendto.h deleted file mode 100644 index ef670c2..0000000 --- a/src/contrib/miniupnp/miniupnpd/asyncsendto.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $Id: asyncsendto.h,v 1.3 2017/11/02 15:48:29 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef ASYNCSENDTO_H_INCLUDED -#define ASYNCSENDTO_H_INCLUDED -/* for fd_set */ -#include - -/* sendto_schedule() : see sendto(2) - * schedule sendto() call after delay (milliseconds) */ -ssize_t -sendto_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr, - unsigned int delay); - -#define sendto_schedule(sockfd, buf, len, flags, dest_addr, addrlen, delay) \ - sendto_schedule2(sockfd, buf, len, flags, dest_addr, addrlen, NULL, delay) - -/* sendto_schedule() : see sendto(2) - * try sendto() at once and schedule if EINTR/EAGAIN/EWOULDBLOCK */ -ssize_t -sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen); - -/* same as sendto_schedule() except it will try to set source address - * (for IPV6 only) */ -ssize_t -sendto_or_schedule2(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - const struct sockaddr_in6 *src_addr); - -/* get_next_scheduled_send() - * return number of scheduled sendto - * set next_send to timestamp to send next packet */ -int get_next_scheduled_send(struct timeval * next_send); - -/* execute sendto() for needed packets */ -int try_sendto(fd_set * writefds); - -/* set writefds before select() */ -int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now); - -/* empty the list */ -void finalize_sendto(void); - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/bsd/Makefile b/src/contrib/miniupnp/miniupnpd/bsd/Makefile deleted file mode 100644 index e66d29a..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# $Id: Makefile,v 1.2 2011/05/20 09:34:25 nanard Exp $ -# made for GNU Make -CFLAGS = -Wall -g -EXECUTABLES = testgetifstats testifacewatcher - -all: $(EXECUTABLES) - -clean: - rm -f *.o $(EXECUTABLES) - -testobsdrdr.o: testobsdrdr.c obsdrdr.h - -testgetifstats: testgetifstats.o getifstats.o - $(CC) $(CFLAGS) -o $@ $> -lkvm - -testifacewatcher: testifacewatcher.o ifacewatcher.o upnputils.o - $(CC) $(CFLAGS) -o $@ $> - -upnputils.o: ../upnputils.c - diff --git a/src/contrib/miniupnp/miniupnpd/bsd/getifstats.c b/src/contrib/miniupnp/miniupnpd/bsd/getifstats.c deleted file mode 100644 index 5443a99..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/getifstats.c +++ /dev/null @@ -1,77 +0,0 @@ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * author: Gleb Smirnoff - * (c) 2006 Ryan Wagoner - * (c) 2014 Gleb Smirnoff - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ENABLE_GETIFSTATS_CACHING -#include -#endif - -#include "../getifstats.h" -#include "../config.h" - -int -getifstats(const char *ifname, struct ifdata *data) -{ - static struct ifaddrs *ifap, *ifa; -#ifdef ENABLE_GETIFSTATS_CACHING - static time_t cache_timestamp; - time_t current_time; -#endif - if(!data) - return -1; - data->baudrate = 4200000; - data->opackets = 0; - data->ipackets = 0; - data->obytes = 0; - data->ibytes = 0; - if(!ifname || ifname[0]=='\0') - return -1; - -#ifdef ENABLE_GETIFSTATS_CACHING - current_time = upnp_time(); - if (ifap != NULL && - current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) - goto copy; -#endif - - if (ifap != NULL) { - freeifaddrs(ifap); - ifap = NULL; - } - - if (getifaddrs(&ifap) != 0) { - syslog (LOG_ERR, "getifstats() : getifaddrs(): %s", - strerror(errno)); - return (-1); - } - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) - if (ifa->ifa_addr->sa_family == AF_LINK && - strcmp(ifa->ifa_name, ifname) == 0) { -#ifdef ENABLE_GETIFSTATS_CACHING - cache_timestamp = current_time; -copy: -#endif -#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) - data->opackets = IFA_STAT(opackets); - data->ipackets = IFA_STAT(ipackets); - data->obytes = IFA_STAT(obytes); - data->ibytes = IFA_STAT(ibytes); - data->baudrate = IFA_STAT(baudrate); - return (0); - } - - return (-1); -} diff --git a/src/contrib/miniupnp/miniupnpd/bsd/getroute.c b/src/contrib/miniupnp/miniupnpd/bsd/getroute.c deleted file mode 100644 index 292504d..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/getroute.c +++ /dev/null @@ -1,145 +0,0 @@ -/* $Id: getroute.c,v 1.12 2015/11/19 11:46:30 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef AF_LINK -#include -#endif - -#include "../config.h" -#include "../upnputils.h" - -/* SA_SIZE() is a multiple of sizeof(long) with a minimum value of sizeof(long) */ -#ifndef SA_SIZE -#define SA_SIZE(sa) (((SA_LEN(sa)) == 0) ? sizeof(long) : (1 + (((SA_LEN(sa)) - 1) | (sizeof(long) - 1)))) -#endif /* SA_SIZE */ - -int -get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len, - int * index) -{ - int found = 0; - int s; - int l, i; - char * p; - struct sockaddr * sa; - struct { - struct rt_msghdr m_rtm; - char m_space[512]; - } m_rtmsg; -#define rtm m_rtmsg.m_rtm - - if(dst == NULL) - return -1; - if(SA_LEN(dst) > 0) { - l = SA_LEN(dst); - } else { - if(dst->sa_family == AF_INET) - l = sizeof(struct sockaddr_in); - else if(dst->sa_family == AF_INET6) - l = sizeof(struct sockaddr_in6); - else { - syslog(LOG_ERR, "unknown address family %d", dst->sa_family); - return -1; - } - } - s = socket(PF_ROUTE, SOCK_RAW, dst->sa_family); - if(s < 0) { - syslog(LOG_ERR, "socket(PF_ROUTE) failed : %m"); - return -1; - } - memset(&rtm, 0, sizeof(rtm)); - rtm.rtm_type = RTM_GET; - rtm.rtm_flags = RTF_UP; - rtm.rtm_version = RTM_VERSION; - rtm.rtm_seq = 1; - rtm.rtm_addrs = RTA_DST | RTA_IFA | RTA_IFP; /* pass destination address, request source address & interface */ - memcpy(m_rtmsg.m_space, dst, l); -#if !defined(__sun) - ((struct sockaddr *)m_rtmsg.m_space)->sa_len = l; -#endif - rtm.rtm_msglen = sizeof(struct rt_msghdr) + l; - if(write(s, &m_rtmsg, rtm.rtm_msglen) < 0) { - syslog(LOG_ERR, "write: %m"); - close(s); - return -1; - } - - do { - l = read(s, &m_rtmsg, sizeof(m_rtmsg)); - if(l<0) { - syslog(LOG_ERR, "read: %m"); - close(s); - return -1; - } - syslog(LOG_DEBUG, "read l=%d seq=%d pid=%d sizeof(struct rt_msghdr)=%d", - l, rtm.rtm_seq, rtm.rtm_pid, (int)sizeof(struct rt_msghdr)); - } while(l > 0 && (rtm.rtm_pid != getpid() || rtm.rtm_seq != 1)); - close(s); - if(l <= 0) { - syslog(LOG_WARNING, "no matching ROUTE response message"); - return -1; - } - p = m_rtmsg.m_space; - if(rtm.rtm_addrs) { - for(i=1; i<0x8000; i <<= 1) { - if(i & rtm.rtm_addrs) { - char tmp[256] = { 0 }; - if(p >= (char *)&m_rtmsg + l) { - syslog(LOG_ERR, "error parsing ROUTE response message"); - break; - } - sa = (struct sockaddr *)p; - sockaddr_to_string(sa, tmp, sizeof(tmp)); - syslog(LOG_DEBUG, "offset=%3d type=%2d sa_len=%d sa_family=%d %s", - (int)(p - m_rtmsg.m_space), - i, SA_LEN(sa), sa->sa_family, tmp); - if(i == RTA_IFA) { - size_t len = 0; - void * paddr = NULL; - if(sa->sa_family == AF_INET) { - paddr = &((struct sockaddr_in *)sa)->sin_addr; - len = sizeof(struct in_addr); - } else if(sa->sa_family == AF_INET6) { - paddr = &((struct sockaddr_in6 *)sa)->sin6_addr; - len = sizeof(struct in6_addr); - } - if(paddr) { - if(src && src_len) { - if(*src_len < len) { - syslog(LOG_WARNING, "cannot copy src. %u<%u", - (unsigned)*src_len, (unsigned)len); - return -1; - } - memcpy(src, paddr, len); - *src_len = len; - } - found = 1; - } - } -#ifdef AF_LINK - else if((i == RTA_IFP) && (sa->sa_family == AF_LINK)) { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa; - if(index) - *index = sdl->sdl_index; - } -#endif - p += SA_SIZE(sa); - } - } - } - return found ? 0 : -1; -} - diff --git a/src/contrib/miniupnp/miniupnpd/bsd/ifacewatcher.c b/src/contrib/miniupnp/miniupnpd/bsd/ifacewatcher.c deleted file mode 100644 index c3949b3..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/ifacewatcher.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $Id: ifacewatcher.c,v 1.8 2014/04/18 08:23:51 nanard Exp $ */ -/* Project MiniUPnP - * web : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011 Thomas BERNARD - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "../config.h" - -#include -#include -#include -#include -#include -#include -#include - -#define SALIGN (sizeof(long) - 1) -#define SA_RLEN(sa) (SA_LEN(sa) ? ((SA_LEN(sa) + SALIGN) & ~SALIGN) : (SALIGN + 1)) - -#include "../upnputils.h" -#include "../upnpglobalvars.h" - -extern volatile sig_atomic_t should_send_public_address_change_notif; - -int -OpenAndConfInterfaceWatchSocket(void) -{ - int s; - - /*s = socket(PF_ROUTE, SOCK_RAW, AF_INET);*/ - s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); -/* The family parameter may be AF_UNSPEC which will provide routing informa- - * tion for all address families, or can be restricted to a specific address - * family by specifying which one is desired. There can be more than one - * routing socket open per system. */ - if(s < 0) { - syslog(LOG_ERR, "OpenAndConfInterfaceWatchSocket socket: %m"); - } - return s; -} - -void -ProcessInterfaceWatchNotify(int s) -{ - char buf[4096]; - ssize_t len; - char tmp[64]; - struct rt_msghdr * rtm; - struct if_msghdr * ifm; - struct ifa_msghdr * ifam; -#ifdef RTM_IFANNOUNCE - struct if_announcemsghdr * ifanm; -#endif - char * p; - struct sockaddr * sa; - unsigned int ext_if_name_index = 0; - - len = recv(s, buf, sizeof(buf), 0); - if(len < 0) { - syslog(LOG_ERR, "ProcessInterfaceWatchNotify recv: %m"); - return; - } - if(ext_if_name) { - ext_if_name_index = if_nametoindex(ext_if_name); - } - rtm = (struct rt_msghdr *)buf; - syslog(LOG_DEBUG, "%u rt_msg : msglen=%d version=%d type=%d", (unsigned)len, - rtm->rtm_msglen, rtm->rtm_version, rtm->rtm_type); - switch(rtm->rtm_type) { - case RTM_IFINFO: /* iface going up/down etc. */ - ifm = (struct if_msghdr *)buf; - syslog(LOG_DEBUG, " RTM_IFINFO: addrs=%x flags=%x index=%hu", - ifm->ifm_addrs, ifm->ifm_flags, ifm->ifm_index); - break; - case RTM_ADD: /* Add Route */ - syslog(LOG_DEBUG, " RTM_ADD"); - break; - case RTM_DELETE: /* Delete Route */ - syslog(LOG_DEBUG, " RTM_DELETE"); - break; - case RTM_CHANGE: /* Change Metrics or flags */ - syslog(LOG_DEBUG, " RTM_CHANGE"); - break; - case RTM_GET: /* Report Metrics */ - syslog(LOG_DEBUG, " RTM_GET"); - break; -#ifdef RTM_IFANNOUNCE - case RTM_IFANNOUNCE: /* iface arrival/departure */ - ifanm = (struct if_announcemsghdr *)buf; - syslog(LOG_DEBUG, " RTM_IFANNOUNCE: index=%hu what=%hu ifname=%s", - ifanm->ifan_index, ifanm->ifan_what, ifanm->ifan_name); - break; -#endif -#ifdef RTM_IEEE80211 - case RTM_IEEE80211: /* IEEE80211 wireless event */ - syslog(LOG_DEBUG, " RTM_IEEE80211"); - break; -#endif - case RTM_NEWADDR: /* address being added to iface */ - ifam = (struct ifa_msghdr *)buf; - syslog(LOG_DEBUG, " RTM_NEWADDR: addrs=%x flags=%x index=%hu", - ifam->ifam_addrs, ifam->ifam_flags, ifam->ifam_index); - p = buf + sizeof(struct ifa_msghdr); - while(p < buf + len) { - sa = (struct sockaddr *)p; - sockaddr_to_string(sa, tmp, sizeof(tmp)); - syslog(LOG_DEBUG, " %s", tmp); - p += SA_RLEN(sa); - } - if(ifam->ifam_index == ext_if_name_index) { - should_send_public_address_change_notif = 1; - } - break; - case RTM_DELADDR: /* address being removed from iface */ - ifam = (struct ifa_msghdr *)buf; - if(ifam->ifam_index == ext_if_name_index) { - should_send_public_address_change_notif = 1; - } - break; - default: - syslog(LOG_DEBUG, "unprocessed RTM message type=%d", rtm->rtm_type); - } -} - diff --git a/src/contrib/miniupnp/miniupnpd/bsd/testgetifstats.c b/src/contrib/miniupnp/miniupnpd/bsd/testgetifstats.c deleted file mode 100644 index 4dff850..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/testgetifstats.c +++ /dev/null @@ -1,32 +0,0 @@ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include - -#include "../getifstats.h" - -int -main(int argc, char * * argv) -{ - int r; - struct ifdata data; - printf("usage: %s if_name\n", argv[0]); - if(argc<2) - return -1; - r = getifstats(argv[1], &data); - if(r<0) - printf("getifstats() failed\n"); - else - { - printf("ipackets = %10lu opackets = %10lu\n", - data.ipackets, data.opackets); - printf("ibytes = %10lu obytes = %10lu\n", - data.ibytes, data.obytes); - printf("baudrate = %10lu\n", data.baudrate); - } - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/bsd/testifacewatcher.c b/src/contrib/miniupnp/miniupnpd/bsd/testifacewatcher.c deleted file mode 100644 index 354b7e0..0000000 --- a/src/contrib/miniupnp/miniupnpd/bsd/testifacewatcher.c +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id: testifacewatcher.c,v 1.2 2012/05/21 08:55:10 nanard Exp $ */ - -#include - -int -OpenAndConfInterfaceWatchSocket(void); - -void -ProcessInterfaceWatchNotify(int s); - -const char * ext_if_name; -volatile sig_atomic_t should_send_public_address_change_notif = 0; - -int main(int argc, char * * argv) -{ - int s; - - ext_if_name = "ep0"; - openlog("testifacewatcher", LOG_CONS|LOG_PERROR, LOG_USER); - - syslog(LOG_DEBUG, "test"); - s = OpenAndConfInterfaceWatchSocket(); - for(;;) { - if(should_send_public_address_change_notif) { - syslog(LOG_DEBUG, "should_send_public_address_change_notif !"); - should_send_public_address_change_notif = 0; - } - ProcessInterfaceWatchNotify(s); - } - closelog(); - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/codelength.h b/src/contrib/miniupnp/miniupnpd/codelength.h deleted file mode 100644 index f5f8e30..0000000 --- a/src/contrib/miniupnp/miniupnpd/codelength.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2005-2015 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef CODELENGTH_H_INCLUDED -#define CODELENGTH_H_INCLUDED - -/* Encode length by using 7bit per Byte : - * Most significant bit of each byte specifies that the - * following byte is part of the code */ - -/* n : unsigned - * p : unsigned char * - */ -#define DECODELENGTH(n, p) n = 0; \ - do { n = (n << 7) | (*p & 0x7f); } \ - while((*(p++)&0x80) && (n<(1<<25))); - -/* n : unsigned - * READ : function/macro to read one byte (unsigned char) - */ -#define DECODELENGTH_READ(n, READ) \ - n = 0; \ - do { \ - unsigned char c; \ - READ(c); \ - n = (n << 7) | (c & 0x07f); \ - if(!(c&0x80)) break; \ - } while(n<(1<<25)); - -/* n : unsigned - * p : unsigned char * - * p_limit : unsigned char * - */ -#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ - n = 0; \ - do { \ - if((p) >= (p_limit)) break; \ - n = (n << 7) | (*(p) & 0x7f); \ - } while((*((p)++)&0x80) && (n<(1<<25))); - - -/* n : unsigned - * p : unsigned char * - */ -#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ - if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ - if(n>=16384) *(p++) = (n >> 14) | 0x80; \ - if(n>=128) *(p++) = (n >> 7) | 0x80; \ - *(p++) = n & 0x7f; - -#endif /* CODELENGTH_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/commonrdr.h b/src/contrib/miniupnp/miniupnpd/commonrdr.h deleted file mode 100644 index 61352e4..0000000 --- a/src/contrib/miniupnp/miniupnpd/commonrdr.h +++ /dev/null @@ -1,67 +0,0 @@ -/* $Id: commonrdr.h,v 1.10 2016/02/12 12:34:39 nanard Exp $ */ -/* MiniUPnP project - * (c) 2006-2016 Thomas Bernard - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef COMMONRDR_H_INCLUDED -#define COMMONRDR_H_INCLUDED - -#include "config.h" - -/* init and shutdown functions */ -/* init_redirect() return values : - * 0 : OK - * -1 : error */ -int -init_redirect(void); - -void -shutdown_redirect(void); - -/* get_redirect_rule() gets internal IP and port from - * interface, external port and protocol - * return value : - * 0 success (rule found) - * -1 error or rule not found - */ -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -/* get_redirect_rule_by_index() - * return values : - * 0 success (rule found) - * -1 error or rule not found */ -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -/* return an (malloc'ed) array of "external" port for which there is - * a port mapping. number is the size of the array */ -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number); - -/* update the port mapping internal port, decription and timestamp */ -int -update_portmapping(const char * ifname, unsigned short eport, int proto, - unsigned short iport, const char * desc, - unsigned int timestamp); - -/* update the port mapping decription and timestamp */ -int -update_portmapping_desc_timestamp(const char * ifname, - unsigned short eport, int proto, - const char * desc, unsigned int timestamp); - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/daemonize.c b/src/contrib/miniupnp/miniupnpd/daemonize.c deleted file mode 100644 index 4c5909d..0000000 --- a/src/contrib/miniupnp/miniupnpd/daemonize.c +++ /dev/null @@ -1,129 +0,0 @@ -/* $Id: daemonize.c,v 1.12 2011/05/27 09:35:02 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "daemonize.h" -#include "config.h" - -#ifndef USE_DAEMON - -int -daemonize(void) -{ - int pid, i; - - switch(fork()) - { - /* fork error */ - case -1: - perror("fork()"); - exit(1); - - /* child process */ - case 0: - /* obtain a new process group */ - if( (pid = setsid()) < 0) - { - perror("setsid()"); - exit(1); - } - - /* close all descriptors */ - for (i=getdtablesize();i>=0;--i) close(i); - - i = open("/dev/null", O_RDWR); /* open stdin */ - dup(i); /* stdout */ - dup(i); /* stderr */ - - umask(027); - chdir("/"); /* chdir to /tmp ? */ - - return pid; - - /* parent process */ - default: - exit(0); - } -} -#endif - -int -writepidfile(const char * fname, int pid) -{ - char pidstring[16]; - int pidstringlen; - int pidfile; - - if(!fname || fname[0] == '\0') - return -1; - - if( (pidfile = open(fname, O_WRONLY|O_CREAT, 0644)) < 0) - { - syslog(LOG_ERR, "Unable to open pidfile for writing %s: %m", fname); - return -1; - } - - pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid); - if(pidstringlen <= 0) - { - syslog(LOG_ERR, - "Unable to write to pidfile %s: snprintf(): FAILED", fname); - close(pidfile); - return -1; - } - else - { - if(write(pidfile, pidstring, pidstringlen) < 0) - syslog(LOG_ERR, "Unable to write to pidfile %s: %m", fname); - } - - close(pidfile); - - return 0; -} - -int -checkforrunning(const char * fname) -{ - char buffer[64]; - int pidfile; - pid_t pid; - - if(!fname || fname[0] == '\0') - return -1; - - if( (pidfile = open(fname, O_RDONLY)) < 0) - return 0; - - memset(buffer, 0, 64); - - if(read(pidfile, buffer, 63)) - { - if( (pid = atol(buffer)) > 0) - { - if(!kill(pid, 0)) - { - close(pidfile); - return -2; - } - } - } - - close(pidfile); - - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/daemonize.h b/src/contrib/miniupnp/miniupnpd/daemonize.h deleted file mode 100644 index 818ce73..0000000 --- a/src/contrib/miniupnp/miniupnpd/daemonize.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: daemonize.h,v 1.6 2008/01/29 13:04:46 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef DAEMONIZE_H_INCLUDED -#define DAEMONIZE_H_INCLUDED - -#include "config.h" - -#ifndef USE_DAEMON -/* daemonize() - * "fork" to background, detach from terminal, etc... - * returns: pid of the daemon, exits upon failure */ -int -daemonize(void); -#endif - -/* writepidfile() - * write the pid to a file */ -int -writepidfile(const char * fname, int pid); - -/* checkforrunning() - * check for another instance running - * returns: 0 only instance - * -1 invalid filename - * -2 another instance running */ -int -checkforrunning(const char * fname); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/genconfig.sh b/src/contrib/miniupnp/miniupnpd/genconfig.sh deleted file mode 100644 index d0bcf1f..0000000 --- a/src/contrib/miniupnp/miniupnpd/genconfig.sh +++ /dev/null @@ -1,634 +0,0 @@ -#! /bin/sh -# $Id: genconfig.sh,v 1.95 2018/01/16 00:50:46 nanard Exp $ -# vim: tabstop=4 shiftwidth=4 noexpandtab -# -# miniupnp daemon -# http://miniupnp.free.fr or https://miniupnp.tuxfamily.org/ -# (c) 2006-2018 Thomas Bernard -# This software is subject to the conditions detailed in the -# LICENCE file provided within the distribution - -# default to UPnP Device Architecture (UDA) v1.1 -# some control points do not like UDA v2.0 -UPNP_VERSION_MAJOR=1 -UPNP_VERSION_MINOR=1 - -for argv; do -case "$argv" in - --ipv6) IPV6=1 ;; - --igd2) IGD2=1 ;; - --strict) STRICT=1 ;; - --leasefile) LEASEFILE=1 ;; - --vendorcfg) VENDORCFG=1 ;; - --pcp-peer) PCP_PEER=1 ;; - --portinuse) PORTINUSE=1 ;; - --uda-version=*) - UPNP_VERSION=$(echo $argv | cut -d= -f2) - UPNP_VERSION_MAJOR=$(echo $UPNP_VERSION | cut -s -d. -f1) - UPNP_VERSION_MINOR=$(echo $UPNP_VERSION | cut -s -d. -f2) - echo "Setting UPnP version major=$UPNP_VERSION_MAJOR minor=$UPNP_VERSION_MINOR" - if [ -z "$UPNP_VERSION_MAJOR" ] || [ -z "$UPNP_VERSION_MINOR" ] ; then - echo "UPnP Version invalid in option $argv" - exit 1 - fi ;; - --disable-pppconn) DISABLEPPPCONN=1 ;; - --help|-h) - echo "Usage : $0 [options]" - echo " --ipv6 enable IPv6" - echo " --igd2 build an IGDv2 instead of an IGDv1" - echo " --strict be more strict regarding compliance with UPnP specifications" - echo " --leasefile enable lease file" - echo " --vendorcfg enable configuration of manufacturer info" - echo " --pcp-peer enable PCP PEER operation" - echo " --portinuse enable port in use check" - echo " --uda-version=x.x set advertised UPnP version (default to ${UPNP_VERSION_MAJOR}.${UPNP_VERSION_MINOR})" - echo " --disable-pppconn disable WANPPPConnection" - exit 1 - ;; - *) - echo "Option not recognized : $argv" - echo "use -h option to display help" - exit 1 - ;; -esac -done - -RM="rm -f" -MV="mv" -CONFIGFILE=`mktemp tmp.config.h.XXXXXXXXXX` -CONFIGFILE_FINAL="config.h" -CONFIGMACRO="CONFIG_H_INCLUDED" - -MINIUPNPD_DATE=`date +"%Y%m%d"` -if [ -n "$SOURCE_DATE_EPOCH" ]; then - MINIUPNPD_DATE=`date --utc --date="@$SOURCE_DATE_EPOCH" +"%Y%m%d"` -fi - -# Facility to syslog -LOG_MINIUPNPD="LOG_DAEMON" - -# detecting the OS name and version -OS_NAME=`uname -s` -OS_VERSION=`uname -r` - -# pfSense special case -if [ -f /etc/platform ]; then - if [ `cat /etc/platform` = "pfSense" ]; then - OS_NAME=pfSense - OS_VERSION=`cat /etc/version` - fi -fi - -# OpenWRT special case -if [ -f ./os.openwrt ]; then - OS_NAME=OpenWRT - OS_VERSION=$(cat ./os.openwrt) -fi - -# AstLinux special case -if [ -f ./os.astlinux ]; then - OS_NAME=AstLinux - OS_VERSION=$(cat ./os.astlinux) -fi - -# Tomato USB special case -if [ -f ../shared/tomato_version ]; then - OS_NAME=Tomato - TOMATO_VER=`cat ../shared/tomato_version | cut -d' ' -f2,3` - OS_VERSION="Tomato $TOMATO_VER" -fi - -${RM} ${CONFIGFILE} - -echo "/* MiniUPnP Project" >> ${CONFIGFILE} -echo " * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/" >> ${CONFIGFILE} -echo " * (c) 2006-2018 Thomas Bernard" >> ${CONFIGFILE} -echo " * generated by $0 on `date`" >> ${CONFIGFILE} -echo " * `uname -a`" >> ${CONFIGFILE} -if [ -z "$*" ] ; then - echo " * using no command line option */" >> ${CONFIGFILE} -else - echo " * using command line options $* */" >> ${CONFIGFILE} -fi -echo "#ifndef $CONFIGMACRO" >> ${CONFIGFILE} -echo "#define $CONFIGMACRO" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} -echo "#include " >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} -echo "#define MINIUPNPD_VERSION \"`cat VERSION`\"" >> ${CONFIGFILE} -echo "#define MINIUPNPD_DATE \"$MINIUPNPD_DATE\"" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -cat >> ${CONFIGFILE} <> ${CONFIGFILE} -cat >> ${CONFIGFILE} <> ${CONFIGFILE} - -# OS Specific stuff -case $OS_NAME in - OpenBSD) - MAJORVER=`echo $OS_VERSION | cut -d. -f1` - MINORVER=`echo $OS_VERSION | cut -d. -f2` - #echo "OpenBSD majorversion=$MAJORVER minorversion=$MINORVER" - # rtableid was introduced in OpenBSD 4.0 - if [ $MAJORVER -ge 4 ]; then - echo "#define PFRULE_HAS_RTABLEID" >> ${CONFIGFILE} - fi - # from the 3.8 version, packets and bytes counters are double : in/out - if [ \( $MAJORVER -ge 4 \) -o \( $MAJORVER -eq 3 -a $MINORVER -ge 8 \) ]; then - echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE} - fi - # from the 4.7 version, new pf - if [ \( $MAJORVER -ge 5 \) -o \( $MAJORVER -eq 4 -a $MINORVER -ge 7 \) ]; then - echo "#define PF_NEWSTYLE" >> ${CONFIGFILE} - fi - # onrdomain was introduced in OpenBSD 5.0 - if [ $MAJORVER -ge 5 ]; then - echo "#define PFRULE_HAS_ONRDOMAIN" >> ${CONFIGFILE} - fi - FW=pf - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - OS_URL=http://www.openbsd.org/ - V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` - ;; - FreeBSD) - VER=`grep '#define __FreeBSD_version' /usr/include/sys/param.h | awk '{print $3}'` - if [ $VER -ge 700049 ]; then - echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE} - fi - HAVE_IP_MREQN=1 - # new way to see which one to use PF or IPF. - # see http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=957 - if [ -f /etc/rc.subr ] && [ -f /etc/default/rc.conf ] ; then - # source file with handy subroutines like checkyesno - . /etc/rc.subr - # source config file so we can probe vars - . /etc/default/rc.conf - if checkyesno ipfilter_enable; then - echo "Using ipf" - FW=ipf - elif checkyesno pf_enable; then - echo "Using pf" - FW=pf - elif checkyesno firewall_enable; then - echo "Using ifpw" - FW=ipfw - fi - fi - if [ -z $FW ] ; then - echo "Could not detect usage of ipf, pf, ipfw. Compiling for pf by default" - FW=pf - fi - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - OS_URL=http://www.freebsd.org/ - V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` - ;; - pfSense) - # we need to detect if PFRULE_INOUT_COUNTS macro is needed - FW=pf - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - OS_URL=http://www.pfsense.com/ - V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` - ;; - NetBSD) - if [ -f /etc/rc.subr ] && [ -f /etc/rc.conf ] ; then - # source file with handy subroutines like checkyesno - . /etc/rc.subr - # source config file so we can probe vars - . /etc/rc.conf - if checkyesno pf; then - FW=pf - elif checkyesno ipfilter; then - FW=ipf - fi - fi - if [ -z $FW ] ; then - echo "Could not detect ipf nor pf, defaulting to pf." - FW=pf - fi - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - OS_URL=http://www.netbsd.org/ - ;; - DragonFly) - if [ -f /etc/rc.subr ] && [ -f /etc/rc.conf ] ; then - # source file with handy subroutines like checkyesno - . /etc/rc.subr - # source config file so we can probe vars - . /etc/rc.conf - if checkyesno pf; then - FW=pf - elif checkyesno ipfilter; then - FW=ipf - fi - fi - if [ -z $FW ] ; then - echo "Could not detect ipf nor pf, defaulting to pf." - FW=pf - fi - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - # PFRULE_INOUT_COUNTS should be set for DragonFly > 2.8 - # version detection is not yet added to this script. - echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE} - # net.inet6.ip6.v6only has been on by default for many years - # and this sysctl node has been removed - V6SOCKETS_ARE_V6ONLY=1 - OS_URL=http://www.dragonflybsd.org/ - ;; - SunOS) - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - FW=ipf - echo "#define LOG_PERROR 0" >> ${CONFIGFILE} - echo "#define SOLARIS_KSTATS 1" >> ${CONFIGFILE} - # solaris 10 does not define u_int64_t ? - # but it does define uint64_t - echo "typedef uint64_t u_int64_t;" >> ${CONFIGFILE} - OS_URL=http://www.sun.com/solaris/ - ;; - Linux) - OS_URL=http://www.kernel.org/ - KERNVERA=`echo $OS_VERSION | awk -F. '{print $1}'` - KERNVERB=`echo $OS_VERSION | awk -F. '{print $2}'` - KERNVERC=`echo $OS_VERSION | awk -F. '{print $3}'` - KERNVERD=`echo $OS_VERSION | awk -F. '{print $4}'` - #echo "$KERNVERA.$KERNVERB.$KERNVERC.$KERNVERD" - # from the 2.4 version, struct ip_mreqn instead of struct ip_mreq - if [ \( $KERNVERA -ge 3 \) -o \( $KERNVERA -eq 2 -a $KERNVERB -ge 4 \) ]; then - HAVE_IP_MREQN=1 - fi - # Debian GNU/Linux special case - if [ -f /etc/debian_version ]; then - OS_NAME=Debian - OS_VERSION=`cat /etc/debian_version` - OS_URL=http://www.debian.org/ - fi - # same thing for Gentoo linux - if [ -f /etc/gentoo-release ]; then - OS_NAME=Gentoo - OS_VERSION=`cat /etc/gentoo-release` - OS_URL=http://www.gentoo.org/ - fi - # ClearOS special case - if [ -f /etc/clearos-release ]; then - OS_NAME=ClearOS - OS_VERSION=`grep ^base_version /etc/product | awk '{ print $3 }'` - OS_URL=https://www.clearos.com/ - fi - # use lsb_release (Linux Standard Base) when available - LSB_RELEASE=`which lsb_release` - if [ 0 -eq $? ]; then - OS_NAME=`${LSB_RELEASE} -i -s` - OS_VERSION=`${LSB_RELEASE} -r -s` - case $OS_NAME in - Debian) - OS_URL=http://www.debian.org/ - OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - Ubuntu) - OS_URL=http://www.ubuntu.com/ - OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - Gentoo) - OS_URL=http://www.gentoo.org/ - ;; - arch) - OS_URL=http://www.archlinux.org/ - OS_VERSION=`uname -r` - ;; - esac - fi - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - FW=netfilter - V6SOCKETS_ARE_V6ONLY=`/sbin/sysctl -n net.ipv6.bindv6only` - ;; - OpenWRT) - OS_URL=http://www.openwrt.org/ - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - FW=netfilter - ;; - AstLinux) - OS_URL=http://www.astlinux.org/ - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - FW=netfilter - ;; - Tomato) - OS_NAME=UPnP - OS_URL=http://tomatousb.org/ - echo "" >> ${CONFIGFILE} - echo "#ifndef TOMATO" >> ${CONFIGFILE} - echo "#define TOMATO" >> ${CONFIGFILE} - echo "#endif" >> ${CONFIGFILE} - echo "" >> ${CONFIGFILE} - echo "#ifdef LINUX26" >> ${CONFIGFILE} - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - echo "#endif" >> ${CONFIGFILE} - echo "#ifdef TCONFIG_IPV6" >> ${CONFIGFILE} - echo "#define ENABLE_IPV6" >> ${CONFIGFILE} - echo "#endif" >> ${CONFIGFILE} - FW=netfilter - ;; - Darwin) - MAJORVER=`echo $OS_VERSION | cut -d. -f1` - echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - # OS X switched to pf since 10.7 Lion (Darwin 11.0) - if [ $MAJORVER -ge 11 ] ; then - FW=pf - echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE} - else - FW=ipfw - fi - OS_URL=http://developer.apple.com/macosx - ;; - *) - echo "Unknown OS : $OS_NAME" - echo "Please contact the author at http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/." - exit 1 - ;; -esac - -case $FW in - pf) - echo "#define USE_PF 1" >> ${CONFIGFILE} - ;; - ipf) - echo "#define USE_IPF 1" >> ${CONFIGFILE} - ;; - ipfw) - echo "#define USE_IPFW 1" >> ${CONFIGFILE} - ;; - netfilter) - echo "#define USE_NETFILTER 1" >> ${CONFIGFILE} - ;; - *) - echo "Unknown Firewall/packet filtering software [$FW]" - echo "Please contact the author at http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/." - exit 1 - ;; -esac - -# UUID API -if grep uuid_create /usr/include/uuid.h > /dev/null 2>&1 ; then - echo "#define BSD_UUID" >> ${CONFIGFILE} -fi -if grep uuid_generate /usr/include/uuid/uuid.h > /dev/null 2>&1 ; then - echo "#define LIB_UUID" >> ${CONFIGFILE} -fi - -# set V6SOCKETS_ARE_V6ONLY to 0 if it was not set above -if [ -z "$V6SOCKETS_ARE_V6ONLY" ] ; then - V6SOCKETS_ARE_V6ONLY=0 -fi - -echo "Configuring compilation for [$OS_NAME] [$OS_VERSION] with [$FW] firewall software." -echo "Please edit config.h for more compilation options." - -# define SUPPORT_REMOTEHOST if the FW related code really supports setting -# a RemoteHost -if [ \( "$FW" = "netfilter" \) -o \( "$FW" = "pf" \) -o \( "$FW" = "ipfw" \) ] ; then - echo "#define SUPPORT_REMOTEHOST" >> ${CONFIGFILE} -fi - -echo "/* Enable IGD2 \"Port Triggering\" as defined in Section 2.5.16" >> ${CONFIGFILE} -echo " * figure 2.2 in UPnP-gw-WANIPConnection-v2-Service.pdf */" >> ${CONFIGFILE} -echo "#define ENABLE_PORT_TRIGGERING" >> ${CONFIGFILE} - -echo "" >> ${CONFIGFILE} -echo "#define OS_NAME \"$OS_NAME\"" >> ${CONFIGFILE} -echo "#define OS_VERSION \"$OS_NAME/$OS_VERSION\"" >> ${CONFIGFILE} -echo "#define OS_URL \"${OS_URL}\"" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* syslog facility to be used by miniupnpd */" >> ${CONFIGFILE} -echo "#define LOG_MINIUPNPD ${LOG_MINIUPNPD}" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to allow miniupnpd to be" >> ${CONFIGFILE} -echo " * controlled by miniupnpdctl */" >> ${CONFIGFILE} -echo "/*#define USE_MINIUPNPDCTL*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Comment the following line to disable NAT-PMP operations */" >> ${CONFIGFILE} -echo "#define ENABLE_NATPMP" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Comment the following line to disable PCP operations */" >> ${CONFIGFILE} -echo "#define ENABLE_PCP" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "#ifdef ENABLE_PCP" >> ${CONFIGFILE} -if [ -n "$PCP_PEER" ]; then -echo "/* Comment the following line to disable PCP PEER operation */" >> ${CONFIGFILE} -echo "#define PCP_PEER" >> ${CONFIGFILE} -else -echo "/* Uncomment the following line to enable PCP PEER operation */" >> ${CONFIGFILE} -echo "/*#define PCP_PEER*/" >> ${CONFIGFILE} -fi -echo "#ifdef PCP_PEER" >> ${CONFIGFILE} -echo "/*#define PCP_FLOWP*/" >> ${CONFIGFILE} -echo "#endif /*PCP_PEER*/" >> ${CONFIGFILE} -echo "/*#define PCP_SADSCP*/" >> ${CONFIGFILE} -echo "#endif /*ENABLE_PCP*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to enable generation of" >> ${CONFIGFILE} -echo " * filter rules with pf */" >> ${CONFIGFILE} -echo "/*#define PF_ENABLE_FILTER_RULES*/">> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to enable caching of results of" >> ${CONFIGFILE} -echo " * the getifstats() function */" >> ${CONFIGFILE} -echo "/*#define ENABLE_GETIFSTATS_CACHING*/" >> ${CONFIGFILE} -echo "/* The cache duration is indicated in seconds */" >> ${CONFIGFILE} -echo "#define GETIFSTATS_CACHING_DURATION 2" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to enable multiple external ip support */" >> ${CONFIGFILE} -echo "/* note : That is EXPERIMENTAL, do not use that unless you know perfectly what you are doing */" >> ${CONFIGFILE} -echo "/* Dynamic external ip adresses are not supported when this option is enabled." >> ${CONFIGFILE} -echo " * Also note that you would need to configure your .conf file accordingly. */" >> ${CONFIGFILE} -echo "/*#define MULTIPLE_EXTERNAL_IP*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Comment the following line to use home made daemonize() func instead" >> ${CONFIGFILE} -echo " * of BSD daemon() */" >> ${CONFIGFILE} -echo "#define USE_DAEMON" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to enable lease file support */" >> ${CONFIGFILE} -if [ -n "$LEASEFILE" ] ; then - echo "#define ENABLE_LEASEFILE" >> ${CONFIGFILE} -else - echo "/*#define ENABLE_LEASEFILE*/" >> ${CONFIGFILE} -fi -echo "/* Uncomment the following line to store remaining time in lease file */" >> ${CONFIGFILE} -echo "/*#define LEASEFILE_USE_REMAINING_TIME*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to enable port in use check */" >> ${CONFIGFILE} -if [ -n "$PORTINUSE" ]; then - echo "#define CHECK_PORTINUSE" >> ${CONFIGFILE} -else - echo "/*#define CHECK_PORTINUSE*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* Define one or none of the two following macros in order to make some" >> ${CONFIGFILE} -echo " * clients happy. It will change the XML Root Description of the IGD." >> ${CONFIGFILE} -echo " * Enabling the Layer3Forwarding Service seems to be the more compatible" >> ${CONFIGFILE} -echo " * option. */" >> ${CONFIGFILE} -echo "/*#define HAS_DUMMY_SERVICE*/" >> ${CONFIGFILE} -echo "#define ENABLE_L3F_SERVICE" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* define ADVERTISE_WANPPPCONN to allow buggy Control Point to use" >> ${CONFIGFILE} -echo " * WANPPPConnection instead of WANIPConnection. */" >> ${CONFIGFILE} -if [ -n "$STRICT" ] || [ -n "$DISABLEPPPCONN" ] ; then - echo "/*#define ADVERTISE_WANPPPCONN*/" >> ${CONFIGFILE} -else - echo "#define ADVERTISE_WANPPPCONN" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* Enable IP v6 support */" >> ${CONFIGFILE} -if [ -n "$IPV6" ]; then - echo "#define ENABLE_IPV6" >> ${CONFIGFILE} -else - echo "/*#define ENABLE_IPV6*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* Define V6SOCKETS_ARE_V6ONLY if AF_INET6 sockets are restricted" >> ${CONFIGFILE} -echo " * to IPv6 communications only. */" >> ${CONFIGFILE} -if [ $V6SOCKETS_ARE_V6ONLY -eq 1 ] ; then - echo "#define V6SOCKETS_ARE_V6ONLY" >> ${CONFIGFILE} -else - echo "/*#define V6SOCKETS_ARE_V6ONLY*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -if [ -n "$HAVE_IP_MREQN" ]; then - echo "#define HAVE_IP_MREQN" >> ${CONFIGFILE} - echo "" >> ${CONFIGFILE} -fi - -echo "/* Enable the support of IGD v2 specification." >> ${CONFIGFILE} -echo " * This is not fully tested yet and can cause incompatibilities with some" >> ${CONFIGFILE} -echo " * control points, so enable with care. */" >> ${CONFIGFILE} -if [ -n "$IGD2" ]; then - echo "#define IGD_V2" >> ${CONFIGFILE} -else - echo "/*#define IGD_V2*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "#ifdef IGD_V2" >> ${CONFIGFILE} -echo "/* Enable DeviceProtection service (IGDv2) */" >> ${CONFIGFILE} -echo "#define ENABLE_DP_SERVICE" >> ${CONFIGFILE} -echo "/*#define ENABLE_HTTPS*/" >> ${CONFIGFILE} -echo "/*#define HTTPS_CERTFILE \"/path/to/certificate.pem\"*/" >> ${CONFIGFILE} -echo "/*#define HTTPS_KEYFILE \"/path/to/private.key\"*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} -echo "/* Enable WANIPv6FirewallControl service (IGDv2). needs IPv6 */" >> ${CONFIGFILE} -echo "#ifdef ENABLE_IPV6" >> ${CONFIGFILE} -echo "#define ENABLE_6FC_SERVICE" >> ${CONFIGFILE} -echo "#endif /* ENABLE_IPV6 */" >> ${CONFIGFILE} -echo "#endif /* IGD_V2 */" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* UPnP Events support. Working well enough to be enabled by default." >> ${CONFIGFILE} -echo " * It can be disabled to save a few bytes. */" >> ${CONFIGFILE} -echo "#define ENABLE_EVENTS" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* include interface name in pf and ipf rules */" >> ${CONFIGFILE} -echo "#define USE_IFNAME_IN_RULES" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Experimental NFQUEUE support. */" >> ${CONFIGFILE} -echo "/*#define ENABLE_NFQUEUE*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Enable to make MiniUPnPd more strict about UPnP conformance" >> ${CONFIGFILE} -echo " * and the messages it receives from control points */" >> ${CONFIGFILE} -if [ -n "$STRICT" ] ; then - echo "#define UPNP_STRICT" >> ${CONFIGFILE} -else - echo "/*#define UPNP_STRICT*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* If SSDP_RESPOND_SAME_VERSION is defined, the M-SEARCH response" >> ${CONFIGFILE} -echo " * include the same device version as was contained in the search" >> ${CONFIGFILE} -echo " * request. It conforms to UPnP DA v1.1 */" >> ${CONFIGFILE} -echo "#define SSDP_RESPOND_SAME_VERSION" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Add the optional Date: header in all HTTP responses */" >> ${CONFIGFILE} -if [ -n "$STRICT" ] ; then - echo "#define ENABLE_HTTP_DATE" >> ${CONFIGFILE} -else - echo "/*#define ENABLE_HTTP_DATE*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* Wait a little before answering M-SEARCH request */" >> ${CONFIGFILE} -if [ -n "$STRICT" ] ; then - echo "#define DELAY_MSEARCH_RESPONSE" >> ${CONFIGFILE} -else - echo "/*#define DELAY_MSEARCH_RESPONSE*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -echo "/* disable reading and parsing of config file (miniupnpd.conf) */" >> ${CONFIGFILE} -echo "/*#define DISABLE_CONFIG_FILE*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} - -echo "/* Uncomment the following line to configure all manufacturer infos through miniupnpd.conf */" >> ${CONFIGFILE} -if [ -n "$VENDORCFG" ] ; then - echo "#define ENABLE_MANUFACTURER_INFO_CONFIGURATION" >> ${CONFIGFILE} -else - echo "/*#define ENABLE_MANUFACTURER_INFO_CONFIGURATION*/" >> ${CONFIGFILE} -fi -echo "" >> ${CONFIGFILE} - -cat >> ${CONFIGFILE} <> ${CONFIGFILE} <> ${CONFIGFILE} <> ${CONFIGFILE} - -${MV} ${CONFIGFILE} ${CONFIGFILE_FINAL} - -exit 0 diff --git a/src/contrib/miniupnp/miniupnpd/getconnstatus.c b/src/contrib/miniupnp/miniupnpd/getconnstatus.c deleted file mode 100644 index 332784c..0000000 --- a/src/contrib/miniupnp/miniupnpd/getconnstatus.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $Id: getconnstatus.c,v 1.6 2013/03/23 10:46:54 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include "getconnstatus.h" -#include "getifaddr.h" - -#define STATUS_UNCONFIGURED (0) -#define STATUS_CONNECTING (1) -#define STATUS_CONNECTED (2) -#define STATUS_PENDINGDISCONNECT (3) -#define STATUS_DISCONNECTING (4) -#define STATUS_DISCONNECTED (5) - -/** - * get the connection status - * return values : - * 0 - Unconfigured - * 1 - Connecting - * 2 - Connected - * 3 - PendingDisconnect - * 4 - Disconnecting - * 5 - Disconnected */ -int -get_wan_connection_status(const char * ifname) -{ - char addr[INET_ADDRSTRLEN]; - int r; - - /* we need a better implementation here. - * I'm afraid it should be device specific */ - r = getifaddr(ifname, addr, INET_ADDRSTRLEN, NULL, NULL); - return (r < 0) ? STATUS_DISCONNECTED : STATUS_CONNECTED; -} - -/** - * return the same value as get_wan_connection_status() - * as a C string */ -const char * -get_wan_connection_status_str(const char * ifname) -{ - int status; - const char * str = NULL; - - status = get_wan_connection_status(ifname); - switch(status) { - case 0: - str = "Unconfigured"; - break; - case 1: - str = "Connecting"; - break; - case 2: - str = "Connected"; - break; - case 3: - str = "PendingDisconnect"; - break; - case 4: - str = "Disconnecting"; - break; - case 5: - str = "Disconnected"; - break; - } - return str; -} - diff --git a/src/contrib/miniupnp/miniupnpd/getconnstatus.h b/src/contrib/miniupnp/miniupnpd/getconnstatus.h deleted file mode 100644 index 5b5da61..0000000 --- a/src/contrib/miniupnp/miniupnpd/getconnstatus.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: getconnstatus.h,v 1.2 2011/05/23 20:22:41 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETCONNSTATUS_H_INCLUDED -#define GETCONNSTATUS_H_INCLUDED - -/** - * get the connection status - * return values : - * 0 - Unconfigured - * 1 - Connecting - * 2 - Connected - * 3 - PendingDisconnect - * 4 - Disconnecting - * 5 - Disconnected */ -int -get_wan_connection_status(const char * ifname); - -/** - * return the same value as get_wan_connection_status() - * as a C string */ -const char * -get_wan_connection_status_str(const char * ifname); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/getifaddr.c b/src/contrib/miniupnp/miniupnpd/getifaddr.c deleted file mode 100644 index 8016d63..0000000 --- a/src/contrib/miniupnp/miniupnpd/getifaddr.c +++ /dev/null @@ -1,261 +0,0 @@ -/* $Id: getifaddr.c,v 1.19 2013/12/13 14:28:40 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(sun) -#include -#endif - -#include "config.h" -#include "getifaddr.h" -#if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) || defined(ENABLE_PCP) -#include -#endif - -int -getifaddr(const char * ifname, char * buf, int len, - struct in_addr * addr, struct in_addr * mask) -{ -#ifndef USE_GETIFADDRS - /* use ioctl SIOCGIFADDR. Works only for ip v4 */ - /* SIOCGIFADDR struct ifreq * */ - int s; - struct ifreq ifr; - int ifrlen; - struct sockaddr_in * ifaddr; - ifrlen = sizeof(ifr); - - if(!ifname || ifname[0]=='\0') - return -1; - s = socket(PF_INET, SOCK_DGRAM, 0); - if(s < 0) - { - syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m"); - return -1; - } - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ-1] = '\0'; - if(ioctl(s, SIOCGIFFLAGS, &ifr, &ifrlen) < 0) - { - syslog(LOG_DEBUG, "ioctl(s, SIOCGIFFLAGS, ...): %m"); - close(s); - return -1; - } - if ((ifr.ifr_flags & IFF_UP) == 0) - { - syslog(LOG_DEBUG, "network interface %s is down", ifname); - close(s); - return -1; - } - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0) - { - syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m"); - close(s); - return -1; - } - ifaddr = (struct sockaddr_in *)&ifr.ifr_addr; - if(addr) *addr = ifaddr->sin_addr; - if(buf) - { - if(!inet_ntop(AF_INET, &ifaddr->sin_addr, buf, len)) - { - syslog(LOG_ERR, "inet_ntop(): %m"); - close(s); - return -1; - } - } - if(mask) - { - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0) - { - syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m"); - close(s); - return -1; - } -#ifdef ifr_netmask - *mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr; -#else - *mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; -#endif - } - close(s); -#else /* ifndef USE_GETIFADDRS */ - /* Works for all address families (both ip v4 and ip v6) */ - struct ifaddrs * ifap; - struct ifaddrs * ife; - - if(!ifname || ifname[0]=='\0') - return -1; - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - switch(ife->ifa_addr->sa_family) - { - case AF_INET: - if(buf) - { - inet_ntop(ife->ifa_addr->sa_family, - &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, - buf, len); - } - if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr; - if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr; - break; -/* - case AF_INET6: - inet_ntop(ife->ifa_addr->sa_family, - &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, - buf, len); -*/ - } - } - freeifaddrs(ifap); -#endif - return 0; -} - -#ifdef ENABLE_PCP - -int getifaddr_in6(const char * ifname, int af, struct in6_addr * addr) -{ -#if defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) - struct ifaddrs * ifap; - struct ifaddrs * ife; -#ifdef ENABLE_IPV6 - const struct sockaddr_in6 * tmpaddr; -#endif /* ENABLE_IPV6 */ - int found = 0; - - if(!ifname || ifname[0]=='\0') - return -1; - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife && !found; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - if (ife->ifa_addr->sa_family != af) - continue; - switch(ife->ifa_addr->sa_family) - { - case AF_INET: - /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */ - memset(addr->s6_addr, 0, 10); - addr->s6_addr[10] = 0xff; - addr->s6_addr[11] = 0xff; - memcpy(addr->s6_addr + 12, - &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr), - 4); - found = 1; - break; - -#ifdef ENABLE_IPV6 - case AF_INET6: - tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr; - if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr) - && !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr)) - { - memcpy(addr->s6_addr, - &tmpaddr->sin6_addr, - 16); - found = 1; - } - break; -#endif /* ENABLE_IPV6 */ - } - } - freeifaddrs(ifap); - return (found ? 0 : -1); -#else /* defined(ENABLE_IPV6) || defined(USE_GETIFADDRS) */ - /* IPv4 only */ - struct in_addr addr4; - if(af != AF_INET) - return -1; - if(getifaddr(ifname, NULL, 0, &addr4, NULL) < 0) - return -1; - /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */ - memset(addr->s6_addr, 0, 10); - addr->s6_addr[10] = 0xff; - addr->s6_addr[11] = 0xff; - memcpy(addr->s6_addr + 12, &addr4.s_addr, 4); - return 0; -#endif -} -#endif /* ENABLE_PCP */ - -#ifdef ENABLE_IPV6 -int -find_ipv6_addr(const char * ifname, - char * dst, int n) -{ - struct ifaddrs * ifap; - struct ifaddrs * ife; - const struct sockaddr_in6 * addr; - char buf[64]; - int r = 0; - - if(!dst) - return -1; - - if(getifaddrs(&ifap)<0) - { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife; ife = ife->ifa_next) - { - /* skip other interfaces if one was specified */ - if(ifname && (0 != strcmp(ifname, ife->ifa_name))) - continue; - if(ife->ifa_addr == NULL) - continue; - if(ife->ifa_addr->sa_family == AF_INET6) - { - addr = (const struct sockaddr_in6 *)ife->ifa_addr; - if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr) - && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) - { - inet_ntop(ife->ifa_addr->sa_family, - &addr->sin6_addr, - buf, sizeof(buf)); - /* add brackets */ - snprintf(dst, n, "[%s]", buf); - r = 1; - } - } - } - freeifaddrs(ifap); - return r; -} -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/getifaddr.h b/src/contrib/miniupnp/miniupnpd/getifaddr.h deleted file mode 100644 index 2be2f45..0000000 --- a/src/contrib/miniupnp/miniupnpd/getifaddr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id: getifaddr.h,v 1.8 2013/03/23 10:46:54 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETIFADDR_H_INCLUDED -#define GETIFADDR_H_INCLUDED - -struct in_addr; -struct in6_addr; - -/* getifaddr() - * take a network interface name and write the - * ip v4 address as text in the buffer - * returns: 0 success, -1 failure */ -int -getifaddr(const char * ifname, char * buf, int len, - struct in_addr * addr, struct in_addr * mask); - -int -getifaddr_in6(const char * ifname, int af, struct in6_addr* addr); - -/* find a non link local IP v6 address for the interface. - * if ifname is NULL, look for all interfaces */ -int -find_ipv6_addr(const char * ifname, - char * dst, int n); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/getifstats.h b/src/contrib/miniupnp/miniupnpd/getifstats.h deleted file mode 100644 index e14b853..0000000 --- a/src/contrib/miniupnp/miniupnpd/getifstats.h +++ /dev/null @@ -1,25 +0,0 @@ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2008 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETIFSTATS_H_INCLUDED -#define GETIFSTATS_H_INCLUDED - -struct ifdata { - unsigned long opackets; - unsigned long ipackets; - unsigned long obytes; - unsigned long ibytes; - unsigned long baudrate; -}; - -/* getifstats() - * Fill the ifdata structure with statistics for network interface ifname. - * Return 0 in case of success, -1 for bad arguments or any error */ -int -getifstats(const char * ifname, struct ifdata * data); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/getroute.h b/src/contrib/miniupnp/miniupnpd/getroute.h deleted file mode 100644 index 86d0496..0000000 --- a/src/contrib/miniupnp/miniupnpd/getroute.h +++ /dev/null @@ -1,17 +0,0 @@ -/* $Id: getroute.h,v 1.3 2013/02/06 10:50:04 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef GETROUTE_H_INCLUDED -#define GETROUTE_H_INCLUDED - -int -get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len, - int * index); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/ifacewatcher.h b/src/contrib/miniupnp/miniupnpd/ifacewatcher.h deleted file mode 100644 index 4b2e15a..0000000 --- a/src/contrib/miniupnp/miniupnpd/ifacewatcher.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id: ifacewatcher.h,v 1.2 2011/05/20 09:42:49 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2009 Thomas Bernard - * - * ifacewatcher.h - * - * This file implements dynamic serving of new network interfaces - * which weren't available during daemon start. It also takes care - * of interfaces which become unavailable. - * - * Copyright (c) 2011, Alexey Osipov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef IFACEWATCHER_H_INCLUDED -#define IFACEWATCHER_H_INCLUDED - -#include "config.h" - -#ifdef USE_IFACEWATCHER -int OpenAndConfInterfaceWatchSocket(void); -void ProcessInterfaceWatchNotify(int s); -#endif - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/ipf/Makefile b/src/contrib/miniupnp/miniupnpd/ipf/Makefile deleted file mode 100644 index d46d1e9..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipf/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# $Id: Makefile,v 1.1 2007/09/25 19:44:43 nanard Exp $ -CC=gcc -CFLAGS=-Wall -g -I. - -all: testipfrdr - -clean: - rm *.o testipfrdr - -testipfrdr: testipfrdr.o ipfrdr.o - $(CC) -o $@ $^ - -ipfrdr.o: ipfrdr.c - -testipfrdr.o: testipfrdr.c - diff --git a/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.c b/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.c deleted file mode 100644 index 0a311b0..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.c +++ /dev/null @@ -1,831 +0,0 @@ -/* $Id: ipfrdr.c,v 1.18 2016/02/12 14:12:25 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2007 Darren Reed - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -/* - * This is a workaround for troubles on FreeBSD, HPUX, OpenBSD. - * Needed here because on some systems gets included by things - * like - */ -#ifndef _KERNEL -# define ADD_KERNEL -# define _KERNEL -# define KERNEL -#endif -#ifdef __OpenBSD__ -struct file; -#endif -#include -#ifdef ADD_KERNEL -# undef _KERNEL -# undef KERNEL -#endif -#include -#include -#include -#include -#include -#if __FreeBSD_version >= 300000 -# include -#endif -#include -#include -#include -#include -#ifndef TCP_PAWS_IDLE /* IRIX */ -# include -#endif -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(__SVR4) && !defined(__svr4__) && defined(sun) -# include -#endif -#include -#include - -#include "../config.h" -#include "netinet/ipl.h" -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" - -#include "../macros.h" - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif -#ifndef __STDC__ -# undef const -# define const -#endif - -#ifndef U_32_T -# define U_32_T 1 -# if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ - defined(__sgi) -typedef u_int32_t u_32_t; -# else -# if defined(__alpha__) || defined(__alpha) || defined(_LP64) -typedef unsigned int u_32_t; -# else -# if SOLARIS2 >= 6 -typedef uint32_t u_32_t; -# else -typedef unsigned int u_32_t; -# endif -# endif -# endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */ -#endif /* U_32_T */ - - -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ - SOLARIS || defined(__sgi) || defined(__osf__) || defined(linux) -# include -typedef int (* ioctlfunc_t) __P((int, ioctlcmd_t, ...)); -#else -typedef int (* ioctlfunc_t) __P((dev_t, ioctlcmd_t, void *)); -#endif -typedef void (* addfunc_t) __P((int, ioctlfunc_t, void *)); -typedef int (* copyfunc_t) __P((void *, void *, size_t)); - - -/* - * SunOS4 - */ -#if defined(sun) && !defined(__SVR4) && !defined(__svr4__) -extern int ioctl __P((int, int, void *)); -#endif - -#include "../upnpglobalvars.h" - -/* group name */ -static const char group_name[] = "miniupnpd"; - -static int dev = -1; -static int dev_ipl = -1; - -/* IPFilter cannot store redirection descriptions, so we use our - * own structure to store them */ -struct rdr_desc { - struct rdr_desc * next; - unsigned short eport; - int proto; - unsigned int timestamp; - char str[]; -}; - -/* pointer to the chained list where descriptions are stored */ -static struct rdr_desc * rdr_desc_list; - -static void -add_redirect_desc(unsigned short eport, int proto, - unsigned int timestamp, const char * desc) -{ - struct rdr_desc * p; - size_t l; - - if (desc != NULL) { - l = strlen(desc) + 1; - p = malloc(sizeof(struct rdr_desc) + l); - if (p) { - p->next = rdr_desc_list; - p->eport = eport; - p->proto = proto; - p->timestamp = timestamp; - memcpy(p->str, desc, l); - rdr_desc_list = p; - } - } -} - -static void -del_redirect_desc(unsigned short eport, int proto) -{ - struct rdr_desc * p, * last; - - last = NULL; - for (p = rdr_desc_list; p; p = p->next) { - if(p->eport == eport && p->proto == proto) { - if (last == NULL) - rdr_desc_list = p->next; - else - last->next = p->next; - free(p); - return; - } - } -} - -static void -get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen, unsigned int * timestamp) -{ - struct rdr_desc * p; - - if (desc == NULL || desclen == 0) - return; - for (p = rdr_desc_list; p; p = p->next) { - if (p->eport == eport && p->proto == proto) - { - strncpy(desc, p->str, desclen); - *timestamp = p->timestamp; - return; - } - } - return; -} - -int init_redirect(void) -{ - - dev = open(IPNAT_NAME, O_RDWR); - if (dev < 0) { - syslog(LOG_ERR, "open(\"%s\"): %m", IPNAT_NAME); - return -1; - } - dev_ipl = open(IPL_NAME, O_RDWR); - if (dev_ipl < 0) { - syslog(LOG_ERR, "open(\"%s\"): %m", IPL_NAME); - return -1; - } - return 0; -} - -void shutdown_redirect(void) -{ - - if (dev >= 0) { - close(dev); - dev = -1; - } - if (dev_ipl >= 0) { - close(dev_ipl); - dev = -1; - } - return; -} - -int -add_redirect_rule2(const char * ifname, const char * rhost, - unsigned short eport, const char * iaddr, unsigned short iport, - int proto, const char * desc, unsigned int timestamp) -{ - struct ipnat ipnat; - struct ipfobj obj; - int r; - - if (dev < 0) { - syslog(LOG_ERR, "%s not open", IPNAT_NAME); - return -1; - } - - memset(&obj, 0, sizeof(obj)); - memset(&ipnat, 0, sizeof(ipnat)); - - ipnat.in_redir = NAT_REDIRECT; -#if IPFILTER_VERSION >= 5000000 - ipnat.in_pr[0] = proto; - ipnat.in_pr[1] = proto; -#else - ipnat.in_p = proto; -#endif - if (proto == IPPROTO_TCP) - ipnat.in_flags = IPN_TCP; - if (proto == IPPROTO_UDP) - ipnat.in_flags = IPN_UDP; - ipnat.in_dcmp = FR_EQUAL; -#if IPFILTER_VERSION >= 5000000 - ipnat.in_dpmin = htons(eport); - ipnat.in_dpmax = htons(eport); - ipnat.in_dpnext = htons(iport); - ipnat.in_v[0] = 4; - ipnat.in_v[1] = 4; -#else - ipnat.in_pmin = htons(eport); - ipnat.in_pmax = htons(eport); - ipnat.in_pnext = htons(iport); - ipnat.in_v = 4; -#endif - strlcpy(ipnat.in_tag.ipt_tag, group_name, IPFTAG_LEN); - -#ifdef USE_IFNAME_IN_RULES - if (ifname) { -#if IPFILTER_VERSION >= 5000000 - /* XXX check for stack overflow ! */ - ipnat.in_ifnames[0] = 0; - ipnat.in_ifnames[1] = 0; - strlcpy(ipnat.in_names, ifname, IFNAMSIZ); - ipnat.in_namelen = strlen(ipnat.in_names) + 1; -#else - strlcpy(ipnat.in_ifnames[0], ifname, IFNAMSIZ); - strlcpy(ipnat.in_ifnames[1], ifname, IFNAMSIZ); -#endif - } -#endif - - if(rhost && rhost[0] != '\0' && rhost[0] != '*') - { -#if IPFILTER_VERSION >= 5000000 - inet_pton(AF_INET, rhost, &ipnat.in_nsrc.na_addr[0].in4); /* in_nsrcip */ - ipnat.in_nsrc.na_addr[1].in4.s_addr = 0xffffffff; /* in_nsrcmsk */ -#else - inet_pton(AF_INET, rhost, &ipnat.in_src[0].in4); - ipnat.in_src[1].in4.s_addr = 0xffffffff; -#endif - } - -#if IPFILTER_VERSION >= 5000000 - inet_pton(AF_INET, iaddr, &ipnat.in_ndst.na_addr[0].in4); /* in_ndstip */ - ipnat.in_ndst.na_addr[1].in4.s_addr = 0xffffffff; /* in_ndstmsk */ -#else - inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4); - ipnat.in_in[1].in4.s_addr = 0xffffffff; -#endif - - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(ipnat); - obj.ipfo_ptr = &ipnat; - obj.ipfo_type = IPFOBJ_IPNAT; - - r = ioctl(dev, SIOCADNAT, &obj); - if (r == -1) - syslog(LOG_ERR, "ioctl(SIOCADNAT): %m"); - else - add_redirect_desc(eport, proto, timestamp, desc); - return r; -} - -/* get_redirect_rule() - * return value : 0 success (found) - * -1 = error or rule not found */ -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - ipfgeniter_t iter; - ipfobj_t obj; - ipnat_t ipn; - int r; - UNUSED(ifname); - - memset(&obj, 0, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_type = IPFOBJ_GENITER; - obj.ipfo_size = sizeof(iter); - obj.ipfo_ptr = &iter; - - iter.igi_type = IPFGENITER_IPNAT; -#if IPFILTER_VERSION > 4011300 - iter.igi_nitems = 1; -#endif - iter.igi_data = &ipn; - - if (dev < 0) { - syslog(LOG_ERR, "%s not open", IPNAT_NAME); - return -1; - } - - r = -1; - do { - if (ioctl(dev, SIOCGENITER, &obj) == -1) { - syslog(LOG_ERR, "ioctl(dev, SIOCGENITER): %m"); - break; - } -#if IPFILTER_VERSION >= 5000000 - if (eport == ntohs(ipn.in_dpmin) && - eport == ntohs(ipn.in_dpmax) && - strcmp(ipn.in_tag.ipt_tag, group_name) == 0 && - ipn.in_pr[0] == proto) -#else - if (eport == ntohs(ipn.in_pmin) && - eport == ntohs(ipn.in_pmax) && - strcmp(ipn.in_tag.ipt_tag, group_name) == 0 && - ipn.in_p == proto) -#endif - { - strlcpy(desc, "", desclen); - if (packets != NULL) - *packets = 0; - if (bytes != NULL) - *bytes = 0; - if (iport != NULL) -#if IPFILTER_VERSION >= 5000000 - *iport = ntohs(ipn.in_dpnext); -#else - *iport = ntohs(ipn.in_pnext); -#endif - if ((desc != NULL) && (timestamp != NULL)) - get_redirect_desc(eport, proto, desc, desclen, timestamp); - if ((rhost != NULL) && (rhostlen > 0)) -#if IPFILTER_VERSION >= 5000000 - inet_ntop(AF_INET, &ipn.in_nsrc.na_addr[0].in4, rhost, rhostlen); /* in_nsrcip */ -#else - inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen); -#endif -#if IPFILTER_VERSION >= 5000000 - inet_ntop(AF_INET, &ipn.in_ndst.na_addr[0].in4, iaddr, iaddrlen); /* in_ndstip */ -#else - inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen); -#endif - r = 0; - } - } while (ipn.in_next != NULL); - return r; -} - - -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - ipfgeniter_t iter; - ipfobj_t obj; - ipnat_t ipn; - int n, r; - - if (index < 0) - return -1; - - if (dev < 0) { - syslog(LOG_ERR, "%s not open", IPNAT_NAME); - return -1; - } - - memset(&obj, 0, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_ptr = &iter; - obj.ipfo_size = sizeof(iter); - obj.ipfo_type = IPFOBJ_GENITER; - - iter.igi_type = IPFGENITER_IPNAT; -#if IPFILTER_VERSION > 4011300 - iter.igi_nitems = 1; -#endif - iter.igi_data = &ipn; - - n = 0; - r = -1; - do { - if (ioctl(dev, SIOCGENITER, &obj) == -1) { - syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m", - "get_redirect_rule_by_index"); - break; - } - - if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0) - continue; - - if (index == n++) { -#if IPFILTER_VERSION >= 5000000 - *proto = ipn.in_pr[0]; - *eport = ntohs(ipn.in_dpmax); - *iport = ntohs(ipn.in_dpnext); -#else - *proto = ipn.in_p; - *eport = ntohs(ipn.in_pmax); - *iport = ntohs(ipn.in_pnext); -#endif - - if (ifname) -#if IPFILTER_VERSION >= 5000000 - strlcpy(ifname, ipn.in_names + ipn.in_ifnames[0], IFNAMSIZ); -#else - strlcpy(ifname, ipn.in_ifnames[0], IFNAMSIZ); -#endif - if (packets != NULL) - *packets = 0; - if (bytes != NULL) - *bytes = 0; - if ((desc != NULL) && (timestamp != NULL)) - get_redirect_desc(*eport, *proto, desc, desclen, timestamp); - if ((rhost != NULL) && (rhostlen > 0)) -#if IPFILTER_VERSION >= 5000000 - inet_ntop(AF_INET, &ipn.in_nsrc.na_addr[0].in4, rhost, rhostlen); /* in_nsrcip */ -#else - inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen); -#endif -#if IPFILTER_VERSION >= 5000000 - inet_ntop(AF_INET, &ipn.in_ndst.na_addr[0].in4, iaddr, iaddrlen); /* in_ndstip */ -#else - inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen); -#endif - r = 0; - } - } while (ipn.in_next != NULL); - return r; -} - -static int -real_delete_redirect_rule(const char * ifname, unsigned short eport, int proto) -{ - ipfgeniter_t iter; - ipfobj_t obj; - ipnat_t ipn; - int r; - UNUSED(ifname); - - memset(&obj, 0, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_type = IPFOBJ_GENITER; - obj.ipfo_size = sizeof(iter); - obj.ipfo_ptr = &iter; - - iter.igi_type = IPFGENITER_IPNAT; -#if IPFILTER_VERSION > 4011300 - iter.igi_nitems = 1; -#endif - iter.igi_data = &ipn; - - if (dev < 0) { - syslog(LOG_ERR, "%s not open", IPNAT_NAME); - return -1; - } - - r = -1; - do { - if (ioctl(dev, SIOCGENITER, &obj) == -1) { - syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m", - "delete_redirect_rule"); - break; - } -#if IPFILTER_VERSION >= 5000000 - if (eport == ntohs(ipn.in_dpmin) && - eport == ntohs(ipn.in_dpmax) && - strcmp(ipn.in_tag.ipt_tag, group_name) == 0 && - ipn.in_pr[0] == proto) -#else - if (eport == ntohs(ipn.in_pmin) && - eport == ntohs(ipn.in_pmax) && - strcmp(ipn.in_tag.ipt_tag, group_name) == 0 && - ipn.in_p == proto) -#endif - { - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(ipn); - obj.ipfo_ptr = &ipn; - obj.ipfo_type = IPFOBJ_IPNAT; - r = ioctl(dev, SIOCRMNAT, &obj); - if (r == -1) - syslog(LOG_ERR, "%s:ioctl(SIOCRMNAT): %m", - "delete_redirect_rule"); - /* Delete the desc even if the above failed */ - del_redirect_desc(eport, proto); - break; - } - } while (ipn.in_next != NULL); - return r; -} - -/* FIXME: For some reason, the iter isn't reset every other delete, - * so we attempt 2 deletes. */ -int -delete_redirect_rule(const char * ifname, unsigned short eport, int proto) -{ - int r; - - r = real_delete_redirect_rule(ifname, eport, proto); - if (r == -1) - r = real_delete_redirect_rule(ifname, eport, proto); - return r; -} - -/* thanks to Seth Mos for this function */ -int -add_filter_rule2(const char * ifname, const char * rhost, - const char * iaddr, unsigned short eport, unsigned short iport, - int proto, const char * desc) -{ - ipfobj_t obj; - frentry_t fr; - fripf_t ipffr; - int r; - UNUSED(ifname); UNUSED(desc); - UNUSED(iport); - - if (dev_ipl < 0) { - syslog(LOG_ERR, "%s not open", IPL_NAME); - return -1; - } - - memset(&obj, 0, sizeof(obj)); - memset(&fr, 0, sizeof(fr)); - memset(&ipffr, 0, sizeof(ipffr)); - - fr.fr_flags = FR_PASS|FR_KEEPSTATE|FR_QUICK|FR_INQUE; - if (GETFLAG(LOGPACKETSMASK)) - fr.fr_flags |= FR_LOG|FR_LOGFIRST; -#if IPFILTER_VERSION >= 5000000 - fr.fr_family = PF_INET; -#else - fr.fr_v = 4; -#endif - - fr.fr_type = FR_T_IPF; - fr.fr_dun.fru_ipf = &ipffr; - fr.fr_dsize = sizeof(ipffr); - fr.fr_isc = (void *)-1; - - fr.fr_proto = proto; - fr.fr_mproto = 0xff; - fr.fr_dcmp = FR_EQUAL; - fr.fr_dport = eport; -#ifdef USE_IFNAME_IN_RULES - if (ifname) { -#if IPFILTER_VERSION >= 5000000 - /* XXX check for stack overflow ! */ - fr.fr_ifnames[0] = fr.fr_namelen; - strlcpy(fr.fr_names + fr.fr_ifnames[0], ifname, IFNAMSIZ); - fr.fr_namelen += strlen(ifname) + 1; -#else - strlcpy(fr.fr_ifnames[0], ifname, IFNAMSIZ); -#endif - } -#endif -#if IPFILTER_VERSION >= 5000000 - /* XXX check for stack overflow ! */ - fr.fr_group = fr.fr_namelen; - strlcpy(fr.fr_names + fr.fr_group, group_name, FR_GROUPLEN); - fr.fr_namelen += strlen(group_name) + 1; -#else - strlcpy(fr.fr_group, group_name, sizeof(fr.fr_group)); -#endif - - if (proto == IPPROTO_TCP) { - fr.fr_tcpf = TH_SYN; - fr.fr_tcpfm = TH_SYN|TH_ACK|TH_RST|TH_FIN|TH_URG|TH_PUSH; - } - - if(rhost && rhost[0] != '\0' && rhost[0] != '*') - { - inet_pton(AF_INET, rhost, &fr.fr_saddr); - fr.fr_smask = 0xffffffff; - } - - inet_pton(AF_INET, iaddr, &fr.fr_daddr); - fr.fr_dmask = 0xffffffff; - - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_ptr = &fr; - obj.ipfo_size = sizeof(fr); - - r = ioctl(dev_ipl, SIOCINAFR, &obj); - if (r == -1) { - if (errno == ESRCH) - syslog(LOG_ERR, - "SIOCINAFR(missing 'head %s' rule?):%m", - group_name); - else - syslog(LOG_ERR, "SIOCINAFR:%m"); - } - return r; -} - -int -delete_filter_rule(const char * ifname, unsigned short eport, int proto) -{ - ipfobj_t wobj, dobj; - ipfruleiter_t rule; - u_long darray[1000]; - u_long array[1000]; - friostat_t fio; - frentry_t *fp; - int r; - UNUSED(ifname); - - if (dev_ipl < 0) { - syslog(LOG_ERR, "%s not open", IPL_NAME); - return -1; - } - - wobj.ipfo_rev = IPFILTER_VERSION; - wobj.ipfo_type = IPFOBJ_IPFSTAT; - wobj.ipfo_size = sizeof(fio); - wobj.ipfo_ptr = &fio; - - if (ioctl(dev_ipl, SIOCGETFS, &wobj) == -1) { - syslog(LOG_ERR, "ioctl(SIOCGETFS): %m"); - return -1; - } - - wobj.ipfo_rev = IPFILTER_VERSION; - wobj.ipfo_ptr = &rule; - wobj.ipfo_size = sizeof(rule); - wobj.ipfo_type = IPFOBJ_IPFITER; - - fp = (frentry_t *)array; - fp->fr_dun.fru_data = darray; - fp->fr_dsize = sizeof(darray); - - rule.iri_inout = 0; - rule.iri_active = fio.f_active; -#if IPFILTER_VERSION > 4011300 - rule.iri_nrules = 1; - rule.iri_v = 4; -#endif - rule.iri_rule = fp; - strlcpy(rule.iri_group, group_name, sizeof(rule.iri_group)); - - dobj.ipfo_rev = IPFILTER_VERSION; - dobj.ipfo_size = sizeof(*fp); - dobj.ipfo_type = IPFOBJ_FRENTRY; - - r = -1; - do { - memset(array, 0xff, sizeof(array)); - - if (ioctl(dev_ipl, SIOCIPFITER, &wobj) == -1) { - syslog(LOG_ERR, "ioctl(SIOCIPFITER): %m"); - break; - } - - if (fp->fr_data != NULL) - fp->fr_data = (char *)fp + sizeof(*fp); - if ((fp->fr_type & ~FR_T_BUILTIN) == FR_T_IPF && - fp->fr_dport == eport && - fp->fr_proto == proto) - { - dobj.ipfo_ptr = fp; - - r = ioctl(dev_ipl, SIOCRMAFR, &dobj); - if (r == -1) - syslog(LOG_ERR, "ioctl(SIOCRMAFR): %m"); - break; - } - } while (fp->fr_next != NULL); - return r; -} - -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number) -{ - unsigned short *array, *array2; - unsigned int capacity; - unsigned short eport; - ipfgeniter_t iter; - ipfobj_t obj; - ipnat_t ipn; - - *number = 0; - if (dev < 0) { - syslog(LOG_ERR, "%s not open", IPNAT_NAME); - return NULL; - } - capacity = 128; - array = calloc(capacity, sizeof(unsigned short)); - if(!array) - { - syslog(LOG_ERR, "get_portmappings_in_range() : calloc error"); - return NULL; - } - - memset(&obj, 0, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_ptr = &iter; - obj.ipfo_size = sizeof(iter); - obj.ipfo_type = IPFOBJ_GENITER; - - iter.igi_type = IPFGENITER_IPNAT; -#if IPFILTER_VERSION > 4011300 - iter.igi_nitems = 1; -#endif - iter.igi_data = &ipn; - - do { - if (ioctl(dev, SIOCGENITER, &obj) == -1) { - syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m", - "get_portmappings_in_range"); - break; - } - - if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0) - continue; - -#if IPFILTER_VERSION >= 5000000 - eport = ntohs(ipn.in_dpmin); - if( (eport == ntohs(ipn.in_dpmax)) - && (ipn.in_pr[0] == proto) - && (startport <= eport) && (eport <= endport) ) -#else - eport = ntohs(ipn.in_pmin); - if( (eport == ntohs(ipn.in_pmax)) - && (ipn.in_p == proto) - && (startport <= eport) && (eport <= endport) ) -#endif - { - if(*number >= capacity) - { - /* need to increase the capacity of the array */ - capacity += 128; - array2 = realloc(array, sizeof(unsigned short)*capacity); - if(!array2) - { - syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity); - *number = 0; - free(array); - return NULL; - } - array = array2; - } - array[*number] = eport; - (*number)++; - } - } while (ipn.in_next != NULL); - return array; -} - -/* update the port mapping internal port, decription and timestamp */ -int -update_portmapping(const char * ifname, unsigned short eport, int proto, - unsigned short iport, const char * desc, - unsigned int timestamp) -{ - UNUSED(ifname); UNUSED(eport); UNUSED(proto); - UNUSED(iport); UNUSED(desc); UNUSED(timestamp); - /* TODO: implement update_portmapping() */ - syslog(LOG_ERR, __FILE__ " update_portmapping() is not implemented"); - return -1; -} - -/* update the port mapping decription and timestamp */ -int -update_portmapping_desc_timestamp(const char * ifname, - unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - UNUSED(ifname); - del_redirect_desc(eport, proto); - add_redirect_desc(eport,proto, timestamp, desc); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.h b/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.h deleted file mode 100644 index f48b083..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipf/ipfrdr.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id: ipfrdr.h,v 1.3 2007/11/02 22:54:01 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2007 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef IPFRDR_H_INCLUDED -#define IPFRDR_H_INCLUDED - -#include "../commonrdr.h" - -int -add_redirect_rule2(const char * ifname, const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -add_filter_rule2(const char * ifname, const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc); - - -/* get_redirect_rule() gets internal IP and port from - * interface, external port and protocl - */ -#if 0 -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - u_int64_t * packets, u_int64_t * bytes); - -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - u_int64_t * packets, u_int64_t * bytes); -#endif - -/* delete_redirect_rule() - */ -int -delete_redirect_rule(const char * ifname, unsigned short eport, int proto); - -/* delete_filter_rule() - */ -int -delete_filter_rule(const char * ifname, unsigned short eport, int proto); - -int -clear_redirect_rules(void); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/ipf/testipfrdr.c b/src/contrib/miniupnp/miniupnpd/ipf/testipfrdr.c deleted file mode 100644 index 61f8b91..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipf/testipfrdr.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $Id: testipfrdr.c,v 1.3 2007/10/01 16:21:23 nanard Exp $ */ - -#include -#include -#include -#include -#include -#include "ipfrdr.h" - -/* test program for ipfrdr.c */ - -int runtime_flags = 0; - -void -list_eports_tcp(void) -{ - unsigned short * port_list; - unsigned int number = 0; - unsigned int i; - port_list = get_portmappings_in_range(0, 65535, IPPROTO_TCP, &number); - printf("%u ports redirected (TCP) :", number); - for(i = 0; i < number; i++) - { - printf(" %hu", port_list[i]); - } - printf("\n"); - free(port_list); - port_list = get_portmappings_in_range(0, 65535, IPPROTO_UDP, &number); - printf("%u ports redirected (UDP) :", number); - for(i = 0; i < number; i++) - { - printf(" %hu", port_list[i]); - } - printf("\n"); - free(port_list); -} - -int -main(int argc, char * * argv) -{ - char c; - - openlog("testipfrdrd", LOG_CONS|LOG_PERROR, LOG_USER); - if(init_redirect() < 0) - { - fprintf(stderr, "init_redirect() failed\n"); - return 1; - } - - printf("List rdr ports :\n"); - list_eports_tcp(); - - printf("Add redirection !\n"); - add_redirect_rule2("xennet0", "*", 12345, "192.168.1.100", 54321, IPPROTO_UDP, - "redirection description", 0); - add_redirect_rule2("xennet0", "8.8.8.8", 12345, "192.168.1.100", 54321, IPPROTO_TCP, - "redirection description", 0); - - printf("Check redirect rules with \"ipnat -l\" then press any key.\n"); - c = getchar(); - - printf("List rdr ports :\n"); - list_eports_tcp(); - - printf("Delete redirection !\n"); - delete_redirect_rule("xennet0", 12345, IPPROTO_UDP); - delete_redirect_rule("xennet0", 12345, IPPROTO_TCP); - - printf("List rdr ports :\n"); - list_eports_tcp(); - - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/Makefile b/src/contrib/miniupnp/miniupnpd/ipfw/Makefile deleted file mode 100644 index 6a2467d..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $Id: Makefile,v 1.2 2009/08/20 09:31:10 nanard Exp $ -CC=gcc -CFLAGS=-Wall -g -I. -RM=rm -f - -all: testipfwrdr - -clean: - $(RM) *.o testipfwrdr - -testipfwrdr: testipfwrdr.o ipfwrdr.o ipfwaux.o - $(CC) -o $@ $^ - -ipfwrdr.o: ipfwrdr.c ipfwaux.c - -testipfwrdr.o: testipfwrdr.c - diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.c b/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.c deleted file mode 100644 index d5ecf35..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009-2012 Jardel Weyrich - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#include "ipfwaux.h" -#include -#include -#include -#include -#include - -int ipfw_exec(int optname, void * optval, uintptr_t optlen) { - static int sock = -1; - int result; - - switch (optname) { - case IP_FW_INIT: - if (sock == -1) - sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - if (sock < 0) { - syslog(LOG_ERR, "socket(SOCK_RAW): %m"); - return -1; - } - break; - case IP_FW_TERM: - if (sock != -1) - close(sock); - sock = -1; - break; - case IP_FW_ADD: - case IP_FW_DEL: - result = setsockopt(sock, IPPROTO_IP, optname, optval, optlen); - if (result == -1) { - syslog(LOG_ERR, "setsockopt(): %m"); - return -1; - } - break; - case IP_FW_GET: - result = getsockopt(sock, IPPROTO_IP, optname, optval, (socklen_t *)optlen); - if (result == -1) { - syslog(LOG_ERR, "getsockopt(): %m"); - return -1; - } - break; - default: - syslog(LOG_ERR, "unhandled option"); - return -1; - } - - return 0; -} - -void ipfw_free_ruleset(struct ip_fw ** rules) { - if (rules == NULL || *rules == NULL) - return; - free(*rules); - *rules = NULL; -} - -int ipfw_fetch_ruleset(struct ip_fw ** rules, int * total_fetched, int count) { - int fetched; - socklen_t size; - - if (rules == NULL || *total_fetched < 0 || count < 1) - return -1; - - size = sizeof(struct ip_fw) * (*total_fetched + count); - *rules = (struct ip_fw *)realloc(*rules, size); - if (*rules == NULL) { - syslog(LOG_ERR, "realloc(): %m"); - return -1; - } - - (*rules)->version = IP_FW_CURRENT_API_VERSION; - if (ipfw_exec(IP_FW_GET, *rules, (uintptr_t)&size) < 0) - return -1; - fetched = *total_fetched; - *total_fetched = size / sizeof(struct ip_fw); - - return *total_fetched - fetched; -} - -int ipfw_validate_protocol(int value) { - switch (value) { - case IPPROTO_TCP: - case IPPROTO_UDP: - break; - default: - syslog(LOG_ERR, "invalid protocol"); - return -1; - } - return 0; -} - -int ipfw_validate_ifname(const char * const value) { - int len = strlen(value); - if (len < 2 || len > FW_IFNLEN) { - syslog(LOG_ERR, "invalid interface name"); - return -1; - } - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.h b/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.h deleted file mode 100644 index 44d4046..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwaux.h +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id: ipfwaux.h,v 1.6 2015/09/04 14:20:58 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009-2012 Jardel Weyrich - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ -#ifndef IPFWAUX_H -#define IPFWAUX_H - -#include -#include -#include -#include -#include - -#define IP_FW_BASE (IP_FW_ADD - 5) -#define IP_FW_INIT (IP_FW_BASE + 1) -#define IP_FW_TERM (IP_FW_BASE + 2) - -int ipfw_exec(int optname, void * optval, uintptr_t optlen); -void ipfw_free_ruleset(struct ip_fw ** rules); -int ipfw_fetch_ruleset(struct ip_fw ** rules, int * total_fetched, int count); -int ipfw_validate_protocol(int value); -int ipfw_validate_ifname(const char * const value); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.c b/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.c deleted file mode 100644 index ce37af3..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.c +++ /dev/null @@ -1,548 +0,0 @@ -/* $Id: ipfwrdr.c,v 1.16 2016/02/12 13:44:01 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009 Jardel Weyrich - * (c) 2011-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#include "../config.h" -#include "../macros.h" - -#include -#include -#include - -/* -This is a workaround for troubles on FreeBSD, HPUX, OpenBSD. -Needed here because on some systems gets included by things -like -*/ -#ifndef _KERNEL -# define ADD_KERNEL -# define _KERNEL -# define KERNEL -#endif -#ifdef __OpenBSD__ -struct file; -#endif -#include -#ifdef ADD_KERNEL -# undef _KERNEL -# undef KERNEL -#endif - -#include -#include -#include -#include -#include -#if __FreeBSD_version >= 300000 -# include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ipfwaux.h" -#include "ipfwrdr.h" - -#include "../upnpglobalvars.h" - -/* init and shutdown functions */ - -int init_redirect(void) { - return ipfw_exec(IP_FW_INIT, NULL, 0); -} - -void shutdown_redirect(void) { - ipfw_exec(IP_FW_TERM, NULL, 0); -} - -/* ipfw cannot store descriptions and timestamp for port mappings so we keep - * our own list in memory */ -struct mapping_desc_time { - struct mapping_desc_time * next; - unsigned int timestamp; - unsigned short eport; - short proto; - char desc[]; -}; - -static struct mapping_desc_time * mappings_list = NULL; - -/* add an element to the port mappings descriptions & timestamp list */ -static void -add_desc_time(unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - struct mapping_desc_time * tmp; - size_t l; - if(!desc) - desc = "miniupnpd"; - l = strlen(desc) + 1; - tmp = malloc(sizeof(struct mapping_desc_time) + l); - if(tmp) { - /* fill the element and insert it as head of the list */ - tmp->next = mappings_list; - tmp->timestamp = timestamp; - tmp->eport = eport; - tmp->proto = (short)proto; - memcpy(tmp->desc, desc, l); - mappings_list = tmp; - } -} - -/* remove an element to the port mappings descriptions & timestamp list */ -static void -del_desc_time(unsigned short eport, int proto) -{ - struct mapping_desc_time * e; - struct mapping_desc_time * * p; - p = &mappings_list; - e = *p; - while(e) { - if(e->eport == eport && e->proto == (short)proto) { - *p = e->next; - free(e); - return; - } else { - p = &e->next; - e = *p; - } - } -} - -/* go through the list and find the description and timestamp */ -static void -get_desc_time(unsigned short eport, int proto, - char * desc, int desclen, - unsigned int * timestamp) -{ - struct mapping_desc_time * e; - - for(e = mappings_list; e; e = e->next) { - if(e->eport == eport && e->proto == (short)proto) { - if(desc) - strlcpy(desc, e->desc, desclen); - if(timestamp) - *timestamp = e->timestamp; - return; - } - } -} - -/* --- */ -int add_redirect_rule2( - const char * ifname, - const char * rhost, - unsigned short eport, - const char * iaddr, - unsigned short iport, - int proto, - const char * desc, - unsigned int timestamp) -{ - struct ip_fw rule; - int r; - - if (ipfw_validate_protocol(proto) < 0) - return -1; - if (ipfw_validate_ifname(ifname) < 0) - return -1; - - memset(&rule, 0, sizeof(struct ip_fw)); - rule.version = IP_FW_CURRENT_API_VERSION; -#if 0 - rule.fw_number = 1000; /* rule number */ - rule.context = (void *)desc; /* The description is kept in a separate list */ -#endif - rule.fw_prot = proto; /* protocol */ - rule.fw_flg |= IP_FW_F_IIFACE; /* interfaces to check */ - rule.fw_flg |= IP_FW_F_IIFNAME; /* interfaces to check by name */ - rule.fw_flg |= (IP_FW_F_IN | IP_FW_F_OUT); /* packet direction */ - rule.fw_flg |= IP_FW_F_FWD; /* forward action */ -#ifdef USE_IFNAME_IN_RULES - if (ifname != NULL) { - strlcpy(rule.fw_in_if.fu_via_if.name, ifname, IFNAMSIZ); /* src interface */ - rule.fw_in_if.fu_via_if.unit = -1; - } -#endif - if (inet_aton(iaddr, &rule.fw_out_if.fu_via_ip) == 0) { - syslog(LOG_ERR, "inet_aton(): %m"); - return -1; - } - memcpy(&rule.fw_dst, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr)); - memcpy(&rule.fw_fwd_ip.sin_addr, &rule.fw_out_if.fu_via_ip, sizeof(struct in_addr)); - rule.fw_dmsk.s_addr = INADDR_BROADCAST; /* TODO check this */ - IP_FW_SETNDSTP(&rule, 1); /* number of external ports */ - rule.fw_uar.fw_pts[0] = eport; /* external port */ - rule.fw_fwd_ip.sin_port = iport; /* internal port */ - if (rhost && rhost[0] != '\0') { - inet_aton(rhost, &rule.fw_src); - rule.fw_smsk.s_addr = htonl(INADDR_NONE); - } - - r = ipfw_exec(IP_FW_ADD, &rule, sizeof(rule)); - if(r >= 0) - add_desc_time(eport, proto, desc, timestamp); - return r; -} - -/* get_redirect_rule() - * return value : 0 success (found) - * -1 = error or rule not found */ -int get_redirect_rule( - const char * ifname, - unsigned short eport, - int proto, - char * iaddr, - int iaddrlen, - unsigned short * iport, - char * desc, - int desclen, - char * rhost, - int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, - u_int64_t * bytes) -{ - int i, count_rules, total_rules = 0; - struct ip_fw * rules = NULL; - - if (ipfw_validate_protocol(proto) < 0) - return -1; - if (ipfw_validate_ifname(ifname) < 0) - return -1; - if (timestamp) - *timestamp = 0; - - do { - count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10); - if (count_rules < 0) - goto error; - } while (count_rules == 10); - - for (i=0; ifw_prot && eport == ptr->fw_uar.fw_pts[0]) { - if (packets != NULL) - *packets = ptr->fw_pcnt; - if (bytes != NULL) - *bytes = ptr->fw_bcnt; - if (iport != NULL) - *iport = ptr->fw_fwd_ip.sin_port; - if (iaddr != NULL && iaddrlen > 0) { - /* looks like fw_out_if.fu_via_ip is zero */ - /*if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {*/ - if (inet_ntop(AF_INET, &ptr->fw_fwd_ip.sin_addr, iaddr, iaddrlen) == NULL) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - } - if (rhost != NULL && rhostlen > 0) { - if (ptr->fw_src.s_addr == 0) - rhost[0] = '\0'; - else if (inet_ntop(AF_INET, &ptr->fw_src.s_addr, rhost, rhostlen) == NULL) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - } - /* And what if we found more than 1 matching rule? */ - ipfw_free_ruleset(&rules); - get_desc_time(eport, proto, desc, desclen, timestamp); - return 0; - } - } - -error: - if (rules != NULL) - ipfw_free_ruleset(&rules); - return -1; -} - -int delete_redirect_rule( - const char * ifname, - unsigned short eport, - int proto) -{ - int i, count_rules, total_rules = 0; - struct ip_fw * rules = NULL; - - if (ipfw_validate_protocol(proto) < 0) - return -1; - if (ipfw_validate_ifname(ifname) < 0) - return -1; - - do { - count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10); - if (count_rules < 0) - goto error; - } while (count_rules == 10); - - for (i=0; ifw_prot && eport == ptr->fw_uar.fw_pts[0]) { - if (ipfw_exec(IP_FW_DEL, (struct ip_fw *)ptr, sizeof(*ptr)) < 0) - goto error; - /* And what if we found more than 1 matching rule? */ - ipfw_free_ruleset(&rules); - del_desc_time(eport, proto); - return 0; - } - } - -error: - if (rules != NULL) - ipfw_free_ruleset(&rules); - return -1; -} - -int add_filter_rule2( - const char * ifname, - const char * rhost, - const char * iaddr, - unsigned short eport, - unsigned short iport, - int proto, - const char * desc) -{ - UNUSED(ifname); - UNUSED(rhost); - UNUSED(iaddr); - UNUSED(eport); - UNUSED(iport); - UNUSED(proto); - UNUSED(desc); - return 0; /* nothing to do, always success */ -} - -int delete_filter_rule( - const char * ifname, - unsigned short eport, - int proto) -{ - UNUSED(ifname); - UNUSED(eport); - UNUSED(proto); - return 0; /* nothing to do, always success */ -} - -int get_redirect_rule_by_index( - int index, - char * ifname, - unsigned short * eport, - char * iaddr, - int iaddrlen, - unsigned short * iport, - int * proto, - char * desc, - int desclen, - char * rhost, - int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, - u_int64_t * bytes) -{ - int total_rules = 0; - struct ip_fw * rules = NULL; - - if (index < 0) /* TODO shouldn't we also validate the maximum? */ - return -1; - - if(timestamp) - *timestamp = 0; - - ipfw_fetch_ruleset(&rules, &total_rules, index + 1); - - if (total_rules > index) { - const struct ip_fw const * ptr = &rules[index]; - if (ptr->fw_prot == 0) /* invalid rule */ - goto error; - if (proto != NULL) - *proto = ptr->fw_prot; - if (eport != NULL) - *eport = ptr->fw_uar.fw_pts[0]; - if (iport != NULL) - *iport = ptr->fw_fwd_ip.sin_port; - if (ifname != NULL) - strlcpy(ifname, ptr->fw_in_if.fu_via_if.name, IFNAMSIZ); - if (packets != NULL) - *packets = ptr->fw_pcnt; - if (bytes != NULL) - *bytes = ptr->fw_bcnt; - if (iport != NULL) - *iport = ptr->fw_fwd_ip.sin_port; - if (iaddr != NULL && iaddrlen > 0) { - /* looks like fw_out_if.fu_via_ip is zero */ - /*if (inet_ntop(AF_INET, &ptr->fw_out_if.fu_via_ip, iaddr, iaddrlen) == NULL) {*/ - if (inet_ntop(AF_INET, &ptr->fw_fwd_ip.sin_addr, iaddr, iaddrlen) == NULL) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - } - if (rhost != NULL && rhostlen > 0) { - if (ptr->fw_src.s_addr == 0) - rhost[0] = '\0'; - else if (inet_ntop(AF_INET, &ptr->fw_src.s_addr, rhost, rhostlen) == NULL) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - } - ipfw_free_ruleset(&rules); - get_desc_time(*eport, *proto, desc, desclen, timestamp); - return 0; - } - -error: - if (rules != NULL) - ipfw_free_ruleset(&rules); - return -1; -} - -/* upnp_get_portmappings_in_range() - * return a list of all "external" ports for which a port - * mapping exists */ -unsigned short * -get_portmappings_in_range(unsigned short startport, - unsigned short endport, - int proto, - unsigned int * number) -{ - unsigned short *array = NULL, *array2 = NULL; - unsigned int capacity = 128; - int i, count_rules, total_rules = 0; - struct ip_fw * rules = NULL; - - if (ipfw_validate_protocol(proto) < 0) - return NULL; - - do { - count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10); - if (count_rules < 0) - goto error; - } while (count_rules == 10); - - array = calloc(capacity, sizeof(unsigned short)); - if(!array) { - syslog(LOG_ERR, "get_portmappings_in_range() : calloc error"); - goto error; - } - *number = 0; - - for (i=0; ifw_uar.fw_pts[0]; - if (proto == ptr->fw_prot - && startport <= eport - && eport <= endport) { - if(*number >= capacity) { - capacity += 128; - array2 = realloc(array, sizeof(unsigned short)*capacity); - if(!array2) { - syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity); - *number = 0; - free(array); - goto error; - } - array = array2; - } - array[*number] = eport; - (*number)++; - } - } -error: - if (rules != NULL) - ipfw_free_ruleset(&rules); - return array; -} - -int -update_portmapping_desc_timestamp(const char * ifname, - unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - UNUSED(ifname); - del_desc_time(eport, proto); - add_desc_time(eport, proto, desc, timestamp); - return 0; -} - -int -update_portmapping(const char * ifname, unsigned short eport, int proto, - unsigned short iport, const char * desc, - unsigned int timestamp) -{ - int i, count_rules, total_rules = 0; - struct ip_fw * rules = NULL; - int r = -1; - char iaddr[16]; - char rhost[16]; - int found; - - if (ipfw_validate_protocol(proto) < 0) - return -1; - if (ipfw_validate_ifname(ifname) < 0) - return -1; - - do { - count_rules = ipfw_fetch_ruleset(&rules, &total_rules, 10); - if (count_rules < 0) - goto error; - } while (count_rules == 10); - - found = 0; - iaddr[0] = '\0'; - rhost[0] = '\0'; - - for (i=0; ifw_prot && eport == ptr->fw_uar.fw_pts[0]) { - if (inet_ntop(AF_INET, &ptr->fw_fwd_ip.sin_addr, iaddr, sizeof(iaddr)) == NULL) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - if ((ptr->fw_src.s_addr != 0) && - (inet_ntop(AF_INET, &ptr->fw_src.s_addr, rhost, sizeof(rhost)) == NULL)) { - syslog(LOG_ERR, "inet_ntop(): %m"); - goto error; - } - found = 1; - if (ipfw_exec(IP_FW_DEL, (struct ip_fw *)ptr, sizeof(*ptr)) < 0) - goto error; - del_desc_time(eport, proto); - break; - } - } - ipfw_free_ruleset(&rules); - rules = NULL; - - if(found) - r = add_redirect_rule2(ifname, rhost, eport, iaddr, iport, proto, desc, timestamp); - -error: - if (rules != NULL) - ipfw_free_ruleset(&rules); - return r; -} diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.h b/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.h deleted file mode 100644 index 9e55038..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/ipfwrdr.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $Id: ipfwrdr.h,v 1.6 2012/02/11 13:10:57 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009 Jardel Weyrich - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#ifndef IPFWRDR_H_INCLUDED -#define IPFWRDR_H_INCLUDED - -#include "../commonrdr.h" - -int add_redirect_rule2( - const char * ifname, /* src interface (external) */ - const char * rhost, /* remote host (ip) */ - unsigned short eport, /* src port (external) */ - const char * iaddr, /* dst address (internal) */ - unsigned short iport, /* dst port (internal) */ - int proto, - const char * desc, - unsigned int timestamp); - -int add_filter_rule2( - const char * ifname, - const char * rhost, - const char * iaddr, - unsigned short eport, - unsigned short iport, - int proto, - const char * desc); - -#if 0 - -/* - * get_redirect_rule() gets internal IP and port from - * interface, external port and protocl -*/ -int get_redirect_rule( - const char * ifname, - unsigned short eport, - int proto, - char * iaddr, - int iaddrlen, - unsigned short * iport, - char * desc, - int desclen, - u_int64_t * packets, - u_int64_t * bytes); - -int get_redirect_rule_by_index( - int index, - char * ifname, - unsigned short * eport, - char * iaddr, - int iaddrlen, - unsigned short * iport, - int * proto, - char * desc, - int desclen, - u_int64_t * packets, - u_int64_t * bytes); - -#endif - -/* - * delete_redirect_rule() -*/ -int delete_redirect_rule(const char * ifname, unsigned short eport, int proto); - -/* - * delete_filter_rule() -*/ -int delete_filter_rule(const char * ifname, unsigned short eport, int proto); - -int clear_redirect_rules(void); - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/ipfw/testipfwrdr.c b/src/contrib/miniupnp/miniupnpd/ipfw/testipfwrdr.c deleted file mode 100644 index d6791d2..0000000 --- a/src/contrib/miniupnp/miniupnpd/ipfw/testipfwrdr.c +++ /dev/null @@ -1,87 +0,0 @@ -/* $Id: testipfwrdr.c,v 1.7 2011/06/22 21:57:17 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009-2011 Jardel Weyrich, Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#include -#include -#include -#include -#include "ipfwrdr.h" - -// test program for ipfwrdr.c -static const char * ifname = "lo0"; - -static void -list_port_mappings(void) -{ - int i; - unsigned short eport; - char iaddr[16]; - unsigned short iport; - int proto; - char desc[64]; - char rhost[32]; - unsigned int timestamp; - u_int64_t packets, bytes; - - printf("== Port Mapping List ==\n"); - for(i = 0;; i++) { - iaddr[0] = '\0'; - desc[0] = '\0'; - eport = iport = 0; - timestamp = 0; - packets = bytes = 0; - proto = -1; - if(get_redirect_rule_by_index(i, 0/*ifname*/, &eport, iaddr, sizeof(iaddr), - &iport, &proto, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, &packets, &bytes) < 0) - break; - printf("%2d - %5hu=>%15s:%5hu %d '%s' '%s' %u %" PRIu64 " %" PRIu64 "\n", - i, eport, iaddr, iport, proto, desc, rhost, timestamp, - packets, bytes); - } - printf("== %d Port Mapping%s ==\n", i, (i > 1)?"s":""); -} - -int main(int argc, char * * argv) { - unsigned int timestamp; - char desc[64]; - char addr[16]; - char rhost[40]; - unsigned short iport = 0; - const char * in_rhost = "8.8.8.8"; - - desc[0] = '\0'; - addr[0] = '\0'; - openlog("testipfwrdrd", LOG_CONS | LOG_PERROR, LOG_USER); - if(init_redirect() < 0) { - fprintf(stderr, "init_redirect() failed.\n"); - return 1; - } - list_port_mappings(); - delete_redirect_rule(ifname, 2222, IPPROTO_TCP); - delete_redirect_rule(ifname, 2223, IPPROTO_TCP); - add_redirect_rule2(ifname, "", 2223, - "10.1.1.17", 4445, IPPROTO_TCP, - "test miniupnpd", time(NULL) + 60); - add_redirect_rule2(ifname, in_rhost, 2222, - "10.1.1.16", 4444, IPPROTO_TCP, - "test miniupnpd", time(NULL) + 60); - get_redirect_rule(ifname, 2222, IPPROTO_TCP, addr, sizeof(addr), &iport, - desc, sizeof(desc), rhost, sizeof(rhost), - ×tamp, NULL, NULL); - printf("'%s' %s:%hu '%s' %u\n", rhost, addr, iport, desc, timestamp); - list_port_mappings(); - delete_redirect_rule(ifname, 2222, IPPROTO_TCP); - delete_redirect_rule(ifname, 2223, IPPROTO_TCP); - list_port_mappings(); - shutdown_redirect(); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/linux/getifstats.c b/src/contrib/miniupnp/miniupnpd/linux/getifstats.c deleted file mode 100644 index 5a4386c..0000000 --- a/src/contrib/miniupnp/miniupnpd/linux/getifstats.c +++ /dev/null @@ -1,135 +0,0 @@ -/* $Id: getifstats.c,v 1.14 2018/03/13 23:05:21 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include - -#include "../config.h" -#include "../getifstats.h" - -#ifdef GET_WIRELESS_STATS -#include -#include -#include -#include -#endif /* GET_WIRELESS_STATS */ - -/* that is the answer */ -#define BAUDRATE_DEFAULT 4200000 - -int -getifstats(const char * ifname, struct ifdata * data) -{ - FILE *f; - char line[512]; - char * p; - int i; - int r = -1; - char fname[64]; -#ifdef ENABLE_GETIFSTATS_CACHING - static time_t cache_timestamp = 0; - static struct ifdata cache_data; - time_t current_time; -#endif /* ENABLE_GETIFSTATS_CACHING */ - if(!data) - return -1; - data->baudrate = BAUDRATE_DEFAULT; - data->opackets = 0; - data->ipackets = 0; - data->obytes = 0; - data->ibytes = 0; - if(!ifname || ifname[0]=='\0') - return -1; -#ifdef ENABLE_GETIFSTATS_CACHING - current_time = upnp_time(); - if(current_time == ((time_t)-1)) { - syslog(LOG_ERR, "getifstats() : time() error : %m"); - } else { - if(current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) { - /* return cached data */ - memcpy(data, &cache_data, sizeof(struct ifdata)); - return 0; - } - } -#endif /* ENABLE_GETIFSTATS_CACHING */ - f = fopen("/proc/net/dev", "r"); - if(!f) { - syslog(LOG_ERR, "getifstats() : cannot open /proc/net/dev : %m"); - return -1; - } - /* discard the two header lines */ - if(!fgets(line, sizeof(line), f) || !fgets(line, sizeof(line), f)) { - syslog(LOG_ERR, "getifstats() : error reading /proc/net/dev : %m"); - } - while(fgets(line, sizeof(line), f)) { - p = line; - while(*p==' ') p++; - i = 0; - while(ifname[i] == *p) { - p++; i++; - } - /* TODO : how to handle aliases ? */ - if(ifname[i] || *p != ':') - continue; - p++; - while(*p==' ') p++; - data->ibytes = strtoul(p, &p, 0); - while(*p==' ') p++; - data->ipackets = strtoul(p, &p, 0); - /* skip 6 columns */ - for(i=6; i>0 && *p!='\0'; i--) { - while(*p==' ') p++; - while(*p!=' ' && *p) p++; - } - while(*p==' ') p++; - data->obytes = strtoul(p, &p, 0); - while(*p==' ') p++; - data->opackets = strtoul(p, &p, 0); - r = 0; - break; - } - fclose(f); - /* get interface speed */ - snprintf(fname, sizeof(fname), "/sys/class/net/%s/speed", ifname); - f = fopen(fname, "r"); - if(f) { - if(fgets(line, sizeof(line), f)) { - i = atoi(line); /* 65535 means unknown */ - if(i > 0 && i < 65535) - data->baudrate = 1000000*i; - } - fclose(f); - } else { - syslog(LOG_INFO, "cannot read %s file : %m", fname); - } -#ifdef GET_WIRELESS_STATS - if(data->baudrate == BAUDRATE_DEFAULT) { - struct iwreq iwr; - int s; - s = socket(AF_INET, SOCK_DGRAM, 0); - if(s >= 0) { - strncpy(iwr.ifr_name, ifname, IFNAMSIZ); - if(ioctl(s, SIOCGIWRATE, &iwr) >= 0) { - data->baudrate = iwr.u.bitrate.value; - } - close(s); - } - } -#endif /* GET_WIRELESS_STATS */ -#ifdef ENABLE_GETIFSTATS_CACHING - if(r==0 && current_time!=((time_t)-1)) { - /* cache the new data */ - cache_timestamp = current_time; - memcpy(&cache_data, data, sizeof(struct ifdata)); - } -#endif /* ENABLE_GETIFSTATS_CACHING */ - return r; -} - diff --git a/src/contrib/miniupnp/miniupnpd/linux/getroute.c b/src/contrib/miniupnp/miniupnpd/linux/getroute.c deleted file mode 100644 index f9afea7..0000000 --- a/src/contrib/miniupnp/miniupnpd/linux/getroute.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: getroute.c,v 1.4 2013/02/06 10:50:04 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ -#include -#include -#ifdef USE_LIBNFNETLINK -/* define USE_LIBNFNETLINK in order to use libnfnetlink - * instead of custom code - * see https://github.com/miniupnp/miniupnp/issues/110 */ -#include -#endif /* USE_LIBNFNETLINK */ - -#include "../getroute.h" -#include "../upnputils.h" - -int -get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len, - int * index) -{ - int fd = -1; - struct nlmsghdr *h; - int status; - struct { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - struct sockaddr_nl nladdr; - struct iovec iov = { - .iov_base = (void*) &req.n, - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - const struct sockaddr_in * dst4; - const struct sockaddr_in6 * dst6; -#ifndef USE_LIBNFNETLINK - struct rtattr * rta; -#endif /* USE_LIBNFNETLINK */ - - memset(&req, 0, sizeof(req)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_GETROUTE; - req.r.rtm_family = dst->sa_family; - req.r.rtm_table = 0; - req.r.rtm_protocol = 0; - req.r.rtm_scope = 0; - req.r.rtm_type = 0; - req.r.rtm_src_len = 0; - req.r.rtm_dst_len = 0; - req.r.rtm_tos = 0; - - { - char dst_str[128]; - sockaddr_to_string(dst, dst_str, sizeof(dst_str)); - syslog(LOG_DEBUG, "get_src_for_route_to (%s)", dst_str); - } - /* add address */ -#ifndef USE_LIBNFNETLINK - rta = (struct rtattr *)(((char*)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); - rta->rta_type = RTA_DST; -#endif /* USE_LIBNFNETLINK */ - if(dst->sa_family == AF_INET) { - dst4 = (const struct sockaddr_in *)dst; -#ifdef USE_LIBNFNETLINK - nfnl_addattr_l(&req.n, sizeof(req), RTA_DST, &dst4->sin_addr, 4); -#else - rta->rta_len = RTA_SPACE(sizeof(dst4->sin_addr)); - memcpy(RTA_DATA(rta), &dst4->sin_addr, sizeof(dst4->sin_addr)); -#endif /* USE_LIBNFNETLINK */ - req.r.rtm_dst_len = 32; - } else { - dst6 = (const struct sockaddr_in6 *)dst; -#ifdef USE_LIBNFNETLINK - nfnl_addattr_l(&req.n, sizeof(req), RTA_DST, &dst6->sin6_addr, 16); -#else - rta->rta_len = RTA_SPACE(sizeof(dst6->sin6_addr)); - memcpy(RTA_DATA(rta), &dst6->sin6_addr, sizeof(dst6->sin6_addr)); -#endif /* USE_LIBNFNETLINK */ - req.r.rtm_dst_len = 128; - } -#ifndef USE_LIBNFNETLINK - req.n.nlmsg_len += rta->rta_len; -#endif /* USE_LIBNFNETLINK */ - - fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (fd < 0) { - syslog(LOG_ERR, "socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) : %m"); - return -1; - } - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - req.n.nlmsg_seq = 1; - iov.iov_len = req.n.nlmsg_len; - - status = sendmsg(fd, &msg, 0); - - if (status < 0) { - syslog(LOG_ERR, "sendmsg(rtnetlink) : %m"); - goto error; - } - - memset(&req, 0, sizeof(req)); - - for(;;) { - iov.iov_len = sizeof(req); - status = recvmsg(fd, &msg, 0); - if(status < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - syslog(LOG_ERR, "recvmsg(rtnetlink) %m"); - goto error; - } - if(status == 0) { - syslog(LOG_ERR, "recvmsg(rtnetlink) EOF"); - goto error; - } - for (h = (struct nlmsghdr*)&req.n; status >= (int)sizeof(*h); ) { - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - syslog(LOG_ERR, "Truncated message"); - } - syslog(LOG_ERR, "malformed message: len=%d", len); - goto error; - } - - if(nladdr.nl_pid != 0 || h->nlmsg_seq != 1/*seq*/) { - syslog(LOG_ERR, "wrong seq = %d\n", h->nlmsg_seq); - /* Don't forget to skip that message. */ - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - continue; - } - - if(h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - syslog(LOG_ERR, "NLMSG_ERROR %d : %s", err->error, strerror(-err->error)); - goto error; - } - if(h->nlmsg_type == RTM_NEWROUTE) { - struct rtattr * rta; - int len = h->nlmsg_len; - len -= NLMSG_LENGTH(sizeof(struct rtmsg)); - for(rta = RTM_RTA(NLMSG_DATA((h))); RTA_OK(rta, len); rta = RTA_NEXT(rta,len)) { - unsigned char * data = RTA_DATA(rta); - if(rta->rta_type == RTA_PREFSRC) { - if(src_len && src) { - if(*src_len < RTA_PAYLOAD(rta)) { - syslog(LOG_WARNING, "cannot copy src: %u<%lu", - (unsigned)*src_len, (unsigned long)RTA_PAYLOAD(rta)); - goto error; - } - *src_len = RTA_PAYLOAD(rta); - memcpy(src, data, RTA_PAYLOAD(rta)); - } - } else if(rta->rta_type == RTA_OIF) { - if(index) - memcpy(index, data, sizeof(int)); - } - } - close(fd); - return 0; - } - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - } - syslog(LOG_WARNING, "get_src_for_route_to() : src not found"); -error: - if(fd >= 0) - close(fd); - return -1; -} - diff --git a/src/contrib/miniupnp/miniupnpd/linux/ifacewatcher.c b/src/contrib/miniupnp/miniupnpd/linux/ifacewatcher.c deleted file mode 100644 index 7095a0f..0000000 --- a/src/contrib/miniupnp/miniupnpd/linux/ifacewatcher.c +++ /dev/null @@ -1,350 +0,0 @@ -/* $Id: ifacewatcher.c,v 1.9 2018/02/03 22:05:42 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * - * ifacewatcher.c - * - * This file implements dynamic serving of new network interfaces - * which weren't available during daemon start. It also takes care - * of interfaces which become unavailable. - * - * Copyright (c) 2011, Alexey Osipov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../config.h" - -#ifdef USE_IFACEWATCHER - -#include "../ifacewatcher.h" -#include "../minissdp.h" -#include "../getifaddr.h" -#include "../upnpglobalvars.h" -#include "../natpmp.h" - -extern volatile sig_atomic_t should_send_public_address_change_notif; - - -int -OpenAndConfInterfaceWatchSocket(void) -{ - int s; - struct sockaddr_nl addr; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s == -1) - { - syslog(LOG_ERR, "socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE): %m"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR; - /*addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;*/ - - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - syslog(LOG_ERR, "bind(netlink): %m"); - close(s); - return -1; - } - - return s; -} - -#if 0 -/* disabled at the moment */ -int -ProcessInterfaceUp(struct ifinfomsg *ifi) -{ - struct lan_iface_s * lan_iface; - struct lan_iface_s * lan_iface2; - struct lan_addr_s * lan_addr; - char ifname[IFNAMSIZ]; - char ifstraddr[16]; - struct in_addr ifaddr; - - /* check if we already have this iface */ - for(lan_iface = lan_ifaces.lh_first; lan_iface != NULL; lan_iface = lan_iface->list.le_next) - if (lan_iface->iface.index == ifi->ifi_index) - break; - - if (lan_iface != NULL) - return 0; - - if (if_indextoname(ifi->ifi_index, ifname) == NULL) - { - syslog(LOG_ERR, "if_indextoname(%d, ifname) failed", ifi->ifi_index); - return -1; - } - - if (getifaddr(ifname, ifstraddr, 16) < 0) - { - syslog(LOG_DEBUG, "getifaddr(%s, ifaddr, 16) failed", ifname); - return 1; - } - - if (inet_pton(AF_INET, ifstraddr, &ifaddr) != 1) - { - syslog(LOG_ERR, "inet_pton(AF_INET, \"%s\", &ifaddr) failed", ifstraddr); - return -1; - } - - /* check if this new interface has address which we need to listen to */ - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - { - if (lan_addr->addr.s_addr != ifaddr.s_addr) - continue; - - syslog(LOG_INFO, "Interface up: %s (%s)", ifname, ifstraddr); - - /* adding new lan_iface entry */ - lan_iface = (struct lan_iface_s *) malloc(sizeof(struct lan_iface_s)); - if (lan_iface == NULL) - { - syslog(LOG_ERR, "malloc(sizeof(struct lan_iface_s): %m"); - continue; - } - - lan_iface->lan_addr = lan_addr; - strncpy(lan_iface->iface.name, ifname, IFNAMSIZ); - lan_iface->iface.index = ifi->ifi_index; - lan_iface->iface.addr = ifaddr; - lan_iface->snotify = -1; -#ifdef ENABLE_NATPMP - lan_iface->snatpmp = -1; -#endif - - LIST_INSERT_HEAD(&lan_ifaces, lan_iface, list); - - /* adding multicast membership for SSDP */ - if(AddMulticastMembership(sudp, ifaddr.s_addr, ifi->ifi_index) < 0) - syslog(LOG_WARNING, "Failed to add multicast membership for interface %s (%s)", ifname, ifstraddr); - else - syslog(LOG_INFO, "Multicast membership added for %s (%s)", ifname, ifstraddr); - - /* create SSDP notify socket */ - if (OpenAndConfSSDPNotifySocket(lan_iface) < 0) - syslog(LOG_WARNING, "Failed to open SSDP notify socket for interface %s (%s)", ifname, ifstraddr); - -#ifdef ENABLE_NATPMP - /* create NAT-PMP socket */ - for(lan_iface2 = lan_ifaces.lh_first; lan_iface2 != NULL; lan_iface2 = lan_iface2->list.le_next) - if (lan_iface2->lan_addr->addr.s_addr == lan_iface->lan_addr->addr.s_addr && - lan_iface2->snatpmp >= 0) - lan_iface->snatpmp = lan_iface2->snatpmp; - - if (lan_iface->snatpmp < 0) - { - lan_iface->snatpmp = OpenAndConfNATPMPSocket(ifaddr.s_addr); - if (lan_iface->snatpmp < 0) - syslog(LOG_ERR, "OpenAndConfNATPMPSocket(ifaddr.s_addr) failed for %s (%s)", ifname, ifstraddr); - else - syslog(LOG_INFO, "Listening for NAT-PMP connection on %s:%d", ifstraddr, NATPMP_PORT); - } -#endif - } - - return 0; -} - -int -ProcessInterfaceDown(struct ifinfomsg *ifi) -{ - struct lan_iface_s * lan_iface; - struct lan_iface_s * lan_iface2; - - /* check if we have this iface */ - for(lan_iface = lan_ifaces.lh_first; lan_iface != NULL; lan_iface = lan_iface->list.le_next) - if (lan_iface->iface.index == ifi->ifi_index) - break; - - if (lan_iface == NULL) - return 0; - - /* one of our interfaces is going down, clean up */ - syslog(LOG_INFO, "Interface down: %s", lan_iface->iface.name); - - /* remove multicast membership for SSDP */ - if(DropMulticastMembership(sudp, lan_iface->lan_addr->addr.s_addr, lan_iface->iface.index) < 0) - syslog(LOG_WARNING, "Failed to drop multicast membership for interface %s (%s)", lan_iface->iface.name, lan_iface->lan_addr->str); - else - syslog(LOG_INFO, "Multicast membership dropped for %s (%s)", lan_iface->iface.name, lan_iface->lan_addr->str); - - /* closing SSDP notify socket */ - close(lan_iface->snotify); - -#ifdef ENABLE_NATPMP - /* closing NAT-PMP socket if it's not used anymore */ - for(lan_iface2 = lan_ifaces.lh_first; lan_iface2 != NULL; lan_iface2 = lan_iface2->list.le_next) - if (lan_iface2 != lan_iface && lan_iface2->snatpmp == lan_iface->snatpmp) - break; - - if (lan_iface2 == NULL) - close(lan_iface->snatpmp); -#endif - - /* del corresponding lan_iface entry */ - LIST_REMOVE(lan_iface, list); - free(lan_iface); - - return 0; -} -#endif - -void -ProcessInterfaceWatchNotify(int s) -{ - char buffer[4096]; - struct iovec iov; - struct msghdr hdr; - struct nlmsghdr *nlhdr; -#if 0 -/* disabled at the moment */ - struct ifinfomsg *ifi; -#endif - struct ifaddrmsg *ifa; - int len; - - struct rtattr *rth; - int rtl; - - unsigned int ext_if_name_index = 0; - - iov.iov_base = buffer; - iov.iov_len = sizeof(buffer); - - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - - len = recvmsg(s, &hdr, 0); - if (len < 0) - { - syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m"); - return; - } - - if(ext_if_name) { - ext_if_name_index = if_nametoindex(ext_if_name); - } - - for (nlhdr = (struct nlmsghdr *) buffer; - NLMSG_OK (nlhdr, (unsigned int)len); - nlhdr = NLMSG_NEXT (nlhdr, len)) - { - int is_del = 0; - char address[48]; - char ifname[IFNAMSIZ]; - address[0] = '\0'; - ifname[0] = '\0'; - if (nlhdr->nlmsg_type == NLMSG_DONE) - break; - switch(nlhdr->nlmsg_type) { - case RTM_DELLINK: - is_del = 1; - case RTM_NEWLINK: -#if 0 -/* disabled at the moment */ - ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr); - if(is_del) { - if(ProcessInterfaceDown(ifi) < 0) - syslog(LOG_ERR, "ProcessInterfaceDown(ifi) failed"); - } else { - if(ProcessInterfaceUp(ifi) < 0) - syslog(LOG_ERR, "ProcessInterfaceUp(ifi) failed"); - } -#endif - break; - case RTM_DELADDR: - is_del = 1; - case RTM_NEWADDR: - /* see /usr/include/linux/netlink.h - * and /usr/include/linux/rtnetlink.h */ - ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr); - syslog(LOG_DEBUG, "%s %s index=%d fam=%d", "ProcessInterfaceWatchNotify", - is_del ? "RTM_DELADDR" : "RTM_NEWADDR", - ifa->ifa_index, ifa->ifa_family); - for(rth = IFA_RTA(ifa), rtl = IFA_PAYLOAD(nlhdr); - rtl && RTA_OK(rth, rtl); - rth = RTA_NEXT(rth, rtl)) { - char tmp[128]; - memset(tmp, 0, sizeof(tmp)); - switch(rth->rta_type) { - case IFA_ADDRESS: - case IFA_LOCAL: - case IFA_BROADCAST: - case IFA_ANYCAST: - inet_ntop(ifa->ifa_family, RTA_DATA(rth), tmp, sizeof(tmp)); - if(rth->rta_type == IFA_ADDRESS) - strncpy(address, tmp, sizeof(address)); - break; - case IFA_LABEL: - strncpy(tmp, RTA_DATA(rth), sizeof(tmp)); - strncpy(ifname, tmp, sizeof(ifname)); - break; - case IFA_CACHEINFO: - { - struct ifa_cacheinfo *cache_info; - cache_info = RTA_DATA(rth); - snprintf(tmp, sizeof(tmp), "valid=%u preferred=%u", - cache_info->ifa_valid, cache_info->ifa_prefered); - } - break; - default: - strncpy(tmp, "*unknown*", sizeof(tmp)); - } - syslog(LOG_DEBUG, " - %u - %s type=%d", - ifa->ifa_index, tmp, - rth->rta_type); - } - if(ifa->ifa_index == ext_if_name_index) { - should_send_public_address_change_notif = 1; - } - break; - default: - syslog(LOG_DEBUG, "%s type %d ignored", - "ProcessInterfaceWatchNotify", nlhdr->nlmsg_type); - } - } - -} - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/linux/miniupnpd.init.d.script b/src/contrib/miniupnp/miniupnpd/linux/miniupnpd.init.d.script deleted file mode 100644 index f4ea7e3..0000000 --- a/src/contrib/miniupnp/miniupnpd/linux/miniupnpd.init.d.script +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -# $Id: miniupnpd.init.d.script,v 1.2 2007/09/23 16:11:12 nanard Exp $ -# MiniUPnP project -# author: Thomas Bernard -# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - -### BEGIN INIT INFO -# Provides: miniupnpd -# Required-Start: $remote_fs $syslog -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: MiniUPnPd port-forwarding daemon -### END INIT INFO - -set -e - -MINIUPNPD=/usr/sbin/miniupnpd -ARGS='-f /etc/miniupnpd/miniupnpd.conf' - -IPTABLES_CREATE=/etc/miniupnpd/iptables_init.sh -IPTABLES_REMOVE=/etc/miniupnpd/iptables_removeall.sh - -test -f $MINIUPNPD || exit 0 - -. /lib/lsb/init-functions - -case "$1" in - start) - log_daemon_msg "Starting miniupnpd" "miniupnpd" - $IPTABLES_CREATE > /dev/null 2>&1 - start-stop-daemon --start --quiet --pidfile /var/run/miniupnpd.pid --startas $MINIUPNPD -- $ARGS $LSBNAMES - log_end_msg $? - ;; - stop) - log_daemon_msg "Stopping miniupnpd" "miniupnpd" - start-stop-daemon --stop --quiet --pidfile /var/run/miniupnpd.pid - log_end_msg $? - $IPTABLES_REMOVE > /dev/null 2>&1 - ;; - restart|reload|force-reload) - log_daemon_msg "Restarting miniupnpd" "miniupnpd" - start-stop-daemon --stop --retry 5 --quiet --pidfile /var/run/miniupnpd.pid - $IPTABLES_REMOVE > /dev/null 2>&1 - $IPTABLES_CREATE > /dev/null 2>&1 - start-stop-daemon --start --quiet --pidfile /var/run/miniupnpd.pid --startas $MINIUPNPD -- $ARGS $LSBNAMES - log_end_msg $? - ;; - status) - status_of_proc /usr/sbin/miniupnpd miniupnpd - ;; - *) - log_action_msg "Usage: /etc/init.d/miniupnpd {start|stop|restart|reload|force-reload}" - exit 2 - ;; -esac -exit 0 diff --git a/src/contrib/miniupnp/miniupnpd/mac/Makefile b/src/contrib/miniupnp/miniupnpd/mac/Makefile deleted file mode 100644 index 968562f..0000000 --- a/src/contrib/miniupnp/miniupnpd/mac/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $Id: Makefile,v 1.2 2011/02/20 23:43:41 nanard Exp $ -# made for GNU Make -CFLAGS = -Wall -g -EXECUTABLES = testgetifstats - -all: $(EXECUTABLES) - -clean: - rm -f *.o $(EXECUTABLES) - -testmacrdr.o: testmacrdr.c macrdr.h - -testgetifstats: testgetifstats.o getifstats.o - diff --git a/src/contrib/miniupnp/miniupnpd/mac/getifstats.c b/src/contrib/miniupnp/miniupnpd/mac/getifstats.c deleted file mode 100644 index 83ab7f8..0000000 --- a/src/contrib/miniupnp/miniupnpd/mac/getifstats.c +++ /dev/null @@ -1,94 +0,0 @@ -/* $Id: getifstats.c,v 1.8 2018/03/13 23:05:21 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009 Jardel Weyrich - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../getifstats.h" -#include "../config.h" - -int getifstats(const char * ifname, struct ifdata * data) { - int mib[] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, if_nametoindex(ifname) }; - const size_t mib_len = sizeof(mib) / sizeof(mib[0]); - size_t needed; - char *buf, *end, *p; - struct if_msghdr *ifm; - struct if_data ifdata; -#ifdef ENABLE_GETIFSTATS_CACHING - static time_t cache_timestamp = 0; - static struct ifdata cache_data; - time_t current_time; -#endif - - if (data == NULL || ifname == NULL || ifname[0] == '\0') - return -1; /* error */ - - data->baudrate = 4200000; - data->opackets = 0; - data->ipackets = 0; - data->obytes = 0; - data->ibytes = 0; - -#ifdef ENABLE_GETIFSTATS_CACHING - current_time = upnp_time(); - if (current_time == ((time_t)-1)) { - syslog(LOG_ERR, "getifstats() : time() error : %m"); - } else { - if (current_time < cache_timestamp + GETIFSTATS_CACHING_DURATION) { - memcpy(data, &cache_data, sizeof(struct ifdata)); - return 0; - } - } -#endif - - if (sysctl(mib, mib_len, NULL, &needed, NULL, 0) == -1) { - syslog(LOG_ERR, "sysctl(): %m"); - return -1; - } - buf = (char *) malloc(needed); - if (buf == NULL) - return -1; /* error */ - if (sysctl(mib, mib_len, buf, &needed, NULL, 0) == -1) { - syslog(LOG_ERR, "sysctl(): %m"); - free(buf); - return -1; /* error */ - } else { - for (end = buf + needed, p = buf; p < end; p += ifm->ifm_msglen) { - ifm = (struct if_msghdr *) p; - if (ifm->ifm_type == RTM_IFINFO && ifm->ifm_data.ifi_type == IFT_ETHER) { - ifdata = ifm->ifm_data; - data->opackets = ifdata.ifi_opackets; - data->ipackets = ifdata.ifi_ipackets; - data->obytes = ifdata.ifi_obytes; - data->ibytes = ifdata.ifi_ibytes; - data->baudrate = ifdata.ifi_baudrate; - free(buf); -#ifdef ENABLE_GETIFSTATS_CACHING - if (current_time!=((time_t)-1)) { - cache_timestamp = current_time; - memcpy(&cache_data, data, sizeof(struct ifdata)); - } -#endif - return 0; /* found, ok */ - } - } - } - free(buf); - return -1; /* not found or error */ -} - diff --git a/src/contrib/miniupnp/miniupnpd/mac/org.tuxfamily.miniupnpd.plist.before b/src/contrib/miniupnp/miniupnpd/mac/org.tuxfamily.miniupnpd.plist.before deleted file mode 100644 index ed6e81f..0000000 --- a/src/contrib/miniupnp/miniupnpd/mac/org.tuxfamily.miniupnpd.plist.before +++ /dev/null @@ -1,16 +0,0 @@ - - - - - miniupnpd - org.tuxfamily.miniupnpd - ProgramArguments - - INSTALLPREFIX/sbin/miniupnpd - -f INSTALLPREFIX/etc/miniupnpd/miniupnpd.conf - - RunAtLoad - - - diff --git a/src/contrib/miniupnp/miniupnpd/mac/testgetifstats.c b/src/contrib/miniupnp/miniupnpd/mac/testgetifstats.c deleted file mode 100644 index 8e23f95..0000000 --- a/src/contrib/miniupnp/miniupnpd/mac/testgetifstats.c +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id: testgetifstats.c,v 1.3 2011/02/20 23:43:41 nanard Exp $ */ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2009 Jardel Weyrich - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution - */ - -#include -#include "../getifstats.h" - -int main(int argc, char * * argv) { - int r; - struct ifdata data; - printf("usage: %s if_name\n", argv[0]); - if (argc < 2) - return -1; - r = getifstats(argv[1], &data); - if (r < 0) - printf("getifstats() failed\n"); - else { - printf("ipackets = %10lu opackets = %10lu\n", data.ipackets, data.opackets); - printf("ibytes = %10lu obytes = %10lu\n", data.ibytes, data.obytes); - printf("baudrate = %10lu\n", data.baudrate); - } - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/macros.h b/src/contrib/miniupnp/miniupnpd/macros.h deleted file mode 100644 index f1d93f6..0000000 --- a/src/contrib/miniupnp/miniupnpd/macros.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $Id: macros.h,v 1.1 2012/04/30 20:37:56 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef MACROS_H_INCLUDED -#define MACROS_H_INCLUDED - -#define UNUSED(arg) (void)(arg) - -#include - -#ifndef INLINE -#define INLINE static inline -#endif -/* theses macros are designed to read/write unsigned short/long int - * from an unsigned char array in network order (big endian). - * Avoid pointer casting, so avoid accessing unaligned memory, which - * can crash with some cpu's */ -INLINE uint32_t readnu32(const uint8_t * p) -{ - return (p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]); -} -#define READNU32(p) readnu32(p) -INLINE uint16_t readnu16(const uint8_t * p) -{ - return (p[0] << 8 | p[1]); -} -#define READNU16(p) readnu16(p) -INLINE void writenu32(uint8_t * p, uint32_t n) -{ - p[0] = (n & 0xff000000) >> 24; - p[1] = (n & 0xff0000) >> 16; - p[2] = (n & 0xff00) >> 8; - p[3] = n & 0xff; -} -#define WRITENU32(p, n) writenu32(p, n) -INLINE void writenu16(uint8_t * p, uint16_t n) -{ - p[0] = (n & 0xff00) >> 8; - p[1] = n & 0xff; -} -#define WRITENU16(p, n) writenu16(p, n) - -#endif /* MACROS_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/minissdp.c b/src/contrib/miniupnp/miniupnpd/minissdp.c deleted file mode 100644 index d345d64..0000000 --- a/src/contrib/miniupnp/miniupnpd/minissdp.c +++ /dev/null @@ -1,1566 +0,0 @@ -/* $Id: minissdp.c,v 1.92 2018/03/13 10:52:39 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef IP_RECVIF -#include -#include -#include -#include -#endif - -#include "config.h" -#if defined(ENABLE_IPV6) && defined(UPNP_STRICT) -#include -#endif /* defined(ENABLE_IPV6) && defined(UPNP_STRICT) */ - -#include "upnpdescstrings.h" -#include "miniupnpdpath.h" -#include "upnphttp.h" -#include "upnpglobalvars.h" -#include "minissdp.h" -#include "upnputils.h" -#include "getroute.h" -#include "asyncsendto.h" -#include "codelength.h" -#include "macros.h" - -#ifndef MIN -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif /* MIN */ - -/* SSDP ip/port */ -#define SSDP_PORT (1900) -#define SSDP_MCAST_ADDR ("239.255.255.250") -#define LL_SSDP_MCAST_ADDR "FF02::C" -#define SL_SSDP_MCAST_ADDR "FF05::C" -#define GL_SSDP_MCAST_ADDR "FF0E::C" - -/* AddMulticastMembership() - * param s socket - * param lan_addr lan address - */ -static int -AddMulticastMembership(int s, struct lan_addr_s * lan_addr) -{ -#ifndef HAVE_IP_MREQN - /* The ip_mreqn structure appeared in Linux 2.4. */ - struct ip_mreq imr; /* Ip multicast membership */ -#else /* HAVE_IP_MREQN */ - struct ip_mreqn imr; /* Ip multicast membership */ -#endif /* HAVE_IP_MREQN */ - - /* setting up imr structure */ - imr.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDR); - /*imr.imr_interface.s_addr = htonl(INADDR_ANY);*/ -#ifndef HAVE_IP_MREQN - imr.imr_interface.s_addr = lan_addr->addr.s_addr; -#else /* HAVE_IP_MREQN */ - imr.imr_address.s_addr = lan_addr->addr.s_addr; -#ifndef MULTIPLE_EXTERNAL_IP -#ifdef ENABLE_IPV6 - imr.imr_ifindex = lan_addr->index; -#else /* ENABLE_IPV6 */ - imr.imr_ifindex = if_nametoindex(lan_addr->ifname); -#endif /* ENABLE_IPV6 */ -#else /* MULTIPLE_EXTERNAL_IP */ - imr.imr_ifindex = 0; -#endif /* MULTIPLE_EXTERNAL_IP */ -#endif /* HAVE_IP_MREQN */ - -#ifndef HAVE_IP_MREQN - if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreq)) < 0) -#else /* HAVE_IP_MREQN */ - if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreqn)) < 0) -#endif /* HAVE_IP_MREQN */ - { - syslog(LOG_ERR, "setsockopt(udp, IP_ADD_MEMBERSHIP): %m"); - return -1; - } - - return 0; -} - -/* AddMulticastMembershipIPv6() - * param s socket (IPv6) - * param ifindex : interface index (0 : All interfaces) */ -#ifdef ENABLE_IPV6 -static int -AddMulticastMembershipIPv6(int s, unsigned int ifindex) -{ - struct ipv6_mreq mr; - - memset(&mr, 0, sizeof(mr)); - mr.ipv6mr_interface = ifindex; /* 0 : all interfaces */ -#ifndef IPV6_ADD_MEMBERSHIP -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif - inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr); - if(setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(struct ipv6_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, IPV6_ADD_MEMBERSHIP): %m"); - return -1; - } - inet_pton(AF_INET6, SL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr); - if(setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(struct ipv6_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, IPV6_ADD_MEMBERSHIP): %m"); - return -1; - } - inet_pton(AF_INET6, GL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr); - if(setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(struct ipv6_mreq)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp, IPV6_ADD_MEMBERSHIP): %m"); - return -1; - } - return 0; -} -#endif - - -#if defined(ENABLE_IPV6) && defined(UPNP_STRICT) -static int get_link_local_addr(unsigned scope_id, struct in6_addr * addr6) -{ - struct ifaddrs * ifap; - struct ifaddrs * ife; - if(getifaddrs(&ifap)<0) { - syslog(LOG_ERR, "getifaddrs: %m"); - return -1; - } - for(ife = ifap; ife != NULL; ife = ife->ifa_next) { - if(ife->ifa_addr == NULL) continue; - if(ife->ifa_addr->sa_family != AF_INET6) continue; - if(!IN6_IS_ADDR_LINKLOCAL(&(((const struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr))) continue; - if(scope_id != if_nametoindex(ife->ifa_name)) continue; - memcpy(addr6, &(((const struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr), sizeof(struct in6_addr)); - break; - } - freeifaddrs(ifap); - return 0; -} -#endif /* defined(ENABLE_IPV6) && defined(UPNP_STRICT) */ - -/* Open and configure the socket listening for - * SSDP udp packets sent on 239.255.255.250 port 1900 - * SSDP v6 udp packets sent on FF02::C, or FF05::C, port 1900 */ -int -OpenAndConfSSDPReceiveSocket(int ipv6) -{ - int s; - struct sockaddr_storage sockname; - socklen_t sockname_len; - struct lan_addr_s * lan_addr; - const int on = 1; - - if( (s = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0)) < 0) - { - syslog(LOG_ERR, "%s: socket(udp): %m", - "OpenAndConfSSDPReceiveSocket"); - return -1; - } - - memset(&sockname, 0, sizeof(struct sockaddr_storage)); -#ifdef ENABLE_IPV6 - if(ipv6) - { - struct sockaddr_in6 * saddr = (struct sockaddr_in6 *)&sockname; - saddr->sin6_family = AF_INET6; - saddr->sin6_port = htons(SSDP_PORT); - saddr->sin6_addr = ipv6_bind_addr; - sockname_len = sizeof(struct sockaddr_in6); - } - else -#endif /* ENABLE_IPV6 */ - { - struct sockaddr_in * saddr = (struct sockaddr_in *)&sockname; - saddr->sin_family = AF_INET; - saddr->sin_port = htons(SSDP_PORT); - /* NOTE : it seems it doesn't work when binding on the specific address */ - /*saddr->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/ - saddr->sin_addr.s_addr = htonl(INADDR_ANY); - /*saddr->sin_addr.s_addr = inet_addr(ifaddr);*/ - sockname_len = sizeof(struct sockaddr_in); - } - - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) - { - syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m"); - } -#ifdef IP_RECVIF - /* BSD */ - if(!ipv6) { - if(setsockopt(s, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0) - { - syslog(LOG_WARNING, "setsockopt(udp, IP_RECVIF): %m"); - } - } -#endif /* IP_RECVIF */ -#ifdef IP_PKTINFO - /* Linux */ - if(!ipv6) { - if(setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0) - { - syslog(LOG_WARNING, "setsockopt(udp, IP_PKTINFO): %m"); - } - } -#endif /* IP_PKTINFO */ -#if defined(ENABLE_IPV6) && defined(IPV6_RECVPKTINFO) - if(ipv6) { - if(setsockopt(s, IPPROTO_IP, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) - { - syslog(LOG_WARNING, "setsockopt(udp, IPV6_RECVPKTINFO): %m"); - } - } -#endif /* defined(ENABLE_IPV6) && defined(IPV6_RECVPKTINFO) */ - - if(!set_non_blocking(s)) - { - syslog(LOG_WARNING, "%s: set_non_blocking(): %m", - "OpenAndConfSSDPReceiveSocket"); - } - -#if defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) - /* One and only one LAN interface */ - if(lan_addrs.lh_first != NULL && lan_addrs.lh_first->list.le_next == NULL - && lan_addrs.lh_first->ifname[0] != '\0') - { - if(setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, - lan_addrs.lh_first->ifname, - strlen(lan_addrs.lh_first->ifname)) < 0) - syslog(LOG_WARNING, "%s: setsockopt(udp%s, SO_BINDTODEVICE, %s): %m", - "OpenAndConfSSDPReceiveSocket", ipv6 ? "6" : "", - lan_addrs.lh_first->ifname); - } -#endif /* defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) */ - - if(bind(s, (struct sockaddr *)&sockname, sockname_len) < 0) - { - syslog(LOG_ERR, "%s: bind(udp%s): %m", - "OpenAndConfSSDPReceiveSocket", ipv6 ? "6" : ""); - close(s); - return -1; - } - -#ifdef ENABLE_IPV6 - if(ipv6) - { - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - { - if(AddMulticastMembershipIPv6(s, lan_addr->index) < 0) - { - syslog(LOG_WARNING, - "Failed to add IPv6 multicast membership for interface %s", - strlen(lan_addr->str) ? lan_addr->str : "NULL"); - } - } - } - else -#endif - { - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - { - if(AddMulticastMembership(s, lan_addr) < 0) - { - syslog(LOG_WARNING, - "Failed to add multicast membership for interface %s", - strlen(lan_addr->str) ? lan_addr->str : "NULL"); - } - } - } - - return s; -} - -/* open the UDP socket used to send SSDP notifications to - * the multicast group reserved for them */ -static int -OpenAndConfSSDPNotifySocket(in_addr_t addr) -{ - int s; - unsigned char loopchar = 0; - int bcast = 1; - unsigned char ttl = 2; /* UDA v1.1 says : - The TTL for the IP packet SHOULD default to 2 and - SHOULD be configurable. */ - /* TODO: Make TTL be configurable */ - struct in_addr mc_if; - struct sockaddr_in sockname; - - if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) - { - syslog(LOG_ERR, "socket(udp_notify): %m"); - return -1; - } - - mc_if.s_addr = addr; /*inet_addr(addr);*/ - - if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %m"); - close(s); - return -1; - } - - if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_IF): %m"); - close(s); - return -1; - } - - if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) - { - syslog(LOG_WARNING, "setsockopt(udp_notify, IP_MULTICAST_TTL,): %m"); - } - - if(setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify, SO_BROADCAST): %m"); - close(s); - return -1; - } - - /* bind() socket before using sendto() is not mandatory - * (sendto() will implicitly bind the socket when called on - * an unbound socket) - * here it is used to se a specific sending address */ - memset(&sockname, 0, sizeof(struct sockaddr_in)); - sockname.sin_family = AF_INET; - sockname.sin_addr.s_addr = addr; /*inet_addr(addr);*/ - - if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0) - { - syslog(LOG_ERR, "bind(udp_notify): %m"); - close(s); - return -1; - } - - return s; -} - -#ifdef ENABLE_IPV6 -/* open the UDP socket used to send SSDP notifications to - * the multicast group reserved for them. IPv6 */ -static int -OpenAndConfSSDPNotifySocketIPv6(unsigned int if_index) -{ - int s; - unsigned int loop = 0; - /* UDA 2.0 : The hop limit of each IP packet for a Site-Local scope - * multicast message SHALL be configurable and SHOULD default to 10 */ - int hop_limit = 10; - struct sockaddr_in6 sockname; - - s = socket(PF_INET6, SOCK_DGRAM, 0); - if(s < 0) - { - syslog(LOG_ERR, "socket(udp_notify IPv6): %m"); - return -1; - } - if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify IPv6, IPV6_MULTICAST_IF, %u): %m", if_index); - close(s); - return -1; - } - if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify, IPV6_MULTICAST_LOOP): %m"); - close(s); - return -1; - } - if(setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hop_limit, sizeof(hop_limit)) < 0) - { - syslog(LOG_ERR, "setsockopt(udp_notify, IPV6_MULTICAST_HOPS): %m"); - close(s); - return -1; - } - - /* bind() socket before using sendto() is not mandatory - * (sendto() will implicitly bind the socket when called on - * an unbound socket) - * but explicit bind permits to set port/scope_id/etc. */ - memset(&sockname, 0, sizeof(sockname)); - sockname.sin6_family = AF_INET6; - sockname.sin6_addr = in6addr_any; - /*sockname.sin6_port = htons(port);*/ - /*sockname.sin6_scope_id = if_index;*/ - if(bind(s, (struct sockaddr *)&sockname, sizeof(sockname)) < 0) - { - syslog(LOG_ERR, "bind(udp_notify IPv6): %m"); - close(s); - return -1; - } - - return s; -} -#endif - -int -OpenAndConfSSDPNotifySockets(int * sockets) -/*OpenAndConfSSDPNotifySockets(int * sockets, - struct lan_addr_s * lan_addr, int n_lan_addr)*/ -{ - int i; - struct lan_addr_s * lan_addr; - - for(i=0, lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - sockets[i] = OpenAndConfSSDPNotifySocket(lan_addr->addr.s_addr); - if(sockets[i] < 0) - goto error; - i++; -#ifdef ENABLE_IPV6 - if(GETFLAG(IPV6DISABLEDMASK)) - { - sockets[i] = -1; - } - else - { - sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index); - if(sockets[i] < 0) - goto error; - } - i++; -#endif - } - return 0; -error: - while(--i >= 0) - { - close(sockets[i]); - sockets[i] = -1; - } - return -1; -} - -/* - * response from a LiveBox (Wanadoo) -HTTP/1.1 200 OK -CACHE-CONTROL: max-age=1800 -DATE: Thu, 01 Jan 1970 04:03:23 GMT -EXT: -LOCATION: http://192.168.0.1:49152/gatedesc.xml -SERVER: Linux/2.4.17, UPnP/1.0, Intel SDK for UPnP devices /1.2 -ST: upnp:rootdevice -USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::upnp:rootdevice - - * response from a Linksys 802.11b : -HTTP/1.1 200 OK -Cache-Control:max-age=120 -Location:http://192.168.5.1:5678/rootDesc.xml -Server:NT/5.0 UPnP/1.0 -ST:upnp:rootdevice -USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice -EXT: - */ - -/* Responds to a SSDP "M-SEARCH" - * s : socket to use - * addr : peer - * st, st_len : ST: header - * suffix : suffix for USN: header - * host, port : our HTTP host, port - * delay : in milli-seconds - */ -static void -SendSSDPResponse(int s, const struct sockaddr * addr, - const char * st, int st_len, const char * suffix, - const char * host, unsigned short http_port, -#ifdef ENABLE_HTTPS - unsigned short https_port, -#endif - const char * uuidvalue, unsigned int delay) -{ - int l, n; - char buf[SSDP_PACKET_MAX_LEN]; - char addr_str[64]; - socklen_t addrlen; - int st_is_uuid; -#ifdef ENABLE_HTTP_DATE - char http_date[64]; - time_t t; - struct tm tm; - - time(&t); - gmtime_r(&t, &tm); - strftime(http_date, sizeof(http_date), - "%a, %d %b %Y %H:%M:%S GMT", &tm); -#endif - - st_is_uuid = (st_len == (int)strlen(uuidvalue)) && - (memcmp(uuidvalue, st, st_len) == 0); - /* - * follow guideline from document "UPnP Device Architecture 1.0" - * uppercase is recommended. - * DATE: is recommended - * SERVER: OS/ver UPnP/1.0 miniupnpd/1.0 - * - check what to put in the 'Cache-Control' header - * - * have a look at the document "UPnP Device Architecture v1.1 */ - l = snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=120\r\n" -#ifdef ENABLE_HTTP_DATE - "DATE: %s\r\n" -#endif - "ST: %.*s%s\r\n" - "USN: %s%s%.*s%s\r\n" - "EXT:\r\n" - "SERVER: " MINIUPNPD_SERVER_STRING "\r\n" -#ifndef RANDOMIZE_URLS - "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n" -#ifdef ENABLE_HTTPS - "SECURELOCATION.UPNP.ORG: https://%s:%u" ROOTDESC_PATH "\r\n" -#endif /* ENABLE_HTTPS */ -#else /* RANDOMIZE_URLS */ - "LOCATION: http://%s:%u/%s" ROOTDESC_PATH "\r\n" -#ifdef ENABLE_HTTPS - "SECURELOCATION.UPNP.ORG: https://%s:%u/%s" ROOTDESC_PATH "\r\n" -#endif /* ENABLE_HTTPS */ -#endif /* RANDOMIZE_URLS */ - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */ - "01-NLS: %u\r\n" /* same as BOOTID. UDA v1.1 */ - "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "\r\n", -#ifdef ENABLE_HTTP_DATE - http_date, -#endif - st_len, st, suffix, - uuidvalue, st_is_uuid ? "" : "::", - st_is_uuid ? 0 : st_len, st, suffix, - host, (unsigned int)http_port, -#ifdef RANDOMIZE_URLS - random_url, -#endif /* RANDOMIZE_URLS */ -#ifdef ENABLE_HTTPS - host, (unsigned int)https_port, -#ifdef RANDOMIZE_URLS - random_url, -#endif /* RANDOMIZE_URLS */ -#endif /* ENABLE_HTTPS */ - upnp_bootid, upnp_bootid, upnp_configid); - if(l<0) - { - syslog(LOG_ERR, "%s: snprintf failed %m", - "SendSSDPResponse()"); - return; - } - else if((unsigned)l>=sizeof(buf)) - { - syslog(LOG_WARNING, "%s: truncated output (%u>=%u)", - "SendSSDPResponse()", (unsigned)l, (unsigned)sizeof(buf)); - l = sizeof(buf) - 1; - } - addrlen = (addr->sa_family == AF_INET6) - ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); - n = sendto_schedule(s, buf, l, 0, - addr, addrlen, delay); - sockaddr_to_string(addr, addr_str, sizeof(addr_str)); - syslog(LOG_DEBUG, "%s: %d bytes to %s ST: %.*s", - "SendSSDPResponse()", - n, addr_str, l, buf); - if(n < 0) - { - syslog(LOG_ERR, "%s: sendto(udp): %m", - "SendSSDPResponse()"); - } -} - -static struct { - const char * s; - const int version; - const char * uuid; -} const known_service_types[] = -{ - {"upnp:rootdevice", 0, uuidvalue_igd}, -#ifdef IGD_V2 - {"urn:schemas-upnp-org:device:InternetGatewayDevice:", 2, uuidvalue_igd}, - {"urn:schemas-upnp-org:device:WANConnectionDevice:", 2, uuidvalue_wcd}, - {"urn:schemas-upnp-org:device:WANDevice:", 2, uuidvalue_wan}, - {"urn:schemas-upnp-org:service:WANIPConnection:", 2, uuidvalue_wcd}, - {"urn:schemas-upnp-org:service:DeviceProtection:", 1, uuidvalue_igd}, -#ifdef ENABLE_6FC_SERVICE - {"urn:schemas-upnp-org:service:WANIPv6FirewallControl:", 1, uuidvalue_wcd}, -#endif -#else /* IGD_V2 */ - /* IGD v1 */ - {"urn:schemas-upnp-org:device:InternetGatewayDevice:", 1, uuidvalue_igd}, - {"urn:schemas-upnp-org:device:WANConnectionDevice:", 1, uuidvalue_wcd}, - {"urn:schemas-upnp-org:device:WANDevice:", 1, uuidvalue_wan}, - {"urn:schemas-upnp-org:service:WANIPConnection:", 1, uuidvalue_wcd}, -#endif /* IGD_V2 */ - {"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", 1, uuidvalue_wan}, -#ifdef ADVERTISE_WANPPPCONN - /* We use WAN IP Connection, not PPP connection, - * but buggy control points may try to use WanPPPConnection - * anyway */ - {"urn:schemas-upnp-org:service:WANPPPConnection:", 1, uuidvalue_wcd}, -#endif /* ADVERTISE_WANPPPCONN */ -#ifdef ENABLE_L3F_SERVICE - {"urn:schemas-upnp-org:service:Layer3Forwarding:", 1, uuidvalue_igd}, -#endif /* ENABLE_L3F_SERVICE */ -/* we might want to support urn:schemas-wifialliance-org:device:WFADevice:1 - * urn:schemas-wifialliance-org:device:WFADevice:1 - * in the future */ - {0, 0, 0} -}; - -/* SendSSDPNotify() sends the SSDP NOTIFY to a specific - * destination, for a specific UPnP service or device */ -static void -SendSSDPNotify(int s, const struct sockaddr * dest, socklen_t dest_len, - const char * dest_str, - const char * host, unsigned short http_port, -#ifdef ENABLE_HTTPS - unsigned short https_port, -#endif - const char * nt, const char * suffix, - const char * usn1, const char * usn2, const char * usn3, - unsigned int lifetime) -{ - char bufr[SSDP_PACKET_MAX_LEN]; - int n, l; - - l = snprintf(bufr, sizeof(bufr), - "NOTIFY * HTTP/1.1\r\n" - "HOST: %s:%d\r\n" - "CACHE-CONTROL: max-age=%u\r\n" -#ifndef RANDOMIZE_URLS - "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n" -#ifdef ENABLE_HTTPS - "SECURELOCATION.UPNP.ORG: https://%s:%u" ROOTDESC_PATH "\r\n" -#endif /* ENABLE_HTTPS */ -#else /* RANDOMIZE_URLS */ - "LOCATION: http://%s:%u/%s" ROOTDESC_PATH "\r\n" -#ifdef ENABLE_HTTPS - "SECURELOCATION.UPNP.ORG: https://%s:%u/%s" ROOTDESC_PATH "\r\n" -#endif /* ENABLE_HTTPS */ -#endif /* RANDOMIZE_URLS */ - "SERVER: " MINIUPNPD_SERVER_STRING "\r\n" - "NT: %s%s\r\n" - "USN: %s%s%s%s\r\n" - "NTS: ssdp:alive\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */ - "01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */ - "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "\r\n", - dest_str, SSDP_PORT, /* HOST: */ - lifetime, /* CACHE-CONTROL: */ - host, (unsigned int)http_port, /* LOCATION: */ -#ifdef RANDOMIZE_URLS - random_url, -#endif /* RANDOMIZE_URLS */ -#ifdef ENABLE_HTTPS - host, (unsigned int)https_port, /* SECURE-LOCATION: */ -#ifdef RANDOMIZE_URLS - random_url, -#endif /* RANDOMIZE_URLS */ -#endif /* ENABLE_HTTPS */ - nt, suffix, /* NT: */ - usn1, usn2, usn3, suffix, /* USN: */ - upnp_bootid, /* 01-NLS: */ - upnp_bootid, /* BOOTID.UPNP.ORG: */ - upnp_configid ); /* CONFIGID.UPNP.ORG: */ - if(l<0) { - syslog(LOG_ERR, "%s: snprintf error", "SendSSDPNotify()"); - return; - } else if((unsigned int)l >= sizeof(bufr)) { - syslog(LOG_WARNING, "%s: truncated output (%u>=%u)", - "SendSSDPNotify()", (unsigned)l, (unsigned)sizeof(bufr)); - l = sizeof(bufr) - 1; - } - n = sendto_or_schedule(s, bufr, l, 0, dest, dest_len); - if(n < 0) { - syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, - host ? host : "NULL"); - } else if(n != l) { - syslog(LOG_NOTICE, "sendto() sent %d out of %d bytes", n, l); - } - /* Due to the unreliable nature of UDP, devices SHOULD send the entire - * set of discovery messages more than once with some delay between - * sets e.g. a few hundred milliseconds. To avoid network congestion - * discovery messages SHOULD NOT be sent more than three times. */ - n = sendto_schedule(s, bufr, l, 0, dest, dest_len, 250); - if(n < 0) { - syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, - host ? host : "NULL"); - } -} - -/* SendSSDPNotifies() send SSPD NOTIFY for a specific - * LAN (network interface) for all devices / services */ -#ifdef ENABLE_HTTPS -static void -SendSSDPNotifies(int s, const char * host, unsigned short http_port, - unsigned short https_port, - unsigned int lifetime, int ipv6) -#else -static void -SendSSDPNotifies(int s, const char * host, unsigned short http_port, - unsigned int lifetime, int ipv6) -#endif -{ -#ifdef ENABLE_IPV6 - struct sockaddr_storage sockname; - /* UDA 1.1 AnnexA and UDA 2.0 only allow/define the use of - * Link-Local and Site-Local multicast scopes */ - static struct { const char * p1, * p2; } const mcast_addrs[] = - { { LL_SSDP_MCAST_ADDR, "[" LL_SSDP_MCAST_ADDR "]" }, /* Link Local */ - { SL_SSDP_MCAST_ADDR, "[" SL_SSDP_MCAST_ADDR "]" }, /* Site Local */ -#ifndef UPNP_STRICT - { GL_SSDP_MCAST_ADDR, "[" GL_SSDP_MCAST_ADDR "]" }, /* Global */ -#endif /* ! UPNP_STRICT */ - { NULL, NULL } }; - int j; -#else /* ENABLE_IPV6 */ - struct sockaddr_in sockname; -#endif /* ENABLE_IPV6 */ - socklen_t sockname_len; - const char * dest_str; - int i; - char ver_str[4]; -#ifndef ENABLE_IPV6 - UNUSED(ipv6); -#endif /* ENABLE_IPV6 */ - - memset(&sockname, 0, sizeof(sockname)); -#ifdef ENABLE_IPV6 - /* first iterate destinations for this LAN interface (only 1 for IPv4) */ - for(j = 0; (mcast_addrs[j].p1 != 0 && ipv6) || j < 1; j++) { - if(ipv6) { - struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockname; - sockname_len = sizeof(struct sockaddr_in6); - p->sin6_family = AF_INET6; - p->sin6_port = htons(SSDP_PORT); - inet_pton(AF_INET6, mcast_addrs[j].p1, &(p->sin6_addr)); - dest_str = mcast_addrs[j].p2; - /* UPnP Device Architecture 1.1 : - * Devices MUST multicast SSDP messages for each of the UPnP-enabled - * interfaces. The scope of multicast SSDP messages MUST be - * link local FF02::C if the message is sent from a link local address. - * If the message is sent from a global address it MUST be multicast - * using either global scope FF0E::C or site local scope FF05::C. - * In networks with complex topologies and overlapping sites, use of - * global scope is RECOMMENDED. */ - } else { -#else /* ENABLE_IPV6 */ - { -#endif /* ENABLE_IPV6 */ - /* IPv4 */ - struct sockaddr_in *p = (struct sockaddr_in *)&sockname; - sockname_len = sizeof(struct sockaddr_in); - p->sin_family = AF_INET; - p->sin_port = htons(SSDP_PORT); - p->sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR); - dest_str = SSDP_MCAST_ADDR; - } - - /* iterate all services / devices */ - for(i = 0; known_service_types[i].s; i++) { - if(i==0) - ver_str[0] = '\0'; - else - snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version); - SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str, - host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - known_service_types[i].s, ver_str, /* NT: */ - known_service_types[i].uuid, "::", - known_service_types[i].s, /* ver_str, USN: */ - lifetime); - /* for devices, also send NOTIFY on the uuid */ - if(0==memcmp(known_service_types[i].s, - "urn:schemas-upnp-org:device", sizeof("urn:schemas-upnp-org:device")-1)) { - SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str, - host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - known_service_types[i].uuid, "", /* NT: */ - known_service_types[i].uuid, "", "", /* ver_str, USN: */ - lifetime); - } - } /* for(i = 0; known_service_types[i].s; i++) */ -#ifdef ENABLE_IPV6 - } /* for(j = 0; (mcast_addrs[j].p1 != 0 && ipv6) || j < 1; j++) */ -#endif /* ENABLE_IPV6 */ -} - -/* SendSSDPNotifies2() sends SSDP NOTIFY packets on all interfaces - * for all destinations, all devices / services */ -void -SendSSDPNotifies2(int * sockets, - unsigned short http_port, -#ifdef ENABLE_HTTPS - unsigned short https_port, -#endif - unsigned int lifetime) -{ - int i; - struct lan_addr_s * lan_addr; - for(i = 0, lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) { - SendSSDPNotifies(sockets[i], lan_addr->str, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - lifetime, 0); - i++; -#ifdef ENABLE_IPV6 - if(sockets[i] >= 0) { - SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - lifetime, 1); - } - i++; -#endif /* ENABLE_IPV6 */ - } -} - -/* ProcessSSDPRequest() - * process SSDP M-SEARCH requests and responds to them */ -void -#ifdef ENABLE_HTTPS -ProcessSSDPRequest(int s, unsigned short http_port, unsigned short https_port) -#else -ProcessSSDPRequest(int s, unsigned short http_port) -#endif -{ - int n; - char bufr[1500]; -#ifdef ENABLE_IPV6 - struct sockaddr_storage sendername; -#else - struct sockaddr_in sendername; -#endif - int source_ifindex = -1; -#ifdef IP_PKTINFO - char cmbuf[CMSG_SPACE(sizeof(struct in_pktinfo))]; - struct iovec iovec = { - .iov_base = bufr, - .iov_len = sizeof(bufr) - }; - struct msghdr mh = { - .msg_name = &sendername, - .msg_namelen = sizeof(sendername), - .msg_iov = &iovec, - .msg_iovlen = 1, - .msg_control = cmbuf, - .msg_controllen = sizeof(cmbuf) - }; - struct cmsghdr *cmptr; -#endif /* IP_PKTINFO */ -#ifdef IP_RECVIF - char cmbuf[CMSG_SPACE(sizeof(struct sockaddr_dl))]; - struct iovec iovec = { - .iov_base = bufr, - .iov_len = sizeof(bufr) - }; - struct msghdr mh = { - .msg_name = &sendername, - .msg_namelen = sizeof(sendername), - .msg_iov = &iovec, - .msg_iovlen = 1, - .msg_control = cmbuf, - .msg_controllen = sizeof(cmbuf) - }; - struct cmsghdr *cmptr; -#endif /* IP_RECVIF */ - -#if defined(IP_RECVIF) || defined(IP_PKTINFO) - n = recvmsg(s, &mh, 0); -#else - socklen_t len_r; - len_r = sizeof(sendername); - n = recvfrom(s, bufr, sizeof(bufr), 0, - (struct sockaddr *)&sendername, &len_r); -#endif /* defined(IP_RECVIF) || defined(IP_PKTINFO) */ - if(n < 0) - { - /* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time) - * other errors : log to LOG_ERR */ - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) - { - syslog(LOG_ERR, "recvfrom(udp): %m"); - } - return; - } - -#if defined(IP_RECVIF) || defined(IP_PKTINFO) - for(cmptr = CMSG_FIRSTHDR(&mh); cmptr != NULL; cmptr = CMSG_NXTHDR(&mh, cmptr)) - { - syslog(LOG_DEBUG, "level=%d type=%d", cmptr->cmsg_level, cmptr->cmsg_type); -#ifdef IP_PKTINFO - if(cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) - { - struct in_pktinfo * pi; /* fields : ifindex, spec_dst, addr */ - pi = (struct in_pktinfo *)CMSG_DATA(cmptr); - syslog(LOG_DEBUG, "ifindex = %u %s", pi->ipi_ifindex, inet_ntoa(pi->ipi_spec_dst)); - source_ifindex = pi->ipi_ifindex; - } -#endif /* IP_PKTINFO */ -#if defined(ENABLE_IPV6) && defined(IPV6_RECVPKTINFO) - if(cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_RECVPKTINFO) - { - struct in6_pktinfo * pi6; /* fields : ifindex, addr */ - pi6 = (struct in6_pktinfo *)CMSG_DATA(cmptr); - syslog(LOG_DEBUG, "ifindex = %u", pi6->ipi6_ifindex); - source_ifindex = pi6->ipi6_ifindex; - } -#endif /* defined(ENABLE_IPV6) && defined(IPV6_RECVPKTINFO) */ -#ifdef IP_RECVIF - if(cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) - { - struct sockaddr_dl *sdl; /* fields : len, family, index, type, nlen, alen, slen, data */ - sdl = (struct sockaddr_dl *)CMSG_DATA(cmptr); - syslog(LOG_DEBUG, "sdl_index = %d %s", sdl->sdl_index, link_ntoa(sdl)); - source_ifindex = sdl->sdl_index; - } -#endif /* IP_RECVIF */ - } -#endif /* defined(IP_RECVIF) || defined(IP_PKTINFO) */ -#ifdef ENABLE_HTTPS - ProcessSSDPData(s, bufr, n, (struct sockaddr *)&sendername, source_ifindex, - http_port, https_port); -#else - ProcessSSDPData(s, bufr, n, (struct sockaddr *)&sendername, source_ifindex, - http_port); -#endif - -} - -#ifdef ENABLE_HTTPS -void -ProcessSSDPData(int s, const char *bufr, int n, - const struct sockaddr * sender, int source_if, - unsigned short http_port, unsigned short https_port) -#else -void -ProcessSSDPData(int s, const char *bufr, int n, - const struct sockaddr * sender, int source_if, - unsigned short http_port) -#endif -{ - int i, l; - struct lan_addr_s * lan_addr = NULL; - const char * st = NULL; - int st_len = 0; - int st_ver = 0; - char sender_str[64]; - char ver_str[4]; - const char * announced_host = NULL; -#ifdef UPNP_STRICT -#ifdef ENABLE_IPV6 - char announced_host_buf[64]; -#endif -#endif -#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) - int mx_value = -1; -#endif - unsigned int delay = 50; /* Non-zero default delay to prevent flooding */ - /* UPnP Device Architecture v1.1. 1.3.3 Search response : - * Devices responding to a multicast M-SEARCH SHOULD wait a random period - * of time between 0 seconds and the number of seconds specified in the - * MX field value of the search request before responding, in order to - * avoid flooding the requesting control point with search responses - * from multiple devices. If the search request results in the need for - * a multiple part response from the device, those multiple part - * responses SHOULD be spread at random intervals through the time period - * from 0 to the number of seconds specified in the MX header field. */ - char atoi_buffer[8]; - - /* get the string representation of the sender address */ - sockaddr_to_string(sender, sender_str, sizeof(sender_str)); - lan_addr = get_lan_for_peer(sender); - if(source_if >= 0) - { - if(lan_addr != NULL) - { - if(lan_addr->index != (unsigned)source_if && lan_addr->index != 0) - { - syslog(LOG_WARNING, "interface index not matching %u != %d", lan_addr->index, source_if); - } - } - else - { - /* use the interface index */ - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - if(lan_addr->index == (unsigned)source_if) - break; - } - } - } - if(lan_addr == NULL) - { - syslog(LOG_WARNING, "SSDP packet sender %s (if_index=%d) not from a LAN, ignoring", - sender_str, source_if); - return; - } - - if(memcmp(bufr, "NOTIFY", 6) == 0) - { - /* ignore NOTIFY packets. We could log the sender and device type */ - return; - } - else if(memcmp(bufr, "M-SEARCH", 8) == 0) - { - i = 0; - while(i < n) - { - while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n')) - i++; - i += 2; - if((i < n - 3) && (strncasecmp(bufr+i, "st:", 3) == 0)) - { - st = bufr+i+3; - st_len = 0; - while((*st == ' ' || *st == '\t') && (st < bufr + n)) - st++; - while((st + st_len < bufr + n) - && (st[st_len]!='\r' && st[st_len]!='\n')) - st_len++; - l = st_len; - while(l > 0 && st[l-1] != ':') - l--; - memset(atoi_buffer, 0, sizeof(atoi_buffer)); - memcpy(atoi_buffer, st + l, MIN((int)(sizeof(atoi_buffer) - 1), st_len - l)); - st_ver = atoi(atoi_buffer); - syslog(LOG_DEBUG, "ST: %.*s (ver=%d)", st_len, st, st_ver); - /*j = 0;*/ - /*while(bufr[i+j]!='\r') j++;*/ - /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/ - } -#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) - else if((i < n - 3) && (strncasecmp(bufr+i, "mx:", 3) == 0)) - { - const char * mx; - int mx_len; - mx = bufr+i+3; - mx_len = 0; - while((mx < bufr + n) && (*mx == ' ' || *mx == '\t')) - mx++; - while((mx + mx_len < bufr + n) - && (mx[mx_len]!='\r' && mx[mx_len]!='\n')) - mx_len++; - memset(atoi_buffer, 0, sizeof(atoi_buffer)); - memcpy(atoi_buffer, mx, MIN((int)(sizeof(atoi_buffer) - 1), mx_len)); - mx_value = atoi(atoi_buffer); - syslog(LOG_DEBUG, "MX: %.*s (value=%d)", mx_len, mx, mx_value); - } -#endif /* defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) */ -#if defined(UPNP_STRICT) - /* Fix UDA-1.2.10 Man header empty or invalid */ - else if((i < n - 4) && (strncasecmp(bufr+i, "man:", 3) == 0)) - { - const char * man; - int man_len; - man = bufr+i+4; - man_len = 0; - while((man < bufr + n) && (*man == ' ' || *man == '\t')) - man++; - while((man + man_len < bufr + n) - && (man[man_len]!='\r' && man[man_len]!='\n')) - man_len++; - if((man_len < 15) || (strncmp(man, "\"ssdp:discover\"", 15) != 0)) { - syslog(LOG_INFO, "ignoring SSDP packet MAN empty or invalid header"); - return; - } - } -#endif /* defined(UPNP_STRICT) */ - } -#ifdef UPNP_STRICT - /* For multicast M-SEARCH requests, if the search request does - * not contain an MX header field, the device MUST silently - * discard and ignore the search request. */ - if(mx_value < 0) { - syslog(LOG_INFO, "ignoring SSDP packet missing MX: header"); - return; - } else if(mx_value > 5) { - /* If the MX header field specifies a field value greater - * than 5, the device SHOULD assume that it contained the - * value 5 or less. */ - mx_value = 5; - } -#elif defined(DELAY_MSEARCH_RESPONSE) - if(mx_value < 0) { - mx_value = 1; - } else if(mx_value > 5) { - /* If the MX header field specifies a field value greater - * than 5, the device SHOULD assume that it contained the - * value 5 or less. */ - mx_value = 5; - } -#endif - /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s", - sender_str );*/ - if(st && (st_len > 0)) - { - syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s", - sender_str, st_len, st); - /* find in which sub network the client is */ - if(sender->sa_family == AF_INET) - { - if (lan_addr == NULL) - { - syslog(LOG_ERR, - "Can't find in which sub network the client %s is", - sender_str); - return; - } - announced_host = lan_addr->str; - } -#ifdef ENABLE_IPV6 - else - { - /* IPv6 address with brackets */ -#ifdef UPNP_STRICT - int index; - struct in6_addr addr6; - size_t addr6_len = sizeof(addr6); - /* retrieve the IPv6 address which - * will be used locally to reach sender */ - memset(&addr6, 0, sizeof(addr6)); - if(IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6 *)sender)->sin6_addr))) { - get_link_local_addr(((struct sockaddr_in6 *)sender)->sin6_scope_id, &addr6); - } else if(get_src_for_route_to (sender, &addr6, &addr6_len, &index) < 0) { - syslog(LOG_WARNING, "get_src_for_route_to() failed, using %s", ipv6_addr_for_http_with_brackets); - announced_host = ipv6_addr_for_http_with_brackets; - } - if(announced_host == NULL) { - if(inet_ntop(AF_INET6, &addr6, - announced_host_buf+1, - sizeof(announced_host_buf) - 2)) { - announced_host_buf[0] = '['; - i = strlen(announced_host_buf); - if(i < (int)sizeof(announced_host_buf) - 1) { - announced_host_buf[i] = ']'; - announced_host_buf[i+1] = '\0'; - } else { - syslog(LOG_NOTICE, "cannot suffix %s with ']'", - announced_host_buf); - } - announced_host = announced_host_buf; - } else { - syslog(LOG_NOTICE, "inet_ntop() failed %m"); - announced_host = ipv6_addr_for_http_with_brackets; - } - } -#else - announced_host = ipv6_addr_for_http_with_brackets; -#endif - } -#endif - /* Responds to request with a device as ST header */ - for(i = 0; known_service_types[i].s; i++) - { - l = (int)strlen(known_service_types[i].s); - if(l<=st_len && (0 == memcmp(st, known_service_types[i].s, l)) -#ifdef UPNP_STRICT - && (st_ver <= known_service_types[i].version) - /* only answer for service version lower or equal of supported one */ -#endif - ) - { - /* SSDP_RESPOND_SAME_VERSION : - * response is urn:schemas-upnp-org:service:WANIPConnection:1 when - * M-SEARCH included urn:schemas-upnp-org:service:WANIPConnection:1 - * else the implemented versions is included in the response - * - * From UPnP Device Architecture v1.1 : - * 1.3.2 [...] Updated versions of device and service types - * are REQUIRED to be fully backward compatible with - * previous versions. Devices MUST respond to M-SEARCH - * requests for any supported version. For example, if a - * device implements “urn:schemas-upnporg:service:xyz:2â€, - * it MUST respond to search requests for both that type - * and “urn:schemas-upnp-org:service:xyz:1â€. The response - * MUST specify the same version as was contained in the - * search request. [...] */ -#ifndef SSDP_RESPOND_SAME_VERSION - if(i==0) - ver_str[0] = '\0'; - else - snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version); -#endif - syslog(LOG_INFO, "Single search found"); -#ifdef DELAY_MSEARCH_RESPONSE - delay = random() / (1 + RAND_MAX / (1000 * mx_value)); -#ifdef DEBUG - syslog(LOG_DEBUG, "mx=%dsec delay=%ums", mx_value, delay); -#endif -#endif - SendSSDPResponse(s, sender, -#ifdef SSDP_RESPOND_SAME_VERSION - st, st_len, "", -#else - known_service_types[i].s, l, ver_str, -#endif - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - known_service_types[i].uuid, - delay); - break; - } - } - /* Responds to request with ST: ssdp:all */ - /* strlen("ssdp:all") == 8 */ - if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) - { -#ifdef DELAY_MSEARCH_RESPONSE - unsigned int delay_increment = (mx_value * 1000) / 15; -#endif - syslog(LOG_INFO, "ssdp:all found"); - for(i=0; known_service_types[i].s; i++) - { -#ifdef DELAY_MSEARCH_RESPONSE - delay += delay_increment; -#endif - if(i==0) - ver_str[0] = '\0'; - else - snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version); - l = (int)strlen(known_service_types[i].s); - SendSSDPResponse(s, sender, - known_service_types[i].s, l, ver_str, - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - known_service_types[i].uuid, - delay); - } - /* also answer for uuid */ -#ifdef DELAY_MSEARCH_RESPONSE - delay += delay_increment; -#endif - SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_igd, delay); -#ifdef DELAY_MSEARCH_RESPONSE - delay += delay_increment; -#endif - SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_wan, delay); -#ifdef DELAY_MSEARCH_RESPONSE - delay += delay_increment; -#endif - SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_wcd, delay); - } - /* responds to request by UUID value */ - l = (int)strlen(uuidvalue_igd); - if(l==st_len) - { -#ifdef DELAY_MSEARCH_RESPONSE - delay = random() / (1 + RAND_MAX / (1000 * mx_value)); -#endif - if(0 == memcmp(st, uuidvalue_igd, l)) - { - syslog(LOG_INFO, "ssdp:uuid (IGD) found"); - SendSSDPResponse(s, sender, st, st_len, "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_igd, delay); - } - else if(0 == memcmp(st, uuidvalue_wan, l)) - { - syslog(LOG_INFO, "ssdp:uuid (WAN) found"); - SendSSDPResponse(s, sender, st, st_len, "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_wan, delay); - } - else if(0 == memcmp(st, uuidvalue_wcd, l)) - { - syslog(LOG_INFO, "ssdp:uuid (WCD) found"); - SendSSDPResponse(s, sender, st, st_len, "", - announced_host, http_port, -#ifdef ENABLE_HTTPS - https_port, -#endif - uuidvalue_wcd, delay); - } - } - } - else - { - syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s", sender_str); - } - } - else - { - syslog(LOG_NOTICE, "Unknown udp packet received from %s", sender_str); - } -} - -static int -SendSSDPbyebye(int s, const struct sockaddr * dest, socklen_t destlen, - const char * dest_str, - const char * nt, const char * suffix, - const char * usn1, const char * usn2, const char * usn3) -{ - int n, l; - char bufr[SSDP_PACKET_MAX_LEN]; - - l = snprintf(bufr, sizeof(bufr), - "NOTIFY * HTTP/1.1\r\n" - "HOST: %s:%d\r\n" - "NT: %s%s\r\n" - "USN: %s%s%s%s\r\n" - "NTS: ssdp:byebye\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */ - "01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */ - "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "\r\n", - dest_str, SSDP_PORT, /* HOST : */ - nt, suffix, /* NT: */ - usn1, usn2, usn3, suffix, /* USN: */ - upnp_bootid, upnp_bootid, upnp_configid); - if(l<0) - { - syslog(LOG_ERR, "%s: snprintf error", "SendSSDPbyebye()"); - return -1; - } - else if((unsigned int)l >= sizeof(bufr)) - { - syslog(LOG_WARNING, "%s: truncated output (%u>=%u)", - "SendSSDPbyebye()", (unsigned)l, (unsigned)sizeof(bufr)); - l = sizeof(bufr) - 1; - } - n = sendto_or_schedule(s, bufr, l, 0, dest, destlen); - if(n < 0) - { - syslog(LOG_ERR, "sendto(udp_shutdown=%d): %m", s); - return -1; - } - else if(n != l) - { - syslog(LOG_NOTICE, "sendto() sent %d out of %d bytes", n, l); - return -1; - } - return 0; -} - -/* This will broadcast ssdp:byebye notifications to inform - * the network that UPnP is going down. */ -int -SendSSDPGoodbye(int * sockets, int n_sockets) -{ - struct sockaddr_in sockname4; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 sockname6; - struct sockaddr * sockname; - socklen_t socknamelen; - int ipv6 = 0; -#endif - int i, j; - char ver_str[4]; - int ret = 0; - const char * dest_str; - - memset(&sockname4, 0, sizeof(struct sockaddr_in)); - sockname4.sin_family = AF_INET; - sockname4.sin_port = htons(SSDP_PORT); - sockname4.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR); -#ifdef ENABLE_IPV6 - memset(&sockname6, 0, sizeof(struct sockaddr_in6)); - sockname6.sin6_family = AF_INET6; - sockname6.sin6_port = htons(SSDP_PORT); - inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &(sockname6.sin6_addr)); -#else - dest_str = SSDP_MCAST_ADDR; -#endif - - for(j=0; j=sizeof(strbuf)) { - l = sizeof(strbuf) - 1; - } - CODELENGTH(l, p); - memcpy(p, strbuf, l); - p += l; - l = snprintf(strbuf, sizeof(strbuf), "%s::%s%s", - known_service_types[i].uuid, known_service_types[i].s, ver_str); - if(l<0) { - syslog(LOG_WARNING, "SubmitServicesToMiniSSDPD: snprintf %m"); - continue; - } else if((unsigned)l>=sizeof(strbuf)) { - l = sizeof(strbuf) - 1; - } - CODELENGTH(l, p); - memcpy(p, strbuf, l); - p += l; - l = (int)strlen(MINIUPNPD_SERVER_STRING); - CODELENGTH(l, p); - memcpy(p, MINIUPNPD_SERVER_STRING, l); - p += l; - l = snprintf(strbuf, sizeof(strbuf), "http://%s:%u" ROOTDESC_PATH, - host, (unsigned int)port); - if(l<0) { - syslog(LOG_WARNING, "SubmitServicesToMiniSSDPD: snprintf %m"); - continue; - } else if((unsigned)l>=sizeof(strbuf)) { - l = sizeof(strbuf) - 1; - } - CODELENGTH(l, p); - memcpy(p, strbuf, l); - p += l; - /* now write the encoded data */ - n = p - buffer; /* bytes to send */ - p = buffer; /* start */ - while(n > 0) { - l = write(s, p, n); - if (l < 0) { - if(errno == EINTR) - continue; - syslog(LOG_ERR, "write(): %m"); - close(s); - return -1; - } else if (l == 0) { - syslog(LOG_ERR, "write() returned 0"); - close(s); - return -1; - } - p += l; - n -= l; - } - } - close(s); - syslog(LOG_DEBUG, "%d service submitted to MiniSSDPd", i); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/minissdp.h b/src/contrib/miniupnp/miniupnpd/minissdp.h deleted file mode 100644 index a0e51a0..0000000 --- a/src/contrib/miniupnp/miniupnpd/minissdp.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $Id: minissdp.h,v 1.12 2014/04/09 07:20:59 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef MINISSDP_H_INCLUDED -#define MINISSDP_H_INCLUDED - -#include "miniupnpdtypes.h" - -int -OpenAndConfSSDPReceiveSocket(int ipv6); - -int -OpenAndConfSSDPNotifySockets(int * sockets); - -#ifdef ENABLE_HTTPS -void -SendSSDPNotifies2(int * sockets, - unsigned short http_port, - unsigned short https_port, - unsigned int lifetime); -#else -void -SendSSDPNotifies2(int * sockets, - unsigned short http_port, - unsigned int lifetime); -#endif - -void -#ifdef ENABLE_HTTPS -ProcessSSDPRequest(int s, - unsigned short http_port, unsigned short https_port); -#else -ProcessSSDPRequest(int s, unsigned short http_port); -#endif - -#ifdef ENABLE_HTTPS -void -ProcessSSDPData(int s, const char *bufr, int n, - const struct sockaddr * sendername, int source_if, - unsigned short http_port, unsigned short https_port); -#else -void -ProcessSSDPData(int s, const char *bufr, int n, - const struct sockaddr * sendername, int source_if, - unsigned short http_port); -#endif - -int -SendSSDPGoodbye(int * sockets, int n); - -int -SubmitServicesToMiniSSDPD(const char * host, unsigned short port); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpd.8 b/src/contrib/miniupnp/miniupnpd/miniupnpd.8 deleted file mode 100644 index 83123c4..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpd.8 +++ /dev/null @@ -1,89 +0,0 @@ -.TH MINIUPNPD 8 -.SH NAME -miniupnpd \- UPnP Internet Gateway Device Daemon -.SH SYNOPSIS -.B miniupnpd -.RB [ "\-f \fIconfig_file" "] [" "\-i \fIext_ifname" "] [" "\-o \fIext_ip" ] -.RB [ "\-a \fIlistening_ip" "] [" "\-p \fIport" "] [" \-d "] [" \-U "] [" \-S "] [" \-N ] -.RB [ "\-u \fIuuid" "] [" "\-s \fIserial" "] [" "\-m \fImodel_number" ] -.RB [ "\-t \fInotify_interval" "] [" "\-P \fIpid_filename" ] -.RB [ "\-B \fIdown up" "] [" "\-w \fIurl" "] [" "\-r \fIclean_ruleset_interval" ] -.RB [ "\-A \fIpermission rule" "] [" "\-b \fIBOOTID" "] [" \-1 ] -.SH DESCRIPTION -miniupnpd act as a UPnP Internet Gateway Device. It is designed -to run on the gateway between the internet and a NAT'ed LAN. It provides -an interface, as defined in the UPnP standard, for enabling -clients on the LAN to ask for port redirections. -.SH OPTIONS -.TP -.BI \-f " config_file" -load the config from file. default is /etc/miniupnpd.conf. -.TP -.BI \-i " ext_ifname" -interface used to connect to the internet. -.TP -.BI \-o " ext_ip" -address used to connect to the internet. -default address of the interface will be used if not specified. -.TP -.BI \-a " listening_ip" -address on the LAN. \-a option can by used multiple time if LAN is -subdivised in several subnetworks. -.TP -.BI \-p " port" -port used for HTTP. -.TP -.B \-d -debug mode : do not go to background, output messages on console -and do not filter out low priority messages. -.TP -.B \-U -report system uptime instead of daemon uptime to clients. -.TP -.B \-S -sets "secure" mode : clients can only add mappings to their own ip -.TP -.B \-N -enables NAT-PMP functionality. -.TP -.BI \-u " uuid" -set the uuid of the UPnP Internet Gateway Device. -.TP -.BI \-s " serial" -serial number for the UPnP Internet Gateway Device. -.TP -.BI \-m " model_number" -model number for the UPnP Internet Gateway Device. -.TP -.BI \-t " notify_interval" -SSDP notify interval in seconds : -SSDP announce messages will be broadcasted at this interval. -.TP -.BI \-P " pid_filename" -pid file. default is /var/run/miniupnpd.pid -.TP -.BI \-B " down up" -download and upload bitrates reported to clients. -.TP -.BI \-w " url" -presentation url. default is first address on LAN, port 80. -.TP -.BI \-r " clean_ruleset_interval" -(minimum) interval between unused rules cleaning checks. -.TP -.BI \-A " permission rule" -use following syntax for permission rules : - (allow|deny) (external port range) ip/mask (internal port range) -.br -examples : - "allow 1024-65535 192.168.1.0/24 1024-65535" - "deny 0-65535 0.0.0.0/0 0-65535" -.TP -.BI \-b " BOOTID" -sets the value of BOOTID.UPNP.ORG SSDP header -.TP -.B \-1 -force reporting IGDv1 in rootDesc when compiled as IGDv2 *use with care* -.SH "SEE ALSO" -minissdpd(1) miniupnpc(3) -.SH BUGS diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpd.c b/src/contrib/miniupnp/miniupnpd/miniupnpd.c deleted file mode 100644 index 625b5e6..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpd.c +++ /dev/null @@ -1,2741 +0,0 @@ -/* $Id: miniupnpd.c,v 1.226 2018/03/13 10:35:55 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -/* Experimental support for NFQUEUE interfaces */ -#ifdef ENABLE_NFQUEUE -/* apt-get install libnetfilter-queue-dev */ -#include -#include -#if 0 -#include /* Defines verdicts (NF_ACCEPT, etc) */ -#endif -#include -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(sun) -#include -#elif !defined(__linux__) -/* for BSD's sysctl */ -#include -#endif - -/* unix sockets */ -#ifdef USE_MINIUPNPDCTL -#include -#endif - -#ifdef TOMATO -#include -#endif /* TOMATO */ -#include "macros.h" -#include "upnpglobalvars.h" -#include "upnphttp.h" -#include "upnpdescgen.h" -#include "miniupnpdpath.h" -#include "getifaddr.h" -#include "upnpsoap.h" -#include "options.h" -#include "minissdp.h" -#include "upnpredirect.h" -#include "upnppinhole.h" -#include "miniupnpdtypes.h" -#include "daemonize.h" -#include "upnpevents.h" -#include "asyncsendto.h" -#ifdef ENABLE_NATPMP -#include "natpmp.h" -#ifdef ENABLE_PCP -#include "pcpserver.h" -#else -#define PCP_MAX_LEN 32 -#endif -#endif -#include "commonrdr.h" -#include "upnputils.h" -#ifdef USE_IFACEWATCHER -#include "ifacewatcher.h" -#endif -#ifdef ENABLE_UPNPPINHOLE -#ifdef USE_NETFILTER -void init_iptpinhole(void); -#endif -#endif - -#ifndef DEFAULT_CONFIG -#define DEFAULT_CONFIG "/etc/miniupnpd.conf" -#endif - -#ifdef USE_MINIUPNPDCTL -struct ctlelem { - int socket; - LIST_ENTRY(ctlelem) entries; -}; -#endif /* USE_MINIUPNPDCTL */ - -#ifdef ENABLE_NFQUEUE -/* globals */ -static struct nfq_handle *nfqHandle; -static struct sockaddr_in ssdp; - -/* prototypes */ -static int nfqueue_cb( struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) ; -int identify_ip_protocol (char *payload); -int get_udp_dst_port (char *payload); -#endif /* ENABLE_NFQUEUE */ - -/* variables used by signals */ -static volatile sig_atomic_t quitting = 0; -volatile sig_atomic_t should_send_public_address_change_notif = 0; -#if !defined(TOMATO) && defined(ENABLE_LEASEFILE) && defined(LEASEFILE_USE_REMAINING_TIME) -volatile sig_atomic_t should_rewrite_leasefile = 0; -#endif /* !TOMATO && ENABLE_LEASEFILE && LEASEFILE_USE_REMAINING_TIME */ - -#ifdef TOMATO -#if 1 -/* Tomato specific code */ -static volatile sig_atomic_t gotusr2 = 0; - -static void -sigusr2(int sig) -{ - gotusr2 = 1; -} - -static void -tomato_save(const char *fname) -{ - unsigned short eport; - unsigned short iport; - unsigned int leaseduration; - unsigned int timestamp; - char proto[4]; - char iaddr[32]; - char desc[64]; - char rhost[32]; - int n; - FILE *f; - int t; - char tmp[128]; - - strcpy(tmp, "/etc/upnp/saveXXXXXX"); - if ((t = mkstemp(tmp)) != -1) - { - if ((f = fdopen(t, "w")) != NULL) - { - n = 0; - while (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) - { - timestamp = (leaseduration > 0) ? time(NULL) + leaseduration : 0; - fprintf(f, "%s %u %s %u [%s] %u\n", proto, eport, iaddr, iport, desc, timestamp); - ++n; - } - fclose(f); - rename(tmp, fname); - } - else - { - close(t); - } - unlink(tmp); - } -} - -static void -tomato_load(void) -{ - FILE *f; - char s[256]; - unsigned short eport; - unsigned short iport; - unsigned int leaseduration; - unsigned int timestamp; - time_t current_time; - char proto[4]; - char iaddr[32]; - char *rhost; - char *a, *b; - - if ((f = fopen("/etc/upnp/data", "r")) != NULL) - { - current_time = time(NULL); - s[sizeof(s) - 1] = 0; - while (fgets(s, sizeof(s) - 1, f)) { - if (sscanf(s, "%3s %hu %31s %hu [%*[^]]] %u", proto, &eport, iaddr, &iport, ×tamp) >= 4) - { - if (((a = strchr(s, '[')) != NULL) && ((b = strrchr(a, ']')) != NULL)) - { - if (timestamp > 0) - { - if (timestamp > current_time) - leaseduration = timestamp - current_time; - else - continue; - } - else - { - leaseduration = 0; /* default value */ - } - *b = 0; - rhost = NULL; - syslog(LOG_DEBUG, "Read redirection [%s] from file: %s port %hu to %s port %hu, timestamp: %u (%u)", - a + 1, proto, eport, iaddr, iport, timestamp, leaseduration); - upnp_redirect(rhost, eport, iaddr, iport, proto, a + 1, leaseduration); - } - } - } - fclose(f); - } -#ifdef ENABLE_NATPMP -#if 0 - ScanNATPMPforExpiration(); -#endif -#endif /* ENABLE_NATPMP */ - unlink("/etc/upnp/load"); -} - -static void -tomato_delete(void) -{ - FILE *f; - char s[128]; - unsigned short eport; - unsigned short iport; - unsigned int leaseduration; - char proto[4]; - char iaddr[32]; - char desc[64]; - char rhost[32]; - int n; - - if ((f = fopen("/etc/upnp/delete", "r")) != NULL) - { - s[sizeof(s) - 1] = 0; - while (fgets(s, sizeof(s) - 1, f)) - { - if (sscanf(s, "%3s %hu", proto, &eport) == 2) - { - if (proto[0] == '*') - { - n = upnp_get_portmapping_number_of_entries(); - while (--n >= 0) - { - if (upnp_get_redirection_infos_by_index(n, &eport, proto, &iport, iaddr, sizeof(iaddr), desc, sizeof(desc), rhost, sizeof(rhost), &leaseduration) == 0) - { - upnp_delete_redirection(eport, proto); - } - } - break; - } - else - { - upnp_delete_redirection(eport, proto); - } - } - } - fclose(f); - unlink("/etc/upnp/delete"); - } -} - -static void -tomato_helper(void) -{ - struct stat st; - - if (stat("/etc/upnp/delete", &st) == 0) - { - tomato_delete(); - } - - if (stat("/etc/upnp/load", &st) == 0) - { - tomato_load(); - } - - if (stat("/etc/upnp/save", &st) == 0) - { - tomato_save("/etc/upnp/data"); - unlink("/etc/upnp/save"); - } - - if (stat("/etc/upnp/info", &st) == 0) - { - tomato_save("/etc/upnp/data.info"); - unlink("/etc/upnp/info"); - } -} -#endif /* 1 (tomato) */ -#endif /* TOMATO */ - -/* OpenAndConfHTTPSocket() : - * setup the socket used to handle incoming HTTP connections. */ -static int -#ifdef ENABLE_IPV6 -OpenAndConfHTTPSocket(unsigned short * port, int ipv6) -#else -OpenAndConfHTTPSocket(unsigned short * port) -#endif -{ - int s; - int i = 1; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 listenname6; - struct sockaddr_in listenname4; -#else - struct sockaddr_in listenname; -#endif - socklen_t listenname_len; - - s = socket( -#ifdef ENABLE_IPV6 - ipv6 ? PF_INET6 : PF_INET, -#else - PF_INET, -#endif - SOCK_STREAM, 0); -#ifdef ENABLE_IPV6 - if(s < 0 && ipv6 && errno == EAFNOSUPPORT) - { - /* the system doesn't support IPV6 */ - syslog(LOG_WARNING, "socket(PF_INET6, ...) failed with EAFNOSUPPORT, disabling IPv6"); - SETFLAG(IPV6DISABLEDMASK); - ipv6 = 0; - /* Try again with IPv4 */ - s = socket(PF_INET, SOCK_STREAM, 0); - } -#endif - if(s < 0) - { - syslog(LOG_ERR, "socket(http): %m"); - return -1; - } - - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) - { - syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m"); - } -#if 0 - /* enable this to force IPV6 only for IPV6 socket. - * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */ - if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) - { - syslog(LOG_WARNING, "setsockopt(http, IPV6_V6ONLY): %m"); - } -#endif - - if(!set_non_blocking(s)) - { - syslog(LOG_WARNING, "set_non_blocking(http): %m"); - } - -#ifdef ENABLE_IPV6 - if(ipv6) - { - memset(&listenname6, 0, sizeof(struct sockaddr_in6)); - listenname6.sin6_family = AF_INET6; - listenname6.sin6_port = htons(*port); - listenname6.sin6_addr = ipv6_bind_addr; - listenname_len = sizeof(struct sockaddr_in6); - } else { - memset(&listenname4, 0, sizeof(struct sockaddr_in)); - listenname4.sin_family = AF_INET; - listenname4.sin_port = htons(*port); - listenname4.sin_addr.s_addr = htonl(INADDR_ANY); - listenname_len = sizeof(struct sockaddr_in); - } -#else - memset(&listenname, 0, sizeof(struct sockaddr_in)); - listenname.sin_family = AF_INET; - listenname.sin_port = htons(*port); - listenname.sin_addr.s_addr = htonl(INADDR_ANY); - listenname_len = sizeof(struct sockaddr_in); -#endif - -#if defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) - /* One and only one LAN interface */ - if(lan_addrs.lh_first != NULL && lan_addrs.lh_first->list.le_next == NULL - && strlen(lan_addrs.lh_first->ifname) > 0) - { - if(setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, - lan_addrs.lh_first->ifname, - strlen(lan_addrs.lh_first->ifname)) < 0) - syslog(LOG_WARNING, "setsockopt(http, SO_BINDTODEVICE, %s): %m", - lan_addrs.lh_first->ifname); - } -#endif /* defined(SO_BINDTODEVICE) && !defined(MULTIPLE_EXTERNAL_IP) */ - -#ifdef ENABLE_IPV6 - if(bind(s, - ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4, - listenname_len) < 0) -#else - if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0) -#endif - { - syslog(LOG_ERR, "bind(http): %m"); - close(s); - return -1; - } - - if(listen(s, 5) < 0) - { - syslog(LOG_ERR, "listen(http): %m"); - close(s); - return -1; - } - - if(*port == 0) { -#ifdef ENABLE_IPV6 - if(ipv6) { - struct sockaddr_in6 sockinfo; - socklen_t len = sizeof(struct sockaddr_in6); - if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) { - syslog(LOG_ERR, "getsockname(): %m"); - } else { - *port = ntohs(sockinfo.sin6_port); - } - } else { -#endif /* ENABLE_IPV6 */ - struct sockaddr_in sockinfo; - socklen_t len = sizeof(struct sockaddr_in); - if (getsockname(s, (struct sockaddr *)&sockinfo, &len) < 0) { - syslog(LOG_ERR, "getsockname(): %m"); - } else { - *port = ntohs(sockinfo.sin_port); - } -#ifdef ENABLE_IPV6 - } -#endif /* ENABLE_IPV6 */ - } - return s; -} - -static struct upnphttp * -ProcessIncomingHTTP(int shttpl, const char * protocol) -{ - int shttp; - socklen_t clientnamelen; -#ifdef ENABLE_IPV6 - struct sockaddr_storage clientname; - clientnamelen = sizeof(struct sockaddr_storage); -#else - struct sockaddr_in clientname; - clientnamelen = sizeof(struct sockaddr_in); -#endif - shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); - if(shttp<0) - { - /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - syslog(LOG_ERR, "accept(http): %m"); - } - else - { - struct upnphttp * tmp = 0; - char addr_str[64]; - - sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); -#ifdef DEBUG - syslog(LOG_DEBUG, "%s connection from %s", protocol, addr_str); -#endif /* DEBUG */ - if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL) - { - /* The peer is not a LAN ! */ - syslog(LOG_WARNING, - "%s peer %s is not from a LAN, closing the connection", - protocol, addr_str); - close(shttp); - } - else - { - /* Create a new upnphttp object and add it to - * the active upnphttp object list */ - tmp = New_upnphttp(shttp); - if(tmp) - { -#ifdef ENABLE_IPV6 - if(clientname.ss_family == AF_INET) - { - tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; - } - else if(clientname.ss_family == AF_INET6) - { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; - if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) - { - memcpy(&tmp->clientaddr, - &addr->sin6_addr.s6_addr[12], - 4); - } - else - { - tmp->ipv6 = 1; - memcpy(&tmp->clientaddr_v6, - &addr->sin6_addr, - sizeof(struct in6_addr)); - } - } -#else - tmp->clientaddr = clientname.sin_addr; -#endif - memcpy(tmp->clientaddr_str, addr_str, sizeof(tmp->clientaddr_str)); - return tmp; - } - else - { - syslog(LOG_ERR, "New_upnphttp() failed"); - close(shttp); - } - } - } - return NULL; -} - -#ifdef ENABLE_NFQUEUE - -int identify_ip_protocol(char *payload) { - return payload[9]; -} - - -/* - * This function returns the destination port of the captured packet UDP - */ -int get_udp_dst_port(char *payload) { - char *pkt_data_ptr = NULL; - pkt_data_ptr = payload + sizeof(struct ip); - - /* Cast the UDP Header from the raw packet */ - struct udphdr *udp = (struct udphdr *) pkt_data_ptr; - - /* get the dst port of the packet */ - return(ntohs(udp->dest)); - -} -static int -OpenAndConfNFqueue(){ - - struct nfq_q_handle *myQueue; - struct nfnl_handle *netlinkHandle; - - int fd = 0, e = 0; - - inet_pton(AF_INET, "239.255.255.250", &(ssdp.sin_addr)); - - /* Get a queue connection handle from the module */ - if (!(nfqHandle = nfq_open())) { - syslog(LOG_ERR, "Error in nfq_open(): %m"); - return -1; - } - - /* Unbind the handler from processing any IP packets - Not totally sure why this is done, or if it's necessary... */ - if ((e = nfq_unbind_pf(nfqHandle, AF_INET)) < 0) { - syslog(LOG_ERR, "Error in nfq_unbind_pf(): %m"); - return -1; - } - - /* Bind this handler to process IP packets... */ - if (nfq_bind_pf(nfqHandle, AF_INET) < 0) { - syslog(LOG_ERR, "Error in nfq_bind_pf(): %m"); - return -1; - } - - /* Install a callback on queue -Q */ - if (!(myQueue = nfq_create_queue(nfqHandle, nfqueue, &nfqueue_cb, NULL))) { - syslog(LOG_ERR, "Error in nfq_create_queue(): %m"); - return -1; - } - - /* Turn on packet copy mode */ - if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) { - syslog(LOG_ERR, "Error setting packet copy mode (): %m"); - return -1; - } - - netlinkHandle = nfq_nfnlh(nfqHandle); - fd = nfnl_fd(netlinkHandle); - - return fd; - -} - - -static int nfqueue_cb( - struct nfq_q_handle *qh, - struct nfgenmsg *nfmsg, - struct nfq_data *nfa, - void *data) { - - char *pkt; - struct nfqnl_msg_packet_hdr *ph; - ph = nfq_get_msg_packet_hdr(nfa); - - if ( ph ) { - - int id = 0, size = 0; - id = ntohl(ph->packet_id); - - size = nfq_get_payload(nfa, &pkt); - - struct ip *iph = (struct ip *) pkt; - - int id_protocol = identify_ip_protocol(pkt); - - int dport = get_udp_dst_port(pkt); - - int x = sizeof (struct ip) + sizeof (struct udphdr); - - /* packets we are interested in are UDP multicast to 239.255.255.250:1900 - * and start with a data string M-SEARCH - */ - if ( (dport == 1900) && (id_protocol == IPPROTO_UDP) - && (ssdp.sin_addr.s_addr == iph->ip_dst.s_addr) ) { - - /* get the index that the packet came in on */ - u_int32_t idx = nfq_get_indev(nfa); - int i = 0; - for ( ;i < n_nfqix ; i++) { - if ( nfqix[i] == idx ) { - - struct udphdr *udp = (struct udphdr *) (pkt + sizeof(struct ip)); - - char *dd = pkt + x; - - struct sockaddr_in sendername; - sendername.sin_family = AF_INET; - sendername.sin_port = udp->source; - sendername.sin_addr.s_addr = iph->ip_src.s_addr; - - /* printf("pkt found %s\n",dd);*/ - ProcessSSDPData (sudp, dd, size - x, - &sendername, -1, (unsigned short) 5555); - } - } - } - - nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); - - } else { - syslog(LOG_ERR,"nfq_get_msg_packet_hdr failed"); - return 1; - /* from nfqueue source: 0 = ok, >0 = soft error, <0 hard error */ - } - - return 0; -} - -static void ProcessNFQUEUE(int fd){ - char buf[4096]; - - socklen_t len_r; - struct sockaddr_in sendername; - len_r = sizeof(struct sockaddr_in); - - int res = recvfrom(fd, buf, sizeof(buf), 0, - (struct sockaddr *)&sendername, &len_r); - - nfq_handle_packet(nfqHandle, buf, res); -} -#endif - -/* Functions used to communicate with miniupnpdctl */ -#ifdef USE_MINIUPNPDCTL -static int -OpenAndConfCtlUnixSocket(const char * path) -{ - struct sockaddr_un localun; - int s; - s = socket(AF_UNIX, SOCK_STREAM, 0); - localun.sun_family = AF_UNIX; - strncpy(localun.sun_path, path, - sizeof(localun.sun_path)); - if(bind(s, (struct sockaddr *)&localun, - sizeof(struct sockaddr_un)) < 0) - { - syslog(LOG_ERR, "bind(sctl): %m"); - close(s); - s = -1; - } - else if(listen(s, 5) < 0) - { - syslog(LOG_ERR, "listen(sctl): %m"); - close(s); - s = -1; - } - return s; -} - -static void -write_upnphttp_details(int fd, struct upnphttp * e) -{ - char buffer[256]; - int len; - write(fd, "HTTP :\n", 7); - while(e) - { - len = snprintf(buffer, sizeof(buffer), - "%d %d %s req_buf=%p(%dbytes) res_buf=%p(%dbytes alloc)\n", - e->socket, e->state, e->HttpVer, - e->req_buf, e->req_buflen, - e->res_buf, e->res_buf_alloclen); - write(fd, buffer, len); - e = e->entries.le_next; - } -} - -static void -write_ctlsockets_list(int fd, struct ctlelem * e) -{ - char buffer[256]; - int len; - write(fd, "CTL :\n", 6); - while(e) - { - len = snprintf(buffer, sizeof(buffer), - "struct ctlelem: socket=%d\n", e->socket); - write(fd, buffer, len); - e = e->entries.le_next; - } -} - -#ifndef DISABLE_CONFIG_FILE -static void -write_option_list(int fd) -{ - char buffer[256]; - int len; - unsigned int i; - write(fd, "Options :\n", 10); - for(i=0; iifname)) - { - /* not starting with a digit : suppose it is an interface name */ - memcpy(lan_addr->ifname, str, n); - lan_addr->ifname[n] = '\0'; - if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str), - &lan_addr->addr, &lan_addr->mask) < 0) { -#ifdef ENABLE_IPV6 - fprintf(stderr, "interface \"%s\" has no IPv4 address\n", str); - lan_addr->str[0] = '\0'; - lan_addr->addr.s_addr = htonl(0x00000000u); - lan_addr->mask.s_addr = htonl(0xffffffffu); -#else /* ENABLE_IPV6 */ - goto parselan_error; -#endif /* ENABLE_IPV6 */ - } - /*printf("%s => %s\n", lan_addr->ifname, lan_addr->str);*/ - } - else - { - if(n>15) - goto parselan_error; - memcpy(lan_addr->str, str, n); - lan_addr->str[n] = '\0'; - if(!inet_aton(lan_addr->str, &lan_addr->addr)) - goto parselan_error; - } - if(*p == '/') - { - const char * q = ++p; - while(*p && isdigit(*p)) - p++; - if(*p=='.') - { - /* parse mask in /255.255.255.0 format */ - while(*p && (*p=='.' || isdigit(*p))) - p++; - n = p - q; - if(n>15) - goto parselan_error; - memcpy(tmp, q, n); - tmp[n] = '\0'; - if(!inet_aton(tmp, &lan_addr->mask)) - goto parselan_error; - } - else - { - /* it is a /24 format */ - int nbits = atoi(q); - if(nbits > 32 || nbits < 0) - goto parselan_error; - lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0); - } - } - else if(lan_addr->mask.s_addr == 0) - { - /* by default, networks are /24 */ - lan_addr->mask.s_addr = htonl(0xffffff00u); - } -#ifdef MULTIPLE_EXTERNAL_IP - /* skip spaces */ - while(*p && isspace(*p)) - p++; - if(*p) { - /* parse the exteral ip address to associate with this subnet */ - n = 0; - while(p[n] && !isspace(*p)) - n++; - if(n<=15) { - memcpy(lan_addr->ext_ip_str, p, n); - lan_addr->ext_ip_str[n] = '\0'; - if(!inet_aton(lan_addr->ext_ip_str, &lan_addr->ext_ip_addr)) { - /* error */ - fprintf(stderr, "Error parsing address : %s\n", lan_addr->ext_ip_str); - } - } - } -#endif - if(lan_addr->ifname[0] != '\0') - { - lan_addr->index = if_nametoindex(lan_addr->ifname); - if(lan_addr->index == 0) - fprintf(stderr, "Cannot get index for network interface %s", - lan_addr->ifname); - } -#ifdef ENABLE_IPV6 - else - { - fprintf(stderr, - "Error: please specify LAN network interface by name instead of IPv4 address : %s\n", - str); - return -1; - } -#else - else - { - syslog(LOG_NOTICE, "it is advised to use network interface name instead of %s", str); - } -#endif - return 0; -parselan_error: - fprintf(stderr, "Error parsing address/mask (or interface name) : %s\n", - str); - return -1; -} - -/* fill uuidvalue_wan and uuidvalue_wcd based on uuidvalue_igd */ -void complete_uuidvalues(void) -{ - size_t len; - len = strlen(uuidvalue_igd); - memcpy(uuidvalue_wan, uuidvalue_igd, len+1); - switch(uuidvalue_wan[len-1]) { - case '9': - uuidvalue_wan[len-1] = 'a'; - break; - case 'f': - uuidvalue_wan[len-1] = '0'; - break; - default: - uuidvalue_wan[len-1]++; - } - memcpy(uuidvalue_wcd, uuidvalue_wan, len+1); - switch(uuidvalue_wcd[len-1]) { - case '9': - uuidvalue_wcd[len-1] = 'a'; - break; - case 'f': - uuidvalue_wcd[len-1] = '0'; - break; - default: - uuidvalue_wcd[len-1]++; - } -} - -/* init phase : - * 1) read configuration file - * 2) read command line arguments - * 3) daemonize - * 4) open syslog - * 5) check and write pid file - * 6) set startup time stamp - * 7) compute presentation URL - * 8) set signal handlers - * 9) init random generator (srandom()) - * 10) init redirection engine - * 11) reload mapping from leasefile */ -static int -init(int argc, char * * argv, struct runtime_vars * v) -{ - int i; - int pid; - int debug_flag = 0; - int openlog_option; - struct sigaction sa; - /*const char * logfilename = 0;*/ - const char * presurl = 0; -#ifndef DISABLE_CONFIG_FILE - int options_flag = 0; - const char * optionsfile = DEFAULT_CONFIG; -#endif /* DISABLE_CONFIG_FILE */ - struct lan_addr_s * lan_addr; - struct lan_addr_s * lan_addr2; - - /* only print usage if -h is used */ - for(i=1; iport = -1; -#ifdef ENABLE_HTTPS - v->https_port = -1; -#endif - v->notify_interval = 30; /* seconds between SSDP announces */ - v->clean_ruleset_threshold = 20; - v->clean_ruleset_interval = 0; /* interval between ruleset check. 0=disabled */ -#ifndef DISABLE_CONFIG_FILE - /* read options file first since - * command line arguments have final say */ - if(readoptionsfile(optionsfile) < 0) - { - /* only error if file exists or using -f */ - if(access(optionsfile, F_OK) == 0 || options_flag) - fprintf(stderr, "Error reading configuration file %s\n", optionsfile); - } - else - { - for(i=0; i<(int)num_options; i++) - { - switch(ary_options[i].id) - { - case UPNPEXT_IFNAME: - ext_if_name = ary_options[i].value; - break; - case UPNPEXT_IP: - use_ext_ip_addr = ary_options[i].value; - break; - case UPNPLISTENING_IP: - lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); - if (lan_addr == NULL) - { - fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m"); - break; - } - if(parselanaddr(lan_addr, ary_options[i].value) != 0) - { - fprintf(stderr, "can't parse \"%s\" as a valid " -#ifndef ENABLE_IPV6 - "LAN address or " -#endif - "interface name\n", ary_options[i].value); - free(lan_addr); - break; - } - LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); - break; -#ifdef ENABLE_IPV6 - case UPNPIPV6_LISTENING_IP: - if (inet_pton(AF_INET6, ary_options[i].value, &ipv6_bind_addr) < 1) - { - fprintf(stderr, "can't parse \"%s\" as valid IPv6 listening address", ary_options[i].value); - } - break; -#endif /* ENABLE_IPV6 */ - case UPNPPORT: - v->port = atoi(ary_options[i].value); - break; -#ifdef ENABLE_HTTPS - case UPNPHTTPSPORT: - v->https_port = atoi(ary_options[i].value); - break; -#endif - case UPNPBITRATE_UP: - upstream_bitrate = strtoul(ary_options[i].value, 0, 0); - break; - case UPNPBITRATE_DOWN: - downstream_bitrate = strtoul(ary_options[i].value, 0, 0); - break; - case UPNPPRESENTATIONURL: - presurl = ary_options[i].value; - break; -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION - case UPNPFRIENDLY_NAME: - strncpy(friendly_name, ary_options[i].value, FRIENDLY_NAME_MAX_LEN); - friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0'; - break; - case UPNPMANUFACTURER_NAME: - strncpy(manufacturer_name, ary_options[i].value, MANUFACTURER_NAME_MAX_LEN); - manufacturer_name[MANUFACTURER_NAME_MAX_LEN-1] = '\0'; - break; - case UPNPMANUFACTURER_URL: - strncpy(manufacturer_url, ary_options[i].value, MANUFACTURER_URL_MAX_LEN); - manufacturer_url[MANUFACTURER_URL_MAX_LEN-1] = '\0'; - break; - case UPNPMODEL_NAME: - strncpy(model_name, ary_options[i].value, MODEL_NAME_MAX_LEN); - model_name[MODEL_NAME_MAX_LEN-1] = '\0'; - break; - case UPNPMODEL_DESCRIPTION: - strncpy(model_description, ary_options[i].value, MODEL_DESCRIPTION_MAX_LEN); - model_description[MODEL_DESCRIPTION_MAX_LEN-1] = '\0'; - break; - case UPNPMODEL_URL: - strncpy(model_url, ary_options[i].value, MODEL_URL_MAX_LEN); - model_url[MODEL_URL_MAX_LEN-1] = '\0'; - break; -#endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */ -#ifdef USE_NETFILTER - case UPNPFORWARDCHAIN: - miniupnpd_forward_chain = ary_options[i].value; - break; - case UPNPNATCHAIN: - miniupnpd_nat_chain = ary_options[i].value; - break; - case UPNPNATPOSTCHAIN: - miniupnpd_nat_postrouting_chain = ary_options[i].value; - break; -#endif /* USE_NETFILTER */ - case UPNPNOTIFY_INTERVAL: - v->notify_interval = atoi(ary_options[i].value); - break; - case UPNPSYSTEM_UPTIME: - if(strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(SYSUPTIMEMASK); /*sysuptime = 1;*/ - break; -#if defined(USE_PF) || defined(USE_IPF) - case UPNPPACKET_LOG: - if(strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(LOGPACKETSMASK); /*logpackets = 1;*/ - break; -#endif /* defined(USE_PF) || defined(USE_IPF) */ - case UPNPUUID: - strncpy(uuidvalue_igd+5, ary_options[i].value, - strlen(uuidvalue_igd+5) + 1); - complete_uuidvalues(); - break; - case UPNPSERIAL: - strncpy(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN); - serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0'; - break; - case UPNPMODEL_NUMBER: - strncpy(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN); - modelnumber[MODELNUMBER_MAX_LEN-1] = '\0'; - break; - case UPNPCLEANTHRESHOLD: - v->clean_ruleset_threshold = atoi(ary_options[i].value); - break; - case UPNPCLEANINTERVAL: - v->clean_ruleset_interval = atoi(ary_options[i].value); - break; -#ifdef USE_PF - case UPNPANCHOR: - anchor_name = ary_options[i].value; - break; - case UPNPQUEUE: - queue = ary_options[i].value; - break; - case UPNPTAG: - tag = ary_options[i].value; - break; -#endif /* USE_PF */ -#ifdef ENABLE_NATPMP - case UPNPENABLENATPMP: - if(strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(ENABLENATPMPMASK); /*enablenatpmp = 1;*/ - else - if(atoi(ary_options[i].value)) - SETFLAG(ENABLENATPMPMASK); - /*enablenatpmp = atoi(ary_options[i].value);*/ - break; -#endif /* ENABLE_NATPMP */ -#ifdef ENABLE_PCP - case UPNPPCPMINLIFETIME: - min_lifetime = atoi(ary_options[i].value); - if (min_lifetime > 120 ) { - min_lifetime = 120; - } - break; - case UPNPPCPMAXLIFETIME: - max_lifetime = atoi(ary_options[i].value); - if (max_lifetime > 86400 ) { - max_lifetime = 86400; - } - break; - case UPNPPCPALLOWTHIRDPARTY: - if(strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(PCP_ALLOWTHIRDPARTYMASK); - break; -#endif /* ENABLE_PCP */ -#ifdef PF_ENABLE_FILTER_RULES - case UPNPQUICKRULES: - if(strcmp(ary_options[i].value, "no") == 0) - SETFLAG(PFNOQUICKRULESMASK); - break; -#endif /* PF_ENABLE_FILTER_RULES */ - case UPNPENABLE: - if(strcmp(ary_options[i].value, "yes") != 0) - CLEARFLAG(ENABLEUPNPMASK); - break; - case UPNPSECUREMODE: - if(strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(SECUREMODEMASK); - break; -#ifdef ENABLE_LEASEFILE - case UPNPLEASEFILE: - lease_file = ary_options[i].value; - break; -#endif /* ENABLE_LEASEFILE */ - case UPNPMINISSDPDSOCKET: - minissdpdsocketpath = ary_options[i].value; - break; -#ifdef IGD_V2 - case UPNPFORCEIGDDESCV1: - if (strcmp(ary_options[i].value, "yes") == 0) - SETFLAG(FORCEIGDDESCV1MASK); - else if (strcmp(ary_options[i].value, "no") != 0 ) { - fprintf(stderr, "force_igd_desc_v1 can only be yes or no\n"); - } - break; -#endif - default: - fprintf(stderr, "Unknown option in file %s\n", - optionsfile); - } - } -#ifdef ENABLE_PCP - /* if lifetimes are inverse */ - if (min_lifetime >= max_lifetime) { - fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime); - fprintf(stderr, "Check your configuration file.\n"); - return 1; - } -#endif /* ENABLE_PCP */ - } -#endif /* DISABLE_CONFIG_FILE */ - - /* command line arguments processing */ - for(i=1; inotify_interval = atoi(argv[++i]); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; - case 'r': - if(i+1 < argc) - v->clean_ruleset_interval = atoi(argv[++i]); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; - case 'u': - if(i+1 < argc) { - strncpy(uuidvalue_igd+5, argv[++i], strlen(uuidvalue_igd+5) + 1); - complete_uuidvalues(); - } else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION - case 'z': - if(i+1 < argc) - strncpy(friendly_name, argv[++i], FRIENDLY_NAME_MAX_LEN); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - friendly_name[FRIENDLY_NAME_MAX_LEN-1] = '\0'; - break; -#endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */ - case 's': - if(i+1 < argc) - strncpy(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - serialnumber[SERIALNUMBER_MAX_LEN-1] = '\0'; - break; - case 'm': - if(i+1 < argc) - strncpy(modelnumber, argv[++i], MODELNUMBER_MAX_LEN); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - modelnumber[MODELNUMBER_MAX_LEN-1] = '\0'; - break; -#ifdef ENABLE_NATPMP - case 'N': - /*enablenatpmp = 1;*/ - SETFLAG(ENABLENATPMPMASK); - break; -#endif /* ENABLE_NATPMP */ - case 'U': - /*sysuptime = 1;*/ - SETFLAG(SYSUPTIMEMASK); - break; - /*case 'l': - logfilename = argv[++i]; - break;*/ -#if defined(USE_PF) || defined(USE_IPF) - case 'L': - /*logpackets = 1;*/ - SETFLAG(LOGPACKETSMASK); - break; -#endif /* defined(USE_PF) || defined(USE_IPF) */ - case 'S': - SETFLAG(SECUREMODEMASK); - break; - case 'i': - if(i+1 < argc) - ext_if_name = argv[++i]; - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; -#ifdef USE_PF - case 'q': - if(i+1 < argc) - queue = argv[++i]; - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; - case 'T': - if(i+1 < argc) - tag = argv[++i]; - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; -#endif /* USE_PF */ - case 'p': - if(i+1 < argc) - v->port = atoi(argv[++i]); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; -#ifdef ENABLE_HTTPS - case 'H': - if(i+1 < argc) - v->https_port = atoi(argv[++i]); - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; -#endif /* ENABLE_HTTPS */ -#ifdef ENABLE_NFQUEUE - case 'Q': - if(i+1list.le_next) - { - if (0 == strncmp(lan_addr2->str, lan_addr->str, 15)) - break; - } - if (lan_addr2 == NULL) - LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); - } - else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); -#else /* #ifndef MULTIPLE_EXTERNAL_IP */ - if(i+2 < argc) - { - char *val = calloc((strlen(argv[i+1]) + strlen(argv[i+2]) + 2), sizeof(char)); - if (val == NULL) - { - fprintf(stderr, "memory allocation error for listen address storage\n"); - break; - } - sprintf(val, "%s %s", argv[i+1], argv[i+2]); - - lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); - if (lan_addr == NULL) - { - fprintf(stderr, "malloc(sizeof(struct lan_addr_s)): %m"); - free(val); - break; - } - if(parselanaddr(lan_addr, val) != 0) - { - fprintf(stderr, "can't parse \"%s\" as a valid LAN address or interface name\n", val); - free(lan_addr); - free(val); - break; - } - /* check if we already have this address */ - for(lan_addr2 = lan_addrs.lh_first; lan_addr2 != NULL; lan_addr2 = lan_addr2->list.le_next) - { - if (0 == strncmp(lan_addr2->str, lan_addr->str, 15)) - break; - } - if (lan_addr2 == NULL) - LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); - - free(val); - i+=2; - } - else - fprintf(stderr, "Option -%c takes two arguments.\n", argv[i][1]); -#endif /* #ifndef MULTIPLE_EXTERNAL_IP */ - break; - case 'A': - if(i+1 < argc) { - void * tmp; - tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1)); - if(tmp == NULL) { - fprintf(stderr, "memory allocation error for permission\n"); - } else { - upnppermlist = tmp; - if(read_permission_line(upnppermlist + num_upnpperm, argv[++i]) >= 0) { - num_upnpperm++; - } else { - fprintf(stderr, "Permission rule parsing error :\n%s\n", argv[i]); - } - } - } else - fprintf(stderr, "Option -%c takes one argument.\n", argv[i][1]); - break; - case 'f': - i++; /* discarding, the config file is already read */ - break; - default: - fprintf(stderr, "Unknown option: %s\n", argv[i]); - } - } - if(!ext_if_name || !lan_addrs.lh_first) - { - /* bad configuration */ - goto print_usage; - } - - if(debug_flag) - { - pid = getpid(); - } - else - { -#ifdef USE_DAEMON - if(daemon(0, 0)<0) { - perror("daemon()"); - } - pid = getpid(); -#else - pid = daemonize(); -#endif - } - - openlog_option = LOG_PID|LOG_CONS; - if(debug_flag) - { - openlog_option |= LOG_PERROR; /* also log on stderr */ - } - - openlog("miniupnpd", openlog_option, LOG_MINIUPNPD); - - if(!debug_flag) - { - /* speed things up and ignore LOG_INFO and LOG_DEBUG */ - setlogmask(LOG_UPTO(LOG_NOTICE)); - } - - if(checkforrunning(pidfilename) < 0) - { - syslog(LOG_ERR, "MiniUPnPd is already running. EXITING"); - return 1; - } - -#ifdef TOMATO - syslog(LOG_NOTICE, "version " MINIUPNPD_VERSION " started"); -#endif /* TOMATO */ - - set_startup_time(); - - /* presentation url */ - if(presurl) - { - strncpy(presentationurl, presurl, PRESENTATIONURL_MAX_LEN); - presentationurl[PRESENTATIONURL_MAX_LEN-1] = '\0'; - } - else - { - snprintf(presentationurl, PRESENTATIONURL_MAX_LEN, - "http://%s/", lan_addrs.lh_first->str); - /*"http://%s:%d/", lan_addrs.lh_first->str, 80);*/ - } - - /* set signal handler */ - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = sigterm; - - if(sigaction(SIGTERM, &sa, NULL) < 0) - { - syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGTERM"); - return 1; - } - if(sigaction(SIGINT, &sa, NULL) < 0) - { - syslog(LOG_ERR, "Failed to set %s handler. EXITING", "SIGINT"); - return 1; - } -#ifdef TOMATO - sa.sa_handler = sigusr2; - sigaction(SIGUSR2, &sa, NULL); - if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) -#else /* TOMATO */ - sa.sa_handler = SIG_IGN; - if(sigaction(SIGPIPE, &sa, NULL) < 0) -#endif /* TOMATO */ - { - syslog(LOG_ERR, "Failed to ignore SIGPIPE signals"); - } - sa.sa_handler = sigusr1; - if(sigaction(SIGUSR1, &sa, NULL) < 0) - { - syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1"); - } -#if !defined(TOMATO) && defined(ENABLE_LEASEFILE) && defined(LEASEFILE_USE_REMAINING_TIME) - sa.sa_handler = sigusr2; - if(sigaction(SIGUSR2, &sa, NULL) < 0) - { - syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR2"); - } -#endif /* !TOMATO && ENABLE_LEASEFILE && LEASEFILE_USE_REMAINING_TIME */ - - /* initialize random number generator */ - srandom((unsigned int)time(NULL)); -#ifdef RANDOMIZE_URLS - snprintf(random_url, RANDOM_URL_MAX_LEN, "%08lx", random()); -#endif /* RANDOMIZE_URLS */ - - /* initialize redirection engine (and pinholes) */ - if(init_redirect() < 0) - { - syslog(LOG_ERR, "Failed to init redirection engine. EXITING"); - return 1; - } -#ifdef ENABLE_UPNPPINHOLE -#ifdef USE_NETFILTER - init_iptpinhole(); -#endif -#endif - - if(writepidfile(pidfilename, pid) < 0) - pidfilename = NULL; - -#ifdef ENABLE_LEASEFILE - /*remove(lease_file);*/ - syslog(LOG_INFO, "Reloading rules from lease file"); - reload_from_lease_file(); -#endif - -#ifdef TOMATO - tomato_load(); -#endif /* TOMATO */ - - return 0; -print_usage: - fprintf(stderr, "Usage:\n\t" - "%s " -#ifndef DISABLE_CONFIG_FILE - "[-f config_file] " -#endif - "[-i ext_ifname] [-o ext_ip]\n" -#ifndef MULTIPLE_EXTERNAL_IP - "\t\t[-a listening_ip]" -#else - "\t\t[-a listening_ip ext_ip]" -#endif -#ifdef ENABLE_HTTPS - " [-H https_port]" -#endif - " [-p port] [-d]" -#if defined(USE_PF) || defined(USE_IPF) - " [-L]" -#endif - " [-U] [-S]" -#ifdef ENABLE_NATPMP - " [-N]" -#endif - "\n" - /*"[-l logfile] " not functionnal */ - "\t\t[-u uuid] [-s serial] [-m model_number] \n" - "\t\t[-t notify_interval] [-P pid_filename] " -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION - "[-z fiendly_name]" -#endif - "\n\t\t[-B down up] [-w url] [-r clean_ruleset_interval]\n" -#ifdef USE_PF - "\t\t[-q queue] [-T tag]\n" -#endif -#ifdef ENABLE_NFQUEUE - "\t\t[-Q queue] [-n name]\n" -#endif - "\t\t[-A \"permission rule\"] [-b BOOTID]" -#ifdef IGD_V2 - " [-1]" -#endif - "\n" - "\nNotes:\n\tThere can be one or several listening_ips.\n" - "\tNotify interval is in seconds. Default is 30 seconds.\n" - "\tDefault pid file is '%s'.\n" - "\tDefault config file is '%s'.\n" - "\tWith -d miniupnpd will run as a standard program.\n" -#if defined(USE_PF) || defined(USE_IPF) - "\t-L sets packet log in pf and ipf on.\n" -#endif - "\t-S sets \"secure\" mode : clients can only add mappings to their own ip\n" - "\t-U causes miniupnpd to report system uptime instead " - "of daemon uptime.\n" -#ifdef ENABLE_NATPMP - "\t-N enables NAT-PMP functionality.\n" -#endif - "\t-B sets bitrates reported by daemon in bits per second.\n" - "\t-w sets the presentation url. Default is http address on port 80\n" -#ifdef USE_PF - "\t-q sets the ALTQ queue in pf.\n" - "\t-T sets the tag name in pf.\n" -#endif -#ifdef ENABLE_NFQUEUE - "\t-Q sets the queue number that is used by NFQUEUE.\n" - "\t-n sets the name of the interface(s) that packets will arrive on.\n" -#endif - "\t-A use following syntax for permission rules :\n" - "\t (allow|deny) (external port range) ip/mask (internal port range)\n" - "\texamples :\n" - "\t \"allow 1024-65535 192.168.1.0/24 1024-65535\"\n" - "\t \"deny 0-65535 0.0.0.0/0 0-65535\"\n" - "\t-b sets the value of BOOTID.UPNP.ORG SSDP header\n" -#ifdef IGD_V2 - "\t-1 force reporting IGDv1 in rootDesc *use with care*\n" -#endif - "\t-h prints this help and quits.\n" - "", argv[0], pidfilename, DEFAULT_CONFIG); - return 1; -} - -/* === main === */ -/* process HTTP or SSDP requests */ -int -main(int argc, char * * argv) -{ - int i; - int shttpl = -1; /* socket for HTTP */ -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */ -#endif -#ifdef ENABLE_HTTPS - int shttpsl = -1; /* socket for HTTPS */ -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - int shttpsl_v4 = -1; /* socket for HTTPS (ipv4 only) */ -#endif -#endif /* ENABLE_HTTPS */ - int sudp = -1; /* IP v4 socket for receiving SSDP */ -#ifdef ENABLE_IPV6 - int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ -#endif -#ifdef ENABLE_NATPMP - int * snatpmp = NULL; /* also used for PCP */ -#endif -#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) - int spcp_v6 = -1; -#endif -#ifdef ENABLE_NFQUEUE - int nfqh = -1; -#endif -#ifdef USE_IFACEWATCHER - int sifacewatcher = -1; -#endif - - int * snotify = NULL; - int addr_count; - LIST_HEAD(httplisthead, upnphttp) upnphttphead; - struct upnphttp * e = 0; - struct upnphttp * next; - fd_set readset; /* for select() */ - fd_set writeset; - struct timeval timeout, timeofday, lasttimeofday = {0, 0}; - int max_fd = -1; -#ifdef USE_MINIUPNPDCTL - int sctl = -1; - LIST_HEAD(ctlstructhead, ctlelem) ctllisthead; - struct ctlelem * ectl; - struct ctlelem * ectlnext; -#endif - struct runtime_vars v; - /* variables used for the unused-rule cleanup process */ - struct rule_state * rule_list = 0; - struct timeval checktime = {0, 0}; - struct lan_addr_s * lan_addr; -#ifdef ENABLE_UPNPPINHOLE - unsigned int next_pinhole_ts; -#endif - - if(init(argc, argv, &v) != 0) - return 1; -#ifdef ENABLE_HTTPS - if(init_ssl() < 0) - return 1; -#endif /* ENABLE_HTTPS */ - /* count lan addrs */ - addr_count = 0; - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - addr_count++; - if(addr_count > 0) { -#ifndef ENABLE_IPV6 - snotify = calloc(addr_count, sizeof(int)); -#else - /* one for IPv4, one for IPv6 */ - snotify = calloc(addr_count * 2, sizeof(int)); -#endif - } -#ifdef ENABLE_NATPMP - if(addr_count > 0) { - snatpmp = malloc(addr_count * sizeof(int)); - for(i = 0; i < addr_count; i++) - snatpmp[i] = -1; - } -#endif - - LIST_INIT(&upnphttphead); -#ifdef USE_MINIUPNPDCTL - LIST_INIT(&ctllisthead); -#endif - - if( -#ifdef ENABLE_NATPMP - !GETFLAG(ENABLENATPMPMASK) && !GETFLAG(ENABLEUPNPMASK) -#else - !GETFLAG(ENABLEUPNPMASK) -#endif - ) { - syslog(LOG_ERR, "Why did you run me anyway?"); - return 0; - } - - syslog(LOG_INFO, "version " MINIUPNPD_VERSION " starting%s%sext if %s BOOTID=%u", -#ifdef ENABLE_NATPMP -#ifdef ENABLE_PCP - GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ", -#else - GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ", -#endif -#else - " ", -#endif - GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "", - ext_if_name, upnp_bootid); - - if(GETFLAG(ENABLEUPNPMASK)) - { - unsigned short listen_port; - listen_port = (v.port > 0) ? v.port : 0; - /* open socket for HTTP connections. Listen on the 1st LAN address */ -#ifdef ENABLE_IPV6 - shttpl = OpenAndConfHTTPSocket(&listen_port, 1); -#else /* ENABLE_IPV6 */ - shttpl = OpenAndConfHTTPSocket(&listen_port); -#endif /* ENABLE_IPV6 */ - if(shttpl < 0) - { - syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING"); - return 1; - } - v.port = listen_port; - syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if(!GETFLAG(IPV6DISABLEDMASK)) - { - shttpl_v4 = OpenAndConfHTTPSocket(&listen_port, 0); - if(shttpl_v4 < 0) - { - syslog(LOG_ERR, "Failed to open socket for HTTP on port %d (IPv4). EXITING", v.port); - return 1; - } - } -#endif /* V6SOCKETS_ARE_V6ONLY */ -#ifdef ENABLE_HTTPS - /* https */ - listen_port = (v.https_port > 0) ? v.https_port : 0; -#ifdef ENABLE_IPV6 - shttpsl = OpenAndConfHTTPSocket(&listen_port, 1); -#else /* ENABLE_IPV6 */ - shttpsl = OpenAndConfHTTPSocket(&listen_port); -#endif /* ENABLE_IPV6 */ - if(shttpl < 0) - { - syslog(LOG_ERR, "Failed to open socket for HTTPS. EXITING"); - return 1; - } - v.https_port = listen_port; - syslog(LOG_NOTICE, "HTTPS listening on port %d", v.https_port); -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - shttpsl_v4 = OpenAndConfHTTPSocket(&listen_port, 0); - if(shttpsl_v4 < 0) - { - syslog(LOG_ERR, "Failed to open socket for HTTPS on port %d (IPv4). EXITING", v.https_port); - return 1; - } -#endif /* V6SOCKETS_ARE_V6ONLY */ -#endif /* ENABLE_HTTPS */ -#ifdef ENABLE_IPV6 - if(!GETFLAG(IPV6DISABLEDMASK)) { - if(find_ipv6_addr(lan_addrs.lh_first ? lan_addrs.lh_first->ifname : NULL, - ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) { - syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s", - ipv6_addr_for_http_with_brackets); - } else { - memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); - syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6"); - SETFLAG(IPV6DISABLEDMASK); - } - } -#endif /* ENABLE_IPV6 */ - - /* open socket for SSDP connections */ - sudp = OpenAndConfSSDPReceiveSocket(0); - if(sudp < 0) - { - syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd"); - if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) { - syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING"); - return 1; - } - } -#ifdef ENABLE_IPV6 - if(!GETFLAG(IPV6DISABLEDMASK)) - { - sudpv6 = OpenAndConfSSDPReceiveSocket(1); - if(sudpv6 < 0) - { - syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); - } - } -#endif - - /* open socket for sending notifications */ - if(OpenAndConfSSDPNotifySockets(snotify) < 0) - { - syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify " - "messages. EXITING"); - return 1; - } - -#ifdef USE_IFACEWATCHER - /* open socket for kernel notifications about new network interfaces */ - if (sudp >= 0) - { - sifacewatcher = OpenAndConfInterfaceWatchSocket(); - if (sifacewatcher < 0) - { - syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications"); - } - } -#endif - } - -#ifdef ENABLE_NATPMP - /* open socket for NAT PMP traffic */ - if(GETFLAG(ENABLENATPMPMASK)) - { - if(OpenAndConfNATPMPSockets(snatpmp) < 0) -#ifdef ENABLE_PCP - { - syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP."); - } else { - syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u", - NATPMP_PORT); - } -#else - { - syslog(LOG_ERR, "Failed to open sockets for NAT PMP."); - } else { - syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", - NATPMP_PORT); - } -#endif - } -#endif - -#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) - if(!GETFLAG(IPV6DISABLEDMASK)) { - spcp_v6 = OpenAndConfPCPv6Socket(); - } -#endif - - /* for miniupnpdctl */ -#ifdef USE_MINIUPNPDCTL - sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl"); -#endif - -#ifdef ENABLE_NFQUEUE - if ( nfqueue != -1 && n_nfqix > 0) { - nfqh = OpenAndConfNFqueue(); - if(nfqh < 0) { - syslog(LOG_ERR, "Failed to open fd for NFQUEUE."); - return 1; - } else { - syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue); - } - } -#endif - -#ifdef TOMATO - tomato_helper(); -#endif - - /* main loop */ - while(!quitting) - { -#ifdef USE_TIME_AS_BOOTID - /* Correct startup_time if it was set with a RTC close to 0 */ - if((upnp_bootid<60*60*24) && (time(NULL)>60*60*24)) - { - upnp_bootid = time(NULL); - } -#endif -#if !defined(TOMATO) && defined(ENABLE_LEASEFILE) && defined(LEASEFILE_USE_REMAINING_TIME) - if(should_rewrite_leasefile) - { - lease_file_rewrite(); - should_rewrite_leasefile = 0; - } -#endif /* !TOMATO && ENABLE_LEASEFILE && LEASEFILE_USE_REMAINING_TIME */ - /* send public address change notifications if needed */ - if(should_send_public_address_change_notif) - { - syslog(LOG_INFO, "should send external iface address change notification(s)"); -#ifdef ENABLE_NATPMP - if(GETFLAG(ENABLENATPMPMASK)) - SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count); -#endif -#ifdef ENABLE_EVENTS - if(GETFLAG(ENABLEUPNPMASK)) - { - upnp_event_var_change_notify(EWanIPC); - } -#endif -#ifdef ENABLE_PCP - if(GETFLAG(ENABLENATPMPMASK)) - { -#ifdef ENABLE_IPV6 - PCPPublicAddressChanged(snatpmp, addr_count, spcp_v6); -#else /* IPv4 only */ - PCPPublicAddressChanged(snatpmp, addr_count); -#endif - } -#endif - should_send_public_address_change_notif = 0; - } - /* Check if we need to send SSDP NOTIFY messages and do it if - * needed */ - if(upnp_gettimeofday(&timeofday) < 0) - { - syslog(LOG_ERR, "gettimeofday(): %m"); - timeout.tv_sec = v.notify_interval; - timeout.tv_usec = 0; - } - else - { - /* the comparaison is not very precise but who cares ? */ - if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval)) - { - if (GETFLAG(ENABLEUPNPMASK)) - SendSSDPNotifies2(snotify, - (unsigned short)v.port, -#ifdef ENABLE_HTTPS - (unsigned short)v.https_port, -#endif - v.notify_interval << 1); - memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval)); - timeout.tv_sec = v.notify_interval; - timeout.tv_usec = 0; - } - else - { - timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval - - timeofday.tv_sec; - if(timeofday.tv_usec > lasttimeofday.tv_usec) - { - timeout.tv_usec = 1000000 + lasttimeofday.tv_usec - - timeofday.tv_usec; - timeout.tv_sec--; - } - else - { - timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec; - } - } - } - /* remove unused rules */ - if( v.clean_ruleset_interval - && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval)) - { - if(rule_list) - { - remove_unused_rules(rule_list); - rule_list = NULL; - } - else - { - rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold); - } - memcpy(&checktime, &timeofday, sizeof(struct timeval)); - } - /* Remove expired port mappings, based on UPnP IGD LeaseDuration - * or NAT-PMP lifetime) */ - if(nextruletoclean_timestamp - && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp)) - { - syslog(LOG_DEBUG, "cleaning expired Port Mappings"); - get_upnp_rules_state_list(0); - } - if(nextruletoclean_timestamp - && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))) - { - timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec; - timeout.tv_usec = 0; - syslog(LOG_DEBUG, "setting timeout to %u sec", - (unsigned)timeout.tv_sec); - } -#ifdef ENABLE_UPNPPINHOLE - /* Clean up expired IPv6 PinHoles */ - next_pinhole_ts = 0; - upnp_clean_expired_pinholes(&next_pinhole_ts); - if(next_pinhole_ts && - timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) { - timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec; - timeout.tv_usec = 0; - } -#endif /* ENABLE_UPNPPINHOLE */ - - /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ - FD_ZERO(&readset); - FD_ZERO(&writeset); - - if (sudp >= 0) - { - FD_SET(sudp, &readset); - max_fd = MAX( max_fd, sudp); -#ifdef USE_IFACEWATCHER - if (sifacewatcher >= 0) - { - FD_SET(sifacewatcher, &readset); - max_fd = MAX(max_fd, sifacewatcher); - } -#endif - } - if (shttpl >= 0) - { - FD_SET(shttpl, &readset); - max_fd = MAX( max_fd, shttpl); - } -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if (shttpl_v4 >= 0) - { - FD_SET(shttpl_v4, &readset); - max_fd = MAX( max_fd, shttpl_v4); - } -#endif -#ifdef ENABLE_HTTPS - if (shttpsl >= 0) - { - FD_SET(shttpsl, &readset); - max_fd = MAX( max_fd, shttpsl); - } -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if (shttpsl_v4 >= 0) - { - FD_SET(shttpsl_v4, &readset); - max_fd = MAX( max_fd, shttpsl_v4); - } -#endif -#endif /* ENABLE_HTTPS */ -#ifdef ENABLE_IPV6 - if (sudpv6 >= 0) - { - FD_SET(sudpv6, &readset); - max_fd = MAX( max_fd, sudpv6); - } -#endif - -#ifdef ENABLE_NFQUEUE - if (nfqh >= 0) - { - FD_SET(nfqh, &readset); - max_fd = MAX( max_fd, nfqh); - } -#endif - - i = 0; /* active HTTP connections count */ - for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) - { - if(e->socket >= 0) - { - if(e->state <= EWaitingForHttpContent) - FD_SET(e->socket, &readset); - else if(e->state == ESendingAndClosing) - FD_SET(e->socket, &writeset); - else - continue; - max_fd = MAX(max_fd, e->socket); - i++; - } - } - /* for debug */ -#ifdef DEBUG - if(i > 1) - { - syslog(LOG_DEBUG, "%d active incoming HTTP connections", i); - } -#endif -#ifdef ENABLE_NATPMP - for(i=0; i= 0) { - FD_SET(snatpmp[i], &readset); - max_fd = MAX( max_fd, snatpmp[i]); - } - } -#endif -#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) - if(spcp_v6 >= 0) { - FD_SET(spcp_v6, &readset); - max_fd = MAX(max_fd, spcp_v6); - } -#endif -#ifdef USE_MINIUPNPDCTL - if(sctl >= 0) { - FD_SET(sctl, &readset); - max_fd = MAX( max_fd, sctl); - } - - for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next) - { - if(ectl->socket >= 0) { - FD_SET(ectl->socket, &readset); - max_fd = MAX( max_fd, ectl->socket); - } - } -#endif - -#ifdef ENABLE_EVENTS - upnpevents_selectfds(&readset, &writeset, &max_fd); -#endif - - /* queued "sendto" */ - { - struct timeval next_send; - i = get_next_scheduled_send(&next_send); - if(i > 0) { -#ifdef DEBUG - syslog(LOG_DEBUG, "%d queued sendto", i); -#endif - i = get_sendto_fds(&writeset, &max_fd, &timeofday); - if(timeofday.tv_sec > next_send.tv_sec || - (timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) { - if(i > 0) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - } - } else { - struct timeval tmp_timeout; - tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec); - tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec); - if(tmp_timeout.tv_usec < 0) { - tmp_timeout.tv_usec += 1000000; - tmp_timeout.tv_sec--; - } - if(timeout.tv_sec > tmp_timeout.tv_sec - || (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) { - timeout.tv_sec = tmp_timeout.tv_sec; - timeout.tv_usec = tmp_timeout.tv_usec; - } - } - } - } - - if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) - { - if(quitting) goto shutdown; -#ifdef TOMATO - if (gotusr2) - { - gotusr2 = 0; - tomato_helper(); - continue; - } -#endif /* TOMATO */ - if(errno == EINTR) continue; /* interrupted by a signal, start again */ - syslog(LOG_ERR, "select(all): %m"); - syslog(LOG_ERR, "Failed to select open sockets. EXITING"); - return 1; /* very serious cause of error */ - } - i = try_sendto(&writeset); - if(i < 0) { - syslog(LOG_ERR, "try_sendto failed to send %d packets", -i); - } -#ifdef USE_MINIUPNPDCTL - for(ectl = ctllisthead.lh_first; ectl;) - { - ectlnext = ectl->entries.le_next; - if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset)) - { - char buf[256]; - int l; - l = read(ectl->socket, buf, sizeof(buf)); - if(l > 0) - { - /*write(ectl->socket, buf, l);*/ - write_command_line(ectl->socket, argc, argv); -#ifndef DISABLE_CONFIG_FILE - write_option_list(ectl->socket); -#endif - write_permlist(ectl->socket, upnppermlist, num_upnpperm); - write_upnphttp_details(ectl->socket, upnphttphead.lh_first); - write_ctlsockets_list(ectl->socket, ctllisthead.lh_first); - write_ruleset_details(ectl->socket); -#ifdef ENABLE_EVENTS - write_events_details(ectl->socket); -#endif - /* close the socket */ - close(ectl->socket); - ectl->socket = -1; - } - else - { - close(ectl->socket); - ectl->socket = -1; - } - } - if(ectl->socket < 0) - { - LIST_REMOVE(ectl, entries); - free(ectl); - } - ectl = ectlnext; - } - if((sctl >= 0) && FD_ISSET(sctl, &readset)) - { - int s; - struct sockaddr_un clientname; - struct ctlelem * tmp; - socklen_t clientnamelen = sizeof(struct sockaddr_un); - /*syslog(LOG_DEBUG, "sctl!");*/ - s = accept(sctl, (struct sockaddr *)&clientname, - &clientnamelen); - syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path); - tmp = malloc(sizeof(struct ctlelem)); - if (tmp == NULL) - { - syslog(LOG_ERR, "Unable to allocate memory for ctlelem in main()"); - close(s); - } - else - { - tmp->socket = s; - LIST_INSERT_HEAD(&ctllisthead, tmp, entries); - } - } -#endif -#ifdef ENABLE_EVENTS - upnpevents_processfds(&readset, &writeset); -#endif -#ifdef ENABLE_NATPMP - /* process NAT-PMP packets */ - for(i=0; i= 0) && FD_ISSET(snatpmp[i], &readset)) - { - unsigned char msg_buff[PCP_MAX_LEN]; - struct sockaddr_in senderaddr; - socklen_t senderaddrlen; - int len; - memset(msg_buff, 0, PCP_MAX_LEN); - senderaddrlen = sizeof(senderaddr); - len = ReceiveNATPMPOrPCPPacket(snatpmp[i], - (struct sockaddr *)&senderaddr, - &senderaddrlen, - NULL, - msg_buff, sizeof(msg_buff)); - if (len < 1) - continue; -#ifdef ENABLE_PCP - if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */ - /* Check if the packet is coming from a LAN to enforce RFC6886 : - * The NAT gateway MUST NOT accept mapping requests destined to the NAT - * gateway's external IP address or received on its external network - * interface. Only packets received on the internal interface(s) with a - * destination address matching the internal address(es) of the NAT - * gateway should be allowed. */ - /* TODO : move to ProcessIncomingNATPMPPacket() ? */ - lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr); - if(lan_addr == NULL) { - char sender_str[64]; - sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str)); - syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring", - sender_str); - continue; - } - ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, - &senderaddr); - } else { /* everything else can be PCP */ - ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len, - (struct sockaddr *)&senderaddr, NULL); - } - -#else - /* Check if the packet is coming from a LAN to enforce RFC6886 : - * The NAT gateway MUST NOT accept mapping requests destined to the NAT - * gateway's external IP address or received on its external network - * interface. Only packets received on the internal interface(s) with a - * destination address matching the internal address(es) of the NAT - * gateway should be allowed. */ - /* TODO : move to ProcessIncomingNATPMPPacket() ? */ - lan_addr = get_lan_for_peer((struct sockaddr *)&senderaddr); - if(lan_addr == NULL) { - char sender_str[64]; - sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str)); - syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring", - sender_str); - continue; - } - ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr); -#endif - } - } -#endif -#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) - /* in IPv6, only PCP is supported, not NAT-PMP */ - if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset)) - { - unsigned char msg_buff[PCP_MAX_LEN]; - struct sockaddr_in6 senderaddr; - socklen_t senderaddrlen; - struct sockaddr_in6 receiveraddr; - int len; - memset(msg_buff, 0, PCP_MAX_LEN); - senderaddrlen = sizeof(senderaddr); - len = ReceiveNATPMPOrPCPPacket(spcp_v6, - (struct sockaddr *)&senderaddr, - &senderaddrlen, - &receiveraddr, - msg_buff, sizeof(msg_buff)); - if(len >= 1) - ProcessIncomingPCPPacket(spcp_v6, msg_buff, len, - (struct sockaddr *)&senderaddr, - &receiveraddr); - } -#endif - /* process SSDP packets */ - if(sudp >= 0 && FD_ISSET(sudp, &readset)) - { - /*syslog(LOG_INFO, "Received UDP Packet");*/ -#ifdef ENABLE_HTTPS - ProcessSSDPRequest(sudp, (unsigned short)v.port, (unsigned short)v.https_port); -#else - ProcessSSDPRequest(sudp, (unsigned short)v.port); -#endif - } -#ifdef ENABLE_IPV6 - if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset)) - { - syslog(LOG_INFO, "Received UDP Packet (IPv6)"); -#ifdef ENABLE_HTTPS - ProcessSSDPRequest(sudpv6, (unsigned short)v.port, (unsigned short)v.https_port); -#else - ProcessSSDPRequest(sudpv6, (unsigned short)v.port); -#endif - } -#endif -#ifdef USE_IFACEWATCHER - /* process kernel notifications */ - if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset)) - ProcessInterfaceWatchNotify(sifacewatcher); -#endif - - /* process active HTTP connections */ - /* LIST_FOREACH macro is not available under linux */ - for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) - { - if(e->socket >= 0) - { - if(FD_ISSET(e->socket, &readset) || - FD_ISSET(e->socket, &writeset)) - { - Process_upnphttp(e); - } - } - } - /* process incoming HTTP connections */ - if(shttpl >= 0 && FD_ISSET(shttpl, &readset)) - { - struct upnphttp * tmp; - tmp = ProcessIncomingHTTP(shttpl, "HTTP"); - if(tmp) - { - LIST_INSERT_HEAD(&upnphttphead, tmp, entries); - } - } -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset)) - { - struct upnphttp * tmp; - tmp = ProcessIncomingHTTP(shttpl_v4, "HTTP"); - if(tmp) - { - LIST_INSERT_HEAD(&upnphttphead, tmp, entries); - } - } -#endif -#ifdef ENABLE_HTTPS - if(shttpsl >= 0 && FD_ISSET(shttpsl, &readset)) - { - struct upnphttp * tmp; - tmp = ProcessIncomingHTTP(shttpsl, "HTTPS"); - if(tmp) - { - InitSSL_upnphttp(tmp); - LIST_INSERT_HEAD(&upnphttphead, tmp, entries); - } - } -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if(shttpsl_v4 >= 0 && FD_ISSET(shttpsl_v4, &readset)) - { - struct upnphttp * tmp; - tmp = ProcessIncomingHTTP(shttpsl_v4, "HTTPS"); - if(tmp) - { - InitSSL_upnphttp(tmp); - LIST_INSERT_HEAD(&upnphttphead, tmp, entries); - } - } -#endif -#endif /* ENABLE_HTTPS */ -#ifdef ENABLE_NFQUEUE - /* process NFQ packets */ - if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) - { - /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/ - ProcessNFQUEUE(nfqh); - } -#endif - /* delete finished HTTP connections */ - for(e = upnphttphead.lh_first; e != NULL; ) - { - next = e->entries.le_next; - if(e->state >= EToDelete) - { - LIST_REMOVE(e, entries); - Delete_upnphttp(e); - } - e = next; - } - - } /* end of main loop */ - -shutdown: - syslog(LOG_NOTICE, "shutting down MiniUPnPd"); - /* send good-bye */ - if (GETFLAG(ENABLEUPNPMASK)) - { -#ifndef ENABLE_IPV6 - if(SendSSDPGoodbye(snotify, addr_count) < 0) -#else - if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) -#endif - { - syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); - } - } - /* try to send pending packets */ - finalize_sendto(); - -#ifdef TOMATO - tomato_save("/etc/upnp/data"); -#endif /* TOMATO */ -#if defined(ENABLE_LEASEFILE) && defined(LEASEFILE_USE_REMAINING_TIME) - lease_file_rewrite(); -#endif /* ENABLE_LEASEFILE && LEASEFILE_USE_REMAINING_TIME */ - /* close out open sockets */ - while(upnphttphead.lh_first != NULL) - { - e = upnphttphead.lh_first; - LIST_REMOVE(e, entries); - Delete_upnphttp(e); - } - - if (sudp >= 0) close(sudp); - if (shttpl >= 0) close(shttpl); -#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) - if (shttpl_v4 >= 0) close(shttpl_v4); -#endif -#ifdef ENABLE_IPV6 - if (sudpv6 >= 0) close(sudpv6); -#endif -#ifdef USE_IFACEWATCHER - if(sifacewatcher >= 0) close(sifacewatcher); -#endif -#ifdef ENABLE_NATPMP - for(i=0; i=0) - { - close(snatpmp[i]); - snatpmp[i] = -1; - } - } -#endif -#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) - if(spcp_v6 >= 0) - { - close(spcp_v6); - spcp_v6 = -1; - } -#endif -#ifdef USE_MINIUPNPDCTL - if(sctl>=0) - { - close(sctl); - sctl = -1; - if(unlink("/var/run/miniupnpd.ctl") < 0) - { - syslog(LOG_ERR, "unlink() %m"); - } - } -#endif - - if (GETFLAG(ENABLEUPNPMASK)) - { -#ifndef ENABLE_IPV6 - for(i = 0; i < addr_count; i++) -#else - for(i = 0; i < addr_count * 2; i++) -#endif - close(snotify[i]); - } - - /* remove pidfile */ - if(pidfilename && (unlink(pidfilename) < 0)) - { - syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); - } - - /* delete lists */ - while(lan_addrs.lh_first != NULL) - { - lan_addr = lan_addrs.lh_first; - LIST_REMOVE(lan_addrs.lh_first, list); - free(lan_addr); - } - -#ifdef ENABLE_HTTPS - free_ssl(); -#endif -#ifdef ENABLE_NATPMP - free(snatpmp); -#endif - free(snotify); - closelog(); -#ifndef DISABLE_CONFIG_FILE - freeoptions(); -#endif - - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpd.conf b/src/contrib/miniupnp/miniupnpd/miniupnpd.conf deleted file mode 100644 index 133566f..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpd.conf +++ /dev/null @@ -1,152 +0,0 @@ -# WAN network interface -#ext_ifname=eth1 -#ext_ifname=xl1 -# If the WAN interface has several IP addresses, you -# can specify the one to use below -#ext_ip= - -# LAN network interfaces IPs / networks -# There can be multiple listening IPs for SSDP traffic, in that case -# use multiple 'listening_ip=...' lines, one for each network interface. -# It can be IP address or network interface name (ie. "eth0") -# It is mandatory to use the network interface name in order to enable IPv6 -# HTTP is available on all interfaces. -# When MULTIPLE_EXTERNAL_IP is enabled, the external IP -# address associated with the subnet follows. For example: -# listening_ip=192.168.0.1/24 88.22.44.13 -#listening_ip=192.168.0.1/24 -#listening_ip=10.5.0.0/16 -#listening_ip=eth0 -# CAUTION: mixing up WAN and LAN interfaces may introduce security risks! -# Be sure to assign the correct interfaces to LAN and WAN and consider -# implementing UPnP permission rules at the bottom of this configuration file - -# Port for HTTP (descriptions and SOAP) traffic. Set to 0 for autoselect. -#http_port=0 -# Port for HTTPS. Set to 0 for autoselect (default) -#https_port=0 - -# Path to the UNIX socket used to communicate with MiniSSDPd -# If running, MiniSSDPd will manage M-SEARCH answering. -# default is /var/run/minissdpd.sock -#minissdpdsocket=/var/run/minissdpd.sock - -# Enable NAT-PMP support (default is no) -#enable_natpmp=yes - -# Enable UPNP support (default is yes) -#enable_upnp=no - -# PCP -# Configure the minimum and maximum lifetime of a port mapping in seconds -# 120s and 86400s (24h) are suggested values from PCP-base -#min_lifetime=120 -#max_lifetime=86400 - -# Chain names for netfilter (not used for pf or ipf). -# default is MINIUPNPD for both -#upnp_forward_chain=forwardUPnP -#upnp_nat_chain=UPnP -#upnp_nat_postrouting_chain=UPnP-Postrouting - -# Lease file location -#lease_file=/var/log/upnp.leases - -# To enable the next few runtime options, see compile time -# ENABLE_MANUFACTURER_INFO_CONFIGURATION (config.h) - -# Name of this service, default is "`uname -s` router" -#friendly_name=MiniUPnPd router - -# Manufacturer name, default is "`uname -s`" -#manufacturer_name=Manufacturer corp - -# Manufacturer URL, default is URL of OS vendor -#manufacturer_url=http://miniupnp.free.fr/ - -# Model name, default is "`uname -s` router" -#model_name=Router Model - -# Model description, default is "`uname -s` router" -#model_description=Very Secure Router - Model - -# Model URL, default is URL of OS vendor -#model_url=http://miniupnp.free.fr/ - -# Bitrates reported by daemon in bits per second -# by default miniupnpd tries to get WAN interface speed -#bitrate_up=1000000 -#bitrate_down=10000000 - -# Secure Mode, UPnP clients can only add mappings to their own IP -#secure_mode=yes -secure_mode=no - -# Default presentation URL is HTTP address on port 80 -# If set to an empty string, no presentationURL element will appear -# in the XML description of the device, which prevents MS Windows -# from displaying an icon in the "Network Connections" panel. -#presentation_url=http://www.mylan/index.php - -# Report system uptime instead of daemon uptime -system_uptime=yes - -# Notify interval in seconds. default is 30 seconds. -#notify_interval=240 -notify_interval=60 - -# Unused rules cleaning. -# never remove any rule before this threshold for the number -# of redirections is exceeded. default to 20 -#clean_ruleset_threshold=10 -# Clean process work interval in seconds. default to 0 (disabled). -# a 600 seconds (10 minutes) interval makes sense -clean_ruleset_interval=600 - -# Log packets in pf (default is no) -#packet_log=no - -# Anchor name in pf (default is miniupnpd) -#anchor=miniupnpd - -# ALTQ queue in pf -# Filter rules must be used for this to be used. -# compile with PF_ENABLE_FILTER_RULES (see config.h file) -#queue=queue_name1 - -# Tag name in pf -#tag=tag_name1 - -# Make filter rules in pf quick or not. default is yes -# active when compiled with PF_ENABLE_FILTER_RULES (see config.h file) -#quickrules=no - -# UUID, generate your own UUID with "make genuuid" -uuid=00000000-0000-0000-0000-000000000000 - -# Daemon's serial and model number when reporting to clients -# (in XML description) -#serial=12345678 -#model_number=1 - -# If compiled with IGD_V2 defined, force reporting IGDv1 in rootDesc (default -# is no) -#force_igd_desc_v1=no - -# UPnP permission rules -# (allow|deny) (external port range) IP/mask (internal port range) -# A port range is - or if there is only -# one port in the range. -# IP/mask format must be nnn.nnn.nnn.nnn/nn -# It is advised to only allow redirection of port >= 1024 -# and end the rule set with "deny 0-65535 0.0.0.0/0 0-65535" -# The following default ruleset allows specific LAN side IP addresses -# to request only ephemeral ports. It is recommended that users -# modify the IP ranges to match their own internal networks, and -# also consider implementing network-specific restrictions -# CAUTION: failure to enforce any rules may permit insecure requests to be made! -allow 1024-65535 192.168.0.0/24 1024-65535 -allow 1024-65535 192.168.1.0/24 1024-65535 -allow 1024-65535 192.168.0.0/23 22 -allow 12345 192.168.7.113/32 54321 -deny 0-65535 0.0.0.0/0 0-65535 diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpd.rc.once.d.script b/src/contrib/miniupnp/miniupnpd/miniupnpd.rc.once.d.script deleted file mode 100644 index c1d5f99..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpd.rc.once.d.script +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -# -# generate a UUID on first system start -# - -UUID=`uuidgen` -CONFFILE=/etc/miniupnpd/miniupnpd.conf - -mv "${CONFFILE}" "${CONFFILE}.before" -sed -e "s/^uuid=[-0-9a-fA-F]*/uuid=$UUID/" "${CONFFILE}.before" > "${CONFFILE}" -rm "${CONFFILE}.before" diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpdctl.c b/src/contrib/miniupnp/miniupnpd/miniupnpdctl.c deleted file mode 100644 index 5758e0b..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpdctl.c +++ /dev/null @@ -1,83 +0,0 @@ -/* $Id: miniupnpdctl.c,v 1.10 2012/04/30 21:08:00 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "macros.h" - -#if 0 -static void sighandler(int sig) -{ - printf("received signal %d\n", sig); -} -#endif - -int -main(int argc, char * * argv) -{ - /*char test[] = "test!";*/ - static const char command[] = "show all\n"; - char buf[256]; - int l; - int s; - struct sockaddr_un addr; - UNUSED(argc); - UNUSED(argv); - - /*signal(SIGINT, sighandler);*/ - s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s<0) - { - perror("socket"); - return 1; - } - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, "/var/run/miniupnpd.ctl", - sizeof(addr.sun_path)); - if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) - { - perror("connect"); - close(s); - return 1; - } - - printf("Connected.\n"); - if(write(s, command, sizeof(command)) < 0) - { - perror("write"); - close(s); - return 1; - } - for(;;) - { - l = read(s, buf, sizeof(buf)); - if(l<0) - { - perror("read"); - break; - } - if(l==0) - break; - /*printf("%d bytes read\n", l);*/ - fflush(stdout); - if(write(fileno(stdout), buf, l) < 0) { - perror("error writing to stdout"); - } - /*printf("\n");*/ - } - - close(s); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpdctl.txt b/src/contrib/miniupnp/miniupnpd/miniupnpdctl.txt deleted file mode 100644 index 40bedbe..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpdctl.txt +++ /dev/null @@ -1,18 +0,0 @@ -miniupnpdctl - -the communication between a running miniupnpd and miniupnpdctl is -established through a unix socket. "/var/run/miniupnpd.ctl" - -miniupnpdctl can send the following commands : - -1 - print all open sockets -2 - print config -3 - print current redirections - -show options -show permissions/show perms? -show rdr -show opensockets - -show all ? - diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpdpath.h b/src/contrib/miniupnp/miniupnpd/miniupnpdpath.h deleted file mode 100644 index a728ec1..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpdpath.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: miniupnpdpath.h,v 1.8 2011/05/20 17:51:23 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef MINIUPNPDPATH_H_INCLUDED -#define MINIUPNPDPATH_H_INCLUDED - -#include "config.h" - -/* Paths and other URLs in the miniupnpd http server */ - -#define ROOTDESC_PATH "/rootDesc.xml" - -#ifdef HAS_DUMMY_SERVICE -#define DUMMY_PATH "/dummy.xml" -#endif - -#define WANCFG_PATH "/WANCfg.xml" -#define WANCFG_CONTROLURL "/ctl/CmnIfCfg" -#define WANCFG_EVENTURL "/evt/CmnIfCfg" - -#define WANIPC_PATH "/WANIPCn.xml" -#define WANIPC_CONTROLURL "/ctl/IPConn" -#define WANIPC_EVENTURL "/evt/IPConn" - -#ifdef ENABLE_L3F_SERVICE -#define L3F_PATH "/L3F.xml" -#define L3F_CONTROLURL "/ctl/L3F" -#define L3F_EVENTURL "/evt/L3F" -#endif - -#ifdef ENABLE_6FC_SERVICE -#define WANIP6FC_PATH "/WANIP6FC.xml" -#define WANIP6FC_CONTROLURL "/ctl/IP6FCtl" -#define WANIP6FC_EVENTURL "/evt/IP6FCtl" -#endif - -#ifdef ENABLE_DP_SERVICE -/* For DeviceProtection introduced in IGD v2 */ -#define DP_PATH "/DP.xml" -#define DP_CONTROLURL "/ctl/DP" -#define DP_EVENTURL "/evt/DP" -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/miniupnpdtypes.h b/src/contrib/miniupnp/miniupnpd/miniupnpdtypes.h deleted file mode 100644 index 4e71c7e..0000000 --- a/src/contrib/miniupnp/miniupnpd/miniupnpdtypes.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: miniupnpdtypes.h,v 1.4 2012/04/06 15:27:21 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef MINIUPNPDTYPES_H_INCLUDED -#define MINIUPNPDTYPES_H_INCLUDED - -#include "config.h" -#include -#include -#include - -/* structure and list for storing lan addresses - * with ascii representation and mask */ -struct lan_addr_s { - char ifname[IFNAMSIZ]; /* example: eth0 */ - unsigned int index; /* use if_nametoindex() */ - char str[16]; /* example: 192.168.0.1 */ - struct in_addr addr, mask; /* ip/mask */ -#ifdef MULTIPLE_EXTERNAL_IP - char ext_ip_str[16]; - struct in_addr ext_ip_addr; -#endif - LIST_ENTRY(lan_addr_s) list; -}; -LIST_HEAD(lan_addr_list, lan_addr_s); - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/minixml.c b/src/contrib/miniupnp/miniupnpd/minixml.c deleted file mode 100644 index ed2d3c7..0000000 --- a/src/contrib/miniupnp/miniupnpd/minixml.c +++ /dev/null @@ -1,231 +0,0 @@ -/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * minixml.c : the minimum size a xml parser can be ! */ -/* Project : miniupnp - * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - -Copyright (c) 2005-2017, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -#include -#include "minixml.h" - -/* parseatt : used to parse the argument list - * return 0 (false) in case of success and -1 (true) if the end - * of the xmlbuffer is reached. */ -static int parseatt(struct xmlparser * p) -{ - const char * attname; - int attnamelen; - const char * attvalue; - int attvaluelen; - while(p->xml < p->xmlend) - { - if(*p->xml=='/' || *p->xml=='>') - return 0; - if( !IS_WHITE_SPACE(*p->xml) ) - { - char sep; - attname = p->xml; - attnamelen = 0; - while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) - { - attnamelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - while(*(p->xml++) != '=') - { - if(p->xml >= p->xmlend) - return -1; - } - while(IS_WHITE_SPACE(*p->xml)) - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - sep = *p->xml; - if(sep=='\'' || sep=='\"') - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - attvalue = p->xml; - attvaluelen = 0; - while(*p->xml != sep) - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - else - { - attvalue = p->xml; - attvaluelen = 0; - while( !IS_WHITE_SPACE(*p->xml) - && *p->xml != '>' && *p->xml != '/') - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - /*printf("%.*s='%.*s'\n", - attnamelen, attname, attvaluelen, attvalue);*/ - if(p->attfunc) - p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); - } - p->xml++; - } - return -1; -} - -/* parseelt parse the xml stream and - * call the callback functions when needed... */ -static void parseelt(struct xmlparser * p) -{ - int i; - const char * elementname; - while(p->xml < (p->xmlend - 1)) - { - if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); - p->xml += 3; - } - else if((p->xml)[0]=='<' && (p->xml)[1]!='?') - { - i = 0; elementname = ++p->xml; - while( !IS_WHITE_SPACE(*p->xml) - && (*p->xml!='>') && (*p->xml!='/') - ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - /* to ignore namespace : */ - if(*p->xml==':') - { - i = 0; - elementname = ++p->xml; - } - } - if(i>0) - { - if(p->starteltfunc) - p->starteltfunc(p->data, elementname, i); - if(parseatt(p)) - return; - if(*p->xml!='/') - { - const char * data; - i = 0; data = ++p->xml; - if (p->xml >= p->xmlend) - return; - while( IS_WHITE_SPACE(*p->xml) ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - /* CDATA are at least 9 + 3 characters long : */ - if((p->xmlend >= (p->xml + (9 + 3))) && (memcmp(p->xml, "xml += 9; - data = p->xml; - i = 0; - while(memcmp(p->xml, "]]>", 3) != 0) - { - i++; p->xml++; - if ((p->xml + 3) >= p->xmlend) - return; - } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); - while(*p->xml!='<') - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - } - else - { - while(*p->xml!='<') - { - i++; p->xml++; - if ((p->xml + 1) >= p->xmlend) - return; - } - if(i>0 && p->datafunc && *(p->xml + 1) == '/') - p->datafunc(p->data, data, i); - } - } - } - else if(*p->xml == '/') - { - i = 0; elementname = ++p->xml; - if (p->xml >= p->xmlend) - return; - while((*p->xml != '>')) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(p->endeltfunc) - p->endeltfunc(p->data, elementname, i); - p->xml++; - } - } - else - { - p->xml++; - } - } -} - -/* the parser must be initialized before calling this function */ -void parsexml(struct xmlparser * parser) -{ - parser->xml = parser->xmlstart; - parser->xmlend = parser->xmlstart + parser->xmlsize; - parseelt(parser); -} - - diff --git a/src/contrib/miniupnp/miniupnpd/minixml.h b/src/contrib/miniupnp/miniupnpd/minixml.h deleted file mode 100644 index 19e6f51..0000000 --- a/src/contrib/miniupnp/miniupnpd/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/natpmp.c b/src/contrib/miniupnp/miniupnpd/natpmp.c deleted file mode 100644 index 0ed09e0..0000000 --- a/src/contrib/miniupnp/miniupnpd/natpmp.c +++ /dev/null @@ -1,486 +0,0 @@ -/* $Id: natpmp.c,v 1.55 2018/03/12 22:41:54 nanard Exp $ */ -/* MiniUPnP project - * (c) 2007-2017 Thomas Bernard - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "natpmp.h" -#include "upnpglobalvars.h" -#include "getifaddr.h" -#include "upnpredirect.h" -#include "commonrdr.h" -#include "upnputils.h" -#include "portinuse.h" -#include "asyncsendto.h" - -#ifdef ENABLE_NATPMP - -int OpenAndConfNATPMPSocket(in_addr_t addr) -{ - int snatpmp; - int i = 1; - snatpmp = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/); - if(snatpmp<0) - { - syslog(LOG_ERR, "%s: socket(): %m", - "OpenAndConfNATPMPSocket"); - return -1; - } - if(setsockopt(snatpmp, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) - { - syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m", - "OpenAndConfNATPMPSocket"); - } - if(!set_non_blocking(snatpmp)) - { - syslog(LOG_WARNING, "%s: set_non_blocking(): %m", - "OpenAndConfNATPMPSocket"); - } - { - struct sockaddr_in natpmp_addr; - memset(&natpmp_addr, 0, sizeof(natpmp_addr)); - natpmp_addr.sin_family = AF_INET; - natpmp_addr.sin_port = htons(NATPMP_PORT); - /*natpmp_addr.sin_addr.s_addr = INADDR_ANY; */ - natpmp_addr.sin_addr.s_addr = addr; - if(bind(snatpmp, (struct sockaddr *)&natpmp_addr, sizeof(natpmp_addr)) < 0) - { - syslog(LOG_ERR, "%s: bind(): %m", - "OpenAndConfNATPMPSocket"); - close(snatpmp); - return -1; - } - } - return snatpmp; -} - -int OpenAndConfNATPMPSockets(int * sockets) -{ - int i; - struct lan_addr_s * lan_addr; - for(i = 0, lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - sockets[i] = OpenAndConfNATPMPSocket(lan_addr->addr.s_addr); - if(sockets[i] < 0) - goto error; - i++; - } - return 0; -error: - while(--i >= 0) - { - close(sockets[i]); - sockets[i] = -1; - } - return -1; -} - -static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr) -{ -#ifndef MULTIPLE_EXTERNAL_IP - char tmp[16]; - UNUSED(senderaddr); - - if(use_ext_ip_addr) { - inet_pton(AF_INET, use_ext_ip_addr, resp+8); - } else { - if(!ext_if_name || ext_if_name[0]=='\0') { - resp[3] = 3; /* Network Failure (e.g. NAT box itself - * has not obtained a DHCP lease) */ - } else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN, NULL, NULL) < 0) { - syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name); - resp[3] = 3; /* Network Failure (e.g. NAT box itself - * has not obtained a DHCP lease) */ - } else { - inet_pton(AF_INET, tmp, resp+8); /* ok */ - } - } -#else - struct lan_addr_s * lan_addr; - - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { - if( (senderaddr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) { - memcpy(resp+8, &lan_addr->ext_ip_addr, - sizeof(lan_addr->ext_ip_addr)); - break; - } - } -#endif -} - -/* - * Receives NATPMP and PCP packets and stores them in msg_buff. - * The sender information is stored in senderaddr. - * Returns number of bytes recevied, even if number is negative. - */ -int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr, - socklen_t * senderaddrlen, - struct sockaddr_in6 * receiveraddr, - unsigned char * msg_buff, size_t msg_buff_size) -{ -#ifdef IPV6_PKTINFO - struct iovec iov; - uint8_t c[1000]; - struct msghdr msg; - int n; - struct cmsghdr *h; - - iov.iov_base = msg_buff; - iov.iov_len = msg_buff_size; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_name = senderaddr; - msg.msg_namelen = *senderaddrlen; - msg.msg_control = c; - msg.msg_controllen = sizeof(c); - - n = recvmsg(s, &msg, 0); - if(n < 0) { - /* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time) - * other errors : log to LOG_ERR */ - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) { - syslog(LOG_ERR, "recvmsg(natpmp): %m"); - } - return n; - } - - if(receiveraddr) { - memset(receiveraddr, 0, sizeof(struct sockaddr_in6)); - } - if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC)) { - syslog(LOG_WARNING, "%s: truncated message", - "ReceiveNATPMPOrPCPPacket"); - } - for(h = CMSG_FIRSTHDR(&msg); h; - h = CMSG_NXTHDR(&msg, h)) { - if(h->cmsg_level == IPPROTO_IPV6 && h->cmsg_type == IPV6_PKTINFO) { - char tmp[INET6_ADDRSTRLEN]; - struct in6_pktinfo *ipi6 = (struct in6_pktinfo *)CMSG_DATA(h); - syslog(LOG_DEBUG, "%s: packet destination: %s scope_id=%u", - "ReceiveNATPMPOrPCPPacket", - inet_ntop(AF_INET6, &ipi6->ipi6_addr, tmp, sizeof(tmp)), - ipi6->ipi6_ifindex); - if(receiveraddr) { - receiveraddr->sin6_addr = ipi6->ipi6_addr; - receiveraddr->sin6_scope_id = ipi6->ipi6_ifindex; - receiveraddr->sin6_family = AF_INET6; - receiveraddr->sin6_port = htons(NATPMP_PORT); - } - } - } -#else /* IPV6_PKTINFO */ - int n; - - n = recvfrom(s, msg_buff, msg_buff_size, 0, - senderaddr, senderaddrlen); - - if(n<0) { - /* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time) - * other errors : log to LOG_ERR */ - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) { - syslog(LOG_ERR, "recvfrom(natpmp): %m"); - } - return n; - } -#endif /* IPV6_PKTINFO */ - - return n; -} - -/** read the request from the socket, process it and then send the - * response back. - */ -void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, - struct sockaddr_in *senderaddr) -{ - unsigned char *req=msg_buff; /* request udp packet */ - unsigned char resp[32]; /* response udp packet */ - int resplen; - int n = len; - char senderaddrstr[16]; - - if(!inet_ntop(AF_INET, &senderaddr->sin_addr, - senderaddrstr, sizeof(senderaddrstr))) { - syslog(LOG_ERR, "inet_ntop(natpmp): %m"); - } - - syslog(LOG_INFO, "NAT-PMP request received from %s:%hu %dbytes", - senderaddrstr, ntohs(senderaddr->sin_port), n); - - if(n<2 || ((((req[1]-1)&~1)==0) && n<12)) { - syslog(LOG_WARNING, "discarding NAT-PMP request (too short) %dBytes", - n); - return; - } - if(req[1] & 128) { - /* discarding NAT-PMP responses silently */ - return; - } - memset(resp, 0, sizeof(resp)); - resplen = 8; - resp[1] = 128 + req[1]; /* response OPCODE is request OPCODE + 128 */ - /* setting response TIME STAMP : - * time elapsed since its port mapping table was initialized on - * startup or reset for any other reason */ - if(epoch_origin == 0) { - epoch_origin = startup_time; - } - WRITENU32(resp+4, upnp_time() - epoch_origin); - if(req[0] > 0) { - /* invalid version */ - syslog(LOG_WARNING, "unsupported NAT-PMP version : %u", - (unsigned)req[0]); - resp[3] = 1; /* unsupported version */ - } else switch(req[1]) { - case 0: /* Public address request */ - syslog(LOG_INFO, "NAT-PMP public address request"); - FillPublicAddressResponse(resp, senderaddr->sin_addr.s_addr); - resplen = 12; - break; - case 1: /* UDP port mapping request */ - case 2: /* TCP port mapping request */ - { - unsigned short iport; /* private port */ - unsigned short eport; /* public port */ - uint32_t lifetime; /* lifetime=0 => remove port mapping */ - int r; - int proto; - char iaddr_old[16]; - unsigned short iport_old; - unsigned int timestamp; - - iport = READNU16(req+4); - eport = READNU16(req+6); - lifetime = READNU32(req+8); - proto = (req[1]==1)?IPPROTO_UDP:IPPROTO_TCP; - syslog(LOG_INFO, "NAT-PMP port mapping request : " - "%hu->%s:%hu %s lifetime=%us", - eport, senderaddrstr, iport, - (req[1]==1)?"udp":"tcp", lifetime); - /* TODO: accept port mapping if iport ok but eport not ok - * (and set eport correctly) */ - if(lifetime == 0) { - /* remove the mapping */ - /* RFC6886 : - * A client MAY also send an explicit packet to request deletion of a - * mapping that is no longer needed. A client requests explicit - * deletion of a mapping by sending a message to the NAT gateway - * requesting the mapping, with the Requested Lifetime in Seconds set to - * zero. The Suggested External Port MUST be set to zero by the client - * on sending, and MUST be ignored by the gateway on reception. */ - int index = 0; - unsigned short eport2, iport2; - char iaddr2[16]; - int proto2; - char desc[64]; - eport = 0; /* to indicate correct removing of port mapping */ - while(get_redirect_rule_by_index(index, 0, - &eport2, iaddr2, sizeof(iaddr2), - &iport2, &proto2, - desc, sizeof(desc), - 0, 0, ×tamp, 0, 0) >= 0) { - syslog(LOG_DEBUG, "%d %d %hu->'%s':%hu '%s'", - index, proto2, eport2, iaddr2, iport2, desc); - if(0 == strcmp(iaddr2, senderaddrstr) - && 0 == memcmp(desc, "NAT-PMP", 7)) { - /* (iport == 0) => remove all the mappings for this client */ - if((iport == 0) || ((iport == iport2) && (proto == proto2))) { - r = _upnp_delete_redir(eport2, proto2); - if(r < 0) { - syslog(LOG_ERR, "Failed to remove NAT-PMP mapping eport %hu, protocol %s", - eport2, (proto2==IPPROTO_TCP)?"TCP":"UDP"); - resp[3] = 2; /* Not Authorized/Refused */ - break; - } else { - syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed", - proto2==IPPROTO_TCP?"TCP":"UDP", eport2); - index--; - } - } - } - index++; - } - } else if(iport==0) { - resp[3] = 2; /* Not Authorized/Refused */ - } else { /* iport > 0 && lifetime > 0 */ - unsigned short eport_first = 0; - int any_eport_allowed = 0; - char desc[64]; - if(eport==0) /* if no suggested external port, use same a internal port */ - eport = iport; - while(resp[3] == 0) { - if(eport_first == 0) { /* first time in loop */ - eport_first = eport; - } else if(eport == eport_first) { /* no eport available */ - if(any_eport_allowed == 0) { /* all eports rejected by permissions */ - syslog(LOG_ERR, "No allowed eport for NAT-PMP %hu %s->%s:%hu", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 2; /* Not Authorized/Refused */ - } else { /* at least one eport allowed (but none available) */ - syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 4; /* Out of resources */ - } - break; - } - if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { - eport++; - if(eport == 0) eport++; /* skip port zero */ - continue; - } - any_eport_allowed = 1; /* at lease one eport is allowed */ -#ifdef CHECK_PORTINUSE - if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport) > 0) { - syslog(LOG_INFO, "port %hu protocol %s already in use", - eport, (proto==IPPROTO_TCP)?"tcp":"udp"); - eport++; - if(eport == 0) eport++; /* skip port zero */ - continue; - } -#endif - r = get_redirect_rule(ext_if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0, - ×tamp, 0, 0); - if(r==0) { - if(strcmp(senderaddrstr, iaddr_old)==0 - && iport==iport_old) { - /* redirection already existing */ - syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old); - /* remove and then add again */ - if(_upnp_delete_redir(eport, proto) < 0) { - syslog(LOG_ERR, "failed to remove port mapping"); - break; - } - } else { - eport++; - if(eport == 0) eport++; /* skip port zero */ - continue; - } - } - /* do the redirection */ - timestamp = upnp_time() + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", - eport, (proto==IPPROTO_TCP)?"tcp":"udp"); - /* TODO : check return code */ - if(upnp_redirect_internal(NULL, eport, senderaddrstr, - iport, proto, desc, - timestamp) < 0) { - syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); - resp[3] = 3; /* Failure */ - } - break; - } - } - WRITENU16(resp+8, iport); /* private port */ - WRITENU16(resp+10, eport); /* public port */ - WRITENU32(resp+12, lifetime); /* Port Mapping lifetime */ - } - resplen = 16; - break; - default: - resp[3] = 5; /* Unsupported OPCODE */ - } - n = sendto_or_schedule(s, resp, resplen, 0, - (struct sockaddr *)senderaddr, sizeof(*senderaddr)); - if(n<0) { - syslog(LOG_ERR, "sendto(natpmp): %m"); - } else if(nlist.le_next; - FillPublicAddressResponse(notif, lan_addr->addr.s_addr); - } -#endif - /* Port to use in 2006 version of the NAT-PMP specification */ - sockname.sin_port = htons(NATPMP_PORT); - n = sendto_or_schedule(sockets[j], notif, 12, 0, - (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); - if(n < 0) - { - syslog(LOG_ERR, "%s: sendto(s_udp=%d, port=%d): %m", - "SendNATPMPPublicAddressChangeNotification", sockets[j], NATPMP_PORT); - return; - } - /* Port to use in 2008 version of the NAT-PMP specification */ - sockname.sin_port = htons(NATPMP_NOTIF_PORT); - n = sendto_or_schedule(sockets[j], notif, 12, 0, - (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); - if(n < 0) - { - syslog(LOG_ERR, "%s: sendto(s_udp=%d, port=%d): %m", - "SendNATPMPPublicAddressChangeNotification", sockets[j], NATPMP_NOTIF_PORT); - return; - } - } -} - -#endif /* ENABLE_NATPMP */ diff --git a/src/contrib/miniupnp/miniupnpd/natpmp.h b/src/contrib/miniupnp/miniupnpd/natpmp.h deleted file mode 100644 index d44bcad..0000000 --- a/src/contrib/miniupnp/miniupnpd/natpmp.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: natpmp.h,v 1.12 2014/03/24 10:49:46 nanard Exp $ */ -/* MiniUPnP project - * author : Thomas Bernard - * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - */ -#ifndef NATPMP_H_INCLUDED -#define NATPMP_H_INCLUDED - -/* The NAT-PMP specification which can be found at the url : - * http://files.dns-sd.org/draft-cheshire-nat-pmp.txt - * draft version 3 of April 2008 - * define 5351 as listening port for the gateway, - * and the 224.0.0.1 port 5350 as the local link - * multicast address for address change announces. - * Previous versions of the specification defined 5351 - * as the port for address change announces. */ -#define NATPMP_PORT (5351) -#define NATPMP_NOTIF_PORT (5350) -#define NATPMP_NOTIF_ADDR ("224.0.0.1") - -int OpenAndConfNATPMPSockets(int * sockets); - -/* receiveraddr is only used with IPV6 sockets */ -int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr, - socklen_t * senderaddrlen, - struct sockaddr_in6 * receiveraddr, - unsigned char * msg_buff, size_t msg_buff_size); - -void ProcessIncomingNATPMPPacket(int s, unsigned char * msg_buff, int len, - struct sockaddr_in * senderaddr); - -void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/Makefile b/src/contrib/miniupnp/miniupnpd/netfilter/Makefile deleted file mode 100644 index 7bc52a2..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -# $Id: Makefile,v 1.6 2012/04/26 13:50:48 nanard Exp $ -CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement -CC = gcc - -#LIBS = -liptc -LIBS = -lip4tc - -ARCH := $(shell uname -m | grep -q "x86_64" && echo 64) -ifdef IPTABLESPATH -CFLAGS := $(CFLAGS) -I$(IPTABLESPATH)/include/ -LDFLAGS := $(LDFLAFGS) -L$(IPTABLESPATH)/libiptc/ -# get iptables version and set IPTABLES_143 macro if needed -IPTABLESVERSION := $(shell grep "\#define VERSION" $(IPTABLESPATH)/config.h | tr -d \" |cut -d" " -f3 ) -IPTABLESVERSION1 := $(shell echo $(IPTABLESVERSION) | cut -d. -f1 ) -IPTABLESVERSION2 := $(shell echo $(IPTABLESVERSION) | cut -d. -f2 ) -IPTABLESVERSION3 := $(shell echo $(IPTABLESVERSION) | cut -d. -f3 ) -# test if iptables version >= 1.4.3 -TEST := $(shell [ \( \( $(IPTABLESVERSION1) -ge 1 \) -a \( $(IPTABLESVERSION2) -ge 4 \) \) -a \( $(IPTABLESVERSION3) -ge 3 \) ] && echo 1 ) -ifeq ($(TEST), 1) -CFLAGS := $(CFLAGS) -DIPTABLES_143 -# the following sucks, but works -LIBS = $(IPTABLESPATH)/libiptc/.libs/libip4tc.o -#LIBS = $(IPTABLESPATH)/libiptc/.libs/libiptc.a -else -LIBS = $(IPTABLESPATH)/libiptc/libiptc.a -endif -else -# check for system-wide iptables files. Test if iptables version >= 1.4.3 -#TEST := $(shell test -f /usr/include/iptables/internal.h && grep -q "\#define IPTABLES_VERSION" /usr/include/iptables/internal.h && echo 1) -TEST := $(shell test -f /usr/include/xtables.h && grep -q "XTABLES_VERSION_CODE" /usr/include/xtables.h && echo 1) -ifeq ($(TEST), 1) -CFLAGS := $(CFLAGS) -DIPTABLES_143 -LIBS = -liptc -TEST_LIB := $(shell test -f /usr/lib$(ARCH)/libiptc.a && echo 1) -ifeq ($(TEST_LIB), 1) -LIBS = -liptc /usr/lib$(ARCH)/libiptc.a -endif -endif -endif - -LIBS += /lib/libip4tc.so /lib/libip6tc.so - -all: iptcrdr.o testiptcrdr iptpinhole.o \ - testiptcrdr_peer testiptcrdr_dscp test_nfct_get -# testiptpinhole - -clean: - $(RM) *.o testiptcrdr testiptpinhole testiptcrdr_peer test_nfct_get \ - testiptcrdr_dscp - -testiptcrdr: testiptcrdr.o upnpglobalvars.o $(LIBS) - -testiptcrdr_peer: testiptcrdr_peer.o upnpglobalvars.o $(LIBS) - -testiptcrdr_dscp: testiptcrdr_dscp.o upnpglobalvars.o $(LIBS) - -testiptpinhole: testiptpinhole.o iptpinhole.o upnpglobalvars.o $(LIBS) - -test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack - -test_nfct_get.o: test_nfct_get.c - -testiptcrdr_peer.o: testiptcrdr_peer.c - -testiptcrdr_dscp.o: testiptcrdr_dscp.c - -iptcrdr.o: iptcrdr.c iptcrdr.h - -iptpinhole.o: iptpinhole.c iptpinhole.h - -upnpglobalvars.o: ../upnpglobalvars.c ../upnpglobalvars.h - $(CC) -c -o $@ $< - - -#depends -testiptcrdr.o: testiptcrdr.c iptcrdr.c -testiptcrdr_dscp.o: testiptcrdr_dscp.c iptcrdr.c -testiptcrdr_peer.o: testiptcrdr_peer.c iptcrdr.c -test_nfct_get.o: test_nfct_get.c nfct_get.c diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_display.sh b/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_display.sh deleted file mode 100644 index 4ef5995..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_display.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh -# $Id: ip6tables_display.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $ - -IPV6=1 -. $(dirname "$0")/miniupnpd_functions.sh - -#display all chains relative to miniupnpd -$IPTABLES -v -n -t filter -L FORWARD -$IPTABLES -v -n -t filter -L $CHAIN diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_flush.sh b/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_flush.sh deleted file mode 100644 index ceec1e4..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_flush.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/sh -# $Id: ip6tables_flush.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $ - -IPV6=1 -. $(dirname "$0")/miniupnpd_functions.sh - -#flush all rules owned by miniupnpd -$IPTABLES -t filter -F $CHAIN diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_init.sh b/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_init.sh deleted file mode 100644 index 162ef13..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_init.sh +++ /dev/null @@ -1,22 +0,0 @@ -#! /bin/sh -# $Id: ip6tables_init_and_clean.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $ -# Improved Miniupnpd iptables init script. -# Checks for state of filter before doing anything.. - -IPV6=1 -EXT=1 -. $(dirname "$0")/miniupnpd_functions.sh - -if [ "$FDIRTY" = "${CHAIN}Chain" ]; then - echo "Filter table dirty; Cleaning..." -elif [ "$FDIRTY" = "Chain" ]; then - echo "Dirty filter chain but no reference..? Fixing..." - $IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN -else - echo "Filter table clean..initalizing.." - $IPTABLES -t filter -N $CHAIN - $IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN -fi -if [ "$CLEAN" = "yes" ]; then - $IPTABLES -t filter -F $CHAIN -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_removeall.sh b/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_removeall.sh deleted file mode 100644 index 126ca58..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/ip6tables_removeall.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/sh -# $Id: ip6tables_removeall.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $ - -IPV6=1 -EXT=1 -. $(dirname "$0")/miniupnpd_functions.sh - -#removing the MINIUPNPD chain for filter -if [ "$FDIRTY" = "${CHAIN}Chain" ]; then - $IPTABLES -t filter -F $CHAIN - $IPTABLES -t filter -D FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN - $IPTABLES -t filter -X $CHAIN -elif [ "$FDIRTY" = "Chain" ]; then - $IPTABLES -t filter -F $CHAIN - $IPTABLES -t filter -X $CHAIN -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display.sh b/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display.sh deleted file mode 100644 index 956375f..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/sh -# $Id: iptables_display.sh,v 1.4 2011/05/16 12:11:37 nanard Exp $ - -. $(dirname "$0")/miniupnpd_functions.sh - -#display all chains relative to miniupnpd -$IPTABLES -v -n -t nat -L PREROUTING -$IPTABLES -v -n -t nat -L $CHAIN -$IPTABLES -v -n -t nat -L POSTROUTING -$IPTABLES -v -n -t nat -L $CHAIN-POSTROUTING -$IPTABLES -v -n -t mangle -L PREROUTING -$IPTABLES -v -n -t mangle -L $CHAIN -$IPTABLES -v -n -t filter -L FORWARD -$IPTABLES -v -n -t filter -L $CHAIN diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display_miniupnpd.sh b/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display_miniupnpd.sh deleted file mode 100644 index 1d69457..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_display_miniupnpd.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/sh -# $Id: iptables_display_miniupnpd.sh,v 1.1 2016/02/12 15:23:29 nanard Exp $ - -. $(dirname "$0")/miniupnpd_functions.sh - -#display miniupnpd chains -$IPTABLES -v -n -t nat -L $CHAIN -$IPTABLES -v -n -t nat -L $CHAIN-POSTROUTING -$IPTABLES -v -n -t mangle -L $CHAIN -$IPTABLES -v -n -t filter -L $CHAIN diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_flush.sh b/src/contrib/miniupnp/miniupnpd/netfilter/iptables_flush.sh deleted file mode 100644 index e147829..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_flush.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/sh -# $Id: iptables_flush.sh,v 1.6 2017/04/21 11:16:09 nanard Exp $ - -. $(dirname "$0")/miniupnpd_functions.sh - -#flush all rules owned by miniupnpd -$IPTABLES -t nat -F $CHAIN -$IPTABLES -t nat -F $CHAIN-POSTROUTING -$IPTABLES -t filter -F $CHAIN -$IPTABLES -t mangle -F $CHAIN diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_init.sh b/src/contrib/miniupnp/miniupnpd/netfilter/iptables_init.sh deleted file mode 100644 index 1983277..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_init.sh +++ /dev/null @@ -1,37 +0,0 @@ -#! /bin/sh -# $Id: iptables_init_and_clean.sh,v 1.7 2017/04/21 11:16:09 nanard Exp $ -# Improved Miniupnpd iptables init script. -# Checks for state of filter before doing anything.. - -EXT=1 -. $(dirname "$0")/miniupnpd_functions.sh - -if [ "$NDIRTY" = "${CHAIN}Chain" ]; then - echo "Nat table dirty; Cleaning..." -elif [ "$NDIRTY" = "Chain" ]; then - echo "Dirty NAT chain but no reference..? Fixing..." - #$IPTABLES -t nat -A PREROUTING -d $EXTIP -i $EXTIF -j $CHAIN - $IPTABLES -t nat -A PREROUTING -i $EXTIF -j $CHAIN -else - echo "NAT table clean..initalizing.." - $IPTABLES -t nat -N $CHAIN - #$IPTABLES -t nat -A PREROUTING -d $EXTIP -i $EXTIF -j $CHAIN - $IPTABLES -t nat -A PREROUTING -i $EXTIF -j $CHAIN -fi -if [ "$CLEAN" = "yes" ]; then - $IPTABLES -t nat -F $CHAIN -fi - -if [ "$FDIRTY" = "${CHAIN}Chain" ]; then - echo "Filter table dirty; Cleaning..." -elif [ "$FDIRTY" = "Chain" ]; then - echo "Dirty filter chain but no reference..? Fixing..." - $IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN -else - echo "Filter table clean..initalizing.." - $IPTABLES -t filter -N MINIUPNPD - $IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN -fi -if [ "$CLEAN" = "yes" ]; then - $IPTABLES -t filter -F $CHAIN -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_removeall.sh b/src/contrib/miniupnp/miniupnpd/netfilter/iptables_removeall.sh deleted file mode 100644 index cd24596..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptables_removeall.sh +++ /dev/null @@ -1,46 +0,0 @@ -#! /bin/sh -# $Id: iptables_removeall.sh,v 1.10 2017/04/21 11:16:09 nanard Exp $ - -EXT=1 -. $(dirname "$0")/miniupnpd_functions.sh - -#removing the MINIUPNPD chain for nat -if [ "$NDIRTY" = "${CHAIN}Chain" ]; then - $IPTABLES -t nat -F $CHAIN - #$IPTABLES -t nat -D PREROUTING -d $EXTIP -i $EXTIF -j $CHAIN - $IPTABLES -t nat -D PREROUTING -i $EXTIF -j $CHAIN - $IPTABLES -t nat -X $CHAIN -elif [ "$NDIRTY" = "Chain" ]; then - $IPTABLES -t nat -F $CHAIN - $IPTABLES -t nat -X $CHAIN -fi - -#removing the MINIUPNPD chain for mangle -if [ "$MDIRTY" = "${CHAIN}Chain" ]; then - $IPTABLES -t mangle -F $CHAIN - $IPTABLES -t mangle -D FORWARD -i $EXTIF -j $CHAIN - $IPTABLES -t mangle -X $CHAIN -elif [ "$MDIRTY" = "Chain" ]; then - $IPTABLES -t mangle -F $CHAIN - $IPTABLES -t mangle -X $CHAIN -fi - -#removing the MINIUPNPD chain for filter -if [ "$FDIRTY" = "${CHAIN}Chain" ]; then - $IPTABLES -t filter -F $CHAIN - $IPTABLES -t filter -D FORWARD -i $EXTIF ! -o $EXTIF -j $CHAIN - $IPTABLES -t filter -X $CHAIN -elif [ "$FDIRTY" = "Chain" ]; then - $IPTABLES -t filter -F $CHAIN - $IPTABLES -t filter -X $CHAIN -fi - -#removing the MINIUPNPD-POSTROUTING chain for nat -if [ "$NPDIRTY" = "${CHAIN}-POSTROUTINGChain" ]; then - $IPTABLES -t nat -F $CHAIN-POSTROUTING - $IPTABLES -t nat -D POSTROUTING -o $EXTIF -j $CHAIN-POSTROUTING - $IPTABLES -t nat -X $CHAIN-POSTROUTING -elif [ "$NPDIRTY" = "Chain" ]; then - $IPTABLES -t nat -F $CHAIN-POSTROUTING - $IPTABLES -t nat -X $CHAIN-POSTROUTING -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.c b/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.c deleted file mode 100644 index 48c6dbb..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.c +++ /dev/null @@ -1,1948 +0,0 @@ -/* $Id: iptcrdr.c,v 1.59 2016/03/08 09:23:52 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if IPTABLES_143 -/* IPTABLES API version >= 1.4.3 */ - -/* added in order to compile on gentoo : - * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=2183 */ -#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) -#define __must_be_array(a) \ - BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0]))) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) -#define LIST_POISON2 ((void *) 0x00200200 ) - -#if 0 -#include -#else -#include "tiny_nf_nat.h" -#endif -#define ip_nat_multi_range nf_nat_multi_range -#define ip_nat_range nf_nat_range -#define IPTC_HANDLE struct iptc_handle * -#else -/* IPTABLES API version < 1.4.3 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#include -#else -#if 0 -#include -#else -#include "tiny_nf_nat.h" -#endif -#endif -#define IPTC_HANDLE iptc_handle_t -#endif - -/* IPT_ALIGN was renamed XT_ALIGN in iptables-1.4.11 */ -#ifndef IPT_ALIGN -#define IPT_ALIGN XT_ALIGN -#endif - -#include "../macros.h" -#include "../config.h" -#include "iptcrdr.h" -#include "../upnpglobalvars.h" - -/* local functions declarations */ -static int -addnatrule(int proto, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost); - -static int -add_filter_rule(int proto, const char * rhost, - const char * iaddr, unsigned short iport); - -#ifdef ENABLE_PORT_TRIGGERING -static int -addmasqueraderule(int proto, - unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost/*, const char * extif*/); -#endif /* ENABLE_PORT_TRIGGERING */ - -static int -addpeernatrule(int proto, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost, unsigned short rport); - -static int -addpeerdscprule(int proto, unsigned char dscp, - const char * iaddr, unsigned short iport, - const char * rhost, unsigned short rport); - -/* dummy init and shutdown functions - * Only test iptc_init() */ -int init_redirect(void) -{ - IPTC_HANDLE h; - - h = iptc_init("nat"); - if(!h) { - syslog(LOG_ERR, "iptc_init() failed : %s", - iptc_strerror(errno)); - return -1; - } else { -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - } - return 0; -} - -void shutdown_redirect(void) -{ - return; -} - -/* convert an ip address to string */ -static int snprintip(char * dst, size_t size, uint32_t ip) -{ - return snprintf(dst, size, - "%u.%u.%u.%u", ip >> 24, (ip >> 16) & 0xff, - (ip >> 8) & 0xff, ip & 0xff); -} - -/* netfilter cannot store redirection descriptions, so we use our - * own structure to store them */ -struct rdr_desc { - struct rdr_desc * next; - unsigned int timestamp; - unsigned short eport; - short proto; - char str[]; -}; - -/* pointer to the chained list where descriptions are stored */ -static struct rdr_desc * rdr_desc_list = 0; - -/* add a description to the list of redirection descriptions */ -static void -add_redirect_desc(unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - struct rdr_desc * p; - size_t l; - /* set a default description if none given */ - if(!desc) - desc = "miniupnpd"; - l = strlen(desc) + 1; - p = malloc(sizeof(struct rdr_desc) + l); - if(p) - { - p->next = rdr_desc_list; - p->timestamp = timestamp; - p->eport = eport; - p->proto = (short)proto; - memcpy(p->str, desc, l); - rdr_desc_list = p; - } -} - -/* delete a description from the list */ -static void -del_redirect_desc(unsigned short eport, int proto) -{ - struct rdr_desc * p, * last; - p = rdr_desc_list; - last = 0; - while(p) - { - if(p->eport == eport && p->proto == proto) - { - if(!last) - rdr_desc_list = p->next; - else - last->next = p->next; - free(p); - return; - } - last = p; - p = p->next; - } -} - -/* go through the list to find the description */ -static void -get_redirect_desc(unsigned short eport, int proto, - char * desc, int desclen, - unsigned int * timestamp) -{ - struct rdr_desc * p; - for(p = rdr_desc_list; p; p = p->next) - { - if(p->eport == eport && p->proto == (short)proto) - { - if(desc) - strncpy(desc, p->str, desclen); - if(timestamp) - *timestamp = p->timestamp; - return; - } - } - /* if no description was found, return miniupnpd as default */ - if(desc) - strncpy(desc, "miniupnpd", desclen); - if(timestamp) - *timestamp = 0; -} - -/* add_redirect_rule2() */ -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - int r; - UNUSED(ifname); - - r = addnatrule(proto, eport, iaddr, iport, rhost); - if(r >= 0) { - add_redirect_desc(eport, proto, desc, timestamp); -#ifdef ENABLE_PORT_TRIGGERING - /* http://www.netfilter.org/documentation/HOWTO/NAT-HOWTO-6.html#ss6.3 - * The default behavior is to alter the connection as little - * as possible, within the constraints of the rule given by - * the user. - * This means we won't remap ports unless we have to. */ - if(iport != eport) { - /* TODO : check if this should be done only with UDP */ - r = addmasqueraderule(proto, eport, iaddr, iport, rhost/*, ifname*/); - if(r < 0) { - syslog(LOG_NOTICE, "add_redirect_rule2(): addmasqueraderule returned %d", r); - } - } -#endif /* ENABLE_PORT_TRIGGERING */ - } - return r; -} - -/* add_peer_redirect_rule2() */ -int -add_peer_redirect_rule2(const char * ifname, - const char * rhost, unsigned short rport, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - int r; - UNUSED(ifname); - - r = addpeernatrule(proto, eaddr, eport, iaddr, iport, rhost, rport); - if(r >= 0) - add_redirect_desc(eport, proto, desc, timestamp); - return r; -} - -int -add_peer_dscp_rule2(const char * ifname, - const char * rhost, unsigned short rport, - unsigned char dscp, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - int r; - UNUSED(ifname); - UNUSED(desc); - UNUSED(timestamp); - - r = addpeerdscprule(proto, dscp, iaddr, iport, rhost, rport); -/* if(r >= 0) - add_redirect_desc(dscp, proto, desc, timestamp); */ - return r; -} - -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc) -{ - UNUSED(ifname); - UNUSED(eport); - UNUSED(desc); - - return add_filter_rule(proto, rhost, iaddr, iport); -} - -/* get_redirect_rule() - * returns -1 if the rule is not found */ -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - return get_nat_redirect_rule(miniupnpd_nat_chain, - ifname, eport, proto, - iaddr, iaddrlen, iport, - desc, desclen, - rhost, rhostlen, - timestamp, packets, bytes); -} - -int -get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int r = -1; - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_target * target; - const struct ip_nat_multi_range * mr; - const struct ipt_entry_match *match; - UNUSED(ifname); - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "get_nat_redirect_rule", iptc_strerror(errno)); - return -1; - } - if(!iptc_is_chain(nat_chain_name, h)) - { - syslog(LOG_ERR, "chain %s not found", nat_chain_name); - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(nat_chain_name, h); - e; - e = iptc_next_rule(e, h)) -#else - for(e = iptc_first_rule(nat_chain_name, &h); - e; - e = iptc_next_rule(e, &h)) -#endif - { - if(proto==e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(eport != info->dpts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(eport != info->dpts[0]) - continue; - } - target = (void *)e + e->target_offset; - /* target = ipt_get_target(e); */ - mr = (const struct ip_nat_multi_range *)&target->data[0]; - snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip)); - *iport = ntohs(mr->range[0].min.all); - get_redirect_desc(eport, proto, desc, desclen, timestamp); - if(packets) - *packets = e->counters.pcnt; - if(bytes) - *bytes = e->counters.bcnt; - /* rhost */ - if(e->ip.src.s_addr && rhost) { - snprintip(rhost, rhostlen, ntohl(e->ip.src.s_addr)); - } - r = 0; - break; - } - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return r; -} - -/* get_redirect_rule_by_index() - * return -1 when the rule was not found */ -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int r = -1; - int i = 0; - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_target * target; - const struct ip_nat_multi_range * mr; - const struct ipt_entry_match *match; - UNUSED(ifname); - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "get_redirect_rule_by_index", iptc_strerror(errno)); - return -1; - } - if(!iptc_is_chain(miniupnpd_nat_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h)) -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h)) -#endif - { - if(i==index) - { - *proto = e->ip.proto; - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - *eport = info->dpts[0]; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - *eport = info->dpts[0]; - } - target = (void *)e + e->target_offset; - mr = (const struct ip_nat_multi_range *)&target->data[0]; - snprintip(iaddr, iaddrlen, ntohl(mr->range[0].min_ip)); - *iport = ntohs(mr->range[0].min.all); - get_redirect_desc(*eport, *proto, desc, desclen, timestamp); - if(packets) - *packets = e->counters.pcnt; - if(bytes) - *bytes = e->counters.bcnt; - /* rhost */ - if(rhost && rhostlen > 0) { - if(e->ip.src.s_addr) { - snprintip(rhost, rhostlen, ntohl(e->ip.src.s_addr)); - } else { - rhost[0] = '\0'; - } - } - r = 0; - break; - } - i++; - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return r; -} - -/* get_peer_rule_by_index() - * return -1 when the rule was not found */ -int -get_peer_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, unsigned short * rport, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int r = -1; - int i = 0; - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_target * target; - const struct ip_nat_multi_range * mr; - const struct ipt_entry_match *match; - UNUSED(ifname); - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "get_peer_rule_by_index", iptc_strerror(errno)); - return -1; - } - if(!iptc_is_chain(miniupnpd_nat_postrouting_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_postrouting_chain); - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_postrouting_chain, h); - e; - e = iptc_next_rule(e, h)) -#else - for(e = iptc_first_rule(miniupnpd_nat_postrouting_chain, &h); - e; - e = iptc_next_rule(e, &h)) -#endif - { - if(i==index) - { - *proto = e->ip.proto; - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if (rport) - *rport = info->dpts[0]; - if (iport) - *iport = info->spts[0]; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if (rport) - *rport = info->dpts[0]; - if (iport) - *iport = info->spts[0]; - } - target = (void *)e + e->target_offset; - mr = (const struct ip_nat_multi_range *)&target->data[0]; - *eport = ntohs(mr->range[0].min.all); - get_redirect_desc(*eport, *proto, desc, desclen, timestamp); - if(packets) - *packets = e->counters.pcnt; - if(bytes) - *bytes = e->counters.bcnt; - /* rhost */ - if(rhost && rhostlen > 0) { - if(e->ip.dst.s_addr) { - snprintip(rhost, rhostlen, ntohl(e->ip.dst.s_addr)); - } else { - rhost[0] = '\0'; - } - } - if(iaddr && iaddrlen > 0) { - if(e->ip.src.s_addr) { - snprintip(iaddr, iaddrlen, ntohl(e->ip.src.s_addr)); - } else { - rhost[0] = '\0'; - } - } - r = 0; - break; - } - i++; - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return r; -} - -/* delete_rule_and_commit() : - * subfunction used in delete_redirect_and_filter_rules() */ -static int -delete_rule_and_commit(unsigned int index, IPTC_HANDLE h, - const char * miniupnpd_chain, - const char * logcaller) -{ - int r = 0; -#ifdef IPTABLES_143 - if(!iptc_delete_num_entry(miniupnpd_chain, index, h)) -#else - if(!iptc_delete_num_entry(miniupnpd_chain, index, &h)) -#endif - { - syslog(LOG_ERR, "%s() : iptc_delete_num_entry(): %s\n", - logcaller, iptc_strerror(errno)); - r = -1; - } -#ifdef IPTABLES_143 - else if(!iptc_commit(h)) -#else - else if(!iptc_commit(&h)) -#endif - { - syslog(LOG_ERR, "%s() : iptc_commit(): %s\n", - logcaller, iptc_strerror(errno)); - r = -1; - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return r; -} - -/* delete_redirect_and_filter_rules() - */ -int -delete_redirect_and_filter_rules(unsigned short eport, int proto) -{ - int r = -1, r2 = -1; - unsigned index = 0; - unsigned i = 0; - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_target * target; - const struct ip_nat_multi_range * mr; - const struct ipt_entry_match *match; - unsigned short iport = 0; - uint32_t iaddr = 0; - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "delete_redirect_and_filter_rules", iptc_strerror(errno)); - return -1; - } - /* First step : find the right nat rule */ - if(!iptc_is_chain(miniupnpd_nat_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto==e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(eport != info->dpts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(eport != info->dpts[0]) - continue; - } - /* get the index, the internal address and the internal port - * of the rule */ - index = i; - target = (void *)e + e->target_offset; - mr = (const struct ip_nat_multi_range *)&target->data[0]; - iaddr = mr->range[0].min_ip; - iport = ntohs(mr->range[0].min.all); - r = 0; - break; - } - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - if(r == 0) - { - syslog(LOG_INFO, "Trying to delete nat rule at index %u", index); - /* Now delete both rules */ - /* first delete the nat rule */ - h = iptc_init("nat"); - if(h) - { - r = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_redirect_rule"); - } - if((r == 0) && (h = iptc_init("filter"))) - { - i = 0; - /* we must find the right index for the filter rule */ -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_forward_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_forward_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto==e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - /*syslog(LOG_DEBUG, "filter rule #%u: %s %s", - i, match->u.user.name, inet_ntoa(e->ip.dst));*/ - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(iport != info->dpts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(iport != info->dpts[0]) - continue; - } - if(iaddr != e->ip.dst.s_addr) - continue; - index = i; - syslog(LOG_INFO, "Trying to delete filter rule at index %u", index); - r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule"); - h = NULL; - break; - } - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - } - - /*delete PEER rule*/ - if((h = iptc_init("nat"))) - { - i = 0; - /* we must find the right index for the filter rule */ -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_postrouting_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_nat_postrouting_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto==e->ip.proto) - { - target = (void *)e + e->target_offset; - mr = (const struct ip_nat_multi_range *)&target->data[0]; - syslog(LOG_DEBUG, "postrouting rule #%u: %s %s %hu", - i, target->u.user.name, inet_ntoa(e->ip.src), ntohs(mr->range[0].min.all)); - /* target->u.user.name SNAT / MASQUERADE */ - if (eport != ntohs(mr->range[0].min.all)) { - continue; - } - iaddr = e->ip.src.s_addr; - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - iport = info->spts[0]; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - iport = info->dpts[0]; - } - - index = i; - syslog(LOG_INFO, "Trying to delete peer rule at index %u", index); - r2 = delete_rule_and_commit(index, h, miniupnpd_nat_postrouting_chain, "delete_peer_rule"); - h = NULL; - break; - } - } - } - - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - /*delete DSCP rule*/ - if((r2==0)&&(h = iptc_init("mangle"))) - { - i = 0; - index = -1; - /* we must find the right index for the filter rule */ -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto==e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - /*syslog(LOG_DEBUG, "filter rule #%u: %s %s", - i, match->u.user.name, inet_ntoa(e->ip.dst));*/ - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(iport != info->spts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(iport != info->spts[0]) - continue; - } - if(iaddr != e->ip.src.s_addr) - continue; - index = i; - syslog(LOG_INFO, "Trying to delete dscp rule at index %u", index); - r2 = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_dscp_rule"); - h = NULL; - break; - } - } - if (h) - #ifdef IPTABLES_143 - iptc_free(h); - #else - iptc_free(&h); - #endif - } - - del_redirect_desc(eport, proto); - return r*r2; -} - -/* ==================================== */ -/* TODO : add the -m state --state NEW,ESTABLISHED,RELATED - * only for the filter rule */ -static struct ipt_entry_match * -get_tcp_match(unsigned short dport, unsigned short sport) -{ - struct ipt_entry_match *match; - struct ipt_tcp * tcpinfo; - size_t size; - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + IPT_ALIGN(sizeof(struct ipt_tcp)); - match = calloc(1, size); - match->u.match_size = size; - strncpy(match->u.user.name, "tcp", sizeof(match->u.user.name)); - tcpinfo = (struct ipt_tcp *)match->data; - if (sport == 0) { - tcpinfo->spts[0] = 0; /* all source ports */ - tcpinfo->spts[1] = 0xFFFF; - } else { - tcpinfo->spts[0] = sport; /* specified source port */ - tcpinfo->spts[1] = sport; - } - if (dport == 0) { - tcpinfo->dpts[0] = 0; /* all destination ports */ - tcpinfo->dpts[1] = 0xFFFF; - } else { - tcpinfo->dpts[0] = dport; /* specified destination port */ - tcpinfo->dpts[1] = dport; - } - return match; -} - -static struct ipt_entry_match * -get_udp_match(unsigned short dport, unsigned short sport) -{ - struct ipt_entry_match *match; - struct ipt_udp * udpinfo; - size_t size; - size = IPT_ALIGN(sizeof(struct ipt_entry_match)) - + IPT_ALIGN(sizeof(struct ipt_udp)); - match = calloc(1, size); - match->u.match_size = size; - strncpy(match->u.user.name, "udp", sizeof(match->u.user.name)); - udpinfo = (struct ipt_udp *)match->data; - if (sport == 0) { - udpinfo->spts[0] = 0; /* all source ports */ - udpinfo->spts[1] = 0xFFFF; - } else { - udpinfo->spts[0] = sport; /* specified source port */ - udpinfo->spts[1] = sport; - } - if (dport == 0) { - udpinfo->dpts[0] = 0; /* all destination ports */ - udpinfo->dpts[1] = 0xFFFF; - } else { - udpinfo->dpts[0] = dport; /* specified destination port */ - udpinfo->dpts[1] = dport; - } - return match; -} - -static struct ipt_entry_target * -get_dnat_target(const char * daddr, unsigned short dport) -{ - struct ipt_entry_target * target; - struct ip_nat_multi_range * mr; - struct ip_nat_range * range; - size_t size; - - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + IPT_ALIGN(sizeof(struct ip_nat_multi_range)); - target = calloc(1, size); - target->u.target_size = size; - strncpy(target->u.user.name, "DNAT", sizeof(target->u.user.name)); - /* one ip_nat_range already included in ip_nat_multi_range */ - mr = (struct ip_nat_multi_range *)&target->data[0]; - mr->rangesize = 1; - range = &mr->range[0]; - range->min_ip = range->max_ip = inet_addr(daddr); - range->flags |= IP_NAT_RANGE_MAP_IPS; - range->min.all = range->max.all = htons(dport); - range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; - return target; -} - -static struct ipt_entry_target * -get_snat_target(const char * saddr, unsigned short sport) -{ - struct ipt_entry_target * target; - struct ip_nat_multi_range * mr; - struct ip_nat_range * range; - size_t size; - - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + IPT_ALIGN(sizeof(struct ip_nat_multi_range)); - target = calloc(1, size); - target->u.target_size = size; - strncpy(target->u.user.name, "SNAT", sizeof(target->u.user.name)); - /* one ip_nat_range already included in ip_nat_multi_range */ - mr = (struct ip_nat_multi_range *)&target->data[0]; - mr->rangesize = 1; - range = &mr->range[0]; - range->min_ip = range->max_ip = inet_addr(saddr); - range->flags |= IP_NAT_RANGE_MAP_IPS; - range->min.all = range->max.all = htons(sport); - range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; - return target; -} - -static struct ipt_entry_target * -get_dscp_target(unsigned char dscp) -{ - struct ipt_entry_target * target; - struct xt_DSCP_info * di; - size_t size; - - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + IPT_ALIGN(sizeof(struct xt_DSCP_info)); - target = calloc(1, size); - target->u.target_size = size; - strncpy(target->u.user.name, "DSCP", sizeof(target->u.user.name)); - /* one ip_nat_range already included in ip_nat_multi_range */ - di = (struct xt_DSCP_info *)&target->data[0]; - di->dscp=dscp; - return target; -} - -#ifdef ENABLE_PORT_TRIGGERING -static struct ipt_entry_target * -get_masquerade_target(unsigned short port) -{ - struct ipt_entry_target * target; - struct ip_nat_multi_range * mr; - struct ip_nat_range * range; - size_t size; - - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + IPT_ALIGN(sizeof(struct ip_nat_multi_range)); - target = calloc(1, size); - target->u.target_size = size; - strncpy(target->u.user.name, "MASQUERADE", sizeof(target->u.user.name)); - /* one ip_nat_range already included in ip_nat_multi_range */ - mr = (struct ip_nat_multi_range *)&target->data[0]; - mr->rangesize = 1; - range = &mr->range[0]; - range->min.tcp.port = range->max.tcp.port = htons(port); - /*range->min.all = range->max.all = htons(port);*/ - range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; - return target; -} -#endif /* ENABLE_PORT_TRIGGERING */ - -/* iptc_init_verify_and_append() - * return 0 on success, -1 on failure */ -static int -iptc_init_verify_and_append(const char * table, - const char * miniupnpd_chain, - struct ipt_entry * e, - const char * logcaller) -{ - IPTC_HANDLE h; - h = iptc_init(table); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() error : %s\n", - logcaller, iptc_strerror(errno)); - return -1; - } - if(!iptc_is_chain(miniupnpd_chain, h)) - { - syslog(LOG_ERR, "%s() : chain %s not found", - logcaller, miniupnpd_chain); - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return -1; - } - /* iptc_insert_entry(miniupnpd_chain, e, n, h/&h) could also be used */ -#ifdef IPTABLES_143 - if(!iptc_append_entry(miniupnpd_chain, e, h)) -#else - if(!iptc_append_entry(miniupnpd_chain, e, &h)) -#endif - { - syslog(LOG_ERR, "%s() : iptc_append_entry() error : %s\n", - logcaller, iptc_strerror(errno)); - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return -1; - } -#ifdef IPTABLES_143 - if(!iptc_commit(h)) -#else - if(!iptc_commit(&h)) -#endif - { - syslog(LOG_ERR, "%s() : iptc_commit() error : %s\n", - logcaller, iptc_strerror(errno)); - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return -1; - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return 0; -} - -/* add nat rule - * iptables -t nat -A MINIUPNPD -p [-s ] --dport -j DNAT --to : - * */ -static int -addnatrule(int proto, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost) -{ - int r = 0; - struct ipt_entry * e; - struct ipt_entry * tmp; - struct ipt_entry_match *match = NULL; - struct ipt_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ipt_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) error", "addnatrule", - (int)sizeof(struct ipt_entry)); - return -1; - } - e->ip.proto = proto; - if(proto == IPPROTO_TCP) { - match = get_tcp_match(eport, 0); - } else { - match = get_udp_match(eport, 0); - } - e->nfcache = NFC_IP_DST_PT; - target = get_dnat_target(iaddr, iport); - e->nfcache |= NFC_UNKNOWN; - tmp = realloc(e, sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) error", "addnatrule", - (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ipt_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size; - /* remote host */ - if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) { - e->ip.src.s_addr = inet_addr(rhost); - e->ip.smsk.s_addr = INADDR_NONE; - } - - r = iptc_init_verify_and_append("nat", miniupnpd_nat_chain, e, "addnatrule"); - free(target); - free(match); - free(e); - return r; -} - -/* for "Port Triggering" - * Section 2.5.16 figure 2.2 in UPnP-gw-WANIPConnection-v2-Service.pdf - * - * When a control point creates a port forwarding rule with AddPortMapping() - * action for inbound traffic , this rule MUST also be applied when NAT port - * triggering occurs for outbound traffic. - * - * iptables -t nat -A MINIUPNPD-POSTROUTING {-o } -s - * -p [-d ] --sport -j MASQUERADE --to-ports - */ -#ifdef ENABLE_PORT_TRIGGERING -static int -addmasqueraderule(int proto, - unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost/*, const char * extif*/) -{ - int r = 0; - struct ipt_entry * e; - struct ipt_entry * tmp; - struct ipt_entry_match *match = NULL; - struct ipt_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ipt_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) error", "addmasqueraderule", - (int)sizeof(struct ipt_entry)); - return -1; - } - e->ip.proto = proto; - if(proto == IPPROTO_TCP) { - match = get_tcp_match(0, iport); - } else { - match = get_udp_match(0, iport); - } - e->nfcache = NFC_IP_DST_PT; - target = get_masquerade_target(eport); - e->nfcache |= NFC_UNKNOWN; - tmp = realloc(e, sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) error", "addmasqueraderule", - (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ipt_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size; -#if 0 - /* do not add outiface (-o) to rule, as the MINIUPNPD-POSTROUTING chain - * should already have matched it */ - if(extif != NULL) { - strncpy(e->ip.outiface, extif, sizeof(e->ip.outiface)); - memset(e->ip.outiface_mask, 0xff, strlen(e->ip.outiface) + 1);/* Include nul-terminator in match */ - } -#endif - /* internal host */ - if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*"))) - { - e->ip.src.s_addr = inet_addr(iaddr); - e->ip.smsk.s_addr = INADDR_NONE; - } - /* remote host */ - if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) { - e->ip.dst.s_addr = inet_addr(rhost); - e->ip.dmsk.s_addr = INADDR_NONE; - } - - r = iptc_init_verify_and_append("nat", miniupnpd_nat_postrouting_chain, e, "addmasqueraderule"); - free(target); - free(match); - free(e); - return r; -} -#endif /* ENABLE_PORT_TRIGGERING */ - -/* called by add_peer_redirect_rule2() - * - * iptables -t nat -A MINIUPNPD-POSTROUTING -s -d - * -p --sport --dport -j SNAT - * --to-source : */ -static int -addpeernatrule(int proto, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost, unsigned short rport) -{ - int r = 0; - struct ipt_entry * e; - struct ipt_entry * tmp; - struct ipt_entry_match *match = NULL; - struct ipt_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ipt_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) error", "addpeernatrule", - (int)sizeof(struct ipt_entry)); - return -1; - } - e->ip.proto = proto; - /* TODO: Fill port matches and SNAT */ - if(proto == IPPROTO_TCP) { - match = get_tcp_match(rport, iport); - } else { - match = get_udp_match(rport, iport); - } - e->nfcache = NFC_IP_DST_PT | NFC_IP_SRC_PT; - target = get_snat_target(eaddr, eport); - e->nfcache |= NFC_UNKNOWN; - tmp = realloc(e, sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) error", "addpeernatrule", - (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ipt_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size; - - /* internal host */ - if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*"))) - { - e->ip.src.s_addr = inet_addr(iaddr); - e->ip.smsk.s_addr = INADDR_NONE; - } - /* remote host */ - if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) - { - e->ip.dst.s_addr = inet_addr(rhost); - e->ip.dmsk.s_addr = INADDR_NONE; - } - - r = iptc_init_verify_and_append("nat", miniupnpd_nat_postrouting_chain, e, "addpeernatrule"); - free(target); - free(match); - free(e); - return r; -} - -/* called by add_peer_dscp_rule2() - * iptables -t mangle -A MINIUPNPD -s -d - * -p --sport --dport -j DSCP - * --set-dscp 0xXXXX */ -static int -addpeerdscprule(int proto, unsigned char dscp, - const char * iaddr, unsigned short iport, - const char * rhost, unsigned short rport) -{ - int r = 0; - struct ipt_entry * e; - struct ipt_entry * tmp; - struct ipt_entry_match *match = NULL; - struct ipt_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ipt_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) error", "addpeerdscprule", - (int)sizeof(struct ipt_entry)); - return -1; - } - e->ip.proto = proto; - /* TODO: Fill port matches and SNAT */ - if(proto == IPPROTO_TCP) { - match = get_tcp_match(rport, iport); - } else { - match = get_udp_match(rport, iport); - } - e->nfcache = NFC_IP_DST_PT | NFC_IP_SRC_PT; - target = get_dscp_target(dscp); - e->nfcache |= NFC_UNKNOWN; - tmp = realloc(e, sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) error", "addpeerdscprule", - (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ipt_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size; - - /* internal host */ - if(iaddr && (iaddr[0] != '\0') && (0 != strcmp(iaddr, "*"))) - { - e->ip.src.s_addr = inet_addr(iaddr); - e->ip.smsk.s_addr = INADDR_NONE; - } - /* remote host */ - if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) - { - e->ip.dst.s_addr = inet_addr(rhost); - e->ip.dmsk.s_addr = INADDR_NONE; - } - - r = iptc_init_verify_and_append("mangle", miniupnpd_nat_chain, e, - "addpeerDSCPrule"); - free(target); - free(match); - free(e); - return r; -} - - -/* ================================= */ -static struct ipt_entry_target * -get_accept_target(void) -{ - struct ipt_entry_target * target = NULL; - size_t size; - size = IPT_ALIGN(sizeof(struct ipt_entry_target)) - + IPT_ALIGN(sizeof(int)); - target = calloc(1, size); - target->u.user.target_size = size; - strncpy(target->u.user.name, "ACCEPT", sizeof(target->u.user.name)); - return target; -} - -/* add_filter_rule() - * iptables -t filter -A MINIUPNPD [-s ] -p -d --dport -j ACCEPT */ -static int -add_filter_rule(int proto, const char * rhost, - const char * iaddr, unsigned short iport) -{ - int r = 0; - struct ipt_entry * e; - struct ipt_entry * tmp; - struct ipt_entry_match *match = NULL; - struct ipt_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ipt_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) error", "add_filter_rule", - (int)sizeof(struct ipt_entry)); - return -1; - } - e->ip.proto = proto; - if(proto == IPPROTO_TCP) { - match = get_tcp_match(iport,0); - } else { - match = get_udp_match(iport,0); - } - e->nfcache = NFC_IP_DST_PT; - e->ip.dst.s_addr = inet_addr(iaddr); - e->ip.dmsk.s_addr = INADDR_NONE; - target = get_accept_target(); - e->nfcache |= NFC_UNKNOWN; - tmp = realloc(e, sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) error", "add_filter_rule", - (int)(sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ipt_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ipt_entry) - + match->u.match_size - + target->u.target_size; - /* remote host */ - if(rhost && (rhost[0] != '\0') && (0 != strcmp(rhost, "*"))) - { - e->ip.src.s_addr = inet_addr(rhost); - e->ip.smsk.s_addr = INADDR_NONE; - } - - r = iptc_init_verify_and_append("filter", miniupnpd_forward_chain, e, "add_filter_rule"); - free(target); - free(match); - free(e); - return r; -} - -/* return an (malloc'ed) array of "external" port for which there is - * a port mapping. number is the size of the array */ -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number) -{ - unsigned short * array; - unsigned int capacity; - unsigned short eport; - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_match *match; - - *number = 0; - capacity = 128; - array = calloc(capacity, sizeof(unsigned short)); - if(!array) - { - syslog(LOG_ERR, "%s() : calloc error", "get_portmappings_in_range"); - return NULL; - } - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "get_portmappings_in_range", iptc_strerror(errno)); - free(array); - return NULL; - } - if(!iptc_is_chain(miniupnpd_nat_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); - free(array); - array = NULL; - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h)) -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h)) -#endif - { - if(proto == e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - eport = info->dpts[0]; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - eport = info->dpts[0]; - } - if(startport <= eport && eport <= endport) - { - if(*number >= capacity) - { - unsigned short * tmp; - /* need to increase the capacity of the array */ - tmp = realloc(array, sizeof(unsigned short)*capacity); - if(!tmp) - { - syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%u) error", - (unsigned)sizeof(unsigned short)*capacity); - *number = 0; - free(array); - array = NULL; - break; - } - array = tmp; - } - array[*number] = eport; - (*number)++; - } - } - } - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return array; -} - -int -update_portmapping_desc_timestamp(const char * ifname, - unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - UNUSED(ifname); - del_redirect_desc(eport, proto); - add_redirect_desc(eport, proto, desc, timestamp); - return 0; -} - -static int -update_rule_and_commit(const char * table, const char * chain, - unsigned index, const struct ipt_entry * e) -{ - IPTC_HANDLE h; - int r = 0; - - h = iptc_init(table); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "update_rule_and_commit", iptc_strerror(errno)); - return -1; - } -#ifdef IPTABLES_143 - if(!iptc_replace_entry(chain, e, index, h)) -#else - if(!iptc_replace_entry(chain, e, index, &h)) -#endif - { - syslog(LOG_ERR, "%s(): iptc_replace_entry: %s", - "update_rule_and_commit", iptc_strerror(errno)); - r = -1; - } -#ifdef IPTABLES_143 - else if(!iptc_commit(h)) -#else - else if(!iptc_commit(&h)) -#endif - { - syslog(LOG_ERR, "%s(): iptc_commit: %s", - "update_rule_and_commit", iptc_strerror(errno)); - r = -1; - } -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return r; -} - -int -update_portmapping(const char * ifname, unsigned short eport, int proto, - unsigned short iport, const char * desc, - unsigned int timestamp) -{ - int r = 0; - int found = 0; - unsigned index = 0; - unsigned i = 0; - IPTC_HANDLE h; - const struct ipt_entry * e; - struct ipt_entry * new_e = NULL; - size_t entry_len; - const struct ipt_entry_target * target; - struct ip_nat_multi_range * mr; - const struct ipt_entry_match *match; - uint32_t iaddr = 0; - unsigned short old_iport = 0; - - h = iptc_init("nat"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "update_portmapping", iptc_strerror(errno)); - return -1; - } - /* First step : find the right nat rule */ - if(!iptc_is_chain(miniupnpd_nat_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_nat_chain); - r = -1; - } - else - { -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto==e->ip.proto) - { - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(eport != info->dpts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(eport != info->dpts[0]) - continue; - } - /* we found the right rule */ - found = 1; - index = i; - target = (void *)e + e->target_offset; - mr = (struct ip_nat_multi_range *)&target->data[0]; - iaddr = mr->range[0].min_ip; - old_iport = ntohs(mr->range[0].min.all); - entry_len = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; - new_e = malloc(entry_len); - if(new_e == NULL) { - syslog(LOG_ERR, "%s: malloc(%u) error", - "update_portmapping", (unsigned)entry_len); - r = -1; - } - else - { - memcpy(new_e, e, entry_len); - } - break; - } - } - } -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - if(!found || r < 0) - return -1; - syslog(LOG_INFO, "Trying to update nat rule at index %u", index); - target = (void *)new_e + new_e->target_offset; - mr = (struct ip_nat_multi_range *)&target->data[0]; - mr->range[0].min.all = mr->range[0].max.all = htons(iport); - /* first update the nat rule */ - r = update_rule_and_commit("nat", miniupnpd_nat_chain, index, new_e); - free(new_e); new_e = NULL; - if(r < 0) - return r; - - /* update filter rule */ - h = iptc_init("filter"); - if(!h) - { - syslog(LOG_ERR, "%s() : iptc_init() failed : %s", - "update_portmapping", iptc_strerror(errno)); - return -1; - } - i = 0; found = 0; - if(!iptc_is_chain(miniupnpd_forward_chain, h)) - { - syslog(LOG_ERR, "chain %s not found", miniupnpd_forward_chain); - } - else - { - /* we must find the right index for the filter rule */ -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_forward_chain, h); - e; - e = iptc_next_rule(e, h), i++) -#else - for(e = iptc_first_rule(miniupnpd_forward_chain, &h); - e; - e = iptc_next_rule(e, &h), i++) -#endif - { - if(proto!=e->ip.proto) - continue; - target = (void *)e + e->target_offset; - match = (const struct ipt_entry_match *)&e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - const struct ipt_tcp * info; - info = (const struct ipt_tcp *)match->data; - if(old_iport != info->dpts[0]) - continue; - } - else - { - const struct ipt_udp * info; - info = (const struct ipt_udp *)match->data; - if(old_iport != info->dpts[0]) - continue; - } - if(iaddr != e->ip.dst.s_addr) - continue; - index = i; - found = 1; - entry_len = sizeof(struct ipt_entry) + match->u.match_size + target->u.target_size; - new_e = malloc(entry_len); - if(new_e == NULL) { - syslog(LOG_ERR, "%s: malloc(%u) error", - "update_portmapping", (unsigned)entry_len); - r = -1; - } else { - memcpy(new_e, e, entry_len); - } - break; - } - } -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - if(!found || r < 0) - return -1; - - syslog(LOG_INFO, "Trying to update filter rule at index %u", index); - match = (struct ipt_entry_match *)&new_e->elems; - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - struct ipt_tcp * info; - info = (struct ipt_tcp *)match->data; - info->dpts[0] = info->dpts[1] = iport; - } - else - { - struct ipt_udp * info; - info = (struct ipt_udp *)match->data; - info->dpts[0] = info->dpts[1] = iport; - } - r = update_rule_and_commit("filter", miniupnpd_forward_chain, index, new_e); - free(new_e); new_e = NULL; - if(r < 0) - return r; - - return update_portmapping_desc_timestamp(ifname, eport, proto, desc, timestamp); -} - -/* ================================ */ -#ifdef DEBUG -static int -print_match(const struct ipt_entry_match *match) -{ - printf("match %s :\n", match->u.user.name); - if(0 == strncmp(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN)) - { - struct ipt_tcp * tcpinfo; - tcpinfo = (struct ipt_tcp *)match->data; - printf(" srcport = %hu:%hu dstport = %hu:%hu\n", - tcpinfo->spts[0], tcpinfo->spts[1], - tcpinfo->dpts[0], tcpinfo->dpts[1]); - } - else if(0 == strncmp(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN)) - { - struct ipt_udp * udpinfo; - udpinfo = (struct ipt_udp *)match->data; - printf(" srcport = %hu:%hu dstport = %hu:%hu\n", - udpinfo->spts[0], udpinfo->spts[1], - udpinfo->dpts[0], udpinfo->dpts[1]); - } - return 0; -} - -static void -print_iface(const char * iface, const unsigned char * mask, int invert) -{ - unsigned i; - if(mask[0] == 0) - return; - if(invert) - printf("! "); - for(i=0; i> 24, (ip >> 16) & 0xff, - (ip >> 8) & 0xff, ip & 0xff); -} - -/* for debug */ -/* read the "filter" and "nat" tables */ -int -list_redirect_rule(const char * ifname) -{ - IPTC_HANDLE h; - const struct ipt_entry * e; - const struct ipt_entry_target * target; - const struct ip_nat_multi_range * mr; - const char * target_str; - char addr[16], mask[16]; - unsigned int index; - (void)ifname; - - h = iptc_init("nat"); - if(!h) - { - printf("iptc_init() error : %s\n", iptc_strerror(errno)); - return -1; - } - if(!iptc_is_chain(miniupnpd_nat_chain, h)) - { - printf("chain %s not found\n", miniupnpd_nat_chain); -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - return -1; - } - index = 0; -#ifdef IPTABLES_143 - for(e = iptc_first_rule(miniupnpd_nat_chain, h); - e; - e = iptc_next_rule(e, h)) - { - target_str = iptc_get_target(e, h); -#else - for(e = iptc_first_rule(miniupnpd_nat_chain, &h); - e; - e = iptc_next_rule(e, &h)) - { - target_str = iptc_get_target(e, &h); -#endif - printf("=== rule #%u ===\n", index); - inet_ntop(AF_INET, &e->ip.src, addr, sizeof(addr)); - inet_ntop(AF_INET, &e->ip.smsk, mask, sizeof(mask)); - printf("src = %s%s/%s\t", (e->ip.invflags & IPT_INV_SRCIP)?"! ":"", - /*inet_ntoa(e->ip.src), inet_ntoa(e->ip.smsk)*/ - addr, mask); - inet_ntop(AF_INET, &e->ip.dst, addr, sizeof(addr)); - inet_ntop(AF_INET, &e->ip.dmsk, mask, sizeof(mask)); - printf("dst = %s%s/%s\n", (e->ip.invflags & IPT_INV_DSTIP)?"! ":"", - /*inet_ntoa(e->ip.dst), inet_ntoa(e->ip.dmsk)*/ - addr, mask); - /*printf("in_if = %s out_if = %s\n", e->ip.iniface, e->ip.outiface);*/ - printf("in_if = "); - print_iface(e->ip.iniface, e->ip.iniface_mask, - e->ip.invflags & IPT_INV_VIA_IN); - printf("\tout_if = "); - print_iface(e->ip.outiface, e->ip.outiface_mask, - e->ip.invflags & IPT_INV_VIA_OUT); - printf("\n"); - printf("ip.proto = %s%d\n", (e->ip.invflags & IPT_INV_PROTO)?"! ":"", - e->ip.proto); - /* display matches stuff */ - if(e->target_offset) - { - IPT_MATCH_ITERATE(e, print_match); - /*printf("\n");*/ - } - printf("target = %s :\n", target_str); - target = (void *)e + e->target_offset; - mr = (const struct ip_nat_multi_range *)&target->data[0]; - printf(" ips "); - printip(ntohl(mr->range[0].min_ip)); - printf(" "); - printip(ntohl(mr->range[0].max_ip)); - printf("\n ports %hu %hu\n", ntohs(mr->range[0].min.all), - ntohs(mr->range[0].max.all)); - printf(" flags = %x\n", mr->range[0].flags); - index++; - } - if(h) -#ifdef IPTABLES_143 - iptc_free(h); -#else - iptc_free(&h); -#endif - printf("======\n"); - return 0; -} -#endif diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.h b/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.h deleted file mode 100644 index 21d5405..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptcrdr.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id: iptcrdr.h,v 1.18 2012/03/05 20:36:20 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef IPTCRDR_H_INCLUDED -#define IPTCRDR_H_INCLUDED - -#include "../commonrdr.h" - -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -add_peer_redirect_rule2(const char * ifname, - const char * rhost, unsigned short rport, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc); - -int -delete_redirect_and_filter_rules(unsigned short eport, int proto); - -int -add_peer_dscp_rule2(const char * ifname, - const char * rhost, unsigned short rport, - unsigned char dscp, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr* ret_ext); -int -get_peer_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, unsigned short * rport, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); -int -get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -/* for debug */ -int -list_redirect_rule(const char * ifname); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.c b/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.c deleted file mode 100644 index 2f5fc08..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.c +++ /dev/null @@ -1,484 +0,0 @@ -/* $Id: iptpinhole.c,v 1.18 2018/03/13 23:05:21 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include - -#include "../config.h" -#include "../macros.h" -#include "iptpinhole.h" -#include "../upnpglobalvars.h" -#include "../upnputils.h" - -#ifdef ENABLE_UPNPPINHOLE - -#include -#include -#include "tiny_nf_nat.h" - -#define IP6TC_HANDLE struct ip6tc_handle * - -static int next_uid = 1; - -static LIST_HEAD(pinhole_list_t, pinhole_t) pinhole_list; - -static struct pinhole_t * -get_pinhole(unsigned short uid); - -struct pinhole_t { - struct in6_addr saddr; - struct in6_addr daddr; - LIST_ENTRY(pinhole_t) entries; - unsigned int timestamp; - unsigned short sport; - unsigned short dport; - unsigned short uid; - unsigned char proto; - char desc[]; -}; - -void init_iptpinhole(void) -{ - LIST_INIT(&pinhole_list); -} - -void shutdown_iptpinhole(void) -{ - struct pinhole_t * p; - while(pinhole_list.lh_first != NULL) { - p = pinhole_list.lh_first; - LIST_REMOVE(p, entries); - free(p); - } -} - -/* return uid */ -static int -add_to_pinhole_list(struct in6_addr * saddr, unsigned short sport, - struct in6_addr * daddr, unsigned short dport, - int proto, const char *desc, unsigned int timestamp) -{ - struct pinhole_t * p; - - p = calloc(1, sizeof(struct pinhole_t) + strlen(desc) + 1); - if(!p) { - syslog(LOG_ERR, "add_to_pinhole_list calloc() error"); - return -1; - } - strcpy(p->desc, desc); - memcpy(&p->saddr, saddr, sizeof(struct in6_addr)); - p->sport = sport; - memcpy(&p->daddr, daddr, sizeof(struct in6_addr)); - p->dport = dport; - p->timestamp = timestamp; - p->proto = (unsigned char)proto; - LIST_INSERT_HEAD(&pinhole_list, p, entries); - while(get_pinhole(next_uid) != NULL) { - next_uid++; - if(next_uid > 65535) - next_uid = 1; - } - p->uid = next_uid; - next_uid++; - if(next_uid > 65535) - next_uid = 1; - return p->uid; -} - -static struct pinhole_t * -get_pinhole(unsigned short uid) -{ - struct pinhole_t * p; - - for(p = pinhole_list.lh_first; p != NULL; p = p->entries.le_next) { - if(p->uid == uid) - return p; - } - return NULL; /* not found */ -} - -/* new_match() - * Allocate and set a new ip6t_entry_match structure - * The caller must free() it after usage */ -static struct ip6t_entry_match * -new_match(int proto, unsigned short sport, unsigned short dport) -{ - struct ip6t_entry_match *match; - struct ip6t_tcp *info; /* TODO : use ip6t_udp if needed */ - size_t size; - const char * name; - size = XT_ALIGN(sizeof(struct ip6t_entry_match)) - + XT_ALIGN(sizeof(struct ip6t_tcp)); - match = calloc(1, size); - match->u.user.match_size = size; - switch(proto) { - case IPPROTO_TCP: - name = "tcp"; - break; - case IPPROTO_UDP: - name = "udp"; - break; - case IPPROTO_UDPLITE: - name = "udplite"; - break; - default: - name = NULL; - } - if(name) - strncpy(match->u.user.name, name, sizeof(match->u.user.name)); - else - syslog(LOG_WARNING, "no name for protocol %d", proto); - info = (struct ip6t_tcp *)match->data; - if(sport) { - info->spts[0] = sport; /* specified source port */ - info->spts[1] = sport; - } else { - info->spts[0] = 0; /* all source ports */ - info->spts[1] = 0xFFFF; - } - info->dpts[0] = dport; /* specified destination port */ - info->dpts[1] = dport; - return match; -} - -static struct ip6t_entry_target * -get_accept_target(void) -{ - struct ip6t_entry_target * target = NULL; - size_t size; - size = XT_ALIGN(sizeof(struct ip6t_entry_target)) - + XT_ALIGN(sizeof(int)); - target = calloc(1, size); - target->u.user.target_size = size; - strncpy(target->u.user.name, "ACCEPT", sizeof(target->u.user.name)); - return target; -} - -static int -ip6tc_init_verify_append(const char * table, - const char * chain, - struct ip6t_entry * e) -{ - IP6TC_HANDLE h; - - h = ip6tc_init(table); - if(!h) { - syslog(LOG_ERR, "ip6tc_init error : %s", ip6tc_strerror(errno)); - return -1; - } - if(!ip6tc_is_chain(chain, h)) { - syslog(LOG_ERR, "chain %s not found", chain); - goto error; - } - if(!ip6tc_append_entry(chain, e, h)) { - syslog(LOG_ERR, "ip6tc_append_entry() error : %s", ip6tc_strerror(errno)); - goto error; - } - if(!ip6tc_commit(h)) { - syslog(LOG_ERR, "ip6tc_commit() error : %s", ip6tc_strerror(errno)); - goto error; - } - return 0; /* ok */ -error: - ip6tc_free(h); - return -1; -} - -/* -ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT -ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT - -miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport - -ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE -ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE -*/ -int add_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, const char * desc, unsigned int timestamp) -{ - int uid; - struct ip6t_entry * e; - struct ip6t_entry * tmp; - struct ip6t_entry_match *match = NULL; - struct ip6t_entry_target *target = NULL; - - e = calloc(1, sizeof(struct ip6t_entry)); - if(!e) { - syslog(LOG_ERR, "%s: calloc(%d) failed", - "add_pinhole", (int)sizeof(struct ip6t_entry)); - return -1; - } - e->ipv6.proto = proto; - if (proto) - e->ipv6.flags |= IP6T_F_PROTO; - - /* TODO: check if enforcing USE_IFNAME_IN_RULES is needed */ - if(ifname) - strncpy(e->ipv6.iniface, ifname, IFNAMSIZ); - if(rem_host && (rem_host[0] != '\0')) { - inet_pton(AF_INET6, rem_host, &e->ipv6.src); - memset(&e->ipv6.smsk, 0xff, sizeof(e->ipv6.smsk)); - } - inet_pton(AF_INET6, int_client, &e->ipv6.dst); - memset(&e->ipv6.dmsk, 0xff, sizeof(e->ipv6.dmsk)); - - /*e->nfcache = NFC_IP_DST_PT;*/ - /*e->nfcache |= NFC_UNKNOWN;*/ - - match = new_match(proto, rem_port, int_port); - target = get_accept_target(); - tmp = realloc(e, sizeof(struct ip6t_entry) - + match->u.match_size - + target->u.target_size); - if(!tmp) { - syslog(LOG_ERR, "%s: realloc(%d) failed", - "add_pinhole", (int)(sizeof(struct ip6t_entry) + match->u.match_size + target->u.target_size)); - free(e); - free(match); - free(target); - return -1; - } - e = tmp; - memcpy(e->elems, match, match->u.match_size); - memcpy(e->elems + match->u.match_size, target, target->u.target_size); - e->target_offset = sizeof(struct ip6t_entry) - + match->u.match_size; - e->next_offset = sizeof(struct ip6t_entry) - + match->u.match_size - + target->u.target_size; - free(match); - free(target); - - if(ip6tc_init_verify_append("filter", miniupnpd_v6_filter_chain, e) < 0) { - free(e); - return -1; - } - uid = add_to_pinhole_list(&e->ipv6.src, rem_port, - &e->ipv6.dst, int_port, - proto, desc, timestamp); - free(e); - return uid; -} - -int -find_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, - char *desc, int desc_len, unsigned int * timestamp) -{ - struct pinhole_t * p; - struct in6_addr saddr; - struct in6_addr daddr; - UNUSED(ifname); - - if(rem_host && (rem_host[0] != '\0')) { - inet_pton(AF_INET6, rem_host, &saddr); - } else { - memset(&saddr, 0, sizeof(struct in6_addr)); - } - inet_pton(AF_INET6, int_client, &daddr); - for(p = pinhole_list.lh_first; p != NULL; p = p->entries.le_next) { - if((proto == p->proto) && (rem_port == p->sport) && - (0 == memcmp(&saddr, &p->saddr, sizeof(struct in6_addr))) && - (int_port == p->dport) && - (0 == memcmp(&daddr, &p->daddr, sizeof(struct in6_addr)))) { - if(desc) strncpy(desc, p->desc, desc_len); - if(timestamp) *timestamp = p->timestamp; - return (int)p->uid; - } - } - return -2; /* not found */ -} - -int -delete_pinhole(unsigned short uid) -{ - struct pinhole_t * p; - IP6TC_HANDLE h; - const struct ip6t_entry * e; - const struct ip6t_entry_match *match = NULL; - /*const struct ip6t_entry_target *target = NULL;*/ - unsigned int index; - - p = get_pinhole(uid); - if(!p) - return -2; /* not found */ - - h = ip6tc_init("filter"); - if(!h) { - syslog(LOG_ERR, "ip6tc_init error : %s", ip6tc_strerror(errno)); - return -1; - } - if(!ip6tc_is_chain(miniupnpd_v6_filter_chain, h)) { - syslog(LOG_ERR, "chain %s not found", miniupnpd_v6_filter_chain); - goto error; - } - index = 0; - for(e = ip6tc_first_rule(miniupnpd_v6_filter_chain, h); - e; - e = ip6tc_next_rule(e, h)) { - if((e->ipv6.proto == p->proto) && - (0 == memcmp(&e->ipv6.src, &p->saddr, sizeof(e->ipv6.src))) && - (0 == memcmp(&e->ipv6.dst, &p->daddr, sizeof(e->ipv6.dst)))) { - const struct ip6t_tcp * info; - match = (const struct ip6t_entry_match *)&e->elems; - info = (const struct ip6t_tcp *)&match->data; - if((info->spts[0] == p->sport) && (info->dpts[0] == p->dport)) { - if(!ip6tc_delete_num_entry(miniupnpd_v6_filter_chain, index, h)) { - syslog(LOG_ERR, "ip6tc_delete_num_entry(%s,%u,...): %s", - miniupnpd_v6_filter_chain, index, ip6tc_strerror(errno)); - goto error; - } - if(!ip6tc_commit(h)) { - syslog(LOG_ERR, "ip6tc_commit(): %s", - ip6tc_strerror(errno)); - goto error; - } - ip6tc_free(h); - LIST_REMOVE(p, entries); - return 0; /* ok */ - } - } - index++; - } - ip6tc_free(h); - syslog(LOG_WARNING, "delete_pinhole() rule with PID=%hu not found", uid); - LIST_REMOVE(p, entries); - return -2; /* not found */ -error: - ip6tc_free(h); - return -1; -} - -int -update_pinhole(unsigned short uid, unsigned int timestamp) -{ - struct pinhole_t * p; - - p = get_pinhole(uid); - if(p) { - p->timestamp = timestamp; - return 0; - } else { - return -2; /* Not found */ - } -} - -int -get_pinhole_info(unsigned short uid, - char * rem_host, int rem_hostlen, - unsigned short * rem_port, - char * int_client, int int_clientlen, - unsigned short * int_port, - int * proto, char * desc, int desclen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - struct pinhole_t * p; - - p = get_pinhole(uid); - if(!p) - return -2; /* Not found */ - if(rem_host && (rem_host[0] != '\0')) { - if(inet_ntop(AF_INET6, &p->saddr, rem_host, rem_hostlen) == NULL) - return -1; - } - if(rem_port) - *rem_port = p->sport; - if(int_client) { - if(inet_ntop(AF_INET6, &p->daddr, int_client, int_clientlen) == NULL) - return -1; - } - if(int_port) - *int_port = p->dport; - if(proto) - *proto = p->proto; - if(timestamp) - *timestamp = p->timestamp; - if (desc) - strncpy(desc, p->desc, desclen); - if(packets || bytes) { - /* theses informations need to be read from netfilter */ - IP6TC_HANDLE h; - const struct ip6t_entry * e; - const struct ip6t_entry_match * match; - h = ip6tc_init("filter"); - if(!h) { - syslog(LOG_ERR, "ip6tc_init error : %s", ip6tc_strerror(errno)); - return -1; - } - for(e = ip6tc_first_rule(miniupnpd_v6_filter_chain, h); - e; - e = ip6tc_next_rule(e, h)) { - if((e->ipv6.proto == p->proto) && - (0 == memcmp(&e->ipv6.src, &p->saddr, sizeof(e->ipv6.src))) && - (0 == memcmp(&e->ipv6.dst, &p->daddr, sizeof(e->ipv6.dst)))) { - const struct ip6t_tcp * info; - match = (const struct ip6t_entry_match *)&e->elems; - info = (const struct ip6t_tcp *)&match->data; - if((info->spts[0] == p->sport) && (info->dpts[0] == p->dport)) { - if(packets) - *packets = e->counters.pcnt; - if(bytes) - *bytes = e->counters.bcnt; - break; - } - } - } - ip6tc_free(h); - } - return 0; -} - -int get_pinhole_uid_by_index(int index) -{ - struct pinhole_t * p; - - for(p = pinhole_list.lh_first; p != NULL; p = p->entries.le_next) - if (!index--) - return p->uid; - return -1; -} - -int -clean_pinhole_list(unsigned int * next_timestamp) -{ - unsigned int min_ts = UINT_MAX; - struct pinhole_t * p; - time_t current_time; - int n = 0; - - current_time = upnp_time(); - p = pinhole_list.lh_first; - while(p != NULL) { - if(p->timestamp <= (unsigned int)current_time) { - unsigned short uid = p->uid; - syslog(LOG_INFO, "removing expired pinhole with uid=%hu", uid); - p = p->entries.le_next; - if(delete_pinhole(uid) == 0) - n++; - else - break; - } else { - if(p->timestamp < min_ts) - min_ts = p->timestamp; - p = p->entries.le_next; - } - } - if(next_timestamp && (min_ts != UINT_MAX)) - *next_timestamp = min_ts; - return n; -} - -#endif /* ENABLE_UPNPPINHOLE */ diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.h b/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.h deleted file mode 100644 index 55f91a6..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/iptpinhole.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $Id: iptpinhole.h,v 1.5 2012/05/08 20:41:45 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef IPTPINHOLE_H_INCLUDED -#define IPTPINHOLE_H_INCLUDED - -#ifdef ENABLE_UPNPPINHOLE -#include - -int find_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, - char *desc, int desc_len, unsigned int * timestamp); - -int add_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, const char *desc, unsigned int timestamp); - -int update_pinhole(unsigned short uid, unsigned int timestamp); - -int delete_pinhole(unsigned short uid); - -int -get_pinhole_info(unsigned short uid, - char * rem_host, int rem_hostlen, unsigned short * rem_port, - char * int_client, int int_clientlen, - unsigned short * int_port, - int * proto, char * desc, int desclen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -int get_pinhole_uid_by_index(int index); - -int clean_pinhole_list(unsigned int * next_timestamp); - -#endif /* ENABLE_UPNPPINHOLE */ - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/miniupnpd_functions.sh b/src/contrib/miniupnp/miniupnpd/netfilter/miniupnpd_functions.sh deleted file mode 100644 index 20c7a1c..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/miniupnpd_functions.sh +++ /dev/null @@ -1,64 +0,0 @@ -#! /bin/sh -# $Id: miniupnpd_functions.sh,v 1.1 2018/02/24 12:15:19 nanard Exp $ - -IP=$(which ip) || { - echo "Can't find ip" >&2 - exit 1 -} -if [ -z "$IPV6" ]; then - IPTABLES=$(which iptables) || { - echo "Can't find iptables" >&2 - exit 1 - } - IP="$IP -4" -else - IPTABLES=$(which ip6tables) || { - echo "Can't find ip6tables" >&2 - exit 1 - } - IP="$IP -6" -fi - -CHAIN=MINIUPNPD -CLEAN= - -while getopts ":c:i:f" opt; do - case $opt in - c) - CHAIN=$OPTARG - ;; - i) - EXTIF=$OPTARG - ;; - f) - CLEAN=yes - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 - ;; - esac -done - -if [ -n "$EXT" ]; then - if [ -z "$EXTIF" ]; then - EXTIF=$(LC_ALL=C $IP route | grep 'default' | sed -e 's/.*dev[[:space:]]*//' -e 's/[[:space:]].*//') || { - echo "Can't find default interface" >&2 - exit 1 - } - fi - #if [ -z "$IPV6" ]; then - # EXTIP=$(LC_ALL=C $IP addr show $EXTIF | awk '/inet/ { print $2 }' | cut -d "/" -f 1) - #fi -fi - -FDIRTY=$(LC_ALL=C $IPTABLES -t filter -L -n | awk "/$CHAIN/ {printf \$1}") -if [ -z "$IPV6" ]; then - NDIRTY=$(LC_ALL=C $IPTABLES -t nat -L -n | awk "/$CHAIN/ {printf \$1}") - MDIRTY=$(LC_ALL=C $IPTABLES -t mangle -L -n | awk "/$CHAIN/ {printf \$1}") - NPDIRTY=$(LC_ALL=C $IPTABLES -t nat -L -n | awk "/$CHAIN-POSTROUTING/ {printf \$1}") -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/nfct_get.c b/src/contrib/miniupnp/miniupnpd/netfilter/nfct_get.c deleted file mode 100644 index cbffd28..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/nfct_get.c +++ /dev/null @@ -1,258 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef USE_NFCT -#include -#include - -#include - -struct data_cb_s -{ - struct sockaddr_storage * ext; - uint8_t found; -}; - -static int data_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nf_conntrack *ct; - struct data_cb_s * d = (struct data_cb_s*) data; - struct sockaddr_in* ext4 = (struct sockaddr_in*) d->ext; - - ct = nfct_new(); - if (ct == NULL) - return MNL_CB_OK; - nfct_nlmsg_parse(nlh, ct); - - if (data) { - ext4->sin_addr.s_addr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST); - ext4->sin_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); - } - d->found = 1; - nfct_destroy(ct); - - return MNL_CB_OK; -} - -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr_storage* ret_ext) -{ - struct mnl_socket *nl; - struct nlmsghdr *nlh; - struct nfgenmsg *nfh; - char buf[MNL_SOCKET_BUFFER_SIZE]; - unsigned int seq, portid; - struct nf_conntrack *ct; - int ret; - struct data_cb_s data; - - if ((!src)&&(!dst)) { - return 0; - } - - if (src->sa_family != dst->sa_family) { - return 0; - } - - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { -// perror("mnl_socket_open"); - goto free_nl; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { -// perror("mnl_socket_bind"); - goto free_nl; - } - portid = mnl_socket_get_portid(nl); - - memset(buf, 0, sizeof(buf)); - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET; - nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - - nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); - nfh->nfgen_family = src->sa_family; - nfh->version = NFNETLINK_V0; - nfh->res_id = 0; - - ct = nfct_new(); - if (ct == NULL) { - goto free_nl; - } - - nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family); - if (src->sa_family == AF_INET) { - struct sockaddr_in *src4 = (struct sockaddr_in *)src; - struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; - nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr); - nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr); - nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port); - nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port); - } else if (src->sa_family == AF_INET6) { - struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src; - struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; - nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr); - nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr); - nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port); - nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port); - } - nfct_set_attr_u8(ct, ATTR_L4PROTO, proto); - - nfct_nlmsg_build(nlh, ct); - - ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); - if (ret == -1) { - goto free_ct; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - data.ext = ret_ext; - data.found = 0; - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data); - if (ret <= MNL_CB_STOP) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - -free_ct: - nfct_destroy(ct); -free_nl: - mnl_socket_close(nl); - - return data.found; -} - -#else -#define DST "dst=" -#define DST_PORT "dport=" -#define SRC "src=" -#define SRC_PORT "sport=" -#define IP_CONNTRACK_LOCATION "/proc/net/ip_conntrack" -#define NF_CONNTRACK_LOCATION "/proc/net/nf_conntrack" - -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr_storage* ret_ext) -{ - FILE *f; - int af; - - if (!src) - return -2; - - af = src->sa_family; - - if ((f = fopen(NF_CONNTRACK_LOCATION, "r")) == NULL) { - if ((f = fopen(IP_CONNTRACK_LOCATION, "r")) == NULL) { - printf("could not read info about connections from the kernel, " - "make sure netfilter is enabled in kernel or by modules.\n"); - return -1; - } - } - - while (!feof(f)) { - char line[256], *str; - memset(line, 0, sizeof(line)); - str = fgets(line, sizeof(line), f); - if (line[0] != 0) { - char *token, *saveptr; - int j; - uint8_t src_f, src_port_f, dst_f, dst_port_f; - src_f=src_port_f=dst_f=dst_port_f=0; - - for (j = 1; ; j++, str = NULL) { - token = strtok_r(str, " ", &saveptr); - if (token == NULL) - break; - - if ((j==2)&&(af!=atoi(token))) - break; - if ((j==4)&&(proto!=atoi(token))) - break; - if (j<=4) - continue; - - if (strncmp(token, SRC, sizeof(SRC) - 1) == 0) { - char *srcip = token + sizeof(SRC) - 1; - uint32_t buf[4]; - memset(buf,0,sizeof(buf)); - - if (inet_pton(af, srcip, buf)!=1) - break; - - if (af==AF_INET) { - struct sockaddr_in *src4=(struct sockaddr_in*)src; - if (!src_f) { - if (src4->sin_addr.s_addr != buf[0]) - break; - src_f = 1; - } - } - } - if (strncmp(token, SRC_PORT, sizeof(SRC_PORT) - 1) == 0) { - char *src_port = token + sizeof(SRC_PORT) - 1; - uint16_t port=atoi(src_port); - - if (af==AF_INET) { - struct sockaddr_in *src4=(struct sockaddr_in*)src; - if (!src_port_f) { - if (ntohs(src4->sin_port) != port) - break; - src_port_f = 1; - } - } - } - - if (strncmp(token, DST, sizeof(DST) - 1) == 0) { - char *dstip = token + sizeof(DST) - 1; - uint32_t buf[4]; - memset(buf,0,sizeof(buf)); - if (inet_pton(af, dstip, buf)!=1) - break; - if (af==AF_INET) { - struct sockaddr_in *dst4=(struct sockaddr_in*)dst; - if (!dst_f) { - if (dst4->sin_addr.s_addr != buf[0]) - break; - dst_f = 1; - } else { - struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext; - ret_ext->ss_family = AF_INET; - ret4->sin_addr.s_addr = buf[0]; - } - } - } - if (strncmp(token, DST_PORT, sizeof(DST_PORT)-1) == 0) { - char *dst_port = token + sizeof(DST_PORT) - 1; - uint16_t port=atoi(dst_port); - if (af==AF_INET) { - struct sockaddr_in *dst4=(struct sockaddr_in*)dst; - if (!dst_port_f) { - if (ntohs(dst4->sin_port) != port) - break; - dst_port_f = 1; - } else { - struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext; - ret_ext->ss_family = AF_INET; - ret4->sin_port = htons(port); - } - } - } - } - if (src_f && src_port_f && dst_f && dst_port_f) { - fclose(f); - return 1; - } - } - } - fclose(f); - - return 0; -} -#endif diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/test_nfct_get.c b/src/contrib/miniupnp/miniupnpd/netfilter/test_nfct_get.c deleted file mode 100644 index af8c07d..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/test_nfct_get.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "nfct_get.c" - -int main(int argc, char *argv[]) -{ - struct sockaddr_storage src, dst, ext; - char buff[INET6_ADDRSTRLEN]; - - if (argc!=5) - return 0; - - if (1 != inet_pton(AF_INET, argv[1], - &((struct sockaddr_in*)&src)->sin_addr)) { - if (1 != inet_pton(AF_INET6, argv[1], - &((struct sockaddr_in6*) &src)->sin6_addr)) { - perror("bad input param"); - } else { - ((struct sockaddr_in6*)(&src))->sin6_port = htons(atoi(argv[2])); - src.ss_family = AF_INET6; - } - } else { - ((struct sockaddr_in*)(&src))->sin_port = htons(atoi(argv[2])); - src.ss_family = AF_INET; - } - - if (1 != inet_pton(AF_INET, argv[3], - &((struct sockaddr_in*)&dst)->sin_addr)) { - if (1 != inet_pton(AF_INET6, argv[3], - &((struct sockaddr_in6*) &dst)->sin6_addr)) { - perror("bad input param"); - } else { - ((struct sockaddr_in6*)(&dst))->sin6_port = htons(atoi(argv[4])); - dst.ss_family = AF_INET6; - } - } else { - ((struct sockaddr_in*)(&dst))->sin_port = htons(atoi(argv[4])); - dst.ss_family = AF_INET; - } - - if (get_nat_ext_addr((struct sockaddr*)&src, (struct sockaddr*)&dst, - IPPROTO_TCP, &ext)) { - printf("Ext address %s:%d\n", - inet_ntop(src.ss_family, - &((struct sockaddr_in*)&ext)->sin_addr, - buff, sizeof(buff)), - ntohs(((struct sockaddr_in*)(&ext))->sin_port)); - } else { - printf("no entry\n"); - } - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr.c b/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr.c deleted file mode 100644 index 59663f7..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr.c +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id: testiptcrdr.c,v 1.21 2016/02/12 12:35:50 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include - -#include "iptcrdr.c" -/*#include "../commonrdr.h"*/ - -#ifndef PRIu64 -#define PRIu64 "llu" -#endif - -int -main(int argc, char ** argv) -{ - unsigned short eport, iport; - const char * iaddr; - int r; - int proto = IPPROTO_TCP; - printf("Usage %s [TCP/UDP]\n", argv[0]); - - if(argc<4) - return -1; - openlog("testiptcrdr", LOG_PERROR|LOG_CONS, LOG_LOCAL0); - if(init_redirect() < 0) - return -1; - eport = (unsigned short)atoi(argv[1]); - iaddr = argv[2]; - iport = (unsigned short)atoi(argv[3]); - if(argc >= 4) { - if(strcasecmp(argv[4], "udp") == 0) - proto = IPPROTO_UDP; - } - printf("trying to redirect port %hu to %s:%hu proto %d\n", - eport, iaddr, iport, proto); - if(addnatrule(proto, eport, iaddr, iport, NULL) < 0) - return -1; - r = addmasqueraderule(proto, eport, iaddr, iport, NULL); - syslog(LOG_DEBUG, "addmasqueraderule() returned %d", r); - if(add_filter_rule(proto, NULL, iaddr, iport) < 0) - return -1; -#if 0 - /* TEST */ - if(proto == IPPROTO_UDP) { - if(addpeernatrule(proto, "8.8.8.8"/*eaddr*/, eport, iaddr, iport, NULL, 0) < 0) - fprintf(stderr, "addpeenatrule failed\n"); - } -#endif - /*update_portmapping_desc_timestamp(NULL, eport, proto, "updated desc", time(NULL)+42);*/ - update_portmapping(NULL, eport, proto, iport+1, "updated rule", time(NULL)+42); - /* test */ - { - unsigned short p1, p2; - char addr[16]; - int proto2; - char desc[256]; - char rhost[256]; - unsigned int timestamp; - u_int64_t packets, bytes; - - desc[0] = '\0'; - if(get_redirect_rule_by_index(0, "", &p1, - addr, sizeof(addr), &p2, - &proto2, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) < 0) - { - printf("rule not found\n"); - } - else - { - printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 " ts=%u desc='%s'\n", - p1, addr, p2, proto2, packets, bytes, timestamp, desc); - } - } - printf("trying to list nat rules :\n"); - list_redirect_rule(NULL); - printf("deleting\n"); - delete_redirect_and_filter_rules(eport, proto); - shutdown_redirect(); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_dscp.c b/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_dscp.c deleted file mode 100644 index 4ad56d7..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_dscp.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include - -#include "iptcrdr.h" -#include "../commonrdr.h" -#include "iptcrdr.c" - -#ifndef PRIu64 -#define PRIu64 "llu" -#endif - -int -main(int argc, char ** argv) -{ - unsigned char dscp; - unsigned short iport, rport; - const char * iaddr, *rhost; - printf("Usage %s \n", argv[0]); - - if(argc<6) - return -1; - openlog("testiptcrdr_peer", LOG_PERROR|LOG_CONS, LOG_LOCAL0); - dscp = (unsigned short)atoi(argv[1]); - iaddr = argv[2]; - iport = (unsigned short)atoi(argv[3]); - rhost = argv[4]; - rport = (unsigned short)atoi(argv[5]); -#if 1 - if(addpeerdscprule(IPPROTO_TCP, dscp, iaddr, iport, rhost, rport) < 0) - return -1; -#endif - /* test */ - { - unsigned short p1, p2; - char addr[16]; - int proto2; - char desc[256]; - char rhost[256]; - unsigned int timestamp; - u_int64_t packets, bytes; - - desc[0] = '\0'; - if(get_redirect_rule_by_index(0, "", &p1, - addr, sizeof(addr), &p2, - &proto2, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) < 0) - { - printf("rule not found\n"); - } - else - { - printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n", - p1, addr, p2, proto2, packets, bytes); - } - } - printf("trying to list nat rules :\n"); - list_redirect_rule(argv[1]); - printf("deleting\n"); -// delete_redirect_and_filter_rules(eport, IPPROTO_TCP); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_peer.c b/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_peer.c deleted file mode 100644 index 6e1d175..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/testiptcrdr_peer.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include - -#include "iptcrdr.h" -#include "../commonrdr.h" -#include "iptcrdr.c" - -#ifndef PRIu64 -#define PRIu64 "llu" -#endif - -int -main(int argc, char ** argv) -{ - unsigned short eport, iport, rport; - const char * eaddr, *iaddr, *rhost; - printf("Usage %s \n", argv[0]); - - if(argc<6) - return -1; - openlog("testiptcrdr_peer", LOG_PERROR|LOG_CONS, LOG_LOCAL0); - eaddr = argv[1]; - eport = (unsigned short)atoi(argv[2]); - iaddr = argv[3]; - iport = (unsigned short)atoi(argv[4]); - rhost = argv[5]; - rport = (unsigned short)atoi(argv[6]); -#if 1 - printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport); - if(addpeernatrule(IPPROTO_TCP, eaddr, eport, iaddr, iport, rhost, rport) < 0) - return -1; -#endif - /* test */ - { - unsigned short p1, p2; - char addr[16]; - int proto2; - char desc[256]; - char rhost[256]; - unsigned int timestamp; - u_int64_t packets, bytes; - - desc[0] = '\0'; - if(get_redirect_rule_by_index(0, "", &p1, - addr, sizeof(addr), &p2, - &proto2, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) < 0) - { - printf("rule not found\n"); - } - else - { - printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n", - p1, addr, p2, proto2, packets, bytes); - } - } - printf("trying to list nat rules :\n"); - list_redirect_rule(argv[1]); - printf("deleting\n"); - delete_redirect_and_filter_rules(eport, IPPROTO_TCP); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/testiptpinhole.c b/src/contrib/miniupnp/miniupnpd/netfilter/testiptpinhole.c deleted file mode 100644 index caa3832..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/testiptpinhole.c +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: testiptpinhole.c,v 1.1 2012/04/26 13:50:48 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include - -#include "../config.h" -#include "iptpinhole.h" -#include "../commonrdr.h" - - -int main(int argc, char * * argv) -{ - int uid; - - openlog("testiptpinhole", LOG_PERROR|LOG_CONS, LOG_LOCAL0); - - uid = add_pinhole("eth0", NULL, 0, "ff::123", 54321, IPPROTO_TCP); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter/tiny_nf_nat.h b/src/contrib/miniupnp/miniupnpd/netfilter/tiny_nf_nat.h deleted file mode 100644 index f7f5b27..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter/tiny_nf_nat.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: tiny_nf_nat.h,v 1.1 2011/07/30 13:14:36 nanard Exp $ */ -/* Only what miniupnpd needs, until linux-libc-dev gains nf_nat.h */ - -#ifndef TINY_NF_NAT_H -#define TINY_NF_NAT_H - -#include - -#define IP_NAT_RANGE_MAP_IPS 1 -#define IP_NAT_RANGE_PROTO_SPECIFIED 2 -#define IP_NAT_RANGE_PROTO_RANDOM 4 -#define IP_NAT_RANGE_PERSISTENT 8 - -union nf_conntrack_man_proto { - __be16 all; - struct { __be16 port; } tcp; - struct { __be16 port; } udp; - struct { __be16 id; } icmp; - struct { __be16 port; } dccp; - struct { __be16 port; } sctp; - struct { __be16 key; } gre; -}; - -struct nf_nat_range { - unsigned int flags; - __be32 min_ip, max_ip; - union nf_conntrack_man_proto min, max; -}; - -struct nf_nat_multi_range_compat { - unsigned int rangesize; - struct nf_nat_range range[1]; -}; - -#define nf_nat_multi_range nf_nat_multi_range_compat - -#endif /*TINY_NF_NAT_H*/ diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/Makefile b/src/contrib/miniupnp/miniupnpd/netfilter_nft/Makefile deleted file mode 100644 index 19846cf..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement -CC = gcc - -LIBS = -lnftnl -lmnl - -ARCH := $(shell uname -m | grep -q "x86_64" && echo 64) - -all: test_nfct_get testnftnlrdr - -clean: - $(RM) *.o testnftnlcrdr testnftnlpinhole testnftnlrdr_peer \ - test_nfct_get testnftnlrdr - -testnftnlrdr: nftnlrdr.o nftnlrdr_misc.o testnftnlrdr.o upnpglobalvars.o $(LIBS) - -testiptpinhole: testiptpinhole.o iptpinhole.o upnpglobalvars.o $(LIBS) - -test_nfct_get: test_nfct_get.o test_nfct_get.o -lmnl -lnetfilter_conntrack - -test_nfct_get.o: test_nfct_get.c - -testnftnlrdr_peer.o: testnftnlrdr_peer.c - -testnftnlrdr_dscp.o: testnftnlrdr_dscp.c - -nftnlrdr.o: nftnlrdr.c nftnlrdr.h - -nftnlrdr_misc.o: nftnlrdr_misc.c - -iptpinhole.o: iptpinhole.c iptpinhole.h - -upnpglobalvars.o: ../upnpglobalvars.c ../upnpglobalvars.h - $(CC) -c -o $@ $< diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/README.md b/src/contrib/miniupnp/miniupnpd/netfilter_nft/README.md deleted file mode 100644 index b37d482..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Miniupnpd nftables support by Tomofumi Hayashi (s1061123@gmail.com). - -##Current Status -nftables support is 'alpha' version, not "so much" stable. - -##Supported Features -- IPv4 NAT/Filter add/del. - -##How to build miniupnpd with nftables: -Run 'make' command with 'Makefile.linux_nft', - -`make -f Makefile.linux_nft` - -##How to Run -Please run 'netfilter_nft/scripts/nft_init.sh' to add miniupnpd chain. - -`sudo ./netfilter_nft/scripts/nft_init.sh` - -##FAQ -I will add this section when I get question. -Comments and Questions are welcome ;) diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nfct_get.c b/src/contrib/miniupnp/miniupnpd/netfilter_nft/nfct_get.c deleted file mode 100644 index cbffd28..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nfct_get.c +++ /dev/null @@ -1,258 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifdef USE_NFCT -#include -#include - -#include - -struct data_cb_s -{ - struct sockaddr_storage * ext; - uint8_t found; -}; - -static int data_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nf_conntrack *ct; - struct data_cb_s * d = (struct data_cb_s*) data; - struct sockaddr_in* ext4 = (struct sockaddr_in*) d->ext; - - ct = nfct_new(); - if (ct == NULL) - return MNL_CB_OK; - nfct_nlmsg_parse(nlh, ct); - - if (data) { - ext4->sin_addr.s_addr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST); - ext4->sin_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); - } - d->found = 1; - nfct_destroy(ct); - - return MNL_CB_OK; -} - -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr_storage* ret_ext) -{ - struct mnl_socket *nl; - struct nlmsghdr *nlh; - struct nfgenmsg *nfh; - char buf[MNL_SOCKET_BUFFER_SIZE]; - unsigned int seq, portid; - struct nf_conntrack *ct; - int ret; - struct data_cb_s data; - - if ((!src)&&(!dst)) { - return 0; - } - - if (src->sa_family != dst->sa_family) { - return 0; - } - - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { -// perror("mnl_socket_open"); - goto free_nl; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { -// perror("mnl_socket_bind"); - goto free_nl; - } - portid = mnl_socket_get_portid(nl); - - memset(buf, 0, sizeof(buf)); - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET; - nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - - nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); - nfh->nfgen_family = src->sa_family; - nfh->version = NFNETLINK_V0; - nfh->res_id = 0; - - ct = nfct_new(); - if (ct == NULL) { - goto free_nl; - } - - nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family); - if (src->sa_family == AF_INET) { - struct sockaddr_in *src4 = (struct sockaddr_in *)src; - struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; - nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr); - nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr); - nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port); - nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port); - } else if (src->sa_family == AF_INET6) { - struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src; - struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; - nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr); - nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr); - nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port); - nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port); - } - nfct_set_attr_u8(ct, ATTR_L4PROTO, proto); - - nfct_nlmsg_build(nlh, ct); - - ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); - if (ret == -1) { - goto free_ct; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - data.ext = ret_ext; - data.found = 0; - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data); - if (ret <= MNL_CB_STOP) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - -free_ct: - nfct_destroy(ct); -free_nl: - mnl_socket_close(nl); - - return data.found; -} - -#else -#define DST "dst=" -#define DST_PORT "dport=" -#define SRC "src=" -#define SRC_PORT "sport=" -#define IP_CONNTRACK_LOCATION "/proc/net/ip_conntrack" -#define NF_CONNTRACK_LOCATION "/proc/net/nf_conntrack" - -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr_storage* ret_ext) -{ - FILE *f; - int af; - - if (!src) - return -2; - - af = src->sa_family; - - if ((f = fopen(NF_CONNTRACK_LOCATION, "r")) == NULL) { - if ((f = fopen(IP_CONNTRACK_LOCATION, "r")) == NULL) { - printf("could not read info about connections from the kernel, " - "make sure netfilter is enabled in kernel or by modules.\n"); - return -1; - } - } - - while (!feof(f)) { - char line[256], *str; - memset(line, 0, sizeof(line)); - str = fgets(line, sizeof(line), f); - if (line[0] != 0) { - char *token, *saveptr; - int j; - uint8_t src_f, src_port_f, dst_f, dst_port_f; - src_f=src_port_f=dst_f=dst_port_f=0; - - for (j = 1; ; j++, str = NULL) { - token = strtok_r(str, " ", &saveptr); - if (token == NULL) - break; - - if ((j==2)&&(af!=atoi(token))) - break; - if ((j==4)&&(proto!=atoi(token))) - break; - if (j<=4) - continue; - - if (strncmp(token, SRC, sizeof(SRC) - 1) == 0) { - char *srcip = token + sizeof(SRC) - 1; - uint32_t buf[4]; - memset(buf,0,sizeof(buf)); - - if (inet_pton(af, srcip, buf)!=1) - break; - - if (af==AF_INET) { - struct sockaddr_in *src4=(struct sockaddr_in*)src; - if (!src_f) { - if (src4->sin_addr.s_addr != buf[0]) - break; - src_f = 1; - } - } - } - if (strncmp(token, SRC_PORT, sizeof(SRC_PORT) - 1) == 0) { - char *src_port = token + sizeof(SRC_PORT) - 1; - uint16_t port=atoi(src_port); - - if (af==AF_INET) { - struct sockaddr_in *src4=(struct sockaddr_in*)src; - if (!src_port_f) { - if (ntohs(src4->sin_port) != port) - break; - src_port_f = 1; - } - } - } - - if (strncmp(token, DST, sizeof(DST) - 1) == 0) { - char *dstip = token + sizeof(DST) - 1; - uint32_t buf[4]; - memset(buf,0,sizeof(buf)); - if (inet_pton(af, dstip, buf)!=1) - break; - if (af==AF_INET) { - struct sockaddr_in *dst4=(struct sockaddr_in*)dst; - if (!dst_f) { - if (dst4->sin_addr.s_addr != buf[0]) - break; - dst_f = 1; - } else { - struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext; - ret_ext->ss_family = AF_INET; - ret4->sin_addr.s_addr = buf[0]; - } - } - } - if (strncmp(token, DST_PORT, sizeof(DST_PORT)-1) == 0) { - char *dst_port = token + sizeof(DST_PORT) - 1; - uint16_t port=atoi(dst_port); - if (af==AF_INET) { - struct sockaddr_in *dst4=(struct sockaddr_in*)dst; - if (!dst_port_f) { - if (ntohs(dst4->sin_port) != port) - break; - dst_port_f = 1; - } else { - struct sockaddr_in*ret4=(struct sockaddr_in*)ret_ext; - ret_ext->ss_family = AF_INET; - ret4->sin_port = htons(port); - } - } - } - } - if (src_f && src_port_f && dst_f && dst_port_f) { - fclose(f); - return 1; - } - } - } - fclose(f); - - return 0; -} -#endif diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.c b/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.c deleted file mode 100644 index 389273f..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2015 Tomofumi Hayashi - * - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include - -#include "tiny_nf_nat.h" - -#include "../macros.h" -#include "../config.h" -#include "nftnlrdr.h" -#include "../upnpglobalvars.h" - -#include "nftnlrdr_misc.h" - -#ifdef DEBUG -#define d_printf(x) do { printf x; } while (0) -#else -#define d_printf(x) -#endif - -/* dummy init and shutdown functions */ -int init_redirect(void) -{ - return 0; -} - -void shutdown_redirect(void) -{ - return; -} - - -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - struct nft_rule *r; - UNUSED(rhost); - UNUSED(timestamp); - d_printf(("add redirect rule2(%s, %s, %u, %s, %u, %d, %s)!\n", - ifname, rhost, eport, iaddr, iport, proto, desc)); - r = rule_set_dnat(NFPROTO_IPV4, ifname, proto, - 0, eport, - inet_addr(iaddr), iport, desc, NULL); - return nft_send_request(r, NFT_MSG_NEWRULE); -} - -/* - * This function submit the rule as following: - * nft add rule nat miniupnpd-pcp-peer ip - * saddr ip daddr tcp sport - * tcp dport snat : - */ -int -add_peer_redirect_rule2(const char * ifname, - const char * rhost, unsigned short rport, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - struct nft_rule *r; - UNUSED(ifname); UNUSED(timestamp); - - d_printf(("add peer redirect rule2()!\n")); - r = rule_set_snat(NFPROTO_IPV4, proto, - inet_addr(rhost), rport, - inet_addr(eaddr), eport, - inet_addr(iaddr), iport, desc, NULL); - - return nft_send_request(r, NFT_MSG_NEWRULE); -} - -/* - * This function submit the rule as following: - * nft add rule filter miniupnpd - * ip daddr tcp dport accept - * - */ -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc) -{ - struct nft_rule *r = NULL; - in_addr_t rhost_addr = 0; - - d_printf(("add_filter_rule2(%s, %s, %s, %d, %d, %d, %s)\n", - ifname, rhost, iaddr, eport, iport, proto, desc)); - if (rhost != NULL && strcmp(rhost, "") != 0) { - rhost_addr = inet_addr(rhost); - } - r = rule_set_filter(NFPROTO_IPV4, ifname, proto, - rhost_addr, inet_addr(iaddr), eport, iport, - desc, 0); - return nft_send_request(r, NFT_MSG_NEWRULE); -} - -/* - * add_peer_dscp_rule2() is not supported due to nft does not support - * dscp set. - */ -int -add_peer_dscp_rule2(const char * ifname, - const char * rhost, unsigned short rport, - unsigned char dscp, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - UNUSED(ifname); UNUSED(rhost); UNUSED(rport); - UNUSED(dscp); UNUSED(iaddr); UNUSED(iport); UNUSED(proto); - UNUSED(desc); UNUSED(timestamp); - syslog(LOG_ERR, "add_peer_dscp_rule2: not supported"); - return 0; -} - -/* - * Clear all rules corresponding eport/proto - */ -int -delete_redirect_and_filter_rules(unsigned short eport, int proto) -{ - rule_t *p; - struct nft_rule *r = NULL; - in_addr_t iaddr = 0; - uint16_t iport = 0; - extern void print_rule(rule_t *r) ; - - d_printf(("delete_redirect_and_filter_rules(%d %d)\n", eport, proto)); - reflesh_nft_cache(NFPROTO_IPV4); - LIST_FOREACH(p, &head, entry) { - if (p->eport == eport && p->proto == proto && - (p->type == RULE_NAT || p->type == RULE_SNAT)) { - iaddr = p->iaddr; - iport = p->iport; - - r = rule_del_handle(p); - /* Todo: send bulk request */ - nft_send_request(r, NFT_MSG_DELRULE); - break; - } - } - - if (iaddr == 0 && iport == 0) { - return -1; - } - reflesh_nft_cache(NFPROTO_IPV4); - LIST_FOREACH(p, &head, entry) { - if (p->eport == iport && - p->iaddr == iaddr && p->type == RULE_FILTER) { - r = rule_del_handle(p); - /* Todo: send bulk request */ - nft_send_request(r, NFT_MSG_DELRULE); - break; - } - } - - return 0; -} - -/* - * get peer by index as array. - * return -1 when not found. - */ -int -get_peer_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, unsigned short * rport, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int i; - struct in_addr addr; - char *addr_str; - rule_t *r; - UNUSED(timestamp); UNUSED(packets); UNUSED(bytes); - - d_printf(("get_peer_rule_by_index()\n")); - reflesh_nft_cache(NFPROTO_IPV4); - if (peer_cache == NULL) { - return -1; - } - - for (i = 0; peer_cache[i] != NULL; i++) { - if (index == i) { - r = peer_cache[i]; - if (ifname != NULL) { - if_indextoname(r->ingress_ifidx, ifname); - } - if (eport != NULL) { - *eport = r->eport; - } - if (iaddr != NULL) { - addr.s_addr = r->iaddr; - addr_str = inet_ntoa(addr); - strncpy(iaddr , addr_str, iaddrlen); - } - if (iport != NULL) { - *iport = r->iport; - } - if (proto != NULL) { - *proto = r->proto; - } - if (rhost != NULL) { - addr.s_addr = r->rhost; - addr_str = inet_ntoa(addr); - strncpy(iaddr , addr_str, rhostlen); - } - if (rport != NULL) { - *rport = r->rport; - } - if (desc != NULL) { - strncpy(desc, r->desc, desclen); - } - - /* - * TODO: Implement counter in case of add {nat,filter} - */ - return 0; - } - } - return -1; -} - -/* - * get_redirect_rule() - * returns -1 if the rule is not found - */ -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - return get_nat_redirect_rule(NFT_TABLE_NAT, - ifname, eport, proto, - iaddr, iaddrlen, iport, - desc, desclen, - rhost, rhostlen, - timestamp, packets, bytes); -} - -/* - * get_redirect_rule_by_index() - * return -1 when the rule was not found - */ -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int i; - struct in_addr addr; - char *addr_str; - rule_t *r; - UNUSED(timestamp); UNUSED(packets); UNUSED(bytes); - - d_printf(("get_redirect_rule_by_index()\n")); - reflesh_nft_cache(NFPROTO_IPV4); - if (redirect_cache == NULL) { - return -1; - } - - for (i = 0; redirect_cache[i] != NULL; i++) { - if (index == i) { - r = redirect_cache[i]; - if (ifname != NULL) { - if_indextoname(r->ingress_ifidx, ifname); - } - if (eport != NULL) { - *eport = r->eport; - } - if (iaddr != NULL) { - addr.s_addr = r->iaddr; - addr_str = inet_ntoa(addr); - strncpy(iaddr , addr_str, iaddrlen); - } - if (iport != NULL) { - *iport = r->iport; - } - if (proto != NULL) { - *proto = r->proto; - } - if (rhost != NULL) { - addr.s_addr = r->rhost; - addr_str = inet_ntoa(addr); - strncpy(iaddr , addr_str, rhostlen); - } - if (desc != NULL && r->desc) { - strncpy(desc, r->desc, desclen); - } - - /* - * TODO: Implement counter in case of add {nat,filter} - */ - return 0; - } - } - return -1; -} - -/* - * return -1 not found. - * return 0 found - */ -int -get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, - unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - rule_t *p; - struct in_addr addr; - char *addr_str; - UNUSED(nat_chain_name); - UNUSED(ifname); - UNUSED(iaddrlen); - UNUSED(timestamp); - UNUSED(packets); - UNUSED(bytes); - - d_printf(("get_nat_redirect_rule()\n")); - reflesh_nft_cache(NFPROTO_IPV4); - - LIST_FOREACH(p, &head, entry) { - if (p->proto == proto && - p->eport == eport) { - if (p->rhost && rhost) { - addr.s_addr = p->rhost; - addr_str = inet_ntoa(addr); - strncpy(iaddr , addr_str, rhostlen); - - } - if (desc != NULL && p->desc) { - strncpy(desc, p->desc, desclen); - } - *iport = p->iport; - return 0; - } - } - - return -1; -} - -/* - * return an (malloc'ed) array of "external" port for which there is - * a port mapping. number is the size of the array - */ -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number) -{ - uint32_t capacity; - rule_t *p; - unsigned short *array; - unsigned short *tmp; - - d_printf(("get_portmappings_in_range()\n")); - *number = 0; - capacity = 128; - array = calloc(capacity, sizeof(unsigned short)); - - if (array == NULL) { - syslog(LOG_ERR, "get_portmappings_in_range(): calloc error"); - return NULL; - } - - LIST_FOREACH(p, &head, entry) { - if (p->proto == proto && - startport <= p->eport && - p->eport <= endport) { - - if (*number >= capacity) { - tmp = realloc(array, - sizeof(unsigned short)*capacity); - if (tmp == NULL) { - syslog(LOG_ERR, - "get_portmappings_in_range(): " - "realloc(%u) error", - (unsigned)sizeof(unsigned short)*capacity); - *number = 0; - free(array); - return NULL; - } - array = tmp; - } - array[*number] = p->eport; - (*number)++; - } - } - return array; -} - -/* for debug */ -/* read the "filter" and "nat" tables */ -int -list_redirect_rule(const char * ifname) -{ - rule_t *p; - UNUSED(ifname); - - reflesh_nft_cache(NFPROTO_IPV4); - - LIST_FOREACH(p, &head, entry) { - print_rule(p); - } - - return -1; - return 0; -} - - -#if 0 -/* delete_rule_and_commit() : - * subfunction used in delete_redirect_and_filter_rules() */ -static int -delete_rule_and_commit(unsigned int index, IPTC_HANDLE h, - const char * miniupnpd_chain, - const char * logcaller) -{ -/* TODO: Implement it */ -} - -/* TODO: Implement it */ -static void -print_iface(const char * iface, const unsigned char * mask, int invert) -{ - unsigned i; - if(mask[0] == 0) - return; - if(invert) - printf("! "); - for(i=0; i> 24, (ip >> 16) & 0xff, - (ip >> 8) & 0xff, ip & 0xff); -} -#endif - -#endif /* if 0 */ diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.h b/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.h deleted file mode 100644 index 1acf4b3..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2015 Tomofumi Hayashi - * - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution. - */ - -#ifndef NFTNLRDR_H_INCLUDED -#define NFTNLRDR_H_INCLUDED - -#include "../commonrdr.h" -int init_redirect(void); -void shutdown_redirect(void); - -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -add_peer_redirect_rule2(const char * ifname, - const char * rhost, unsigned short rport, - const char * eaddr, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc); - -int -delete_redirect_and_filter_rules(unsigned short eport, int proto); - -int -add_peer_dscp_rule2(const char * ifname, - const char * rhost, unsigned short rport, - unsigned char dscp, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -int -get_peer_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, unsigned short * rport, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); -int -get_nat_redirect_rule(const char * nat_chain_name, const char * ifname, - unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number); - -/* in nfct_get.c */ -int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, - struct sockaddr* ret_ext); - -/* for debug */ -int -list_redirect_rule(const char * ifname); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.c b/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.c deleted file mode 100644 index a35c45e..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2015 Tomofumi Hayashi - * - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "nftnlrdr_misc.h" -#include "../macros.h" -#include "../upnpglobalvars.h" - -#ifdef DEBUG -#define d_printf(x) do { printf x; } while (0) -#else -#define d_printf(x) -#endif - -#define RULE_CACHE_INVALID 0 -#define RULE_CACHE_VALID 1 - -const char * miniupnpd_nft_nat_chain = "miniupnpd"; -const char * miniupnpd_nft_peer_chain = "miniupnpd-pcp-peer"; -const char * miniupnpd_nft_forward_chain = "miniupnpd"; - -static struct mnl_socket *nl = NULL; -struct rule_list head = LIST_HEAD_INITIALIZER(head); -static uint32_t rule_list_validate = RULE_CACHE_INVALID; - -uint32_t rule_list_length = 0; -uint32_t rule_list_peer_length = 0; - -rule_t **redirect_cache; -rule_t **peer_cache; - - -static const char * -get_family_string(uint32_t family) -{ - switch (family) { - case NFPROTO_IPV4: - return "ipv4"; - } - return "unknown family"; -} - -static const char * -get_proto_string(uint32_t proto) -{ - switch (proto) { - case IPPROTO_TCP: - return "tcp"; - case IPPROTO_UDP: - return "udp"; - } - return "unknown proto"; -} - -static const char * -get_verdict_string(uint32_t val) -{ - switch (val) { - case NF_ACCEPT: - return "accept"; - case NF_DROP: - return "drop"; - default: - return "unknown verdict"; - } -} - -void -print_rule(rule_t *r) -{ - struct in_addr addr; - char *iaddr_str = NULL, *rhost_str = NULL, *eaddr_str = NULL; - char ifname_buf[IF_NAMESIZE]; - - switch (r->type) { - case RULE_NAT: - if (r->iaddr != 0) { - addr.s_addr = r->iaddr; - iaddr_str = strdupa(inet_ntoa(addr)); - } - if (r->rhost != 0) { - addr.s_addr = r->rhost; - rhost_str = strdupa(inet_ntoa(addr)); - } - if (r->eaddr != 0) { - addr.s_addr = r->eaddr; - eaddr_str = strdupa(inet_ntoa(addr)); - } - if (r->nat_type == NFT_NAT_DNAT) { - printf("%"PRIu64":[%s/%s] iif %s, %s/%s, %d -> " - "%s:%d (%s)\n", - r->handle, - r->table, r->chain, - if_indextoname(r->ingress_ifidx, ifname_buf), - get_family_string(r->family), - get_proto_string(r->proto), r->eport, - iaddr_str, r->iport, - r->desc); - } else if (r->nat_type == NFT_NAT_SNAT) { - printf("%"PRIu64":[%s/%s] " - "nat type:%d, family:%d, ifidx: %d, " - "eaddr: %s, eport:%d, " - "proto:%d, iaddr: %s, " - "iport:%d, rhost:%s rport:%d (%s)\n", - r->handle, r->table, r->chain, - r->nat_type, r->family, r->ingress_ifidx, - eaddr_str, r->eport, - r->proto, iaddr_str, r->iport, - rhost_str, r->rport, - r->desc); - } else { - printf("%"PRIu64":[%s/%s] " - "nat type:%d, family:%d, ifidx: %d, " - "eaddr: %s, eport:%d, " - "proto:%d, iaddr: %s, iport:%d, rhost:%s (%s)\n", - r->handle, r->table, r->chain, - r->nat_type, r->family, r->ingress_ifidx, - eaddr_str, r->eport, - r->proto, iaddr_str, r->iport, rhost_str, - r->desc); - } - break; - case RULE_FILTER: - if (r->iaddr != 0) { - addr.s_addr = r->iaddr; - iaddr_str = strdupa(inet_ntoa(addr)); - } - if (r->rhost != 0) { - addr.s_addr = r->rhost; - rhost_str = strdupa(inet_ntoa(addr)); - } - printf("%"PRIu64":[%s/%s] %s/%s, %s %s:%d: %s (%s)\n", - r->handle, r->table, r->chain, - get_family_string(r->family), get_proto_string(r->proto), - rhost_str, - iaddr_str, r->eport, - get_verdict_string(r->filter_action), - r->desc); - break; - case RULE_COUNTER: - if (r->iaddr != 0) { - addr.s_addr = r->iaddr; - iaddr_str = strdupa(inet_ntoa(addr)); - } - if (r->rhost != 0) { - addr.s_addr = r->iaddr; - rhost_str = strdupa(inet_ntoa(addr)); - } - printf("%"PRIu64":[%s/%s] %s/%s, %s:%d: " - "packets:%"PRIu64", bytes:%"PRIu64"\n", - r->handle, r->table, r->chain, - get_family_string(r->family), get_proto_string(r->proto), - iaddr_str, r->eport, r->packets, r->bytes); - break; - default: - printf("nftables: unknown type: %d\n", r->type); - } -} - -static enum rule_reg_type * -get_reg_type_ptr(rule_t *r, uint32_t dreg) -{ - switch (dreg) { - case NFT_REG_1: - return &r->reg1_type; - case NFT_REG_2: - return &r->reg2_type; - default: - return NULL; - } -} - -static uint32_t * -get_reg_val_ptr(rule_t *r, uint32_t dreg) -{ - switch (dreg) { - case NFT_REG_1: - return &r->reg1_val; - case NFT_REG_2: - return &r->reg2_val; - default: - return NULL; - } -} - -static void -set_reg (rule_t *r, uint32_t dreg, enum rule_reg_type type, uint32_t val) -{ - if (dreg == NFT_REG_1) { - r->reg1_type = type; - if (type == RULE_REG_IMM_VAL) { - r->reg1_val = val; - } - } else if (dreg == NFT_REG_2) { - r->reg2_type = type; - if (type == RULE_REG_IMM_VAL) { - r->reg2_val = val; - } - } else if (dreg == NFT_REG_VERDICT) { - if (r->type == RULE_FILTER) { - r->filter_action = val; - } - } else { - syslog(LOG_ERR, "%s: unknown reg:%d", "set_reg", dreg); - } - return ; -} - -static inline void -parse_rule_immediate(struct nft_rule_expr *e, rule_t *r) -{ - uint32_t dreg, reg_val, reg_len; - - dreg = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_DREG); - - if (dreg == NFT_REG_VERDICT) { - reg_val = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT); - } else { - reg_val = *(uint32_t *)nft_rule_expr_get(e, - NFT_EXPR_IMM_DATA, - ®_len); - } - - set_reg(r, dreg, RULE_REG_IMM_VAL, reg_val); - return; -} - -static inline void -parse_rule_counter(struct nft_rule_expr *e, rule_t *r) -{ - r->type = RULE_COUNTER; - r->bytes = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES); - r->packets = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS); - - return; -} - -static inline void -parse_rule_meta(struct nft_rule_expr *e, rule_t *r) -{ - uint32_t key = nft_rule_expr_get_u32(e, NFT_EXPR_META_KEY); - uint32_t dreg = nft_rule_expr_get_u32(e, NFT_EXPR_META_DREG); - enum rule_reg_type reg_type; - - switch (key) { - case NFT_META_IIF: - reg_type = RULE_REG_IIF; - set_reg(r, dreg, reg_type, 0); - return ; - - case NFT_META_OIF: - reg_type = RULE_REG_IIF; - set_reg(r, dreg, reg_type, 0); - return ; - - } - syslog(LOG_DEBUG, "parse_rule_meta :Not support key %d\n", key); - - return; -} - -static inline void -parse_rule_nat(struct nft_rule_expr *e, rule_t *r) -{ - uint32_t addr_min_reg, addr_max_reg, proto_min_reg, proto_max_reg; - uint16_t proto_min_val; - r->type = RULE_NAT; - - r->nat_type = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_TYPE); - r->family = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_FAMILY); - addr_min_reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN); - addr_max_reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX); - proto_min_reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_PROTO_MIN); - proto_max_reg = nft_rule_expr_get_u32(e, NFT_EXPR_NAT_REG_PROTO_MAX); - - if (addr_min_reg != addr_max_reg || - proto_min_reg != proto_max_reg) { - syslog(LOG_ERR, "Unsupport proto/addr range for NAT"); - } - - proto_min_val = htons((uint16_t)*get_reg_val_ptr(r, proto_min_reg)); - if (r->nat_type == NFT_NAT_DNAT) { - r->iaddr = (in_addr_t)*get_reg_val_ptr(r, addr_min_reg); - r->iport = proto_min_val; - } else if (r->nat_type == NFT_NAT_SNAT) { - r->eaddr = (in_addr_t)*get_reg_val_ptr(r, addr_min_reg); - if (proto_min_reg == NFT_REG_1) { - r->eport = proto_min_val; - } - } - - set_reg(r, NFT_REG_1, RULE_REG_NONE, 0); - set_reg(r, NFT_REG_2, RULE_REG_NONE, 0); - return; -} - -static inline void -parse_rule_payload(struct nft_rule_expr *e, rule_t *r) -{ - uint32_t base, dreg, offset, len; - uint32_t *regptr; - - dreg = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_DREG); - base = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_BASE); - offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET); - len = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_LEN); - regptr = get_reg_type_ptr(r, dreg); - - switch (base) { - case NFT_PAYLOAD_NETWORK_HEADER: - if (offset == offsetof(struct iphdr, daddr) && - len == sizeof(in_addr_t)) { - *regptr = RULE_REG_IP_DEST_ADDR; - return; - } else if (offset == offsetof(struct iphdr, saddr) && - len == sizeof(in_addr_t)) { - *regptr = RULE_REG_IP_SRC_ADDR; - return; - } else if (offset == offsetof(struct iphdr, saddr) && - len == sizeof(in_addr_t) * 2) { - *regptr = RULE_REG_IP_SD_ADDR; - return; - } else if (offset == offsetof(struct iphdr, protocol) && - len == sizeof(uint8_t)) { - *regptr = RULE_REG_IP_PROTO; - return; - } - case NFT_PAYLOAD_TRANSPORT_HEADER: - if (offset == offsetof(struct tcphdr, dest) && - len == sizeof(uint16_t)) { - *regptr = RULE_REG_TCP_DPORT; - return; - } else if (offset == offsetof(struct tcphdr, source) && - len == sizeof(uint16_t) * 2) { - *regptr = RULE_REG_TCP_SD_PORT; - return; - } - } - syslog(LOG_DEBUG, - "Unsupport payload: (dreg:%d, base:%d, offset:%d, len:%d)", - dreg, base, offset, len); - return; -} - -/* - * - * Note: Currently support only NFT_REG_1 - */ -static inline void -parse_rule_cmp(struct nft_rule_expr *e, rule_t *r) { - uint32_t data_len; - void *data_val; - uint32_t op, sreg; - uint16_t *ports; - in_addr_t *addrp; - - data_val = (void *)nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &data_len); - sreg = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_SREG); - op = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_OP); - - if (sreg != NFT_REG_1) { - syslog(LOG_ERR, "parse_rule_cmp: Unsupport reg:%d", sreg); - return; - } - - switch (r->reg1_type) { - case RULE_REG_IIF: - if (data_len == sizeof(uint32_t) && op == NFT_CMP_EQ) { - r->ingress_ifidx = *(uint32_t *)data_val; - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_IP_SRC_ADDR: - if (data_len == sizeof(in_addr_t) && op == NFT_CMP_EQ) { - r->rhost = *(in_addr_t *)data_val; - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_IP_DEST_ADDR: - if (data_len == sizeof(in_addr_t) && op == NFT_CMP_EQ) { - if (r->type == RULE_FILTER) { - r->iaddr = *(in_addr_t *)data_val; - } else { - r->rhost = *(in_addr_t *)data_val; - } - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_IP_SD_ADDR: - if (data_len == sizeof(in_addr_t) * 2 && op == NFT_CMP_EQ) { - addrp = (in_addr_t *)data_val; - r->iaddr = addrp[0]; - r->rhost = addrp[1]; - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_IP_PROTO: - if (data_len == sizeof(uint8_t) && op == NFT_CMP_EQ) { - r->proto = *(uint8_t *)data_val; - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_TCP_DPORT: - if (data_len == sizeof(uint16_t) && op == NFT_CMP_EQ) { - r->eport = ntohs(*(uint16_t *)data_val); - r->reg1_type = RULE_REG_NONE; - return; - } - case RULE_REG_TCP_SD_PORT: - if (data_len == sizeof(uint16_t) * 2 && op == NFT_CMP_EQ) { - ports = (uint16_t *)data_val; - r->iport = ntohs(ports[0]); - r->rport = ntohs(ports[1]); - r->reg1_type = RULE_REG_NONE; - return; - } - default: - break; - } - syslog(LOG_DEBUG, "Unknown cmp (r1type:%d, data_len:%d, op:%d)", - r->reg1_type, data_len, op); - return; -} - -static int -rule_expr_cb(struct nft_rule_expr *e, void *data) -{ - rule_t *r = data; - const char *attr_name = nft_rule_expr_get_str(e, - NFT_RULE_EXPR_ATTR_NAME); - - if (strncmp("cmp", attr_name, sizeof("cmp")) == 0) { - parse_rule_cmp(e, r); - } else if (strncmp("nat", attr_name, sizeof("nat")) == 0) { - parse_rule_nat(e, r); - } else if (strncmp("meta", attr_name, sizeof("meta")) == 0) { - parse_rule_meta(e, r); - } else if (strncmp("counter", attr_name, sizeof("counter")) == 0) { - parse_rule_counter(e, r); - } else if (strncmp("payload", attr_name, sizeof("payload")) == 0) { - parse_rule_payload(e, r); - } else if (strncmp("immediate", attr_name, sizeof("immediate")) == 0) { - parse_rule_immediate(e, r); - } else { - syslog(LOG_ERR, "unknown attr: %s\n", attr_name); - } - return MNL_CB_OK; -} - - -static int -table_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nft_rule *t; - uint32_t len; - struct nft_rule_expr *expr; - struct nft_rule_expr_iter *itr; - rule_t *r; - char *chain; - UNUSED(data); - - r = malloc(sizeof(rule_t)); - - memset(r, 0, sizeof(rule_t)); - t = nft_rule_alloc(); - if (t == NULL) { - perror("OOM"); - goto err; - } - - if (nft_rule_nlmsg_parse(nlh, t) < 0) { - perror("nft_rule_nlmsg_parse"); - goto err_free; - } - - chain = (char *)nft_rule_attr_get_data(t, NFT_RULE_ATTR_CHAIN, &len); - if (strcmp(chain, miniupnpd_nft_nat_chain) != 0 && - strcmp(chain, miniupnpd_nft_peer_chain) != 0 && - strcmp(chain, miniupnpd_nft_forward_chain) != 0) { - goto rule_skip; - } - - r->table = strdup( - (char *)nft_rule_attr_get_data(t, NFT_RULE_ATTR_TABLE, &len)); - r->chain = strdup(chain); - r->family = *(uint32_t*)nft_rule_attr_get_data(t, NFT_RULE_ATTR_FAMILY, - &len); - r->desc = (char *)nft_rule_attr_get_data(t, NFT_RULE_ATTR_USERDATA, - &len); - r->handle = *(uint32_t*)nft_rule_attr_get_data(t, - NFT_RULE_ATTR_HANDLE, - &len); - if (strcmp(r->table, NFT_TABLE_NAT) == 0) { - r->type = RULE_NAT; - } else if (strcmp(r->table, NFT_TABLE_FILTER) == 0) { - r->type = RULE_FILTER; - } - if (strcmp(r->chain, miniupnpd_nft_peer_chain) == 0) { - rule_list_peer_length++; - } - - itr = nft_rule_expr_iter_create(t); - - while ((expr = nft_rule_expr_iter_next(itr)) != NULL) { - rule_expr_cb(expr, r); - } - - if (r->type == RULE_NONE) { - free(r); - } else { - LIST_INSERT_HEAD(&head, r, entry); - rule_list_length++; - } - -rule_skip: -err_free: - nft_rule_free(t); -err: - return MNL_CB_OK; -} - -void -reflesh_nft_redirect_cache(void) -{ - rule_t *p; - int i; - uint32_t len; - - if (redirect_cache != NULL) { - free(redirect_cache); - } - len = rule_list_length - rule_list_peer_length; - if (len == 0) { - redirect_cache = NULL; - return; - } - - redirect_cache = (rule_t **)malloc(sizeof(rule_t *) * len); - bzero(redirect_cache, sizeof(rule_t *) * len); - - i = 0; - LIST_FOREACH(p, &head, entry) { - if (strcmp(p->chain, miniupnpd_nft_nat_chain) == 0 && - (p->type == RULE_NAT || p->type == RULE_SNAT)) { - redirect_cache[i] = p; - i++; - } - } - - return; -} - -void -reflesh_nft_peer_cache(void) -{ - rule_t *p; - int i; - - if (peer_cache != NULL) { - free(peer_cache); - } - if (rule_list_peer_length == 0) { - peer_cache = NULL; - return; - } - peer_cache = (rule_t **)malloc( - sizeof(rule_t *) * rule_list_peer_length); - bzero(peer_cache, sizeof(rule_t *) * rule_list_peer_length); - - i = 0; - LIST_FOREACH(p, &head, entry) { - if (strcmp(p->chain, miniupnpd_nft_peer_chain) == 0) { - peer_cache[i] = p; - i++; - } - } - - return; -} - -void -reflesh_nft_cache(uint32_t family) -{ - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - uint32_t portid, seq, type = NFT_OUTPUT_DEFAULT; - struct nft_rule *t; - rule_t *p1, *p2; - int ret; - - if (rule_list_validate == RULE_CACHE_VALID) { - return; - } - - t = NULL; - p1 = LIST_FIRST(&head); - if (p1 != NULL) { - while(p1 != NULL) { - p2 = (rule_t *)LIST_NEXT(p1, entry); - if (p1->desc != NULL) { - free(p1->desc); - } - if (p1->table != NULL) { - free(p1->table); - } - if (p1->chain != NULL) { - free(p1->chain); - } - free(p1); - p1 = p2; - } - } - LIST_INIT(&head); - - t = nft_rule_alloc(); - if (t == NULL) { - perror("OOM"); - exit(EXIT_FAILURE); - } - - seq = time(NULL); - nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, - NLM_F_DUMP, seq); - nft_rule_nlmsg_build_payload(nlh, t); - nft_rule_free(t); - - if (nl == NULL) { - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - perror("mnl_socket_open"); - exit(EXIT_FAILURE); - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - perror("mnl_socket_bind"); - exit(EXIT_FAILURE); - } - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - perror("mnl_socket_send"); - exit(EXIT_FAILURE); - } - - rule_list_peer_length = 0; - rule_list_length = 0; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, table_cb, &type); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - perror("error"); - exit(EXIT_FAILURE); - } - /* mnl_socket_close(nl); */ - - reflesh_nft_peer_cache(); - reflesh_nft_redirect_cache(); - rule_list_validate = RULE_CACHE_VALID; - return; -} - -static void -expr_add_payload(struct nft_rule *r, uint32_t base, uint32_t dreg, - uint32_t offset, uint32_t len) -{ - struct nft_rule_expr *e; - - e = nft_rule_expr_alloc("payload"); - if (e == NULL) { - perror("expr payload oom"); - exit(EXIT_FAILURE); - } - - nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_BASE, base); - nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_DREG, dreg); - nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_OFFSET, offset); - nft_rule_expr_set_u32(e, NFT_EXPR_PAYLOAD_LEN, len); - - nft_rule_add_expr(r, e); -} - -#if 0 -static void -expr_add_bitwise(struct nft_rule *r, uint32_t sreg, uint32_t dreg, - uint32_t len, uint32_t mask, uint32_t xor) -{ - struct nft_rule_expr *e; - - e = nft_rule_expr_alloc("bitwise"); - if (e == NULL) { - perror("expr cmp bitwise"); - exit(EXIT_FAILURE); - } - - nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_SREG, sreg); - nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_DREG, dreg); - nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_LEN, len); - nft_rule_expr_set(e, NFT_EXPR_BITWISE_MASK, &mask, sizeof(mask)); - nft_rule_expr_set(e, NFT_EXPR_BITWISE_XOR, &xor, sizeof(xor)); - - nft_rule_add_expr(r, e); -} -#endif - -static void -expr_add_cmp(struct nft_rule *r, uint32_t sreg, uint32_t op, - const void *data, uint32_t data_len) -{ - struct nft_rule_expr *e; - - e = nft_rule_expr_alloc("cmp"); - if (e == NULL) { - perror("expr cmp oom"); - exit(EXIT_FAILURE); - } - - nft_rule_expr_set_u32(e, NFT_EXPR_CMP_SREG, sreg); - nft_rule_expr_set_u32(e, NFT_EXPR_CMP_OP, op); - nft_rule_expr_set(e, NFT_EXPR_CMP_DATA, data, data_len); - - nft_rule_add_expr(r, e); -} - -static void -expr_add_meta(struct nft_rule *r, uint32_t meta_key, uint32_t dreg) -{ - struct nft_rule_expr *e; - - e = nft_rule_expr_alloc("meta"); - if (e == NULL) { - perror("expr meta oom"); - exit(EXIT_FAILURE); - } - - nft_rule_expr_set_u32(e, NFT_EXPR_META_KEY, meta_key); - nft_rule_expr_set_u32(e, NFT_EXPR_META_DREG, dreg); - - nft_rule_add_expr(r, e); -} - -static void -expr_set_reg_val_u32(struct nft_rule *r, enum nft_registers dreg, uint32_t val) -{ - struct nft_rule_expr *e; - e = nft_rule_expr_alloc("immediate"); - if (e == NULL) { - perror("expr dreg oom"); - exit(EXIT_FAILURE); - } - nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DREG, dreg); - nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DATA, val); - nft_rule_add_expr(r, e); -} - -static void -expr_set_reg_val_u16(struct nft_rule *r, enum nft_registers dreg, uint32_t val) -{ - struct nft_rule_expr *e; - e = nft_rule_expr_alloc("immediate"); - if (e == NULL) { - perror("expr dreg oom"); - exit(EXIT_FAILURE); - } - nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DREG, dreg); - nft_rule_expr_set_u16(e, NFT_EXPR_IMM_DATA, val); - nft_rule_add_expr(r, e); -} - -static void -expr_set_reg_verdict(struct nft_rule *r, uint32_t val) -{ - struct nft_rule_expr *e; - e = nft_rule_expr_alloc("immediate"); - if (e == NULL) { - perror("expr dreg oom"); - exit(EXIT_FAILURE); - } - nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT); - nft_rule_expr_set_u32(e, NFT_EXPR_IMM_VERDICT, val); - nft_rule_add_expr(r, e); -} - -static void -expr_add_nat(struct nft_rule *r, uint32_t t, uint32_t family, - in_addr_t addr_min, uint32_t proto_min, uint32_t flags) -{ - struct nft_rule_expr *e; - UNUSED(flags); - - e = nft_rule_expr_alloc("nat"); - if (e == NULL) { - perror("expr nat oom"); - exit(EXIT_FAILURE); - } - - nft_rule_expr_set_u32(e, NFT_EXPR_NAT_TYPE, t); - nft_rule_expr_set_u32(e, NFT_EXPR_NAT_FAMILY, family); - - expr_set_reg_val_u32(r, NFT_REG_1, (uint32_t)addr_min); - nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MIN, NFT_REG_1); - nft_rule_expr_set_u32(e, NFT_EXPR_NAT_REG_ADDR_MAX, NFT_REG_1); - expr_set_reg_val_u16(r, NFT_REG_2, proto_min); - nft_rule_expr_set_u16(e, NFT_EXPR_NAT_REG_PROTO_MIN, NFT_REG_2); - nft_rule_expr_set_u16(e, NFT_EXPR_NAT_REG_PROTO_MAX, NFT_REG_2); - - nft_rule_add_expr(r, e); -} - - -/* - * Todo: add expr for rhost - */ -struct nft_rule * -rule_set_snat(uint8_t family, uint8_t proto, - in_addr_t rhost, unsigned short rport, - in_addr_t ehost, unsigned short eport, - in_addr_t ihost, unsigned short iport, - const char *descr, - const char *handle) -{ - struct nft_rule *r = NULL; - uint32_t destport; - in_addr_t addr[2]; - uint16_t port[2]; - uint32_t descr_len; - UNUSED(handle); - - r = nft_rule_alloc(); - if (r == NULL) { - perror("OOM"); - exit(EXIT_FAILURE); - } - - nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, NFT_TABLE_NAT); - nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, miniupnpd_nft_peer_chain); - if (descr != NULL) { - descr_len = strlen(descr); - nft_rule_attr_set_data(r, NFT_RULE_ATTR_USERDATA, - descr, descr_len); - } - nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family); - - addr[0] = ihost; - addr[1] = rhost; - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, saddr), sizeof(uint32_t)*2); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, addr, sizeof(uint32_t)*2); - - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, protocol), sizeof(uint8_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &proto, sizeof(uint8_t)); - - port[0] = htons(iport); - port[1] = htons(rport); - if (proto == IPPROTO_TCP) { - expr_add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, - offsetof(struct tcphdr, source), - sizeof(uint32_t)); - } else if (proto == IPPROTO_UDP) { - expr_add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, - offsetof(struct udphdr, source), - sizeof(uint32_t)); - } - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, port, sizeof(uint32_t)); - - destport = htons(eport); - expr_add_nat(r, NFT_NAT_SNAT, AF_INET, ehost, destport, 0); - - return r; -} - -/* - * Todo: add expr for rhost - */ -struct nft_rule * -rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto, - in_addr_t rhost, unsigned short eport, - in_addr_t ihost, uint32_t iport, - const char *descr, - const char *handle) -{ - struct nft_rule *r = NULL; - uint16_t dport; - uint64_t handle_num; - uint32_t if_idx; - uint32_t descr_len; - - UNUSED(handle); - UNUSED(rhost); - - r = nft_rule_alloc(); - if (r == NULL) { - perror("OOM"); - exit(EXIT_FAILURE); - } - - nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, NFT_TABLE_NAT); - nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, miniupnpd_nft_nat_chain); - nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family); - if (descr != NULL) { - descr_len = strlen(descr); - nft_rule_attr_set_data(r, NFT_RULE_ATTR_USERDATA, - descr, descr_len); - } - - if (handle != NULL) { - handle_num = atoll(handle); - nft_rule_attr_set_u64(r, NFT_RULE_ATTR_POSITION, handle_num); - } - - if (ifname != NULL) { - if_idx = (uint32_t)if_nametoindex(ifname); - expr_add_meta(r, NFT_META_IIF, NFT_REG_1); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &if_idx, - sizeof(uint32_t)); - } - - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, protocol), sizeof(uint8_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &proto, sizeof(uint8_t)); - - if (proto == IPPROTO_TCP) { - dport = htons(eport); - expr_add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, - offsetof(struct tcphdr, dest), - sizeof(uint16_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &dport, - sizeof(uint16_t)); - } else if (proto == IPPROTO_UDP) { - dport = htons(eport); - expr_add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, - offsetof(struct udphdr, dest), - sizeof(uint16_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &dport, - sizeof(uint16_t)); - } - - expr_add_nat(r, NFT_NAT_DNAT, AF_INET, ihost, htons(iport), 0); - - return r; -} - -struct nft_rule * -rule_set_filter(uint8_t family, const char * ifname, uint8_t proto, - in_addr_t rhost, in_addr_t iaddr, unsigned short eport, - unsigned short iport, const char *descr, const char *handle) -{ - struct nft_rule *r = NULL; - uint16_t dport; - uint64_t handle_num; - uint32_t if_idx; - uint32_t descr_len; - UNUSED(eport); - - r = nft_rule_alloc(); - if (r == NULL) { - perror("OOM"); - exit(EXIT_FAILURE); - } - - nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, NFT_TABLE_FILTER); - nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, miniupnpd_nft_forward_chain); - nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, family); - if (descr != NULL) { - descr_len = strlen(descr); - nft_rule_attr_set_data(r, NFT_RULE_ATTR_USERDATA, - descr, descr_len); - } - - if (handle != NULL) { - handle_num = atoll(handle); - nft_rule_attr_set_u64(r, NFT_RULE_ATTR_POSITION, handle_num); - } - - if (ifname != NULL) { - if_idx = (uint32_t)if_nametoindex(ifname); - expr_add_meta(r, NFT_META_IIF, NFT_REG_1); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &if_idx, - sizeof(uint32_t)); - } - - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, daddr), sizeof(uint32_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &iaddr, sizeof(uint32_t)); - - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, protocol), sizeof(uint8_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &proto, sizeof(uint8_t)); - - dport = htons(iport); - expr_add_payload(r, NFT_PAYLOAD_TRANSPORT_HEADER, NFT_REG_1, - offsetof(struct tcphdr, dest), sizeof(uint16_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &dport, sizeof(uint16_t)); - - if (rhost != 0) { - expr_add_payload(r, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, - offsetof(struct iphdr, saddr), - sizeof(in_addr_t)); - expr_add_cmp(r, NFT_REG_1, NFT_CMP_EQ, &rhost, - sizeof(in_addr_t)); - } - - expr_set_reg_verdict(r, NF_ACCEPT); - - return r; -} - -struct nft_rule * -rule_del_handle(rule_t *rule) -{ - struct nft_rule *r = NULL; - - r = nft_rule_alloc(); - if (r == NULL) { - perror("OOM"); - exit(EXIT_FAILURE); - } - - nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, rule->table); - nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, rule->chain); - nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FAMILY, rule->family); - nft_rule_attr_set_u64(r, NFT_RULE_ATTR_HANDLE, rule->handle); - - return r; -} - -static void -nft_mnl_batch_put(char *buf, uint16_t type, uint32_t seq) -{ - struct nlmsghdr *nlh; - struct nfgenmsg *nfg; - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = type; - nlh->nlmsg_flags = NLM_F_REQUEST; - nlh->nlmsg_seq = seq; - - nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); - nfg->nfgen_family = AF_INET; - nfg->version = NFNETLINK_V0; - nfg->res_id = NFNL_SUBSYS_NFTABLES; -} - -int -nft_send_request(struct nft_rule * rule, uint16_t cmd) -{ - struct nlmsghdr *nlh; - struct mnl_nlmsg_batch *batch; - char buf[MNL_SOCKET_BUFFER_SIZE]; - uint32_t seq = time(NULL); - int ret; - - rule_list_validate = RULE_CACHE_INVALID; - if (nl == NULL) { - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - perror("mnl_socket_bind"); - return -1; - } - } - - batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); - - nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), - NFNL_MSG_BATCH_BEGIN, seq++); - mnl_nlmsg_batch_next(batch); - - nlh = nft_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), - cmd, - nft_rule_attr_get_u32(rule, NFT_RULE_ATTR_FAMILY), - NLM_F_APPEND|NLM_F_CREATE|NLM_F_ACK, - seq++); - - nft_rule_nlmsg_build_payload(nlh, rule); - nft_rule_free(rule); - mnl_nlmsg_batch_next(batch); - - nft_mnl_batch_put(mnl_nlmsg_batch_current(batch), NFNL_MSG_BATCH_END, - seq++); - mnl_nlmsg_batch_next(batch); - - ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), - mnl_nlmsg_batch_size(batch)); - if (ret == -1) { - perror("mnl_socket_sendto"); - return -1; - } - - mnl_nlmsg_batch_stop(batch); - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret == -1) { - perror("mnl_socket_recvfrom"); - return -1; - } - - ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(nl), NULL, NULL); - if (ret < 0) { - perror("mnl_cb_run"); - return -1; - } - - /* mnl_socket_close(nl); */ - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.h b/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.h deleted file mode 100644 index e04403e..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/nftnlrdr_misc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2015 Tomofumi Hayashi - * - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution. - */ -#include - -#define NFT_TABLE_NAT "nat" -#define NFT_TABLE_FILTER "filter" - -enum rule_reg_type { - RULE_REG_NONE, - RULE_REG_IIF, - RULE_REG_OIF, - RULE_REG_IP_SRC_ADDR, - RULE_REG_IP_DEST_ADDR, - RULE_REG_IP_SD_ADDR, /* source & dest */ - RULE_REG_IP_PROTO, - RULE_REG_TCP_DPORT, - RULE_REG_TCP_SD_PORT, /* source & dest */ - RULE_REG_IMM_VAL, - RULE_REG_MAX, -}; - -enum rule_type { - RULE_NONE, - RULE_NAT, - RULE_SNAT, - RULE_FILTER, - RULE_COUNTER, -}; - -typedef struct rule_ { - LIST_ENTRY(rule_t) entry; - char * table; - char * chain; - uint64_t handle; - enum rule_type type; - uint32_t nat_type; - uint32_t filter_action; - uint32_t family; - uint32_t ingress_ifidx; - uint32_t egress_ifidx; - in_addr_t eaddr; - in_addr_t iaddr; - in_addr_t rhost; - uint16_t eport; - uint16_t iport; - uint16_t rport; - uint8_t proto; - enum rule_reg_type reg1_type; - enum rule_reg_type reg2_type; - uint32_t reg1_val; - uint32_t reg2_val; - uint64_t packets; - uint64_t bytes; - char *desc; -} rule_t; - -LIST_HEAD(rule_list, rule_); -extern struct rule_list head; -extern rule_t **peer_cache; -extern rule_t **redirect_cache; - -int -nft_send_request(struct nft_rule * rule, uint16_t cmd); -struct nft_rule * -rule_set_dnat(uint8_t family, const char * ifname, uint8_t proto, - in_addr_t rhost, unsigned short eport, - in_addr_t ihost, uint32_t iport, - const char *descr, - const char *handle); -struct nft_rule * -rule_set_snat(uint8_t family, uint8_t proto, - in_addr_t rhost, unsigned short rport, - in_addr_t ehost, unsigned short eport, - in_addr_t ihost, unsigned short iport, - const char *descr, - const char *handle); -struct nft_rule * -rule_set_filter(uint8_t family, const char * ifname, uint8_t proto, - in_addr_t rhost, in_addr_t iaddr, unsigned short eport, - unsigned short iport, const char * descr, const char *handle); -struct nft_rule * -rule_del_handle(rule_t *r); -void -reflesh_nft_cache(uint32_t family); -void print_rule(rule_t *r); diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_delete_chain.sh b/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_delete_chain.sh deleted file mode 100644 index 97f9fbe..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_delete_chain.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /sbin/nft -f - -delete chain nat miniupnpd -delete chain nat miniupnpd-pcp-peer -delete chain filter miniupnpd diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_flush.sh b/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_flush.sh deleted file mode 100644 index bd6c878..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_flush.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /sbin/nft -f - -flush chain ip nat miniupnpd -flush chain ip nat miniupnpd-pcp-peer -flush chain ip filter miniupnpd diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_init.sh b/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_init.sh deleted file mode 100644 index 45b42ea..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_init.sh +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh - -nft list table nat > /dev/null -nft_nat_exists=$? -nft list table filter > /dev/null -nft_filter_exists=$? -nft list table mangle > /dev/null -nft_mangle_exists=$? - -if [ $nft_nat_exists -eq "1" ]; then - echo "create nat" - nft "add table nat" -fi -if [ $nft_filter_exists -eq "1" ]; then - echo "create filter" - nft "add table filter" -fi -if [ $nft_mangle_exists -eq "1" ]; then - echo "create mangle" - nft "add table mangle" -fi - -nft list chain nat miniupnpd > /dev/null -nft_nat_miniupnpd_exists=$? -nft list chain nat miniupnpd-pcp-peer > /dev/null -nft_nat_miniupnpd_pcp_peer_exists=$? -nft list chain filter miniupnpd > /dev/null -nft_filter_miniupnpd_exists=$? -nft list chain mangle miniupnpd > /dev/null -nft_mangle_miniupnpd_exists=$? - -if [ $nft_nat_miniupnpd_exists -eq "1" ]; then - echo "create chain in nat" - nft "add chain nat miniupnpd" -fi -if [ $nft_nat_miniupnpd_pcp_peer_exists -eq "1" ]; then - echo "create pcp peer chain in nat" - nft "add chain nat miniupnpd-pcp-peer" -fi -if [ $nft_filter_miniupnpd_exists -eq "1" ]; then - echo "create chain in filter " - nft "add chain filter miniupnpd" -fi -if [ $nft_mangle_miniupnpd_exists -eq "1" ]; then - echo "create chain in mangle" - nft "add chain mangle miniupnpd" -fi diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_removeall.sh b/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_removeall.sh deleted file mode 100644 index 11c38e7..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/scripts/nft_removeall.sh +++ /dev/null @@ -1,5 +0,0 @@ -#! /sbin/nft -f - -delete rule nat miniupnpd -delete rule nat miniupnpd-pcp-peer -delete rule filter miniupnpd diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/test_nfct_get.c b/src/contrib/miniupnp/miniupnpd/netfilter_nft/test_nfct_get.c deleted file mode 100644 index af8c07d..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/test_nfct_get.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "nfct_get.c" - -int main(int argc, char *argv[]) -{ - struct sockaddr_storage src, dst, ext; - char buff[INET6_ADDRSTRLEN]; - - if (argc!=5) - return 0; - - if (1 != inet_pton(AF_INET, argv[1], - &((struct sockaddr_in*)&src)->sin_addr)) { - if (1 != inet_pton(AF_INET6, argv[1], - &((struct sockaddr_in6*) &src)->sin6_addr)) { - perror("bad input param"); - } else { - ((struct sockaddr_in6*)(&src))->sin6_port = htons(atoi(argv[2])); - src.ss_family = AF_INET6; - } - } else { - ((struct sockaddr_in*)(&src))->sin_port = htons(atoi(argv[2])); - src.ss_family = AF_INET; - } - - if (1 != inet_pton(AF_INET, argv[3], - &((struct sockaddr_in*)&dst)->sin_addr)) { - if (1 != inet_pton(AF_INET6, argv[3], - &((struct sockaddr_in6*) &dst)->sin6_addr)) { - perror("bad input param"); - } else { - ((struct sockaddr_in6*)(&dst))->sin6_port = htons(atoi(argv[4])); - dst.ss_family = AF_INET6; - } - } else { - ((struct sockaddr_in*)(&dst))->sin_port = htons(atoi(argv[4])); - dst.ss_family = AF_INET; - } - - if (get_nat_ext_addr((struct sockaddr*)&src, (struct sockaddr*)&dst, - IPPROTO_TCP, &ext)) { - printf("Ext address %s:%d\n", - inet_ntop(src.ss_family, - &((struct sockaddr_in*)&ext)->sin_addr, - buff, sizeof(buff)), - ntohs(((struct sockaddr_in*)(&ext))->sin_port)); - } else { - printf("no entry\n"); - } - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/testnftnlrdr.c b/src/contrib/miniupnp/miniupnpd/netfilter_nft/testnftnlrdr.c deleted file mode 100644 index efeccb3..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/testnftnlrdr.c +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include - -#include "nftnlrdr.h" -#include "../commonrdr.h" - -#ifndef PRIu64 -#define PRIu64 "llu" -#endif - -static int -add_filter_rule(int proto, const char * rhost, - const char * iaddr, unsigned short iport) -{ - return add_filter_rule2(NULL, rhost, iaddr, 0, iport, proto, NULL); -} - -static int -addnatrule(int proto, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * rhost) -{ - return add_redirect_rule2(NULL, rhost, eport, iaddr, iport, proto, NULL, 0); -} - -int -main(int argc, char ** argv) -{ - unsigned short eport, iport; - const char * iaddr; - - if(argc<4) { - printf("Usage %s \n", argv[0]); - return -1; - } - openlog("testnftnlrdr", LOG_PERROR|LOG_CONS, LOG_LOCAL0); - eport = (unsigned short)atoi(argv[1]); - iaddr = argv[2]; - iport = (unsigned short)atoi(argv[3]); - printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport); - if(addnatrule(IPPROTO_TCP, eport, iaddr, iport, NULL) < 0) { - printf("addnatrule() failed!\n"); - return -1; - } - if(add_filter_rule(IPPROTO_TCP, NULL, iaddr, iport) < 0) { - printf("add_filter_rule() failed!\n"); - return -1; - } - /* test */ - { - unsigned short p1, p2; - char addr[16]; - int proto2; - char desc[256]; - char rhost[256]; - unsigned int timestamp; - u_int64_t packets, bytes; - - desc[0] = '\0'; - printf("test0\n"); - if(get_redirect_rule_by_index(0, "", &p1, - addr, sizeof(addr), &p2, - &proto2, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) < 0) - { - printf("rule not found\n"); - } - else - { - printf("redirected port %hu to %s:%hu proto %d packets=%" PRIu64 " bytes=%" PRIu64 "\n", - p1, addr, p2, proto2, packets, bytes); - } - printf("test\n"); - } - printf("trying to list nat rules :\n"); - list_redirect_rule(argv[1]); - printf("deleting\n"); - delete_redirect_and_filter_rules(eport, IPPROTO_TCP); - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/netfilter_nft/tiny_nf_nat.h b/src/contrib/miniupnp/miniupnpd/netfilter_nft/tiny_nf_nat.h deleted file mode 100644 index f7f5b27..0000000 --- a/src/contrib/miniupnp/miniupnpd/netfilter_nft/tiny_nf_nat.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: tiny_nf_nat.h,v 1.1 2011/07/30 13:14:36 nanard Exp $ */ -/* Only what miniupnpd needs, until linux-libc-dev gains nf_nat.h */ - -#ifndef TINY_NF_NAT_H -#define TINY_NF_NAT_H - -#include - -#define IP_NAT_RANGE_MAP_IPS 1 -#define IP_NAT_RANGE_PROTO_SPECIFIED 2 -#define IP_NAT_RANGE_PROTO_RANDOM 4 -#define IP_NAT_RANGE_PERSISTENT 8 - -union nf_conntrack_man_proto { - __be16 all; - struct { __be16 port; } tcp; - struct { __be16 port; } udp; - struct { __be16 id; } icmp; - struct { __be16 port; } dccp; - struct { __be16 port; } sctp; - struct { __be16 key; } gre; -}; - -struct nf_nat_range { - unsigned int flags; - __be32 min_ip, max_ip; - union nf_conntrack_man_proto min, max; -}; - -struct nf_nat_multi_range_compat { - unsigned int rangesize; - struct nf_nat_range range[1]; -}; - -#define nf_nat_multi_range nf_nat_multi_range_compat - -#endif /*TINY_NF_NAT_H*/ diff --git a/src/contrib/miniupnp/miniupnpd/options.c b/src/contrib/miniupnp/miniupnpd/options.c deleted file mode 100644 index 9448ba8..0000000 --- a/src/contrib/miniupnp/miniupnpd/options.c +++ /dev/null @@ -1,323 +0,0 @@ -/* $Id: options.c,v 1.28 2013/12/13 14:07:08 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * author: Ryan Wagoner - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include "config.h" -#include "options.h" -#include "upnppermissions.h" -#ifdef PCP_SADSCP -#include "pcplearndscp.h" -#endif /* PCP_SADSPC */ -#include "upnpglobalvars.h" - -#ifndef DISABLE_CONFIG_FILE -struct option * ary_options = NULL; -static char * string_repo = NULL; -unsigned int num_options = 0; - -static const struct { - enum upnpconfigoptions id; - const char * name; -} optionids[] = { - { UPNPEXT_IFNAME, "ext_ifname" }, - { UPNPEXT_IP, "ext_ip" }, - { UPNPLISTENING_IP, "listening_ip" }, -#ifdef ENABLE_IPV6 - { UPNPIPV6_LISTENING_IP, "ipv6_listening_ip" }, -#endif /* ENABLE_IPV6 */ - { UPNPPORT, "port" }, - { UPNPPORT, "http_port" }, /* "port" and "http_port" are synonims */ -#ifdef ENABLE_HTTPS - { UPNPHTTPSPORT, "https_port" }, -#endif /* ENABLE_HTTPS */ - { UPNPBITRATE_UP, "bitrate_up" }, - { UPNPBITRATE_DOWN, "bitrate_down" }, - { UPNPPRESENTATIONURL, "presentation_url" }, -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION - { UPNPFRIENDLY_NAME, "friendly_name" }, - { UPNPMANUFACTURER_NAME, "manufacturer_name" }, - { UPNPMANUFACTURER_URL, "manufacturer_url" }, - { UPNPMODEL_NAME, "model_name" }, - { UPNPMODEL_DESCRIPTION, "model_description" }, - { UPNPMODEL_URL, "model_url" }, -#endif - { UPNPNOTIFY_INTERVAL, "notify_interval" }, - { UPNPSYSTEM_UPTIME, "system_uptime" }, - { UPNPPACKET_LOG, "packet_log" }, - { UPNPUUID, "uuid"}, - { UPNPSERIAL, "serial"}, - { UPNPMODEL_NUMBER, "model_number"}, - { UPNPCLEANTHRESHOLD, "clean_ruleset_threshold"}, - { UPNPCLEANINTERVAL, "clean_ruleset_interval"}, -#ifdef USE_NETFILTER - { UPNPFORWARDCHAIN, "upnp_forward_chain"}, - { UPNPNATCHAIN, "upnp_nat_chain"}, - { UPNPNATPOSTCHAIN, "upnp_nat_postrouting_chain"}, -#endif -#ifdef ENABLE_NATPMP - { UPNPENABLENATPMP, "enable_natpmp"}, -#endif -#ifdef ENABLE_PCP - { UPNPPCPMINLIFETIME, "min_lifetime"}, - { UPNPPCPMAXLIFETIME, "max_lifetime"}, - { UPNPPCPALLOWTHIRDPARTY, "pcp_allow_thirdparty"}, -#endif - { UPNPENABLE, "enable_upnp"}, -#ifdef USE_PF - { UPNPANCHOR, "anchor"}, - { UPNPQUEUE, "queue"}, - { UPNPTAG, "tag"}, -#endif -#ifdef PF_ENABLE_FILTER_RULES - { UPNPQUICKRULES, "quickrules" }, -#endif -#ifdef ENABLE_LEASEFILE - { UPNPLEASEFILE, "lease_file"}, -#endif -#ifdef IGD_V2 - { UPNPFORCEIGDDESCV1, "force_igd_desc_v1"}, -#endif - { UPNPMINISSDPDSOCKET, "minissdpdsocket"}, - { UPNPSECUREMODE, "secure_mode"} -}; - -int -readoptionsfile(const char * fname) -{ - FILE *hfile = NULL; - char buffer[1024]; - char *equals; - char *name; - char *value; - char *t; - int linenum = 0; - unsigned int i; - enum upnpconfigoptions id; - size_t string_repo_len = 0; - size_t len; - void *tmp; - - if(!fname || (fname[0] == '\0')) - return -1; - - memset(buffer, 0, sizeof(buffer)); - -#ifdef DEBUG - printf("Reading configuration from file %s\n", fname); -#endif - - if(!(hfile = fopen(fname, "r"))) - return -1; - - if(ary_options != NULL) - { - free(ary_options); - num_options = 0; - } - - while(fgets(buffer, sizeof(buffer), hfile)) - { - linenum++; - t = strchr(buffer, '\n'); - if(t) - { - *t = '\0'; - t--; - /* remove spaces at the end of the line */ - while((t >= buffer) && isspace(*t)) - { - *t = '\0'; - t--; - } - } - - /* skip leading whitespaces */ - name = buffer; - while(isspace(*name)) - name++; - - /* check for comments or empty lines */ - if(name[0] == '#' || name[0] == '\0') continue; - - len = strlen(name); /* length of the whole line excluding leading - * and ending white spaces */ - /* check for UPnP permissions rule */ - if((len > 6) && (0 == memcmp(name, "allow", 5) || 0 == memcmp(name, "deny", 4))) - { - tmp = realloc(upnppermlist, sizeof(struct upnpperm) * (num_upnpperm+1)); - if(tmp == NULL) - { - fprintf(stderr, "memory allocation error. Permission line in file %s line %d\n", - fname, linenum); - } - else - { - upnppermlist = tmp; - /* parse the rule */ - if(read_permission_line(upnppermlist + num_upnpperm, name) >= 0) - { - num_upnpperm++; - } - else - { - fprintf(stderr, "parsing error file %s line %d : %s\n", - fname, linenum, name); - } - } - continue; - } -#ifdef PCP_SADSCP - /* check for DSCP values configuration */ - if((len > 15) && 0 == memcmp(name, "set_learn_dscp", sizeof("set_learn_dscp")-1) ) - { - tmp = realloc(dscp_values_list, sizeof(struct dscp_values) * (num_dscp_values+1)); - if(tmp == NULL) - { - fprintf(stderr, "memory allocation error. DSCP line in file %s line %d\n", - fname, linenum); - } - else - { - dscp_values_list = tmp; - /* parse the rule */ - if(read_learn_dscp_line(dscp_values_list + num_dscp_values, name) >= 0) - { - num_dscp_values++; - } - else - { - fprintf(stderr, "parsing error file %s line %d : %s\n", - fname, linenum, name); - } - } - continue; - } -#endif /* PCP_SADSCP */ - if(!(equals = strchr(name, '='))) - { - fprintf(stderr, "parsing error file %s line %d : %s\n", - fname, linenum, name); - continue; - } - - /* remove ending whitespaces */ - for(t=equals-1; t>name && isspace(*t); t--) - *t = '\0'; - - *equals = '\0'; - value = equals+1; - - /* skip leading whitespaces */ - while(isspace(*value)) - value++; - - id = UPNP_INVALID; - for(i=0; i -#include -#include -#include -#include - -#include "upnpglobalvars.h" -#include "pcplearndscp.h" - -#ifdef PCP_SADSCP - -void -print_dscp(void) { - unsigned int i; - - for (i=0; i < num_dscp_values; i++){ - syslog(LOG_DEBUG, "Appname %*.s, del %d, loss %d, jitter %d, dscp %d", - dscp_values_list[i].app_name_len, - dscp_values_list[i].app_name, dscp_values_list[i].delay, - dscp_values_list[i].loss, dscp_values_list[i].jitter, - dscp_values_list[i].dscp_value - ); - } -} - -int -read_learn_dscp_line(struct dscp_values *dscpvalues, char *p) -{ - char * q; - size_t len; - unsigned int sizeof_first_token = sizeof("set_learn_dscp") - 1; - int af_value; - int cs_value; - - /* first token: (set_learn_dscp) skip it */ - while(isspace(*p)) - p++; - if(0 == memcmp(p, "set_learn_dscp", sizeof_first_token)) - { - p += sizeof_first_token; - } - else - { - return -1; - } - while(isspace(*p)) - p++; - - /* second token: name of the application */ - // if - if(!(*p == '"')) - return -1; - p++; - for(q = p; !(*q == '"'); q++); - len = q - p; - if (len != 0) { - dscpvalues->app_name = strndup(p, len); - } else { - dscpvalues->app_name = NULL; - } - dscpvalues->app_name_len = len; - p = q + 1; - - /* third token: delay */ - while(isspace(*p)) - p++; - if(!isdigit(*p)) - goto exit_err_and_cleanup; - for(q = p; isdigit(*q); q++); - if(isspace(*q)) - { - *q = '\0'; - dscpvalues->delay = (unsigned char)atoi(p); - if (dscpvalues->delay >= 3) { - fprintf(stderr, "Wrong delay value %d in \n", dscpvalues->delay); - fprintf(stderr, "Delay can be from set {0,1,2} 0=low delay, 1=medium delay, 2=high delay\n"); - goto exit_err_and_cleanup; - } - } - else - { - goto exit_err_and_cleanup; - } - p = q + 1; - - /* fourth token: loss */ - while(isspace(*p)) - p++; - if(!isdigit(*p)) - goto exit_err_and_cleanup; - - for(q = p; isdigit(*q); q++); - if(isspace(*q)) - { - *q = '\0'; - dscpvalues->loss = (unsigned char)atoi(p); - if (dscpvalues->loss >= 3) { - fprintf(stderr, "Wrong loss value %d \n", dscpvalues->loss); - fprintf(stderr, "Delay can be from set {0,1,2} 0=low loss, 1=medium loss, 2=high loss\n"); - goto exit_err_and_cleanup; - } - } - else - { - goto exit_err_and_cleanup; - } - p = q + 1; - - /* fifth token: jitter */ - while(isspace(*p)) - p++; - if(!isdigit(*p)) - goto exit_err_and_cleanup; - for(q = p; isdigit(*q); q++); - if(isspace(*q)) - { - *q = '\0'; - dscpvalues->jitter = (unsigned char)atoi(p); - if (dscpvalues->jitter >= 3) { - fprintf(stderr, "Wrong jitter value %d \n", dscpvalues->jitter); - fprintf(stderr, "Delay can be from set {0,1,2} 0=low jitter, 1=medium jitter, 2=high jitter \n"); - goto exit_err_and_cleanup; - } - } - else - { - goto exit_err_and_cleanup; - } - p = q + 1; - while(isspace(*p)) - p++; - /*{ - }*/ - p = q + 1; - - /* sixth token: DSCP value */ - while(isspace(*p)) - p++; - if(!isdigit(*p) && !( toupper(*p) == 'A' && toupper(*(p+1)) == 'F') && - !( toupper(*p) == 'C' && toupper(*(p+1)) == 'S') && - !( toupper(*p) == 'E' && toupper(*(p+1)) == 'F') - ) - goto exit_err_and_cleanup; -// for(q = p; isdigit(*q) || (toupper(*q) == 'A') || (toupper(*q) == 'F'); q++); - for(q = p; isdigit(*q) || isalpha(*q); q++); - if(isspace(*q) || *q == '\0') - { - *q = '\0'; - if (toupper(*p) == 'A' && toupper(*(p+1)) == 'F'){ - p = p+2; - if (*p == '\0') { - dscpvalues->dscp_value = 0; - } - else if (!isdigit(*p)) { - goto exit_err_and_cleanup; - } - else { - af_value = atoi(p); - switch(af_value) { - case 11: - dscpvalues->dscp_value = 10; - break; - case 12: - dscpvalues->dscp_value = 12; - break; - case 13: - dscpvalues->dscp_value = 14; - break; - case 21: - dscpvalues->dscp_value = 18; - break; - case 22: - dscpvalues->dscp_value = 20; - break; - case 23: - dscpvalues->dscp_value = 22; - break; - case 31: - dscpvalues->dscp_value = 26; - break; - case 32: - dscpvalues->dscp_value = 28; - break; - case 33: - dscpvalues->dscp_value = 30; - break; - case 41: - dscpvalues->dscp_value = 34; - break; - case 42: - dscpvalues->dscp_value = 36; - break; - case 43: - dscpvalues->dscp_value = 38; - break; - default: - fprintf(stderr, "Unknown AF value %d \n", af_value); - goto exit_err_and_cleanup; - } - } - } - else if (toupper(*p) == 'C' && toupper(*(p+1)) == 'S'){ - p=p+2; - if (*p == '\0') { - dscpvalues->dscp_value = 0; - } - else if (!isdigit(*p)) { - fprintf(stderr, "Not digit after CS but %c \n", *p); - goto exit_err_and_cleanup; - } - else { - cs_value = atoi(p); - switch(cs_value) { - case 1: - dscpvalues->dscp_value = 8; - break; - case 2: - dscpvalues->dscp_value = 16; - break; - case 3: - dscpvalues->dscp_value = 24; - break; - case 4: - dscpvalues->dscp_value = 32; - break; - case 5: - dscpvalues->dscp_value = 40; - break; - case 6: - dscpvalues->dscp_value = 48; - break; - case 7: - dscpvalues->dscp_value = 56; - break; - default: - fprintf(stderr, "Unknown CS value %d \n", cs_value); - goto exit_err_and_cleanup; - } - } - } - else if (toupper(*p) == 'E' && toupper(*(p+1)) == 'F'){ - dscpvalues->dscp_value = 46; - } - else { - dscpvalues->dscp_value = (unsigned char)atoi(p); - } - } - else - { - goto exit_err_and_cleanup; - } - - return 0; - -exit_err_and_cleanup: - free(dscpvalues->app_name); - dscpvalues->app_name = NULL; - dscpvalues->app_name_len = 0; - return -1; - - -} - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/pcplearndscp.h b/src/contrib/miniupnp/miniupnpd/pcplearndscp.h deleted file mode 100644 index 93fee33..0000000 --- a/src/contrib/miniupnp/miniupnpd/pcplearndscp.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $Id: pcplearndscp.h,v 1.2 2013/12/13 15:47:23 nanard Exp $ */ -/* MiniUPnP project - * Website : http://miniupnp.free.fr/ - * Author : Miroslav Bagljas - -Copyright (c) 2013 by Cisco Systems, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef PCPLEARNDSCP_H_INCLUDED -#define PCPLEARNDSCP_H_INCLUDED - -struct dscp_values { - char *app_name; - unsigned int app_name_len; - unsigned char delay; - unsigned char loss; - unsigned char jitter; - unsigned char dscp_value; -}; - - - -/* #set_learn_dscp "Webex" 1 1 1 34 */ -int -read_learn_dscp_line(struct dscp_values *dscpvalues, char *p); - -#endif /* PCPLEARNDSCP_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/pcpserver.c b/src/contrib/miniupnp/miniupnpd/pcpserver.c deleted file mode 100644 index 7930fa5..0000000 --- a/src/contrib/miniupnp/miniupnpd/pcpserver.c +++ /dev/null @@ -1,1700 +0,0 @@ -/* $Id: pcpserver.c,v 1.47 2018/03/13 10:21:19 nanard Exp $ */ -/* MiniUPnP project - * Website : http://miniupnp.free.fr/ - * Author : Peter Tatrai - -Copyright (c) 2013 by Cisco Systems, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -/* Current assumptions: - - IPv4 is always NATted (internal -> external) - - IPv6 is always firewalled (this may need some work, NAT6* do exist) - - - we make the judgement based on (in order, picking first one available): - - third party address - - internal client address - - TODO : handle NAT46, NAT64, NPT66. In addition, beyond FW/NAT - choice, should also add for proxy (=as much as possible transparent - pass-through to one or more servers). - - TODO: IPv6 permission handling (for the time being, we just assume - anyone on IPv6 is a good guy, but fixing that would include - upnppermissions rewrite to be AF neutral). -*/ - -#include "config.h" - -#ifdef ENABLE_PCP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcpserver.h" -#include "natpmp.h" -#include "macros.h" -#include "upnpglobalvars.h" -#include "pcplearndscp.h" -#include "upnpredirect.h" -#include "commonrdr.h" -#include "getifaddr.h" -#include "asyncsendto.h" -#include "upnputils.h" -#include "portinuse.h" -#include "pcp_msg_struct.h" -#ifdef ENABLE_UPNPPINHOLE -#include "upnppinhole.h" -#endif /* ENABLE_UPNPPINHOLE */ - - -#ifdef PCP_PEER -/* TODO make this platform independent */ -#ifdef USE_NETFILTER -#include "netfilter/iptcrdr.h" -#else -#error "PCP Peer is only supported with NETFILTER" -#endif /* USE_NETFILTER */ -#endif /* PCP_PEER */ - -/* server specific information */ -struct pcp_server_info { - uint8_t server_version; -}; - -/* default server settings, highest version supported is the default */ -static const struct pcp_server_info this_server_info = {2}; - -/* structure holding information from PCP msg*/ -/* all variables are in host byte order except IP addresses */ -typedef struct pcp_info { - uint8_t version; - uint8_t opcode; - uint8_t result_code; - uint32_t lifetime; /* lifetime of the mapping */ - uint32_t epochtime; - /* both MAP and PEER opcode specific information */ - uint32_t nonce[3]; /* random value generated by client */ - uint8_t protocol; - uint16_t int_port; - const struct in6_addr *int_ip; /* in network order */ - uint16_t ext_port; - const struct in6_addr *ext_ip; /* Suggested external IP in network order*/ - /* PEER specific information */ -#ifdef PCP_PEER - uint16_t peer_port; - const struct in6_addr *peer_ip; /* Destination IP in network order */ -#endif /* PCP_PEER */ - -#ifdef PCP_SADSCP - /* SADSCP specific information */ - uint8_t delay_tolerance; - uint8_t loss_tolerance; - uint8_t jitter_tolerance; - uint8_t app_name_len; - const char* app_name; - uint8_t sadscp_dscp; - uint8_t matched_name; - int8_t is_sadscp_op; -#endif - -#ifdef PCP_FLOWP - uint8_t dscp_up; - uint8_t dscp_down; - int flowp_present; -#endif - uint8_t is_map_op; - uint8_t is_peer_op; - const struct in6_addr *thirdp_ip; - const struct in6_addr *mapped_ip; - char mapped_str[INET6_ADDRSTRLEN]; - int pfailure_present; - struct in6_addr sender_ip; - int is_fw; /* is this firewall operation? if not, nat. */ - char desc[64]; -} pcp_info_t; - -/* getPCPOpCodeStr() - * return a string representation of the PCP OpCode - * can be used for debug output */ -static const char * getPCPOpCodeStr(uint8_t opcode) -{ - switch(opcode) { - case PCP_OPCODE_ANNOUNCE: - return "ANNOUNCE"; - case PCP_OPCODE_MAP: - return "MAP"; - case PCP_OPCODE_PEER: - return "PEER"; -#ifdef PCP_SADSCP - case PCP_OPCODE_SADSCP: - return "SADSCP"; -#endif /* PCP_SADSCP */ - default: - return "UNKNOWN"; - } -} - -/* useful to copy ext_ip only if needed, as request and response - * buffers are same */ -static void copyIPv6IfDifferent(void * dest, const void * src) -{ - if(dest != src) { - memcpy(dest, src, sizeof(struct in6_addr)); - } -} - -#ifdef PCP_SADSCP -int get_dscp_value(pcp_info_t *pcp_msg_info) { - - unsigned int ind; - - for (ind = 0; ind < num_dscp_values; ind++) { - - if ((dscp_values_list[ind].app_name) && - (!strcmp(dscp_values_list[ind].app_name, - pcp_msg_info->app_name)) && - (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && - (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && - (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) - ) - { - pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; - pcp_msg_info->matched_name = 1; - return 0; - } else - if ((pcp_msg_info->app_name_len==0) && - (dscp_values_list[ind].app_name_len==0) && - (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && - (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && - (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) - ) - { - pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; - pcp_msg_info->matched_name = 0; - return 0; - } else - if ((dscp_values_list[ind].app_name_len==0) && - (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && - (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && - (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) - ) - { - pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; - pcp_msg_info->matched_name = 0; - return 0; - } - } - //if nothing matched return Default value i.e. 0 - pcp_msg_info->sadscp_dscp = 0; - pcp_msg_info->matched_name = 0; - return 0; -} -#endif -/* - * Function extracting information from common_req (common request header) - * into pcp_msg_info. - * @return : when no problem occurred 0 is returned, 1 otherwise and appropriate - * result code is assigned to pcp_msg_info->result_code to indicate - * what kind of error occurred - */ -static int parseCommonRequestHeader(const uint8_t *common_req, pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->version = common_req[0] ; - pcp_msg_info->opcode = common_req[1] & 0x7f; - pcp_msg_info->lifetime = READNU32(common_req + 4); - pcp_msg_info->int_ip = (struct in6_addr *)(common_req + 8); - pcp_msg_info->mapped_ip = (struct in6_addr *)(common_req + 8); - - - if ( (pcp_msg_info->version > this_server_info.server_version) ) { - pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION; - return 1; - } - - if (pcp_msg_info->lifetime > max_lifetime ) { - pcp_msg_info->lifetime = max_lifetime; - } - - if ( (pcp_msg_info->lifetime < min_lifetime) && (pcp_msg_info->lifetime != 0) ) { - pcp_msg_info->lifetime = min_lifetime; - } - - return 0; -} - -#ifdef DEBUG -static void printMAPOpcodeVersion1(const uint8_t *buf) -{ - char map_addr[INET6_ADDRSTRLEN]; - syslog(LOG_DEBUG, "PCP MAP: v1 Opcode specific information. \n"); - syslog(LOG_DEBUG, "MAP protocol: \t\t %d\n", (int)buf[0] ); - syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", (int)READNU16(buf+4)); - syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", (int)READNU16(buf+6)); - syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6, - buf+8, map_addr, INET6_ADDRSTRLEN)); -} - -static void printMAPOpcodeVersion2(const uint8_t *buf) -{ - char map_addr[INET6_ADDRSTRLEN]; - syslog(LOG_DEBUG, "PCP MAP: v2 Opcode specific information."); - syslog(LOG_DEBUG, "MAP nonce: \t%08x%08x%08x", - READNU32(buf), READNU32(buf+4), READNU32(buf+8)); - syslog(LOG_DEBUG, "MAP protocol:\t%d", (int)buf[12]); - syslog(LOG_DEBUG, "MAP int port:\t%d", (int)READNU16(buf+16)); - syslog(LOG_DEBUG, "MAP ext port:\t%d", (int)READNU16(buf+18)); - syslog(LOG_DEBUG, "MAP Ext IP: \t%s", inet_ntop(AF_INET6, - buf+20, map_addr, INET6_ADDRSTRLEN)); -} -#endif /* DEBUG */ - -static void parsePCPMAP_version1(const uint8_t *map_v1, - pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->is_map_op = 1; - pcp_msg_info->protocol = map_v1[0]; - pcp_msg_info->int_port = READNU16(map_v1 + 4); - pcp_msg_info->ext_port = READNU16(map_v1 + 6); - - pcp_msg_info->ext_ip = (struct in6_addr *)(map_v1 + 8); -} - -static void parsePCPMAP_version2(const uint8_t *map_v2, - pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->is_map_op = 1; - memcpy(pcp_msg_info->nonce, map_v2, 12); - pcp_msg_info->protocol = map_v2[12]; - pcp_msg_info->int_port = READNU16(map_v2 + 16); - pcp_msg_info->ext_port = READNU16(map_v2 + 18); - - pcp_msg_info->ext_ip = (struct in6_addr *)(map_v2 + 20); -} - -#ifdef PCP_PEER -#ifdef DEBUG -static void printPEEROpcodeVersion1(const uint8_t *buf) -{ - char ext_addr[INET6_ADDRSTRLEN]; - char peer_addr[INET6_ADDRSTRLEN]; - syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n"); - syslog(LOG_DEBUG, "Protocol: \t\t %d\n", (int)buf[0]); - syslog(LOG_DEBUG, "Internal port: \t\t %d\n", READNU16(buf + 4)); - syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 8, - ext_addr,INET6_ADDRSTRLEN)); - syslog(LOG_DEBUG, "External port port: \t\t %d\n", READNU16(buf + 6)); - syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 28, - peer_addr,INET6_ADDRSTRLEN)); - syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", READNU16(buf + 24)); -} - -static void printPEEROpcodeVersion2(const uint8_t *buf) -{ - char ext_addr[INET6_ADDRSTRLEN]; - char peer_addr[INET6_ADDRSTRLEN]; - - syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information."); - syslog(LOG_DEBUG, "nonce: \t%08x%08x%08x", - READNU32(buf), READNU32(buf+4), READNU32(buf+8)); - syslog(LOG_DEBUG, "Protocol: \t%d", buf[12]); - syslog(LOG_DEBUG, "Internal port:\t%d", READNU16(buf + 16)); - syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, buf + 20, - ext_addr, INET6_ADDRSTRLEN)); - syslog(LOG_DEBUG, "External port:\t%d", READNU16(buf + 18)); - syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, buf + 40, - peer_addr, INET6_ADDRSTRLEN)); - syslog(LOG_DEBUG, "PEER port: \t%d", READNU16(buf + 36)); -} -#endif /* DEBUG */ - -/* - * Function extracting information from peer_buf to pcp_msg_info - * @return : when no problem occurred 0 is returned, 1 otherwise - */ -static void parsePCPPEER_version1(const uint8_t *buf, - pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->is_peer_op = 1; - pcp_msg_info->protocol = buf[0]; - pcp_msg_info->int_port = READNU16(buf + 4); - pcp_msg_info->ext_port = READNU16(buf + 6); - pcp_msg_info->peer_port = READNU16(buf + 24); - - pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 8); - pcp_msg_info->peer_ip = (struct in6_addr *)(buf + 28); -} - -/* - * Function extracting information from peer_buf to pcp_msg_info - * @return : when no problem occurred 0 is returned, 1 otherwise - */ -static void parsePCPPEER_version2(const uint8_t *buf, pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->is_peer_op = 1; - memcpy(pcp_msg_info->nonce, buf, 12); - pcp_msg_info->protocol = buf[12]; - pcp_msg_info->int_port = READNU16(buf + 16); - pcp_msg_info->ext_port = READNU16(buf + 18); - pcp_msg_info->peer_port = READNU16(buf + 36); - - pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 20); - pcp_msg_info->peer_ip = (struct in6_addr *)(buf + 40); -} -#endif /* PCP_PEER */ - -#ifdef PCP_SADSCP -#ifdef DEBUG -static void printSADSCPOpcode(const uint8_t *buf) -{ - unsigned char sadscp_tol; - sadscp_tol = buf[12]; /* tolerance_fields */ - - syslog(LOG_DEBUG, "PCP SADSCP: Opcode specific information.\n"); - syslog(LOG_DEBUG, "Delay tolerance %d \n", (sadscp_tol>>6)&3); - syslog(LOG_DEBUG, "Loss tolerance %d \n", (sadscp_tol>>4)&3); - syslog(LOG_DEBUG, "Jitter tolerance %d \n", (sadscp_tol>>2)&3); - syslog(LOG_DEBUG, "RRR %d \n", sadscp_tol&3); - syslog(LOG_DEBUG, "AppName Length %d \n", buf[13]); - syslog(LOG_DEBUG, "Application name %.*s \n", buf[13], buf + 14); -} -#endif //DEBUG - -static int parseSADSCP(const uint8_t *buf, pcp_info_t *pcp_msg_info) -{ - pcp_msg_info->delay_tolerance = (buf[12]>>6)&3; - pcp_msg_info->loss_tolerance = (buf[12]>>4)&3; - pcp_msg_info->jitter_tolerance = (buf[12]>>2)&3; - - if (pcp_msg_info->delay_tolerance == 3 || - pcp_msg_info->loss_tolerance == 3 || - pcp_msg_info->jitter_tolerance == 3 ) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 1; - } - - pcp_msg_info->app_name = (const char *)(buf + 14); - pcp_msg_info->app_name_len = buf[13]; - - return 0; -} -#endif /* PCP_SADSCP */ - - -static int parsePCPOption(uint8_t* pcp_buf, int remain, pcp_info_t *pcp_msg_info) -{ -#ifdef DEBUG - char third_addr[INET6_ADDRSTRLEN]; -#endif /* DEBUG */ - unsigned short option_length; - - /* Do centralized option sanity checks here. */ - - if (remain < (int)PCP_OPTION_HDR_SIZE) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } - - option_length = READNU16(pcp_buf + 2) + 4; /* len */ - - if (remain < option_length) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } - - switch (pcp_buf[0]) { /* code */ - - case PCP_OPTION_3RD_PARTY: - - if (option_length != PCP_3RD_PARTY_OPTION_SIZE) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } -#ifdef DEBUG - syslog(LOG_DEBUG, "PCP OPTION: \t Third party\n"); - syslog(LOG_DEBUG, "Third PARTY IP: \t %s\n", inet_ntop(AF_INET6, - pcp_buf + 4, third_addr, INET6_ADDRSTRLEN)); -#endif - if (pcp_msg_info->thirdp_ip ) { - syslog(LOG_ERR, "PCP: THIRD PARTY OPTION was already present. \n"); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } else { - pcp_msg_info->thirdp_ip = (struct in6_addr *)(pcp_buf + 4); - pcp_msg_info->mapped_ip = (struct in6_addr *)(pcp_buf + 4); - } - break; - - case PCP_OPTION_PREF_FAIL: - - if (option_length != PCP_PREFER_FAIL_OPTION_SIZE) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } -#ifdef DEBUG - syslog(LOG_DEBUG, "PCP OPTION: \t Prefer failure \n"); -#endif - if (pcp_msg_info->opcode != PCP_OPCODE_MAP) { - syslog(LOG_DEBUG, "PCP: Unsupported OPTION for given OPCODE.\n"); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - } - if (pcp_msg_info->pfailure_present != 0 ) { - syslog(LOG_DEBUG, "PCP: PREFER FAILURE OPTION was already present.\n"); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - } else { - pcp_msg_info->pfailure_present = 1; - } - break; - - case PCP_OPTION_FILTER: - /* TODO fully implement filter */ - if (option_length != PCP_FILTER_OPTION_SIZE) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } -#ifdef DEBUG - syslog(LOG_DEBUG, "PCP OPTION: \t Filter\n"); -#endif - if (pcp_msg_info->opcode != PCP_OPCODE_MAP) { - syslog(LOG_ERR, "PCP: Unsupported OPTION for given OPCODE.\n"); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 0; - } - break; - -#ifdef PCP_FLOWP - case PCP_OPTION_FLOW_PRIORITY: - -#ifdef DEBUG - syslog(LOG_DEBUG, "PCP OPTION: \t Flow priority\n"); -#endif - if (option_length != PCP_FLOW_PRIORITY_OPTION_SIZE) { - syslog(LOG_ERR, "PCP: Error processing DSCP. sizeof %d and remaining %d. flow len %d \n", - PCP_FLOW_PRIORITY_OPTION_SIZE, remain, READNU16(pcp_buf + 2)); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } - -#ifdef DEBUG - syslog(LOG_DEBUG, "DSCP UP: \t %d\n", pcp_buf[4]); - syslog(LOG_DEBUG, "DSCP DOWN: \t %d\n", pcp_buf[5]); -#endif - pcp_msg_info->dscp_up = pcp_buf[4]; - pcp_msg_info->dscp_down = pcp_buf[5]; - pcp_msg_info->flowp_present = 1; - - break; -#endif - default: - if (pcp_buf[0] < 128) { - syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", (int)pcp_buf[0]); - /* Mandatory to understand */ - pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION; - remain = 0; - break; - } - /* TODO - log optional not understood options? */ - break; - } - return option_length; -} - - -static void parsePCPOptions(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info) -{ - int option_length; - - while (remain > 0) { - option_length = parsePCPOption(pcp_buf, remain, pcp_msg_info); - if (!option_length) - break; - remain -= option_length; - pcp_buf += option_length; - } - if (remain > 0) { - syslog(LOG_WARNING, "%s: remain=%d", "parsePCPOptions", remain); - } -} - - -/* CheckExternalAddress() - * Check that suggested external address in request match a real external - * IP address. - * Suggested address can also be 0 IPv4 or IPv6 address. - * (see http://tools.ietf.org/html/rfc6887#section-10 ) - * return values : - * 0 : check is OK - * -1 : check failed */ -static int CheckExternalAddress(pcp_info_t* pcp_msg_info) -{ - /* can contain a IPv4-mapped IPv6 address */ - static struct in6_addr external_addr; - int af; - - af = IN6_IS_ADDR_V4MAPPED(pcp_msg_info->mapped_ip) - ? AF_INET : AF_INET6; - - pcp_msg_info->is_fw = af == AF_INET6; - - if (pcp_msg_info->is_fw) { - external_addr = *pcp_msg_info->mapped_ip; - } else { - /* TODO : be able to handle case with multiple - * external addresses */ - if(use_ext_ip_addr) { - if (inet_pton(AF_INET, use_ext_ip_addr, - ((uint32_t*)external_addr.s6_addr)+3) == 1) { - ((uint32_t*)external_addr.s6_addr)[0] = 0; - ((uint32_t*)external_addr.s6_addr)[1] = 0; - ((uint32_t*)external_addr.s6_addr)[2] = htonl(0xFFFF); - } else if (inet_pton(AF_INET6, use_ext_ip_addr, external_addr.s6_addr) - != 1) { - pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; - return -1; - } - } else { - if(!ext_if_name || ext_if_name[0]=='\0') { - pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; - return -1; - } - if(getifaddr_in6(ext_if_name, af, &external_addr) < 0) { - pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; - return -1; - } - } - } - if (pcp_msg_info->ext_ip == NULL || - IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip) || - (IN6_IS_ADDR_V4MAPPED(pcp_msg_info->ext_ip) - && ((uint32_t *)pcp_msg_info->ext_ip->s6_addr)[3] == INADDR_ANY)) { - /* no suggested external address : use real external address */ - pcp_msg_info->ext_ip = &external_addr; - return 0; - } - - if (!IN6_ARE_ADDR_EQUAL(pcp_msg_info->ext_ip, &external_addr)) { - syslog(LOG_ERR, - "PCP: External IP in request didn't match interface IP \n"); -#ifdef DEBUG - { - char s[INET6_ADDRSTRLEN]; - syslog(LOG_DEBUG, "Interface IP %s \n", - inet_ntop(AF_INET6, &external_addr.s6_addr, s, sizeof(s))); - syslog(LOG_DEBUG, "IP in the PCP request %s \n", - inet_ntop(AF_INET6, pcp_msg_info->ext_ip, s, sizeof(s))); - } -#endif - - if (pcp_msg_info->pfailure_present) { - pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - return -1; - } else { - pcp_msg_info->ext_ip = &external_addr; - } - - } - - return 0; -} - - -static const char* inet_n46top(const struct in6_addr* in, - char* buf, size_t buf_len) -{ - if (IN6_IS_ADDR_V4MAPPED(in)) { - return inet_ntop(AF_INET, ((uint32_t*)(in->s6_addr))+3, buf, buf_len); - } else { - return inet_ntop(AF_INET6, in, buf, buf_len); - } -} - -#ifdef PCP_PEER -static void FillSA(struct sockaddr *sa, const struct in6_addr *in6, - uint16_t port) -{ - if (IN6_IS_ADDR_V4MAPPED(in6)) { - struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; - sa4->sin_family = AF_INET; - sa4->sin_addr.s_addr = ((uint32_t*)(in6)->s6_addr)[3]; - sa4->sin_port = htons(port); - } else { - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; - sa6->sin6_family = AF_INET6; - sa6->sin6_addr = *in6; - sa6->sin6_port = htons(port); - } -} - -static const char* inet_satop(struct sockaddr* sa, char* buf, size_t buf_len) -{ - if (sa->sa_family == AF_INET) { - return inet_ntop(AF_INET, &(((struct sockaddr_in*)sa)->sin_addr), buf, buf_len); - } else { - return inet_ntop(AF_INET6, &(((struct sockaddr_in6*)sa)->sin6_addr), buf, buf_len); - } -} - -static int CreatePCPPeer_NAT(pcp_info_t *pcp_msg_info) -{ - struct sockaddr_storage intip; - struct sockaddr_storage peerip; - struct sockaddr_storage extip; - struct sockaddr_storage ret_extip; - - uint8_t proto = pcp_msg_info->protocol; - - uint16_t eport = pcp_msg_info->ext_port; /* public port */ - - char peerip_s[INET6_ADDRSTRLEN], extip_s[INET6_ADDRSTRLEN]; - time_t timestamp = upnp_time() + pcp_msg_info->lifetime; - int r; - - FillSA((struct sockaddr*)&intip, pcp_msg_info->mapped_ip, - pcp_msg_info->int_port); - FillSA((struct sockaddr*)&peerip, pcp_msg_info->peer_ip, - pcp_msg_info->peer_port); - FillSA((struct sockaddr*)&extip, pcp_msg_info->ext_ip, - eport); - - inet_satop((struct sockaddr*)&peerip, peerip_s, sizeof(peerip_s)); - inet_satop((struct sockaddr*)&extip, extip_s, sizeof(extip_s)); - - /* check if connection with given peer exists, if it was */ - /* already established use this external port */ - if (get_nat_ext_addr( (struct sockaddr*)&intip, (struct sockaddr*)&peerip, - proto, (struct sockaddr*)&ret_extip) == 1) { - if (ret_extip.ss_family == AF_INET) { - struct sockaddr_in* ret_ext4 = (struct sockaddr_in*)&ret_extip; - uint16_t ret_eport = ntohs(ret_ext4->sin_port); - eport = ret_eport; - } else if (ret_extip.ss_family == AF_INET6) { - struct sockaddr_in6* ret_ext6 = (struct sockaddr_in6*)&ret_extip; - uint16_t ret_eport = ntohs(ret_ext6->sin6_port); - eport = ret_eport; - } else { - return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - } - } - /* Create Peer Mapping */ - if (eport == 0) { - eport = pcp_msg_info->int_port; - } - -#ifdef PCP_FLOWP - if (pcp_msg_info->flowp_present && pcp_msg_info->dscp_up) { - if (add_peer_dscp_rule2(ext_if_name, peerip_s, - pcp_msg_info->peer_port, pcp_msg_info->dscp_up, - pcp_msg_info->mapped_str, pcp_msg_info->int_port, - proto, pcp_msg_info->desc, timestamp) < 0 ) { - syslog(LOG_ERR, "PCP: failed to add flowp upstream mapping %s:%hu->%s:%hu '%s'", - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - peerip_s, - pcp_msg_info->peer_port, - pcp_msg_info->desc); - return PCP_ERR_NO_RESOURCES; - } - } - - if (pcp_msg_info->flowp_present && pcp_msg_info->dscp_down) { - if (add_peer_dscp_rule2(ext_if_name, pcp_msg_info->mapped_str, - pcp_msg_info->int_port, pcp_msg_info->dscp_down, - peerip_s, pcp_msg_info->peer_port, proto, pcp_msg_info->desc, timestamp) - < 0 ) { - syslog(LOG_ERR, "PCP: failed to add flowp downstream mapping %s:%hu->%s:%hu '%s'", - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - peerip_s, - pcp_msg_info->peer_port, - pcp_msg_info->desc); - pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; - return PCP_ERR_NO_RESOURCES; - } - } -#endif - - r = add_peer_redirect_rule2(ext_if_name, - peerip_s, - pcp_msg_info->peer_port, - extip_s, - eport, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->protocol, - pcp_msg_info->desc, - timestamp); - if (r < 0) - return PCP_ERR_NO_RESOURCES; - pcp_msg_info->ext_port = eport; - return PCP_SUCCESS; -} - -static void CreatePCPPeer(pcp_info_t *pcp_msg_info) -{ - char peerip_s[INET6_ADDRSTRLEN]; - int r = -1; - - if (!inet_n46top(pcp_msg_info->peer_ip, peerip_s, sizeof(peerip_s))) { - syslog(LOG_ERR, "inet_n46top(peer_ip): %m"); - return; - } - - if (pcp_msg_info->is_fw) { -#if 0 - /* Someday, something like this is available.. and we're ready! */ -#ifdef ENABLE_UPNPPINHOLE - pcp_msg_info->ext_port = pcp_msg_info->int_port; - r = upnp_add_outbound_pinhole(peerip_s, - pcp_msg_info->peer_port, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->protocol, - pcp_msg_info->desc, - pcp_msg_info->lifetime, NULL); -#endif /* ENABLE_UPNPPINHOLE */ -#else - r = PCP_ERR_UNSUPP_OPCODE; -#endif /* 0 */ - } else { - r = CreatePCPPeer_NAT(pcp_msg_info); - } - /* TODO: add upnp function for PI */ - pcp_msg_info->result_code = r; - syslog(r == PCP_SUCCESS ? LOG_INFO : LOG_ERR, - "PCP PEER: %s peer mapping %s %s:%hu(%hu)->%s:%hu '%s'", - r == PCP_SUCCESS ? "added" : "failed to add", - (pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP", - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->ext_port, - peerip_s, - pcp_msg_info->peer_port, - pcp_msg_info->desc); -} - -static void DeletePCPPeer(pcp_info_t *pcp_msg_info) -{ - uint16_t iport = pcp_msg_info->int_port; /* private port */ - uint16_t rport = pcp_msg_info->peer_port; /* private port */ - uint8_t proto = pcp_msg_info->protocol; - char rhost[INET6_ADDRSTRLEN]; - int r = -1; - - /* remove requested mappings for this client */ - int index = 0; - unsigned short eport2, iport2, rport2; - char iaddr2[INET6_ADDRSTRLEN], rhost2[INET6_ADDRSTRLEN]; - int proto2; - char desc[64]; - unsigned int timestamp; -#if 0 - int uid; -#endif /* 0 */ - - if (pcp_msg_info->is_fw) { - pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; - return; - } - - inet_n46top((struct in6_addr*)pcp_msg_info->peer_ip, rhost, sizeof(rhost)); - - for (index = 0 ; - (!pcp_msg_info->is_fw && - get_peer_rule_by_index(index, 0, - &eport2, iaddr2, sizeof(iaddr2), - &iport2, &proto2, - desc, sizeof(desc), - rhost2, sizeof(rhost2), &rport2, - ×tamp, 0, 0) >= 0) -#if 0 - /* Some day if outbound pinholes are supported.. */ - || - (pcp_msg_info->is_fw && - (uid=upnp_get_pinhole_uid_by_index(index))>=0 && - upnp_get_pinhole_info((unsigned short)uid, - rhost2, sizeof(rhost2), &rport2, - iaddr2, sizeof(iaddr2), &iport2, - &proto2, desc, sizeof(desc), - ×tamp, NULL) >= 0) -#endif /* 0 */ - ; - index++) - if((0 == strcmp(iaddr2, pcp_msg_info->mapped_str)) - && (0 == strcmp(rhost2, rhost)) - && (proto2==proto) - && 0 == strcmp(desc, pcp_msg_info->desc) - && (iport2==iport) && (rport2==rport)) { - if (!pcp_msg_info->is_fw) - r = _upnp_delete_redir(eport2, proto2); -#if 0 - else - r = upnp_delete_outboundpinhole(uid); -#endif /* 0 */ - if(r<0) { - syslog(LOG_ERR, "PCP PEER: failed to remove peer mapping"); - } else { - syslog(LOG_INFO, "PCP PEER: %s port %hu peer mapping removed", - proto2==IPPROTO_TCP?"TCP":"UDP", eport2); - } - return; - } - if (r==-1) { - syslog(LOG_ERR, "PCP PEER: Failed to find PCP mapping internal port %hu, protocol %s", - iport, (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); - pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; - } -} -#endif /* PCP_PEER */ - -static int CreatePCPMap_NAT(pcp_info_t *pcp_msg_info) -{ - int r = 0; - char iaddr_old[INET6_ADDRSTRLEN]; - uint16_t iport_old, eport_first = 0; - int any_eport_allowed = 0; - unsigned int timestamp = upnp_time() + pcp_msg_info->lifetime; - - if (pcp_msg_info->ext_port == 0) { - pcp_msg_info->ext_port = pcp_msg_info->int_port; - } - - /* TODO: Support non-TCP/UDP */ - if (pcp_msg_info->ext_port == 0) { - return PCP_ERR_MALFORMED_REQUEST; - } - - do { - if (eport_first == 0) { /* first time in loop */ - eport_first = pcp_msg_info->ext_port; - } else if (pcp_msg_info->ext_port == eport_first) { /* no eport available */ - /* all eports rejected by permissions? */ - if (any_eport_allowed == 0) - return PCP_ERR_NOT_AUTHORIZED; - /* at least one eport allowed (but none available) */ - return PCP_ERR_NO_RESOURCES; - } - if ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->mapped_ip) && - (!check_upnp_rule_against_permissions(upnppermlist, - num_upnpperm, pcp_msg_info->ext_port, - ((struct in_addr*)pcp_msg_info->mapped_ip->s6_addr)[3], - pcp_msg_info->int_port)))) { - if (pcp_msg_info->pfailure_present) { - return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - } - pcp_msg_info->ext_port++; - if (pcp_msg_info->ext_port == 0) { /* skip port zero */ - pcp_msg_info->ext_port++; - } - continue; - } - any_eport_allowed = 1; -#ifdef CHECK_PORTINUSE - if (port_in_use(ext_if_name, pcp_msg_info->ext_port, pcp_msg_info->protocol, - pcp_msg_info->mapped_str, pcp_msg_info->int_port) > 0) { - syslog(LOG_INFO, "port %hu protocol %s already in use", - pcp_msg_info->ext_port, - (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp"); - pcp_msg_info->ext_port++; - if (pcp_msg_info->ext_port == 0) { /* skip port zero */ - pcp_msg_info->ext_port++; - } - continue; - } -#endif - r = get_redirect_rule(ext_if_name, - pcp_msg_info->ext_port, - pcp_msg_info->protocol, - iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0, - NULL/*×tamp*/, 0, 0); - - if(r==0) { - if((strcmp(pcp_msg_info->mapped_str, iaddr_old)!=0) - || (pcp_msg_info->int_port != iport_old)) { - /* redirection already existing */ - if (pcp_msg_info->pfailure_present) { - return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - } - } else { - syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", - pcp_msg_info->ext_port, (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp", - iaddr_old, iport_old); - /* remove and then add again */ - if (_upnp_delete_redir(pcp_msg_info->ext_port, - pcp_msg_info->protocol)==0) { - break; - } else if (pcp_msg_info->pfailure_present) { - return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - } - } - pcp_msg_info->ext_port++; - if (pcp_msg_info->ext_port == 0) { /* skip port zero */ - pcp_msg_info->ext_port++; - } - } - } while (r==0); - - r = upnp_redirect_internal(NULL, - pcp_msg_info->ext_port, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->protocol, - pcp_msg_info->desc, - timestamp); - if (r < 0) - return PCP_ERR_NO_RESOURCES; - return PCP_SUCCESS; -} - -static int CreatePCPMap_FW(pcp_info_t *pcp_msg_info) -{ -#ifdef ENABLE_UPNPPINHOLE - int uid; - int r; - /* first check if pinhole already exists */ - uid = upnp_find_inboundpinhole(NULL, 0, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->protocol, - NULL, 0, /* desc */ - NULL /* lifetime */); - if(uid >= 0) { - /* pinhole already exists, updating */ - syslog(LOG_INFO, "updating pinhole to %s:%hu %s", - pcp_msg_info->mapped_str, pcp_msg_info->int_port, - (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); - r = upnp_update_inboundpinhole((unsigned short)uid, pcp_msg_info->lifetime); - return r >= 0 ? PCP_SUCCESS : PCP_ERR_NO_RESOURCES; - } else { - r = upnp_add_inboundpinhole(NULL, 0, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->protocol, - pcp_msg_info->desc, - pcp_msg_info->lifetime, - &uid); - if (r < 0) - return PCP_ERR_NO_RESOURCES; - pcp_msg_info->ext_port = pcp_msg_info->int_port; - return PCP_SUCCESS; - } -#else - UNUSED(pcp_msg_info); - return PCP_ERR_NO_RESOURCES; -#endif /* ENABLE_UPNPPINHOLE */ -} - - -/* internal external PCP remote peer actual remote peer - * -------- ------- --------------- ------------------ - * IPv4 firewall IPv4 IPv4 IPv4 IPv4 - * IPv6 firewall IPv6 IPv6 IPv6 IPv6 - * NAT44 IPv4 IPv4 IPv4 IPv4 - * NAT46 IPv4 IPv6 IPv4 IPv6 - * NAT64 IPv6 IPv4 IPv6 IPv4 - * NPTv6 IPv6 IPv6 IPv6 IPv6 - * - * Address Families with MAP and PEER - * - * The 'internal' address is implicitly the same as the source IP - * address of the PCP request, except when the THIRD_PARTY option is - * used. - * - * The 'external' address is the Suggested External Address field of the - * MAP or PEER request, and its address family is usually the same as - * the 'internal' address family, except when technologies like NAT64 - * are used. - * - * The 'remote peer' address is the remote peer IP address of the PEER - * request or the FILTER option of the MAP request, and is always the - * same address family as the 'internal' address, even when NAT64 is - * used. In NAT64, the IPv6 PCP client is not necessarily aware of the - * NAT64 or aware of the actual IPv4 address of the remote peer, so it - * expresses the IPv6 address from its perspective. */ - -/* TODO: Support more than basic NAT44 / IPv6 firewall cases. */ -static void CreatePCPMap(pcp_info_t *pcp_msg_info) -{ - int r; - - if (pcp_msg_info->is_fw) - r = CreatePCPMap_FW(pcp_msg_info); - else - r = CreatePCPMap_NAT(pcp_msg_info); - pcp_msg_info->result_code = r; - syslog(r == PCP_SUCCESS ? LOG_INFO : LOG_ERR, - "PCP MAP: %s mapping %s %hu->%s:%hu '%s'", - r == PCP_SUCCESS ? "added" : "failed to add", - (pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP", - pcp_msg_info->ext_port, - pcp_msg_info->mapped_str, - pcp_msg_info->int_port, - pcp_msg_info->desc); -} - -static void DeletePCPMap(pcp_info_t *pcp_msg_info) -{ - uint16_t iport = pcp_msg_info->int_port; /* private port */ - uint8_t proto = pcp_msg_info->protocol; - int r=-1; - /* remove the mapping */ - /* remove all the mappings for this client */ - int index; - unsigned short eport2, iport2; - char iaddr2[INET6_ADDRSTRLEN]; - int proto2; - char desc[64]; - unsigned int timestamp; -#ifdef ENABLE_UPNPPINHOLE - int uid = -1; -#endif /* ENABLE_UPNPPINHOLE */ - - /* iterate through all rules and delete the requested ones */ - for (index = 0 ; - (!pcp_msg_info->is_fw && - get_redirect_rule_by_index(index, 0, - &eport2, iaddr2, sizeof(iaddr2), - &iport2, &proto2, - desc, sizeof(desc), - 0, 0, ×tamp, 0, 0) >= 0) -#ifdef ENABLE_UPNPPINHOLE - || - (pcp_msg_info->is_fw && - (uid=upnp_get_pinhole_uid_by_index(index))>=0 && - upnp_get_pinhole_info((unsigned short)uid, - NULL, 0, NULL, - iaddr2, sizeof(iaddr2), &iport2, - &proto2, desc, sizeof(desc), - ×tamp, NULL) >= 0) -#endif /* ENABLE_UPNPPINHOLE */ - ; - index++) - if(0 == strcmp(iaddr2, pcp_msg_info->mapped_str) - && (proto2==proto) - && ((iport2==iport) || (iport==0))) { - if(0 != strcmp(desc, pcp_msg_info->desc)) { - /* nonce does not match */ - pcp_msg_info->result_code = PCP_ERR_NOT_AUTHORIZED; - syslog(LOG_ERR, "Unauthorized to remove PCP mapping internal port %hu, protocol %s", - iport, (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); - return; - } else if (!pcp_msg_info->is_fw) { - r = _upnp_delete_redir(eport2, proto2); - } else { -#ifdef ENABLE_UPNPPINHOLE - r = upnp_delete_inboundpinhole(uid); -#endif /* ENABLE_UPNPPINHOLE */ - } - break; - } - if (r >= 0) { - syslog(LOG_INFO, "PCP: %s port %hu mapping removed", - proto2==IPPROTO_TCP?"TCP":"UDP", eport2); - } else { - syslog(LOG_ERR, "Failed to remove PCP mapping internal port %hu, protocol %s", - iport, (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); - pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; - } -} - -static int ValidatePCPMsg(pcp_info_t *pcp_msg_info) -{ - if (pcp_msg_info->result_code) { - return 0; - } - - /* RFC 6887, section 8.2: MUST return address mismatch if NAT - * in middle. */ - if (memcmp(pcp_msg_info->int_ip, - &pcp_msg_info->sender_ip, - sizeof(pcp_msg_info->sender_ip)) != 0) { - pcp_msg_info->result_code = PCP_ERR_ADDRESS_MISMATCH; - return 0; - } - - if (pcp_msg_info->thirdp_ip) { - if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) { - pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION; - return 0; - } - - /* RFC687, section 13.1 - if sender ip == THIRD_PARTY, - * it's an error. */ - if (memcmp(pcp_msg_info->thirdp_ip, - &pcp_msg_info->sender_ip, - sizeof(pcp_msg_info->sender_ip)) == 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 0; - } - } - - /* Produce mapped_str for future use. */ - if (!inet_n46top(pcp_msg_info->mapped_ip, pcp_msg_info->mapped_str, - sizeof(pcp_msg_info->mapped_str))) { - syslog(LOG_ERR, "inet_ntop(pcpserver): %m"); - return 0; - } - - /* protocol zero means 'all protocols' : internal port MUST be zero */ - if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port != 0) { - syslog(LOG_ERR, "PCP %s: Protocol was ZERO, but internal port " - "has non-ZERO value.", getPCPOpCodeStr(pcp_msg_info->opcode)); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 0; - } - - if (pcp_msg_info->pfailure_present) { - if ( (IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip) || - ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->ext_ip)) && - (((uint32_t*)pcp_msg_info->ext_ip->s6_addr)[3] == 0))) && - (pcp_msg_info->ext_port == 0) - ) - { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return 0; - } - } - - if (CheckExternalAddress(pcp_msg_info)) { - return 0; - } - - /* Fill in the desc that describes uniquely what flow we're - * dealing with (same code used in both create + delete of - * MAP/PEER) */ - switch (pcp_msg_info->opcode) { - case PCP_OPCODE_MAP: - case PCP_OPCODE_PEER: - snprintf(pcp_msg_info->desc, sizeof(pcp_msg_info->desc), - "PCP %s %08x%08x%08x", - getPCPOpCodeStr(pcp_msg_info->opcode), - pcp_msg_info->nonce[0], - pcp_msg_info->nonce[1], pcp_msg_info->nonce[2]); - break; - } - return 1; -} - -/* - * return value indicates whether the request is valid or not. - * Based on the return value simple response can be formed. - */ -static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) -{ - int remainingSize; - - /* start with PCP_SUCCESS as result code, - * if everything is OK value will be unchanged */ - pcp_msg_info->result_code = PCP_SUCCESS; - - remainingSize = req_size; - - /* discard request that exceeds maximal length, - or that is shorter than PCP_MIN_LEN (=24) - or that is not the multiple of 4 */ - if (req_size < 3) - return 0; /* ignore msg */ - - if (req_size < PCP_MIN_LEN) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 1; /* send response */ - } - - if ( (req_size > PCP_MAX_LEN) || ( (req_size & 3) != 0)) { - syslog(LOG_ERR, "PCP: Size of PCP packet(%d) is larger than %d bytes or " - "the size is not multiple of 4.\n", req_size, PCP_MAX_LEN); - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 1; /* send response */ - } - - /* first parse request header */ - if (parseCommonRequestHeader(req, pcp_msg_info) ) { - return 1; - } - - remainingSize -= PCP_COMMON_REQUEST_SIZE; - req += PCP_COMMON_REQUEST_SIZE; - - if (pcp_msg_info->version == 1) { - /* legacy PCP version 1 support */ - switch (pcp_msg_info->opcode) { - case PCP_OPCODE_MAP: - - remainingSize -= PCP_MAP_V1_SIZE; - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return pcp_msg_info->result_code; - } - -#ifdef DEBUG - printMAPOpcodeVersion1(req); -#endif /* DEBUG */ - parsePCPMAP_version1(req, pcp_msg_info); - - req += PCP_MAP_V1_SIZE; - - parsePCPOptions(req, remainingSize, pcp_msg_info); - if (ValidatePCPMsg(pcp_msg_info)) { - if (pcp_msg_info->lifetime == 0) { - DeletePCPMap(pcp_msg_info); - } else { - CreatePCPMap(pcp_msg_info); - } - } else { - syslog(LOG_ERR, "PCP: Invalid PCP v1 MAP message."); - return pcp_msg_info->result_code; - } - break; - -#ifdef PCP_PEER - case PCP_OPCODE_PEER: - - remainingSize -= PCP_PEER_V1_SIZE; - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return pcp_msg_info->result_code; - } - -#ifdef DEBUG - printPEEROpcodeVersion1(req); -#endif /* DEBUG */ - parsePCPPEER_version1(req, pcp_msg_info); - - req += PCP_PEER_V1_SIZE; - - parsePCPOptions(req, remainingSize, pcp_msg_info); - - if (ValidatePCPMsg(pcp_msg_info)) { - if (pcp_msg_info->lifetime == 0) { - DeletePCPPeer(pcp_msg_info); - } else { - CreatePCPPeer(pcp_msg_info); - } - } else { - syslog(LOG_ERR, "PCP: Invalid PCP v1 PEER message."); - return pcp_msg_info->result_code; - } - - - break; -#endif /* PCP_PEER */ - default: - pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; - break; - } - - } else if (pcp_msg_info->version == 2) { - /* RFC 6887 PCP support - * http://tools.ietf.org/html/rfc6887 */ - switch (pcp_msg_info->opcode) { - case PCP_OPCODE_ANNOUNCE: - /* should check PCP Client's IP Address in request */ - /* see http://tools.ietf.org/html/rfc6887#section-14.1 */ - break; - case PCP_OPCODE_MAP: - - remainingSize -= PCP_MAP_V2_SIZE; - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return pcp_msg_info->result_code; - } - -#ifdef DEBUG - printMAPOpcodeVersion2(req); -#endif /* DEBUG */ - parsePCPMAP_version2(req, pcp_msg_info); - req += PCP_MAP_V2_SIZE; - - parsePCPOptions(req, remainingSize, pcp_msg_info); - - if (ValidatePCPMsg(pcp_msg_info)) { - if (pcp_msg_info->lifetime == 0) { - DeletePCPMap(pcp_msg_info); - } else { - CreatePCPMap(pcp_msg_info); - } - } else { - syslog(LOG_ERR, "PCP: Invalid PCP v2 MAP message."); - return pcp_msg_info->result_code; - } - - - break; - -#ifdef PCP_PEER - case PCP_OPCODE_PEER: - - remainingSize -= PCP_PEER_V2_SIZE; - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return pcp_msg_info->result_code; - } - -#ifdef DEBUG - printPEEROpcodeVersion2(req); -#endif /* DEBUG */ - parsePCPPEER_version2(req, pcp_msg_info); - req += PCP_PEER_V2_SIZE; - - if (pcp_msg_info->result_code != 0) { - return pcp_msg_info->result_code; - } - - parsePCPOptions(req, remainingSize, pcp_msg_info); - - if (ValidatePCPMsg(pcp_msg_info)) { - if (pcp_msg_info->lifetime == 0) { - DeletePCPPeer(pcp_msg_info); - } else { - CreatePCPPeer(pcp_msg_info); - } - } else { - syslog(LOG_ERR, "PCP: Invalid PCP v2 PEER message."); - } - - break; -#endif /* PCP_PEER */ - -#ifdef PCP_SADSCP - case PCP_OPCODE_SADSCP: - remainingSize -= PCP_SADSCP_REQ_SIZE; - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return pcp_msg_info->result_code; - } - - remainingSize -= ((uint8_t *)req)[13]; /* app_name_length */ - if (remainingSize < 0) { - pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; - return pcp_msg_info->result_code; - } - -#ifdef DEBUG - printSADSCPOpcode(req); -#endif - parseSADSCP(req, pcp_msg_info); - req += PCP_SADSCP_REQ_SIZE; - if (pcp_msg_info->result_code != 0) { - return pcp_msg_info->result_code; - } - req += pcp_msg_info->app_name_len; - - get_dscp_value(pcp_msg_info); - - - break; -#endif - default: - pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; - break; - } - } else { - pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION; - return pcp_msg_info->result_code; - } - return 1; -} - - -static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) -{ - response[2] = 0; /* reserved */ - memset(response + 12, 0, 12); /* reserved */ - if (pcp_msg_info->result_code == PCP_ERR_UNSUPP_VERSION ) { - /* highest supported version */ - response[0] = this_server_info.server_version; - } else { - response[0] = pcp_msg_info->version; - } - - response[1] |= 0x80; /* r_opcode */ - response[3] = pcp_msg_info->result_code; - if(epoch_origin == 0) { - epoch_origin = startup_time; - } - WRITENU32(response + 8, upnp_time() - epoch_origin); /* epochtime */ - switch (pcp_msg_info->result_code) { - /*long lifetime errors*/ - case PCP_ERR_UNSUPP_VERSION: - case PCP_ERR_NOT_AUTHORIZED: - case PCP_ERR_MALFORMED_REQUEST: - case PCP_ERR_UNSUPP_OPCODE: - case PCP_ERR_UNSUPP_OPTION: - case PCP_ERR_MALFORMED_OPTION: - case PCP_ERR_UNSUPP_PROTOCOL: - case PCP_ERR_ADDRESS_MISMATCH: - case PCP_ERR_CANNOT_PROVIDE_EXTERNAL: - case PCP_ERR_EXCESSIVE_REMOTE_PEERS: - WRITENU32(response + 4, 0); /* lifetime */ - break; - - case PCP_ERR_NETWORK_FAILURE: - case PCP_ERR_NO_RESOURCES: - case PCP_ERR_USER_EX_QUOTA: - WRITENU32(response + 4, 30); /* lifetime */ - break; - - case PCP_SUCCESS: - default: - WRITENU32(response + 4, pcp_msg_info->lifetime); /* lifetime */ - break; - } - - if (response[1] == 0x81) { /* MAP response */ - if (response[0] == 1) { /* version */ - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port); - copyIPv6IfDifferent(response + PCP_COMMON_RESPONSE_SIZE + 8, - pcp_msg_info->ext_ip); - } - else if (response[0] == 2) { - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port); - copyIPv6IfDifferent(response + PCP_COMMON_RESPONSE_SIZE + 20, - pcp_msg_info->ext_ip); - } - } -#ifdef PCP_PEER - else if (response[1] == 0x82) { /* PEER response */ - if (response[0] == 1) { - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 24, pcp_msg_info->peer_port); - copyIPv6IfDifferent(response + PCP_COMMON_RESPONSE_SIZE + 8, - pcp_msg_info->ext_ip); - } - else if (response[0] == 2) { - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port); - WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 36, pcp_msg_info->peer_port); - copyIPv6IfDifferent(response + PCP_COMMON_RESPONSE_SIZE + 20, - pcp_msg_info->ext_ip); - } - } -#endif /* PCP_PEER */ - -#ifdef PCP_SADSCP - else if (response[1] == 0x83) { /*SADSCP response*/ - response[PCP_COMMON_RESPONSE_SIZE + 12] - = ((pcp_msg_info->matched_name<<7) & ~(1<<6)) | - (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK); - memset(response + PCP_COMMON_RESPONSE_SIZE + 13, 0, 3); - } -#endif /* PCP_SADSCP */ -} - -int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, - const struct sockaddr *senderaddr, - const struct sockaddr_in6 *receiveraddr) -{ - pcp_info_t pcp_msg_info; - struct lan_addr_s * lan_addr; - char addr_str[64]; - - memset(&pcp_msg_info, 0, sizeof(pcp_info_t)); - - if(senderaddr->sa_family == AF_INET) { - const struct sockaddr_in * senderaddr_v4 = - (const struct sockaddr_in *)senderaddr; - pcp_msg_info.sender_ip.s6_addr[11] = 0xff; - pcp_msg_info.sender_ip.s6_addr[10] = 0xff; - memcpy(pcp_msg_info.sender_ip.s6_addr+12, - &senderaddr_v4->sin_addr, 4); - } else if(senderaddr->sa_family == AF_INET6) { - const struct sockaddr_in6 * senderaddr_v6 = - (const struct sockaddr_in6 *)senderaddr; - pcp_msg_info.sender_ip = senderaddr_v6->sin6_addr; - } else { - syslog(LOG_WARNING, "unknown PCP packet sender address family %d", - senderaddr->sa_family); - return 0; - } - - if(sockaddr_to_string(senderaddr, addr_str, sizeof(addr_str))) - syslog(LOG_DEBUG, "PCP request received from %s %dbytes", - addr_str, len); - - if(buff[1] & 128) { - /* discarding PCP responses silently */ - return 0; - } - - /* If we're in allow third party-mode, we probably don't care - * about locality either. Let's hope firewall is ok. */ - if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) { - lan_addr = get_lan_for_peer(senderaddr); - if(lan_addr == NULL) { - syslog(LOG_WARNING, "PCP packet sender %s not from a LAN, ignoring", - addr_str); - return 0; - } - } - - if (processPCPRequest(buff, len, &pcp_msg_info) ) { - - createPCPResponse(buff, &pcp_msg_info); - - if(len < PCP_MIN_LEN) - len = PCP_MIN_LEN; - else - len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ - len = sendto_or_schedule2(s, buff, len, 0, senderaddr, - (senderaddr->sa_family == AF_INET) ? - sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6), - receiveraddr); - if( len < 0 ) { - syslog(LOG_ERR, "sendto(pcpserver): %m"); - } - } - - return 0; -} - -#ifdef ENABLE_IPV6 -int OpenAndConfPCPv6Socket(void) -{ - int s; - int i = 1; - struct sockaddr_in6 addr; - s = socket(PF_INET6, SOCK_DGRAM, 0/*IPPROTO_UDP*/); - if(s < 0) { - syslog(LOG_ERR, "%s: socket(): %m", "OpenAndConfPCPv6Socket"); - return -1; - } - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m", - "OpenAndConfPCPv6Socket"); - } -#ifdef IPV6_V6ONLY - /* force IPV6 only for IPV6 socket. - * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */ - if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(IPV6_V6ONLY): %m", - "OpenAndConfPCPv6Socket"); - } -#endif -#ifdef IPV6_RECVPKTINFO - /* see RFC3542 */ - if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i, sizeof(i)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(IPV6_RECVPKTINFO): %m", - "OpenAndConfPCPv6Socket"); - } -#endif - if(!set_non_blocking(s)) { - syslog(LOG_WARNING, "%s: set_non_blocking(): %m", - "OpenAndConfPCPv6Socket"); - } - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons(NATPMP_PORT); - addr.sin6_addr = ipv6_bind_addr; - if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - syslog(LOG_ERR, "%s: bind(): %m", "OpenAndConfPCPv6Socket"); - close(s); - return -1; - } - return s; -} -#endif /*ENABLE_IPV6*/ - -#ifdef ENABLE_IPV6 -static void PCPSendUnsolicitedAnnounce(int * sockets, int n_sockets, int socket6) -#else /* IPv4 only */ -static void PCPSendUnsolicitedAnnounce(int * sockets, int n_sockets) -#endif -{ - int i; - unsigned char buff[PCP_MIN_LEN]; - pcp_info_t info; - ssize_t len; - struct sockaddr_in addr; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 addr6; -#endif /* ENABLE_IPV6 */ - /* this is an Unsolicited ANNOUNCE response */ - - info.version = this_server_info.server_version; - info.opcode = PCP_OPCODE_ANNOUNCE; - info.result_code = PCP_SUCCESS; - info.lifetime = 0; - createPCPResponse(buff, &info); - /* Multicast PCP restart announcements are sent to - * 224.0.0.1:5350 and/or [ff02::1]:5350 */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("224.0.0.1"); - addr.sin_port = htons(5350); - for(i = 0; i < n_sockets; i++) { - len = sendto_or_schedule(sockets[i], buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - if( len < 0 ) { - syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce() sendto(): %m"); - } - } -#ifdef ENABLE_IPV6 - memset(&addr6, 0, sizeof(struct sockaddr_in6)); - addr6.sin6_family = AF_INET6; - inet_pton(AF_INET6, "FF02::1", &(addr6.sin6_addr)); - addr6.sin6_port = htons(5350); - len = sendto_or_schedule(socket6, buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)); - if( len < 0 ) { - syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce() IPv6 sendto(): %m"); - } -#endif /* ENABLE_IPV6 */ -} - -#ifdef ENABLE_IPV6 -void PCPPublicAddressChanged(int * sockets, int n_sockets, int socket6) -#else /* IPv4 only */ -void PCPPublicAddressChanged(int * sockets, int n_sockets) -#endif -{ - /* according to RFC 6887 8.5 : - * if the external IP address(es) of the NAT (controlled by - * the PCP server) changes, the Epoch time MUST be reset. */ - epoch_origin = upnp_time(); -#ifdef ENABLE_IPV6 - PCPSendUnsolicitedAnnounce(sockets, n_sockets, socket6); -#else /* IPv4 Only */ - PCPSendUnsolicitedAnnounce(sockets, n_sockets); -#endif -} -#endif /*ENABLE_PCP*/ diff --git a/src/contrib/miniupnp/miniupnpd/pcpserver.h b/src/contrib/miniupnp/miniupnpd/pcpserver.h deleted file mode 100644 index 3357e4f..0000000 --- a/src/contrib/miniupnp/miniupnpd/pcpserver.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id: pcpserver.h,v 1.3 2014/03/24 10:49:46 nanard Exp $ */ -/* MiniUPnP project - * Website : http://miniupnp.free.fr/ - * Author : Peter Tatrai - -Copyright (c) 2013 by Cisco Systems, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PCPSERVER_H_INCLUDED -#define PCPSERVER_H_INCLUDED - -#define PCP_MIN_LEN 24 -#define PCP_MAX_LEN 1100 - -struct sockaddr; - -/* - * receiveraddr is only used for IPV6 - * - * returns 0 upon success 1 otherwise - */ -int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, - const struct sockaddr *senderaddr, - const struct sockaddr_in6 *receiveraddr); - -/* - * returns the socket - */ -int OpenAndConfPCPv6Socket(void); - - -/* - * To be called when Public IP address changed (IPv4) - */ -#ifdef ENABLE_IPV6 -void PCPPublicAddressChanged(int * sockets, int n_sockets, int socket6); -#else /* IPV4 Only */ -void PCPPublicAddressChanged(int * sockets, int n_sockets); -#endif - -#endif /* PCPSERVER_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/pf/Makefile b/src/contrib/miniupnp/miniupnpd/pf/Makefile deleted file mode 100644 index f94c074..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# $Id: Makefile,v 1.4 2012/04/18 20:45:33 nanard Exp $ -# made for GNU Make (and BSD make) -CFLAGS = -Wall -g -DTEST -CFLAGS += -Wextra -EXECUTABLES = testobsdrdr testpfpinhole - -all: $(EXECUTABLES) - -clean: - rm -f *.o $(EXECUTABLES) - -testobsdrdr: testobsdrdr.o obsdrdr.o - $(CC) $(CFLAGS) -o $@ $> - -testpfpinhole: testpfpinhole.o obsdrdr.o pfpinhole.o - $(CC) $(CFLAGS) -o $@ $> - -obsdrdr.o: obsdrdr.c obsdrdr.h - -pfpinhole.o: pfpinhole.c pfpinhole.h - -testobsdrdr.o: testobsdrdr.c obsdrdr.h - -testpfpinhole.o: testpfpinhole.c pfpinhole.h - diff --git a/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.c b/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.c deleted file mode 100644 index 0b00ad9..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* $Id: obsdrdr.c,v 1.88 2018/04/12 09:27:53 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -/* - * pf rules created (with ext_if = xl1) - * - OpenBSD up to version 4.6 : - * rdr pass on xl1 inet proto udp from any to any port = 54321 \ - * keep state label "test label" -> 192.168.0.42 port 12345 - * or a rdr rule + a pass rule : - * rdr quick on xl1 inet proto udp from any to any port = 54321 \ - * keep state label "test label" -> 192.168.0.42 port 12345 - * pass in quick on xl1 inet proto udp from any to 192.168.0.42 port = 12345 \ - * flags S/SA keep state label "test label" - * - * - OpenBSD starting from version 4.7 - * match in on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.42 port 12345 - * or - * pass in quick on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.42 port 12345 - * - * - * - * Macros/#defines : - * - PF_ENABLE_FILTER_RULES - * If set, two rules are created : rdr + pass. Else a rdr/pass rule - * is created. - * - USE_IFNAME_IN_RULES - * If set the interface name is set in the rule. - * - PFRULE_INOUT_COUNTS - * Must be set with OpenBSD version 3.8 and up. - * - PFRULE_HAS_RTABLEID - * Must be set with OpenBSD version 4.0 and up. - * - PF_NEWSSTYLE - * Must be set with OpenBSD version 4.7 and up. - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef __DragonFly__ -#include -#else -#ifdef __APPLE__ -#define PRIVATE 1 -#endif -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "../macros.h" -#include "../config.h" -#include "obsdrdr.h" -#include "../upnpglobalvars.h" - -#ifndef USE_PF -#error "USE_PF macro is undefined, check consistency between config.h and Makefile" -#else - -/* list to keep timestamps for port mappings having a lease duration */ -struct timestamp_entry { - struct timestamp_entry * next; - unsigned int timestamp; - unsigned short eport; - short protocol; -}; - -static struct timestamp_entry * timestamp_list = NULL; - -static unsigned int -get_timestamp(unsigned short eport, int proto) -{ - struct timestamp_entry * e; - e = timestamp_list; - while(e) { - if(e->eport == eport && e->protocol == (short)proto) - return e->timestamp; - e = e->next; - } - return 0; -} - -static void -remove_timestamp_entry(unsigned short eport, int proto) -{ - struct timestamp_entry * e; - struct timestamp_entry * * p; - p = ×tamp_list; - e = *p; - while(e) { - if(e->eport == eport && e->protocol == (short)proto) { - /* remove the entry */ - *p = e->next; - free(e); - return; - } - p = &(e->next); - e = *p; - } -} - -static void -add_timestamp_entry(unsigned short eport, int proto, unsigned timestamp) -{ - struct timestamp_entry * tmp; - tmp = malloc(sizeof(struct timestamp_entry)); - if(tmp) - { - tmp->next = timestamp_list; - tmp->timestamp = timestamp; - tmp->eport = eport; - tmp->protocol = (short)proto; - timestamp_list = tmp; - } - else - { - syslog(LOG_ERR, "add_timestamp_entry() malloc(%lu) error", - sizeof(struct timestamp_entry)); - } -} - -/* /dev/pf when opened */ -int dev = -1; - -/* shutdown_redirect() : - * close the /dev/pf device */ -void -shutdown_redirect(void) -{ - if(close(dev)<0) - syslog(LOG_ERR, "close(\"/dev/pf\"): %m"); - dev = -1; -} - -/* open the device */ -int -init_redirect(void) -{ - struct pf_status status; - if(dev>=0) - shutdown_redirect(); - dev = open("/dev/pf", O_RDWR); - if(dev<0) { - syslog(LOG_ERR, "open(\"/dev/pf\"): %m"); - return -1; - } - if(ioctl(dev, DIOCGETSTATUS, &status)<0) { - syslog(LOG_ERR, "DIOCGETSTATUS: %m"); - return -1; - } - if(!status.running) { - syslog(LOG_ERR, "pf is disabled"); - return -1; - } - return 0; -} - -#if TEST -/* for debug */ -int -clear_redirect_rules(void) -{ - struct pfioc_trans io; - struct pfioc_trans_e ioe; - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&ioe, 0, sizeof(ioe)); - io.size = 1; - io.esize = sizeof(ioe); - io.array = &ioe; -#ifndef PF_NEWSTYLE - ioe.rs_num = PF_RULESET_RDR; -#else - ioe.type = PF_TRANS_RULESET; -#endif - strlcpy(ioe.anchor, anchor_name, MAXPATHLEN); - if(ioctl(dev, DIOCXBEGIN, &io) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m"); - goto error; - } - if(ioctl(dev, DIOCXCOMMIT, &io) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m"); - goto error; - } - return 0; -error: - return -1; -} - -int -clear_filter_rules(void) -{ -#ifndef PF_ENABLE_FILTER_RULES - return 0; -#else - struct pfioc_trans io; - struct pfioc_trans_e ioe; - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&ioe, 0, sizeof(ioe)); - io.size = 1; - io.esize = sizeof(ioe); - io.array = &ioe; -#ifndef PF_NEWSTYLE - ioe.rs_num = PF_RULESET_FILTER; -#else - /* ? */ - ioe.type = PF_TRANS_RULESET; -#endif - strlcpy(ioe.anchor, anchor_name, MAXPATHLEN); - if(ioctl(dev, DIOCXBEGIN, &io) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m"); - goto error; - } - if(ioctl(dev, DIOCXCOMMIT, &io) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m"); - goto error; - } - return 0; -error: - return -1; -#endif -} -#endif - -/* add_redirect_rule2() : - * create a rdr rule */ -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp) -{ - int r; - struct pfioc_rule pcr; -#ifndef PF_NEWSTYLE - struct pfioc_pooladdr pp; - struct pf_pooladdr *a; -#endif - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - r = 0; - memset(&pcr, 0, sizeof(pcr)); - strlcpy(pcr.anchor, anchor_name, MAXPATHLEN); - -#ifndef PF_NEWSTYLE - memset(&pp, 0, sizeof(pp)); - strlcpy(pp.anchor, anchor_name, MAXPATHLEN); - if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m"); - r = -1; - } - else - { - pcr.pool_ticket = pp.ticket; -#else - if(1) - { - pcr.rule.direction = PF_IN; - /*pcr.rule.src.addr.type = PF_ADDR_NONE;*/ - pcr.rule.src.addr.type = PF_ADDR_ADDRMASK; - pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK; - pcr.rule.nat.addr.type = PF_ADDR_NONE; - pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK; -#endif - -#ifdef __APPLE__ - pcr.rule.dst.xport.range.op = PF_OP_EQ; - pcr.rule.dst.xport.range.port[0] = htons(eport); - pcr.rule.dst.xport.range.port[1] = htons(eport); -#else - pcr.rule.dst.port_op = PF_OP_EQ; - pcr.rule.dst.port[0] = htons(eport); - pcr.rule.dst.port[1] = htons(eport); -#endif -#ifndef PF_NEWSTYLE - pcr.rule.action = PF_RDR; -#ifndef PF_ENABLE_FILTER_RULES - pcr.rule.natpass = 1; -#else - pcr.rule.natpass = 0; -#endif -#else -#ifndef PF_ENABLE_FILTER_RULES - pcr.rule.action = PF_PASS; -#else - pcr.rule.action = PF_MATCH; -#endif -#endif - pcr.rule.af = AF_INET; -#ifdef USE_IFNAME_IN_RULES - if(ifname) - strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); -#endif - pcr.rule.proto = proto; - pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/ -#ifdef PFRULE_HAS_RTABLEID - pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */ -#endif -#ifdef PFRULE_HAS_ONRDOMAIN - pcr.rule.onrdomain = -1; /* first appeared in OpenBSD 5.0 */ -#endif - pcr.rule.quick = 1; - pcr.rule.keep_state = PF_STATE_NORMAL; - if(tag) - strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE); - strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE); - if(rhost && rhost[0] != '\0' && rhost[0] != '*') - { - inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr); - pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - } - if(use_ext_ip_addr && use_ext_ip_addr[0] != '\0') - { - inet_pton(AF_INET, use_ext_ip_addr, &pcr.rule.dst.addr.v.a.addr.v4.s_addr); - pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - } -#ifndef PF_NEWSTYLE - pcr.rule.rpool.proxy_port[0] = iport; - pcr.rule.rpool.proxy_port[1] = iport; - TAILQ_INIT(&pcr.rule.rpool.list); - a = calloc(1, sizeof(struct pf_pooladdr)); - inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); - a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries); - - memcpy(&pp.addr, a, sizeof(struct pf_pooladdr)); - if(ioctl(dev, DIOCADDADDR, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m"); - r = -1; - } - else - { -#else - pcr.rule.rdr.proxy_port[0] = iport; - pcr.rule.rdr.proxy_port[1] = iport; - inet_pton(AF_INET, iaddr, &pcr.rule.rdr.addr.v.a.addr.v4.s_addr); - pcr.rule.rdr.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - if(1) - { -#endif - pcr.action = PF_CHANGE_GET_TICKET; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); - r = -1; - } - else - { - pcr.action = PF_CHANGE_ADD_TAIL; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m"); - r = -1; - } - } - } -#ifndef PF_NEWSTYLE - free(a); -#endif - } - if(r == 0 && timestamp > 0) - add_timestamp_entry(eport, proto, timestamp); - return r; -} - -/* thanks to Seth Mos for this function */ -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc) -{ -#ifndef PF_ENABLE_FILTER_RULES - UNUSED(ifname); - UNUSED(rhost); UNUSED(iaddr); - UNUSED(eport); UNUSED(iport); - UNUSED(proto); UNUSED(desc); - return 0; -#else - int r; - struct pfioc_rule pcr; -#ifndef PF_NEWSTYLE - struct pfioc_pooladdr pp; -#endif -#ifndef USE_IFNAME_IN_RULES - UNUSED(ifname); -#endif - UNUSED(eport); - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - r = 0; - memset(&pcr, 0, sizeof(pcr)); - strlcpy(pcr.anchor, anchor_name, MAXPATHLEN); - -#ifndef PF_NEWSTYLE - memset(&pp, 0, sizeof(pp)); - strlcpy(pp.anchor, anchor_name, MAXPATHLEN); - if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m"); - r = -1; - } - else - { - pcr.pool_ticket = pp.ticket; -#else - if(1) - { -#endif - pcr.rule.dst.port_op = PF_OP_EQ; - pcr.rule.dst.port[0] = htons(iport); - pcr.rule.direction = PF_IN; - pcr.rule.action = PF_PASS; - pcr.rule.af = AF_INET; -#ifdef USE_IFNAME_IN_RULES - if(ifname) - strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); -#endif - pcr.rule.proto = proto; - pcr.rule.quick = (GETFLAG(PFNOQUICKRULESMASK))?0:1; - pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/ -/* see the discussion on the forum : - * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */ - pcr.rule.flags = TH_SYN; - pcr.rule.flagset = (TH_SYN|TH_ACK); -#ifdef PFRULE_HAS_RTABLEID - pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */ -#endif -#ifdef PFRULE_HAS_ONRDOMAIN - pcr.rule.onrdomain = -1; /* first appeared in OpenBSD 5.0 */ -#endif - pcr.rule.keep_state = 1; - strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE); - if(queue) - strlcpy(pcr.rule.qname, queue, PF_QNAME_SIZE); - if(tag) - strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE); - - if(rhost && rhost[0] != '\0' && rhost[0] != '*') - { - inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr); - pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - } - /* we want any - iaddr port = # keep state label */ - inet_pton(AF_INET, iaddr, &pcr.rule.dst.addr.v.a.addr.v4.s_addr); - pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); -#ifndef PF_NEWSTYLE - pcr.rule.rpool.proxy_port[0] = iport; - pcr.rule.rpool.proxy_port[1] = iport; - TAILQ_INIT(&pcr.rule.rpool.list); -#endif - if(1) - { - pcr.action = PF_CHANGE_GET_TICKET; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); - r = -1; - } - else - { - pcr.action = PF_CHANGE_ADD_TAIL; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m"); - r = -1; - } - } - } - } - return r; -#endif -} - -/* get_redirect_rule() - * return value : 0 success (found) - * -1 = error or rule not found */ -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes) -{ - int i, n; - struct pfioc_rule pr; -#ifndef PF_NEWSTYLE - struct pfioc_pooladdr pp; -#endif - UNUSED(ifname); - - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); -#ifndef PF_NEWSTYLE - pr.rule.action = PF_RDR; -#endif - if(ioctl(dev, DIOCGETRULES, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - goto error; - } - n = pr.nr; - for(i=0; i 0) - { - if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0) - { - rhost[0] = '\0'; /* empty string */ - } - else - { - inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, - rhost, rhostlen); - } - } - if(timestamp) - *timestamp = get_timestamp(eport, proto); - return 0; - } - } -error: - return -1; -} - -#define priv_delete_redirect_rule(ifname, eport, proto, iport, \ - iaddr, rhost, rhostlen) \ - priv_delete_redirect_rule_check_desc(ifname, eport, proto, iport, \ - iaddr, rhost, rhostlen, 0, NULL) -/* if check_desc is true, only delete the rule if the description differs. - * returns : -1 : error / rule not found - * 0 : rule deleted - * 1 : rule untouched - */ -static int -priv_delete_redirect_rule_check_desc(const char * ifname, unsigned short eport, - int proto, unsigned short * iport, - in_addr_t * iaddr, char * rhost, int rhostlen, - int check_desc, const char * desc) -{ - int i, n; - struct pfioc_rule pr; - UNUSED(ifname); - - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); -#ifndef PF_NEWSTYLE - pr.rule.action = PF_RDR; -#endif - if(ioctl(dev, DIOCGETRULES, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - goto error; - } - n = pr.nr; - for(i=0; i 0) - { - if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0) - rhost[0] = '\0'; /* empty string */ - else - inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, - rhost, rhostlen); - } - if(check_desc) { - if((desc == NULL && pr.rule.label[0] == '\0') || - (desc && 0 == strcmp(desc, pr.rule.label))) { - return 1; - } - } - pr.action = PF_CHANGE_GET_TICKET; - if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); - goto error; - } - pr.action = PF_CHANGE_REMOVE; - pr.nr = i; - if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m"); - goto error; - } - remove_timestamp_entry(eport, proto); - return 0; - } - } -error: - return -1; -} - -int -delete_redirect_rule(const char * ifname, unsigned short eport, - int proto) -{ - return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL, NULL, 0); -} - -static int -priv_delete_filter_rule(const char * ifname, unsigned short iport, - int proto, in_addr_t iaddr) -{ -#ifndef PF_ENABLE_FILTER_RULES - UNUSED(ifname); UNUSED(iport); UNUSED(proto); UNUSED(iaddr); - return 0; -#else - int i, n; - struct pfioc_rule pr; - UNUSED(ifname); - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); - pr.rule.action = PF_PASS; - if(ioctl(dev, DIOCGETRULES, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - goto error; - } - n = pr.nr; - for(i=0; i= n) - goto error; - pr.nr = index; - if(ioctl(dev, DIOCGETRULE, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); - goto error; - } - *proto = pr.rule.proto; -#ifdef __APPLE__ - *eport = ntohs(pr.rule.dst.xport.range.port[0]); -#else - *eport = ntohs(pr.rule.dst.port[0]); -#endif -#ifndef PF_NEWSTYLE - *iport = pr.rule.rpool.proxy_port[0]; -#else - *iport = pr.rule.rdr.proxy_port[0]; -#endif - if(ifname) - strlcpy(ifname, pr.rule.ifname, IFNAMSIZ); - if(desc) - strlcpy(desc, pr.rule.label, desclen); -#ifdef PFRULE_INOUT_COUNTS - if(packets) - *packets = pr.rule.packets[0] + pr.rule.packets[1]; - if(bytes) - *bytes = pr.rule.bytes[0] + pr.rule.bytes[1]; -#else - if(packets) - *packets = pr.rule.packets; - if(bytes) - *bytes = pr.rule.bytes; -#endif -#ifndef PF_NEWSTYLE - memset(&pp, 0, sizeof(pp)); - strlcpy(pp.anchor, anchor_name, MAXPATHLEN); - pp.r_action = PF_RDR; - pp.r_num = index; - pp.ticket = pr.ticket; - if(ioctl(dev, DIOCGETADDRS, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m"); - goto error; - } - if(pp.nr != 1) - { - syslog(LOG_NOTICE, "No address associated with pf rule"); - goto error; - } - pp.nr = 0; /* first */ - if(ioctl(dev, DIOCGETADDR, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m"); - goto error; - } - inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr, - iaddr, iaddrlen); -#else - inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr, - iaddr, iaddrlen); -#endif - if(rhost && rhostlen > 0) - { - if (pr.rule.src.addr.v.a.addr.v4.s_addr == 0) - { - rhost[0] = '\0'; /* empty string */ - } - else - { - inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, - rhost, rhostlen); - } - } - if(timestamp) - *timestamp = get_timestamp(*eport, *proto); - return 0; -error: - return -1; -} - -/* return an (malloc'ed) array of "external" port for which there is - * a port mapping. number is the size of the array */ -unsigned short * -get_portmappings_in_range(unsigned short startport, unsigned short endport, - int proto, unsigned int * number) -{ - unsigned short * array; - unsigned int capacity; - int i, n; - unsigned short eport; - struct pfioc_rule pr; - - *number = 0; - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return NULL; - } - capacity = 128; - array = calloc(capacity, sizeof(unsigned short)); - if(!array) - { - syslog(LOG_ERR, "get_portmappings_in_range() : calloc error"); - return NULL; - } - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); -#ifndef PF_NEWSTYLE - pr.rule.action = PF_RDR; -#endif - if(ioctl(dev, DIOCGETRULES, &pr) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - free(array); - return NULL; - } - n = pr.nr; - for(i=0; i= capacity) - { - /* need to increase the capacity of the array */ - unsigned short * tmp; - capacity += 128; - tmp = realloc(array, sizeof(unsigned short)*capacity); - if(!tmp) - { - syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity); - *number = 0; - free(array); - return NULL; - } - array = tmp; - } - array[*number] = eport; - (*number)++; - } - } - return array; -} - -/* update the port mapping internal port, decription and timestamp */ -int -update_portmapping(const char * ifname, unsigned short eport, int proto, - unsigned short iport, const char * desc, - unsigned int timestamp) -{ - unsigned short old_iport; - in_addr_t iaddr; - char iaddr_str[16]; - char rhost[32]; - - if(priv_delete_redirect_rule(ifname, eport, proto, &old_iport, &iaddr, rhost, sizeof(rhost)) < 0) - return -1; - if (priv_delete_filter_rule(ifname, old_iport, proto, iaddr) < 0) - return -1; - - inet_ntop(AF_INET, &iaddr, iaddr_str, sizeof(iaddr_str)); - - if(add_redirect_rule2(ifname, rhost, eport, iaddr_str, iport, proto, - desc, timestamp) < 0) - return -1; - if(add_filter_rule2(ifname, rhost, iaddr_str, eport, iport, proto, desc) < 0) - return -1; - - return 0; -} - -/* update the port mapping decription and timestamp */ -int -update_portmapping_desc_timestamp(const char * ifname, - unsigned short eport, int proto, - const char * desc, unsigned int timestamp) -{ - unsigned short iport; - in_addr_t iaddr; - char iaddr_str[16]; - char rhost[32]; - int r; - - r = priv_delete_redirect_rule_check_desc(ifname, eport, proto, &iport, &iaddr, rhost, sizeof(rhost), 1, desc); - if(r < 0) - return -1; - if(r == 1) { - /* only change timestamp */ - remove_timestamp_entry(eport, proto); - add_timestamp_entry(eport, proto, timestamp); - return 0; - } - if (priv_delete_filter_rule(ifname, iport, proto, iaddr) < 0) - return -1; - - inet_ntop(AF_INET, &iaddr, iaddr_str, sizeof(iaddr_str)); - - if(add_redirect_rule2(ifname, rhost, eport, iaddr_str, iport, proto, - desc, timestamp) < 0) - return -1; - if(add_filter_rule2(ifname, rhost, iaddr_str, eport, iport, proto, desc) < 0) - return -1; - - return 0; -} - - -/* this function is only for testing */ -#if TEST -void -list_rules(void) -{ - char buf[32]; - char buf2[32]; - int i, n; - struct pfioc_rule pr; -#ifndef PF_NEWSTYLE - struct pfioc_pooladdr pp; -#endif - - if(dev<0) - { - perror("pf dev not open"); - return ; - } - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); - pr.rule.action = PF_RDR; - if(ioctl(dev, DIOCGETRULES, &pr) < 0) - perror("DIOCGETRULES"); - printf("ticket = %d, nr = %d\n", pr.ticket, pr.nr); - n = pr.nr; - for(i=0; i %s %d:%d proto %d keep_state=%d action=%d\n", - pr.rule.ifname, - inet_ntop(AF_INET, &pr.rule.src.addr.v.a.addr.v4.s_addr, buf, 32), - (int)ntohs(pr.rule.dst.port[0]), - (int)ntohs(pr.rule.dst.port[1]), - inet_ntop(AF_INET, &pr.rule.dst.addr.v.a.addr.v4.s_addr, buf2, 32), -#ifndef PF_NEWSTYLE - (int)pr.rule.rpool.proxy_port[0], - (int)pr.rule.rpool.proxy_port[1], -#else - (int)pr.rule.rdr.proxy_port[0], - (int)pr.rule.rdr.proxy_port[1], -#endif - (int)pr.rule.proto, - (int)pr.rule.keep_state, - (int)pr.rule.action); - printf(" description: \"%s\"\n", pr.rule.label); -#ifndef PF_NEWSTYLE - memset(&pp, 0, sizeof(pp)); - strlcpy(pp.anchor, anchor_name, MAXPATHLEN); - pp.r_action = PF_RDR; - pp.r_num = i; - pp.ticket = pr.ticket; - if(ioctl(dev, DIOCGETADDRS, &pp) < 0) - perror("DIOCGETADDRS"); - printf(" nb pool addr = %d ticket=%d\n", pp.nr, pp.ticket); - /*if(ioctl(dev, DIOCGETRULE, &pr) < 0) - perror("DIOCGETRULE"); */ - pp.nr = 0; /* first */ - if(ioctl(dev, DIOCGETADDR, &pp) < 0) - perror("DIOCGETADDR"); - /* addr.v.a.addr.v4.s_addr */ - printf(" %s\n", inet_ntop(AF_INET, &pp.addr.addr.v.a.addr.v4.s_addr, buf, 32)); -#else - printf(" rule_flag=%08x action=%d direction=%d log=%d logif=%d " - "quick=%d ifnot=%d af=%d type=%d code=%d rdr.port_op=%d rdr.opts=%d\n", - pr.rule.rule_flag, pr.rule.action, pr.rule.direction, - pr.rule.log, pr.rule.logif, pr.rule.quick, pr.rule.ifnot, - pr.rule.af, pr.rule.type, pr.rule.code, - pr.rule.rdr.port_op, pr.rule.rdr.opts); - printf(" %s\n", inet_ntop(AF_INET, &pr.rule.rdr.addr.v.a.addr.v4.s_addr, buf, 32)); -#endif - } -} -#endif /* TEST */ - -#endif /* USE_PF */ diff --git a/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.h b/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.h deleted file mode 100644 index 3defa8e..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/obsdrdr.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $Id: obsdrdr.h,v 1.23 2014/03/06 12:24:33 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef OBSDRDR_H_INCLUDED -#define OBSDRDR_H_INCLUDED - -#include "../commonrdr.h" - -/* add_redirect_rule2() uses DIOCCHANGERULE ioctl - * proto can take the values IPPROTO_UDP or IPPROTO_TCP - */ -int -add_redirect_rule2(const char * ifname, - const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, int proto, - const char * desc, unsigned int timestamp); - -/* add_filter_rule2() uses DIOCCHANGERULE ioctl - * proto can take the values IPPROTO_UDP or IPPROTO_TCP - */ -int -add_filter_rule2(const char * ifname, - const char * rhost, const char * iaddr, - unsigned short eport, unsigned short iport, - int proto, const char * desc); - - -/* get_redirect_rule() gets internal IP and port from - * interface, external port and protocl - */ -#if 0 -int -get_redirect_rule(const char * ifname, unsigned short eport, int proto, - char * iaddr, int iaddrlen, unsigned short * iport, - char * desc, int desclen, - u_int64_t * packets, u_int64_t * bytes); - -int -get_redirect_rule_by_index(int index, - char * ifname, unsigned short * eport, - char * iaddr, int iaddrlen, unsigned short * iport, - int * proto, char * desc, int desclen, - u_int64_t * packets, u_int64_t * bytes); -#endif - -/* delete_redirect_rule() - */ -int -delete_redirect_rule(const char * ifname, unsigned short eport, int proto); - -/* delete_redirect_and_filter_rules() - */ -int -delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, - int proto); - -#ifdef TEST -int -clear_redirect_rules(void); -int -clear_filter_rules(void); -#endif - -#endif - - diff --git a/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.c b/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.c deleted file mode 100644 index e0f0959..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.c +++ /dev/null @@ -1,445 +0,0 @@ -/* $Id: pfpinhole.c,v 1.27 2018/03/13 23:05:21 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef __DragonFly__ -#include -#else -#ifdef __APPLE__ -#define PRIVATE 1 -#endif -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "../config.h" -#include "pfpinhole.h" -#include "../upnpglobalvars.h" -#include "../macros.h" - -/* the pass rules created by add_pinhole() are as follow : - * - * pass in quick on ep0 inet6 proto udp - * from any to dead:beef::42:42 port = 8080 - * flags S/SA keep state - * label "pinhole-2 ts-4321000" - * - * with the label "pinhole-$uid ts-$timestamp: $description" - */ - -#ifdef ENABLE_UPNPPINHOLE - -/* /dev/pf when opened */ -extern int dev; - -static int next_uid = 1; - -#define PINEHOLE_LABEL_FORMAT "pinhole-%d ts-%u: %s" -#define PINEHOLE_LABEL_FORMAT_SKIPDESC "pinhole-%d ts-%u: %*s" - -int add_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, const char * desc, unsigned int timestamp) -{ - int uid; - struct pfioc_rule pcr; -#ifndef PF_NEWSTYLE - struct pfioc_pooladdr pp; -#endif - - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - memset(&pcr, 0, sizeof(pcr)); - strlcpy(pcr.anchor, anchor_name, MAXPATHLEN); - -#ifndef PF_NEWSTYLE - memset(&pp, 0, sizeof(pp)); - strlcpy(pp.anchor, anchor_name, MAXPATHLEN); - if(ioctl(dev, DIOCBEGINADDRS, &pp) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCBEGINADDRS, ...): %m"); - return -1; - } else { - pcr.pool_ticket = pp.ticket; -#else - { -#endif - pcr.rule.direction = PF_IN; - pcr.rule.action = PF_PASS; - pcr.rule.af = AF_INET6; -#ifdef PF_NEWSTYLE - pcr.rule.nat.addr.type = PF_ADDR_NONE; - pcr.rule.rdr.addr.type = PF_ADDR_NONE; -#endif -#ifdef USE_IFNAME_IN_RULES - if(ifname) - strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); -#endif - pcr.rule.proto = proto; - - pcr.rule.quick = 1;/*(GETFLAG(PFNOQUICKRULESMASK))?0:1;*/ - pcr.rule.log = (GETFLAG(LOGPACKETSMASK))?1:0; /*logpackets;*/ -/* see the discussion on the forum : - * http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=638 */ - pcr.rule.flags = TH_SYN; - pcr.rule.flagset = (TH_SYN|TH_ACK); -#ifdef PFRULE_HAS_RTABLEID - pcr.rule.rtableid = -1; /* first appeared in OpenBSD 4.0 */ -#endif -#ifdef PFRULE_HAS_ONRDOMAIN - pcr.rule.onrdomain = -1; /* first appeared in OpenBSD 5.0 */ -#endif - pcr.rule.keep_state = 1; - uid = next_uid; - snprintf(pcr.rule.label, PF_RULE_LABEL_SIZE, - PINEHOLE_LABEL_FORMAT, uid, timestamp, desc); - if(queue) - strlcpy(pcr.rule.qname, queue, PF_QNAME_SIZE); - if(tag) - strlcpy(pcr.rule.tagname, tag, PF_TAG_NAME_SIZE); - - if(rem_port) { - pcr.rule.src.port_op = PF_OP_EQ; - pcr.rule.src.port[0] = htons(rem_port); - } - if(rem_host && rem_host[0] != '\0' && rem_host[0] != '*') { - pcr.rule.src.addr.type = PF_ADDR_ADDRMASK; - if(inet_pton(AF_INET6, rem_host, &pcr.rule.src.addr.v.a.addr.v6) != 1) { - syslog(LOG_ERR, "inet_pton(%s) failed", rem_host); - } - memset(&pcr.rule.src.addr.v.a.mask.addr8, 255, 16); - } - - pcr.rule.dst.port_op = PF_OP_EQ; - pcr.rule.dst.port[0] = htons(int_port); - pcr.rule.dst.addr.type = PF_ADDR_ADDRMASK; - if(inet_pton(AF_INET6, int_client, &pcr.rule.dst.addr.v.a.addr.v6) != 1) { - syslog(LOG_ERR, "inet_pton(%s) failed", int_client); - } - memset(&pcr.rule.dst.addr.v.a.mask.addr8, 255, 16); - - if(ifname) - strlcpy(pcr.rule.ifname, ifname, IFNAMSIZ); - - pcr.action = PF_CHANGE_GET_TICKET; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); - return -1; - } else { - pcr.action = PF_CHANGE_ADD_TAIL; - if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_ADD_TAIL: %m"); - return -1; - } - } - } - - if(++next_uid >= 65535) { - next_uid = 1; - } - return uid; -} - -int find_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, - char *desc, int desc_len, unsigned int * timestamp) -{ - int uid; - unsigned int ts; - int i, n; - struct pfioc_rule pr; - struct in6_addr saddr; - struct in6_addr daddr; - UNUSED(ifname); - - if(dev<0) { - syslog(LOG_ERR, "pf device is not open"); - return -1; - } - if(rem_host && (rem_host[0] != '\0')) { - inet_pton(AF_INET6, rem_host, &saddr); - } else { - memset(&saddr, 0, sizeof(struct in6_addr)); - } - inet_pton(AF_INET6, int_client, &daddr); - memset(&pr, 0, sizeof(pr)); - strlcpy(pr.anchor, anchor_name, MAXPATHLEN); -#ifndef PF_NEWSTYLE - pr.rule.action = PF_PASS; -#endif - if(ioctl(dev, DIOCGETRULES, &pr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - return -1; - } - n = pr.nr; - for(i=0; i= 0; i--) { - pr.nr = i; - if(ioctl(dev, DIOCGETRULE, &pr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); - return -1; - } - if(sscanf(pr.rule.label, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) { - syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", pr.rule.label); - continue; - } - if(ts <= (unsigned int)current_time) { - syslog(LOG_INFO, "removing expired pinhole '%s'", pr.rule.label); - pr.action = PF_CHANGE_GET_TICKET; - if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_GET_TICKET: %m"); - return -1; - } - pr.action = PF_CHANGE_REMOVE; - pr.nr = i; - if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCCHANGERULE, ...) PF_CHANGE_REMOVE: %m"); - return -1; - } - n++; -#ifndef PF_NEWSTYLE - pr.rule.action = PF_PASS; -#endif - if(ioctl(dev, DIOCGETRULES, &pr) < 0) { - syslog(LOG_ERR, "ioctl(dev, DIOCGETRULES, ...): %m"); - return -1; - } - } else { - if(uid > max_uid) - max_uid = uid; - else if(uid < min_uid) - min_uid = uid; - if(ts < min_ts) - min_ts = ts; - } - } - if(next_timestamp && (min_ts != UINT_MAX)) - *next_timestamp = min_ts; - if(max_uid > 0) { - if(((min_uid - 32000) <= next_uid) && (next_uid <= max_uid)) { - next_uid = max_uid + 1; - } - if(next_uid >= 65535) { - next_uid = 1; - } - } - return n; /* number of rules removed */ -} - -#endif /* ENABLE_UPNPPINHOLE */ diff --git a/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.h b/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.h deleted file mode 100644 index 5d695df..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/pfpinhole.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id: pfpinhole.h,v 1.9 2012/05/01 22:37:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef PFPINHOLE_H_INCLUDED -#define PFPINHOLE_H_INCLUDED - -#ifdef ENABLE_UPNPPINHOLE - -int find_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, - char *desc, int desc_len, unsigned int * timestamp); - -int add_pinhole(const char * ifname, - const char * rem_host, unsigned short rem_port, - const char * int_client, unsigned short int_port, - int proto, const char * desc, unsigned int timestamp); - -int delete_pinhole(unsigned short uid); - -int -get_pinhole_info(unsigned short uid, - char * rem_host, int rem_hostlen, unsigned short * rem_port, - char * int_client, int int_clientlen, unsigned short * int_port, - int * proto, char * desc, int desclen, - unsigned int * timestamp, - u_int64_t * packets, u_int64_t * bytes); - -int update_pinhole(unsigned short uid, unsigned int timestamp); - -int clean_pinhole_list(unsigned int * next_timestamp); - -#endif /* ENABLE_UPNPPINHOLE */ - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/pf/testobsdrdr.c b/src/contrib/miniupnp/miniupnpd/pf/testobsdrdr.c deleted file mode 100644 index cd0bbba..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/testobsdrdr.c +++ /dev/null @@ -1,147 +0,0 @@ -/* $Id: testobsdrdr.c,v 1.30 2018/04/12 09:27:54 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include - -#include "obsdrdr.h" - -/*int logpackets = 1;*/ -int runtime_flags = 0; -const char * tag = 0; -const char * anchor_name = "miniupnpd"; -const char * queue = NULL; -const char * use_ext_ip_addr = "42.42.42.42"; - -void -list_rules(void); - -void -list_eports_tcp(void) -{ - unsigned short * port_list; - unsigned int number = 0; - unsigned int i; - port_list = get_portmappings_in_range(0, 65535, IPPROTO_TCP, &number); - printf("%u ports redirected (TCP) :", number); - for(i = 0; i < number; i++) - { - printf(" %hu", port_list[i]); - } - printf("\n"); - free(port_list); -} - -void -test_index(void) -{ - char ifname[16/*IFNAMSIZ*/]; - char iaddr[32]; - char desc[64]; - char rhost[32]; - unsigned short iport = 0; - unsigned short eport = 0; - int proto = 0; - unsigned int timestamp; - ifname[0] = '\0'; - iaddr[0] = '\0'; - rhost[0] = '\0'; - if(get_redirect_rule_by_index(0, ifname, &eport, iaddr, sizeof(iaddr), - &iport, &proto, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, 0, 0) < 0) - { - printf("get.._by_index : no rule\n"); - } - else - { - printf("%s %u -> %s:%u proto %d\n", ifname, (unsigned int)eport, - iaddr, (unsigned int)iport, proto); - printf("description: \"%s\"\n", desc); - } -} - -int -main(int argc, char * * argv) -{ - char buf[32]; - char desc[64]; - char rhost[64]; - /*char rhost[32];*/ - unsigned short iport; - unsigned int timestamp; - u_int64_t packets = 0; - u_int64_t bytes = 0; - int clear = 0; - - if(argc > 1) { - if(0 == strcmp(argv[1], "--clear") || 0 == strcmp(argv[1], "-c")) - clear = 1; - } - - openlog("testobsdrdr", LOG_PERROR, LOG_USER); - if(init_redirect() < 0) - { - fprintf(stderr, "init_redirect() failed\n"); - return 1; - } -#if 0 - add_redirect_rule("ep0", 12123, "192.168.1.23", 1234); - add_redirect_rule2("ep0", 12155, "192.168.1.155", 1255, IPPROTO_TCP); -#endif - if(add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, - IPPROTO_UDP, "test description", 0) < 0) - printf("add_redirect_rule2() #3 failed\n"); - use_ext_ip_addr = NULL; - if(add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234, - IPPROTO_TCP, "test description tcp", 0) < 0) - printf("add_redirect_rule2() #4 failed\n"); - if(add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP, - "test description tcp") < 0) - printf("add_filter_rule2() #1 failed\n"); - - list_rules(); - list_eports_tcp(); - - - if(get_redirect_rule("xl1", 4662, IPPROTO_TCP, - buf, sizeof(buf), &iport, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) < 0) - printf("get_redirect_rule() failed\n"); - else - { - printf("\n%s:%d '%s' packets=%" PRIu64 " bytes=%" PRIu64 "\n", buf, (int)iport, desc, - packets, bytes); - } - - if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) - printf("delete_redirect_rule() failed\n"); - - if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) - printf("delete_redirect_rule() failed\n"); - - if(delete_redirect_and_filter_rules("em0", 12123, IPPROTO_TCP) < 0) - printf("delete_redirect_and_filter_rules() failed\n"); - - test_index(); - - if(clear) { - clear_redirect_rules(); - clear_filter_rules(); - } - /*list_rules();*/ - - return 0; -} - - diff --git a/src/contrib/miniupnp/miniupnpd/pf/testpfpinhole.c b/src/contrib/miniupnp/miniupnpd/pf/testpfpinhole.c deleted file mode 100644 index de3d4e0..0000000 --- a/src/contrib/miniupnp/miniupnpd/pf/testpfpinhole.c +++ /dev/null @@ -1,105 +0,0 @@ -/* $Id: testpfpinhole.c,v 1.12 2014/05/15 21:23:43 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include - -#include "../config.h" -#include "obsdrdr.h" -#include "pfpinhole.h" - -int runtime_flags = 0; -const char * tag = NULL; - -const char * anchor_name = "miniupnpd"; -const char * queue = NULL; - -#ifdef ENABLE_IPV6 -static int print_pinhole(int uid) -{ - int r; - char rem_host[64]; - unsigned short rem_port; - char int_client[64]; - unsigned short int_port; - int proto; - unsigned int timestamp; - u_int64_t packets, bytes; - char desc[64]; - - r = get_pinhole_info((unsigned short)uid, - rem_host, sizeof(rem_host), &rem_port, - int_client, sizeof(int_client), &int_port, - &proto, - desc, sizeof(desc), - ×tamp, - &packets, &bytes); - if(r < 0) { - fprintf(stderr, "get_pinhole(%d) returned %d\n", uid, r); - } else { - printf("pinhole %d : [%s]:%hu => [%s]:%hu proto=%d ts=%u\n", - uid, rem_host, rem_port, int_client, int_port, - proto, timestamp); - printf(" desc='%s'\n", desc); - printf(" packets=%" PRIu64 " bytes=%" PRIu64 "\n", packets, bytes); - } - return r; -} -#endif - -int main(int argc, char * *argv) -{ -#ifndef ENABLE_IPV6 - fprintf(stderr,"nothing to test, ENABLE_IPV6 is not defined in config.h\n"); - return 1; -#else - int uid; - int uid2; - int ret; - unsigned int timestamp; - (void)argc; (void)argv; - - openlog("testpfpinhole", LOG_PERROR, LOG_USER); - if(init_redirect() < 0) { - fprintf(stderr, "init_redirect() failed\n"); - return 1; - } - - uid = add_pinhole("ep0", "2001::1:2:3", 12345, "123::ff", 54321, IPPROTO_UDP, "description test 1", 424242); - if(uid < 0) { - fprintf(stderr, "add_pinhole() failed\n"); - } - printf("add_pinhole() returned %d\n", uid); - uid = add_pinhole("ep0", NULL, 0, "dead:beef::42:42", 8080, IPPROTO_UDP, "description test 2", 4321000); - if(uid < 0) { - fprintf(stderr, "add_pinhole() failed\n"); - } - printf("add_pinhole() returned %d\n", uid); - - uid2 = find_pinhole("ep0", NULL, 0, "dead:beef::42:42", 8080, IPPROTO_UDP, NULL, 0, ×tamp); - if(uid2 < 0) { - fprintf(stderr, "find_pinhole() failed\n"); - } else { - printf("find_pinhole() uid=%d timestamp=%u\n", uid2, timestamp); - } - - print_pinhole(1); - print_pinhole(2); - clean_pinhole_list(NULL); - - ret = delete_pinhole(1); - printf("delete_pinhole() returned %d\n", ret); - ret = delete_pinhole(2); - printf("delete_pinhole() returned %d\n", ret); -#endif - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/portinuse.c b/src/contrib/miniupnp/miniupnpd/portinuse.c deleted file mode 100644 index bfff889..0000000 --- a/src/contrib/miniupnp/miniupnpd/portinuse.c +++ /dev/null @@ -1,409 +0,0 @@ -/* $Id: portinuse.c,v 1.3 2014/04/01 12:52:50 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * (c) 2007-2017 Thomas Bernard - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#if defined(__DragonFly__) || defined(__FreeBSD__) -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__OpenBSD__) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#if defined(__DragonFly__) || defined(__FreeBSD__) -#include -#include -/* sys/socketvar.h must be included above the following headers */ -#include -#include -#endif - -#include "macros.h" -#include "config.h" -#include "upnpglobalvars.h" -#include "getifaddr.h" -#include "portinuse.h" - -#if defined(USE_NETFILTER) -#include "netfilter/iptcrdr.h" -#endif - -#ifdef CHECK_PORTINUSE - -#if defined(USE_NETFILTER) -/* Hardcoded for now. Ideally would come from .conf file */ -# ifdef TOMATO - const char *chains_to_check[] = { "WANPREROUTING" , 0 }; -# else - const char *chains_to_check[] = { "PREROUTING" , 0 }; -# endif -#endif - -int -port_in_use(const char *if_name, - unsigned eport, int proto, - const char *iaddr, unsigned iport) -{ - int found = 0; - char ip_addr_str[INET_ADDRSTRLEN]; - struct in_addr ip_addr; -#ifdef __linux__ - /* linux code */ - char line[256]; - FILE *f; - const char * tcpfile = "/proc/net/tcp"; - const char * udpfile = "/proc/net/udp"; -#endif - - if(getifaddr(if_name, ip_addr_str, INET_ADDRSTRLEN, &ip_addr, NULL) < 0) { - ip_addr.s_addr = 0; - ip_addr_str[0] = '\0'; - } - - syslog(LOG_DEBUG, "Check protocol %s for port %u on ext_if %s %s, %08X", - (proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name, - ip_addr_str, (unsigned)ip_addr.s_addr); - - /* Phase 1 : check for local sockets (would be listed by netstat) */ -#if defined(__linux__) - f = fopen((proto==IPPROTO_TCP)?tcpfile:udpfile, "r"); - if (!f) { - syslog(LOG_ERR, "cannot open %s", (proto==IPPROTO_TCP)?tcpfile:udpfile); - return -1; - } - - while (fgets(line, 255, f)) { - char eaddr[68]; - unsigned tmp_port; - if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x " - "%*x:%*x %*x %*d %*d %*llu", - eaddr, &tmp_port) == 2 - ) { - /* TODO add IPV6 support if enabled - * Presently assumes IPV4 */ -#ifdef DEBUG - syslog(LOG_DEBUG, "port_in_use check port %u and address %s", tmp_port, eaddr); -#endif - if (tmp_port == eport) { - char tmp_addr[4]; - struct in_addr *tmp_ip_addr = (struct in_addr *)tmp_addr; - if (sscanf(eaddr,"%2hhx%2hhx%2hhx%2hhx", - &tmp_addr[3],&tmp_addr[2],&tmp_addr[1],&tmp_addr[0]) == 4) - { - if (tmp_ip_addr->s_addr == 0 || tmp_ip_addr->s_addr == ip_addr.s_addr) - { - found++; - break; /* don't care how many, just that we found at least one */ - } - } - } - } - } - fclose(f); - -#elif defined(__OpenBSD__) -static struct nlist list[] = { -#if 0 - {"_tcpstat", 0, 0, 0, 0}, - {"_udpstat", 0, 0, 0, 0}, - {"_tcbinfo", 0, 0, 0, 0}, - {"_udbinfo", 0, 0, 0, 0}, -#endif - {"_tcbtable", 0, 0, 0, 0}, - {"_udbtable", 0, 0, 0, 0}, - {NULL,0, 0, 0, 0} -}; - char errstr[_POSIX2_LINE_MAX]; - kvm_t *kd; - ssize_t n; - struct inpcbtable table; - struct inpcb *next; - struct inpcb inpcb; - kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr); - if(!kd) { - syslog(LOG_ERR, "%s: kvm_openfiles(): %s", - "portinuse()", errstr); - return -1; - } - if(kvm_nlist(kd, list) < 0) { - syslog(LOG_ERR, "%s: kvm_nlist(): %s", - "portinuse()", kvm_geterr(kd)); - kvm_close(kd); - return -1; - } - n = kvm_read(kd, list[(proto==IPPROTO_TCP)?0:1].n_value, &table, sizeof(table)); - if(n < 0) { - syslog(LOG_ERR, "%s: kvm_read(): %s", - "portinuse()", kvm_geterr(kd)); - kvm_close(kd); - return -1; - } - next = CIRCLEQ_FIRST(&table.inpt_queue); /*TAILQ_FIRST(&table.inpt_queue);*/ - while(next != NULL) { - if(((u_long)next & 3) != 0) break; - n = kvm_read(kd, (u_long)next, &inpcb, sizeof(inpcb)); - if(n < 0) { - syslog(LOG_ERR, "kvm_read(): %s", kvm_geterr(kd)); - break; - } - next = CIRCLEQ_NEXT(&inpcb, inp_queue); /*TAILQ_NEXT(&inpcb, inp_queue);*/ - /* skip IPv6 sockets */ - if((inpcb.inp_flags & INP_IPV6) != 0) - continue; -#ifdef DEBUG - syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu", - (u_long)inpcb.inp_laddr.s_addr, ntohs(inpcb.inp_lport), - (u_long)inpcb.inp_faddr.s_addr, ntohs(inpcb.inp_fport)); -#endif - if(eport == (unsigned)ntohs(inpcb.inp_lport)) { - if(inpcb.inp_laddr.s_addr == INADDR_ANY || inpcb.inp_laddr.s_addr == ip_addr.s_addr) { - found++; - break; /* don't care how many, just that we found at least one */ - } - } - } - kvm_close(kd); - -#elif defined(__DragonFly__) - const char *varname; - struct xinpcb *xip; - struct xtcpcb *xtp; - struct inpcb *inp; - void *buf = NULL; - void *so_begin, *so_end; - - size_t len; - - switch (proto) { - case IPPROTO_TCP: - varname = "net.inet.tcp.pcblist"; - break; - case IPPROTO_UDP: - varname = "net.inet.udp.pcblist"; - break; - default: - syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto); - return -1; - } - - if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) { - syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname); - return -1; - } - buf = malloc(len); - if (buf == NULL) { - syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len); - return -1; - } - if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) { - syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname); - free(buf); - return -1; - } - - so_begin = buf; - so_end = (uint8_t *)buf + len; - for (so_begin = buf, so_end = (uint8_t *)so_begin + len; - (uint8_t *)so_begin + sizeof(size_t) < (uint8_t *)so_end && - (uint8_t *)so_begin + *(size_t *)so_begin <= (uint8_t *)so_end; - so_begin = (uint8_t *)so_begin + *(size_t *)so_begin) { - switch (proto) { - case IPPROTO_TCP: - xtp = (struct xtcpcb *)so_begin; - if (xtp->xt_len != sizeof *xtp) { - syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld", - (long)xtp->xt_len, sizeof *xtp); - free(buf); - return -1; - } - inp = &xtp->xt_inp; - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)so_begin; - if (xip->xi_len != sizeof *xip) { - syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld", - (long)xip->xi_len, sizeof *xip); - free(buf); - return -1; - } - inp = &xip->xi_inp; - break; - default: - abort(); - } - /* no support for IPv6 */ - if (INP_ISIPV6(inp) != 0) - continue; - syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu", - (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport), - (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport), - eport, (u_long)ip_addr.s_addr, iport - ); - if (eport == (unsigned)ntohs(inp->inp_lport)) { - if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) { - found++; - break; /* don't care how many, just that we found at least one */ - } - } - } - if (buf) { - free(buf); - buf = NULL; - } -#elif defined(__FreeBSD__) - const char *varname; - struct xinpgen *xig, *exig; - struct xinpcb *xip; - struct xtcpcb *xtp; - struct inpcb *inp; - void *buf = NULL; - size_t len; - - switch (proto) { - case IPPROTO_TCP: - varname = "net.inet.tcp.pcblist"; - break; - case IPPROTO_UDP: - varname = "net.inet.udp.pcblist"; - break; - default: - syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto); - return -1; - } - - if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) { - syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname); - return -1; - } - buf = malloc(len); - if (buf == NULL) { - syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len); - return -1; - } - if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) { - syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname); - free(buf); - return -1; - } - - xig = (struct xinpgen *)buf; - exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig); - if (xig->xig_len != sizeof *xig) { - syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld", - (long)xig->xig_len, sizeof *xig); - free(buf); - return -1; - } - if (exig->xig_len != sizeof *exig) { - syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld", - (long)exig->xig_len, sizeof *exig); - free(buf); - return -1; - } - - while (1) { - xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); - if (xig >= exig) - break; - switch (proto) { - case IPPROTO_TCP: - xtp = (struct xtcpcb *)xig; - if (xtp->xt_len != sizeof *xtp) { - syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld", - (long)xtp->xt_len, sizeof *xtp); - free(buf); - return -1; - } - inp = &xtp->xt_inp; - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { - syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld", - (long)xip->xi_len, sizeof *xip); - free(buf); - return -1; - } - inp = &xip->xi_inp; - break; - default: - abort(); - } - /* no support for IPv6 */ - if ((inp->inp_vflag & INP_IPV6) != 0) - continue; - syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu", - (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport), - (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport), - eport, (u_long)ip_addr.s_addr, iport - ); - if (eport == (unsigned)ntohs(inp->inp_lport)) { - if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) { - found++; - break; /* don't care how many, just that we found at least one */ - } - } - } - if (buf) { - free(buf); - buf = NULL; - } -/* #elif __NetBSD__ */ -#else -/* TODO : NetBSD / Darwin (OS X) / Solaris code */ -#error "No port_in_use() implementation available for this OS" -#endif - - /* Phase 2 : check existing mappings - * TODO : implement for pf/ipfw/etc. */ -#if defined(USE_NETFILTER) - if (!found) { - char iaddr_old[16]; - unsigned short iport_old; - int i; - for (i = 0; chains_to_check[i]; i++) { - if (get_nat_redirect_rule(chains_to_check[i], if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), &iport_old, - 0, 0, 0, 0, 0, 0, 0) == 0) - { - syslog(LOG_DEBUG, "port_in_use check port %d on nat chain %s redirected to %s port %d", eport, - chains_to_check[i], iaddr_old, iport_old); - if (!(strcmp(iaddr, iaddr_old)==0 && iport==iport_old)) { - /* only "in use" if redirected to somewhere else */ - found++; - break; /* don't care how many, just that we found at least one */ - } - } - } - } -#else /* USE_NETFILTER */ - UNUSED(iport); UNUSED(iaddr); -#endif /* USE_NETFILTER */ - return found; -} -#endif /* CHECK_PORTINUSE */ diff --git a/src/contrib/miniupnp/miniupnpd/portinuse.h b/src/contrib/miniupnp/miniupnpd/portinuse.h deleted file mode 100644 index 01842f6..0000000 --- a/src/contrib/miniupnp/miniupnpd/portinuse.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef __PORTINUSE_H__ -#define __PORTINUSE_H__ - -#ifdef CHECK_PORTINUSE -/* portinuse() - * determine wether a port is already in use - * on a given interface. - * returns: 0 not in use, > 0 in use - * -1 in case of error */ -int -port_in_use(const char *if_name, - unsigned port, int proto, - const char *iaddr, unsigned iport); -#endif /* CHECK_PORTINUSE */ - -#endif diff --git a/src/contrib/miniupnp/miniupnpd/solaris/getifstats.c b/src/contrib/miniupnp/miniupnpd/solaris/getifstats.c deleted file mode 100644 index 19170c7..0000000 --- a/src/contrib/miniupnp/miniupnpd/solaris/getifstats.c +++ /dev/null @@ -1,97 +0,0 @@ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * author: Ryan Wagoner and Thomas Bernard - * (c) 2007 Darren Reed - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include - -#include "../getifstats.h" - -int -getifstats(const char * ifname, struct ifdata * data) -{ - char buffer[64], *s; - kstat_named_t *kn; - kstat_ctl_t *kc; - int instance; - kstat_t *ksp; - - if (data == NULL) - goto error; - - if (ifname == NULL || *ifname == '\0') - goto error; - - s = (char *)ifname + strlen(ifname); - s--; - while ((s > ifname) && isdigit(*s)) - s--; - - s++; - instance = atoi(s); - strlcpy(buffer, ifname, MIN(s - ifname + 1, 64)); - - kc = kstat_open(); - if (kc != NULL) { - ksp = kstat_lookup(kc, buffer, instance, (char *)ifname); - if (ksp && (kstat_read(kc, ksp, NULL) != -1)) { - /* found the right interface */ - if (sizeof(long) == 8) { - kn = kstat_data_lookup(ksp, "rbytes64"); - if (kn != NULL) { - data->ibytes = kn->value.i64; - } - kn = kstat_data_lookup(ksp, "ipackets64"); - if (kn != NULL) { - data->ipackets = kn->value.i64; - } - kn = kstat_data_lookup(ksp, "obytes64"); - if (kn != NULL) { - data->obytes = kn->value.i64; - } - kn = kstat_data_lookup(ksp, "opackets64"); - if (kn != NULL) { - data->opackets = kn->value.i64; - } - } else { - kn = kstat_data_lookup(ksp, "rbytes"); - if (kn != NULL) { - data->ibytes = kn->value.i32; - } - kn = kstat_data_lookup(ksp, "ipackets"); - if (kn != NULL) { - data->ipackets = kn->value.i32; - } - kn = kstat_data_lookup(ksp, "obytes"); - if (kn != NULL) { - data->obytes = kn->value.i32; - } - kn = kstat_data_lookup(ksp, "opackets"); - if (kn != NULL) { - data->ipackets = kn->value.i32; - } - } - kn = kstat_data_lookup(ksp, "ifspeed"); - if (kn != NULL) { - data->baudrate = kn->value.i32; - } - kstat_close(kc); - return 0; /* ok */ - } - syslog(LOG_ERR, "kstat_lookup/read() failed: %m"); - kstat_close(kc); - return -1; - } else { - syslog(LOG_ERR, "kstat_open() failed: %m"); - } -error: - return -1; /* not found or error */ -} - diff --git a/src/contrib/miniupnp/miniupnpd/testasyncsendto.c b/src/contrib/miniupnp/miniupnpd/testasyncsendto.c deleted file mode 100644 index 6d441ea..0000000 --- a/src/contrib/miniupnp/miniupnpd/testasyncsendto.c +++ /dev/null @@ -1,129 +0,0 @@ -/* $Id: testasyncsendto.c,v 1.5 2018/03/13 10:25:52 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "miniupnpdtypes.h" -#include "upnputils.h" -#include "asyncsendto.h" - -struct lan_addr_list lan_addrs; -int runtime_flags = 0; -time_t startup_time = 0; - -#define DEST_IP "239.255.255.250" -#define DEST_PORT 1900 -/* -ssize_t -sendto_schedule(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen, - unsigned int delay) -*/ - -int test(void) -{ - int s; - ssize_t n; - int i; - struct sockaddr_in addr; - struct sockaddr_in dest_addr; - struct timeval next_send; - if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "socket(): %m"); - return 1; - } - set_non_blocking(s); - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - syslog(LOG_ERR, "bind(): %m"); - close(s); - return 1; - } - memset(&dest_addr, 0, sizeof(struct sockaddr_in)); - dest_addr.sin_family = AF_INET; - dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); - dest_addr.sin_port = htons(DEST_PORT); - n = sendto_or_schedule(s, "1234", 4, 0, - (struct sockaddr *)&dest_addr, sizeof(dest_addr)); - syslog(LOG_DEBUG, "sendto_or_schedule : %d", (int)n); - n = sendto_schedule(s, "1234", 4, 0, - (struct sockaddr *)&dest_addr, sizeof(dest_addr), - 4400); - syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); - n = sendto_schedule(s, "1234", 4, 0, - (struct sockaddr *)&dest_addr, sizeof(dest_addr), - 3000); - syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); - while ((i = get_next_scheduled_send(&next_send)) > 0) { - fd_set writefds; - int max_fd; - struct timeval timeout; - struct timeval now; - syslog(LOG_DEBUG, "get_next_scheduled_send : %d next_send=%ld.%06ld", - i, (long)next_send.tv_sec, (long)next_send.tv_usec); - FD_ZERO(&writefds); - max_fd = 0; - gettimeofday(&now, NULL); - i = get_sendto_fds(&writefds, &max_fd, &now); - if(now.tv_sec > next_send.tv_sec || - (now.tv_sec == next_send.tv_sec && now.tv_usec >= next_send.tv_usec)) { - if(i > 0) { - /* don't wait */ - timeout.tv_sec = 0; - } else { - /* wait 10sec :) */ - timeout.tv_sec = 10; - } - timeout.tv_usec = 0; - } else { - /* ... */ - timeout.tv_sec = (next_send.tv_sec - now.tv_sec); - timeout.tv_usec = (next_send.tv_usec - now.tv_usec); - if(timeout.tv_usec < 0) { - timeout.tv_usec += 1000000; - timeout.tv_sec--; - } - } - syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i); - syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)", - max_fd, (long)timeout.tv_sec, (long)timeout.tv_usec); - i = select(max_fd, NULL, &writefds, NULL, &timeout); - if(i < 0) { - syslog(LOG_ERR, "select: %m"); - if(errno != EINTR) - break; - } else if(try_sendto(&writefds) < 0) { - syslog(LOG_ERR, "try_sendto: %m"); - break; - } - } - close(s); - return 0; -} - -int main(int argc, char * * argv) -{ - int r; - (void)argc; - (void)argv; - openlog("testasyncsendto", LOG_CONS|LOG_PERROR, LOG_USER); - r = test(); - closelog(); - return r; -} - diff --git a/src/contrib/miniupnp/miniupnpd/testgetifaddr.c b/src/contrib/miniupnp/miniupnpd/testgetifaddr.c deleted file mode 100644 index 8045b89..0000000 --- a/src/contrib/miniupnp/miniupnpd/testgetifaddr.c +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: testgetifaddr.c,v 1.7 2013/04/27 15:38:57 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "getifaddr.h" - -#if defined(__sun) -/* solaris 10 does not define LOG_PERROR */ -#define LOG_PERROR 0 -#endif - -int main(int argc, char * * argv) { - char str_addr[64]; - struct in_addr addr; - struct in_addr mask; -#ifdef ENABLE_IPV6 - int r; - char str_addr6[64]; -#endif - if(argc < 2) { - fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]); - return 1; - } - - openlog("testgetifaddr", LOG_CONS|LOG_PERROR, LOG_USER); - if(getifaddr(argv[1], str_addr, sizeof(str_addr), &addr, &mask) < 0) { - fprintf(stderr, "Cannot get address for interface %s.\n", argv[1]); - return 1; - } - printf("Interface %s has IP address %s.\n", argv[1], str_addr); - printf("addr=%s ", inet_ntoa(addr)); - printf("mask=%s\n", inet_ntoa(mask)); -#ifdef ENABLE_IPV6 - r = find_ipv6_addr(argv[1], str_addr6, sizeof(str_addr6)); - if(r < 0) { - fprintf(stderr, "find_ipv6_addr() failed\n"); - return 1; - } else if(r == 0) { - printf("Interface %s has no IPv6 address.\n", argv[1]); - } else { - printf("Interface %s has IPv6 address %s.\n", argv[1], str_addr6); - } -#endif - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/testgetifaddr.sh b/src/contrib/miniupnp/miniupnpd/testgetifaddr.sh deleted file mode 100644 index 0ab012c..0000000 --- a/src/contrib/miniupnp/miniupnpd/testgetifaddr.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# $Id: testgetifaddr.sh,v 1.2 2015/09/22 14:48:09 nanard Exp $ - -OS=`uname -s` -case $OS in - FreeBSD | OpenBSD | Darwin | SunOS) - NS="`which netstat`" || exit 1 - IFCONFIG="`which ifconfig`" || exit 1 - EXTIF="`$NS -r -f inet | grep 'default' | awk '{ print $NF }' `" || exit 1 - EXTIP="`$IFCONFIG $EXTIF | awk '/inet / { print $2 }' `" - ;; - *) - IP="`which ip`" || exit 1 - EXTIF="`LC_ALL=C $IP -4 route | grep 'default' | sed -e 's/.*dev[[:space:]]*//' -e 's/[[:space:]].*//'`" || exit 1 - EXTIP="`LC_ALL=C $IP -4 addr show $EXTIF | awk '/inet/ { print $2 }' | cut -d "/" -f 1`" - ;; -esac - -#echo "Interface : $EXTIF IP address : $EXTIP" -RES=`./testgetifaddr $EXTIF | head -n1 | sed 's/Interface .* has IP address \(.*\)\./\1/'` || exit 1 - - -if [ "$RES" = "$EXTIP" ] ; then - echo "testgetifaddr test OK" - exit 0 -else - echo "testgetifaddr test FAILED : $EXTIP != $RES" - exit 1 -fi diff --git a/src/contrib/miniupnp/miniupnpd/testgetifstats.c b/src/contrib/miniupnp/miniupnpd/testgetifstats.c deleted file mode 100644 index 9c29b4e..0000000 --- a/src/contrib/miniupnp/miniupnpd/testgetifstats.c +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id: testgetifstats.c,v 1.5 2012/03/05 20:36:17 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "getifstats.h" - -#if defined(__sun) -/* solaris 10 does not define LOG_PERROR */ -#define LOG_PERROR 0 -#endif - -int -main(int argc, char **argv) -{ - int r; - struct ifdata data; - if(argc<2) - { - fprintf(stderr, "usage : %s \n", argv[0]); - return 1; - } - openlog("testgetifstats", LOG_CONS|LOG_PERROR, LOG_USER); - memset(&data, 0, sizeof(data)); - r = getifstats(argv[1], &data); - printf("getifstats() returned %d\n", r); - printf("stats for interface %s :\n", argv[1]); - printf("bitrate = %lu\n", data.baudrate); - printf(" input packets : %9lu\t input bytes : %9lu\n", - data.ipackets, data.ibytes); - printf("output packets : %9lu\toutput bytes : %9lu\n", - data.opackets, data.obytes); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/testgetroute.c b/src/contrib/miniupnp/miniupnpd/testgetroute.c deleted file mode 100644 index 61491be..0000000 --- a/src/contrib/miniupnp/miniupnpd/testgetroute.c +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id: testgetroute.c,v 1.7 2018/03/13 10:25:52 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include - -#include "getroute.h" -#include "upnputils.h" -#include "upnpglobalvars.h" - -#ifndef LOG_PERROR -/* solaris does not define LOG_PERROR */ -#define LOG_PERROR 0 -#endif - -struct lan_addr_list lan_addrs; -int runtime_flags = 0; -time_t startup_time = 0; - -int -main(int argc, char ** argv) -{ - struct sockaddr_in dst4; - struct sockaddr_in6 dst6; - struct sockaddr * dst; - void * src; - size_t src_len; - int r; - int index = -1; - - memset(&dst4, 0, sizeof(dst4)); - memset(&dst6, 0, sizeof(dst6)); - dst = NULL; - if(argc < 2) { - fprintf(stderr, "usage: %s \n", argv[0]); - fprintf(stderr, "both v4 and v6 IP addresses are supported.\n"); - return 1; - } - openlog("testgetroute", LOG_CONS|LOG_PERROR, LOG_USER); - r = inet_pton (AF_INET, argv[1], &dst4.sin_addr); - if(r < 0) { - syslog(LOG_ERR, "inet_pton(AF_INET, %s) : %m", argv[1]); - closelog(); - return 2; - } - if (r == 0) { - r = inet_pton (AF_INET6, argv[1], &dst6.sin6_addr); - if(r < 0) { - syslog(LOG_ERR, "inet_pton(AF_INET6, %s) : %m", argv[1]); - closelog(); - return 2; - } else if(r > 0) { - dst6.sin6_family = AF_INET6; - dst = (struct sockaddr *)&dst6; - src = &dst6.sin6_addr; - src_len = sizeof(dst6.sin6_addr); - } else { - /* r == 0 */ - syslog(LOG_ERR, "%s is not a correct IPv4 or IPv6 address", argv[1]); - closelog(); - return 1; - } - } else { - dst4.sin_family = AF_INET; - dst = (struct sockaddr *)&dst4; - src = &dst4.sin_addr; - src_len = sizeof(dst4.sin_addr); - } - - if (dst) { - syslog(LOG_DEBUG, "calling get_src_for_route_to(%p, NULL, NULL, %p)", - dst, &index); - r = get_src_for_route_to (dst, NULL, NULL, &index); - syslog(LOG_DEBUG, "get_src_for_route_to() returned %d", r); - if(r >= 0) { - syslog(LOG_DEBUG, "index=%d", index); - } - syslog(LOG_DEBUG, "calling get_src_for_route_to(%p, %p, %p(%u), %p)", - dst, src, &src_len, (unsigned)src_len, &index); - r = get_src_for_route_to (dst, src, &src_len, &index); - syslog(LOG_DEBUG, "get_src_for_route_to() returned %d", r); - if(r >= 0) { - char src_str[128]; - sockaddr_to_string(dst, src_str, sizeof(src_str)); - syslog(LOG_DEBUG, "src=%s", src_str); - syslog(LOG_DEBUG, "index=%d", index); - } - } - closelog(); - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/testminissdp.c b/src/contrib/miniupnp/miniupnpd/testminissdp.c deleted file mode 100644 index fffadb1..0000000 --- a/src/contrib/miniupnp/miniupnpd/testminissdp.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id: testminissdp.c,v 1.3 2018/01/15 16:46:48 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2017-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "minissdp.h" -#include "upnpglobalvars.h" - -void test(const char * buffer, size_t n) -{ - int s = 0; - struct sockaddr_in dummy_sender; - - memset(&dummy_sender, 0, sizeof(dummy_sender)); - dummy_sender.sin_family = AF_INET; - - ProcessSSDPData(s, buffer, n, - (struct sockaddr *)&dummy_sender, 0, -#ifdef ENABLE_HTTPS - 80, 443 -#else - 80 -#endif - ); - -} - -int main(int argc, char * * argv) -{ - FILE * f = NULL; - char buffer[1500]; - size_t n = 0; - struct lan_addr_s * lan_addr; - - if((argc > 1) && ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0))) { - fprintf(stderr, "Usage:\t%s [file]\nIf no file is specified, the program is reading the standard input.\n", argv[0]); - return 1; - } - openlog("testminissdp", LOG_CONS|LOG_PERROR, LOG_USER); - - /* populate lan_addrs */ - LIST_INIT(&lan_addrs); - lan_addr = (struct lan_addr_s *) malloc(sizeof(struct lan_addr_s)); - memset(lan_addr, 0, sizeof(struct lan_addr_s)); - LIST_INSERT_HEAD(&lan_addrs, lan_addr, list); - - if(argc > 1) { - f = fopen(argv[1], "rb"); - if(f == NULL) { - syslog(LOG_ERR, "error opening file %s", argv[1]); - return 1; - } - } - n = fread(buffer, 1, sizeof(buffer), f ? f : stdin); - if(n <= 0) { - syslog(LOG_ERR, "error reading"); - return 1; - } - - test(buffer, n); - - if(f) fclose(f); - /* free memory */ - while(lan_addrs.lh_first != NULL) - { - lan_addr = lan_addrs.lh_first; - LIST_REMOVE(lan_addrs.lh_first, list); - free(lan_addr); - } - - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/testportinuse.c b/src/contrib/miniupnp/miniupnpd/testportinuse.c deleted file mode 100644 index 48504bc..0000000 --- a/src/contrib/miniupnp/miniupnpd/testportinuse.c +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: testportinuse.c,v 1.3 2014/03/28 12:13:17 nanard Exp $ */ -/* MiniUPnP project - * (c) 2014 Thomas Bernard - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "portinuse.h" - -#ifdef USE_NETFILTER -const char * miniupnpd_nat_chain = "MINIUPNPD"; -const char * miniupnpd_nat_postrouting_chain = "MINIUPNPD-POSTROUTING"; -const char * miniupnpd_forward_chain = "MINIUPNPD"; -#endif /* USE_NETFILTER */ - -int main(int argc, char * * argv) -{ -#ifndef CHECK_PORTINUSE - UNUSED(argc); UNUSED(argv); - printf("CHECK_PORTINUSE is not defined.\n"); -#else /* CHECK_PORTINUSE */ - int r; - const char * if_name; - unsigned eport; - int proto; - const char * iaddr; - unsigned iport; - - if(argc <= 5) { - fprintf(stderr, "usage: %s if_name eport (tcp|udp) iaddr iport\n", - argv[0]); - return 1; - } - openlog("testportinuse", LOG_CONS|LOG_PERROR, LOG_USER); - if_name = argv[1]; - eport = (unsigned)atoi(argv[2]); - proto = (0==strcmp(argv[3], "tcp"))?IPPROTO_TCP:IPPROTO_UDP; - iaddr = argv[4]; - iport = (unsigned)atoi(argv[5]); - - r = port_in_use(if_name, eport, proto, iaddr, iport); - printf("port_in_use(%s, %u, %d, %s, %u) returned %d\n", - if_name, eport, proto, iaddr, iport, r); - closelog(); -#endif /* CHECK_PORTINUSE */ - return 0; -} diff --git a/src/contrib/miniupnp/miniupnpd/testssdppktgen.c b/src/contrib/miniupnp/miniupnpd/testssdppktgen.c deleted file mode 100644 index 5de7998..0000000 --- a/src/contrib/miniupnp/miniupnpd/testssdppktgen.c +++ /dev/null @@ -1,100 +0,0 @@ -/* $Id: $ */ -#include -#include -#include - -#include "config.h" -#include "miniupnpdpath.h" -#include "upnphttp.h" -#include "macros.h" - -#define SSDP_PORT 1900 - -char uuidvalue_igd[] = "uuid:12345678-0000-0000-0000-000000abcd01"; -unsigned upnp_bootid; -unsigned upnp_configid; - -static int -MakeSSDPPacket(const char * dest_str, - const char * host, unsigned short http_port, -#ifdef ENABLE_HTTPS - unsigned short https_port, -#endif - const char * nt, const char * suffix, - const char * usn1, const char * usn2, const char * usn3, - unsigned int lifetime) -{ - char bufr[SSDP_PACKET_MAX_LEN]; - int l; - - l = snprintf(bufr, sizeof(bufr), - "NOTIFY * HTTP/1.1\r\n" - "HOST: %s:%d\r\n" - "CACHE-CONTROL: max-age=%u\r\n" - "LOCATION: http://%s:%u" ROOTDESC_PATH "\r\n" -#ifdef ENABLE_HTTPS - "SECURELOCATION.UPNP.ORG: https://%s:%u" ROOTDESC_PATH "\r\n" -#endif - "SERVER: " MINIUPNPD_SERVER_STRING "\r\n" - "NT: %s%s\r\n" - "USN: %s%s%s%s\r\n" - "NTS: ssdp:alive\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" /* UDA v1.1 */ - "01-NLS: %u\r\n" /* same as BOOTID field. UDA v1.1 */ - "BOOTID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "CONFIGID.UPNP.ORG: %u\r\n" /* UDA v1.1 */ - "\r\n", - dest_str, SSDP_PORT, /* HOST: */ - lifetime, /* CACHE-CONTROL: */ - host, (unsigned int)http_port, /* LOCATION: */ -#ifdef ENABLE_HTTPS - host, (unsigned int)https_port, /* SECURE-LOCATION: */ -#endif - nt, suffix, /* NT: */ - usn1, usn2, usn3, suffix, /* USN: */ - upnp_bootid, /* 01-NLS: */ - upnp_bootid, /* BOOTID.UPNP.ORG: */ - upnp_configid ); /* CONFIGID.UPNP.ORG: */ - if(l<0) { - syslog(LOG_ERR, "%s: snprintf error", "MakeSSDPPacket()"); - return -1; - } else if((unsigned int)l >= sizeof(bufr)) { - syslog(LOG_WARNING, "%s: truncated output (%u>=%u)", - "MakeSSDPPacket()", (unsigned)l, (unsigned)sizeof(bufr)); - l = sizeof(bufr) - 1; - return -1; - } - return 0; -} - - -int main(int argc, char * * argv) -{ - int r; - UNUSED(argc); UNUSED(argv); - - openlog("testssdppktgen", LOG_CONS|LOG_PERROR, LOG_USER); - upnp_bootid = (unsigned)time(NULL); - upnp_configid = 1234567890; - r = MakeSSDPPacket("123.456.789.123", "222.222.222.222", 12345, -#ifdef ENABLE_HTTPS - 54321, -#endif /* ENABLE_HTTPS */ - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", "1", - uuidvalue_igd, "", "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", - 1234567890); - if(r < 0) return 1; -#ifdef ENABLE_IPV6 - r = MakeSSDPPacket("[1234:5678:abcd:ef00:1234:5678:abcd:ef00]", - "[1000:2000:3000:4000:5000:6000:7000:8000]", 12345, -#ifdef ENABLE_HTTPS - 54321, -#endif /* ENABLE_HTTPS */ - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", "1", - uuidvalue_igd, "", "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:", - 1234567890); - if(r < 0) return 1; -#endif /* ENABLE_IPV6 */ - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/testupnpdescgen.c b/src/contrib/miniupnp/miniupnpd/testupnpdescgen.c deleted file mode 100644 index 5b88c2a..0000000 --- a/src/contrib/miniupnp/miniupnpd/testupnpdescgen.c +++ /dev/null @@ -1,267 +0,0 @@ -/* $Id: testupnpdescgen.c,v 1.34 2017/05/27 07:47:57 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -/* for mkdir */ -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "upnpglobalvars.h" -#include "upnpdescgen.h" -#include "upnpdescstrings.h" -#include "getifaddr.h" - -char uuidvalue_igd[] = "uuid:12345678-0000-0000-0000-000000abcd01"; -char uuidvalue_wan[] = "uuid:12345678-0000-0000-0000-000000abcd02"; -char uuidvalue_wcd[] = "uuid:12345678-0000-0000-0000-000000abcd03"; -char serialnumber[] = "12345678"; -char modelnumber[] = "1"; -char presentationurl[] = "http://192.168.0.1:8080/"; -/*char presentationurl[] = "";*/ -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION -char friendly_name[] = OS_NAME " router"; -char manufacturer_name[] = ROOTDEV_MANUFACTURER; -char manufacturer_url[] = ROOTDEV_MANUFACTURERURL; -char model_name[] = ROOTDEV_MODELNAME; -char model_description[] = ROOTDEV_MODELDESCRIPTION; -char model_url[] = ROOTDEV_MODELURL; -#endif /* ENABLE_MANUFACTURER_INFO_CONFIGURATION */ -#ifdef RANDOMIZE_URLS -char random_url[] = "RANDOM"; -#endif /* RANDOMIZE_URLS */ -unsigned int upnp_configid = 666; - -const char * use_ext_ip_addr = NULL; -const char * ext_if_name = "eth0"; - -int runtime_flags = 0; - -int getifaddr(const char * ifname, char * buf, int len, struct in_addr * addr, struct in_addr * mask) -{ - UNUSED(ifname); - UNUSED(addr); - UNUSED(mask); - strncpy(buf, "1.2.3.4", len); - return 0; -} - -int upnp_get_portmapping_number_of_entries(void) -{ - return 42; -} - -int get_wan_connection_status(const char * ifname) -{ - UNUSED(ifname); - return 2; -} - -/* To be improved */ -int -xml_pretty_print(const char * s, int len, FILE * f) -{ - int n = 0, i; - int elt_close = 0; - int c, indent = 0; - - if(!s) - return n; - while(len > 0) - { - c = *(s++); len--; - switch(c) - { - case '<': - if(len>0 && *s == '/') - elt_close++; - else if(len>0 && *s == '?') - elt_close = 1; - else - elt_close = 0; - if(elt_close!=1) - { - if(elt_close > 1) - indent--; - fputc('\n', f); n++; - for(i=indent; i>0; i--) - fputc(' ', f); - n += indent; - } - fputc(c, f); n++; - break; - case '>': - fputc(c, f); n++; - if(elt_close==1) - { - /*fputc('\n', f); n++; */ - /* elt_close = 0; */ - if(indent > 0) - indent--; - } - else if(elt_close == 0) - indent++; - break; - case '\n': - /* remove existing LF */ - break; - default: - fputc(c, f); n++; - } - } - return n; -} - -/* stupid test */ -const char * str1 = "Prefix123String"; -const char * str2 = "123String"; - -void stupid_test(void) -{ - printf("str1:'%s' str2:'%s'\n", str1, str2); - printf("str1:%p str2:%p str2-str1:%ld\n", str1, str2, (long)(str2-str1)); -} - -/* main */ - -int -main(int argc, char * * argv) -{ - char * rootDesc; - int rootDescLen; - char * s; - int l; - FILE * f; - - for(l = 1; l < argc; l++) { - if(0 == strcmp(argv[l], "--help") || 0 == strcmp(argv[l], "-h")) { - printf("Usage:\t%s [options]\n", argv[0]); - printf("options:\n"); -#ifdef IGD_V2 - printf("\t--forceigdv1 Force versions of devices to be 1\n"); -#else - printf("\tNone\n"); -#endif - return 0; -#ifdef IGD_V2 - } else if(0 == strcmp(argv[l], "--forceigdv1")) { - SETFLAG(FORCEIGDDESCV1MASK); -#endif - } else { - fprintf(stderr, "unknown option %s\n", argv[l]); - } - } - - if(mkdir("testdescs", 0777) < 0) { - if(errno != EEXIST) { - perror("mkdir"); - } - } - printf("Root Description :\n"); - rootDesc = genRootDesc(&rootDescLen); - xml_pretty_print(rootDesc, rootDescLen, stdout); - f = fopen("testdescs/rootdesc.xml", "w"); - if(f) { - xml_pretty_print(rootDesc, rootDescLen, f); - fclose(f); - } - free(rootDesc); - printf("\n-------------\n"); - printf("WANIPConnection Description :\n"); - s = genWANIPCn(&l); - xml_pretty_print(s, l, stdout); - f = fopen("testdescs/wanipc_scpd.xml", "w"); - if(f) { - xml_pretty_print(s, l, f); - fclose(f); - } - free(s); - printf("\n-------------\n"); - printf("WANConfig Description :\n"); - s = genWANCfg(&l); - xml_pretty_print(s, l, stdout); - f = fopen("testdescs/wanconfig_scpd.xml", "w"); - if(f) { - xml_pretty_print(s, l, f); - fclose(f); - } - free(s); - printf("\n-------------\n"); -#ifdef ENABLE_L3F_SERVICE - printf("Layer3Forwarding service :\n"); - s = genL3F(&l); - xml_pretty_print(s, l, stdout); - f = fopen("testdescs/l3f_scpd.xml", "w"); - if(f) { - xml_pretty_print(s, l, f); - fclose(f); - } - free(s); - printf("\n-------------\n"); -#endif -#ifdef ENABLE_6FC_SERVICE - printf("WANIPv6FirewallControl service :\n"); - s = gen6FC(&l); - xml_pretty_print(s, l, stdout); - f = fopen("testdescs/wanipv6fc_scpd.xml", "w"); - if(f) { - xml_pretty_print(s, l, f); - fclose(f); - } - free(s); - printf("\n-------------\n"); -#endif -#ifdef ENABLE_DP_SERVICE - printf("DeviceProtection service :\n"); - s = genDP(&l); - xml_pretty_print(s, l, stdout); - f = fopen("testdescs/dp_scpd.xml", "w"); - if(f) { - xml_pretty_print(s, l, f); - fclose(f); - } - free(s); - printf("\n-------------\n"); -#endif -#ifdef ENABLE_EVENTS - s = getVarsWANIPCn(&l); - xml_pretty_print(s, l, stdout); - free(s); - printf("\n-------------\n"); - s = getVarsWANCfg(&l); - xml_pretty_print(s, l, stdout); - free(s); - printf("\n-------------\n"); -#ifdef ENABLE_L3F_SERVICE - s = getVarsL3F(&l); - xml_pretty_print(s, l, stdout); - free(s); - printf("\n-------------\n"); -#ifdef ENABLE_6FC_SERVICE - s = getVars6FC(&l); - xml_pretty_print(s, l, stdout); - free(s); - printf("\n-------------\n"); -#endif -#ifdef ENABLE_DP_SERVICE - s = getVarsDP(&l); - xml_pretty_print(s, l, stdout); - free(s); - printf("\n-------------\n"); -#endif -#endif -#endif -/* - stupid_test(); -*/ - return 0; -} - diff --git a/src/contrib/miniupnp/miniupnpd/testupnppermissions.c b/src/contrib/miniupnp/miniupnpd/testupnppermissions.c deleted file mode 100644 index 16174c6..0000000 --- a/src/contrib/miniupnp/miniupnpd/testupnppermissions.c +++ /dev/null @@ -1,62 +0,0 @@ -/* $Id: testupnppermissions.c,v 1.3 2009/09/14 15:24:46 nanard Exp $ */ -/* (c) 2007-2015 Thomas Bernard - * MiniUPnP Project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - */ -#include -#include -#include -#include -#include -#include -#include -#include "upnppermissions.h" - -void -print_upnpperm(const struct upnpperm * p) -{ - switch(p->type) - { - case UPNPPERM_ALLOW: - printf("allow "); - break; - case UPNPPERM_DENY: - printf("deny "); - break; - default: - printf("error ! "); - } - printf("%hu-%hu ", p->eport_min, p->eport_max); - printf("%s/", inet_ntoa(p->address)); - printf("%s ", inet_ntoa(p->mask)); - printf("%hu-%hu", p->iport_min, p->iport_max); - putchar('\n'); -} - -int main(int argc, char * * argv) -{ - int i, r, ret; - struct upnpperm p; - if(argc < 2) { - fprintf(stderr, "Usage: %s \"permission line\" [...]\n", argv[0]); - fprintf(stderr, "Example: %s \"allow 1234 10.10.10.10/32 1234\"\n", argv[0]); - return 1; - } - openlog("testupnppermissions", LOG_PERROR, LOG_USER); - ret = 0; - for(i=1; i -#include -#include - -#include "config.h" -#ifdef ENABLE_EVENTS -#include "getifaddr.h" -#include "upnpredirect.h" -#endif -#include "upnpdescgen.h" -#include "miniupnpdpath.h" -#include "upnpglobalvars.h" -#include "upnpdescstrings.h" -#include "upnpurns.h" -#include "getconnstatus.h" - - -/* Event magical values codes */ -#define SETUPREADY_MAGICALVALUE (248) -#define CONNECTIONSTATUS_MAGICALVALUE (249) -#define FIREWALLENABLED_MAGICALVALUE (250) -#define INBOUNDPINHOLEALLOWED_MAGICALVALUE (251) -#define SYSTEMUPDATEID_MAGICALVALUE (252) -#define PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE (253) -#define EXTERNALIPADDRESS_MAGICALVALUE (254) -#define DEFAULTCONNECTIONSERVICE_MAGICALVALUE (255) - - -static const char * const upnptypes[] = -{ - "string", - "boolean", - "ui2", - "ui4", - "bin.base64" -}; - -static const char * const upnpdefaultvalues[] = -{ - 0, - "IP_Routed"/*"Unconfigured"*/, /* 1 default value for ConnectionType */ - "3600", /* 2 default value for PortMappingLeaseDuration */ - "Unconfigured", /* 3 default value for ConnectionStatus */ - "0", /* 4 default value for RSIPAvailable */ - "1", /* 5 default value for NATEnabled */ - "ERROR_NONE", /* 6 default value for LastConnectionError */ -}; - -static const char * const upnpallowedvalues[] = -{ - 0, /* 0 */ - "DSL", /* 1 */ - "POTS", - "Cable", - "Ethernet", - 0, - "Up", /* 6 */ - "Down", - "Initializing", - "Unavailable", - 0, - "TCP", /* 11 */ - "UDP", - 0, - "Unconfigured", /* 14 */ - "IP_Routed", - "IP_Bridged", - 0, - "Unconfigured", /* 18 */ - "Connecting", - "Connected", - "PendingDisconnect", - "Disconnecting", - "Disconnected", - 0, - "ERROR_NONE", /* 25 */ -/* Optionals values : - * ERROR_COMMAND_ABORTED - * ERROR_NOT_ENABLED_FOR_INTERNET - * ERROR_USER_DISCONNECT - * ERROR_ISP_DISCONNECT - * ERROR_IDLE_DISCONNECT - * ERROR_FORCED_DISCONNECT - * ERROR_NO_CARRIER - * ERROR_IP_CONFIGURATION - * ERROR_UNKNOWN */ - 0, - "", /* 27 */ - 0 -}; - -static const int upnpallowedranges[] = { - 0, - /* 1 PortMappingLeaseDuration */ - 0, - 604800, - /* 3 InternalPort */ - 1, - 65535, - /* 5 LeaseTime */ - 1, - 86400, - /* 7 OutboundPinholeTimeout */ - 100, - 200, -}; - -static const char * magicargname[] = { - 0, - "StartPort", /* 1 */ - "EndPort", /* 2 */ - "RemoteHost", /* 3 */ - "RemotePort", /* 4 */ - "InternalClient", /* 5 */ - "InternalPort", /* 6 */ - "IsWorking", /* 7 */ -#ifdef ENABLE_DP_SERVICE - "ProtocolType", /* 8 */ - "InMessage", /* 9 */ - "OutMessage", /* 10 */ - "ProtocolList", /* 11 */ - "RoleList", /* 12 */ -#endif /* ENABLE_DP_SERVICE */ -}; - -static const char xmlver[] = - "\r\n"; -static const char root_service[] = - "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\""; -static const char root_device[] = - "root xmlns=\"urn:schemas-upnp-org:device-1-0\""; - -/* root Description of the UPnP Device - * fixed to match UPnP_IGD_InternetGatewayDevice 1.0.pdf - * Needs to be checked with UPnP-gw-InternetGatewayDevice-v2-Device.pdf - * presentationURL is only "recommended" but the router doesn't appears - * in "Network connections" in Windows XP if it is not present. */ -static const struct XMLElt rootDesc[] = -{ -/* 0 */ - {root_device, INITHELPER(1,2)}, - {"specVersion", INITHELPER(3,2)}, -#if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE) || defined(ENABLE_DP_SERVICE) - {"device", INITHELPER(5,13)}, -#else - {"device", INITHELPER(5,12)}, -#endif - {"/major", UPNP_VERSION_MAJOR_STR}, - {"/minor", UPNP_VERSION_MINOR_STR}, -/* 5 */ - {"/deviceType", DEVICE_TYPE_IGD}, - /* urn:schemas-upnp-org:device:InternetGatewayDevice:1 or 2 */ -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION - {"/friendlyName", friendly_name/*ROOTDEV_FRIENDLYNAME*/}, /* required */ - {"/manufacturer", manufacturer_name/*ROOTDEV_MANUFACTURER*/}, /* required */ -/* 8 */ - {"/manufacturerURL", manufacturer_url/*ROOTDEV_MANUFACTURERURL*/}, /* optional */ - {"/modelDescription", model_description/*ROOTDEV_MODELDESCRIPTION*/}, /* recommended */ - {"/modelName", model_name/*ROOTDEV_MODELNAME*/}, /* required */ - {"/modelNumber", modelnumber}, - {"/modelURL", model_url/*ROOTDEV_MODELURL*/}, -#else - {"/friendlyName", ROOTDEV_FRIENDLYNAME}, /* required */ - {"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */ -/* 8 */ - {"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */ - {"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */ - {"/modelName", ROOTDEV_MODELNAME}, /* required */ - {"/modelNumber", modelnumber}, - {"/modelURL", ROOTDEV_MODELURL}, -#endif - {"/serialNumber", serialnumber}, - {"/UDN", uuidvalue_igd}, /* required */ - /* see if /UPC is needed. */ -#ifdef ENABLE_6FC_SERVICE -#define SERVICES_OFFSET 63 -#else -#define SERVICES_OFFSET 58 -#endif -#if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE) || defined(ENABLE_DP_SERVICE) - /* here we dening Services for the root device : - * L3F and DUMMY and DeviceProtection */ -#ifdef ENABLE_L3F_SERVICE -#define NSERVICES1 1 -#else -#define NSERVICES1 0 -#endif -#ifdef HAS_DUMMY_SERVICE -#define NSERVICES2 1 -#else -#define NSERVICES2 0 -#endif -#ifdef ENABLE_DP_SERVICE -#define NSERVICES3 1 -#else -#define NSERVICES3 0 -#endif -#define NSERVICES (NSERVICES1+NSERVICES2+NSERVICES3) - {"serviceList", INITHELPER(SERVICES_OFFSET,NSERVICES)}, - {"deviceList", INITHELPER(18,1)}, - {"/presentationURL", presentationurl}, /* recommended */ -#else - {"deviceList", INITHELPER(18,1)}, - {"/presentationURL", presentationurl}, /* recommended */ - {0,0}, -#endif -/* 18 */ - {"device", INITHELPER(19,13)}, -/* 19 */ - {"/deviceType", DEVICE_TYPE_WAN}, /* required */ - /* urn:schemas-upnp-org:device:WANDevice:1 or 2 */ - {"/friendlyName", WANDEV_FRIENDLYNAME}, - {"/manufacturer", WANDEV_MANUFACTURER}, - {"/manufacturerURL", WANDEV_MANUFACTURERURL}, - {"/modelDescription" , WANDEV_MODELDESCRIPTION}, - {"/modelName", WANDEV_MODELNAME}, - {"/modelNumber", WANDEV_MODELNUMBER}, - {"/modelURL", WANDEV_MODELURL}, - {"/serialNumber", serialnumber}, - {"/UDN", uuidvalue_wan}, - {"/UPC", WANDEV_UPC}, /* UPC (=12 digit barcode) is optional */ -/* 30 */ - {"serviceList", INITHELPER(32,1)}, - {"deviceList", INITHELPER(38,1)}, -/* 32 */ - {"service", INITHELPER(33,5)}, -/* 33 */ - {"/serviceType", - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"}, - /*{"/serviceId", "urn:upnp-org:serviceId:WANCommonInterfaceConfig"}, */ - {"/serviceId", "urn:upnp-org:serviceId:WANCommonIFC1"}, /* required */ - {"/SCPDURL", WANCFG_PATH}, - {"/controlURL", WANCFG_CONTROLURL}, - {"/eventSubURL", WANCFG_EVENTURL}, -/* 38 */ - {"device", INITHELPER(39,12)}, -/* 39 */ - {"/deviceType", DEVICE_TYPE_WANC}, - /* urn:schemas-upnp-org:device:WANConnectionDevice:1 or 2 */ - {"/friendlyName", WANCDEV_FRIENDLYNAME}, - {"/manufacturer", WANCDEV_MANUFACTURER}, - {"/manufacturerURL", WANCDEV_MANUFACTURERURL}, - {"/modelDescription", WANCDEV_MODELDESCRIPTION}, - {"/modelName", WANCDEV_MODELNAME}, - {"/modelNumber", WANCDEV_MODELNUMBER}, - {"/modelURL", WANCDEV_MODELURL}, - {"/serialNumber", serialnumber}, - {"/UDN", uuidvalue_wcd}, - {"/UPC", WANCDEV_UPC}, /* UPC (=12 digit Barcode) is optional */ -#ifdef ENABLE_6FC_SERVICE - {"serviceList", INITHELPER(51,2)}, -#else - {"serviceList", INITHELPER(51,1)}, -#endif -/* 51 */ - {"service", INITHELPER(53,5)}, - {"service", INITHELPER(58,5)}, -/* 53 */ - {"/serviceType", SERVICE_TYPE_WANIPC}, - /* urn:schemas-upnp-org:service:WANIPConnection:2 for v2 */ - {"/serviceId", SERVICE_ID_WANIPC}, - /* urn:upnp-org:serviceId:WANIPConn1 or 2 */ - {"/SCPDURL", WANIPC_PATH}, - {"/controlURL", WANIPC_CONTROLURL}, - {"/eventSubURL", WANIPC_EVENTURL}, -#ifdef ENABLE_6FC_SERVICE -/* 58 */ - {"/serviceType", "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"}, - {"/serviceId", "urn:upnp-org:serviceId:WANIPv6Firewall1"}, - {"/SCPDURL", WANIP6FC_PATH}, - {"/controlURL", WANIP6FC_CONTROLURL}, - {"/eventSubURL", WANIP6FC_EVENTURL}, -#endif -/* 58 / 63 = SERVICES_OFFSET*/ -#if defined(HAS_DUMMY_SERVICE) || defined(ENABLE_L3F_SERVICE) || defined(ENABLE_DP_SERVICE) - {"service", INITHELPER(SERVICES_OFFSET+2,5)}, - {"service", INITHELPER(SERVICES_OFFSET+7,5)}, -#endif -#ifdef HAS_DUMMY_SERVICE -/* 60 / 65 = SERVICES_OFFSET+2 */ - {"/serviceType", "urn:schemas-dummy-com:service:Dummy:1"}, - {"/serviceId", "urn:dummy-com:serviceId:dummy1"}, - {"/SCPDURL", DUMMY_PATH}, - {"/controlURL", "/dummy"}, - {"/eventSubURL", "/dummy"}, -#endif -#ifdef ENABLE_L3F_SERVICE -/* 60 / 65 = SERVICES_OFFSET+2 */ - {"/serviceType", "urn:schemas-upnp-org:service:Layer3Forwarding:1"}, - {"/serviceId", "urn:upnp-org:serviceId:L3Forwarding1"}, - {"/SCPDURL", L3F_PATH}, - {"/controlURL", L3F_CONTROLURL}, /* The Layer3Forwarding service is only */ - {"/eventSubURL", L3F_EVENTURL}, /* recommended, not mandatory */ -#endif -#ifdef ENABLE_DP_SERVICE -/* InternetGatewayDevice v2 : - * it is RECOMMEDED that DeviceProtection service is implemented and applied. - * If DeviceProtection is not implemented and applied, it is RECOMMENDED - * that control points are able to access only actions and parameters defined - * as Public role. */ -/* 65 / 70 = SERVICES_OFFSET+7 */ - {"/serviceType", "urn:schemas-upnp-org:service:DeviceProtection:1"}, - {"/serviceId", "urn:upnp-org:serviceId:DeviceProtection1"}, - {"/SCPDURL", DP_PATH}, - {"/controlURL", DP_CONTROLURL}, - {"/eventSubURL", DP_EVENTURL}, -#endif - {0, 0} -}; - -/* WANIPCn.xml */ -/* see UPnP_IGD_WANIPConnection 1.0.pdf -static struct XMLElt scpdWANIPCn[] = -{ - {root_service, {INITHELPER(1,2)}}, - {0, {0}} -}; -*/ -static const struct argument AddPortMappingArgs[] = -{ - {1, 11}, /* RemoteHost */ - {1, 12}, /* ExternalPort */ - {1, 14}, /* PortMappingProtocol */ - {1, 13}, /* InternalPort */ - {1, 15}, /* InternalClient */ - {1, 9}, /* PortMappingEnabled */ - {1, 16}, /* PortMappingDescription */ - {1, 10}, /* PortMappingLeaseDuration */ - {0, 0} -}; - -#ifdef IGD_V2 -static const struct argument AddAnyPortMappingArgs[] = -{ - {1, 11}, /* RemoteHost */ - {1, 12}, /* ExternalPort */ - {1, 14}, /* PortMappingProtocol */ - {1, 13}, /* InternalPort */ - {1, 15}, /* InternalClient */ - {1, 9}, /* PortMappingEnabled */ - {1, 16}, /* PortMappingDescription */ - {1, 10}, /* PortMappingLeaseDuration */ - {2, 12}, /* NewReservedPort / ExternalPort */ - {0, 0} -}; - -static const struct argument DeletePortMappingRangeArgs[] = -{ - {1|(1<<2), 12}, /* NewStartPort / ExternalPort */ - {1|(2<<2), 12}, /* NewEndPort / ExternalPort */ - {1, 14}, /* NewProtocol / PortMappingProtocol */ - {1, 18}, /* NewManage / A_ARG_TYPE_Manage */ - {0, 0} -}; - -static const struct argument GetListOfPortMappingsArgs[] = -{ - {1|(1<<2), 12}, /* NewStartPort / ExternalPort */ - {1|(2<<2), 12}, /* NewEndPort / ExternalPort */ - {1, 14}, /* NewProtocol / PortMappingProtocol */ - {1, 18}, /* NewManage / A_ARG_TYPE_Manage */ - {1, 8}, /* NewNumberOfPorts / PortMappingNumberOfEntries */ - {2, 19}, /* NewPortListing / A_ARG_TYPE_PortListing */ - {0, 0} -}; -#endif - -static const struct argument GetExternalIPAddressArgs[] = -{ - {2, 7}, - {0, 0} -}; - -static const struct argument DeletePortMappingArgs[] = -{ - {1, 11}, /* RemoteHost */ - {1, 12}, /* ExternalPort */ - {1, 14}, /* PortMappingProtocol */ - {0, 0} -}; - -static const struct argument SetConnectionTypeArgs[] = -{ - {1, 0}, - {0, 0} -}; - -static const struct argument GetConnectionTypeInfoArgs[] = -{ - {2, 0}, - {2, 1}, - {0, 0} -}; - -static const struct argument GetStatusInfoArgs[] = -{ - {2, 2}, - {2, 4}, - {2, 3}, - {0, 0} -}; - -static const struct argument GetNATRSIPStatusArgs[] = -{ - {2, 5}, - {2, 6}, - {0, 0} -}; - -static const struct argument GetGenericPortMappingEntryArgs[] = -{ - {1, 8}, - {2, 11}, - {2, 12}, - {2, 14}, - {2, 13}, - {2, 15}, - {2, 9}, - {2, 16}, - {2, 10}, - {0, 0} -}; - -static const struct argument GetSpecificPortMappingEntryArgs[] = -{ - {1, 11}, - {1, 12}, - {1, 14}, - {2, 13}, - {2, 15}, - {2, 9}, - {2, 16}, - {2, 10}, - {0, 0} -}; - -static const struct action WANIPCnActions[] = -{ - {"SetConnectionType", SetConnectionTypeArgs}, /* R */ - {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */ - {"RequestConnection", 0}, /* R */ - /*{"RequestTermination", 0},*/ /* O */ - {"ForceTermination", 0}, /* R */ - /*{"SetAutoDisconnectTime", 0},*/ /* O */ - /*{"SetIdleDisconnectTime", 0},*/ /* O */ - /*{"SetWarnDisconnectDelay", 0}, */ /* O */ - {"GetStatusInfo", GetStatusInfoArgs}, /* R */ - /*GetAutoDisconnectTime*/ /* O */ - /*GetIdleDisconnectTime*/ /* O */ - /*GetWarnDisconnectDelay*/ /* O */ - {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */ - {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */ - {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */ - {"AddPortMapping", AddPortMappingArgs}, /* R */ - {"DeletePortMapping", DeletePortMappingArgs}, /* R */ - {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */ -#ifdef IGD_V2 - {"DeletePortMappingRange", DeletePortMappingRangeArgs}, /* R, IGD v2 */ - {"GetListOfPortMappings", GetListOfPortMappingsArgs}, /* R, IGD v2 */ - {"AddAnyPortMapping", AddAnyPortMappingArgs}, /* R, IGD v2 */ -#endif -#if 0 - {"AddPortMapping", AddPortMappingArgs}, /* R */ - {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */ - {"DeletePortMapping", DeletePortMappingArgs}, /* R */ - {"SetConnectionType", SetConnectionTypeArgs}, /* R */ - {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */ - {"RequestConnection", 0}, /* R */ - {"ForceTermination", 0}, /* R */ - {"GetStatusInfo", GetStatusInfoArgs}, /* R */ - {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */ - {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */ - {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */ -/* added in v2 UPnP-gw-WANIPConnection-v2-Service.pdf */ -#ifdef IGD_V2 - {"AddAnyPortMapping", AddAnyPortMappingArgs}, - {"DeletePortMappingRange", DeletePortMappingRangeArgs}, - {"GetListOfPortMappings", GetListOfPortMappingsArgs}, -#endif -#endif - {0, 0} -}; -/* R=Required, O=Optional */ - -/* ignore "warning: missing initializer" */ -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" - -/* struct stateVar : - * {name, itype(&event), idefault, iallowedlist, ieventvalue} */ -static const struct stateVar WANIPCnVars[] = -{ -/* 0 */ -#if 0 - {"ConnectionType", 0, 0/*1*/}, /* required */ - {"PossibleConnectionTypes", 0|0x80, 0, 14, 15}, -#elif 0 - {"ConnectionType", 0, 1, 14, 15}, /* required */ - {"PossibleConnectionTypes", 0|0x80, 0, 0, 15}, -#else - {"ConnectionType", 0, 1, 0, 15}, /* required */ - {"PossibleConnectionTypes", 0|0x80, 0, 14, 15}, -#endif - /* Required - * Allowed values : Unconfigured / IP_Routed / IP_Bridged */ - {"ConnectionStatus", 0|0x80, 3, 18, - CONNECTIONSTATUS_MAGICALVALUE }, /* required */ - /* Allowed Values : Unconfigured / Connecting(opt) / Connected - * PendingDisconnect(opt) / Disconnecting (opt) - * Disconnected */ - {"Uptime", 3, 0}, /* Required */ - {"LastConnectionError", 0, 6, 25}, /* required : */ - /* Allowed Values : ERROR_NONE(req) / ERROR_COMMAND_ABORTED(opt) - * ERROR_NOT_ENABLED_FOR_INTERNET(opt) - * ERROR_USER_DISCONNECT(opt) - * ERROR_ISP_DISCONNECT(opt) - * ERROR_IDLE_DISCONNECT(opt) - * ERROR_FORCED_DISCONNECT(opt) - * ERROR_NO_CARRIER(opt) - * ERROR_IP_CONFIGURATION(opt) - * ERROR_UNKNOWN(opt) */ - {"RSIPAvailable", 1, 4}, /* required */ - {"NATEnabled", 1, 5}, /* required */ - {"ExternalIPAddress", 0|0x80, 0, 0, - EXTERNALIPADDRESS_MAGICALVALUE}, /* required. Default : empty string */ - {"PortMappingNumberOfEntries", 2|0x80, 0, 0, - PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE}, /* required >= 0 */ - {"PortMappingEnabled", 1, 0}, /* Required */ -/* 10 */ - {"PortMappingLeaseDuration", 3, 2, 1}, /* required */ - {"RemoteHost", 0, 0}, /* required. Default : empty string */ - {"ExternalPort", 2, 0}, /* required */ - {"InternalPort", 2, 0, 3}, /* required */ - {"PortMappingProtocol", 0, 0, 11}, /* required allowedValues: TCP/UDP */ - {"InternalClient", 0, 0}, /* required */ - {"PortMappingDescription", 0, 0}, /* required default: empty string */ -/* added in v2 UPnP-gw-WANIPConnection-v2-Service.pdf */ -#ifdef IGD_V2 - {"SystemUpdateID", 3|0x80, 0, 0, SYSTEMUPDATEID_MAGICALVALUE}, - {"A_ARG_TYPE_Manage", 1, 0}, - {"A_ARG_TYPE_PortListing", 0, 0}, -#endif - {0, 0} -}; - -static const struct serviceDesc scpdWANIPCn = -{ WANIPCnActions, WANIPCnVars }; - -/* WANCfg.xml */ -/* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */ - -static const struct argument GetCommonLinkPropertiesArgs[] = -{ - {2, 0}, - {2, 1}, - {2, 2}, - {2, 3}, - {0, 0} -}; - -static const struct argument GetTotalBytesSentArgs[] = -{ - {2, 4}, - {0, 0} -}; - -static const struct argument GetTotalBytesReceivedArgs[] = -{ - {2, 5}, - {0, 0} -}; - -static const struct argument GetTotalPacketsSentArgs[] = -{ - {2, 6}, - {0, 0} -}; - -static const struct argument GetTotalPacketsReceivedArgs[] = -{ - {2, 7}, - {0, 0} -}; - -static const struct action WANCfgActions[] = -{ - {"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */ - {"GetTotalBytesSent", GetTotalBytesSentArgs}, /* optional */ - {"GetTotalBytesReceived", GetTotalBytesReceivedArgs}, /* optional */ - {"GetTotalPacketsSent", GetTotalPacketsSentArgs}, /* optional */ - {"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */ - {0, 0} -}; - -/* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */ -static const struct stateVar WANCfgVars[] = -{ - {"WANAccessType", 0, 0, 1}, - /* Allowed Values : DSL / POTS / Cable / Ethernet - * Default value : empty string */ - {"Layer1UpstreamMaxBitRate", 3, 0}, - {"Layer1DownstreamMaxBitRate", 3, 0}, - {"PhysicalLinkStatus", 0|0x80, 0, 6, 6}, - /* allowed values : - * Up / Down / Initializing (optional) / Unavailable (optionnal) - * no Default value - * Evented */ - {"TotalBytesSent", 3, 0}, /* Optional */ - {"TotalBytesReceived", 3, 0}, /* Optional */ - {"TotalPacketsSent", 3, 0}, /* Optional */ - {"TotalPacketsReceived", 3, 0},/* Optional */ - /*{"MaximumActiveConnections", 2, 0}, // allowed Range value // OPTIONAL */ - /*{"WANAccessProvider", 0, 0},*/ /* Optional */ - {0, 0} -}; - -static const struct serviceDesc scpdWANCfg = -{ WANCfgActions, WANCfgVars }; - -#ifdef ENABLE_L3F_SERVICE -/* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */ -static const struct argument SetDefaultConnectionServiceArgs[] = -{ - {1, 0}, /* in */ - {0, 0} -}; - -static const struct argument GetDefaultConnectionServiceArgs[] = -{ - {2, 0}, /* out */ - {0, 0} -}; - -static const struct action L3FActions[] = -{ - {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */ - {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */ - {0, 0} -}; - -static const struct stateVar L3FVars[] = -{ - {"DefaultConnectionService", 0|0x80, 0, 0, - DEFAULTCONNECTIONSERVICE_MAGICALVALUE}, /* Required */ - {0, 0} -}; - -static const struct serviceDesc scpdL3F = -{ L3FActions, L3FVars }; -#endif - -#ifdef ENABLE_6FC_SERVICE -/* see UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */ -static const struct argument GetFirewallStatusArgs[] = -{ - {2|0x80, 0}, /* OUT : FirewallEnabled */ - {2|0x80, 6}, /* OUT : InboundPinholeAllowed */ - {0, 0} -}; - -static const struct argument GetOutboundPinholeTimeoutArgs[] = -{ - {1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */ - {1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */ - {1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */ - {1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */ - {1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */ - {2|0x80, 7}, /* OutboundPinholeTimeout OUT A_ARG_TYPE_OutboundPinholeTimeout */ - {0, 0} -}; - -static const struct argument AddPinholeArgs[] = -{ - {1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */ - {1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */ - {1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */ - {1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */ - {1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */ - {1|0x80, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */ - {2|0x80, 4}, /* UniqueID OUT A_ARG_TYPE_UniqueID */ - {0, 0} -}; - -static const struct argument UpdatePinholeArgs[] = -{ - {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */ - {1, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */ - {0, 0} -}; - -static const struct argument DeletePinholeArgs[] = -{ - {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */ - {0, 0} -}; - -static const struct argument GetPinholePacketsArgs[] = -{ - {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */ - {2|0x80, 9}, /* PinholePackets OUT A_ARG_TYPE_PinholePackets */ - {0, 0} -}; - -static const struct argument CheckPinholeWorkingArgs[] = -{ - {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */ - {2|0x80|(7<<2), 8}, /* IsWorking OUT A_ARG_TYPE_Boolean */ - {0, 0} -}; - -static const struct action IPv6FCActions[] = -{ - {"GetFirewallStatus", GetFirewallStatusArgs}, /* Req */ - {"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs}, /* Opt */ - {"AddPinhole", AddPinholeArgs}, /* Req */ - {"UpdatePinhole", UpdatePinholeArgs}, /* Req */ - {"DeletePinhole", DeletePinholeArgs}, /* Req */ - {"GetPinholePackets", GetPinholePacketsArgs}, /* Req */ - {"CheckPinholeWorking", CheckPinholeWorkingArgs}, /* Opt */ - {0, 0} -}; - -static const struct stateVar IPv6FCVars[] = -{ - {"FirewallEnabled", 1|0x80, 0, 0, - FIREWALLENABLED_MAGICALVALUE}, /* Required */ - {"A_ARG_TYPE_IPv6Address", 0, 0, 0, 0}, /* Required */ - {"A_ARG_TYPE_Port", 2, 0, 0, 0}, /* Required */ - {"A_ARG_TYPE_Protocol", 2, 0, 0, 0}, /* Required */ -/* 4 */ - {"A_ARG_TYPE_UniqueID", 2, 0, 0, 0}, /* Required */ - {"A_ARG_TYPE_LeaseTime", 3, 0, 5, 0}, /* Required */ - {"InboundPinholeAllowed", 1|0x80, 0, 0, - INBOUNDPINHOLEALLOWED_MAGICALVALUE}, /* Required */ - {"A_ARG_TYPE_OutboundPinholeTimeout", 3, 0, 7, 0}, /* Optional */ -/* 8 */ - {"A_ARG_TYPE_Boolean", 1, 0, 0, 0}, /* Optional */ - {"A_ARG_TYPE_PinholePackets", 3, 0, 0, 0}, /* Required */ - {0, 0} -}; - -static const struct serviceDesc scpd6FC = -{ IPv6FCActions, IPv6FCVars }; -#endif - -#ifdef ENABLE_DP_SERVICE -/* UPnP-gw-DeviceProtection-v1-Service.pdf */ - -static const struct argument SendSetupMessageArgs[] = -{ - {1|0x80|(8<<2), 6}, /* ProtocolType : in ProtocolType / A_ARG_TYPE_String */ - {1|0x80|(9<<2), 5}, /* InMessage : in InMessage / A_ARG_TYPE_Base64 */ - {2|0x80|(10<<2), 5}, /* OutMessage : out OutMessage / A_ARG_TYPE_Base64 */ - {0, 0} -}; - -static const struct argument GetSupportedProtocolsArgs[] = -{ - {2|0x80|(11<<2), 1}, /* ProtocolList : out ProtocolList / SupportedProtocols */ - {0, 0} -}; - -static const struct argument GetAssignedRolesArgs[] = -{ - {2|0x80|(12<<2), 6}, /* RoleList : out RoleList / A_ARG_TYPE_String */ - {0, 0} -}; - -static const struct action DPActions[] = -{ - {"SendSetupMessage", SendSetupMessageArgs}, - {"GetSupportedProtocols", GetSupportedProtocolsArgs}, - {"GetAssignedRoles", GetAssignedRolesArgs}, - {0, 0} -}; - -static const struct stateVar DPVars[] = -{ - {"SetupReady", 1|0x80, 0, 0, SETUPREADY_MAGICALVALUE}, - {"SupportedProtocols", 0}, - {"A_ARG_TYPE_ACL", 0}, - {"A_ARG_TYPE_IdentityList", 0}, - {"A_ARG_TYPE_Identity", 0}, - {"A_ARG_TYPE_Base64", 4}, - {"A_ARG_TYPE_String", 0}, - {0, 0} -}; - -static const struct serviceDesc scpdDP = -{ DPActions, DPVars }; -#endif - -/* strcat_str() - * concatenate the string and use realloc to increase the - * memory buffer if needed. */ -static char * -strcat_str(char * str, int * len, int * tmplen, const char * s2) -{ - int s2len; - int newlen; - char * p; - - s2len = (int)strlen(s2); - if(*tmplen <= (*len + s2len)) - { - if(s2len < 256) - newlen = *tmplen + 256; - else - newlen = *tmplen + s2len + 1; - p = (char *)realloc(str, newlen); - if(p == NULL) /* handle a failure of realloc() */ - return str; - str = p; - *tmplen = newlen; - } - /*strcpy(str + *len, s2); */ - memcpy(str + *len, s2, s2len + 1); - *len += s2len; - return str; -} - -/* strcat_char() : - * concatenate a character and use realloc to increase the - * size of the memory buffer if needed */ -static char * -strcat_char(char * str, int * len, int * tmplen, char c) -{ - char * p; - - if(*tmplen <= (*len + 1)) - { - *tmplen += 256; - p = (char *)realloc(str, *tmplen); - if(p == NULL) /* handle a failure of realloc() */ - { - *tmplen -= 256; - return str; - } - str = p; - } - str[*len] = c; - (*len)++; - return str; -} - -/* strcat_int() - * concatenate the string representation of the integer. - * call strcat_char() */ -static char * -strcat_int(char * str, int * len, int * tmplen, int i) -{ - char buf[16]; - int j; - - if(i < 0) { - str = strcat_char(str, len, tmplen, '-'); - i = -i; - } else if(i == 0) { - /* special case for 0 */ - str = strcat_char(str, len, tmplen, '0'); - return str; - } - j = 0; - while(i && j < (int)sizeof(buf)) { - buf[j++] = '0' + (i % 10); - i = i / 10; - } - while(j > 0) { - str = strcat_char(str, len, tmplen, buf[--j]); - } - return str; -} - -/* iterative subroutine using a small stack - * This way, the progam stack usage is kept low */ -static char * -genXML(char * str, int * len, int * tmplen, - const struct XMLElt * p) -{ -#define GENXML_STACK_SIZE 16 - unsigned short i, j; - unsigned long k; - int top; - const char * eltname, *s; - char c; - struct { - unsigned short i; - unsigned short j; - const char * eltname; - } pile[GENXML_STACK_SIZE]; /* stack */ - top = -1; - i = 0; /* current node */ - j = 1; /* i + number of nodes*/ - for(;;) - { - eltname = p[i].eltname; - if(!eltname) - return str; - if(eltname[0] == '/') - { - /* leaf node */ - if(p[i].data && p[i].data[0]) - { - /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */ - str = strcat_char(str, len, tmplen, '<'); - str = strcat_str(str, len, tmplen, eltname+1); - str = strcat_char(str, len, tmplen, '>'); -#ifdef RANDOMIZE_URLS - if(p[i].data[0] == '/') - { - /* prepend all URL paths with a "random" value */ - str = strcat_char(str, len, tmplen, '/'); - str = strcat_str(str, len, tmplen, random_url); - } -#endif /* RANDOMIZE_URLS */ - str = strcat_str(str, len, tmplen, p[i].data); -#ifdef IGD_V2 - /* checking a single 'u' saves us 4 strcmp() calls most of the time */ - if (GETFLAG(FORCEIGDDESCV1MASK) && (p[i].data[0] == 'u')) - { - if ((strcmp(p[i].data, DEVICE_TYPE_IGD) == 0) || - (strcmp(p[i].data, DEVICE_TYPE_WAN) == 0) || - (strcmp(p[i].data, DEVICE_TYPE_WANC) == 0) || - (strcmp(p[i].data, SERVICE_TYPE_WANIPC) == 0) ) - { - str[*len - 1] = '1'; /* Change the version number to 1 */ - } - } -#endif - str = strcat_char(str, len, tmplen, '<'); - str = strcat_str(str, len, tmplen, eltname); - str = strcat_char(str, len, tmplen, '>'); - } - for(;;) - { - if(top < 0) - return str; - i = ++(pile[top].i); - j = pile[top].j; - /*printf(" pile[%d]\t%d %d\n", top, i, j); */ - if(i==j) - { - /*printf("\n", pile[top].eltname); */ - str = strcat_char(str, len, tmplen, '<'); - str = strcat_char(str, len, tmplen, '/'); - s = pile[top].eltname; - for(c = *s; c > ' '; c = *(++s)) - str = strcat_char(str, len, tmplen, c); - str = strcat_char(str, len, tmplen, '>'); - top--; - } - else - break; - } - } - else - { - /* node with child(ren) */ - /*printf("<%s>\n", eltname); */ - str = strcat_char(str, len, tmplen, '<'); - str = strcat_str(str, len, tmplen, eltname); - if(memcmp(eltname, "root ", 5) == 0) { - char configid_str[16]; - /* add configId attribute, required by UDA 1.1 */ - snprintf(configid_str, sizeof(configid_str), "\"%u\"", upnp_configid); - str = strcat_str(str, len, tmplen, " configId="); - str = strcat_str(str, len, tmplen, configid_str); - } - str = strcat_char(str, len, tmplen, '>'); - k = (unsigned long)p[i].data; - i = k & 0xffff; - j = i + (k >> 16); - if(top < (GENXML_STACK_SIZE - 1)) { - top++; - /*printf(" +pile[%d]\t%d %d\n", top, i, j); */ - pile[top].i = i; - pile[top].j = j; - pile[top].eltname = eltname; -#ifdef DEBUG - } else { - fprintf(stderr, "*** GenXML(): stack OVERFLOW ***\n"); -#endif /* DEBUG */ - } - } - } -} - -/* genRootDesc() : - * - Generate the root description of the UPnP device. - * - the len argument is used to return the length of - * the returned string. - * - tmp_uuid argument is used to build the uuid string */ -char * -genRootDesc(int * len) -{ - char * str; - int tmplen; - tmplen = 2048; - str = (char *)malloc(tmplen); - if(str == NULL) - return NULL; - * len = strlen(xmlver); - /*strcpy(str, xmlver); */ - memcpy(str, xmlver, *len + 1); - str = genXML(str, len, &tmplen, rootDesc); - str[*len] = '\0'; - return str; -} - -/* genServiceDesc() : - * Generate service description with allowed methods and - * related variables. */ -static char * -genServiceDesc(int * len, const struct serviceDesc * s) -{ - int i, j; - const struct action * acts; - const struct stateVar * vars; - const struct argument * args; - const char * p; - char * str; - int tmplen; - tmplen = 2048; - str = (char *)malloc(tmplen); - if(str == NULL) - return NULL; - /*strcpy(str, xmlver); */ - *len = strlen(xmlver); - memcpy(str, xmlver, *len + 1); - - acts = s->actionList; - vars = s->serviceStateTable; - - str = strcat_char(str, len, &tmplen, '<'); - str = strcat_str(str, len, &tmplen, root_service); - str = strcat_char(str, len, &tmplen, '>'); - - str = strcat_str(str, len, &tmplen, - "" UPNP_VERSION_MAJOR_STR "" - "" UPNP_VERSION_MINOR_STR ""); - - i = 0; - str = strcat_str(str, len, &tmplen, ""); - while(acts[i].name) - { - str = strcat_str(str, len, &tmplen, ""); - str = strcat_str(str, len, &tmplen, acts[i].name); - str = strcat_str(str, len, &tmplen, ""); - /* argument List */ - args = acts[i].args; - if(args) - { - str = strcat_str(str, len, &tmplen, ""); - j = 0; - while(args[j].dir) - { - str = strcat_str(str, len, &tmplen, ""); - if((args[j].dir & 0x80) == 0) { - str = strcat_str(str, len, &tmplen, "New"); - } - p = vars[args[j].relatedVar].name; - if(args[j].dir & 0x7c) { - /* use magic values ... */ - str = strcat_str(str, len, &tmplen, magicargname[(args[j].dir & 0x7c) >> 2]); - } else if(0 == memcmp(p, "PortMapping", 11) - && 0 != memcmp(p + 11, "Description", 11)) { - if(0 == memcmp(p + 11, "NumberOfEntries", 15)) { - /* PortMappingNumberOfEntries */ -#ifdef IGD_V2 - if(0 == memcmp(acts[i].name, "GetListOfPortMappings", 22)) { - str = strcat_str(str, len, &tmplen, "NumberOfPorts"); - } else { - str = strcat_str(str, len, &tmplen, "PortMappingIndex"); - } -#else - str = strcat_str(str, len, &tmplen, "PortMappingIndex"); -#endif - } else { - /* PortMappingEnabled - * PortMappingLeaseDuration - * PortMappingProtocol */ - str = strcat_str(str, len, &tmplen, p + 11); - } -#ifdef IGD_V2 - } else if(0 == memcmp(p, "A_ARG_TYPE_", 11)) { - str = strcat_str(str, len, &tmplen, p + 11); - } else if(0 == memcmp(p, "ExternalPort", 13) - && args[j].dir == 2 - && 0 == memcmp(acts[i].name, "AddAnyPortMapping", 18)) { - str = strcat_str(str, len, &tmplen, "ReservedPort"); -#endif - } else { - str = strcat_str(str, len, &tmplen, p); - } - str = strcat_str(str, len, &tmplen, ""); - str = strcat_str(str, len, &tmplen, (args[j].dir&0x03)==1?"in":"out"); - str = strcat_str(str, len, &tmplen, - ""); - str = strcat_str(str, len, &tmplen, p); - str = strcat_str(str, len, &tmplen, - ""); - j++; - } - str = strcat_str(str, len, &tmplen,""); - } - str = strcat_str(str, len, &tmplen, ""); - /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */ - i++; - } - str = strcat_str(str, len, &tmplen, ""); - i = 0; - while(vars[i].name) - { - str = strcat_str(str, len, &tmplen, - ""); - str = strcat_str(str, len, &tmplen, vars[i].name); - str = strcat_str(str, len, &tmplen, ""); - str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]); - str = strcat_str(str, len, &tmplen, ""); - /*if(vars[i].defaultValue) */ - if(vars[i].idefault) - { - str = strcat_str(str, len, &tmplen, ""); - /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */ - str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]); - str = strcat_str(str, len, &tmplen, ""); - } - if(vars[i].iallowedlist) - { - if((vars[i].itype & 0x0f) == 0) - { - /* string */ - str = strcat_str(str, len, &tmplen, ""); - for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++) - { - str = strcat_str(str, len, &tmplen, ""); - str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]); - str = strcat_str(str, len, &tmplen, ""); - } - str = strcat_str(str, len, &tmplen, ""); - } else { - /* ui2 and ui4 */ - str = strcat_str(str, len, &tmplen, ""); - str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist]); - str = strcat_str(str, len, &tmplen, ""); - str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist+1]); - str = strcat_str(str, len, &tmplen, ""); - } - } - str = strcat_str(str, len, &tmplen, ""); - /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */ - i++; - } - str = strcat_str(str, len, &tmplen, ""); - str[*len] = '\0'; - return str; -} - -/* genWANIPCn() : - * Generate the WANIPConnection xml description */ -char * -genWANIPCn(int * len) -{ - return genServiceDesc(len, &scpdWANIPCn); -} - -/* genWANCfg() : - * Generate the WANInterfaceConfig xml description. */ -char * -genWANCfg(int * len) -{ - return genServiceDesc(len, &scpdWANCfg); -} - -#ifdef ENABLE_L3F_SERVICE -char * -genL3F(int * len) -{ - return genServiceDesc(len, &scpdL3F); -} -#endif - -#ifdef ENABLE_6FC_SERVICE -char * -gen6FC(int * len) -{ - return genServiceDesc(len, &scpd6FC); -} -#endif - -#ifdef ENABLE_DP_SERVICE -char * -genDP(int * len) -{ - return genServiceDesc(len, &scpdDP); -} -#endif - -#ifdef ENABLE_EVENTS -static char * -genEventVars(int * len, const struct serviceDesc * s) -{ - char tmp[16]; - const struct stateVar * v; - char * str; - int tmplen; - tmplen = 512; - str = (char *)malloc(tmplen); - if(str == NULL) - return NULL; - *len = 0; - v = s->serviceStateTable; - str = strcat_str(str, len, &tmplen, ""); - while(v->name) { - if(v->itype & 0x80) { - str = strcat_str(str, len, &tmplen, "<"); - str = strcat_str(str, len, &tmplen, v->name); - str = strcat_str(str, len, &tmplen, ">"); - /*printf("<%s>", v->name);*/ - switch(v->ieventvalue) { - case 0: - break; -#ifdef ENABLE_DP_SERVICE - case SETUPREADY_MAGICALVALUE: - /* always ready for setup */ - snprintf(tmp, sizeof(tmp), "%d", 1); - str = strcat_str(str, len, &tmplen, tmp); - break; -#endif - case CONNECTIONSTATUS_MAGICALVALUE: - /* or get_wan_connection_status_str(ext_if_name) */ - str = strcat_str(str, len, &tmplen, - upnpallowedvalues[18 + get_wan_connection_status(ext_if_name)]); - break; -#ifdef ENABLE_6FC_SERVICE - case FIREWALLENABLED_MAGICALVALUE: - /* see 2.4.2 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */ - snprintf(tmp, sizeof(tmp), "%d", - GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1); - str = strcat_str(str, len, &tmplen, tmp); - break; - case INBOUNDPINHOLEALLOWED_MAGICALVALUE: - /* see 2.4.3 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */ - snprintf(tmp, sizeof(tmp), "%d", - GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1); - str = strcat_str(str, len, &tmplen, tmp); - break; -#endif -#ifdef IGD_V2 - case SYSTEMUPDATEID_MAGICALVALUE: - /* Please read section 2.3.23 SystemUpdateID - * of UPnP-gw-WANIPConnection-v2-Service.pdf */ - snprintf(tmp, sizeof(tmp), "%d", - 1/* system update id */); - str = strcat_str(str, len, &tmplen, tmp); - break; -#endif - case PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE: - /* Port mapping number of entries magical value */ - snprintf(tmp, sizeof(tmp), "%d", - upnp_get_portmapping_number_of_entries()); - str = strcat_str(str, len, &tmplen, tmp); - break; - case EXTERNALIPADDRESS_MAGICALVALUE: - /* External ip address magical value */ - if(use_ext_ip_addr) - str = strcat_str(str, len, &tmplen, use_ext_ip_addr); - else { - char ext_ip_addr[INET_ADDRSTRLEN]; - if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) { - str = strcat_str(str, len, &tmplen, "0.0.0.0"); - } else { - str = strcat_str(str, len, &tmplen, ext_ip_addr); - } - } - break; - case DEFAULTCONNECTIONSERVICE_MAGICALVALUE: - /* DefaultConnectionService magical value */ - str = strcat_str(str, len, &tmplen, uuidvalue_wcd); -#ifdef IGD_V2 - str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:2,urn:upnp-org:serviceId:WANIPConn1"); -#else - str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1"); -#endif - break; - default: - str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]); - } - str = strcat_str(str, len, &tmplen, "name); - str = strcat_str(str, len, &tmplen, ">"); - /*printf("\n", v->name);*/ - } - v++; - } - str = strcat_str(str, len, &tmplen, ""); -#if 0 - printf("\n"); - printf("\n"); - printf("%d\n", tmplen); -#endif - str[*len] = '\0'; - return str; -} - -char * -getVarsWANIPCn(int * l) -{ - return genEventVars(l, - &scpdWANIPCn); -} - -char * -getVarsWANCfg(int * l) -{ - return genEventVars(l, - &scpdWANCfg); -} - -#ifdef ENABLE_L3F_SERVICE -char * -getVarsL3F(int * l) -{ - return genEventVars(l, - &scpdL3F); -} -#endif - -#ifdef ENABLE_6FC_SERVICE -char * -getVars6FC(int * l) -{ - return genEventVars(l, - &scpd6FC); -} -#endif - -#ifdef ENABLE_DP_SERVICE -char * -getVarsDP(int * l) -{ - return genEventVars(l, - &scpdDP); -} -#endif - -#endif /* ENABLE_EVENTS */ diff --git a/src/contrib/miniupnp/miniupnpd/upnpdescgen.h b/src/contrib/miniupnp/miniupnpd/upnpdescgen.h deleted file mode 100644 index deaed69..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpdescgen.h +++ /dev/null @@ -1,102 +0,0 @@ -/* $Id: upnpdescgen.h,v 1.22 2011/05/18 22:22:24 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPDESCGEN_H_INCLUDED -#define UPNPDESCGEN_H_INCLUDED - -#include "config.h" - -/* for the root description - * The child list reference is stored in "data" member using the - * INITHELPER macro with index/nchild always in the - * same order, whatever the endianness */ -struct XMLElt { - const char * eltname; /* begin with '/' if no child */ - const char * data; /* Value */ -}; - -/* for service description */ -struct serviceDesc { - const struct action * actionList; - const struct stateVar * serviceStateTable; -}; - -struct action { - const char * name; - const struct argument * args; -}; - -struct argument { /* the name of the arg is obtained from the variable */ - unsigned char dir; /* MSB : don't append "New" Flag, - * 5 Medium bits : magic argument name index - * 2 LSB : 1 = in, 2 = out */ - unsigned char relatedVar; /* index of the related variable */ -}; - -struct stateVar { - const char * name; - unsigned char itype; /* MSB: sendEvent flag, 7 LSB: index in upnptypes */ - unsigned char idefault; /* default value */ - unsigned char iallowedlist; /* index in allowed values list - * or in allowed range list */ - unsigned char ieventvalue; /* fixed value returned or magical values */ -}; - -/* little endian - * The code has now be tested on big endian architecture */ -#define INITHELPER(i, n) ((char *)(((n)<<16)|(i))) - -/* char * genRootDesc(int *); - * returns: NULL on error, string allocated on the heap */ -char * -genRootDesc(int * len); - -/* for the two following functions */ -char * -genWANIPCn(int * len); - -char * -genWANCfg(int * len); - -#ifdef ENABLE_L3F_SERVICE -char * -genL3F(int * len); -#endif - -#ifdef ENABLE_6FC_SERVICE -char * -gen6FC(int * len); -#endif - -#ifdef ENABLE_DP_SERVICE -char * -genDP(int * len); -#endif - -#ifdef ENABLE_EVENTS -char * -getVarsWANIPCn(int * len); - -char * -getVarsWANCfg(int * len); - -#ifdef ENABLE_L3F_SERVICE -char * -getVarsL3F(int * len); -#endif -#ifdef ENABLE_6FC_SERVICE -char * -getVars6FC(int * len); -#endif -#ifdef ENABLE_DP_SERVICE -char * -getVarsDP(int * len); -#endif -#endif /* ENABLE_EVENTS */ - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpdescstrings.h b/src/contrib/miniupnp/miniupnpd/upnpdescstrings.h deleted file mode 100644 index 4fd800e..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpdescstrings.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $Id: upnpdescstrings.h,v 1.8 2012/09/27 16:00:10 nanard Exp $ */ -/* miniupnp project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the coditions detailed in - * the LICENCE file provided within the distribution */ -#ifndef UPNPDESCSTRINGS_H_INCLUDED -#define UPNPDESCSTRINGS_H_INCLUDED - -#include "config.h" - -/* strings used in the root device xml description */ -#define ROOTDEV_FRIENDLYNAME OS_NAME " router" -#define ROOTDEV_MANUFACTURER OS_NAME -#define ROOTDEV_MANUFACTURERURL OS_URL -#define ROOTDEV_MODELNAME OS_NAME " router" -#define ROOTDEV_MODELDESCRIPTION OS_NAME " router" -#define ROOTDEV_MODELURL OS_URL - -#define WANDEV_FRIENDLYNAME "WANDevice" -#define WANDEV_MANUFACTURER "MiniUPnP" -#define WANDEV_MANUFACTURERURL "http://miniupnp.free.fr/" -#define WANDEV_MODELNAME "WAN Device" -#define WANDEV_MODELDESCRIPTION "WAN Device" -#define WANDEV_MODELNUMBER MINIUPNPD_DATE -#define WANDEV_MODELURL "http://miniupnp.free.fr/" -#define WANDEV_UPC "000000000000" -/* UPC is 12 digit (barcode) */ - -#define WANCDEV_FRIENDLYNAME "WANConnectionDevice" -#define WANCDEV_MANUFACTURER WANDEV_MANUFACTURER -#define WANCDEV_MANUFACTURERURL WANDEV_MANUFACTURERURL -#define WANCDEV_MODELNAME "MiniUPnPd" -#define WANCDEV_MODELDESCRIPTION "MiniUPnP daemon" -#define WANCDEV_MODELNUMBER MINIUPNPD_DATE -#define WANCDEV_MODELURL "http://miniupnp.free.fr/" -#define WANCDEV_UPC "000000000000" -/* UPC is 12 digit (barcode) */ - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpevents.c b/src/contrib/miniupnp/miniupnpd/upnpevents.c deleted file mode 100644 index d96bccb..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpevents.c +++ /dev/null @@ -1,670 +0,0 @@ -/* $Id: upnpevents.c,v 1.39 2018/03/12 22:41:54 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2008-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "config.h" -#if defined(LIB_UUID) -/* as found on linux */ -#include -#elif defined(BSD_UUID) -#include -#endif /* LIB_UUID / BSD_UUID */ -#include "upnpevents.h" -#include "miniupnpdpath.h" -#include "upnpglobalvars.h" -#include "upnpdescgen.h" -#include "upnputils.h" - -#ifdef ENABLE_EVENTS -/*enum subscriber_service_enum { - EWanCFG = 1, - EWanIPC, - EL3F -};*/ - -/* stuctures definitions */ -struct subscriber { - LIST_ENTRY(subscriber) entries; - struct upnp_event_notify * notify; - time_t timeout; - uint32_t seq; - enum subscriber_service_enum service; - char uuid[42]; - char callback[]; -}; - -struct upnp_event_notify { - LIST_ENTRY(upnp_event_notify) entries; - int s; /* socket */ - enum { ECreated=1, - EConnecting, - ESending, - EWaitingForResponse, - EFinished, - EError } state; - struct subscriber * sub; - char * buffer; - int buffersize; - int tosend; - int sent; - const char * path; -#ifdef ENABLE_IPV6 - int ipv6; - char addrstr[48]; -#else - char addrstr[16]; -#endif - char portstr[8]; -}; - -/* prototypes */ -static void -upnp_event_create_notify(struct subscriber * sub); - -/* Subscriber list */ -LIST_HEAD(listhead, subscriber) subscriberlist = { NULL }; - -/* notify list */ -LIST_HEAD(listheadnotif, upnp_event_notify) notifylist = { NULL }; - -/* create a new subscriber */ -static struct subscriber * -newSubscriber(const char * eventurl, const char * callback, int callbacklen) -{ - struct subscriber * tmp; - if(!eventurl || !callback || !callbacklen) - return NULL; - tmp = calloc(1, sizeof(struct subscriber)+callbacklen+1); - if(!tmp) - return NULL; - if(strcmp(eventurl, WANCFG_EVENTURL)==0) - tmp->service = EWanCFG; - else if(strcmp(eventurl, WANIPC_EVENTURL)==0) - tmp->service = EWanIPC; -#ifdef ENABLE_L3F_SERVICE - else if(strcmp(eventurl, L3F_EVENTURL)==0) - tmp->service = EL3F; -#endif -#ifdef ENABLE_6FC_SERVICE - else if(strcmp(eventurl, WANIP6FC_EVENTURL)==0) - tmp->service = E6FC; -#endif -#ifdef ENABLE_DP_SERVICE - else if(strcmp(eventurl, DP_EVENTURL)==0) - tmp->service = EDP; -#endif - else { - free(tmp); - return NULL; - } - memcpy(tmp->callback, callback, callbacklen); - tmp->callback[callbacklen] = '\0'; -#if defined(LIB_UUID) - { - uuid_t uuid; - uuid_generate(uuid); - memcpy(tmp->uuid, "uuid:", 5); - uuid_unparse(uuid, tmp->uuid + 5); - } -#elif defined(BSD_UUID) - { - uuid_t uuid; - uint32_t status; - uuid_create(&uuid, &status); - if(status != uuid_s_ok) { - syslog(LOG_ERR, "uuid_create() failed (%u)", status); - } else { - char * uuid_str; - uuid_to_string(&uuid, &uuid_str, &status); - if(status != uuid_s_ok) { - syslog(LOG_ERR, "uuid_to_string() failed (%u)", status); - } else { - if(strlen(uuid_str) != 36) { - syslog(LOG_ERR, "uuid_to_string() returned %s", uuid_str); - status = (uint32_t)-1; - } else { - memcpy(tmp->uuid, "uuid:", 5); - memcpy(tmp->uuid + 5, uuid_str, 36); - tmp->uuid[sizeof(tmp->uuid)-1] = '\0'; - } - free(uuid_str); - } - } - if(status != uuid_s_ok) { - /* make a dummy uuid */ - strncpy(tmp->uuid, uuidvalue_igd, sizeof(tmp->uuid)); - tmp->uuid[sizeof(tmp->uuid)-1] = '\0'; - snprintf(tmp->uuid+sizeof(tmp->uuid)-5, 5, "%04lx", random() & 0xffff); - } - } -#else - /* make a dummy uuid */ - strncpy(tmp->uuid, uuidvalue_igd, sizeof(tmp->uuid)); - tmp->uuid[sizeof(tmp->uuid)-1] = '\0'; - snprintf(tmp->uuid+sizeof(tmp->uuid)-5, 5, "%04lx", random() & 0xffff); -#endif - return tmp; -} - -/* creates a new subscriber and adds it to the subscriber list - * also initiate 1st notify - * TODO : add a check on the number of subscriber in order to - * prevent memory overflow... */ -const char * -upnpevents_addSubscriber(const char * eventurl, - const char * callback, int callbacklen, - int timeout) -{ - struct subscriber * tmp; - /*static char uuid[42];*/ - /* "uuid:00000000-0000-0000-0000-000000000000"; 5+36+1=42bytes */ - syslog(LOG_DEBUG, "addSubscriber(%s, %.*s, %d)", - eventurl, callbacklen, callback, timeout); - /*strncpy(uuid, uuidvalue, sizeof(uuid)); - uuid[sizeof(uuid)-1] = '\0';*/ - tmp = newSubscriber(eventurl, callback, callbacklen); - if(!tmp) - return NULL; - if(timeout) - tmp->timeout = upnp_time() + timeout; - LIST_INSERT_HEAD(&subscriberlist, tmp, entries); - upnp_event_create_notify(tmp); - return tmp->uuid; -} - -/* renew a subscription (update the timeout) */ -const char * -upnpevents_renewSubscription(const char * sid, int sidlen, int timeout) -{ - struct subscriber * sub; - for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - if((sidlen == 41) && (memcmp(sid, sub->uuid, 41) == 0)) { -#ifdef UPNP_STRICT - /* check if the subscription already timeouted */ - if(sub->timeout && upnp_time() > sub->timeout) - continue; -#endif - sub->timeout = (timeout ? upnp_time() + timeout : 0); - return sub->uuid; - } - } - return NULL; -} - -int -upnpevents_removeSubscriber(const char * sid, int sidlen) -{ - struct subscriber * sub; - if(!sid) - return -1; - for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - if((sidlen == 41) && (memcmp(sid, sub->uuid, 41) == 0)) { - if(sub->notify) { - sub->notify->sub = NULL; - } - LIST_REMOVE(sub, entries); - free(sub); - return 0; - } - } - return -1; -} - -/* notifies all subscriber of a number of port mapping change - * or external ip address change */ -void -upnp_event_var_change_notify(enum subscriber_service_enum service) -{ - struct subscriber * sub; - for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - if(sub->service == service && sub->notify == NULL) - upnp_event_create_notify(sub); - } -} - -/* create and add the notify object to the list */ -static void -upnp_event_create_notify(struct subscriber * sub) -{ - struct upnp_event_notify * obj; - /*struct timeval sock_timeout;*/ - - obj = calloc(1, sizeof(struct upnp_event_notify)); - if(!obj) { - syslog(LOG_ERR, "%s: calloc(): %m", "upnp_event_create_notify"); - return; - } - obj->sub = sub; - obj->state = ECreated; -#ifdef ENABLE_IPV6 - obj->s = socket((obj->sub->callback[7] == '[') ? PF_INET6 : PF_INET, - SOCK_STREAM, 0); -#else - obj->s = socket(PF_INET, SOCK_STREAM, 0); -#endif - if(obj->s<0) { - syslog(LOG_ERR, "%s: socket(): %m", "upnp_event_create_notify"); - goto error; - } -#if 0 /* does not work for non blocking connect() */ - /* set timeout to 3 seconds */ - sock_timeout.tv_sec = 3; - sock_timeout.tv_usec = 0; - if(setsockopt(obj->s, SOL_SOCKET, SO_RCVTIMEO, &sock_timeout, sizeof(struct timeval)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(SO_RCVTIMEO): %m", - "upnp_event_create_notify"); - } - sock_timeout.tv_sec = 3; - sock_timeout.tv_usec = 0; - if(setsockopt(obj->s, SOL_SOCKET, SO_SNDTIMEO, &sock_timeout, sizeof(struct timeval)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(SO_SNDTIMEO): %m", - "upnp_event_create_notify"); - } -#endif - /* set socket non blocking */ - if(!set_non_blocking(obj->s)) { - syslog(LOG_ERR, "%s: set_non_blocking(): %m", - "upnp_event_create_notify"); - goto error; - } - if(sub) - sub->notify = obj; - LIST_INSERT_HEAD(¬ifylist, obj, entries); - return; -error: - if(obj->s >= 0) - close(obj->s); - free(obj); -} - -static void -upnp_event_notify_connect(struct upnp_event_notify * obj) -{ - unsigned int i; - const char * p; - unsigned short port; -#ifdef ENABLE_IPV6 - struct sockaddr_storage addr; - socklen_t addrlen; -#else - struct sockaddr_in addr; - socklen_t addrlen; -#endif - - if(!obj) - return; - memset(&addr, 0, sizeof(addr)); - i = 0; - if(obj->sub == NULL) { - obj->state = EError; - return; - } - p = obj->sub->callback; - p += 7; /* http:// */ -#ifdef ENABLE_IPV6 - if(*p == '[') { /* ip v6 */ - obj->addrstr[i++] = '['; - p++; - obj->ipv6 = 1; - while(*p != ']' && i < (sizeof(obj->addrstr)-1)) - obj->addrstr[i++] = *(p++); - if(*p == ']') - p++; - if(i < (sizeof(obj->addrstr)-1)) - obj->addrstr[i++] = ']'; - } else { -#endif - while(*p != '/' && *p != ':' && i < (sizeof(obj->addrstr)-1)) - obj->addrstr[i++] = *(p++); -#ifdef ENABLE_IPV6 - } -#endif - obj->addrstr[i] = '\0'; - if(*p == ':') { - obj->portstr[0] = *p; - i = 1; - p++; - port = (unsigned short)atoi(p); - while(*p != '/') { - if(i<7) obj->portstr[i++] = *p; - p++; - } - obj->portstr[i] = 0; - } else { - port = 80; - obj->portstr[0] = '\0'; - } - obj->path = p; -#ifdef ENABLE_IPV6 - if(obj->ipv6) { - char addrstr_tmp[48]; - struct sockaddr_in6 * sa = (struct sockaddr_in6 *)&addr; - sa->sin6_family = AF_INET6; - i = (int)strlen(obj->addrstr); - if(i > 2) { - i -= 2; - memcpy(addrstr_tmp, obj->addrstr + 1, i); - addrstr_tmp[i] = '\0'; - inet_pton(AF_INET6, addrstr_tmp, &(sa->sin6_addr)); - } - sa->sin6_port = htons(port); - addrlen = sizeof(struct sockaddr_in6); - } else { - struct sockaddr_in * sa = (struct sockaddr_in *)&addr; - sa->sin_family = AF_INET; - inet_pton(AF_INET, obj->addrstr, &(sa->sin_addr)); - sa->sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); - } -#else - addr.sin_family = AF_INET; - inet_aton(obj->addrstr, &addr.sin_addr); - addr.sin_port = htons(port); - addrlen = sizeof(struct sockaddr_in); -#endif - syslog(LOG_DEBUG, "%s: '%s' %hu '%s'", "upnp_event_notify_connect", - obj->addrstr, port, obj->path); - obj->state = EConnecting; - if(connect(obj->s, (struct sockaddr *)&addr, addrlen) < 0) { - if(errno != EINPROGRESS && errno != EWOULDBLOCK) { - syslog(LOG_ERR, "%s: connect(%d, %s, %u): %m", - "upnp_event_notify_connect", obj->s, - obj->addrstr, addrlen); - obj->state = EError; - } - } -} - -static void upnp_event_prepare(struct upnp_event_notify * obj) -{ - static const char notifymsg[] = - "NOTIFY %s HTTP/1.1\r\n" - "Host: %s%s\r\n" -#if (UPNP_VERSION_MAJOR == 1) && (UPNP_VERSION_MINOR == 0) - "Content-Type: text/xml\r\n" /* UDA v1.0 */ -#else - "Content-Type: text/xml; charset=\"utf-8\"\r\n" /* UDA v1.1 or later */ -#endif - "Content-Length: %d\r\n" - "NT: upnp:event\r\n" - "NTS: upnp:propchange\r\n" - "SID: %s\r\n" - "SEQ: %u\r\n" - "Connection: close\r\n" - "Cache-Control: no-cache\r\n" - "\r\n" - "%.*s\r\n"; - char * xml; - int l; - if(obj->sub == NULL) { - obj->state = EError; - return; - } - switch(obj->sub->service) { - case EWanCFG: - xml = getVarsWANCfg(&l); - break; - case EWanIPC: - xml = getVarsWANIPCn(&l); - break; -#ifdef ENABLE_L3F_SERVICE - case EL3F: - xml = getVarsL3F(&l); - break; -#endif -#ifdef ENABLE_6FC_SERVICE - case E6FC: - xml = getVars6FC(&l); - break; -#endif -#ifdef ENABLE_DP_SERVICE - case EDP: - xml = getVarsDP(&l); - break; -#endif - default: - xml = NULL; - l = 0; - } - obj->buffersize = 1024; - obj->buffer = malloc(obj->buffersize); - if(!obj->buffer) { - syslog(LOG_ERR, "%s: malloc returned NULL", "upnp_event_prepare"); - if(xml) { - free(xml); - } - obj->state = EError; - return; - } - obj->tosend = snprintf(obj->buffer, obj->buffersize, notifymsg, - obj->path, obj->addrstr, obj->portstr, l+2, - obj->sub->uuid, obj->sub->seq, - l, xml); - if(xml) { - free(xml); - xml = NULL; - } - obj->state = ESending; -} - -static void upnp_event_send(struct upnp_event_notify * obj) -{ - int i; - - syslog(LOG_DEBUG, "%s: sending event notify message to %s%s", - "upnp_event_send", obj->addrstr, obj->portstr); - syslog(LOG_DEBUG, "%s: msg: %s", - "upnp_event_send", obj->buffer + obj->sent); - i = send(obj->s, obj->buffer + obj->sent, obj->tosend - obj->sent, 0); - if(i<0) { - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { - syslog(LOG_NOTICE, "%s: send(%s%s): %m", "upnp_event_send", - obj->addrstr, obj->portstr); - obj->state = EError; - return; - } else { - /* EAGAIN or EWOULDBLOCK or EINTR : no data sent */ - i = 0; - } - } - if(i != (obj->tosend - obj->sent)) - syslog(LOG_NOTICE, "%s: %d bytes send out of %d", - "upnp_event_send", i, obj->tosend - obj->sent); - obj->sent += i; - if(obj->sent == obj->tosend) - obj->state = EWaitingForResponse; -} - -static void upnp_event_recv(struct upnp_event_notify * obj) -{ - int n; - n = recv(obj->s, obj->buffer, obj->buffersize, 0); - if(n<0) { - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) { - syslog(LOG_ERR, "%s: recv(): %m", "upnp_event_recv"); - obj->state = EError; - } - return; - } - syslog(LOG_DEBUG, "%s: (%dbytes) %.*s", "upnp_event_recv", - n, n, obj->buffer); - /* TODO : do something with the data recevied ? - * right now, n (number of bytes received) is ignored - * We may need to recv() more bytes. */ - obj->state = EFinished; - if(obj->sub) - obj->sub->seq++; -} - -static void -upnp_event_process_notify(struct upnp_event_notify * obj) -{ - int err; - socklen_t len; - switch(obj->state) { - case EConnecting: - /* now connected or failed to connect */ - len = sizeof(err); - if(getsockopt(obj->s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - syslog(LOG_ERR, "%s: getsockopt: %m", "upnp_event_process_notify"); - obj->state = EError; - break; - } - if(err != 0) { - errno = err; - syslog(LOG_WARNING, "%s: connect(%s%s): %m", - "upnp_event_process_notify", - obj->addrstr, obj->portstr); - obj->state = EError; - break; - } - upnp_event_prepare(obj); - if(obj->state == ESending) - upnp_event_send(obj); - break; - case ESending: - upnp_event_send(obj); - break; - case EWaitingForResponse: - upnp_event_recv(obj); - break; - case EFinished: - close(obj->s); - obj->s = -1; - break; - default: - syslog(LOG_ERR, "%s: unknown state", "upnp_event_process_notify"); - } -} - -void upnpevents_selectfds(fd_set *readset, fd_set *writeset, int * max_fd) -{ - struct upnp_event_notify * obj; - for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) { - syslog(LOG_DEBUG, "upnpevents_selectfds: %p %d %d", - obj, obj->state, obj->s); - if(obj->s >= 0) { - switch(obj->state) { - case ECreated: - upnp_event_notify_connect(obj); - if(obj->state != EConnecting) - break; - case EConnecting: - case ESending: - FD_SET(obj->s, writeset); - if(obj->s > *max_fd) - *max_fd = obj->s; - break; - case EWaitingForResponse: - FD_SET(obj->s, readset); - if(obj->s > *max_fd) - *max_fd = obj->s; - break; - default: - ; - } - } - } -} - -void upnpevents_processfds(fd_set *readset, fd_set *writeset) -{ - struct upnp_event_notify * obj; - struct upnp_event_notify * next; - struct subscriber * sub; - struct subscriber * subnext; - time_t curtime; - for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) { - syslog(LOG_DEBUG, "%s: %p %d %d %d %d", - "upnpevents_processfds", obj, obj->state, obj->s, - FD_ISSET(obj->s, readset), FD_ISSET(obj->s, writeset)); - if(obj->s >= 0) { - if(FD_ISSET(obj->s, readset) || FD_ISSET(obj->s, writeset)) - upnp_event_process_notify(obj); - } - } - obj = notifylist.lh_first; - while(obj != NULL) { - next = obj->entries.le_next; - if(obj->state == EError || obj->state == EFinished) { - if(obj->s >= 0) { - close(obj->s); - } - if(obj->sub) - obj->sub->notify = NULL; - /* remove also the subscriber from the list if there was an error */ - if(obj->state == EError && obj->sub) { - syslog(LOG_ERR, "%s: %p, remove subscriber %s after an ERROR cb: %s", - "upnpevents_processfds", obj, obj->sub->uuid, obj->sub->callback); - LIST_REMOVE(obj->sub, entries); - free(obj->sub); - } - if(obj->buffer) { - free(obj->buffer); - } - LIST_REMOVE(obj, entries); - free(obj); - } - obj = next; - } - /* remove timeouted subscribers */ - curtime = upnp_time(); - for(sub = subscriberlist.lh_first; sub != NULL; ) { - subnext = sub->entries.le_next; - if(sub->timeout && curtime > sub->timeout && sub->notify == NULL) { - syslog(LOG_INFO, "subscriber timeouted : %u > %u SID=%s", - (unsigned)curtime, (unsigned)sub->timeout, sub->uuid); - LIST_REMOVE(sub, entries); - free(sub); - } - sub = subnext; - } -} - -#ifdef USE_MINIUPNPDCTL -void write_events_details(int s) { - int n; - char buff[80]; - struct upnp_event_notify * obj; - struct subscriber * sub; - write(s, "Events details :\n", 17); - for(obj = notifylist.lh_first; obj != NULL; obj = obj->entries.le_next) { - n = snprintf(buff, sizeof(buff), " %p sub=%p state=%d s=%d\n", - obj, obj->sub, obj->state, obj->s); - write(s, buff, n); - } - write(s, "Subscribers :\n", 14); - for(sub = subscriberlist.lh_first; sub != NULL; sub = sub->entries.le_next) { - n = snprintf(buff, sizeof(buff), " %p timeout=%d seq=%u service=%d\n", - sub, (int)sub->timeout, sub->seq, sub->service); - write(s, buff, n); - n = snprintf(buff, sizeof(buff), " notify=%p %s\n", - sub->notify, sub->uuid); - write(s, buff, n); - n = snprintf(buff, sizeof(buff), " %s\n", - sub->callback); - write(s, buff, n); - } -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpevents.h b/src/contrib/miniupnp/miniupnpd/upnpevents.h deleted file mode 100644 index ed9104f..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpevents.h +++ /dev/null @@ -1,52 +0,0 @@ -/* $Id: upnpevents.h,v 1.12 2017/11/02 15:48:29 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2008-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPEVENTS_H_INCLUDED -#define UPNPEVENTS_H_INCLUDED - -/* for fd_set */ -#include -#include "config.h" - -#ifdef ENABLE_EVENTS -enum subscriber_service_enum { - EWanCFG = 1, - EWanIPC, -#ifdef ENABLE_L3F_SERVICE - EL3F, -#endif -#ifdef ENABLE_6FC_SERVICE - E6FC, -#endif -#ifdef ENABLE_DP_SERVICE - EDP, -#endif -}; - -void -upnp_event_var_change_notify(enum subscriber_service_enum service); - -const char * -upnpevents_addSubscriber(const char * eventurl, - const char * callback, int callbacklen, - int timeout); - -int -upnpevents_removeSubscriber(const char * sid, int sidlen); - -const char * -upnpevents_renewSubscription(const char * sid, int sidlen, int timeout); - -void upnpevents_selectfds(fd_set *readset, fd_set *writeset, int * max_fd); -void upnpevents_processfds(fd_set *readset, fd_set *writeset); - -#ifdef USE_MINIUPNPDCTL -void write_events_details(int s); -#endif - -#endif -#endif diff --git a/src/contrib/miniupnp/miniupnpd/upnpglobalvars.c b/src/contrib/miniupnp/miniupnpd/upnpglobalvars.c deleted file mode 100644 index 290059c..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpglobalvars.c +++ /dev/null @@ -1,170 +0,0 @@ -/* $Id: upnpglobalvars.c,v 1.41 2017/05/27 07:47:57 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include - -#include "config.h" -#include "upnpglobalvars.h" -#include "upnpdescstrings.h" - -/* network interface for internet */ -const char * ext_if_name = 0; - -/* file to store leases */ -#ifdef ENABLE_LEASEFILE -const char* lease_file = 0; -#endif - -/* forced ip address to use for this interface - * when NULL, getifaddr() is used */ -const char * use_ext_ip_addr = 0; - -unsigned long downstream_bitrate = 0; -unsigned long upstream_bitrate = 0; - -/* startup time */ -time_t startup_time = 0; - -#if defined(ENABLE_NATPMP) || defined(ENABLE_PCP) -/* origin for "epoch time" sent into NATPMP and PCP responses */ -time_t epoch_origin = 0; -#endif /* defined(ENABLE_NATPMP) || defined(ENABLE_PCP) */ - -#ifdef ENABLE_PCP -/* for PCP */ -unsigned long int min_lifetime = 120; -unsigned long int max_lifetime = 86400; -#endif - -int runtime_flags = 0; - -const char * pidfilename = "/var/run/miniupnpd.pid"; - -char uuidvalue_igd[] = "uuid:00000000-0000-0000-0000-000000000000"; -char uuidvalue_wan[] = "uuid:00000000-0000-0000-0000-000000000000"; -char uuidvalue_wcd[] = "uuid:00000000-0000-0000-0000-000000000000"; -char serialnumber[SERIALNUMBER_MAX_LEN] = "00000000"; - -char modelnumber[MODELNUMBER_MAX_LEN] = "1"; - -/* presentation url : - * http://nnn.nnn.nnn.nnn:ppppp/ => max 30 bytes including terminating 0 */ -char presentationurl[PRESENTATIONURL_MAX_LEN]; - -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION -/* friendly name for root devices in XML description */ -char friendly_name[FRIENDLY_NAME_MAX_LEN] = OS_NAME " router"; - -/* manufacturer name for root devices in XML description */ -char manufacturer_name[MANUFACTURER_NAME_MAX_LEN] = ROOTDEV_MANUFACTURER; - -/* manufacturer url for root devices in XML description */ -char manufacturer_url[MANUFACTURER_URL_MAX_LEN] = ROOTDEV_MANUFACTURERURL; - -/* model name for root devices in XML description */ -char model_name[MODEL_NAME_MAX_LEN] = ROOTDEV_MODELNAME; - -/* model description for root devices in XML description */ -char model_description[MODEL_DESCRIPTION_MAX_LEN] = ROOTDEV_MODELDESCRIPTION; - -/* model url for root devices in XML description */ -char model_url[MODEL_URL_MAX_LEN] = ROOTDEV_MODELURL; -#endif - -/* UPnP permission rules : */ -struct upnpperm * upnppermlist = 0; -unsigned int num_upnpperm = 0; - -#ifdef PCP_SADSCP -struct dscp_values* dscp_values_list = 0; -unsigned int num_dscp_values = 0; -#endif /*PCP_SADSCP*/ - -/* For automatic removal of expired rules (with LeaseDuration) */ -unsigned int nextruletoclean_timestamp = 0; - -#ifdef USE_PF -/* "rdr-anchor miniupnpd" or/and "anchor miniupnpd" in pf.conf */ -const char * anchor_name = "miniupnpd"; -const char * queue = 0; -const char * tag = 0; -#endif - -#ifdef USE_NETFILTER -/* chain names to use in the nat and filter tables. */ - -/* iptables -t nat -N MINIUPNPD - * iptables -t nat -A PREROUTING -i -j MINIUPNPD */ -const char * miniupnpd_nat_chain = "MINIUPNPD"; - -/* iptables -t nat -N MINIUPNPD-POSTROUTING - * iptables -t nat -A POSTROUTING -o -j MINIUPNPD-POSTROUTING */ -const char * miniupnpd_nat_postrouting_chain = "MINIUPNPD-POSTROUTING"; - -/* iptables -t filter -N MINIUPNPD - * iptables -t filter -A FORWARD -i ! -o -j MINIUPNPD */ -const char * miniupnpd_forward_chain = "MINIUPNPD"; - -#ifdef ENABLE_UPNPPINHOLE -/* ip6tables -t filter -N MINIUPNPD - * ip6tables -t filter -A FORWARD -i ! -o -j MINIUPNPD */ -const char * miniupnpd_v6_filter_chain = "MINIUPNPD"; -#endif /* ENABLE_UPNPPINHOLE */ - -#endif /* USE_NETFILTER */ - -#ifdef ENABLE_NFQUEUE -int nfqueue = -1; -int n_nfqix = 0; -unsigned nfqix[MAX_LAN_ADDR]; -#endif /* ENABLE_NFQUEUE */ - -struct lan_addr_list lan_addrs; - -#ifdef ENABLE_IPV6 -/* ipv6 address used for HTTP */ -char ipv6_addr_for_http_with_brackets[64]; - -/* address used to bind local services */ -struct in6_addr ipv6_bind_addr; -#endif - -/* Path of the Unix socket used to communicate with MiniSSDPd */ -const char * minissdpdsocketpath = "/var/run/minissdpd.sock"; - -/* BOOTID.UPNP.ORG and CONFIGID.UPNP.ORG */ -/* See UPnP Device Architecture v1.1 section 1.2 Advertisement : - * The field value of the BOOTID.UPNP.ORG header field MUST be increased - * each time a device (re)joins the network and sends an initial announce - * (a "reboot" in UPnP terms), or adds a UPnP-enabled interface. - * Unless the device explicitly announces a change in the BOOTID.UPNP.ORG - * field value using an SSDP message, as long as the device remains - * continuously available in the network, the same BOOTID.UPNP.ORG field - * value MUST be used in all repeat announcements, search responses, - * update messages and eventually bye-bye messages. */ -unsigned int upnp_bootid = 1; /* BOOTID.UPNP.ORG */ -/* The field value of the CONFIGID.UPNP.ORG header field identifies the - * current set of device and service descriptions; control points can - * parse this header field to detect whether they need to send new - * description query messages. */ -/* UPnP 1.1 devices MAY freely assign configid numbers from 0 to - * 16777215 (2^24-1). Higher numbers are reserved for future use, and - * can be assigned by the Technical Committee. The configuration of a - * root device consists of the following information: the DDD of the - * root device and all its embedded devices, and the SCPDs of all the - * contained services. If any part of the configuration changes, the - * CONFIGID.UPNP.ORG field value MUST be changed. - * DDD = Device Description Document - * SCPD = Service Control Protocol Description */ -unsigned int upnp_configid = 1337; /* CONFIGID.UPNP.ORG */ - -#ifdef RANDOMIZE_URLS -char random_url[RANDOM_URL_MAX_LEN] = "random"; -#endif /* RANDOMIZE_URLS */ - diff --git a/src/contrib/miniupnp/miniupnpd/upnpglobalvars.h b/src/contrib/miniupnp/miniupnpd/upnpglobalvars.h deleted file mode 100644 index 80f7a02..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpglobalvars.h +++ /dev/null @@ -1,168 +0,0 @@ -/* $Id: upnpglobalvars.h,v 1.45 2018/01/16 00:50:49 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPGLOBALVARS_H_INCLUDED -#define UPNPGLOBALVARS_H_INCLUDED - -#include -#include "upnppermissions.h" -#include "miniupnpdtypes.h" -#include "config.h" - -/* name of the network interface used to access internet */ -extern const char * ext_if_name; - -/* file to store all leases */ -#ifdef ENABLE_LEASEFILE -extern const char * lease_file; -#endif - -/* forced ip address to use for this interface - * when NULL, getifaddr() is used */ -extern const char * use_ext_ip_addr; - -/* parameters to return to upnp client when asked */ -extern unsigned long downstream_bitrate; -extern unsigned long upstream_bitrate; - -/* statup time */ -extern time_t startup_time; -#if defined(ENABLE_NATPMP) || defined(ENABLE_PCP) -/* origin for "epoch time" sent into NATPMP and PCP responses */ -extern time_t epoch_origin; -#endif /* defined(ENABLE_NATPMP) || defined(ENABLE_PCP) */ - -extern unsigned long int min_lifetime; -extern unsigned long int max_lifetime; - -/* runtime boolean flags */ -extern int runtime_flags; -#define LOGPACKETSMASK 0x0001 -#define SYSUPTIMEMASK 0x0002 -#ifdef ENABLE_NATPMP -#define ENABLENATPMPMASK 0x0004 -#endif -#define CHECKCLIENTIPMASK 0x0008 -#define SECUREMODEMASK 0x0010 - -#define ENABLEUPNPMASK 0x0020 - -#ifdef PF_ENABLE_FILTER_RULES -#define PFNOQUICKRULESMASK 0x0040 -#endif -#ifdef ENABLE_IPV6 -#define IPV6DISABLEDMASK 0x0080 -#endif -#ifdef ENABLE_6FC_SERVICE -#define IPV6FCFWDISABLEDMASK 0x0100 -#define IPV6FCINBOUNDDISALLOWEDMASK 0x0200 -#endif -#ifdef ENABLE_PCP -#define PCP_ALLOWTHIRDPARTYMASK 0x0400 -#endif -#ifdef IGD_V2 -#define FORCEIGDDESCV1MASK 0x0800 -#endif - -#define SETFLAG(mask) runtime_flags |= mask -#define GETFLAG(mask) (runtime_flags & mask) -#define CLEARFLAG(mask) runtime_flags &= ~mask - -extern const char * pidfilename; - -extern char uuidvalue_igd[]; /* uuid of root device (IGD) */ -extern char uuidvalue_wan[]; /* uuid of WAN Device */ -extern char uuidvalue_wcd[]; /* uuid of WAN Connection Device */ - -#define SERIALNUMBER_MAX_LEN (10) -extern char serialnumber[]; - -#define MODELNUMBER_MAX_LEN (48) -extern char modelnumber[]; - -#define PRESENTATIONURL_MAX_LEN (64) -extern char presentationurl[]; - -#ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION -#define FRIENDLY_NAME_MAX_LEN (64) -extern char friendly_name[]; - -#define MANUFACTURER_NAME_MAX_LEN (64) -extern char manufacturer_name[]; - -#define MANUFACTURER_URL_MAX_LEN (64) -extern char manufacturer_url[]; - -#define MODEL_NAME_MAX_LEN (64) -extern char model_name[]; - -#define MODEL_DESCRIPTION_MAX_LEN (64) -extern char model_description[]; - -#define MODEL_URL_MAX_LEN (64) -extern char model_url[]; -#endif - -/* UPnP permission rules : */ -extern struct upnpperm * upnppermlist; -extern unsigned int num_upnpperm; - -#ifdef PCP_SADSCP -extern struct dscp_values* dscp_values_list; -extern unsigned int num_dscp_values; -#endif - -/* For automatic removal of expired rules (with LeaseDuration) */ -extern unsigned int nextruletoclean_timestamp; - -#ifdef USE_PF -extern const char * anchor_name; -/* queue and tag for PF rules */ -extern const char * queue; -extern const char * tag; -#endif - -#ifdef USE_NETFILTER -extern const char * miniupnpd_nat_chain; -extern const char * miniupnpd_nat_postrouting_chain; -extern const char * miniupnpd_forward_chain; -#ifdef ENABLE_UPNPPINHOLE -extern const char * miniupnpd_v6_filter_chain; -#endif -#endif - -#ifdef ENABLE_NFQUEUE -extern int nfqueue; -extern int n_nfqix; -extern unsigned nfqix[]; -#endif - -/* lan addresses to listen to SSDP traffic */ -extern struct lan_addr_list lan_addrs; - -#ifdef ENABLE_IPV6 -/* ipv6 address used for HTTP */ -extern char ipv6_addr_for_http_with_brackets[64]; - -/* address used to bind local services */ -extern struct in6_addr ipv6_bind_addr; - -#endif /* ENABLE_IPV6 */ - -extern const char * minissdpdsocketpath; - -/* BOOTID.UPNP.ORG and CONFIGID.UPNP.ORG */ -extern unsigned int upnp_bootid; -extern unsigned int upnp_configid; - -#ifdef RANDOMIZE_URLS -#define RANDOM_URL_MAX_LEN (16) -extern char random_url[]; -#endif /* RANDOMIZE_URLS */ - -#endif /* UPNPGLOBALVARS_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/upnphttp.c b/src/contrib/miniupnp/miniupnpd/upnphttp.c deleted file mode 100644 index b12d180..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnphttp.c +++ /dev/null @@ -1,1307 +0,0 @@ -/* $Id: upnphttp.c,v 1.107 2018/01/16 00:50:49 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file included in this distribution. - * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "config.h" -#ifdef ENABLE_HTTP_DATE -#include -#endif -#include "upnphttp.h" -#include "upnpdescgen.h" -#include "miniupnpdpath.h" -#include "upnpsoap.h" -#include "upnpevents.h" -#include "upnputils.h" -#ifdef RANDOMIZE_URLS -#include "upnpglobalvars.h" -#endif /* RANDOMIZE_URLS */ - -#ifdef ENABLE_HTTPS -#include -#include -#include -static SSL_CTX *ssl_ctx = NULL; - -#ifndef HTTPS_CERTFILE -#define HTTPS_CERTFILE "/etc/ssl/certs/ssl-cert-snakeoil.pem" -#endif -#ifndef HTTPS_KEYFILE -#define HTTPS_KEYFILE "/etc/ssl/private/ssl-cert-snakeoil.key" -#endif - -static void -syslogsslerr(void) -{ - unsigned long err; - char buffer[256]; - while((err = ERR_get_error()) != 0) { - syslog(LOG_ERR, "%s", ERR_error_string(err, buffer)); - } -} - -static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) -{ - syslog(LOG_DEBUG, "verify_callback(%d, %p)", preverify_ok, ctx); - return preverify_ok; -} - -int init_ssl(void) -{ - const SSL_METHOD *method; - SSL_library_init(); - SSL_load_error_strings(); - method = TLSv1_server_method(); - if(method == NULL) { - syslog(LOG_ERR, "TLSv1_server_method() failed"); - syslogsslerr(); - return -1; - } - ssl_ctx = SSL_CTX_new(method); - if(ssl_ctx == NULL) { - syslog(LOG_ERR, "SSL_CTX_new() failed"); - syslogsslerr(); - return -1; - } - /* set the local certificate */ - if(!SSL_CTX_use_certificate_file(ssl_ctx, HTTPS_CERTFILE, SSL_FILETYPE_PEM)) { - syslog(LOG_ERR, "SSL_CTX_use_certificate_file(%s) failed", HTTPS_CERTFILE); - syslogsslerr(); - return -1; - } - /* set the private key */ - if(!SSL_CTX_use_PrivateKey_file(ssl_ctx, HTTPS_KEYFILE, SSL_FILETYPE_PEM)) { - syslog(LOG_ERR, "SSL_CTX_use_PrivateKey_file(%s) failed", HTTPS_KEYFILE); - syslogsslerr(); - return -1; - } - /* verify private key */ - if(!SSL_CTX_check_private_key(ssl_ctx)) { - syslog(LOG_ERR, "SSL_CTX_check_private_key() failed"); - syslogsslerr(); - return -1; - } - /*SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verify_callback);*/ - SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, verify_callback); - /*SSL_CTX_set_verify_depth(depth);*/ - syslog(LOG_INFO, "using %s", SSLeay_version(SSLEAY_VERSION)); - return 0; -} - -void free_ssl(void) -{ - /* free context */ - if(ssl_ctx != NULL) { - SSL_CTX_free(ssl_ctx); - ssl_ctx = NULL; - } - ERR_remove_state(0); - ENGINE_cleanup(); - CONF_modules_unload(1); - ERR_free_strings(); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); -} -#endif /* ENABLE_HTTPS */ - -struct upnphttp * -New_upnphttp(int s) -{ - struct upnphttp * ret; - if(s<0) - return NULL; - ret = (struct upnphttp *)malloc(sizeof(struct upnphttp)); - if(ret == NULL) - return NULL; - memset(ret, 0, sizeof(struct upnphttp)); - ret->socket = s; - if(!set_non_blocking(s)) - syslog(LOG_WARNING, "New_upnphttp::set_non_blocking(): %m"); - return ret; -} - -#ifdef ENABLE_HTTPS -void -InitSSL_upnphttp(struct upnphttp * h) -{ - int r; - h->ssl = SSL_new(ssl_ctx); - if(h->ssl == NULL) { - syslog(LOG_ERR, "SSL_new() failed"); - syslogsslerr(); - abort(); - } - if(!SSL_set_fd(h->ssl, h->socket)) { - syslog(LOG_ERR, "SSL_set_fd() failed"); - syslogsslerr(); - abort(); - } - r = SSL_accept(h->ssl); /* start the handshaking */ - if(r < 0) { - int err; - err = SSL_get_error(h->ssl, r); - syslog(LOG_DEBUG, "SSL_accept() returned %d, SSL_get_error() %d", r, err); - if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { - syslog(LOG_ERR, "SSL_accept() failed"); - syslogsslerr(); - abort(); - } - } -} -#endif /* ENABLE_HTTPS */ - -void -CloseSocket_upnphttp(struct upnphttp * h) -{ - /* SSL_shutdown() ? */ - if(close(h->socket) < 0) - { - syslog(LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket); - } - h->socket = -1; - h->state = EToDelete; -} - -void -Delete_upnphttp(struct upnphttp * h) -{ - if(h) - { -#ifdef ENABLE_HTTPS - if(h->ssl) - SSL_free(h->ssl); -#endif - if(h->socket >= 0) - CloseSocket_upnphttp(h); - if(h->req_buf) - free(h->req_buf); - if(h->res_buf) - free(h->res_buf); - free(h); - } -} - -/* parse HttpHeaders of the REQUEST - * This function is called after the \r\n\r\n character - * sequence has been found in h->req_buf */ -static void -ParseHttpHeaders(struct upnphttp * h) -{ - char * line; - char * colon; - char * p; - int n; - if((h->req_buf == NULL) || (h->req_contentoff <= 0)) - return; - line = h->req_buf; - while(line < (h->req_buf + h->req_contentoff)) - { - colon = line; - while(*colon != ':') - { - if(*colon == '\r' || *colon == '\n') - { - colon = NULL; /* no ':' character found on the line */ - break; - } - colon++; - } - if(colon) - { - if(strncasecmp(line, "Content-Length:", 15)==0) - { - p = colon; - while((*p < '0' || *p > '9') && (*p != '\r') && (*p != '\n')) - p++; - h->req_contentlen = atoi(p); - if(h->req_contentlen < 0) { - syslog(LOG_WARNING, "ParseHttpHeaders() invalid Content-Length %d", h->req_contentlen); - h->req_contentlen = 0; - } - /*printf("*** Content-Lenght = %d ***\n", h->req_contentlen); - printf(" readbufflen=%d contentoff = %d\n", - h->req_buflen, h->req_contentoff);*/ - } - else if(strncasecmp(line, "Host:", 5)==0) - { - p = colon; - n = 0; - while(*p == ':' || *p == ' ' || *p == '\t') - p++; - while(p[n]>' ') - n++; - h->req_HostOff = p - h->req_buf; - h->req_HostLen = n; - } - else if(strncasecmp(line, "SOAPAction:", 11)==0) - { - p = colon; - n = 0; - while(*p == ':' || *p == ' ' || *p == '\t') - p++; - while(p[n]>=' ') - n++; - if((p[0] == '"' && p[n-1] == '"') - || (p[0] == '\'' && p[n-1] == '\'')) - { - p++; n -= 2; - } - h->req_soapActionOff = p - h->req_buf; - h->req_soapActionLen = n; - } - else if(strncasecmp(line, "accept-language:", 16) == 0) - { - p = colon; - n = 0; - while(*p == ':' || *p == ' ' || *p == '\t') - p++; - while(p[n]>=' ') - n++; - syslog(LOG_DEBUG, "accept-language HTTP header : '%.*s'", n, p); - /* keep only the 1st accepted language */ - n = 0; - while(p[n]>' ' && p[n] != ',') - n++; - if(n >= (int)sizeof(h->accept_language)) - n = (int)sizeof(h->accept_language) - 1; - memcpy(h->accept_language, p, n); - h->accept_language[n] = '\0'; - } - else if(strncasecmp(line, "expect:", 7) == 0) - { - p = colon; - n = 0; - while(*p == ':' || *p == ' ' || *p == '\t') - p++; - while(p[n]>=' ') - n++; - if(strncasecmp(p, "100-continue", 12) == 0) { - h->respflags |= FLAG_CONTINUE; - syslog(LOG_DEBUG, "\"Expect: 100-Continue\" header detected"); - } - } -#ifdef ENABLE_EVENTS - else if(strncasecmp(line, "Callback:", 9)==0) - { - /* The Callback can contain several urls : - * If there is more than one URL, when the service sends - * events, it will try these URLs in order until one - * succeeds. One or more URLs each enclosed by angle - * brackets ("<" and ">") */ - p = colon; - while(*p != '<' && *p != '\r' ) - p++; - n = 0; - while(p[n] != '\r') - n++; - while(n > 0 && p[n] != '>') - n--; - /* found last > character */ - h->req_CallbackOff = p - h->req_buf; - h->req_CallbackLen = MAX(0, n + 1); - } - else if(strncasecmp(line, "SID:", 4)==0) - { - p = colon + 1; - while((*p == ' ') || (*p == '\t')) - p++; - n = 0; - while(!isspace(p[n])) - n++; - h->req_SIDOff = p - h->req_buf; - h->req_SIDLen = n; - } - /* Timeout: Seconds-nnnn */ -/* TIMEOUT -Recommended. Requested duration until subscription expires, -either number of seconds or infinite. Recommendation -by a UPnP Forum working committee. Defined by UPnP vendor. - Consists of the keyword "Second-" followed (without an -intervening space) by either an integer or the keyword "infinite". */ - else if(strncasecmp(line, "Timeout:", 8)==0) - { - p = colon + 1; - while((*p == ' ') || (*p == '\t')) - p++; - if(strncasecmp(p, "Second-", 7)==0) { - h->req_Timeout = atoi(p+7); - } - } -#ifdef UPNP_STRICT - else if(strncasecmp(line, "nt:", 3)==0) - { - p = colon + 1; - while((*p == ' ') || (*p == '\t')) - p++; - n = 0; - while(!isspace(p[n])) - n++; - h->req_NTOff = p - h->req_buf; - h->req_NTLen = n; - } -#endif /* UPNP_STRICT */ -#endif /* ENABLE_EVENTS */ - } - /* the loop below won't run off the end of the buffer - * because the buffer is guaranteed to contain the \r\n\r\n - * character sequence */ - while(!(line[0] == '\r' && line[1] == '\n')) - line++; - line += 2; - } -} - -/* very minimalistic 404 error message */ -static void -Send404(struct upnphttp * h) -{ - static const char body404[] = - "404 Not Found" - "

Not Found

The requested URL was not found" - " on this server.\r\n"; - - h->respflags = FLAG_HTML; - BuildResp2_upnphttp(h, 404, "Not Found", - body404, sizeof(body404) - 1); - SendRespAndClose_upnphttp(h); -} - -static void -Send405(struct upnphttp * h) -{ - static const char body405[] = - "405 Method Not Allowed" - "

Method Not Allowed

The HTTP Method " - "is not allowed on this resource.\r\n"; - - h->respflags |= FLAG_HTML; - BuildResp2_upnphttp(h, 405, "Method Not Allowed", - body405, sizeof(body405) - 1); - SendRespAndClose_upnphttp(h); -} - -/* very minimalistic 501 error message */ -static void -Send501(struct upnphttp * h) -{ - static const char body501[] = - "501 Not Implemented" - "

Not Implemented

The HTTP Method " - "is not implemented by this server.\r\n"; - - h->respflags = FLAG_HTML; - BuildResp2_upnphttp(h, 501, "Not Implemented", - body501, sizeof(body501) - 1); - SendRespAndClose_upnphttp(h); -} - -/* findendheaders() find the \r\n\r\n character sequence and - * return a pointer to it. - * It returns NULL if not found */ -static const char * -findendheaders(const char * s, int len) -{ - while(len-->3) - { - if(s[0]=='\r' && s[1]=='\n' && s[2]=='\r' && s[3]=='\n') - return s; - s++; - } - return NULL; -} - -#ifdef HAS_DUMMY_SERVICE -static void -sendDummyDesc(struct upnphttp * h) -{ - static const char xml_desc[] = "\r\n" - "" - " " - " 1" - " 0" - " " - " " - " " - "\r\n"; - BuildResp_upnphttp(h, xml_desc, sizeof(xml_desc)-1); - SendRespAndClose_upnphttp(h); -} -#endif - -/* Sends the description generated by the parameter */ -static void -sendXMLdesc(struct upnphttp * h, char * (f)(int *)) -{ - char * desc; - int len; - desc = f(&len); - if(!desc) - { - static const char error500[] = "Error 500" - "Internal Server Error\r\n"; - syslog(LOG_ERR, "Failed to generate XML description"); - h->respflags = FLAG_HTML; - BuildResp2_upnphttp(h, 500, "Internal Server Error", - error500, sizeof(error500)-1); - } - else - { - BuildResp_upnphttp(h, desc, len); - } - SendRespAndClose_upnphttp(h); - free(desc); -} - -/* ProcessHTTPPOST_upnphttp() - * executes the SOAP query if it is possible */ -static void -ProcessHTTPPOST_upnphttp(struct upnphttp * h) -{ - if((h->req_buflen - h->req_contentoff) >= h->req_contentlen) - { - /* the request body is received */ - if(h->req_soapActionOff > 0) - { - /* we can process the request */ - syslog(LOG_INFO, "SOAPAction: %.*s", - h->req_soapActionLen, h->req_buf + h->req_soapActionOff); - ExecuteSoapAction(h, - h->req_buf + h->req_soapActionOff, - h->req_soapActionLen); - } - else - { - static const char err400str[] = - "Bad request"; - syslog(LOG_INFO, "No SOAPAction in HTTP headers"); - h->respflags = FLAG_HTML; - BuildResp2_upnphttp(h, 400, "Bad Request", - err400str, sizeof(err400str) - 1); - SendRespAndClose_upnphttp(h); - } - } - else if(h->respflags & FLAG_CONTINUE) - { - /* Sending the 100 Continue response */ - if(!h->res_buf) { - h->res_buf = malloc(256); - h->res_buf_alloclen = 256; - } - h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, - "%s 100 Continue\r\n\r\n", h->HttpVer); - h->res_sent = 0; - h->state = ESendingContinue; - if(SendResp_upnphttp(h)) - h->state = EWaitingForHttpContent; - } - else - { - /* waiting for remaining data */ - h->state = EWaitingForHttpContent; - } -} - -#ifdef ENABLE_EVENTS -/** - * checkCallbackURL() - * check that url is on originating IP - * extract first correct URL - * returns 0 if the callback header value is not valid - * 1 if it is valid. - */ -static int -checkCallbackURL(struct upnphttp * h) -{ - char addrstr[48]; - int ipv6; - const char * p; - unsigned int i; - -start_again: - if(h->req_CallbackOff <= 0 || h->req_CallbackLen < 10) - return 0; - if(memcmp(h->req_buf + h->req_CallbackOff, "req_buf + h->req_CallbackOff + 1; - goto invalid; - } - /* extract host from url to addrstr[] */ - i = 0; - p = h->req_buf + h->req_CallbackOff + 8; - if(*p == '[') { - p++; - ipv6 = 1; - while(*p != ']' && *p != '>' && i < (sizeof(addrstr)-1) - && p < (h->req_buf + h->req_CallbackOff + h->req_CallbackLen)) - addrstr[i++] = *(p++); - } else { - ipv6 = 0; - while(*p != '/' && *p != ':' && *p != '>' && i < (sizeof(addrstr)-1) - && p < (h->req_buf + h->req_CallbackOff + h->req_CallbackLen)) - addrstr[i++] = *(p++); - } - addrstr[i] = '\0'; - /* check addrstr */ - if(ipv6) { -#ifdef ENABLE_IPV6 - struct in6_addr addr; - if(inet_pton(AF_INET6, addrstr, &addr) <= 0) - goto invalid; - if(!h->ipv6 - || (0!=memcmp(&addr, &(h->clientaddr_v6), sizeof(struct in6_addr)))) - goto invalid; -#else - goto invalid; -#endif - } else { - struct in_addr addr; - if(inet_pton(AF_INET, addrstr, &addr) <= 0) - goto invalid; -#ifdef ENABLE_IPV6 - if(h->ipv6) { - if(!IN6_IS_ADDR_V4MAPPED(&(h->clientaddr_v6))) - goto invalid; - if(0!=memcmp(&addr, ((const char *)&(h->clientaddr_v6) + 12), 4)) - goto invalid; - } else { - if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) - goto invalid; - } -#else - if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) - goto invalid; -#endif - } - /* select only the good callback url */ - while(p < h->req_buf + h->req_CallbackOff + h->req_CallbackLen && *p != '>') - p++; - h->req_CallbackOff++; /* skip initial '<' */ - h->req_CallbackLen = (int)(p - h->req_buf - h->req_CallbackOff); - return 1; -invalid: - while(p < h->req_buf + h->req_CallbackOff + h->req_CallbackLen && *p != '>') - p++; - if(*p != '>') return 0; - while(p < h->req_buf + h->req_CallbackOff + h->req_CallbackLen && *p != '<') - p++; - if(*p != '<') return 0; - h->req_CallbackLen -= (int)(p - h->req_buf - h->req_CallbackOff); - h->req_CallbackOff = (int)(p - h->req_buf); - goto start_again; -} - -static void -ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) -{ - const char * sid; - syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path); - syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d", - h->req_CallbackLen, h->req_buf + h->req_CallbackOff, - h->req_Timeout); - syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_buf + h->req_SIDOff); -#if defined(UPNP_STRICT) && (UPNP_VERSION_MAJOR > 1) || (UPNP_VERSION_MINOR > 0) - /*if(h->req_Timeout < 1800) {*/ - if(h->req_Timeout == 0) { - /* Second-infinite is forbidden with UDA v1.1 and later : - * (UDA 1.1 : 4.1.1 Subscription) - * UPnP 1.1 control points MUST NOT subscribe using keyword infinite, - * UPnP 1.1 devices MUST NOT set actual subscription durations to - * "infinite". The presence of infinite in a request MUST be silently - * ignored by a UPnP 1.1 device (the presence of infinite is handled - * by the device as if the TIMEOUT header field in a request was not - * present) . The keyword infinite MUST NOT be returned by a UPnP 1.1 - * device. */ - h->req_Timeout = 1800; /* default to 30 minutes */ - } -#endif /* UPNP_STRICT */ - if((h->req_CallbackOff <= 0) && (h->req_SIDOff <= 0)) { - /* Missing or invalid CALLBACK : 412 Precondition Failed. - * If CALLBACK header is missing or does not contain a valid HTTP URL, - * the publisher must respond with HTTP error 412 Precondition Failed*/ - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - SendRespAndClose_upnphttp(h); - } else { - /* - add to the subscriber list - * - respond HTTP/x.x 200 OK - * - Send the initial event message */ -/* Server:, SID:; Timeout: Second-(xx|infinite) */ - /* Check that the callback URL is on the same IP as - * the request, and not on the internet, nor on ourself (DOS attack ?) */ - if(h->req_CallbackOff > 0) { -#ifdef UPNP_STRICT - /* SID: and Callback: are incompatible */ - if(h->req_SIDOff > 0) { - syslog(LOG_WARNING, "Both Callback: and SID: in SUBSCRIBE"); - BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); - /* "NT: upnp:event" header is mandatory */ - } else if(h->req_NTOff <= 0 || h->req_NTLen != 10 || - 0 != memcmp("upnp:event", h->req_buf + h->req_NTOff, 10)) { - syslog(LOG_WARNING, "Invalid NT in SUBSCRIBE %.*s", - h->req_NTLen, h->req_buf + h->req_NTOff); - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - } else -#endif - if(checkCallbackURL(h)) { - sid = upnpevents_addSubscriber(path, h->req_buf + h->req_CallbackOff, - h->req_CallbackLen, h->req_Timeout); - h->respflags = FLAG_TIMEOUT; - if(sid) { - syslog(LOG_DEBUG, "generated sid=%s", sid); - h->respflags |= FLAG_SID; - h->res_SID = sid; - } - BuildResp_upnphttp(h, 0, 0); - } else { - syslog(LOG_WARNING, "Invalid Callback in SUBSCRIBE %.*s", - h->req_CallbackLen, h->req_buf + h->req_CallbackOff); - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - } - } else { - /* subscription renew */ - /* Invalid SID -412 Precondition Failed. If a SID does not correspond to a known, -un-expired subscription, the publisher must respond -with HTTP error 412 Precondition Failed. */ -#ifdef UPNP_STRICT - /* SID: and NT: headers are incompatibles */ - if(h->req_NTOff > 0) { - syslog(LOG_WARNING, "Both NT: and SID: in SUBSCRIBE"); - BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); - } else { -#endif /* UPNP_STRICT */ - sid = upnpevents_renewSubscription(h->req_buf + h->req_SIDOff, - h->req_SIDLen, h->req_Timeout); - if(!sid) { - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - } else { - h->respflags = FLAG_TIMEOUT | FLAG_SID; - h->res_SID = sid; - BuildResp_upnphttp(h, 0, 0); - } -#ifdef UPNP_STRICT - } -#endif /* UPNP_STRICT */ - } - SendRespAndClose_upnphttp(h); - } -} - -static void -ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path) -{ - syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path); - syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_buf + h->req_SIDOff); - /* Remove from the list */ -#ifdef UPNP_STRICT - if(h->req_SIDOff <= 0 || h->req_SIDLen == 0) { - /* SID: header missing or empty */ - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - } else if(h->req_CallbackOff > 0 || h->req_NTOff > 0) { - /* no NT: or Callback: header must be present */ - BuildResp2_upnphttp(h, 400, "Incompatible header fields", 0, 0); - } else -#endif - if(upnpevents_removeSubscriber(h->req_buf + h->req_SIDOff, h->req_SIDLen) < 0) { - BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); - } else { - BuildResp_upnphttp(h, 0, 0); - } - SendRespAndClose_upnphttp(h); -} -#endif - -/* Parse and process Http Query - * called once all the HTTP headers have been received, - * so it is guaranteed that h->req_buf contains the \r\n\r\n - * character sequence */ -static void -ProcessHttpQuery_upnphttp(struct upnphttp * h) -{ - static const struct { - const char * path; - char * (* f)(int *); - } path_desc[] = { - { ROOTDESC_PATH, genRootDesc}, - { WANIPC_PATH, genWANIPCn}, - { WANCFG_PATH, genWANCfg}, -#ifdef HAS_DUMMY_SERVICE - { DUMMY_PATH, NULL}, -#endif -#ifdef ENABLE_L3F_SERVICE - { L3F_PATH, genL3F}, -#endif -#ifdef ENABLE_6FC_SERVICE - { WANIP6FC_PATH, gen6FC}, -#endif -#ifdef ENABLE_DP_SERVICE - { DP_PATH, genDP}, -#endif - { NULL, NULL} - }; - char HttpCommand[16]; - char HttpUrl[128]; - char * HttpVer; - char * p; - int i; - - p = h->req_buf; - if(!p) - return; - /* note : checking (*p != '\r') is enough to avoid running off the - * end of the buffer, because h->req_buf is guaranteed to contain - * the \r\n\r\n character sequence */ - for(i = 0; i<15 && *p != ' ' && *p != '\r'; i++) - HttpCommand[i] = *(p++); - HttpCommand[i] = '\0'; - while(*p==' ') - p++; - for(i = 0; i<127 && *p != ' ' && *p != '\r'; i++) - HttpUrl[i] = *(p++); - HttpUrl[i] = '\0'; - while(*p==' ') - p++; - HttpVer = h->HttpVer; - for(i = 0; i<15 && *p != '\r'; i++) - HttpVer[i] = *(p++); - HttpVer[i] = '\0'; - syslog(LOG_INFO, "HTTP REQUEST from %s : %s %s (%s)", - h->clientaddr_str, HttpCommand, HttpUrl, HttpVer); - ParseHttpHeaders(h); - if(h->req_HostOff > 0 && h->req_HostLen > 0) { - syslog(LOG_DEBUG, "Host: %.*s", h->req_HostLen, h->req_buf + h->req_HostOff); - p = h->req_buf + h->req_HostOff; - if(*p == '[') { - /* IPv6 */ - p++; - while(p < h->req_buf + h->req_HostOff + h->req_HostLen) { - if(*p == ']') break; - /* TODO check *p in [0-9a-f:.] */ - p++; - } - if(*p != ']') { - syslog(LOG_NOTICE, "DNS rebinding attack suspected (Host: %.*s)", h->req_HostLen, h->req_buf + h->req_HostOff); - Send404(h);/* 403 */ - return; - } - p++; - /* TODO : Check port */ - } else { - for(i = 0; i < h->req_HostLen; i++) { - if(*p != ':' && *p != '.' && (*p > '9' || *p < '0')) { - syslog(LOG_NOTICE, "DNS rebinding attack suspected (Host: %.*s)", h->req_HostLen, h->req_buf + h->req_HostOff); - Send404(h);/* 403 */ - return; - } - p++; - } - } - } -#ifdef RANDOMIZE_URLS - /* first check if the URL begins with the randomized string */ - if(HttpUrl[0] != '/' || memcmp(HttpUrl+1, random_url, strlen(random_url)) != 0) - { - Send404(h); - return; - } - /* remove "random" from the start of the URL */ - p = HttpUrl + strlen(random_url) + 1; - memmove(HttpUrl, p, strlen(p) + 1); -#endif /* RANDOMIZE_URLS */ - if(strcmp("POST", HttpCommand) == 0) - { - h->req_command = EPost; - ProcessHTTPPOST_upnphttp(h); - } - else if(strcmp("GET", HttpCommand) == 0) - { - h->req_command = EGet; - for(i=0; path_desc[i].path; i++) { - if(strcasecmp(path_desc[i].path, HttpUrl) == 0) { - if(path_desc[i].f) - sendXMLdesc(h, path_desc[i].f); - else -#ifdef HAS_DUMMY_SERVICE - sendDummyDesc(h); -#else - continue; -#endif - return; - } - } - if(0 == memcmp(HttpUrl, "/ctl/", 5)) { - /* 405 Method Not Allowed - * Allow: POST */ - h->respflags = FLAG_ALLOW_POST; - Send405(h); - return; - } -#ifdef ENABLE_EVENTS - if(0 == memcmp(HttpUrl, "/evt/", 5)) { - /* 405 Method Not Allowed - * Allow: SUBSCRIBE, UNSUBSCRIBE */ - h->respflags = FLAG_ALLOW_SUB_UNSUB; - Send405(h); - return; - } -#endif - syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); - Send404(h); - } -#ifdef ENABLE_EVENTS - else if(strcmp("SUBSCRIBE", HttpCommand) == 0) - { - h->req_command = ESubscribe; - ProcessHTTPSubscribe_upnphttp(h, HttpUrl); - } - else if(strcmp("UNSUBSCRIBE", HttpCommand) == 0) - { - h->req_command = EUnSubscribe; - ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl); - } -#else - else if(strcmp("SUBSCRIBE", HttpCommand) == 0) - { - syslog(LOG_NOTICE, "SUBSCRIBE not implemented. ENABLE_EVENTS compile option disabled"); - Send501(h); - } -#endif - else - { - syslog(LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand); - Send501(h); - } -} - - -void -Process_upnphttp(struct upnphttp * h) -{ - char * h_tmp; - char buf[2048]; - int n; - - if(!h) - return; - switch(h->state) - { - case EWaitingForHttpRequest: -#ifdef ENABLE_HTTPS - if(h->ssl) { - n = SSL_read(h->ssl, buf, sizeof(buf)); - } else { - n = recv(h->socket, buf, sizeof(buf), 0); - } -#else - n = recv(h->socket, buf, sizeof(buf), 0); -#endif - if(n<0) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - int err; - err = SSL_get_error(h->ssl, n); - if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) - { - syslog(LOG_ERR, "SSL_read() failed"); - syslogsslerr(); - h->state = EToDelete; - } - } else { -#endif - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) - { - syslog(LOG_ERR, "recv (state0): %m"); - h->state = EToDelete; - } - /* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */ -#ifdef ENABLE_HTTPS - } -#endif - } - else if(n==0) - { - syslog(LOG_WARNING, "HTTP Connection from %s closed unexpectedly", inet_ntoa(h->clientaddr)); - h->state = EToDelete; - } - else - { - const char * endheaders; - /* if 1st arg of realloc() is null, - * realloc behaves the same as malloc() */ - h_tmp = (char *)realloc(h->req_buf, n + h->req_buflen + 1); - if (h_tmp == NULL) - { - syslog(LOG_WARNING, "Unable to allocate new memory for h->req_buf)"); - h->state = EToDelete; - } - else - { - h->req_buf = h_tmp; - memcpy(h->req_buf + h->req_buflen, buf, n); - h->req_buflen += n; - h->req_buf[h->req_buflen] = '\0'; - } - /* search for the string "\r\n\r\n" */ - endheaders = findendheaders(h->req_buf, h->req_buflen); - if(endheaders) - { - /* at this point, the request buffer (h->req_buf) - * is guaranteed to contain the \r\n\r\n character sequence */ - h->req_contentoff = endheaders - h->req_buf + 4; - ProcessHttpQuery_upnphttp(h); - } - } - break; - case EWaitingForHttpContent: -#ifdef ENABLE_HTTPS - if(h->ssl) { - n = SSL_read(h->ssl, buf, sizeof(buf)); - } else { - n = recv(h->socket, buf, sizeof(buf), 0); - } -#else - n = recv(h->socket, buf, sizeof(buf), 0); -#endif - if(n<0) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - int err; - err = SSL_get_error(h->ssl, n); - if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) - { - syslog(LOG_ERR, "SSL_read() failed"); - syslogsslerr(); - h->state = EToDelete; - } - } else { -#endif - if(errno != EAGAIN && - errno != EWOULDBLOCK && - errno != EINTR) - { - syslog(LOG_ERR, "recv (state1): %m"); - h->state = EToDelete; - } - /* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */ -#ifdef ENABLE_HTTPS - } -#endif - } - else if(n==0) - { - syslog(LOG_WARNING, "HTTP Connection from %s closed unexpectedly", inet_ntoa(h->clientaddr)); - h->state = EToDelete; - } - else - { - void * tmp = realloc(h->req_buf, n + h->req_buflen); - if(!tmp) - { - syslog(LOG_ERR, "memory allocation error %m"); - h->state = EToDelete; - } - else - { - h->req_buf = tmp; - memcpy(h->req_buf + h->req_buflen, buf, n); - h->req_buflen += n; - if((h->req_buflen - h->req_contentoff) >= h->req_contentlen) - { - ProcessHTTPPOST_upnphttp(h); - } - } - } - break; - case ESendingContinue: - if(SendResp_upnphttp(h)) - h->state = EWaitingForHttpContent; - break; - case ESendingAndClosing: - SendRespAndClose_upnphttp(h); - break; - default: - syslog(LOG_WARNING, "Unexpected state: %d", h->state); - } -} - -static const char httpresphead[] = - "%s %d %s\r\n" - "Content-Type: %s\r\n" - "Connection: close\r\n" - "Content-Length: %d\r\n" - "Server: " MINIUPNPD_SERVER_STRING "\r\n" - "Ext:\r\n" - ; /*"\r\n";*/ -/* - "\n" - "" - "" - - "" - ""; -*/ -/* with response code and response message - * also allocate enough memory */ - -int -BuildHeader_upnphttp(struct upnphttp * h, int respcode, - const char * respmsg, - int bodylen) -{ - int templen; - if(!h->res_buf || - h->res_buf_alloclen < ((int)sizeof(httpresphead) + 256 + bodylen)) { - if(h->res_buf) - free(h->res_buf); - templen = sizeof(httpresphead) + 256 + bodylen; - h->res_buf = (char *)malloc(templen); - if(!h->res_buf) { - syslog(LOG_ERR, "malloc error in BuildHeader_upnphttp()"); - return -1; - } - h->res_buf_alloclen = templen; - } - h->res_sent = 0; - h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, - httpresphead, h->HttpVer, - respcode, respmsg, - (h->respflags&FLAG_HTML)?"text/html":"text/xml; charset=\"utf-8\"", - bodylen); - /* Content-Type MUST be 'text/xml; charset="utf-8"' according to UDA v1.1 */ - /* Content-Type MUST be 'text/xml' according to UDA v1.0 */ - /* Additional headers */ -#ifdef ENABLE_HTTP_DATE - { - char http_date[64]; - time_t t; - struct tm tm; - time(&t); - gmtime_r(&t, &tm); - /* %a and %b depend on locale */ - strftime(http_date, sizeof(http_date), - "%a, %d %b %Y %H:%M:%S GMT", &tm); - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Date: %s\r\n", http_date); - } -#endif -#ifdef ENABLE_EVENTS - if(h->respflags & FLAG_TIMEOUT) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Timeout: Second-"); - if(h->req_Timeout) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "%d\r\n", h->req_Timeout); - } else { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "infinite\r\n"); - } - } - if(h->respflags & FLAG_SID) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "SID: %s\r\n", h->res_SID); - } -#endif - if(h->respflags & FLAG_ALLOW_POST) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Allow: %s\r\n", "POST"); - } else if(h->respflags & FLAG_ALLOW_SUB_UNSUB) { - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Allow: %s\r\n", "SUBSCRIBE, UNSUBSCRIBE"); - } - if(h->accept_language[0] != '\0') { - /* defaulting to "en" */ - h->res_buflen += snprintf(h->res_buf + h->res_buflen, - h->res_buf_alloclen - h->res_buflen, - "Content-Language: %s\r\n", - h->accept_language[0] == '*' ? "en" : h->accept_language); - } - h->res_buf[h->res_buflen++] = '\r'; - h->res_buf[h->res_buflen++] = '\n'; - if(h->res_buf_alloclen < (h->res_buflen + bodylen)) - { - char * tmp; - tmp = (char *)realloc(h->res_buf, (h->res_buflen + bodylen)); - if(tmp) - { - h->res_buf = tmp; - h->res_buf_alloclen = h->res_buflen + bodylen; - } - else - { - syslog(LOG_ERR, "realloc error in BuildHeader_upnphttp()"); - return -1; - } - } - return 0; -} - -void -BuildResp2_upnphttp(struct upnphttp * h, int respcode, - const char * respmsg, - const char * body, int bodylen) -{ - int r = BuildHeader_upnphttp(h, respcode, respmsg, bodylen); - if(body && (r >= 0)) { - memcpy(h->res_buf + h->res_buflen, body, bodylen); - h->res_buflen += bodylen; - } -} - -/* responding 200 OK ! */ -void -BuildResp_upnphttp(struct upnphttp * h, - const char * body, int bodylen) -{ - BuildResp2_upnphttp(h, 200, "OK", body, bodylen); -} - -int -SendResp_upnphttp(struct upnphttp * h) -{ - ssize_t n; - - while (h->res_sent < h->res_buflen) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - n = SSL_write(h->ssl, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent); - } else { - n = send(h->socket, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent, 0); - } -#else - n = send(h->socket, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent, 0); -#endif - if(n<0) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - int err; - err = SSL_get_error(h->ssl, n); - if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - /* try again later */ - return 0; - } - syslog(LOG_ERR, "SSL_write() failed"); - syslogsslerr(); - break; - } else { -#endif - if(errno == EINTR) - continue; /* try again immediately */ - if(errno == EAGAIN || errno == EWOULDBLOCK) - { - /* try again later */ - return 0; - } - syslog(LOG_ERR, "send(res_buf): %m"); - break; /* avoid infinite loop */ -#ifdef ENABLE_HTTPS - } -#endif - } - else if(n == 0) - { - syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)", - h->res_sent, h->res_buflen); - break; - } - else - { - h->res_sent += n; - } - } - return 1; /* finished */ -} - -void -SendRespAndClose_upnphttp(struct upnphttp * h) -{ - ssize_t n; - - while (h->res_sent < h->res_buflen) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - n = SSL_write(h->ssl, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent); - } else { - n = send(h->socket, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent, 0); - } -#else - n = send(h->socket, h->res_buf + h->res_sent, - h->res_buflen - h->res_sent, 0); -#endif - if(n<0) - { -#ifdef ENABLE_HTTPS - if(h->ssl) { - int err; - err = SSL_get_error(h->ssl, n); - if(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { - /* try again later */ - h->state = ESendingAndClosing; - return; - } - syslog(LOG_ERR, "SSL_write() failed"); - syslogsslerr(); - break; /* avoid infinite loop */ - } else { -#endif - if(errno == EINTR) - continue; /* try again immediately */ - if(errno == EAGAIN || errno == EWOULDBLOCK) - { - /* try again later */ - h->state = ESendingAndClosing; - return; - } - syslog(LOG_ERR, "send(res_buf): %m"); - break; /* avoid infinite loop */ -#ifdef ENABLE_HTTPS - } -#endif - } - else if(n == 0) - { - syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)", - h->res_sent, h->res_buflen); - break; - } - else - { - h->res_sent += n; - } - } - CloseSocket_upnphttp(h); -} - diff --git a/src/contrib/miniupnp/miniupnpd/upnphttp.h b/src/contrib/miniupnp/miniupnpd/upnphttp.h deleted file mode 100644 index bf48b47..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnphttp.h +++ /dev/null @@ -1,165 +0,0 @@ -/* $Id: upnphttp.h,v 1.42 2015/12/16 10:21:49 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2015 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPHTTP_H_INCLUDED -#define UPNPHTTP_H_INCLUDED - -#include -#include - -#include "config.h" - -#ifdef ENABLE_HTTPS -#include -#endif /* ENABLE_HTTPS */ - -#define UPNP_VERSION_STRING "UPnP/" UPNP_VERSION_MAJOR_STR "." UPNP_VERSION_MINOR_STR - -/* server: HTTP header returned in all HTTP responses : */ -#define MINIUPNPD_SERVER_STRING OS_VERSION " " UPNP_VERSION_STRING " MiniUPnPd/" MINIUPNPD_VERSION - -/* - states : - 0 - waiting for data to read - 1 - waiting for HTTP Post Content. - ... - >= 100 - to be deleted -*/ -enum httpStates { - EWaitingForHttpRequest = 0, - EWaitingForHttpContent, - ESendingContinue, - ESendingAndClosing, - EToDelete = 100 -}; - -enum httpCommands { - EUnknown = 0, - EGet, - EPost, - ESubscribe, - EUnSubscribe -}; - -struct upnphttp { - int socket; - struct in_addr clientaddr; /* client address */ -#ifdef ENABLE_IPV6 - int ipv6; - struct in6_addr clientaddr_v6; -#endif /* ENABLE_IPV6 */ -#ifdef ENABLE_HTTPS - SSL * ssl; -#endif /* ENABLE_HTTPS */ - char clientaddr_str[64]; /* used for syslog() output */ - enum httpStates state; - char HttpVer[16]; - /* request */ - char * req_buf; - char accept_language[8]; - int req_buflen; - int req_contentlen; - int req_contentoff; /* header length */ - enum httpCommands req_command; - int req_soapActionOff; - int req_soapActionLen; - int req_HostOff; /* Host: header */ - int req_HostLen; -#ifdef ENABLE_EVENTS - int req_CallbackOff; /* For SUBSCRIBE */ - int req_CallbackLen; - int req_Timeout; - int req_SIDOff; /* For UNSUBSCRIBE */ - int req_SIDLen; - const char * res_SID; -#ifdef UPNP_STRICT - int req_NTOff; - int req_NTLen; -#endif -#endif - int respflags; /* see FLAG_* constants below */ - /* response */ - char * res_buf; - int res_buflen; - int res_sent; - int res_buf_alloclen; - LIST_ENTRY(upnphttp) entries; -}; - -/* Include the "Timeout:" header in response */ -#define FLAG_TIMEOUT 0x01 -/* Include the "SID:" header in response */ -#define FLAG_SID 0x02 - -/* If set, the POST request included a "Expect: 100-continue" header */ -#define FLAG_CONTINUE 0x40 - -/* If set, the Content-Type is set to text/xml, otherwise it is text/xml */ -#define FLAG_HTML 0x80 - -/* If set, the corresponding Allow: header is set */ -#define FLAG_ALLOW_POST 0x100 -#define FLAG_ALLOW_SUB_UNSUB 0x200 - -#ifdef ENABLE_HTTPS -int init_ssl(void); -void free_ssl(void); -#endif /* ENABLE_HTTPS */ - -/* New_upnphttp() */ -struct upnphttp * -New_upnphttp(int); - -#ifdef ENABLE_HTTPS -void -InitSSL_upnphttp(struct upnphttp *); -#endif /* ENABLE_HTTPS */ - -/* CloseSocket_upnphttp() */ -void -CloseSocket_upnphttp(struct upnphttp *); - -/* Delete_upnphttp() */ -void -Delete_upnphttp(struct upnphttp *); - -/* Process_upnphttp() */ -void -Process_upnphttp(struct upnphttp *); - -/* BuildHeader_upnphttp() - * build the header for the HTTP Response - * also allocate the buffer for body data - * return -1 on error */ -int -BuildHeader_upnphttp(struct upnphttp * h, int respcode, - const char * respmsg, - int bodylen); - -/* BuildResp_upnphttp() - * fill the res_buf buffer with the complete - * HTTP 200 OK response from the body passed as argument */ -void -BuildResp_upnphttp(struct upnphttp *, const char *, int); - -/* BuildResp2_upnphttp() - * same but with given response code/message */ -void -BuildResp2_upnphttp(struct upnphttp * h, int respcode, - const char * respmsg, - const char * body, int bodylen); - -int -SendResp_upnphttp(struct upnphttp *); - -/* SendRespAndClose_upnphttp() */ -void -SendRespAndClose_upnphttp(struct upnphttp *); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnppermissions.c b/src/contrib/miniupnp/miniupnpd/upnppermissions.c deleted file mode 100644 index ad02d8c..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnppermissions.c +++ /dev/null @@ -1,264 +0,0 @@ -/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "config.h" -#include "upnppermissions.h" - -/* read_permission_line() - * parse the a permission line which format is : - * (deny|allow) [0-9]+(-[0-9]+) ip/mask [0-9]+(-[0-9]+) - * ip/mask is either 192.168.1.1/24 or 192.168.1.1/255.255.255.0 - */ -int -read_permission_line(struct upnpperm * perm, - char * p) -{ - char * q; - int n_bits; - int i; - - /* first token: (allow|deny) */ - while(isspace(*p)) - p++; - if(0 == memcmp(p, "allow", 5)) - { - perm->type = UPNPPERM_ALLOW; - p += 5; - } - else if(0 == memcmp(p, "deny", 4)) - { - perm->type = UPNPPERM_DENY; - p += 4; - } - else - { - return -1; - } - while(isspace(*p)) - p++; - - /* second token: eport or eport_min-eport_max */ - if(!isdigit(*p)) - return -1; - for(q = p; isdigit(*q); q++); - if(*q=='-') - { - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->eport_min = (u_short)i; - q++; - p = q; - while(isdigit(*q)) - q++; - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->eport_max = (u_short)i; - if(perm->eport_min > perm->eport_max) - return -1; - } - else if(isspace(*q)) - { - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->eport_min = perm->eport_max = (u_short)i; - } - else - { - return -1; - } - p = q + 1; - while(isspace(*p)) - p++; - - /* third token: ip/mask */ - if(!isdigit(*p)) - return -1; - for(q = p; isdigit(*q) || (*q == '.'); q++); - if(*q=='/') - { - *q = '\0'; - if(!inet_aton(p, &perm->address)) - return -1; - q++; - p = q; - while(isdigit(*q)) - q++; - if(*q == '.') - { - while(*q == '.' || isdigit(*q)) - q++; - if(!isspace(*q)) - return -1; - *q = '\0'; - if(!inet_aton(p, &perm->mask)) - return -1; - } - else if(!isspace(*q)) - return -1; - else - { - *q = '\0'; - n_bits = atoi(p); - if(n_bits > 32) - return -1; - perm->mask.s_addr = htonl(n_bits ? (0xffffffffu << (32 - n_bits)) : 0); - } - } - else if(isspace(*q)) - { - *q = '\0'; - if(!inet_aton(p, &perm->address)) - return -1; - perm->mask.s_addr = 0xffffffffu; - } - else - { - return -1; - } - p = q + 1; - - /* fourth token: iport or iport_min-iport_max */ - while(isspace(*p)) - p++; - if(!isdigit(*p)) - return -1; - for(q = p; isdigit(*q); q++); - if(*q=='-') - { - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->iport_min = (u_short)i; - q++; - p = q; - while(isdigit(*q)) - q++; - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->iport_max = (u_short)i; - if(perm->iport_min > perm->iport_max) - return -1; - } - else if(isspace(*q) || *q == '\0') - { - *q = '\0'; - i = atoi(p); - if(i > 65535) - return -1; - perm->iport_min = perm->iport_max = (u_short)i; - } - else - { - return -1; - } -#ifdef DEBUG - printf("perm rule added : %s %hu-%hu %08x/%08x %hu-%hu\n", - (perm->type==UPNPPERM_ALLOW)?"allow":"deny", - perm->eport_min, perm->eport_max, ntohl(perm->address.s_addr), - ntohl(perm->mask.s_addr), perm->iport_min, perm->iport_max); -#endif - return 0; -} - -#ifdef USE_MINIUPNPDCTL -void -write_permlist(int fd, const struct upnpperm * permary, - int nperms) -{ - int l; - const struct upnpperm * perm; - int i; - char buf[128]; - write(fd, "Permissions :\n", 14); - for(i = 0; itype==UPNPPERM_ALLOW)?"allow":"deny", - perm->eport_min, perm->eport_max, ntohl(perm->address.s_addr), - ntohl(perm->mask.s_addr), perm->iport_min, perm->iport_max); - if(l<0) - return; - write(fd, buf, l); - } -} -#endif - -/* match_permission() - * returns: 1 if eport, address, iport matches the permission rule - * 0 if no match */ -static int -match_permission(const struct upnpperm * perm, - u_short eport, struct in_addr address, u_short iport) -{ - if( (eport < perm->eport_min) || (perm->eport_max < eport)) - return 0; - if( (iport < perm->iport_min) || (perm->iport_max < iport)) - return 0; - if( (address.s_addr & perm->mask.s_addr) - != (perm->address.s_addr & perm->mask.s_addr) ) - return 0; - return 1; -} - -#if 0 -/* match_permission_internal() - * returns: 1 if address, iport matches the permission rule - * 0 if no match */ -static int -match_permission_internal(const struct upnpperm * perm, - struct in_addr address, u_short iport) -{ - if( (iport < perm->iport_min) || (perm->iport_max < iport)) - return 0; - if( (address.s_addr & perm->mask.s_addr) - != (perm->address.s_addr & perm->mask.s_addr) ) - return 0; - return 1; -} -#endif - -int -check_upnp_rule_against_permissions(const struct upnpperm * permary, - int n_perms, - u_short eport, struct in_addr address, - u_short iport) -{ - int i; - for(i=0; i -#include -#include -#include "config.h" - -/* UPnP permission rule samples: - * allow 1024-65535 192.168.3.0/24 1024-65535 - * deny 0-65535 192.168.1.125/32 0-65535 */ -struct upnpperm { - enum {UPNPPERM_ALLOW=1, UPNPPERM_DENY=2 } type; - /* is it an allow or deny permission rule ? */ - u_short eport_min, eport_max; /* external port range */ - struct in_addr address, mask; /* ip/mask */ - u_short iport_min, iport_max; /* internal port range */ -}; - -/* read_permission_line() - * returns: 0 line read okay - * -1 error reading line - * - * line sample : - * allow 1024-65535 192.168.3.0/24 1024-65535 - * allow 22 192.168.4.33/32 22 - * deny 0-65535 0.0.0.0/0 0-65535 */ -int -read_permission_line(struct upnpperm * perm, - char * p); - -/* check_upnp_rule_against_permissions() - * returns: 0 if the upnp rule should be rejected, - * 1 if it could be accepted */ -int -check_upnp_rule_against_permissions(const struct upnpperm * permary, - int n_perms, - u_short eport, struct in_addr address, - u_short iport); - -#ifdef USE_MINIUPNPDCTL -void -write_permlist(int fd, const struct upnpperm * permary, - int nperms); -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnppinhole.c b/src/contrib/miniupnp/miniupnpd/upnppinhole.c deleted file mode 100644 index 00a74b0..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnppinhole.c +++ /dev/null @@ -1,545 +0,0 @@ -/* $Id: upnppinhole.c,v 1.13 2018/03/13 10:49:13 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "upnpredirect.h" -#include "upnpglobalvars.h" -#include "upnpevents.h" -#include "upnputils.h" -#include "upnppinhole.h" -#ifdef __APPLE__ -/* XXX - Apple version of PF API seems to differ from what - * pf/pfpinhole.c expects so don't use that at least.. */ -#ifdef USE_PF -#undef USE_PF -#endif /* USE_PF */ -#endif /* __APPLE__ */ -#if defined(USE_NETFILTER) -#include "netfilter/iptpinhole.h" -#endif -#if defined(USE_PF) -#include "pf/pfpinhole.h" -#endif -#if defined(USE_IPF) -#endif -#if defined(USE_IPFW) -#endif - -#ifdef ENABLE_UPNPPINHOLE - -#if 0 -int -upnp_check_outbound_pinhole(int proto, int * timeout) -{ - int s, tmptimeout, tmptime_out; - switch(proto) - { - case IPPROTO_UDP: - s = retrieve_timeout("udp_timeout", timeout); - return s; - break; - case IPPROTO_UDPLITE: - s = retrieve_timeout("udp_timeout_stream", timeout); - return s; - break; - case IPPROTO_TCP: - s = retrieve_timeout("tcp_timeout_established", timeout); - return s; - break; - case 65535: - s = retrieve_timeout("udp_timeout", timeout); - s = retrieve_timeout("udp_timeout_stream", &tmptimeout); - s = retrieve_timeout("tcp_timeout_established", &tmptime_out); - if(tmptimeout= 0) { - syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with proto %d found uid=%d. Updating it.", raddr, rport, iaddr, iport, proto, *uid); - r = upnp_update_inboundpinhole(*uid, timestamp); - return (r >= 0) ? 1 : r; - } -#if defined(USE_PF) || defined(USE_NETFILTER) - *uid = add_pinhole (ext_if_name, raddr, rport, - iaddr, iport, proto, desc, timestamp); - return *uid >= 0 ? 1 : -1; -#else - return -42; /* not implemented */ -#endif -} - -#if 0 -int -upnp_add_inboundpinhole_internal(const char * raddr, unsigned short rport, - const char * iaddr, unsigned short iport, - const char * proto, int * uid) -{ - int c = 9999; - char cmd[256], cmd_raw[256], cuid[42]; -#if 0 - static const char cmdval_full_udptcp[] = "ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT"; - static const char cmdval_udptcp[] = "ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT"; - static const char cmdval_full_udplite[] = "ip6tables -I %s %d -p %s -i %s -s %s -d %s -j ACCEPT"; - static const char cmdval_udplite[] = "ip6tables -I %s %d -p %s -i %s -d %s -j ACCEPT"; - // raw table command - static const char cmdval_full_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE"; - static const char cmdval_udptcp_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE"; - static const char cmdval_full_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s -d %s -j TRACE"; - static const char cmdval_udplite_raw[] = "ip6tables -t raw -I PREROUTING %d -p %s -i %s -d %s -j TRACE"; -#endif - /*printf("%s\n", raddr);*/ - if(raddr!=NULL) - { -#ifdef IPPROTO_UDPLITE - if(atoi(proto) == IPPROTO_UDPLITE) - { - /* snprintf(cmd, sizeof(cmd), cmdval_full_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, iaddr); - snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udplite_raw, line_number, proto, ext_if_name, raddr, iaddr);*/ - } - else -#endif - { - /* snprintf(cmd, sizeof(cmd), cmdval_full_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport); - snprintf(cmd_raw, sizeof(cmd_raw), cmdval_full_udptcp_raw, line_number, proto, ext_if_name, raddr, rport, iaddr, iport);*/ - } - } - else - { -#ifdef IPPROTO_UDPLITE - if(atoi(proto) == IPPROTO_UDPLITE) - { - /*snprintf(cmd, sizeof(cmd), cmdval_udplite, miniupnpd_forward_chain, line_number, proto, ext_if_name, iaddr); - snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udplite_raw, line_number, proto, ext_if_name, iaddr);*/ - } - else -#endif - { - /*snprintf(cmd, sizeof(cmd), cmdval_udptcp, miniupnpd_forward_chain, line_number, proto, ext_if_name, rport, iaddr, iport); - snprintf(cmd_raw, sizeof(cmd_raw), cmdval_udptcp_raw, line_number, proto, ext_if_name, rport, iaddr, iport); -*/ - } - } -#ifdef DEBUG - syslog(LOG_INFO, "Adding following ip6tables rule:"); - syslog(LOG_INFO, " -> %s", cmd); - syslog(LOG_INFO, " -> %s", cmd_raw); -#endif - /* TODO Add a better checking error.*/ - if(system(cmd) < 0 || system(cmd_raw) < 0) - { - return 0; - } - srand(time(NULL)); - snprintf(cuid, sizeof(cuid), "%.4d", rand()%c); - *uid = atoi(cuid); - printf("\t_add_ uid: %s\n", cuid); - return 1; -} -#endif - -/* upnp_get_pinhole_info() - * return values : - * 0 OK - * -1 Internal error - * -2 NOT FOUND (no such entry) - * .. - * -42 Not implemented - */ -int -upnp_get_pinhole_info(unsigned short uid, - char * raddr, int raddrlen, - unsigned short * rport, - char * iaddr, int iaddrlen, - unsigned short * iport, - int * proto, char * desc, int desclen, - unsigned int * leasetime, - unsigned int * packets) -{ - /* Call Firewall specific code to get IPv6 pinhole infos */ -#if defined(USE_PF) || defined(USE_NETFILTER) - int r; - unsigned int timestamp; - u_int64_t packets_tmp; - /*u_int64_t bytes_tmp;*/ - - r = get_pinhole_info(uid, raddr, raddrlen, rport, - iaddr, iaddrlen, iport, - proto, desc, desclen, - leasetime ? ×tamp : NULL, - packets ? &packets_tmp : NULL, - NULL/*&bytes_tmp*/); - if(r >= 0) { - if(leasetime) { - time_t current_time; - current_time = upnp_time(); - if(timestamp > (unsigned int)current_time) - *leasetime = timestamp - current_time; - else - *leasetime = 0; - } - if(packets) - *packets = (unsigned int)packets_tmp; - } - return r; -#else - UNUSED(uid); - UNUSED(raddr); UNUSED(raddrlen); UNUSED(rport); - UNUSED(iaddr); UNUSED(iaddrlen); UNUSED(iport); - UNUSED(proto); UNUSED(desc); UNUSED(desclen); - UNUSED(leasetime); UNUSED(packets); - return -42; /* not implemented */ -#endif -} - -int -upnp_get_pinhole_uid_by_index(int index) -{ -#if defined (USE_NETFILTER) - return get_pinhole_uid_by_index(index); -#else - UNUSED(index); - return -42; -#endif /* defined (USE_NETFILTER) */ -} - -int -upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime) -{ -#if defined(USE_PF) || defined(USE_NETFILTER) - unsigned int timestamp; - - timestamp = upnp_time() + leasetime; - return update_pinhole(uid, timestamp); -#else - UNUSED(uid); UNUSED(leasetime); - - return -42; /* not implemented */ -#endif -} - -int -upnp_delete_inboundpinhole(unsigned short uid) -{ -#if defined(USE_PF) || defined(USE_NETFILTER) - return delete_pinhole(uid); -#else - UNUSED(uid); - - return -1; -#endif -} - -#if 0 -/* - * Result: - * 1: Found Result - * -4: No result - * -5: Result in another table - * -6: Result in another chain - * -7: Result in a chain not a rule -*/ -int -upnp_check_pinhole_working(const char * uid, - char * eaddr, - char * iaddr, - unsigned short * eport, - unsigned short * iport, - char * protocol, - int * rulenum_used) -{ - /* TODO : to be implemented */ -#if 0 - FILE * fd; - time_t expire = upnp_time(); - char buf[1024], filename[] = "/var/log/kern.log", expire_time[32]=""; - int res = -4, str_len; - - str_len = strftime(expire_time, sizeof(expire_time), "%b %d %H:%M:%S", localtime(&expire)); - - fd = fopen(filename, "r"); - if (fd==NULL) - { - syslog(LOG_ERR, "Get_rule: could not open file: %s", filename); - return -1; - } - - syslog(LOG_INFO, "Get_rule: Starting getting info in file %s for %s\n", filename, uid); - buf[sizeof(buf)-1] = 0; - while(fgets(buf, sizeof(buf)-1, fd) != NULL && res != 1) - { - //printf("line: %s\n", buf); - char * r, * t, * c, * p; - // looking for something like filter:FORWARD:rule: or filter:MINIUPNPD:rule: - r = strstr(buf, ":rule:"); - p = strstr(buf, ":policy:"); - t = strstr(buf, "TRACE:"); // table pointeur - t += 7; - c = t + 7; // chain pointeur - if(r) - { - printf("\t** Found %.*s\n", 24 ,t); - char * src, * dst, * sport, * dport, * proto, * line; - char time[15]="", src_addr[40], dst_addr[40], proto_tmp[8]; - int proto_int; - strncpy(time, buf, sizeof(time)); - /*if(compare_time(time, expire_time)<0) - { - printf("\t\tNot corresponding time\n"); - continue; - }*/ - - line = r + 6; - printf("\trule line = %d\n", atoi(line)); - - src = strstr(buf, "SRC="); - src += 4; - snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src); -#if 0 - del_char(src_addr); - add_char(src_addr); -#endif - - dst = strstr(buf, "DST="); - dst += 4; - snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst); -#if 0 - del_char(dst_addr); - add_char(dst_addr); -#endif - - proto = strstr(buf, "PROTO="); - proto += 6; - proto_int = atoi(protocol); - if(proto_int == IPPROTO_UDP) - strcpy(proto_tmp, "UDP"); - else if(proto_int == IPPROTO_TCP) - strcpy(proto_tmp, "TCP"); -#ifdef IPPROTO_UDPLITE - else if(proto_int == IPPROTO_UDPLITE) - strcpy(proto_tmp, "UDPLITE"); -#endif - else - strcpy(proto_tmp, "UnsupportedProto"); - - // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto); - // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto); - // TODO Check time - // Check that the paquet found in trace correspond to the one we are looking for - if( /*(strcmp(eaddr, src_addr) == 0) &&*/ (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, strlen(proto_tmp))==0)) - { - sport = strstr(buf, "SPT="); - sport += 4; - dport = strstr(buf, "DPT="); - dport += 4; - printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport)); - printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport)); - if(/*eport != atoi(sport) &&*/ *iport != atoi(dport)) - { - printf("\t\tPort not corresponding\n"); - continue; - } - printf("\ttable found: %.*s\n", 6, t); - printf("\tchain found: %.*s\n", 9, c); - // Check that the table correspond to the filter table - if(strncmp(t, "filter", 6)==0) - { - // Check that the table correspond to the MINIUPNP table - if(strncmp(c, "MINIUPNPD", 9)==0) - { - *rulenum_used = atoi(line); - res = 1; - } - else - { - res = -6; - continue; - } - } - else - { - res = -5; - continue; - } - } - else - { - printf("Packet information not corresponding\n"); - continue; - } - } - if(!r && p) - { - printf("\t** Policy case\n"); - char * src, * dst, * sport, * dport, * proto, * line; - char time[15], src_addr[40], dst_addr[40], proto_tmp[8]; - int proto_int; - strncpy(time, buf, sizeof(time)); - /*if(compare_time(time, expire_time)<0) - { - printf("\t\tNot corresponding time\n"); - continue; - }*/ - - line = p + 8; - printf("\trule line = %d\n", atoi(line)); - - src = strstr(buf, "SRC="); - src += 4; - snprintf(src_addr, sizeof(src_addr), "%.*s", 39, src); -#if 0 - del_char(src_addr); - add_char(src_addr); -#endif - - dst = strstr(buf, "DST="); - dst += 4; - snprintf(dst_addr, sizeof(dst_addr), "%.*s", 39, dst); -#if 0 - del_char(dst_addr); - add_char(dst_addr); -#endif - - proto = strstr(buf, "PROTO="); - proto += 6; - proto_int = atoi(protocol); - if(proto_int == IPPROTO_UDP) - strcpy(proto_tmp, "UDP"); - else if(proto_int == IPPROTO_TCP) - strcpy(proto_tmp, "TCP"); -#ifdef IPPROTO_UDPLITE - else if(proto_int == IPPROTO_UDPLITE) - strcpy(proto_tmp, "UDPLITE"); -#endif - else - strcpy(proto_tmp, "UnsupportedProto"); - - // printf("\tCompare eaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", eaddr, proto_tmp, src_addr, strlen(proto_tmp), proto); - // printf("\tCompare iaddr: %s // protocol: %s\n\t to addr: %s // protocol: %.*s\n", iaddr, proto_tmp, dst_addr, strlen(proto_tmp), proto); - // Check that the paquet found in trace correspond to the one we are looking for - if( (strcmp(eaddr, src_addr) == 0) && (strcmp(iaddr, dst_addr) == 0) && (strncmp(proto_tmp, proto, 5)==0)) - { - sport = strstr(buf, "SPT="); - sport += 4; - dport = strstr(buf, "DPT="); - dport += 4; - printf("\tCompare eport: %hu\n\t to port: %d\n", *eport, atoi(sport)); - printf("\tCompare iport: %hu\n\t to port: %d\n", *iport, atoi(dport)); - if(*eport != atoi(sport) && *iport != atoi(dport)) - { - printf("\t\tPort not corresponding\n"); - continue; - } - else - { - printf("Find a corresponding policy trace in the chain: %.*s\n", 10, c); - res = -7; - continue; - } - } - else - continue; - } - } - fclose(fd); - return res; -#else - return -42; /* to be implemented */ -#endif -} -#endif - -int -upnp_clean_expired_pinholes(unsigned int * next_timestamp) -{ -#if defined(USE_PF) || defined(USE_NETFILTER) - return clean_pinhole_list(next_timestamp); -#else - UNUSED(next_timestamp); - - return 0; /* nothing to do */ -#endif -} - -#endif /* ENABLE_UPNPPINHOLE */ diff --git a/src/contrib/miniupnp/miniupnpd/upnppinhole.h b/src/contrib/miniupnp/miniupnpd/upnppinhole.h deleted file mode 100644 index c979401..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnppinhole.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $Id: upnppinhole.h,v 1.2 2012/09/18 08:29:49 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2016 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPPINHOLE_H_INCLUDED -#define UPNPPINHOLE_H_INCLUDED - -#include "config.h" - -#ifdef ENABLE_UPNPPINHOLE - -/* functions to be used by WANIPv6_FirewallControl implementation - * and PCP (IPv6) */ - -#if 0 -/* retrieve outbound pinhole timeout */ -int -upnp_check_outbound_pinhole(int proto, int * timeout); -#endif - -/* find an inbound pinhole base on remove host:port / local host:port - * return the (positive) uid or a negative value if not found */ -int -upnp_find_inboundpinhole(const char * raddr, unsigned short rport, - const char * iaddr, unsigned short iport, - int proto, - char * desc, int desc_len, unsigned int * leasetime); - - -/* add an inbound pinehole - * return value : - * 1 = success - * -1 = Pinhole space exhausted - * .. = error */ -int -upnp_add_inboundpinhole(const char * raddr, unsigned short rport, - const char * iaddr, unsigned short iport, - int proto, char * desc, - unsigned int leasetime, int * uid); - -/* get from uid - * return values : - * -1 not found - * */ -int -upnp_get_pinhole_info(unsigned short uid, - char * raddr, int raddrlen, - unsigned short * rport, - char * iaddr, int iaddrlen, - unsigned short * iport, - int * proto, char * desc, int desclen, - unsigned int * leasetime, - unsigned int * packets); - -/* - * return values: - * -1 = not found - * 0 .. 65535 = uid of the rule for the index - */ -int -upnp_get_pinhole_uid_by_index(int index); - -/* update the lease time */ -int -upnp_update_inboundpinhole(unsigned short uid, unsigned int leasetime); - -/* remove the inbound pinhole */ -int -upnp_delete_inboundpinhole(unsigned short uid); - -/* ... */ -#if 0 -int -upnp_check_pinhole_working(const char * uid, char * eaddr, char * iaddr, unsigned short * eport, unsigned short * iport, char * protocol, int * rulenum_used); -#endif - -/* return the number of expired pinhole removed - * write timestamp to next pinhole to exprire to next_timestamp - * next_timestamp is left untouched if there is no pinhole lest */ -int -upnp_clean_expired_pinholes(unsigned int * next_timestamp); - -#endif /* ENABLE_UPNPPINHOLE */ - -#endif /* !UPNPPINHOLE_H_INCLUDED */ diff --git a/src/contrib/miniupnp/miniupnpd/upnpredirect.c b/src/contrib/miniupnp/miniupnpd/upnpredirect.c deleted file mode 100644 index 2306ca5..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpredirect.c +++ /dev/null @@ -1,782 +0,0 @@ -/* $Id: upnpredirect.c,v 1.93 2018/03/12 22:41:53 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "upnpredirect.h" -#include "upnpglobalvars.h" -#include "upnpevents.h" -#include "portinuse.h" -#include "upnputils.h" -#if defined(USE_NETFILTER) -#include "netfilter/iptcrdr.h" -#endif -#if defined(USE_PF) -#include "pf/obsdrdr.h" -#endif -#if defined(USE_IPF) -#include "ipf/ipfrdr.h" -#endif -#if defined(USE_IPFW) -#include "ipfw/ipfwrdr.h" -#endif -#ifdef USE_MINIUPNPDCTL -#include -#include -#endif -#ifdef ENABLE_LEASEFILE -#include -#endif - -/* from */ -#ifndef PRIu64 -#define PRIu64 "llu" -#endif - -/* proto_atoi() - * convert the string "UDP" or "TCP" to IPPROTO_UDP and IPPROTO_UDP */ -static int -proto_atoi(const char * protocol) -{ - int proto = IPPROTO_TCP; - if(strcasecmp(protocol, "UDP") == 0) - proto = IPPROTO_UDP; -#ifdef IPPROTO_UDPLITE - else if(strcasecmp(protocol, "UDPLITE") == 0) - proto = IPPROTO_UDPLITE; -#endif /* IPPROTO_UDPLITE */ - return proto; -} - -/* proto_itoa() - * convert IPPROTO_UDP, IPPROTO_UDP, etc. to "UDP", "TCP" */ -static const char * -proto_itoa(int proto) -{ - const char * protocol; - switch(proto) { - case IPPROTO_UDP: - protocol = "UDP"; - break; - case IPPROTO_TCP: - protocol = "TCP"; - break; -#ifdef IPPROTO_UDPLITE - case IPPROTO_UDPLITE: - protocol = "UDPLITE"; - break; -#endif /* IPPROTO_UDPLITE */ - default: - protocol = "*UNKNOWN*"; - } - return protocol; -} - -#ifdef ENABLE_LEASEFILE -static int -lease_file_add(unsigned short eport, - const char * iaddr, - unsigned short iport, - int proto, - const char * desc, - unsigned int timestamp) -{ - FILE * fd; - - if (lease_file == NULL) return 0; - - fd = fopen( lease_file, "a"); - if (fd==NULL) { - syslog(LOG_ERR, "could not open lease file: %s", lease_file); - return -1; - } - - /* convert our time to unix time - * if LEASEFILE_USE_REMAINING_TIME is defined, only the remaining time is stored */ - if (timestamp != 0) { - timestamp -= upnp_time(); -#ifndef LEASEFILE_USE_REMAINING_TIME - timestamp += time(NULL); -#endif - } - - fprintf(fd, "%s:%hu:%s:%hu:%u:%s\n", - proto_itoa(proto), eport, iaddr, iport, - timestamp, desc); - fclose(fd); - - return 0; -} - -static int -lease_file_remove(unsigned short eport, int proto) -{ - FILE* fd, *fdt; - int tmp; - char buf[512]; - char str[32]; - char tmpfilename[128]; - int str_size, buf_size; - - - if (lease_file == NULL) return 0; - - if (strlen( lease_file) + 7 > sizeof(tmpfilename)) { - syslog(LOG_ERR, "Lease filename is too long"); - return -1; - } - - snprintf( tmpfilename, sizeof(tmpfilename), "%sXXXXXX", lease_file); - - fd = fopen( lease_file, "r"); - if (fd==NULL) { - return 0; - } - - snprintf( str, sizeof(str), "%s:%u", proto_itoa(proto), eport); - str_size = strlen(str); - - tmp = mkstemp(tmpfilename); - if (tmp==-1) { - fclose(fd); - syslog(LOG_ERR, "could not open temporary lease file"); - return -1; - } - fchmod(tmp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - fdt = fdopen(tmp, "a"); - - buf[sizeof(buf)-1] = 0; - while( fgets(buf, sizeof(buf)-1, fd) != NULL) { - buf_size = strlen(buf); - - if (buf_size < str_size || strncmp(str, buf, str_size)!=0) { - fwrite(buf, buf_size, 1, fdt); - } - } - fclose(fdt); - fclose(fd); - - if (rename(tmpfilename, lease_file) < 0) { - syslog(LOG_ERR, "could not rename temporary lease file to %s", lease_file); - remove(tmpfilename); - } - - return 0; - -} - -/* reload_from_lease_file() - * read lease_file and add the rules contained - */ -int reload_from_lease_file() -{ - FILE * fd; - char * p; - unsigned short eport, iport; - char * proto; - char * iaddr; - char * desc; - char * rhost; - unsigned int leaseduration; - unsigned int timestamp; - time_t current_time; -#ifndef LEASEFILE_USE_REMAINING_TIME - time_t current_unix_time; -#endif - char line[128]; - int r; - - if(!lease_file) return -1; - fd = fopen( lease_file, "r"); - if (fd==NULL) { - syslog(LOG_ERR, "could not open lease file: %s", lease_file); - return -1; - } - if(unlink(lease_file) < 0) { - syslog(LOG_WARNING, "could not unlink file %s : %m", lease_file); - } - - current_time = upnp_time(); -#ifndef LEASEFILE_USE_REMAINING_TIME - current_unix_time = time(NULL); -#endif - while(fgets(line, sizeof(line), fd)) { - syslog(LOG_DEBUG, "parsing lease file line '%s'", line); - proto = line; - p = strchr(line, ':'); - if(!p) { - syslog(LOG_ERR, "unrecognized data in lease file"); - continue; - } - *(p++) = '\0'; - iaddr = strchr(p, ':'); - if(!iaddr) { - syslog(LOG_ERR, "unrecognized data in lease file"); - continue; - } - *(iaddr++) = '\0'; - eport = (unsigned short)atoi(p); - p = strchr(iaddr, ':'); - if(!p) { - syslog(LOG_ERR, "unrecognized data in lease file"); - continue; - } - *(p++) = '\0'; - iport = (unsigned short)atoi(p); - p = strchr(p, ':'); - if(!p) { - syslog(LOG_ERR, "unrecognized data in lease file"); - continue; - } - *(p++) = '\0'; - desc = strchr(p, ':'); - if(!desc) { - syslog(LOG_ERR, "unrecognized data in lease file"); - continue; - } - *(desc++) = '\0'; - /*timestamp = (unsigned int)atoi(p);*/ - timestamp = (unsigned int)strtoul(p, NULL, 10); - /* trim description */ - while(isspace(*desc)) - desc++; - p = desc; - while(*(p+1)) - p++; - while(isspace(*p) && (p > desc)) - *(p--) = '\0'; - - if(timestamp > 0) { -#ifdef LEASEFILE_USE_REMAINING_TIME - leaseduration = timestamp; - timestamp += current_time; /* convert to our time */ -#else - if(timestamp <= (unsigned int)current_unix_time) { - syslog(LOG_NOTICE, "already expired lease in lease file"); - continue; - } else { - leaseduration = timestamp - current_unix_time; - timestamp = leaseduration + current_time; /* convert to our time */ - } -#endif - } else { - leaseduration = 0; /* default value */ - } - rhost = NULL; - r = upnp_redirect(rhost, eport, iaddr, iport, proto, desc, leaseduration); - if(r == -1) { - syslog(LOG_ERR, "Failed to redirect %hu -> %s:%hu protocol %s", - eport, iaddr, iport, proto); - } else if(r == -2) { - /* Add the redirection again to the lease file */ - lease_file_add(eport, iaddr, iport, proto_atoi(proto), - desc, timestamp); - } - } - fclose(fd); - - return 0; -} - -#ifdef LEASEFILE_USE_REMAINING_TIME -void lease_file_rewrite(void) -{ - int index; - unsigned short eport, iport; - int proto; - char iaddr[32]; - char desc[64]; - char rhost[40]; - unsigned int timestamp; - - if (lease_file == NULL) return; - remove(lease_file); - for(index = 0; ; index++) { - if(get_redirect_rule_by_index(index, 0/*ifname*/, &eport, iaddr, sizeof(iaddr), - &iport, &proto, desc, sizeof(desc), - rhost, sizeof(rhost), ×tamp, - 0, 0) < 0) - break; - if(lease_file_add(eport, iaddr, iport, proto, desc, timestamp) < 0) - break; - } -} -#endif -#endif - -/* upnp_redirect() - * calls OS/fw dependent implementation of the redirection. - * protocol should be the string "TCP" or "UDP" - * returns: 0 on success - * -1 failed to redirect - * -2 already redirected - * -3 permission check failed - * -4 already redirected (other mechanism) - */ -int -upnp_redirect(const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * protocol, const char * desc, - unsigned int leaseduration) -{ - int proto, r; - char iaddr_old[32]; - char rhost_old[32]; - unsigned short iport_old; - struct in_addr address; - unsigned int timestamp; - - proto = proto_atoi(protocol); - if(inet_aton(iaddr, &address) <= 0) { - syslog(LOG_ERR, "inet_aton(%s) FAILED", iaddr); - return -1; - } - - if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, - eport, address, iport)) { - syslog(LOG_INFO, "redirection permission check failed for " - "%hu->%s:%hu %s", eport, iaddr, iport, protocol); - return -3; - } - /* IGDv1 (WANIPConnection:1 Service Template Version 1.01 / Nov 12, 2001) - * - 2.2.20.PortMappingDescription : - * Overwriting Previous / Existing Port Mappings: - * If the RemoteHost, ExternalPort, PortMappingProtocol and InternalClient - * are exactly the same as an existing mapping, the existing mapping values - * for InternalPort, PortMappingDescription, PortMappingEnabled and - * PortMappingLeaseDuration are overwritten. - * Rejecting a New Port Mapping: - * In cases where the RemoteHost, ExternalPort and PortMappingProtocol - * are the same as an existing mapping, but the InternalClient is - * different, the action is rejected with an appropriate error. - * Add or Reject New Port Mapping behavior based on vendor implementation: - * In cases where the ExternalPort, PortMappingProtocol and InternalClient - * are the same, but RemoteHost is different, the vendor can choose to - * support both mappings simultaneously, or reject the second mapping - * with an appropriate error. - * - * - 2.4.16.AddPortMapping - * This action creates a new port mapping or overwrites an existing - * mapping with the same internal client. If the ExternalPort and - * PortMappingProtocol pair is already mapped to another internal client, - * an error is returned. - * - * IGDv2 (WANIPConnection:2 Service Standardized DCP (SDCP) Sep 10, 2010) - * Protocol ExternalPort RemoteHost InternalClient Result - * = = ≠ ≠ Failure - * = = ≠ = Failure or success - * (vendor specific) - * = = = ≠ Failure - * = = = = Success (overwrite) - */ - rhost_old[0] = '\0'; - r = get_redirect_rule(ext_if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0, - rhost_old, sizeof(rhost_old), - ×tamp, 0, 0); - if(r == 0) { - if(strcmp(iaddr, iaddr_old)==0 && - ((rhost == NULL && rhost_old[0]=='\0') || - (rhost && (strcmp(rhost, "*") == 0) && rhost_old[0]=='\0') || - (rhost && (strcmp(rhost, rhost_old) == 0)))) { - syslog(LOG_INFO, "updating existing port mapping %hu %s (rhost '%s') => %s:%hu", - eport, protocol, rhost_old, iaddr_old, iport_old); - timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0; - if(iport != iport_old) { - r = update_portmapping(ext_if_name, eport, proto, iport, desc, timestamp); - } else { - r = update_portmapping_desc_timestamp(ext_if_name, eport, proto, desc, timestamp); - } -#ifdef ENABLE_LEASEFILE - if(r == 0) { - lease_file_remove(eport, proto); - lease_file_add(eport, iaddr, iport, proto, desc, timestamp); - } -#endif /* ENABLE_LEASEFILE */ - return r; - } else { - syslog(LOG_INFO, "port %hu %s (rhost '%s') already redirected to %s:%hu", - eport, protocol, rhost_old, iaddr_old, iport_old); - return -2; - } -#ifdef CHECK_PORTINUSE - } else if (port_in_use(ext_if_name, eport, proto, iaddr, iport) > 0) { - syslog(LOG_INFO, "port %hu protocol %s already in use", - eport, protocol); - return -4; -#endif /* CHECK_PORTINUSE */ - } else { - timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0; - syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s", - eport, iaddr, iport, protocol, desc); - return upnp_redirect_internal(rhost, eport, iaddr, iport, proto, - desc, timestamp); - } -} - -int -upnp_redirect_internal(const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, - int proto, const char * desc, - unsigned int timestamp) -{ - /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s", - eport, iaddr, iport, protocol, desc); */ - if(add_redirect_rule2(ext_if_name, rhost, eport, iaddr, iport, proto, - desc, timestamp) < 0) { - return -1; - } - -#ifdef ENABLE_LEASEFILE - lease_file_add( eport, iaddr, iport, proto, desc, timestamp); -#endif -/* syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s", - iaddr, iport, protocol, desc);*/ - if(add_filter_rule2(ext_if_name, rhost, iaddr, eport, iport, proto, desc) < 0) { - /* clean up the redirect rule */ -#if !defined(__linux__) - delete_redirect_rule(ext_if_name, eport, proto); -#endif - return -1; - } - if(timestamp > 0) { - if(!nextruletoclean_timestamp || (timestamp < nextruletoclean_timestamp)) - nextruletoclean_timestamp = timestamp; - } -#ifdef ENABLE_EVENTS - /* the number of port mappings changed, we must - * inform the subscribers */ - upnp_event_var_change_notify(EWanIPC); -#endif - return 0; -} - - - -/* Firewall independent code which call the FW dependent code. */ -int -upnp_get_redirection_infos(unsigned short eport, const char * protocol, - unsigned short * iport, - char * iaddr, int iaddrlen, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * leaseduration) -{ - int r; - unsigned int timestamp; - time_t current_time; - - if(desc && (desclen > 0)) - desc[0] = '\0'; - if(rhost && (rhostlen > 0)) - rhost[0] = '\0'; - r = get_redirect_rule(ext_if_name, eport, proto_atoi(protocol), - iaddr, iaddrlen, iport, desc, desclen, - rhost, rhostlen, ×tamp, - 0, 0); - if(r == 0 && - timestamp > 0 && - timestamp > (unsigned int)(current_time = upnp_time())) { - *leaseduration = timestamp - current_time; - } else { - *leaseduration = 0; - } - return r; -} - -int -upnp_get_redirection_infos_by_index(int index, - unsigned short * eport, char * protocol, - unsigned short * iport, - char * iaddr, int iaddrlen, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * leaseduration) -{ - /*char ifname[IFNAMSIZ];*/ - int proto = 0; - unsigned int timestamp; - time_t current_time; - - if(desc && (desclen > 0)) - desc[0] = '\0'; - if(rhost && (rhostlen > 0)) - rhost[0] = '\0'; - if(get_redirect_rule_by_index(index, 0/*ifname*/, eport, iaddr, iaddrlen, - iport, &proto, desc, desclen, - rhost, rhostlen, ×tamp, - 0, 0) < 0) - return -1; - else - { - current_time = upnp_time(); - *leaseduration = (timestamp > (unsigned int)current_time) - ? (timestamp - current_time) - : 0; - if(proto == IPPROTO_TCP) - memcpy(protocol, "TCP", 4); -#ifdef IPPROTO_UDPLITE - else if(proto == IPPROTO_UDPLITE) - memcpy(protocol, "UDPLITE", 8); -#endif /* IPPROTO_UDPLITE */ - else - memcpy(protocol, "UDP", 4); - return 0; - } -} - -/* called from natpmp.c too */ -int -_upnp_delete_redir(unsigned short eport, int proto) -{ - int r; -#if defined(__linux__) - r = delete_redirect_and_filter_rules(eport, proto); -#elif defined(USE_PF) - r = delete_redirect_and_filter_rules(ext_if_name, eport, proto); -#else - r = delete_redirect_rule(ext_if_name, eport, proto); - delete_filter_rule(ext_if_name, eport, proto); -#endif -#ifdef ENABLE_LEASEFILE - lease_file_remove( eport, proto); -#endif - -#ifdef ENABLE_EVENTS - upnp_event_var_change_notify(EWanIPC); -#endif - return r; -} - -int -upnp_delete_redirection(unsigned short eport, const char * protocol) -{ - syslog(LOG_INFO, "removing redirect rule port %hu %s", eport, protocol); - return _upnp_delete_redir(eport, proto_atoi(protocol)); -} - -/* upnp_get_portmapping_number_of_entries() - * TODO: improve this code. */ -int -upnp_get_portmapping_number_of_entries() -{ - int n = 0, r = 0; - unsigned short eport, iport; - char protocol[4], iaddr[32], desc[64], rhost[32]; - unsigned int leaseduration; - do { - protocol[0] = '\0'; iaddr[0] = '\0'; desc[0] = '\0'; - r = upnp_get_redirection_infos_by_index(n, &eport, protocol, &iport, - iaddr, sizeof(iaddr), - desc, sizeof(desc), - rhost, sizeof(rhost), - &leaseduration); - n++; - } while(r==0); - return (n-1); -} - -/* functions used to remove unused rules - * As a side effect, delete expired rules (based on LeaseDuration) */ -struct rule_state * -get_upnp_rules_state_list(int max_rules_number_target) -{ - /*char ifname[IFNAMSIZ];*/ - int proto; - unsigned short iport; - unsigned int timestamp; - struct rule_state * tmp; - struct rule_state * list = 0; - struct rule_state * * p; - int i = 0; - time_t current_time; - - /*ifname[0] = '\0';*/ - tmp = malloc(sizeof(struct rule_state)); - if(!tmp) - return 0; - current_time = upnp_time(); - nextruletoclean_timestamp = 0; - while(get_redirect_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0, - &iport, &proto, 0, 0, 0,0, ×tamp, - &tmp->packets, &tmp->bytes) >= 0) - { - tmp->to_remove = 0; - if(timestamp > 0) { - /* need to remove this port mapping ? */ - if(timestamp <= (unsigned int)current_time) - tmp->to_remove = 1; - else if((nextruletoclean_timestamp <= (unsigned int)current_time) - || (timestamp < nextruletoclean_timestamp)) - nextruletoclean_timestamp = timestamp; - } - tmp->proto = (short)proto; - /* add tmp to list */ - tmp->next = list; - list = tmp; - /* prepare next iteration */ - i++; - tmp = malloc(sizeof(struct rule_state)); - if(!tmp) - break; - } -#ifdef PCP_PEER - i=0; - while(get_peer_rule_by_index(i, /*ifname*/0, &tmp->eport, 0, 0, - &iport, &proto, 0, 0, 0,0,0, ×tamp, - &tmp->packets, &tmp->bytes) >= 0) - { - tmp->to_remove = 0; - if(timestamp > 0) { - /* need to remove this port mapping ? */ - if(timestamp <= (unsigned int)current_time) - tmp->to_remove = 1; - else if((nextruletoclean_timestamp <= (unsigned int)current_time) - || (timestamp < nextruletoclean_timestamp)) - nextruletoclean_timestamp = timestamp; - } - tmp->proto = (short)proto; - /* add tmp to list */ - tmp->next = list; - list = tmp; - /* prepare next iteration */ - i++; - tmp = malloc(sizeof(struct rule_state)); - if(!tmp) - break; - } -#endif - free(tmp); - /* remove the redirections that need to be removed */ - for(p = &list, tmp = list; tmp; tmp = *p) - { - if(tmp->to_remove) - { - syslog(LOG_NOTICE, "remove port mapping %hu %s because it has expired", - tmp->eport, proto_itoa(tmp->proto)); - _upnp_delete_redir(tmp->eport, tmp->proto); - *p = tmp->next; - free(tmp); - i--; - } else { - p = &(tmp->next); - } - } - /* return empty list if not enough redirections */ - if(i<=max_rules_number_target) - while(list) - { - tmp = list; - list = tmp->next; - free(tmp); - } - /* return list */ - return list; -} - -void -remove_unused_rules(struct rule_state * list) -{ - char ifname[IFNAMSIZ]; - unsigned short iport; - struct rule_state * tmp; - u_int64_t packets; - u_int64_t bytes; - unsigned int timestamp; - int n = 0; - - while(list) - { - /* remove the rule if no traffic has used it */ - if(get_redirect_rule(ifname, list->eport, list->proto, - 0, 0, &iport, 0, 0, 0, 0, ×tamp, - &packets, &bytes) >= 0) - { - if(packets == list->packets && bytes == list->bytes) - { - syslog(LOG_DEBUG, "removing unused mapping %hu %s : still " - "%" PRIu64 "packets %" PRIu64 "bytes", - list->eport, proto_itoa(list->proto), - packets, bytes); - _upnp_delete_redir(list->eport, list->proto); - n++; - } - } - tmp = list; - list = tmp->next; - free(tmp); - } - if(n>0) - syslog(LOG_NOTICE, "removed %d unused rules", n); -} - -/* upnp_get_portmappings_in_range() - * return a list of all "external" ports for which a port - * mapping exists */ -unsigned short * -upnp_get_portmappings_in_range(unsigned short startport, - unsigned short endport, - const char * protocol, - unsigned int * number) -{ - int proto; - proto = proto_atoi(protocol); - if(!number) - return NULL; - return get_portmappings_in_range(startport, endport, proto, number); -} - -/* stuff for miniupnpdctl */ -#ifdef USE_MINIUPNPDCTL -void -write_ruleset_details(int s) -{ - int proto = 0; - unsigned short eport, iport; - char desc[64]; - char iaddr[32]; - char rhost[32]; - unsigned int timestamp; - u_int64_t packets; - u_int64_t bytes; - int i = 0; - char buffer[256]; - int n; - - write(s, "Ruleset :\n", 10); - while(get_redirect_rule_by_index(i, 0/*ifname*/, &eport, iaddr, sizeof(iaddr), - &iport, &proto, desc, sizeof(desc), - rhost, sizeof(rhost), - ×tamp, - &packets, &bytes) >= 0) - { - n = snprintf(buffer, sizeof(buffer), - "%2d %s %s:%hu->%s:%hu " - "'%s' %u %" PRIu64 " %" PRIu64 "\n", - /*"'%s' %llu %llu\n",*/ - i, proto_itoa(proto), rhost, - eport, iaddr, iport, desc, timestamp, packets, bytes); - write(s, buffer, n); - i++; - } -} -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpredirect.h b/src/contrib/miniupnp/miniupnpd/upnpredirect.h deleted file mode 100644 index bb105de..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpredirect.h +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id: upnpredirect.h,v 1.36 2018/01/16 00:50:49 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREDIRECT_H_INCLUDED -#define UPNPREDIRECT_H_INCLUDED - -/* for u_int64_t */ -#include - -#include "config.h" - -#ifdef ENABLE_LEASEFILE -int reload_from_lease_file(void); -#ifdef LEASEFILE_USE_REMAINING_TIME -void lease_file_rewrite(void); -#endif -#endif - -/* upnp_redirect() - * calls OS/fw dependent implementation of the redirection. - * protocol should be the string "TCP" or "UDP" - * returns: 0 on success - * -1 failed to redirect - * -2 already redirected - * -3 permission check failed - */ -int -upnp_redirect(const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, - const char * protocol, const char * desc, - unsigned int leaseduration); - -/* upnp_redirect_internal() - * same as upnp_redirect() without any check */ -int -upnp_redirect_internal(const char * rhost, unsigned short eport, - const char * iaddr, unsigned short iport, - int proto, const char * desc, - unsigned int timestamp); - -/* upnp_get_redirection_infos() - * returns : 0 on success - * -1 failed to get the port mapping entry or no entry exists */ -int -upnp_get_redirection_infos(unsigned short eport, const char * protocol, - unsigned short * iport, char * iaddr, int iaddrlen, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * leaseduration); - -/* upnp_get_redirection_infos_by_index() - * returns : 0 on success - * -1 failed to get the port mapping or index out of range */ -int -upnp_get_redirection_infos_by_index(int index, - unsigned short * eport, char * protocol, - unsigned short * iport, - char * iaddr, int iaddrlen, - char * desc, int desclen, - char * rhost, int rhostlen, - unsigned int * leaseduration); - -/* upnp_delete_redirection() - * returns: 0 on success - * -1 on failure*/ -int -upnp_delete_redirection(unsigned short eport, const char * protocol); - -/* _upnp_delete_redir() - * same as above */ -int -_upnp_delete_redir(unsigned short eport, int proto); - -/* Periodic cleanup functions - */ -struct rule_state -{ - u_int64_t packets; - u_int64_t bytes; - struct rule_state * next; - unsigned short eport; - unsigned char proto; - unsigned char to_remove; -}; - -/* return a linked list of all rules - * or an empty list if there are not enough - * As a "side effect", delete rules which are expired */ -struct rule_state * -get_upnp_rules_state_list(int max_rules_number_target); - -/* return the number of port mapping entries */ -int -upnp_get_portmapping_number_of_entries(void); - -/* remove_unused_rules() : - * also free the list */ -void -remove_unused_rules(struct rule_state * list); - -/* upnp_get_portmappings_in_range() - * return a list of all "external" ports for which a port - * mapping exists */ -unsigned short * -upnp_get_portmappings_in_range(unsigned short startport, - unsigned short endport, - const char * protocol, - unsigned int * number); - -/* stuff for responding to miniupnpdctl */ -#ifdef USE_MINIUPNPDCTL -void -write_ruleset_details(int s); -#endif - -#endif - - diff --git a/src/contrib/miniupnp/miniupnpd/upnpreplyparse.c b/src/contrib/miniupnp/miniupnpd/upnpreplyparse.c deleted file mode 100644 index 5921349..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpreplyparse.c +++ /dev/null @@ -1,196 +0,0 @@ -/* $Id: upnpreplyparse.c,v 1.20 2017/12/12 11:26:25 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2017 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "upnpreplyparse.h" -#include "minixml.h" - -static void -NameValueParserStartElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - data->topelt = 1; - if(l>63) - l = 63; - memcpy(data->curelt, name, l); - data->curelt[l] = '\0'; - data->cdata = NULL; - data->cdatalen = 0; -} - -static void -NameValueParserEndElt(void * d, const char * name, int namelen) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - (void)name; - (void)namelen; - if(!data->topelt) - return; - if(strcmp(data->curelt, "NewPortListing") != 0) - { - int l; - /* standard case. Limited to n chars strings */ - l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); - if(nv == NULL) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserEndElt"); -#endif /* DEBUG */ - return; - } - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - if(data->cdata != NULL) - { - memcpy(nv->value, data->cdata, l); - nv->value[l] = '\0'; - } - else - { - nv->value[0] = '\0'; - } - nv->l_next = data->l_head; /* insert in list */ - data->l_head = nv; - } - data->cdata = NULL; - data->cdatalen = 0; - data->topelt = 0; -} - -static void -NameValueParserGetData(void * d, const char * datas, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - if(strcmp(data->curelt, "NewPortListing") == 0) - { - /* specific case for NewPortListing which is a XML Document */ - data->portListing = malloc(l + 1); - if(!data->portListing) - { - /* malloc error */ -#ifdef DEBUG - fprintf(stderr, "%s: error allocating memory", - "NameValueParserGetData"); -#endif /* DEBUG */ - return; - } - memcpy(data->portListing, datas, l); - data->portListing[l] = '\0'; - data->portListingLength = l; - } - else - { - /* standard case. */ - data->cdata = datas; - data->cdatalen = l; - } -} - -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) -{ - struct xmlparser parser; - memset(data, 0, sizeof(struct NameValueParserData)); - /* init xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = NameValueParserEndElt; - parser.datafunc = NameValueParserGetData; - parser.attfunc = 0; - parsexml(&parser); -} - -void -ClearNameValueList(struct NameValueParserData * pdata) -{ - struct NameValue * nv; - if(pdata->portListing) - { - free(pdata->portListing); - pdata->portListing = NULL; - pdata->portListingLength = 0; - } - while((nv = pdata->l_head) != NULL) - { - pdata->l_head = nv->l_next; - free(nv); - } -} - -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - for(nv = pdata->l_head; - (nv != NULL) && (p == NULL); - nv = nv->l_next) - { - if(strcmp(nv->name, Name) == 0) - p = nv->value; - } - return p; -} - -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - -/* debug all-in-one function - * do parsing then display to stdout */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize) -{ - struct NameValueParserData pdata; - struct NameValue * nv; - ParseNameValue(buffer, bufsize, &pdata); - for(nv = pdata.l_head; - nv != NULL; - nv = nv->l_next) - { - printf("%s = %s\n", nv->name, nv->value); - } - ClearNameValueList(&pdata); -} -#endif /* DEBUG */ - diff --git a/src/contrib/miniupnp/miniupnpd/upnpreplyparse.h b/src/contrib/miniupnp/miniupnpd/upnpreplyparse.h deleted file mode 100644 index 6badd15..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpreplyparse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - struct NameValue * l_next; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - struct NameValue * l_head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpsoap.c b/src/contrib/miniupnp/miniupnpd/upnpsoap.c deleted file mode 100644 index b4f156c..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpsoap.c +++ /dev/null @@ -1,2322 +0,0 @@ -/* $Id: upnpsoap.c,v 1.151 2018/03/13 10:32:53 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * MiniUPnP project - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "macros.h" -#include "config.h" -#include "upnpglobalvars.h" -#include "upnphttp.h" -#include "upnpsoap.h" -#include "upnpreplyparse.h" -#include "upnpredirect.h" -#include "upnppinhole.h" -#include "getifaddr.h" -#include "getifstats.h" -#include "getconnstatus.h" -#include "upnpurns.h" -#include "upnputils.h" - -/* utility function */ -static int is_numeric(const char * s) -{ - while(*s) { - if(*s < '0' || *s > '9') return 0; - s++; - } - return 1; -} - -static void -BuildSendAndCloseSoapResp(struct upnphttp * h, - const char * body, int bodylen) -{ - static const char beforebody[] = - "\r\n" - "" - ""; - - static const char afterbody[] = - "" - "\r\n"; - - int r = BuildHeader_upnphttp(h, 200, "OK", sizeof(beforebody) - 1 - + sizeof(afterbody) - 1 + bodylen ); - - if(r >= 0) { - memcpy(h->res_buf + h->res_buflen, beforebody, sizeof(beforebody) - 1); - h->res_buflen += sizeof(beforebody) - 1; - - memcpy(h->res_buf + h->res_buflen, body, bodylen); - h->res_buflen += bodylen; - - memcpy(h->res_buf + h->res_buflen, afterbody, sizeof(afterbody) - 1); - h->res_buflen += sizeof(afterbody) - 1; - } else { - BuildResp2_upnphttp(h, 500, "Internal Server Error", NULL, 0); - } - - SendRespAndClose_upnphttp(h); -} - -static void -GetConnectionTypeInfo(struct upnphttp * h, const char * action, const char * ns) -{ -#if 0 - static const char resp[] = - "" - "IP_Routed" - "IP_Routed" - ""; -#endif - static const char resp[] = - "" - "IP_Routed" - "IP_Routed" - ""; - char body[512]; - int bodylen; - - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -/* maximum value for a UPNP ui4 type variable */ -#define UPNP_UI4_MAX (4294967295ul) - -static void -GetTotalBytesSent(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%lu" - ""; - - char body[512]; - int bodylen; - struct ifdata data; - - r = getifstats(ext_if_name, &data); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /* was "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ -#ifdef UPNP_STRICT - r<0?0:(data.obytes & UPNP_UI4_MAX), action); -#else /* UPNP_STRICT */ - r<0?0:data.obytes, action); -#endif /* UPNP_STRICT */ - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetTotalBytesReceived(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%lu" - ""; - - char body[512]; - int bodylen; - struct ifdata data; - - r = getifstats(ext_if_name, &data); - /* TotalBytesReceived - * This variable represents the cumulative counter for total number of - * bytes received downstream across all connection service instances on - * WANDevice. The count rolls over to 0 after it reaching the maximum - * value (2^32)-1. */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /* was "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ -#ifdef UPNP_STRICT - r<0?0:(data.ibytes & UPNP_UI4_MAX), action); -#else /* UPNP_STRICT */ - r<0?0:data.ibytes, action); -#endif /* UPNP_STRICT */ - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetTotalPacketsSent(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%lu" - ""; - - char body[512]; - int bodylen; - struct ifdata data; - - r = getifstats(ext_if_name, &data); - bodylen = snprintf(body, sizeof(body), resp, - action, ns,/*"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",*/ -#ifdef UPNP_STRICT - r<0?0:(data.opackets & UPNP_UI4_MAX), action); -#else /* UPNP_STRICT */ - r<0?0:data.opackets, action); -#endif /* UPNP_STRICT */ - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetTotalPacketsReceived(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%lu" - ""; - - char body[512]; - int bodylen; - struct ifdata data; - - r = getifstats(ext_if_name, &data); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /* was "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ -#ifdef UPNP_STRICT - r<0?0:(data.ipackets & UPNP_UI4_MAX), action); -#else /* UPNP_STRICT */ - r<0?0:data.ipackets, action); -#endif /* UPNP_STRICT */ - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetCommonLinkProperties(struct upnphttp * h, const char * action, const char * ns) -{ - /* WANAccessType : set depending on the hardware : - * DSL, POTS (plain old Telephone service), Cable, Ethernet */ - static const char resp[] = - "" - "%s" - "%lu" - "%lu" - "%s" - ""; - - char body[2048]; - int bodylen; - struct ifdata data; - const char * status = "Up"; /* Up, Down (Required), - * Initializing, Unavailable (Optional) */ - const char * wan_access_type = "Cable"; /* DSL, POTS, Cable, Ethernet */ - char ext_ip_addr[INET_ADDRSTRLEN]; - - if((downstream_bitrate == 0) || (upstream_bitrate == 0)) - { - if(getifstats(ext_if_name, &data) >= 0) - { - if(downstream_bitrate == 0) downstream_bitrate = data.baudrate; - if(upstream_bitrate == 0) upstream_bitrate = data.baudrate; - } - } - if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) { - status = "Down"; - } - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /* was "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - wan_access_type, - upstream_bitrate, downstream_bitrate, - status, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetStatusInfo(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%s" - "ERROR_NONE" - "%ld" - ""; - - char body[512]; - int bodylen; - time_t uptime; - const char * status; - /* ConnectionStatus possible values : - * Unconfigured, Connecting, Connected, PendingDisconnect, - * Disconnecting, Disconnected */ - - status = get_wan_connection_status_str(ext_if_name); - uptime = upnp_get_uptime(); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*SERVICE_TYPE_WANIPC,*/ - status, (long)uptime, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetNATRSIPStatus(struct upnphttp * h, const char * action, const char * ns) -{ -#if 0 - static const char resp[] = - "" - "0" - "1" - ""; - UNUSED(action); -#endif - static const char resp[] = - "" - "0" - "1" - ""; - char body[512]; - int bodylen; - /* 2.2.9. RSIPAvailable - * This variable indicates if Realm-specific IP (RSIP) is available - * as a feature on the InternetGatewayDevice. RSIP is being defined - * in the NAT working group in the IETF to allow host-NATing using - * a standard set of message exchanges. It also allows end-to-end - * applications that otherwise break if NAT is introduced - * (e.g. IPsec-based VPNs). - * A gateway that does not support RSIP should set this variable to 0. */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*SERVICE_TYPE_WANIPC,*/ - action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetExternalIPAddress(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%s" - ""; - - char body[512]; - int bodylen; - char ext_ip_addr[INET_ADDRSTRLEN]; - /* Does that method need to work with IPv6 ? - * There is usually no NAT with IPv6 */ - -#ifndef MULTIPLE_EXTERNAL_IP - if(use_ext_ip_addr) - { - strncpy(ext_ip_addr, use_ext_ip_addr, INET_ADDRSTRLEN); - ext_ip_addr[INET_ADDRSTRLEN - 1] = '\0'; - } - else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) - { - syslog(LOG_ERR, "Failed to get ip address for interface %s", - ext_if_name); - strncpy(ext_ip_addr, "0.0.0.0", INET_ADDRSTRLEN); - } -#else - struct lan_addr_s * lan_addr; - strncpy(ext_ip_addr, "0.0.0.0", INET_ADDRSTRLEN); - for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) - { - if( (h->clientaddr.s_addr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) - { - strncpy(ext_ip_addr, lan_addr->ext_ip_str, INET_ADDRSTRLEN); - break; - } - } -#endif - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*SERVICE_TYPE_WANIPC,*/ - ext_ip_addr, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -/* AddPortMapping method of WANIPConnection Service - * Ignored argument : NewEnabled */ -static void -AddPortMapping(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - /*static const char resp[] = - "";*/ - static const char resp[] = - ""; - - char body[512]; - int bodylen; - struct NameValueParserData data; - char * int_ip, * int_port, * ext_port, * protocol, * desc; - char * leaseduration_str; - unsigned int leaseduration; - char * r_host; - unsigned short iport, eport; - - struct hostent *hp; /* getbyhostname() */ - char ** ptr; /* getbyhostname() */ - struct in_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */ - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - int_ip = GetValueFromNameValueList(&data, "NewInternalClient"); - if (int_ip) { - /* trim */ - while(int_ip[0] == ' ') - int_ip++; - } -#ifdef UPNP_STRICT - if (!int_ip || int_ip[0] == '\0') - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } -#endif - - /* IGD 2 MUST support both wildcard and specific IP address values - * for RemoteHost (only the wildcard value was REQUIRED in release 1.0) */ - r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); -#ifndef SUPPORT_REMOTEHOST -#ifdef UPNP_STRICT - if (r_host && (strlen(r_host) > 0) && (0 != strcmp(r_host, "*"))) - { - ClearNameValueList(&data); - SoapError(h, 726, "RemoteHostOnlySupportsWildcard"); - return; - } -#endif -#endif - -#ifndef UPNP_STRICT - /* if arg is empty, use client address - * see https://github.com/miniupnp/miniupnp/issues/236 */ - if (!int_ip || int_ip[0] == '\0') - { - int_ip = h->clientaddr_str; - memcpy(&result_ip, &(h->clientaddr), sizeof(struct in_addr)); - } - else -#endif - /* if ip not valid assume hostname and convert */ - if (inet_pton(AF_INET, int_ip, &result_ip) <= 0) - { - hp = gethostbyname(int_ip); - if(hp && hp->h_addrtype == AF_INET) - { - for(ptr = hp->h_addr_list; ptr && *ptr; ptr++) - { - int_ip = inet_ntoa(*((struct in_addr *) *ptr)); - result_ip = *((struct in_addr *) *ptr); - /* TODO : deal with more than one ip per hostname */ - break; - } - } - else - { - syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip); - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - } - - /* check if NewInternalAddress is the client address */ - if(GETFLAG(SECUREMODEMASK)) - { - if(h->clientaddr.s_addr != result_ip.s_addr) - { - syslog(LOG_INFO, "Client %s tried to redirect port to %s", - inet_ntoa(h->clientaddr), int_ip); - ClearNameValueList(&data); - SoapError(h, 718, "ConflictInMappingEntry"); - return; - } - } - - int_port = GetValueFromNameValueList(&data, "NewInternalPort"); - ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); - desc = GetValueFromNameValueList(&data, "NewPortMappingDescription"); - leaseduration_str = GetValueFromNameValueList(&data, "NewLeaseDuration"); - - if (!int_port || !ext_port || !protocol) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - - eport = (unsigned short)atoi(ext_port); - iport = (unsigned short)atoi(int_port); - - if (strcmp(ext_port, "*") == 0 || eport == 0) - { - ClearNameValueList(&data); - SoapError(h, 716, "Wildcard not permited in ExtPort"); - return; - } - - leaseduration = leaseduration_str ? atoi(leaseduration_str) : 0; -#ifdef IGD_V2 - /* PortMappingLeaseDuration can be either a value between 1 and - * 604800 seconds or the zero value (for infinite lease time). - * Note that an infinite lease time can be only set by out-of-band - * mechanisms like WWW-administration, remote management or local - * management. - * If a control point uses the value 0 to indicate an infinite lease - * time mapping, it is REQUIRED that gateway uses the maximum value - * instead (e.g. 604800 seconds) */ - if(leaseduration == 0 || leaseduration > 604800) - leaseduration = 604800; -#endif - - syslog(LOG_INFO, "%s: ext port %hu to %s:%hu protocol %s for: %s leaseduration=%u rhost=%s", - action, eport, int_ip, iport, protocol, desc, leaseduration, - r_host ? r_host : "NULL"); - - r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration); - - ClearNameValueList(&data); - - /* possible error codes for AddPortMapping : - * 402 - Invalid Args - * 501 - Action Failed - * 715 - Wildcard not permited in SrcAddr - * 716 - Wildcard not permited in ExtPort - * 718 - ConflictInMappingEntry - * 724 - SamePortValuesRequired (deprecated in IGD v2) - * 725 - OnlyPermanentLeasesSupported - The NAT implementation only supports permanent lease times on - port mappings (deprecated in IGD v2) - * 726 - RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard and cannot be a specific IP - address or DNS name (deprecated in IGD v2) - * 727 - ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and cannot be a specific port - value (deprecated in IGD v2) - * 728 - NoPortMapsAvailable - There are not enough free ports available to complete the mapping - (added in IGD v2) - * 729 - ConflictWithOtherMechanisms (added in IGD v2) */ - switch(r) - { - case 0: /* success */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*SERVICE_TYPE_WANIPC*/); - BuildSendAndCloseSoapResp(h, body, bodylen); - break; - case -4: -#ifdef IGD_V2 - SoapError(h, 729, "ConflictWithOtherMechanisms"); - break; -#endif /* IGD_V2 */ - case -2: /* already redirected */ - case -3: /* not permitted */ - SoapError(h, 718, "ConflictInMappingEntry"); - break; - default: - SoapError(h, 501, "ActionFailed"); - } -} - -/* AddAnyPortMapping was added in WANIPConnection v2 */ -static void -AddAnyPortMapping(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - static const char resp[] = - "" - "%hu" - ""; - - char body[512]; - int bodylen; - - struct NameValueParserData data; - const char * int_ip, * int_port, * ext_port, * protocol, * desc; - const char * r_host; - unsigned short iport, eport; - const char * leaseduration_str; - unsigned int leaseduration; - - struct hostent *hp; /* getbyhostname() */ - char ** ptr; /* getbyhostname() */ - struct in_addr result_ip;/*unsigned char result_ip[16];*/ /* inet_pton() */ - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); - ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); - int_port = GetValueFromNameValueList(&data, "NewInternalPort"); - int_ip = GetValueFromNameValueList(&data, "NewInternalClient"); - /* NewEnabled */ - desc = GetValueFromNameValueList(&data, "NewPortMappingDescription"); - leaseduration_str = GetValueFromNameValueList(&data, "NewLeaseDuration"); - - leaseduration = leaseduration_str ? atoi(leaseduration_str) : 0; - if(leaseduration == 0) - leaseduration = 604800; - - if (!int_ip || !ext_port || !int_port) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - - eport = (unsigned short)atoi(ext_port); - iport = (unsigned short)atoi(int_port); - if(iport == 0 || !is_numeric(ext_port)) { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } -#ifndef SUPPORT_REMOTEHOST -#ifdef UPNP_STRICT - if (r_host && (strlen(r_host) > 0) && (0 != strcmp(r_host, "*"))) - { - ClearNameValueList(&data); - SoapError(h, 726, "RemoteHostOnlySupportsWildcard"); - return; - } -#endif -#endif - - /* if ip not valid assume hostname and convert */ - if (inet_pton(AF_INET, int_ip, &result_ip) <= 0) - { - hp = gethostbyname(int_ip); - if(hp && hp->h_addrtype == AF_INET) - { - for(ptr = hp->h_addr_list; ptr && *ptr; ptr++) - { - int_ip = inet_ntoa(*((struct in_addr *) *ptr)); - result_ip = *((struct in_addr *) *ptr); - /* TODO : deal with more than one ip per hostname */ - break; - } - } - else - { - syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip); - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - } - - /* check if NewInternalAddress is the client address */ - if(GETFLAG(SECUREMODEMASK)) - { - if(h->clientaddr.s_addr != result_ip.s_addr) - { - syslog(LOG_INFO, "Client %s tried to redirect port to %s", - inet_ntoa(h->clientaddr), int_ip); - ClearNameValueList(&data); - SoapError(h, 606, "Action not authorized"); - return; - } - } - - /* TODO : accept a different external port - * have some smart strategy to choose the port */ - for(;;) { - r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration); - if(r==-2 && eport < 65535) { - eport++; - } else { - break; - } - } - - ClearNameValueList(&data); - - switch(r) - { - case 0: /* success */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*SERVICE_TYPE_WANIPC,*/ - eport, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - break; - case -2: /* already redirected */ - SoapError(h, 718, "ConflictInMappingEntry"); - break; - case -3: /* not permitted */ - SoapError(h, 606, "Action not authorized"); - break; - default: - SoapError(h, 501, "ActionFailed"); - } -} - -static void -GetSpecificPortMappingEntry(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%u" - "%s" - "1" - "%s" - "%u" - ""; - - char body[1024]; - int bodylen; - struct NameValueParserData data; - const char * r_host, * ext_port, * protocol; - unsigned short eport, iport; - char int_ip[32]; - char desc[64]; - unsigned int leaseduration = 0; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); - ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); - -#ifdef UPNP_STRICT - if(!ext_port || !protocol || !r_host) -#else - if(!ext_port || !protocol) -#endif - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } -#ifndef SUPPORT_REMOTEHOST -#ifdef UPNP_STRICT - if (r_host && (strlen(r_host) > 0) && (0 != strcmp(r_host, "*"))) - { - ClearNameValueList(&data); - SoapError(h, 726, "RemoteHostOnlySupportsWildcard"); - return; - } -#endif -#endif - - eport = (unsigned short)atoi(ext_port); - if(eport == 0) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - - /* TODO : add r_host as an input parameter ... - * We prevent several Port Mapping with same external port - * but different remoteHost to be set up, so that is not - * a priority. */ - r = upnp_get_redirection_infos(eport, protocol, &iport, - int_ip, sizeof(int_ip), - desc, sizeof(desc), - NULL, 0, - &leaseduration); - - if(r < 0) - { - SoapError(h, 714, "NoSuchEntryInArray"); - } - else - { - syslog(LOG_INFO, "%s: rhost='%s' %s %s found => %s:%u desc='%s'", - action, - r_host ? r_host : "NULL", ext_port, protocol, int_ip, - (unsigned int)iport, desc); - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*SERVICE_TYPE_WANIPC*/, - (unsigned int)iport, int_ip, desc, leaseduration, - action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - - ClearNameValueList(&data); -} - -static void -DeletePortMapping(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - /*static const char resp[] = - "" - "";*/ - static const char resp[] = - "" - ""; - - char body[512]; - int bodylen; - struct NameValueParserData data; - const char * ext_port, * protocol; - unsigned short eport; -#ifdef UPNP_STRICT - const char * r_host; -#endif /* UPNP_STRICT */ - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - ext_port = GetValueFromNameValueList(&data, "NewExternalPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); -#ifdef UPNP_STRICT - r_host = GetValueFromNameValueList(&data, "NewRemoteHost"); -#endif /* UPNP_STRICT */ - -#ifdef UPNP_STRICT - if(!ext_port || !protocol || !r_host) -#else - if(!ext_port || !protocol) -#endif /* UPNP_STRICT */ - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } -#ifndef SUPPORT_REMOTEHOST -#ifdef UPNP_STRICT - if (r_host && (strlen(r_host) > 0) && (0 != strcmp(r_host, "*"))) - { - ClearNameValueList(&data); - SoapError(h, 726, "RemoteHostOnlySupportsWildcard"); - return; - } -#endif /* UPNP_STRICT */ -#endif /* SUPPORT_REMOTEHOST */ - - eport = (unsigned short)atoi(ext_port); - if(eport == 0) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - - syslog(LOG_INFO, "%s: external port: %hu, protocol: %s", - action, eport, protocol); - - /* if in secure mode, check the IP - * Removing a redirection is not a security threat, - * just an annoyance for the user using it. So this is not - * a priority. */ - if(GETFLAG(SECUREMODEMASK)) - { - char int_ip[32]; - struct in_addr int_ip_addr; - unsigned short iport; - unsigned int leaseduration = 0; - r = upnp_get_redirection_infos(eport, protocol, &iport, - int_ip, sizeof(int_ip), - NULL, 0, NULL, 0, - &leaseduration); - if(r >= 0) - { - if(inet_pton(AF_INET, int_ip, &int_ip_addr) > 0) - { - if(h->clientaddr.s_addr != int_ip_addr.s_addr) - { - SoapError(h, 606, "Action not authorized"); - /*SoapError(h, 714, "NoSuchEntryInArray");*/ - ClearNameValueList(&data); - return; - } - } - } - } - - r = upnp_delete_redirection(eport, protocol); - - if(r < 0) - { - SoapError(h, 714, "NoSuchEntryInArray"); - } - else - { - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - - ClearNameValueList(&data); -} - -/* DeletePortMappingRange was added in IGD spec v2 */ -static void -DeletePortMappingRange(struct upnphttp * h, const char * action, const char * ns) -{ - int r = -1; - /*static const char resp[] = - "" - "";*/ - static const char resp[] = - "" - ""; - char body[512]; - int bodylen; - struct NameValueParserData data; - const char * protocol; - const char * startport_s, * endport_s; - unsigned short startport, endport; - /*int manage;*/ - unsigned short * port_list; - unsigned int i, number = 0; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - startport_s = GetValueFromNameValueList(&data, "NewStartPort"); - endport_s = GetValueFromNameValueList(&data, "NewEndPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); - /*manage = atoi(GetValueFromNameValueList(&data, "NewManage"));*/ - if(startport_s == NULL || endport_s == NULL || protocol == NULL || - !is_numeric(startport_s) || !is_numeric(endport_s)) { - SoapError(h, 402, "Invalid Args"); - ClearNameValueList(&data); - return; - } - startport = (unsigned short)atoi(startport_s); - endport = (unsigned short)atoi(endport_s); - - /* possible errors : - 606 - Action not authorized - 730 - PortMappingNotFound - 733 - InconsistentParameter - */ - if(startport > endport) - { - SoapError(h, 733, "InconsistentParameter"); - ClearNameValueList(&data); - return; - } - - syslog(LOG_INFO, "%s: deleting external ports: %hu-%hu, protocol: %s", - action, startport, endport, protocol); - - port_list = upnp_get_portmappings_in_range(startport, endport, - protocol, &number); - if(number == 0) - { - SoapError(h, 730, "PortMappingNotFound"); - ClearNameValueList(&data); - free(port_list); - return; - } - - for(i = 0; i < number; i++) - { - r = upnp_delete_redirection(port_list[i], protocol); - syslog(LOG_INFO, "%s: deleting external port: %hu, protocol: %s: %s", - action, port_list[i], protocol, r < 0 ? "failed" : "ok"); - } - free(port_list); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - - ClearNameValueList(&data); -} - -static void -GetGenericPortMappingEntry(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%s" - "%u" - "%s" - "%u" - "%s" - "1" - "%s" - "%u" - ""; - - long int index = 0; - unsigned short eport, iport; - const char * m_index; - char * endptr; - char protocol[8], iaddr[32]; - char desc[64]; - char rhost[40]; - unsigned int leaseduration = 0; - struct NameValueParserData data; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - m_index = GetValueFromNameValueList(&data, "NewPortMappingIndex"); - - if(!m_index) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - errno = 0; /* To distinguish success/failure after call */ - index = strtol(m_index, &endptr, 10); - if((errno == ERANGE && (index == LONG_MAX || index == LONG_MIN)) - || (errno != 0 && index == 0) || (m_index == endptr)) - { - /* should condition (*endptr != '\0') be also an error ? */ - if(m_index == endptr) - syslog(LOG_WARNING, "%s: no digits were found in <%s>", - "GetGenericPortMappingEntry", "NewPortMappingIndex"); - else - syslog(LOG_WARNING, "%s: strtol('%s'): %m", - "GetGenericPortMappingEntry", m_index); - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - - syslog(LOG_INFO, "%s: index=%d", action, (int)index); - - rhost[0] = '\0'; - r = upnp_get_redirection_infos_by_index((int)index, &eport, protocol, &iport, - iaddr, sizeof(iaddr), - desc, sizeof(desc), - rhost, sizeof(rhost), - &leaseduration); - - if(r < 0) - { - SoapError(h, 713, "SpecifiedArrayIndexInvalid"); - } - else - { - int bodylen; - char body[2048]; - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*SERVICE_TYPE_WANIPC,*/ rhost, - (unsigned int)eport, protocol, (unsigned int)iport, iaddr, desc, - leaseduration, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - - ClearNameValueList(&data); -} - -/* GetListOfPortMappings was added in the IGD v2 specification */ -static void -GetListOfPortMappings(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp_start[] = - "" - "" - ""; - - static const char list_start[] = - ""; - static const char list_end[] = - ""; - - static const char entry[] = - "" - "%s" - "%hu" - "%s" - "%hu" - "%s" - "1" - "%s" - "%u" - ""; - - char * body; - size_t bodyalloc; - int bodylen; - - int r = -1; - unsigned short iport; - char int_ip[32]; - char desc[64]; - char rhost[64]; - unsigned int leaseduration = 0; - - struct NameValueParserData data; - const char * startport_s, * endport_s; - unsigned short startport, endport; - const char * protocol; - /*int manage;*/ - const char * number_s; - int number; - unsigned short * port_list; - unsigned int i, list_size = 0; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - startport_s = GetValueFromNameValueList(&data, "NewStartPort"); - endport_s = GetValueFromNameValueList(&data, "NewEndPort"); - protocol = GetValueFromNameValueList(&data, "NewProtocol"); - /*manage_s = GetValueFromNameValueList(&data, "NewManage");*/ - number_s = GetValueFromNameValueList(&data, "NewNumberOfPorts"); - if(startport_s == NULL || endport_s == NULL || protocol == NULL || - number_s == NULL || !is_numeric(number_s) || - !is_numeric(startport_s) || !is_numeric(endport_s)) { - SoapError(h, 402, "Invalid Args"); - ClearNameValueList(&data); - return; - } - - startport = (unsigned short)atoi(startport_s); - endport = (unsigned short)atoi(endport_s); - /*manage = atoi(manage_s);*/ - number = atoi(number_s); - if(number == 0) number = 1000; /* return up to 1000 mappings by default */ - - if(startport > endport) - { - SoapError(h, 733, "InconsistentParameter"); - ClearNameValueList(&data); - return; - } -/* -build the PortMappingList xml document : - - - -202.233.2.1 -2345 -TCP -2345 -192.168.1.137 -1 -dooom -345 - - -*/ - bodyalloc = 4096; - body = malloc(bodyalloc); - if(!body) - { - ClearNameValueList(&data); - SoapError(h, 501, "ActionFailed"); - return; - } - bodylen = snprintf(body, bodyalloc, resp_start, - action, ns/*SERVICE_TYPE_WANIPC*/); - if(bodylen < 0) - { - SoapError(h, 501, "ActionFailed"); - free(body); - return; - } - memcpy(body+bodylen, list_start, sizeof(list_start)); - bodylen += (sizeof(list_start) - 1); - - port_list = upnp_get_portmappings_in_range(startport, endport, - protocol, &list_size); - /* loop through port mappings */ - for(i = 0; number > 0 && i < list_size; i++) - { - /* have a margin of 1024 bytes to store the new entry */ - if((unsigned int)bodylen + 1024 > bodyalloc) - { - char * body_sav = body; - bodyalloc += 4096; - body = realloc(body, bodyalloc); - if(!body) - { - syslog(LOG_CRIT, "realloc(%p, %u) FAILED", body_sav, (unsigned)bodyalloc); - ClearNameValueList(&data); - SoapError(h, 501, "ActionFailed"); - free(body_sav); - free(port_list); - return; - } - } - rhost[0] = '\0'; - r = upnp_get_redirection_infos(port_list[i], protocol, &iport, - int_ip, sizeof(int_ip), - desc, sizeof(desc), - rhost, sizeof(rhost), - &leaseduration); - if(r == 0) - { - bodylen += snprintf(body+bodylen, bodyalloc-bodylen, entry, - rhost, port_list[i], protocol, - iport, int_ip, desc, leaseduration); - number--; - } - } - free(port_list); - port_list = NULL; - - if((bodylen + sizeof(list_end) + 1024) > bodyalloc) - { - char * body_sav = body; - bodyalloc += (sizeof(list_end) + 1024); - body = realloc(body, bodyalloc); - if(!body) - { - syslog(LOG_CRIT, "realloc(%p, %u) FAILED", body_sav, (unsigned)bodyalloc); - ClearNameValueList(&data); - SoapError(h, 501, "ActionFailed"); - free(body_sav); - return; - } - } - memcpy(body+bodylen, list_end, sizeof(list_end)); - bodylen += (sizeof(list_end) - 1); - bodylen += snprintf(body+bodylen, bodyalloc-bodylen, resp_end, - action); - BuildSendAndCloseSoapResp(h, body, bodylen); - free(body); - - ClearNameValueList(&data); -} - -#ifdef ENABLE_L3F_SERVICE -static void -SetDefaultConnectionService(struct upnphttp * h, const char * action, const char * ns) -{ - /*static const char resp[] = - "" - "";*/ - static const char resp[] = - "" - ""; - char body[512]; - int bodylen; - struct NameValueParserData data; - char * p; - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - p = GetValueFromNameValueList(&data, "NewDefaultConnectionService"); - if(p) { - /* 720 InvalidDeviceUUID - * 721 InvalidServiceID - * 723 InvalidConnServiceSelection */ -#ifdef UPNP_STRICT - char * service; - service = strchr(p, ','); - if(0 != memcmp(uuidvalue_wcd, p, sizeof("uuid:00000000-0000-0000-0000-000000000000") - 1)) { - SoapError(h, 720, "InvalidDeviceUUID"); - } else if(service == NULL || 0 != strcmp(service+1, SERVICE_ID_WANIPC)) { - SoapError(h, 721, "InvalidServiceID"); - } else -#endif - { - syslog(LOG_INFO, "%s(%s) : Ignored", action, p); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - } else { - /* missing argument */ - SoapError(h, 402, "Invalid Args"); - } - ClearNameValueList(&data); -} - -static void -GetDefaultConnectionService(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" -#ifdef IGD_V2 - "%s:WANConnectionDevice:2," -#else - "%s:WANConnectionDevice:1," -#endif - SERVICE_ID_WANIPC "" - ""; - /* example from UPnP_IGD_Layer3Forwarding 1.0.pdf : - * uuid:44f5824f-c57d-418c-a131-f22b34e14111:WANConnectionDevice:1, - * urn:upnp-org:serviceId:WANPPPConn1 */ - char body[1024]; - int bodylen; - - /* namespace : urn:schemas-upnp-org:service:Layer3Forwarding:1 */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns, uuidvalue_wcd, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} -#endif - -/* Added for compliance with WANIPConnection v2 */ -static void -SetConnectionType(struct upnphttp * h, const char * action, const char * ns) -{ -#ifdef UPNP_STRICT - const char * connection_type; -#endif /* UPNP_STRICT */ - struct NameValueParserData data; - UNUSED(action); - UNUSED(ns); - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); -#ifdef UPNP_STRICT - connection_type = GetValueFromNameValueList(&data, "NewConnectionType"); - if(!connection_type) { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } -#endif /* UPNP_STRICT */ - /* Unconfigured, IP_Routed, IP_Bridged */ - ClearNameValueList(&data); - /* always return a ReadOnly error */ - SoapError(h, 731, "ReadOnly"); -} - -/* Added for compliance with WANIPConnection v2 */ -static void -RequestConnection(struct upnphttp * h, const char * action, const char * ns) -{ - UNUSED(action); - UNUSED(ns); - SoapError(h, 606, "Action not authorized"); -} - -/* Added for compliance with WANIPConnection v2 */ -static void -ForceTermination(struct upnphttp * h, const char * action, const char * ns) -{ - UNUSED(action); - UNUSED(ns); - SoapError(h, 606, "Action not authorized"); -} - -/* -If a control point calls QueryStateVariable on a state variable that is not -buffered in memory within (or otherwise available from) the service, -the service must return a SOAP fault with an errorCode of 404 Invalid Var. - -QueryStateVariable remains useful as a limited test tool but may not be -part of some future versions of UPnP. -*/ -static void -QueryStateVariable(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%s" - ""; - - char body[512]; - int bodylen; - struct NameValueParserData data; - const char * var_name; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - /*var_name = GetValueFromNameValueList(&data, "QueryStateVariable"); */ - /*var_name = GetValueFromNameValueListIgnoreNS(&data, "varName");*/ - var_name = GetValueFromNameValueList(&data, "varName"); - - /*syslog(LOG_INFO, "QueryStateVariable(%.40s)", var_name); */ - - if(!var_name) - { - SoapError(h, 402, "Invalid Args"); - } - else if(strcmp(var_name, "ConnectionStatus") == 0) - { - const char * status; - - status = get_wan_connection_status_str(ext_if_name); - bodylen = snprintf(body, sizeof(body), resp, - action, ns,/*"urn:schemas-upnp-org:control-1-0",*/ - status, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } -#if 0 - /* not useful */ - else if(strcmp(var_name, "ConnectionType") == 0) - { - bodylen = snprintf(body, sizeof(body), resp, "IP_Routed"); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - else if(strcmp(var_name, "LastConnectionError") == 0) - { - bodylen = snprintf(body, sizeof(body), resp, "ERROR_NONE"); - BuildSendAndCloseSoapResp(h, body, bodylen); - } -#endif - else if(strcmp(var_name, "PortMappingNumberOfEntries") == 0) - { - char strn[10]; - snprintf(strn, sizeof(strn), "%i", - upnp_get_portmapping_number_of_entries()); - bodylen = snprintf(body, sizeof(body), resp, - action, ns,/*"urn:schemas-upnp-org:control-1-0",*/ - strn, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - else - { - syslog(LOG_NOTICE, "%s: Unknown: %s", action, var_name?var_name:""); - SoapError(h, 404, "Invalid Var"); - } - - ClearNameValueList(&data); -} - -#ifdef ENABLE_6FC_SERVICE -#ifndef ENABLE_IPV6 -#error "ENABLE_6FC_SERVICE needs ENABLE_IPV6" -#endif -/* WANIPv6FirewallControl actions */ -static void -GetFirewallStatus(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%d" - "%d" - ""; - - char body[512]; - int bodylen; - - bodylen = snprintf(body, sizeof(body), resp, - action, ns, /*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1",*/ - GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1, - GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1, - action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static int -CheckStatus(struct upnphttp * h) -{ - if (GETFLAG(IPV6FCFWDISABLEDMASK)) - { - SoapError(h, 702, "FirewallDisabled"); - return 0; - } - else if(GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK)) - { - SoapError(h, 703, "InboundPinholeNotAllowed"); - return 0; - } - else - return 1; -} - -#if 0 -static int connecthostport(const char * host, unsigned short port, char * result) -{ - int s, n; - char hostname[INET6_ADDRSTRLEN]; - char port_str[8], ifname[8], tmp[4]; - struct addrinfo *ai, *p; - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - /* hints.ai_flags = AI_ADDRCONFIG; */ -#ifdef AI_NUMERICSERV - hints.ai_flags = AI_NUMERICSERV; -#endif - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ - /* hints.ai_protocol = IPPROTO_TCP; */ - snprintf(port_str, sizeof(port_str), "%hu", port); - strcpy(hostname, host); - if(!strncmp(host, "fe80", 4)) - { - printf("Using an linklocal address\n"); - strcpy(ifname, "%"); - snprintf(tmp, sizeof(tmp), "%d", linklocal_index); - strcat(ifname, tmp); - strcat(hostname, ifname); - printf("host: %s\n", hostname); - } - n = getaddrinfo(hostname, port_str, &hints, &ai); - if(n != 0) - { - fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); - return -1; - } - s = -1; - for(p = ai; p; p = p->ai_next) - { -#ifdef DEBUG - char tmp_host[256]; - char tmp_service[256]; - printf("ai_family=%d ai_socktype=%d ai_protocol=%d ai_addrlen=%d\n ", - p->ai_family, p->ai_socktype, p->ai_protocol, p->ai_addrlen); - getnameinfo(p->ai_addr, p->ai_addrlen, tmp_host, sizeof(tmp_host), - tmp_service, sizeof(tmp_service), - NI_NUMERICHOST | NI_NUMERICSERV); - printf(" host=%s service=%s\n", tmp_host, tmp_service); -#endif - inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)p->ai_addr)->sin6_addr), result, INET6_ADDRSTRLEN); - return 0; - } - freeaddrinfo(ai); -} -#endif - -/* Check the security policy right */ -static int -PinholeVerification(struct upnphttp * h, char * int_ip, unsigned short int_port) -{ - int n; - char senderAddr[INET6_ADDRSTRLEN]=""; - struct addrinfo hints, *ai, *p; - struct in6_addr result_ip; - - /* Pinhole InternalClient address must correspond to the action sender */ - syslog(LOG_INFO, "Checking internal IP@ and port (Security policy purpose)"); - - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - - /* if ip not valid assume hostname and convert */ - if (inet_pton(AF_INET6, int_ip, &result_ip) <= 0) - { - n = getaddrinfo(int_ip, NULL, &hints, &ai); - if(!n && ai->ai_family == AF_INET6) - { - for(p = ai; p; p = p->ai_next) - { - inet_ntop(AF_INET6, (struct in6_addr *) p, int_ip, sizeof(struct in6_addr)); - result_ip = *((struct in6_addr *) p); - /* TODO : deal with more than one ip per hostname */ - break; - } - } - else - { - syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip); - SoapError(h, 402, "Invalid Args"); - return -1; - } - freeaddrinfo(p); - } - - if(inet_ntop(AF_INET6, &(h->clientaddr_v6), senderAddr, INET6_ADDRSTRLEN) == NULL) - { - syslog(LOG_ERR, "inet_ntop: %m"); - } -#ifdef DEBUG - printf("\tPinholeVerification:\n\t\tCompare sender @: %s\n\t\t to intClient @: %s\n", senderAddr, int_ip); -#endif - if(strcmp(senderAddr, int_ip) != 0) - if(h->clientaddr_v6.s6_addr != result_ip.s6_addr) - { - syslog(LOG_INFO, "Client %s tried to access pinhole for internal %s and is not authorized to do it", - senderAddr, int_ip); - SoapError(h, 606, "Action not authorized"); - return 0; - } - - /* Pinhole InternalPort must be greater than or equal to 1024 */ - if (int_port < 1024) - { - syslog(LOG_INFO, "Client %s tried to access pinhole with port < 1024 and is not authorized to do it", - senderAddr); - SoapError(h, 606, "Action not authorized"); - return 0; - } - return 1; -} - -static void -AddPinhole(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - static const char resp[] = - "" - "%d" - ""; - char body[512]; - int bodylen; - struct NameValueParserData data; - char * rem_host, * rem_port, * int_ip, * int_port, * protocol, * leaseTime; - int uid = 0; - unsigned short iport, rport; - int ltime; - long proto; - char rem_ip[INET6_ADDRSTRLEN]; - - if(CheckStatus(h)==0) - return; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - rem_host = GetValueFromNameValueList(&data, "RemoteHost"); - rem_port = GetValueFromNameValueList(&data, "RemotePort"); - int_ip = GetValueFromNameValueList(&data, "InternalClient"); - int_port = GetValueFromNameValueList(&data, "InternalPort"); - protocol = GetValueFromNameValueList(&data, "Protocol"); - leaseTime = GetValueFromNameValueList(&data, "LeaseTime"); - - rport = (unsigned short)(rem_port ? atoi(rem_port) : 0); - iport = (unsigned short)(int_port ? atoi(int_port) : 0); - ltime = leaseTime ? atoi(leaseTime) : -1; - errno = 0; - proto = protocol ? strtol(protocol, NULL, 0) : -1; - if(errno != 0 || proto > 65535 || proto < 0) - { - SoapError(h, 402, "Invalid Args"); - goto clear_and_exit; - } - if(iport == 0) - { - SoapError(h, 706, "InternalPortWilcardingNotAllowed"); - goto clear_and_exit; - } - - /* In particular, [IGD2] RECOMMENDS that unauthenticated and - * unauthorized control points are only allowed to invoke - * this action with: - * - InternalPort value greater than or equal to 1024, - * - InternalClient value equals to the control point's IP address. - * It is REQUIRED that InternalClient cannot be one of IPv6 - * addresses used by the gateway. */ - if(!int_ip || 0 == strlen(int_ip) || 0 == strcmp(int_ip, "*")) - { - SoapError(h, 708, "WildCardNotPermittedInSrcIP"); - goto clear_and_exit; - } - /* I guess it is useless to convert int_ip to literal ipv6 address */ - if(rem_host) - { - /* trim */ - while(isspace(rem_host[0])) - rem_host++; - } - /* rem_host should be converted to literal ipv6 : */ - if(rem_host && (rem_host[0] != '\0') && (rem_host[0] != '*')) - { - struct addrinfo *ai, *p; - struct addrinfo hints; - int err; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET6; - /*hints.ai_flags = */ - /* hints.ai_protocol = proto; */ - err = getaddrinfo(rem_host, rem_port, &hints, &ai); - if(err == 0) - { - /* take the 1st IPv6 address */ - for(p = ai; p; p = p->ai_next) - { - if(p->ai_family == AF_INET6) - { - inet_ntop(AF_INET6, - &(((struct sockaddr_in6 *)p->ai_addr)->sin6_addr), - rem_ip, sizeof(rem_ip)); - syslog(LOG_INFO, "resolved '%s' to '%s'", rem_host, rem_ip); - rem_host = rem_ip; - break; - } - } - freeaddrinfo(ai); - } - else - { - syslog(LOG_WARNING, "AddPinhole : getaddrinfo(%s) : %s", - rem_host, gai_strerror(err)); -#if 0 - SoapError(h, 402, "Invalid Args"); - goto clear_and_exit; -#endif - } - } - - if(proto == 65535) - { - SoapError(h, 707, "ProtocolWilcardingNotAllowed"); - goto clear_and_exit; - } - if(proto != IPPROTO_UDP && proto != IPPROTO_TCP -#ifdef IPPROTO_UDPITE - && atoi(protocol) != IPPROTO_UDPLITE -#endif - ) - { - SoapError(h, 705, "ProtocolNotSupported"); - goto clear_and_exit; - } - if(ltime < 1 || ltime > 86400) - { - syslog(LOG_WARNING, "%s: LeaseTime=%d not supported, (ip=%s)", - action, ltime, int_ip); - SoapError(h, 402, "Invalid Args"); - goto clear_and_exit; - } - - if(PinholeVerification(h, int_ip, iport) <= 0) - goto clear_and_exit; - - syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with proto %ld during %d sec", - action, rem_host?rem_host:"any", - rport, int_ip, iport, - proto, ltime); - - /* In cases where the RemoteHost, RemotePort, InternalPort, - * InternalClient and Protocol are the same than an existing pinhole, - * but LeaseTime is different, the device MUST extend the existing - * pinhole's lease time and return the UniqueID of the existing pinhole. */ - r = upnp_add_inboundpinhole(rem_host, rport, int_ip, iport, proto, "IGD2 pinhole", ltime, &uid); - - switch(r) - { - case 1: /* success */ - bodylen = snprintf(body, sizeof(body), - resp, action, - ns/*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"*/, - uid, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - break; - case -1: /* not permitted */ - SoapError(h, 701, "PinholeSpaceExhausted"); - break; - default: - SoapError(h, 501, "ActionFailed"); - break; - } - /* 606 Action not authorized - * 701 PinholeSpaceExhausted - * 702 FirewallDisabled - * 703 InboundPinholeNotAllowed - * 705 ProtocolNotSupported - * 706 InternalPortWildcardingNotAllowed - * 707 ProtocolWildcardingNotAllowed - * 708 WildCardNotPermittedInSrcIP */ -clear_and_exit: - ClearNameValueList(&data); -} - -static void -UpdatePinhole(struct upnphttp * h, const char * action, const char * ns) -{ -#if 0 - static const char resp[] = - "" - ""; -#endif - static const char resp[] = - "" - ""; - char body[512]; - int bodylen; - struct NameValueParserData data; - const char * uid_str, * leaseTime; - char iaddr[INET6_ADDRSTRLEN]; - unsigned short iport; - int ltime; - int uid; - int n; - - if(CheckStatus(h)==0) - return; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid_str = GetValueFromNameValueList(&data, "UniqueID"); - leaseTime = GetValueFromNameValueList(&data, "NewLeaseTime"); - uid = uid_str ? atoi(uid_str) : -1; - ltime = leaseTime ? atoi(leaseTime) : -1; - ClearNameValueList(&data); - - if(uid < 0 || uid > 65535 || ltime <= 0 || ltime > 86400) - { - SoapError(h, 402, "Invalid Args"); - return; - } - - /* Check that client is not updating an pinhole - * it doesn't have access to, because of its public access */ - n = upnp_get_pinhole_info(uid, NULL, 0, NULL, - iaddr, sizeof(iaddr), &iport, - NULL, /* proto */ - NULL, 0, /* desc, desclen */ - NULL, NULL); - if (n >= 0) - { - if(PinholeVerification(h, iaddr, iport) <= 0) - return; - } - else if(n == -2) - { - SoapError(h, 704, "NoSuchEntry"); - return; - } - else - { - SoapError(h, 501, "ActionFailed"); - return; - } - - syslog(LOG_INFO, "%s: (inbound) updating lease duration to %d for pinhole with ID: %d", - action, ltime, uid); - - n = upnp_update_inboundpinhole(uid, ltime); - if(n == -1) - SoapError(h, 704, "NoSuchEntry"); - else if(n < 0) - SoapError(h, 501, "ActionFailed"); - else { - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } -} - -static void -GetOutboundPinholeTimeout(struct upnphttp * h, const char * action, const char * ns) -{ - int r; - - static const char resp[] = - "" - "%d" - ""; - - char body[512]; - int bodylen; - struct NameValueParserData data; - char * int_ip, * int_port, * rem_host, * rem_port, * protocol; - int opt=0; - /*int proto=0;*/ - unsigned short iport, rport; - - if (GETFLAG(IPV6FCFWDISABLEDMASK)) - { - SoapError(h, 702, "FirewallDisabled"); - return; - } - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - int_ip = GetValueFromNameValueList(&data, "InternalClient"); - int_port = GetValueFromNameValueList(&data, "InternalPort"); - rem_host = GetValueFromNameValueList(&data, "RemoteHost"); - rem_port = GetValueFromNameValueList(&data, "RemotePort"); - protocol = GetValueFromNameValueList(&data, "Protocol"); - - rport = (unsigned short)atoi(rem_port); - iport = (unsigned short)atoi(int_port); - /*proto = atoi(protocol);*/ - - syslog(LOG_INFO, "%s: retrieving timeout for outbound pinhole from [%s]:%hu to [%s]:%hu protocol %s", action, int_ip, iport,rem_host, rport, protocol); - - /* TODO */ - r = -1;/*upnp_check_outbound_pinhole(proto, &opt);*/ - - switch(r) - { - case 1: /* success */ - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"*/, - opt, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - break; - case -5: /* Protocol not supported */ - SoapError(h, 705, "ProtocolNotSupported"); - break; - default: - SoapError(h, 501, "ActionFailed"); - } - ClearNameValueList(&data); -} - -static void -DeletePinhole(struct upnphttp * h, const char * action, const char * ns) -{ - int n; -#if 0 - static const char resp[] = - "" - ""; -#endif - static const char resp[] = - "" - ""; - char body[512]; - int bodylen; - - struct NameValueParserData data; - const char * uid_str; - char iaddr[INET6_ADDRSTRLEN]; - int proto; - unsigned short iport; - unsigned int leasetime; - int uid; - - if(CheckStatus(h)==0) - return; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid_str = GetValueFromNameValueList(&data, "UniqueID"); - uid = uid_str ? atoi(uid_str) : -1; - ClearNameValueList(&data); - - if(uid < 0 || uid > 65535) - { - SoapError(h, 402, "Invalid Args"); - return; - } - - /* Check that client is not deleting an pinhole - * it doesn't have access to, because of its public access */ - n = upnp_get_pinhole_info(uid, NULL, 0, NULL, - iaddr, sizeof(iaddr), &iport, - &proto, - NULL, 0, /* desc, desclen */ - &leasetime, NULL); - if (n >= 0) - { - if(PinholeVerification(h, iaddr, iport) <= 0) - return; - } - else if(n == -2) - { - SoapError(h, 704, "NoSuchEntry"); - return; - } - else - { - SoapError(h, 501, "ActionFailed"); - return; - } - - n = upnp_delete_inboundpinhole(uid); - if(n < 0) - { - syslog(LOG_INFO, "%s: (inbound) failed to remove pinhole with ID: %d", - action, uid); - SoapError(h, 501, "ActionFailed"); - return; - } - syslog(LOG_INFO, "%s: (inbound) pinhole with ID %d successfully removed", - action, uid); - bodylen = snprintf(body, sizeof(body), resp, - action, ns, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -CheckPinholeWorking(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%d" - ""; - char body[512]; - int bodylen; - int r; - struct NameValueParserData data; - const char * uid_str; - int uid; - char iaddr[INET6_ADDRSTRLEN]; - unsigned short iport; - unsigned int packets; - - if(CheckStatus(h)==0) - return; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid_str = GetValueFromNameValueList(&data, "UniqueID"); - uid = uid_str ? atoi(uid_str) : -1; - ClearNameValueList(&data); - - if(uid < 0 || uid > 65535) - { - SoapError(h, 402, "Invalid Args"); - return; - } - - /* Check that client is not checking a pinhole - * it doesn't have access to, because of its public access */ - r = upnp_get_pinhole_info(uid, - NULL, 0, NULL, - iaddr, sizeof(iaddr), &iport, - NULL, /* proto */ - NULL, 0, /* desc, desclen */ - NULL, &packets); - if (r >= 0) - { - if(PinholeVerification(h, iaddr, iport) <= 0) - return ; - if(packets == 0) - { - SoapError(h, 709, "NoPacketSent"); - return; - } - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"*/, - 1, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - } - else if(r == -2) - SoapError(h, 704, "NoSuchEntry"); - else - SoapError(h, 501, "ActionFailed"); -} - -static void -GetPinholePackets(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%u" - ""; - char body[512]; - int bodylen; - struct NameValueParserData data; - const char * uid_str; - int n; - char iaddr[INET6_ADDRSTRLEN]; - unsigned short iport; - unsigned int packets = 0; - int uid; - int proto; - unsigned int leasetime; - - if(CheckStatus(h)==0) - return; - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - uid_str = GetValueFromNameValueList(&data, "UniqueID"); - uid = uid_str ? atoi(uid_str) : -1; - ClearNameValueList(&data); - - if(uid < 0 || uid > 65535) - { - SoapError(h, 402, "Invalid Args"); - return; - } - - /* Check that client is not getting infos of a pinhole - * it doesn't have access to, because of its public access */ - n = upnp_get_pinhole_info(uid, NULL, 0, NULL, - iaddr, sizeof(iaddr), &iport, - &proto, - NULL, 0, /* desc, desclen */ - &leasetime, &packets); - if (n >= 0) - { - if(PinholeVerification(h, iaddr, iport)<=0) - return ; - } -#if 0 - else if(r == -4 || r == -1) - { - SoapError(h, 704, "NoSuchEntry"); - } -#endif - - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"*/, - packets, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} -#endif - -#ifdef ENABLE_DP_SERVICE -static void -SendSetupMessage(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%s" - ""; - char body[1024]; - int bodylen; - struct NameValueParserData data; - const char * ProtocolType; /* string */ - const char * InMessage; /* base64 */ - const char * OutMessage = ""; /* base64 */ - - ParseNameValue(h->req_buf + h->req_contentoff, h->req_contentlen, &data); - ProtocolType = GetValueFromNameValueList(&data, "ProtocolType"); /* string */ - InMessage = GetValueFromNameValueList(&data, "InMessage"); /* base64 */ - - if(ProtocolType == NULL || InMessage == NULL) - { - ClearNameValueList(&data); - SoapError(h, 402, "Invalid Args"); - return; - } - /*if(strcmp(ProtocolType, "DeviceProtection:1") != 0)*/ - if(strcmp(ProtocolType, "WPS") != 0) - { - ClearNameValueList(&data); - SoapError(h, 600, "Argument Value Invalid"); /* 703 ? */ - return; - } - /* TODO : put here code for WPS */ - - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:DeviceProtection:1"*/, - OutMessage, action); - BuildSendAndCloseSoapResp(h, body, bodylen); - ClearNameValueList(&data); -} - -static void -GetSupportedProtocols(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "" - ""; - char body[1024]; - int bodylen; - const char * ProtocolList = - "\n" - "" - "WPS" - "PKCS5" - ""; - - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:DeviceProtection:1"*/, - ProtocolList, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} - -static void -GetAssignedRoles(struct upnphttp * h, const char * action, const char * ns) -{ - static const char resp[] = - "" - "%s" - ""; - char body[1024]; - int bodylen; - const char * RoleList = "Public"; /* list of roles separated by spaces */ - -#ifdef ENABLE_HTTPS - if(h->ssl != NULL) { - /* we should get the Roles of the session (based on client certificate) */ - X509 * peercert; - peercert = SSL_get_peer_certificate(h->ssl); - if(peercert != NULL) { - RoleList = "Admin Basic"; - X509_free(peercert); - } - } -#endif - - bodylen = snprintf(body, sizeof(body), resp, - action, ns/*"urn:schemas-upnp-org:service:DeviceProtection:1"*/, - RoleList, action); - BuildSendAndCloseSoapResp(h, body, bodylen); -} -#endif - -/* Windows XP as client send the following requests : - * GetConnectionTypeInfo - * GetNATRSIPStatus - * ? GetTotalBytesSent - WANCommonInterfaceConfig - * ? GetTotalBytesReceived - idem - * ? GetTotalPacketsSent - idem - * ? GetTotalPacketsReceived - idem - * GetCommonLinkProperties - idem - * GetStatusInfo - WANIPConnection - * GetExternalIPAddress - * QueryStateVariable / ConnectionStatus! - */ -static const struct -{ - const char * methodName; - void (*methodImpl)(struct upnphttp *, const char *, const char *); -} -soapMethods[] = -{ - /* WANCommonInterfaceConfig */ - { "QueryStateVariable", QueryStateVariable}, - { "GetTotalBytesSent", GetTotalBytesSent}, - { "GetTotalBytesReceived", GetTotalBytesReceived}, - { "GetTotalPacketsSent", GetTotalPacketsSent}, - { "GetTotalPacketsReceived", GetTotalPacketsReceived}, - { "GetCommonLinkProperties", GetCommonLinkProperties}, - { "GetStatusInfo", GetStatusInfo}, - /* WANIPConnection */ - { "GetConnectionTypeInfo", GetConnectionTypeInfo }, - { "GetNATRSIPStatus", GetNATRSIPStatus}, - { "GetExternalIPAddress", GetExternalIPAddress}, - { "AddPortMapping", AddPortMapping}, - { "DeletePortMapping", DeletePortMapping}, - { "GetGenericPortMappingEntry", GetGenericPortMappingEntry}, - { "GetSpecificPortMappingEntry", GetSpecificPortMappingEntry}, -/* Required in WANIPConnection:2 */ - { "SetConnectionType", SetConnectionType}, - { "RequestConnection", RequestConnection}, - { "ForceTermination", ForceTermination}, - { "AddAnyPortMapping", AddAnyPortMapping}, - { "DeletePortMappingRange", DeletePortMappingRange}, - { "GetListOfPortMappings", GetListOfPortMappings}, -#ifdef ENABLE_L3F_SERVICE - /* Layer3Forwarding */ - { "SetDefaultConnectionService", SetDefaultConnectionService}, - { "GetDefaultConnectionService", GetDefaultConnectionService}, -#endif -#ifdef ENABLE_6FC_SERVICE - /* WANIPv6FirewallControl */ - { "GetFirewallStatus", GetFirewallStatus}, /* Required */ - { "AddPinhole", AddPinhole}, /* Required */ - { "UpdatePinhole", UpdatePinhole}, /* Required */ - { "GetOutboundPinholeTimeout", GetOutboundPinholeTimeout}, /* Optional */ - { "DeletePinhole", DeletePinhole}, /* Required */ - { "CheckPinholeWorking", CheckPinholeWorking}, /* Optional */ - { "GetPinholePackets", GetPinholePackets}, /* Required */ -#endif -#ifdef ENABLE_DP_SERVICE - /* DeviceProtection */ - { "SendSetupMessage", SendSetupMessage}, /* Required */ - { "GetSupportedProtocols", GetSupportedProtocols}, /* Required */ - { "GetAssignedRoles", GetAssignedRoles}, /* Required */ -#endif - { 0, 0 } -}; - -void -ExecuteSoapAction(struct upnphttp * h, const char * action, int n) -{ - char * p; - char * p2; - int i, len, methodlen; - char namespace[256]; - - /* SoapAction example : - * urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo */ - p = strchr(action, '#'); - if(p && (p - action) < n) { - for(i = 0; i < ((int)sizeof(namespace) - 1) && (action + i) < p; i++) - namespace[i] = action[i]; - namespace[i] = '\0'; - p++; - p2 = strchr(p, '"'); - if(p2 && (p2 - action) <= n) - methodlen = p2 - p; - else - methodlen = n - (p - action); - /*syslog(LOG_DEBUG, "SoapMethod: %.*s %d %d %p %p %d", - methodlen, p, methodlen, n, action, p, (int)(p - action));*/ - for(i = 0; soapMethods[i].methodName; i++) { - len = strlen(soapMethods[i].methodName); - if((len == methodlen) && memcmp(p, soapMethods[i].methodName, len) == 0) { -#ifdef DEBUG - syslog(LOG_DEBUG, "Remote Call of SoapMethod '%s' %s", - soapMethods[i].methodName, namespace); -#endif /* DEBUG */ - soapMethods[i].methodImpl(h, soapMethods[i].methodName, namespace); - return; - } - } - syslog(LOG_NOTICE, "SoapMethod: Unknown: %.*s %s", methodlen, p, namespace); - } else { - syslog(LOG_NOTICE, "cannot parse SoapAction"); - } - - SoapError(h, 401, "Invalid Action"); -} - -/* Standard Errors: - * - * errorCode errorDescription Description - * -------- ---------------- ----------- - * 401 Invalid Action No action by that name at this service. - * 402 Invalid Args Could be any of the following: not enough in args, - * too many in args, no in arg by that name, - * one or more in args are of the wrong data type. - * 403 Out of Sync Out of synchronization. - * 501 Action Failed May be returned in current state of service - * prevents invoking that action. - * 600-699 TBD Common action errors. Defined by UPnP Forum - * Technical Committee. - * 700-799 TBD Action-specific errors for standard actions. - * Defined by UPnP Forum working committee. - * 800-899 TBD Action-specific errors for non-standard actions. - * Defined by UPnP vendor. -*/ -void -SoapError(struct upnphttp * h, int errCode, const char * errDesc) -{ - static const char resp[] = - "" - "" - "" - "s:Client" - "UPnPError" - "" - "" - "%d" - "%s" - "" - "" - "" - "" - ""; - - char body[2048]; - int bodylen; - - syslog(LOG_INFO, "Returning UPnPError %d: %s", errCode, errDesc); - bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc); - BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen); - SendRespAndClose_upnphttp(h); -} - diff --git a/src/contrib/miniupnp/miniupnpd/upnpsoap.h b/src/contrib/miniupnp/miniupnpd/upnpsoap.h deleted file mode 100644 index 5dda29f..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpsoap.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: upnpsoap.h,v 1.8 2007/02/07 22:16:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPSOAP_H_INCLUDED -#define UPNPSOAP_H_INCLUDED - -/* ExecuteSoapAction(): - * this method executes the requested Soap Action */ -void -ExecuteSoapAction(struct upnphttp *, const char *, int); - -/* SoapError(): - * sends a correct SOAP error with an UPNPError code and - * description */ -void -SoapError(struct upnphttp * h, int errCode, const char * errDesc); - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnpurns.h b/src/contrib/miniupnp/miniupnpd/upnpurns.h deleted file mode 100644 index db10664..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnpurns.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: upnpurns.h,v 1.1 2011/05/13 15:32:53 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPURNS_H_INCLUDED -#define UPNPURNS_H_INCLUDED - -#include "config.h" - -#ifdef IGD_V2 -/* IGD v2 */ -#define DEVICE_TYPE_IGD "urn:schemas-upnp-org:device:InternetGatewayDevice:2" -#define DEVICE_TYPE_WAN "urn:schemas-upnp-org:device:WANDevice:2" -#define DEVICE_TYPE_WANC "urn:schemas-upnp-org:device:WANConnectionDevice:2" -#define SERVICE_TYPE_WANIPC "urn:schemas-upnp-org:service:WANIPConnection:2" -#define SERVICE_ID_WANIPC "urn:upnp-org:serviceId:WANIPConn1" -#else -/* IGD v1 */ -#define DEVICE_TYPE_IGD "urn:schemas-upnp-org:device:InternetGatewayDevice:1" -#define DEVICE_TYPE_WAN "urn:schemas-upnp-org:device:WANDevice:1" -#define DEVICE_TYPE_WANC "urn:schemas-upnp-org:device:WANConnectionDevice:1" -#define SERVICE_TYPE_WANIPC "urn:schemas-upnp-org:service:WANIPConnection:1" -#define SERVICE_ID_WANIPC "urn:upnp-org:serviceId:WANIPConn1" -#endif - -#endif - diff --git a/src/contrib/miniupnp/miniupnpd/upnputils.c b/src/contrib/miniupnp/miniupnpd/upnputils.c deleted file mode 100644 index d0bd5ce..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnputils.c +++ /dev/null @@ -1,238 +0,0 @@ -/* $Id: upnputils.c,v 1.12 2018/03/13 10:25:20 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef AF_LINK -#include -#endif -#include - -#include "upnputils.h" -#include "upnpglobalvars.h" -#ifdef ENABLE_IPV6 -#include "getroute.h" -#endif - -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size) -{ - char buffer[64]; - unsigned short port = 0; - int n = -1; - - switch(addr->sa_family) - { -#ifdef AF_INET6 - case AF_INET6: - if(inet_ntop(addr->sa_family, - &((struct sockaddr_in6 *)addr)->sin6_addr, - buffer, sizeof(buffer)) == NULL) { - snprintf(buffer, sizeof(buffer), "inet_ntop: %s", strerror(errno)); - } - port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); - if(((struct sockaddr_in6 *)addr)->sin6_scope_id > 0) { - char ifname[IF_NAMESIZE]; - if(if_indextoname(((struct sockaddr_in6 *)addr)->sin6_scope_id, ifname) == NULL) - strncpy(ifname, "ERROR", sizeof(ifname)); - n = snprintf(str, size, "[%s%%%s]:%hu", buffer, ifname, port); - } else { - n = snprintf(str, size, "[%s]:%hu", buffer, port); - } - break; -#endif /* AF_INET6 */ - case AF_INET: - if(inet_ntop(addr->sa_family, - &((struct sockaddr_in *)addr)->sin_addr, - buffer, sizeof(buffer)) == NULL) { - snprintf(buffer, sizeof(buffer), "inet_ntop: %s", strerror(errno)); - } - port = ntohs(((struct sockaddr_in *)addr)->sin_port); - n = snprintf(str, size, "%s:%hu", buffer, port); - break; -#ifdef AF_LINK -#if defined(__sun) - /* solaris does not seem to have link_ntoa */ - /* #define link_ntoa _link_ntoa */ -#define link_ntoa(x) "dummy-link_ntoa" -#endif - case AF_LINK: - { - struct sockaddr_dl * sdl = (struct sockaddr_dl *)addr; - n = snprintf(str, size, "index=%hu type=%d %s", - sdl->sdl_index, sdl->sdl_type, - link_ntoa(sdl)); - } - break; -#endif /* AF_LINK */ - default: - n = snprintf(str, size, "unknown address family %d", addr->sa_family); -#if 0 - n = snprintf(str, size, "unknown address family %d " - "%02x %02x %02x %02x %02x %02x %02x %02x", - addr->sa_family, - addr->sa_data[0], addr->sa_data[1], (unsigned)addr->sa_data[2], addr->sa_data[3], - addr->sa_data[4], addr->sa_data[5], (unsigned)addr->sa_data[6], addr->sa_data[7]); -#endif - } - return n; -} - - -int -set_non_blocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if(flags < 0) - return 0; - if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) - return 0; - return 1; -} - -struct lan_addr_s * -get_lan_for_peer(const struct sockaddr * peer) -{ - struct lan_addr_s * lan_addr = NULL; -#ifdef DEBUG - char dbg_str[64]; -#endif /* DEBUG */ - -#ifdef ENABLE_IPV6 - if(peer->sa_family == AF_INET6) - { - struct sockaddr_in6 * peer6 = (struct sockaddr_in6 *)peer; - if(IN6_IS_ADDR_V4MAPPED(&peer6->sin6_addr)) - { - struct in_addr peer_addr; - memcpy(&peer_addr, &peer6->sin6_addr.s6_addr[12], 4); - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - if( (peer_addr.s_addr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) - break; - } - } - else - { - int index = -1; - if(peer6->sin6_scope_id > 0) - index = (int)peer6->sin6_scope_id; - else - { - if(get_src_for_route_to(peer, NULL, NULL, &index) < 0) - return NULL; - } - syslog(LOG_DEBUG, "%s looking for LAN interface index=%d", - "get_lan_for_peer()", index); - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - syslog(LOG_DEBUG, - "ifname=%s index=%u str=%s addr=%08x mask=%08x", - lan_addr->ifname, lan_addr->index, - lan_addr->str, - ntohl(lan_addr->addr.s_addr), - ntohl(lan_addr->mask.s_addr)); - if(index == (int)lan_addr->index) - break; - } - } - } - else if(peer->sa_family == AF_INET) - { -#endif /* ENABLE_IPV6 */ - for(lan_addr = lan_addrs.lh_first; - lan_addr != NULL; - lan_addr = lan_addr->list.le_next) - { - if( (((const struct sockaddr_in *)peer)->sin_addr.s_addr & lan_addr->mask.s_addr) - == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) - break; - } -#ifdef ENABLE_IPV6 - } -#endif /* ENABLE_IPV6 */ - -#ifdef DEBUG - sockaddr_to_string(peer, dbg_str, sizeof(dbg_str)); - if(lan_addr) { - syslog(LOG_DEBUG, "%s: %s found in LAN %s %s", - "get_lan_for_peer()", dbg_str, - lan_addr->ifname, lan_addr->str); - } else { - syslog(LOG_DEBUG, "%s: %s not found !", "get_lan_for_peer()", - dbg_str); - } -#endif /* DEBUG */ - return lan_addr; -} - -time_t upnp_time(void) -{ -#if defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC) -#if defined(CLOCK_MONOTONIC_FAST) -#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST -#else -#define UPNP_CLOCKID CLOCK_MONOTONIC -#endif - struct timespec ts; - if (clock_gettime(UPNP_CLOCKID, &ts) < 0) - return time(NULL); - else - return ts.tv_sec; -#else - return time(NULL); -#endif -} - -time_t upnp_get_uptime(void) -{ -#if defined(CLOCK_UPTIME_FAST) || defined(CLOCK_UPTIME) -#if defined(CLOCK_UPTIME_FAST) -#define UPNP_CLOCKID_UPTIME CLOCK_UPTIME_FAST -#else -#define UPNP_CLOCKID_UPTIME CLOCK_UPTIME -#endif - if(GETFLAG(SYSUPTIMEMASK)) - { - struct timespec ts; - if (clock_gettime(UPNP_CLOCKID_UPTIME, &ts) >= 0) - return ts.tv_sec; - } -#endif - return upnp_time() - startup_time; -} - -int upnp_gettimeofday(struct timeval * tv) -{ -#if defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC) - struct timespec ts; - int ret_code = clock_gettime(UPNP_CLOCKID, &ts); - if (ret_code == 0) - { - tv->tv_sec = ts.tv_sec; - tv->tv_usec = ts.tv_nsec / 1000; - } - return ret_code; -#else - return gettimeofday(tv, NULL); -#endif -} diff --git a/src/contrib/miniupnp/miniupnpd/upnputils.h b/src/contrib/miniupnp/miniupnpd/upnputils.h deleted file mode 100644 index 66de75b..0000000 --- a/src/contrib/miniupnp/miniupnpd/upnputils.h +++ /dev/null @@ -1,74 +0,0 @@ -/* $Id: upnputils.h,v 1.9 2018/03/13 10:25:20 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2018 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPUTILS_H_INCLUDED -#define UPNPUTILS_H_INCLUDED - -/** - * convert a struct sockaddr to a human readable string. - * [ipv6]:port or ipv4:port - * return the number of characters used (as snprintf) - */ -int -sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size); - -/** - * set the file description as non blocking - * return 0 in case of failure, 1 in case of success - */ -int -set_non_blocking(int fd); - -/** - * get the LAN which the peer belongs to - */ -struct lan_addr_s * -get_lan_for_peer(const struct sockaddr * peer); - -/** - * get the time for upnp (release expiration, etc.) - * Similar to a monotonic time(NULL) - */ -time_t upnp_time(void); - -/** - * return either the machine or the daemon uptime - */ -time_t upnp_get_uptime(void); - -/** - * get the time for upnp - * Similar to a monotonic gettimeofday(tv, NULL) - */ -int upnp_gettimeofday(struct timeval * tv); - -/** - * define portability macros - */ -#if defined(__sun) -static __inline size_t _sa_len(const struct sockaddr *addr) -{ - if (addr->sa_family == AF_INET) - return (sizeof(struct sockaddr_in)); - else if (addr->sa_family == AF_INET6) - return (sizeof(struct sockaddr_in6)); - else - return (sizeof(struct sockaddr)); -} -# define SA_LEN(sa) (_sa_len(sa)) -#else -#if !defined(SA_LEN) -# define SA_LEN(sa) ((sa)->sa_len) -#endif -#endif - -#ifndef MAX -# define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - -#endif - diff --git a/src/contrib/miniupnpc/CMakeLists.txt b/src/contrib/miniupnpc/CMakeLists.txt deleted file mode 100644 index 464ae74..0000000 --- a/src/contrib/miniupnpc/CMakeLists.txt +++ /dev/null @@ -1,176 +0,0 @@ -cmake_minimum_required (VERSION 2.6) - -project (miniupnpc C) -set (MINIUPNPC_VERSION 1.9) -set (MINIUPNPC_API_VERSION 10) - -if (NOT CMAKE_BUILD_TYPE) - if (WIN32) - set (DEFAULT_BUILD_TYPE MinSizeRel) - else (WIN32) - set (DEFAULT_BUILD_TYPE RelWithDebInfo) - endif(WIN32) - set (CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() - -option (UPNPC_BUILD_STATIC "Build static library" TRUE) -option (UPNPC_BUILD_SHARED "Build shared library" TRUE) -if (NOT WIN32) - option (UPNPC_BUILD_TESTS "Build test executables" TRUE) -endif (NOT WIN32) -option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE) - -mark_as_advanced (NO_GETADDRINFO) - -if (NO_GETADDRINFO) - add_definitions (-DNO_GETADDRINFO) -endif (NO_GETADDRINFO) - -if (NOT WIN32) - add_definitions (-DMINIUPNPC_SET_SOCKET_TIMEOUT) - add_definitions (-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=1) -else (NOT WIN32) - add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends -endif (NOT WIN32) - -if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") - add_definitions (-DMACOSX -D_DARWIN_C_SOURCE) -endif () - -# Set compiler specific build flags -if (CMAKE_COMPILER_IS_GNUC) - # Set our own default flags at first run. - if (NOT CONFIGURED) - - if (NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - set (_PIC -fPIC) - endif (CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - - set (CMAKE_C_FLAGS "${_PIC} -Wall $ENV{CFLAGS}" # CMAKE_C_FLAGS gets appended to the other C flags - CACHE STRING "Flags used by the C compiler during normal builds." FORCE) - set (CMAKE_C_FLAGS_DEBUG "-g -DDDEBUG" - CACHE STRING "Flags used by the C compiler during debug builds." FORCE) - set (CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG" - CACHE STRING "Flags used by the C compiler during release builds." FORCE) - set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DNDEBUG" - CACHE STRING "Flags used by the C compiler during release builds." FORCE) - set (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" - CACHE STRING "Flags used by the C compiler during release builds." FORCE) - - endif (NOT CONFIGURED) -endif () - -configure_file (miniupnpcstrings.h.cmake ${CMAKE_BINARY_DIR}/miniupnpcstrings.h) -include_directories (${CMAKE_BINARY_DIR}) - -set (MINIUPNPC_SOURCES - igd_desc_parse.c - miniupnpc.c - minixml.c - minisoap.c - miniwget.c - upnpc.c - upnpcommands.c - upnpreplyparse.c - upnperrors.c - connecthostport.c - portlistingparse.c - receivedata.c -) - -if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - set (MINIUPNPC_SOURCES ${MINIUPNPC_SOURCES} minissdpc.c) -endif (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "AmigaOS") - -if (WIN32) - set_source_files_properties (${MINIUPNPC_SOURCES} PROPERTIES - COMPILE_DEFINITIONS STATICLIB - COMPILE_DEFINITIONS MINIUPNP_EXPORTS - ) -endif (WIN32) - -if (WIN32) -# find_library (WINSOCK2_LIBRARY NAMES ws2_32 WS2_32 Ws2_32) -# find_library (IPHLPAPI_LIBRARY NAMES iphlpapi) - set(WINSOCK2_LIBRARY ws2_32) - set(IPHLPAPI_LIBRARY iphlpapi) - set (LDLIBS ${WINSOCK2_LIBRARY} ${IPHLPAPI_LIBRARY} ${LDLIBS}) -#elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris") -# find_library (SOCKET_LIBRARY NAMES socket) -# find_library (NSL_LIBRARY NAMES nsl) -# find_library (RESOLV_LIBRARY NAMES resolv) -# set (LDLIBS ${SOCKET_LIBRARY} ${NSL_LIBRARY} ${RESOLV_LIBRARY} ${LDLIBS}) -endif (WIN32) - -if (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) - message (FATAL "Both shared and static libraries are disabled!") -endif (NOT UPNPC_BUILD_STATIC AND NOT UPNPC_BUILD_SHARED) - -if (UPNPC_BUILD_STATIC) - add_library (upnpc-static STATIC ${MINIUPNPC_SOURCES}) - set_target_properties (upnpc-static PROPERTIES OUTPUT_NAME "miniupnpc") - target_link_libraries (upnpc-static ${LDLIBS}) - set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-static) - set (UPNPC_LIBRARY_TARGET upnpc-static) -endif (UPNPC_BUILD_STATIC) - -if (UPNPC_BUILD_SHARED) - add_library (upnpc-shared SHARED ${MINIUPNPC_SOURCES}) - set_target_properties (upnpc-shared PROPERTIES OUTPUT_NAME "miniupnpc") - set_target_properties (upnpc-shared PROPERTIES VERSION ${MINIUPNPC_VERSION}) - set_target_properties (upnpc-shared PROPERTIES SOVERSION ${MINIUPNPC_API_VERSION}) - target_link_libraries (upnpc-shared ${LDLIBS}) - set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} upnpc-shared) - set (UPNPC_LIBRARY_TARGET upnpc-shared) -endif (UPNPC_BUILD_SHARED) - -if (UPNPC_BUILD_TESTS) - add_executable (testminixml testminixml.c minixml.c igd_desc_parse.c) - target_link_libraries (testminixml ${LDLIBS}) - - add_executable (minixmlvalid minixmlvalid.c minixml.c) - target_link_libraries (minixmlvalid ${LDLIBS}) - - add_executable (testupnpreplyparse testupnpreplyparse.c - minixml.c upnpreplyparse.c) - target_link_libraries (testupnpreplyparse ${LDLIBS}) - - add_executable (testigddescparse testigddescparse.c - igd_desc_parse.c minixml.c miniupnpc.c miniwget.c minissdpc.c - upnpcommands.c upnpreplyparse.c minisoap.c connecthostport.c - portlistingparse.c receivedata.c - ) - target_link_libraries (testigddescparse ${LDLIBS}) - - add_executable (testminiwget testminiwget.c - miniwget.c miniupnpc.c minisoap.c upnpcommands.c minissdpc.c - upnpreplyparse.c minixml.c igd_desc_parse.c connecthostport.c - portlistingparse.c receivedata.c - ) - target_link_libraries (testminiwget ${LDLIBS}) - -# set (UPNPC_INSTALL_TARGETS ${UPNPC_INSTALL_TARGETS} testminixml minixmlvalid testupnpreplyparse testigddescparse testminiwget) -endif (UPNPC_BUILD_TESTS) - - -install (TARGETS ${UPNPC_INSTALL_TARGETS} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX} -) -install (FILES - miniupnpc.h - miniwget.h - upnpcommands.h - igd_desc_parse.h - upnpreplyparse.h - upnperrors.h - declspec.h - DESTINATION include/miniupnpc -) - -set (CONFIGURED YES CACHE INTERNAL "") - -# vim: ts=2:sw=2 diff --git a/src/contrib/miniupnpc/Changelog.txt b/src/contrib/miniupnpc/Changelog.txt deleted file mode 100644 index 53e9a11..0000000 --- a/src/contrib/miniupnpc/Changelog.txt +++ /dev/null @@ -1,585 +0,0 @@ -$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $ -miniUPnP client Changelog. - -2014/02/05: - handle EINPROGRESS after connect() - -2014/02/03: - minixml now handle XML comments - -VERSION 1.9 : released 2014/01/31 - -2014/01/31: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - increment API_VERSION to 10 - -2013/12/09: - --help and -h arguments in upnpc.c - -2013/10/07: - fixed potential buffer overrun in miniwget.c - Modified UPNP_GetValidIGD() to check for ExternalIpAddress - -2013/08/01: - define MAXHOSTNAMELEN if not already done - -2013/06/06: - update upnpreplyparse to allow larger values (128 chars instead of 64) - -2013/05/14: - Update upnpreplyparse to take into account "empty" elements - validate upnpreplyparse.c code with "make check" - -2013/05/03: - Fix Solaris build thanks to Maciej MaÅ‚ecki - -2013/04/27: - Fix testminiwget.sh for BSD - -2013/03/23: - Fixed Makefile for *BSD - -2013/03/11: - Update Makefile to use JNAerator version 0.11 - -2013/02/11: - Fix testminiwget.sh for use with dash - Use $(DESTDIR) in Makefile - -VERSION 1.8 : released 2013/02/06 - -2012/10/16: - fix testminiwget with no IPv6 support - -2012/09/27: - Rename all include guards to not clash with C99 - (7.1.3 Reserved identifiers). - -2012/08/30: - Added -e option to upnpc program (set description for port mappings) - -2012/08/29: - Python 3 support (thanks to Christopher Foo) - -2012/08/11: - Fix a memory link in UPNP_GetValidIGD() - Try to handle scope id in link local IPv6 URL under MS Windows - -2012/07/20: - Disable HAS_IP_MREQN on DragonFly BSD - -2012/06/28: - GetUPNPUrls() now inserts scope into link-local IPv6 addresses - -2012/06/23: - More error return checks in upnpc.c - #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id - parseURL() now parses IPv6 addresses scope - new parameter for miniwget() : IPv6 address scope - increment API_VERSION to 9 - -2012/06/20: - fixed CMakeLists.txt - -2012/05/29 - Improvements in testminiwget.sh - -VERSION 1.7 : released 2012/05/24 - -2012/05/01: - Cleanup settings of CFLAGS in Makefile - Fix signed/unsigned integer comparaisons - -2012/04/20: - Allow to specify protocol with TCP or UDP for -A option - -2012/04/09: - Only try to fetch XML description once in UPNP_GetValidIGD() - Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. - -2012/04/05: - minor improvements to minihttptestserver.c - -2012/03/15: - upnperrors.c returns valid error string for unrecognized error codes - -2012/03/08: - make minihttptestserver listen on loopback interface instead of 0.0.0.0 - -2012/01/25: - Maven installation thanks to Alexey Kuznetsov - -2012/01/21: - Replace WIN32 macro by _WIN32 - -2012/01/19: - Fixes in java wrappers thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc - Make and install .deb packages (python) thanks to Alexey Kuznetsov : - https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc - -2012/01/07: - The multicast interface can now be specified by name with IPv4. - -2012/01/02: - Install man page - -2011/11/25: - added header to Port Mappings list in upnpc.c - -2011/10/09: - Makefile : make clean now removes jnaerator generated files. - MINIUPNPC_VERSION in miniupnpc.h (updated by make) - -2011/09/12: - added rootdescURL to UPNPUrls structure. - -VERSION 1.6 : released 2011/07/25 - -2011/07/25: - Update doc for version 1.6 release - -2011/06/18: - Fix for windows in miniwget.c - -2011/06/04: - display remote host in port mapping listing - -2011/06/03: - Fix in make install : there were missing headers - -2011/05/26: - Fix the socket leak in miniwget thanks to Richard Marsh. - Permit to add leaseduration in -a command. Display lease duration. - -2011/05/15: - Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 - -2011/05/09: - add a test in testminiwget.sh. - more error checking in miniwget.c - -2011/05/06: - Adding some tool to test and validate miniwget.c - simplified and debugged miniwget.c - -2011/04/11: - moving ReceiveData() to a receivedata.c file. - parsing presentation url - adding IGD v2 WANIPv6FirewallControl commands - -2011/04/10: - update of miniupnpcmodule.c - comments in miniwget.c, update in testminiwget - Adding errors codes from IGD v2 - new functions in upnpc.c for IGD v2 - -2011/04/09: - Support for litteral ip v6 address in miniwget - -2011/04/08: - Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 - Updating APIVERSION - Supporting IPV6 in upnpDiscover() - Adding a -6 option to upnpc command line tool - -2011/03/18: - miniwget/parseURL() : return an error when url param is null. - fixing GetListOfPortMappings() - -2011/03/14: - upnpDiscover() now reporting an error code. - improvements in comments. - -2011/03/11: - adding miniupnpcstrings.h.cmake and CMakeLists.txt files. - -2011/02/15: - Implementation of GetListOfPortMappings() - -2011/02/07: - updates to minixml to support character data starting with spaces - minixml now support CDATA - upnpreplyparse treats specificaly - change in simpleUPnPcommand to return the buffer (simplification) - -2011/02/06: - Added leaseDuration argument to AddPortMapping() - Starting to implement GetListOfPortMappings() - -2011/01/11: - updating wingenminiupnpcstrings.c - -2011/01/04: - improving updateminiupnpcstrings.sh - -VERSION 1.5 : released 2011/01/01 - -2010/12/21: - use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo - -2010/12/11: - Improvements on getHTTPResponse() code. - -2010/12/09: - new code for miniwget that handle Chunked transfer encoding - using getHTTPResponse() in SOAP call code - Adding MANIFEST.in for 'python setup.py bdist_rpm' - -2010/11/25: - changes to minissdpc.c to compile under Win32. - see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 - -2010/09/17: - Various improvement to Makefile from MichaÅ‚ Górny - -2010/08/05: - Adding the script "external-ip.sh" from Reuben Hawkins - -2010/06/09: - update to python module to match modification made on 2010/04/05 - update to Java test code to match modification made on 2010/04/05 - all UPNP_* function now return an error if the SOAP request failed - at HTTP level. - -2010/04/17: - Using GetBestRoute() under win32 in order to find the - right interface to use. - -2010/04/12: - Retrying with HTTP/1.1 if HTTP/1.0 failed. see - http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 - -2010/04/07: - avoid returning duplicates in upnpDiscover() - -2010/04/05: - Create a connecthostport.h/.c with connecthostport() function - and use it in miniwget and miniupnpc. - Use getnameinfo() instead of inet_ntop or inet_ntoa - Work to make miniupnpc IPV6 compatible... - Add java test code. - Big changes in order to support device having both WANIPConnection - and WANPPPConnection. - -2010/04/04: - Use getaddrinfo() instead of gethostbyname() in miniwget. - -2010/01/06: - #define _DARWIN_C_SOURCE for Mac OS X - -2009/12/19: - Improve MinGW32 build - -2009/12/11: - adding a MSVC9 project to build the static library and executable - -2009/12/10: - Fixing some compilation stuff for Windows/MinGW - -2009/12/07: - adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS - some fixes for Windows when using virtual ethernet adapters (it is the - case with VMWare installed). - -2009/12/04: - some fixes for AmigaOS compilation - Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked - transfer encoding) - -2009/12/03: - updating printIDG and testigddescparse.c for debug. - modifications to compile under AmigaOS - adding a testminiwget program - Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked - transfer encoding - -2009/11/26: - fixing updateminiupnpcstrings.sh to take into account - which command that does not return an error code. - -VERSION 1.4 : released 2009/10/30 - -2009/10/16: - using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. - -2009/10/10: - Some fixes for compilation under Solaris - compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 - -2009/09/21: - fixing the code to ignore EINTR during connect() calls. - -2009/08/07: - Set socket timeout for connect() - Some cleanup in miniwget.c - -2009/08/04: - remove multiple redirections with -d in upnpc.c - Print textual error code in upnpc.c - Ignore EINTR during the connect() and poll() calls. - -2009/07/29: - fix in updateminiupnpcstrings.sh if OS name contains "/" - Sending a correct value for MX: field in SSDP request - -2009/07/20: - Change the Makefile to compile under Mac OS X - Fixed a stackoverflow in getDevicesFromMiniSSDPD() - -2009/07/09: - Compile under Haiku - generate miniupnpcstrings.h.in from miniupnpcstrings.h - -2009/06/04: - patching to compile under CygWin and cross compile for minGW - -VERSION 1.3 : - -2009/04/17: - updating python module - Use strtoull() when using C99 - -2009/02/28: - Fixed miniwget.c for compiling under sun - -2008/12/18: - cleanup in Makefile (thanks to Paul de Weerd) - minissdpc.c : win32 compatibility - miniupnpc.c : changed xmlns prefix from 'm' to 'u' - Removed NDEBUG (using DEBUG) - -2008/10/14: - Added the ExternalHost argument to DeletePortMapping() - -2008/10/11: - Added the ExternalHost argument to AddPortMapping() - Put a correct User-Agent: header in HTTP requests. - -VERSION 1.2 : - -2008/10/07: - Update docs - -2008/09/25: - Integrated sameport patch from Dario Meloni : Added a "sameport" - argument to upnpDiscover(). - -2008/07/18: - small modif to make Clang happy :) - -2008/07/17: - #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... - -2008/07/14: - include declspec.h in installation (to /usr/include/miniupnpc) - -VERSION 1.1 : - -2008/07/04: - standard options for install/ln instead of gnu-specific stuff. - -2008/07/03: - now builds a .dll and .lib with win32. (mingw32) - -2008/04/28: - make install now install the binary of the upnpc tool - -2008/04/27: - added testupnpigd.py - added error strings for miniupnpc "internal" errors - improved python module error/exception reporting. - -2008/04/23: - Completely rewrite igd_desc_parse.c in order to be compatible with - Linksys WAG200G - Added testigddescparse - updated python module - -VERSION 1.0 : - -2008/02/21: - put some #ifdef DEBUG around DisplayNameValueList() - -2008/02/18: - Improved error reporting in upnpcommands.c - UPNP_GetStatusInfo() returns LastConnectionError - -2008/02/16: - better error handling in minisoap.c - improving display of "valid IGD found" in upnpc.c - -2008/02/03: - Fixing UPNP_GetValidIGD() - improved make install :) - -2007/12/22: - Adding upnperrors.c/h to provide a strupnperror() function - used to translate UPnP error codes to string. - -2007/12/19: - Fixing getDevicesFromMiniSSDPD() - improved error reporting of UPnP functions - -2007/12/18: - It is now possible to specify a different location for MiniSSDPd socket. - working with MiniSSDPd is now more efficient. - python module improved. - -2007/12/16: - improving error reporting - -2007/12/13: - Try to improve compatibility by using HTTP/1.0 instead of 1.1 and - XML a bit different for SOAP. - -2007/11/25: - fixed select() call for linux - -2007/11/15: - Added -fPIC to CFLAG for better shared library code. - -2007/11/02: - Fixed a potential socket leak in miniwget2() - -2007/10/16: - added a parameter to upnpDiscover() in order to allow the use of another - interface than the default multicast interface. - -2007/10/12: - Fixed the creation of symbolic link in Makefile - -2007/10/08: - Added man page - -2007/10/02: - fixed memory bug in GetUPNPUrls() - -2007/10/01: - fixes in the Makefile - Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. - Added SONAME in the shared library to please debian :) - fixed MS Windows compilation (minissdpd is not available under MS Windows). - -2007/09/25: - small change to Makefile to be able to install in a different location - (default is /usr) - -2007/09/24: - now compiling both shared and static library - -2007/09/19: - Cosmetic changes on upnpc.c - -2007/09/02: - adapting to new miniSSDPd (release version ?) - -2007/08/31: - Usage of miniSSDPd to skip discovery process. - -2007/08/27: - fixed python module to allow compilation with Python older than Python 2.4 - -2007/06/12: - Added a python module. - -2007/05/19: - Fixed compilation under MinGW - -2007/05/15: - fixed a memory leak in AddPortMapping() - Added testupnpreplyparse executable to check the parsing of - upnp soap messages - minixml now ignore namespace prefixes. - -2007/04/26: - upnpc now displays external ip address with -s or -l - -2007/04/11: - changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210" - -2007/03/19: - cleanup in miniwget.c - -2007/03/01: - Small typo fix... - -2007/01/30: - Now parsing the HTTP header from SOAP responses in order to - get content-length value. - -2007/01/29: - Fixed the Soap Query to speedup the HTTP request. - added some Win32 DLL stuff... - -2007/01/27: - Fixed some WIN32 compatibility issues - -2006/12/14: - Added UPNPIGD_IsConnected() function in miniupnp.c/.h - Added UPNP_GetValidIGD() in miniupnp.c/.h - cleaned upnpc.c main(). now using UPNP_GetValidIGD() - -2006/12/07: - Version 1.0-RC1 released - -2006/12/03: - Minor changes to compile under SunOS/Solaris - -2006/11/30: - made a minixml parser validator program - updated minixml to handle attributes correctly - -2006/11/22: - Added a -r option to the upnpc sample thanks to Alexander Hubmann. - -2006/11/19: - Cleanup code to make it more ANSI C compliant - -2006/11/10: - detect and display local lan address. - -2006/11/04: - Packets and Bytes Sent/Received are now unsigned int. - -2006/11/01: - Bug fix thanks to Giuseppe D'Angelo - -2006/10/31: - C++ compatibility for .h files. - Added a way to get ip Address on the LAN used to reach the IGD. - -2006/10/25: - Added M-SEARCH to the services in the discovery process. - -2006/10/22: - updated the Makefile to use makedepend, added a "make install" - update Makefile - -2006/10/20: - fixing the description url parsing thanks to patch sent by - Wayne Dawe. - Fixed/translated some comments. - Implemented a better discover process, first looking - for IGD then for root devices (as some devices only reply to - M-SEARCH for root devices). - -2006/09/02: - added freeUPNPDevlist() function. - -2006/08/04: - More command line arguments checking - -2006/08/01: - Added the .bat file to compile under Win32 with minGW32 - -2006/07/31: - Fixed the rootdesc parser (igd_desc_parse.c) - -2006/07/20: - parseMSEARCHReply() is now returning the ST: line as well - starting changes to detect several UPnP devices on the network - -2006/07/19: - using GetCommonLinkProperties to get down/upload bitrate - diff --git a/src/contrib/miniupnpc/LICENSE b/src/contrib/miniupnpc/LICENSE deleted file mode 100644 index ac89a75..0000000 --- a/src/contrib/miniupnpc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -MiniUPnPc -Copyright (c) 2005-2011, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/contrib/miniupnpc/MANIFEST.in b/src/contrib/miniupnpc/MANIFEST.in deleted file mode 100644 index 54b86f9..0000000 --- a/src/contrib/miniupnpc/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README -include miniupnpcmodule.c -include setup.py -include *.h -include libminiupnpc.a diff --git a/src/contrib/miniupnpc/Makefile b/src/contrib/miniupnpc/Makefile deleted file mode 100644 index eaf42f0..0000000 --- a/src/contrib/miniupnpc/Makefile +++ /dev/null @@ -1,319 +0,0 @@ -# $Id: Makefile,v 1.107 2014/01/31 14:19:12 nanard Exp $ -# MiniUPnP Project -# http://miniupnp.free.fr/ -# http://miniupnp.tuxfamily.org/ -# https://github.com/miniupnp/miniupnp -# (c) 2005-2014 Thomas Bernard -# to install use : -# $ make DESTDIR=/tmp/dummylocation install -# or -# $ INSTALLPREFIX=/usr/local make install -# or -# $ make install (default INSTALLPREFIX is /usr) -OS = $(shell uname -s) -VERSION = $(shell cat VERSION) - -ifeq ($(OS), Darwin) -JARSUFFIX=mac -endif -ifeq ($(OS), Linux) -JARSUFFIX=linux -endif -ifneq (,$(findstring NT-5.1,$(OS))) -JARSUFFIX=win32 -endif - -HAVE_IPV6 ?= yes -export HAVE_IPV6 - -CC ?= gcc -#AR = gar -#CFLAGS = -O -g -DDEBUG -CFLAGS ?= -O -CFLAGS += -Wall -CFLAGS += -W -Wstrict-prototypes -CFLAGS += -fno-common -CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT -CFLAGS += -DMINIUPNPC_GET_SRC_ADDR -CFLAGS += -D_BSD_SOURCE -D_POSIX_C_SOURCE=1 -CFLAGS += -ansi -# -DNO_GETADDRINFO -INSTALL = install -SH = /bin/sh -JAVA = java -# see http://code.google.com/p/jnaerator/ -#JNAERATOR = jnaerator-0.9.7.jar -#JNAERATOR = jnaerator-0.9.8-shaded.jar -#JNAERATORARGS = -library miniupnpc -#JNAERATOR = jnaerator-0.10-shaded.jar -JNAERATOR = jnaerator-0.11-shaded.jar -JNAERATORARGS = -mode StandaloneJar -runtime JNAerator -library miniupnpc -JNAERATORBASEURL = http://jnaerator.googlecode.com/files/ - -ifeq (SunOS, $(OS)) - LDFLAGS=-lsocket -lnsl -lresolv -endif - -# APIVERSION is used to build SONAME -APIVERSION = 10 - -SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ - upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ - minixmlvalid.c testupnpreplyparse.c minissdpc.c \ - upnperrors.c testigddescparse.c testminiwget.c \ - connecthostport.c portlistingparse.c receivedata.c - -LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \ - miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ - connecthostport.o portlistingparse.o receivedata.o - -ifneq ($(OS), AmigaOS) -CFLAGS := -fPIC $(CFLAGS) -LIBOBJS := $(LIBOBJS) minissdpc.o -endif - -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -# HEADERS to install -HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \ - upnpreplyparse.h upnperrors.h miniupnpctypes.h \ - portlistingparse.h \ - declspec.h - -# library names -LIBRARY = libminiupnpc.a -ifeq ($(OS), Darwin) - SHAREDLIBRARY = libminiupnpc.dylib - SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib - CFLAGS := -DMACOSX -D_DARWIN_C_SOURCE $(CFLAGS) -else -ifeq ($(JARSUFFIX), win32) - SHAREDLIBRARY = miniupnpc.dll -else - # Linux/BSD/etc. - SHAREDLIBRARY = libminiupnpc.so - SONAME = $(SHAREDLIBRARY).$(APIVERSION) -endif -endif - -EXECUTABLES = upnpc-static -EXECUTABLES_ADDTESTS = testminixml minixmlvalid testupnpreplyparse \ - testigddescparse testminiwget - -TESTMINIXMLOBJS = minixml.o igd_desc_parse.o testminixml.o - -TESTMINIWGETOBJS = miniwget.o testminiwget.o connecthostport.o receivedata.o - -TESTUPNPREPLYPARSE = testupnpreplyparse.o minixml.o upnpreplyparse.o - -TESTIGDDESCPARSE = testigddescparse.o igd_desc_parse.o minixml.o \ - miniupnpc.o miniwget.o upnpcommands.o upnpreplyparse.o \ - minisoap.o connecthostport.o receivedata.o \ - portlistingparse.o - -ifneq ($(OS), AmigaOS) -EXECUTABLES := $(EXECUTABLES) upnpc-shared -TESTMINIWGETOBJS := $(TESTMINIWGETOBJS) minissdpc.o -TESTIGDDESCPARSE := $(TESTIGDDESCPARSE) minissdpc.o -endif - -LIBDIR ?= lib -# install directories -INSTALLPREFIX ?= $(PREFIX)/usr -INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc -INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR) -INSTALLDIRBIN = $(INSTALLPREFIX)/bin -INSTALLDIRMAN = $(INSTALLPREFIX)/share/man - -FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES) -ifneq ($(OS), AmigaOS) -FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY) -endif - - -.PHONY: install clean depend all check test everything \ - installpythonmodule updateversion -# validateminixml validateminiwget - -all: $(LIBRARY) $(EXECUTABLES) - -test: check - -check: validateminixml validateminiwget validateupnpreplyparse - -everything: all $(EXECUTABLES_ADDTESTS) - -pythonmodule: $(LIBRARY) miniupnpcmodule.c setup.py - python setup.py build - touch $@ - -installpythonmodule: pythonmodule - python setup.py install - -pythonmodule3: $(LIBRARY) miniupnpcmodule.c setup.py - python3 setup.py build - touch $@ - -installpythonmodule3: pythonmodule3 - python3 setup.py install - -validateminixml: minixmlvalid - @echo "minixml validation test" - ./minixmlvalid - touch $@ - -validateminiwget: testminiwget minihttptestserver testminiwget.sh - @echo "miniwget validation test" - ./testminiwget.sh - touch $@ - -validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh - @echo "upnpreplyparse validation test" - ./testupnpreplyparse.sh - touch $@ - -clean: - $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h - # clean python stuff - $(RM) pythonmodule pythonmodule3 - $(RM) validateminixml validateminiwget validateupnpreplyparse - $(RM) -r build/ dist/ - #python setup.py clean - # clean jnaerator stuff - $(RM) _jnaerator.* java/miniupnpc_$(OS).jar - -distclean: clean - $(RM) $(JNAERATOR) java/*.jar java/*.class out.errors.txt - -updateversion: miniupnpc.h - cp miniupnpc.h miniupnpc.h.bak - sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h - -install: updateversion $(FILESTOINSTALL) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB) - $(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB) -ifneq ($(OS), AmigaOS) - $(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME) - ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) -endif - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN) -ifeq ($(OS), AmigaOS) - $(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc -else - $(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc -endif - $(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip -ifneq ($(OS), AmigaOS) - $(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3 - $(INSTALL) man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 -ifeq ($(OS), Linux) - gzip $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3 -endif -endif - - -cleaninstall: - $(RM) -r $(DESTDIR)$(INSTALLDIRINC) - $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY) - $(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY) - -depend: - makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null - -$(LIBRARY): $(LIBOBJS) - $(AR) crs $@ $? - -$(SHAREDLIBRARY): $(LIBOBJS) -ifeq ($(OS), Darwin) -# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^ - $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^ -else - $(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^ -endif - -upnpc-static: upnpc.o $(LIBRARY) - $(CC) $(LDFLAGS) -o $@ $^ - -upnpc-shared: upnpc.o $(SHAREDLIBRARY) - $(CC) $(LDFLAGS) -o $@ $^ - -testminixml: $(TESTMINIXMLOBJS) - -testminiwget: $(TESTMINIWGETOBJS) - -minixmlvalid: minixml.o minixmlvalid.o - -testupnpreplyparse: $(TESTUPNPREPLYPARSE) - -testigddescparse: $(TESTIGDDESCPARSE) - -miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION - $(SH) updateminiupnpcstrings.sh - -# ftp tool supplied with OpenBSD can download files from http. -jnaerator-%.jar: - wget $(JNAERATORBASEURL)/$@ || \ - curl -o $@ $(JNAERATORBASEURL)/$@ || \ - ftp $(JNAERATORBASEURL)/$@ - -jar: $(SHAREDLIBRARY) $(JNAERATOR) - $(JAVA) -jar $(JNAERATOR) $(JNAERATORARGS) \ - miniupnpc.h declspec.h upnpcommands.h upnpreplyparse.h \ - igd_desc_parse.h miniwget.h upnperrors.h $(SHAREDLIBRARY) \ - -package fr.free.miniupnp -o . -jar java/miniupnpc_$(JARSUFFIX).jar -v - -mvn_install: - mvn install:install-file -Dfile=java/miniupnpc_$(JARSUFFIX).jar \ - -DgroupId=com.github \ - -DartifactId=miniupnp \ - -Dversion=$(VERSION) \ - -Dpackaging=jar \ - -Dclassifier=$(JARSUFFIX) \ - -DgeneratePom=true \ - -DcreateChecksum=true - -# make .deb packages -deb: /usr/share/pyshared/stdeb all - (python setup.py --command-packages=stdeb.command bdist_deb) - -# install .deb packages -ideb: - (sudo dpkg -i deb_dist/*.deb) - -/usr/share/pyshared/stdeb: /usr/share/doc/python-all-dev - (sudo apt-get install python-stdeb) - -/usr/share/doc/python-all-dev: - (sudo apt-get install python-all-dev) - -minihttptestserver: minihttptestserver.o - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -igd_desc_parse.o: igd_desc_parse.h -miniupnpc.o: miniupnpc.h declspec.h igd_desc_parse.h minissdpc.h miniwget.h -miniupnpc.o: minisoap.h minixml.h upnpcommands.h upnpreplyparse.h -miniupnpc.o: portlistingparse.h miniupnpctypes.h connecthostport.h -miniupnpc.o: receivedata.h -minixml.o: minixml.h -minisoap.o: minisoap.h miniupnpcstrings.h -miniwget.o: miniupnpcstrings.h miniwget.h declspec.h connecthostport.h -miniwget.o: receivedata.h -upnpc.o: miniwget.h declspec.h miniupnpc.h igd_desc_parse.h upnpcommands.h -upnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h upnperrors.h -upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h declspec.h -upnpcommands.o: miniupnpctypes.h miniupnpc.h igd_desc_parse.h -upnpreplyparse.o: upnpreplyparse.h minixml.h -testminixml.o: minixml.h igd_desc_parse.h -minixmlvalid.o: minixml.h -testupnpreplyparse.o: upnpreplyparse.h -minissdpc.o: minissdpc.h miniupnpc.h declspec.h igd_desc_parse.h codelength.h -upnperrors.o: upnperrors.h declspec.h upnpcommands.h upnpreplyparse.h -upnperrors.o: portlistingparse.h miniupnpctypes.h miniupnpc.h -upnperrors.o: igd_desc_parse.h -testigddescparse.o: igd_desc_parse.h minixml.h miniupnpc.h declspec.h -testminiwget.o: miniwget.h declspec.h -connecthostport.o: connecthostport.h -receivedata.o: receivedata.h diff --git a/src/contrib/miniupnpc/Makefile.mingw b/src/contrib/miniupnpc/Makefile.mingw deleted file mode 100644 index 60b3f1b..0000000 --- a/src/contrib/miniupnpc/Makefile.mingw +++ /dev/null @@ -1,91 +0,0 @@ -# $Id: Makefile.mingw,v 1.18 2014/01/17 09:04:01 nanard Exp $ -# Miniupnp project. -# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# (c) 2005-2014 Thomas Bernard -# This Makefile is made for MinGW -# -CC = gcc -#CFLAGS = -Wall -g -DDEBUG -D_WIN32_WINNT=0X501 -CFLAGS = -Wall -Os -DNDEBUG -D_WIN32_WINNT=0X501 -LDLIBS = -lws2_32 -liphlpapi -# -lwsock32 -# -liphlpapi is needed for GetBestRoute() and GetIpAddrTable() -PYTHON=\utils\python25\python -OBJS=miniwget.o minixml.o igd_desc_parse.o minisoap.o \ - miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \ - connecthostport.o portlistingparse.o receivedata.o -OBJSDLL=$(addprefix dll/, $(OBJS)) - -all: init upnpc-static upnpc-shared testminixml libminiupnpc.a miniupnpc.dll - -init: - mkdir dll - echo init > init - -clean: - del upnpc testminixml *.o - del dll\*.o - del *.exe - del miniupnpc.dll - del libminiupnpc.a - -libminiupnpc.a: $(OBJS) - $(AR) cr $@ $? - -pythonmodule: libminiupnpc.a - $(PYTHON) setupmingw32.py build --compiler=mingw32 - $(PYTHON) setupmingw32.py install --skip-build - -miniupnpc.dll: libminiupnpc.a $(OBJSDLL) - dllwrap -k --driver-name gcc \ - --def miniupnpc.def \ - --output-def miniupnpc.dll.def \ - --implib miniupnpc.lib -o $@ \ - $(OBJSDLL) $(LDLIBS) - -miniupnpc.lib: miniupnpc.dll - echo $@ generated with $< - -dll/upnpc.o: upnpc.o - echo $@ generated with $< - -.c.o: - $(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $< - $(CC) $(CFLAGS) -DMINIUPNP_EXPORTS -c -o dll/$@ $< - -upnpc.o: - $(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $< - $(CC) $(CFLAGS) -c -o dll/$@ $< - -# --enable-stdcall-fixup -upnpc-static: upnpc.o libminiupnpc.a - $(CC) -o $@ $^ $(LDLIBS) - -upnpc-shared: dll/upnpc.o miniupnpc.lib - $(CC) -o $@ $^ $(LDLIBS) - -wingenminiupnpcstrings: wingenminiupnpcstrings.o - -wingenminiupnpcstrings.o: wingenminiupnpcstrings.c - -miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings - wingenminiupnpcstrings $< $@ - -minixml.o: minixml.c minixml.h miniupnpcstrings.h - -upnpc.o: upnpc.c miniwget.h minisoap.h miniupnpc.h igd_desc_parse.h upnpreplyparse.h upnpcommands.h upnperrors.h - -miniwget.o: miniwget.c miniwget.h miniupnpcstrings.h connecthostport.h - -minisoap.o: minisoap.c minisoap.h miniupnpcstrings.h - -miniupnpc.o: miniupnpc.c miniupnpc.h minisoap.h miniwget.h minixml.h - -igd_desc_parse.o: igd_desc_parse.c igd_desc_parse.h - -testminixml: minixml.o igd_desc_parse.o testminixml.c - -upnpreplyparse.o: upnpreplyparse.c upnpreplyparse.h minixml.h - -upnpcommands.o: upnpcommands.c upnpcommands.h upnpreplyparse.h miniupnpc.h portlistingparse.h - diff --git a/src/contrib/miniupnpc/README b/src/contrib/miniupnpc/README deleted file mode 100644 index b23478d..0000000 --- a/src/contrib/miniupnpc/README +++ /dev/null @@ -1,66 +0,0 @@ -Project: miniupnp -Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -github: https://github.com/miniupnp/miniupnp -freecode: http://freecode.com/projects/miniupnp -Author: Thomas Bernard -Copyright (c) 2005-2012 Thomas Bernard -This software is subject to the conditions detailed in the -LICENSE file provided within this distribution. - - -For the comfort of Win32 users, bsdqueue.h is included in the distribution. -Its licence is included in the header of the file. -bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system. - - -* miniUPnP Client - miniUPnPc * - -To compile, simply run 'gmake' (could be 'make' on your system). -Under win32, to compile with MinGW, type "mingw32make.bat". -MS Visual C solution and project files are supplied in the msvc/ subdirectory. - -The compilation is known to work under linux, FreeBSD, -OpenBSD, MacOS X, AmigaOS and cygwin. -The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3. -upx (http://upx.sourceforge.net) is used to compress the win32 .exe files. - -To install the library and headers on the system use : -> su -> make install -> exit - -alternatively, to install into a specific location, use : -> INSTALLPREFIX=/usr/local make install - -upnpc.c is a sample client using the libminiupnpc. -To use the libminiupnpc in your application, link it with -libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h, -upnpcommands.h and miniwget.h : -- upnpDiscover() -- miniwget() -- parserootdesc() -- GetUPNPUrls() -- UPNP_* (calling UPNP methods) - -Note : use #include etc... for the includes -and -lminiupnpc for the link - -Discovery process is speeded up when MiniSSDPd is running on the machine. - - -* Python module * - -you can build a python module with 'make pythonmodule' -and install it with 'make installpythonmodule'. -setup.py (and setupmingw32.py) are included in the distribution. - - -Feel free to contact me if you have any problem : -e-mail : miniupnp@free.fr - -If you are using libminiupnpc in your application, please -send me an email ! - -For any question, you can use the web forum : -http://miniupnp.tuxfamily.org/forum/ - diff --git a/src/contrib/miniupnpc/VERSION b/src/contrib/miniupnpc/VERSION deleted file mode 100644 index 2e0e38c..0000000 --- a/src/contrib/miniupnpc/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.9 diff --git a/src/contrib/miniupnpc/apiversions.txt b/src/contrib/miniupnpc/apiversions.txt deleted file mode 100644 index 69f61c7..0000000 --- a/src/contrib/miniupnpc/apiversions.txt +++ /dev/null @@ -1,127 +0,0 @@ -$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $ - -Differences in API between miniUPnPc versions - -====================== miniUPnPc version 1.9 ====================== -API version 10 - -upnpcommands.h: - added argument remoteHost to UPNP_GetSpecificPortMappingEntry() - -miniupnpc.h: - updated macros : - #define MINIUPNPC_VERSION "1.9" - #define MINIUPNPC_API_VERSION 10 - -====================== miniUPnPc version 1.8 ====================== -API version 9 - -miniupnpc.h: - updated macros : - #define MINIUPNPC_VERSION "1.8" - #define MINIUPNPC_API_VERSION 9 - added "unsigned int scope_id;" to struct UPNPDev - added scope_id argument to GetUPNPUrls() - - - -====================== miniUPnPc version 1.7 ====================== -API version 8 - -miniupnpc.h : - add new macros : - #define MINIUPNPC_VERSION "1.7" - #define MINIUPNPC_API_VERSION 8 - add rootdescURL to struct UPNPUrls - - - -====================== miniUPnPc version 1.6 ====================== -API version 8 - -Adding support for IPv6. -igd_desc_parse.h : - struct IGDdatas_service : - add char presentationurl[MINIUPNPC_URL_MAXSIZE]; - struct IGDdatas : - add struct IGDdatas_service IPv6FC; -miniupnpc.h : - new macros : - #define UPNPDISCOVER_SUCCESS (0) - #define UPNPDISCOVER_UNKNOWN_ERROR (-1) - #define UPNPDISCOVER_SOCKET_ERROR (-101) - #define UPNPDISCOVER_MEMORY_ERROR (-102) - simpleUPnPcommand() prototype changed (but is normaly not used by API users) - add arguments ipv6 and error to upnpDiscover() : - struct UPNPDev * - upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); - add controlURL_6FC member to struct UPNPUrls : - struct UPNPUrls { - char * controlURL; - char * ipcondescURL; - char * controlURL_CIF; - char * controlURL_6FC; - }; - -upnpcommands.h : - add leaseDuration argument to UPNP_AddPortMapping() - add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry() - add UPNP_GetListOfPortMappings() function (IGDv2) - add IGDv2 IPv6 related functions : - UPNP_GetFirewallStatus() - UPNP_GetOutboundPinholeTimeout() - UPNP_AddPinhole() - UPNP_UpdatePinhole() - UPNP_DeletePinhole() - UPNP_CheckPinholeWorking() - UPNP_GetPinholePackets() - - - -====================== miniUPnPc version 1.5 ====================== -API version 5 - -new function : -int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); -new macro in upnpcommands.h : -#define UPNPCOMMAND_HTTP_ERROR - -====================== miniUPnPc version 1.4 ====================== -Same API as version 1.3 - -====================== miniUPnPc version 1.3 ====================== -API version 4 - -Use UNSIGNED_INTEGER type for -UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(), -UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived() -Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping() - -====================== miniUPnPc version 1.2 ====================== -API version 3 - -added sameport argument to upnpDiscover() -struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport); - -====================== miniUPnPc Version 1.1 ====================== -Same API as 1.0 - - -====================== miniUPnPc Version 1.0 ====================== -API version 2 - - -struct UPNPDev { - struct UPNPDev * pNext; - char * descURL; - char * st; - char buffer[2]; -}; -struct UPNPDev * upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock); - diff --git a/src/contrib/miniupnpc/bsdqueue.h b/src/contrib/miniupnpc/bsdqueue.h deleted file mode 100644 index c6afe1f..0000000 --- a/src/contrib/miniupnpc/bsdqueue.h +++ /dev/null @@ -1,531 +0,0 @@ -/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#ifdef QUEUE_MACRO_DEBUG -#define _Q_INVALIDATE(a) (a) = ((void *)-1) -#else -#define _Q_INVALIDATE(a) -#endif - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#ifdef SLIST_ENTRY -#undef SLIST_ENTRY -#endif - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != SLIST_END(head); \ - (varp) = &SLIST_NEXT((var), field)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_NEXT(head, elm, field) do { \ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->slh_first; \ - \ - while (curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ - } \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head).cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head).cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/src/contrib/miniupnpc/codelength.h b/src/contrib/miniupnpc/codelength.h deleted file mode 100644 index d342bd1..0000000 --- a/src/contrib/miniupnpc/codelength.h +++ /dev/null @@ -1,31 +0,0 @@ -/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2005-2011 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef CODELENGTH_H_INCLUDED -#define CODELENGTH_H_INCLUDED - -/* Encode length by using 7bit per Byte : - * Most significant bit of each byte specifies that the - * following byte is part of the code */ -#define DECODELENGTH(n, p) n = 0; \ - do { n = (n << 7) | (*p & 0x7f); } \ - while((*(p++)&0x80) && (n<(1<<25))); - -#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ - n = 0; \ - do { \ - if((p) >= (p_limit)) break; \ - n = (n << 7) | (*(p) & 0x7f); \ - } while((*((p)++)&0x80) && (n<(1<<25))); - -#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ - if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ - if(n>=16384) *(p++) = (n >> 14) | 0x80; \ - if(n>=128) *(p++) = (n >> 7) | 0x80; \ - *(p++) = n & 0x7f; - -#endif - diff --git a/src/contrib/miniupnpc/connecthostport.c b/src/contrib/miniupnpc/connecthostport.c deleted file mode 100644 index d66ae31..0000000 --- a/src/contrib/miniupnpc/connecthostport.c +++ /dev/null @@ -1,261 +0,0 @@ -/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2010-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -/* use getaddrinfo() or gethostbyname() - * uncomment the following line in order to use gethostbyname() */ -#ifdef NO_GETADDRINFO -#define USE_GETHOSTBYNAME -#endif - -#include -#include -#ifdef _WIN32 -#include -#include -#include -#define MAXHOSTNAMELEN 64 -#define snprintf _snprintf -#define herror -#define socklen_t int -#else /* #ifdef _WIN32 */ -#include -#include -#include -#include -#define closesocket close -#include -#include -/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions - * during the connect() call */ -#define MINIUPNPC_IGNORE_EINTR -#ifndef USE_GETHOSTBYNAME -#include -#include -#include -#endif /* #ifndef USE_GETHOSTBYNAME */ -#endif /* #else _WIN32 */ - -/* definition of PRINT_SOCKET_ERROR */ -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -#if defined(__amigaos__) || defined(__amigaos4__) -#define herror(A) printf("%s\n", A) -#endif - -#include "connecthostport.h" - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* connecthostport() - * return a socket connected (TCP) to the host and port - * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port, - unsigned int scope_id) -{ - int s, n; -#ifdef USE_GETHOSTBYNAME - struct sockaddr_in dest; - struct hostent *hp; -#else /* #ifdef USE_GETHOSTBYNAME */ - char tmp_host[MAXHOSTNAMELEN+1]; - char port_str[8]; - struct addrinfo *ai, *p; - struct addrinfo hints; -#endif /* #ifdef USE_GETHOSTBYNAME */ -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - struct timeval timeout; -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - -#ifdef USE_GETHOSTBYNAME - hp = gethostbyname(host); - if(hp == NULL) - { - herror(host); - return -1; - } - memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr)); - memset(dest.sin_zero, 0, sizeof(dest.sin_zero)); - s = socket(PF_INET, SOCK_STREAM, 0); - if(s < 0) - { - PRINT_SOCKET_ERROR("socket"); - return -1; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); -#ifdef MINIUPNPC_IGNORE_EINTR - /* EINTR The system call was interrupted by a signal that was caught - * EINPROGRESS The socket is nonblocking and the connection cannot - * be completed immediately. */ - while(n < 0 && (errno == EINTR || errno = EINPROGRESS)) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - return -1; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ - if(n<0) - { - PRINT_SOCKET_ERROR("connect"); - closesocket(s); - return -1; - } -#else /* #ifdef USE_GETHOSTBYNAME */ - /* use getaddrinfo() instead of gethostbyname() */ - memset(&hints, 0, sizeof(hints)); - /* hints.ai_flags = AI_ADDRCONFIG; */ -#ifdef AI_NUMERICSERV - hints.ai_flags = AI_NUMERICSERV; -#endif - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */ - /* hints.ai_protocol = IPPROTO_TCP; */ - snprintf(port_str, sizeof(port_str), "%hu", port); - if(host[0] == '[') - { - /* literal ip v6 address */ - int i, j; - for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) - { - tmp_host[i] = host[j]; - if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ - j+=2; /* skip "25" */ - } - tmp_host[i] = '\0'; - } - else - { - strncpy(tmp_host, host, MAXHOSTNAMELEN); - } - tmp_host[MAXHOSTNAMELEN] = '\0'; - n = getaddrinfo(tmp_host, port_str, &hints, &ai); - if(n != 0) - { -#ifdef _WIN32 - fprintf(stderr, "getaddrinfo() error : %d\n", n); -#else - fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n)); -#endif - return -1; - } - s = -1; - for(p = ai; p; p = p->ai_next) - { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if(s < 0) - continue; - if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { - struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; - addr6->sin6_scope_id = scope_id; - } -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT - /* setting a 3 seconds timeout for the connect() call */ - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - timeout.tv_sec = 3; - timeout.tv_usec = 0; - if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ - n = connect(s, p->ai_addr, p->ai_addrlen); -#ifdef MINIUPNPC_IGNORE_EINTR - /* EINTR The system call was interrupted by a signal that was caught - * EINPROGRESS The socket is nonblocking and the connection cannot - * be completed immediately. */ - while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) - { - socklen_t len; - fd_set wset; - int err; - FD_ZERO(&wset); - FD_SET(s, &wset); - if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR) - continue; - /*len = 0;*/ - /*n = getpeername(s, NULL, &len);*/ - len = sizeof(err); - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) { - PRINT_SOCKET_ERROR("getsockopt"); - closesocket(s); - freeaddrinfo(ai); - return -1; - } - if(err != 0) { - errno = err; - n = -1; - } - } -#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */ - if(n < 0) - { - closesocket(s); - continue; - } - else - { - break; - } - } - freeaddrinfo(ai); - if(s < 0) - { - PRINT_SOCKET_ERROR("socket"); - return -1; - } - if(n < 0) - { - PRINT_SOCKET_ERROR("connect"); - return -1; - } -#endif /* #ifdef USE_GETHOSTBYNAME */ - return s; -} - diff --git a/src/contrib/miniupnpc/connecthostport.h b/src/contrib/miniupnpc/connecthostport.h deleted file mode 100644 index 56941d6..0000000 --- a/src/contrib/miniupnpc/connecthostport.h +++ /dev/null @@ -1,18 +0,0 @@ -/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2010-2012 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef CONNECTHOSTPORT_H_INCLUDED -#define CONNECTHOSTPORT_H_INCLUDED - -/* connecthostport() - * return a socket connected (TCP) to the host and port - * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port, - unsigned int scope_id); - -#endif - diff --git a/src/contrib/miniupnpc/declspec.h b/src/contrib/miniupnpc/declspec.h deleted file mode 100644 index 7729969..0000000 --- a/src/contrib/miniupnpc/declspec.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef DECLSPEC_H_INCLUDED -#define DECLSPEC_H_INCLUDED - -#if defined(_WIN32) && !defined(STATICLIB) - /* for windows dll */ - #ifdef MINIUPNP_EXPORTS - #define LIBSPEC __declspec(dllexport) - #else - #define LIBSPEC __declspec(dllimport) - #endif -#else - #if defined(__GNUC__) && __GNUC__ >= 4 - /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ - #define LIBSPEC __attribute__ ((visibility ("default"))) - #else - #define LIBSPEC - #endif -#endif - -#endif - diff --git a/src/contrib/miniupnpc/external-ip.sh b/src/contrib/miniupnpc/external-ip.sh deleted file mode 100644 index 965d86b..0000000 --- a/src/contrib/miniupnpc/external-ip.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# $Id: external-ip.sh,v 1.1 2010/08/05 12:57:41 nanard Exp $ -# (c) 2010 Reuben Hawkins -upnpc -s | grep ExternalIPAddress | sed 's/[^0-9\.]//g' diff --git a/src/contrib/miniupnpc/igd_desc_parse.c b/src/contrib/miniupnpc/igd_desc_parse.c deleted file mode 100644 index 6c3e656..0000000 --- a/src/contrib/miniupnpc/igd_desc_parse.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $Id: igd_desc_parse.c,v 1.14 2011/04/11 09:19:24 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2010 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include "igd_desc_parse.h" -#include -#include - -/* Start element handler : - * update nesting level counter and copy element name */ -void IGDstartelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - memcpy( datas->cureltname, name, l); - datas->cureltname[l] = '\0'; - datas->level++; - if( (l==7) && !memcmp(name, "service", l) ) { - datas->tmp.controlurl[0] = '\0'; - datas->tmp.eventsuburl[0] = '\0'; - datas->tmp.scpdurl[0] = '\0'; - datas->tmp.servicetype[0] = '\0'; - } -} - -/* End element handler : - * update nesting level counter and update parser state if - * service element is parsed */ -void IGDendelt(void * d, const char * name, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - datas->level--; - /*printf("endelt %2d %.*s\n", datas->level, l, name);*/ - if( (l==7) && !memcmp(name, "service", l) ) - { - /* - if( datas->state < 1 - && !strcmp(datas->servicetype, - // "urn:schemas-upnp-org:service:WANIPConnection:1") ) - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) - datas->state ++; - */ - if(0==strcmp(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) { - memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(0==strcmp(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1")) { - memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service)); - } else if(0==strcmp(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANIPConnection:1") - || 0==strcmp(datas->tmp.servicetype, - "urn:schemas-upnp-org:service:WANPPPConnection:1") ) { - if(datas->first.servicetype[0] == '\0') { - memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service)); - } else { - memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service)); - } - } - } -} - -/* Data handler : - * copy data depending on the current element name and state */ -void IGDdata(void * d, const char * data, int l) -{ - struct IGDdatas * datas = (struct IGDdatas *)d; - char * dstmember = 0; - /*printf("%2d %s : %.*s\n", - datas->level, datas->cureltname, l, data); */ - if( !strcmp(datas->cureltname, "URLBase") ) - dstmember = datas->urlbase; - else if( !strcmp(datas->cureltname, "presentationURL") ) - dstmember = datas->presentationurl; - else if( !strcmp(datas->cureltname, "serviceType") ) - dstmember = datas->tmp.servicetype; - else if( !strcmp(datas->cureltname, "controlURL") ) - dstmember = datas->tmp.controlurl; - else if( !strcmp(datas->cureltname, "eventSubURL") ) - dstmember = datas->tmp.eventsuburl; - else if( !strcmp(datas->cureltname, "SCPDURL") ) - dstmember = datas->tmp.scpdurl; -/* else if( !strcmp(datas->cureltname, "deviceType") ) - dstmember = datas->devicetype_tmp;*/ - if(dstmember) - { - if(l>=MINIUPNPC_URL_MAXSIZE) - l = MINIUPNPC_URL_MAXSIZE-1; - memcpy(dstmember, data, l); - dstmember[l] = '\0'; - } -} - -void printIGD(struct IGDdatas * d) -{ - printf("urlbase = '%s'\n", d->urlbase); - printf("WAN Device (Common interface config) :\n"); - /*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/ - printf(" serviceType = '%s'\n", d->CIF.servicetype); - printf(" controlURL = '%s'\n", d->CIF.controlurl); - printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl); - printf(" SCPDURL = '%s'\n", d->CIF.scpdurl); - printf("primary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->first.devicetype);*/ - printf(" servicetype = '%s'\n", d->first.servicetype); - printf(" controlURL = '%s'\n", d->first.controlurl); - printf(" eventSubURL = '%s'\n", d->first.eventsuburl); - printf(" SCPDURL = '%s'\n", d->first.scpdurl); - printf("secondary WAN Connection Device (IP or PPP Connection):\n"); - /*printf(" deviceType = '%s'\n", d->second.devicetype);*/ - printf(" servicetype = '%s'\n", d->second.servicetype); - printf(" controlURL = '%s'\n", d->second.controlurl); - printf(" eventSubURL = '%s'\n", d->second.eventsuburl); - printf(" SCPDURL = '%s'\n", d->second.scpdurl); - printf("WAN IPv6 Firewall Control :\n"); - /*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/ - printf(" servicetype = '%s'\n", d->IPv6FC.servicetype); - printf(" controlURL = '%s'\n", d->IPv6FC.controlurl); - printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl); - printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl); -} - - diff --git a/src/contrib/miniupnpc/igd_desc_parse.h b/src/contrib/miniupnpc/igd_desc_parse.h deleted file mode 100644 index 0a49b01..0000000 --- a/src/contrib/miniupnpc/igd_desc_parse.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2010 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef IGD_DESC_PARSE_H_INCLUDED -#define IGD_DESC_PARSE_H_INCLUDED - -/* Structure to store the result of the parsing of UPnP - * descriptions of Internet Gateway Devices */ -#define MINIUPNPC_URL_MAXSIZE (128) -struct IGDdatas_service { - char controlurl[MINIUPNPC_URL_MAXSIZE]; - char eventsuburl[MINIUPNPC_URL_MAXSIZE]; - char scpdurl[MINIUPNPC_URL_MAXSIZE]; - char servicetype[MINIUPNPC_URL_MAXSIZE]; - /*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ -}; - -struct IGDdatas { - char cureltname[MINIUPNPC_URL_MAXSIZE]; - char urlbase[MINIUPNPC_URL_MAXSIZE]; - char presentationurl[MINIUPNPC_URL_MAXSIZE]; - int level; - /*int state;*/ - /* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ - struct IGDdatas_service CIF; - /* "urn:schemas-upnp-org:service:WANIPConnection:1" - * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ - struct IGDdatas_service first; - /* if both WANIPConnection and WANPPPConnection are present */ - struct IGDdatas_service second; - /* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ - struct IGDdatas_service IPv6FC; - /* tmp */ - struct IGDdatas_service tmp; -}; - -void IGDstartelt(void *, const char *, int); -void IGDendelt(void *, const char *, int); -void IGDdata(void *, const char *, int); -void printIGD(struct IGDdatas *); - -#endif - diff --git a/src/contrib/miniupnpc/java/JavaBridgeTest.java b/src/contrib/miniupnpc/java/JavaBridgeTest.java deleted file mode 100644 index a7fa56d..0000000 --- a/src/contrib/miniupnpc/java/JavaBridgeTest.java +++ /dev/null @@ -1,97 +0,0 @@ -import java.nio.ByteBuffer; -import java.nio.IntBuffer; - -import fr.free.miniupnp.*; - -/** - * - * @author syuu - */ -public class JavaBridgeTest { - public static void main(String[] args) { - int UPNP_DELAY = 2000; - MiniupnpcLibrary miniupnpc = MiniupnpcLibrary.INSTANCE; - UPNPDev devlist = null; - UPNPUrls urls = new UPNPUrls(); - IGDdatas data = new IGDdatas(); - ByteBuffer lanaddr = ByteBuffer.allocate(16); - ByteBuffer intClient = ByteBuffer.allocate(16); - ByteBuffer intPort = ByteBuffer.allocate(6); - ByteBuffer desc = ByteBuffer.allocate(80); - ByteBuffer enabled = ByteBuffer.allocate(4); - ByteBuffer leaseDuration = ByteBuffer.allocate(16); - int ret; - int i; - - if(args.length < 2) { - System.err.println("Usage : java [...] JavaBridgeTest port protocol"); - System.out.println(" port is numeric, protocol is TCP or UDP"); - return; - } - - devlist = miniupnpc.upnpDiscover(UPNP_DELAY, (String) null, (String) null, 0, 0, IntBuffer.allocate(1)); - if (devlist != null) { - System.out.println("List of UPNP devices found on the network :"); - for (UPNPDev device = devlist; device != null; device = device.pNext) { - System.out.println("desc: " + device.descURL.getString(0) + " st: " + device.st.getString(0)); - } - if ((i = miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16)) != 0) { - switch (i) { - case 1: - System.out.println("Found valid IGD : " + urls.controlURL.getString(0)); - break; - case 2: - System.out.println("Found a (not connected?) IGD : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - break; - case 3: - System.out.println("UPnP device found. Is it an IGD ? : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - break; - default: - System.out.println("Found device (igd ?) : " + urls.controlURL.getString(0)); - System.out.println("Trying to continue anyway"); - - } - System.out.println("Local LAN ip address : " + new String(lanaddr.array())); - ByteBuffer externalAddress = ByteBuffer.allocate(16); - miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0), - new String(data.first.servicetype), externalAddress); - System.out.println("ExternalIPAddress = " + new String(externalAddress.array())); - ret = miniupnpc.UPNP_AddPortMapping( - urls.controlURL.getString(0), // controlURL - new String(data.first.servicetype), // servicetype - args[0], // external Port - args[0], // internal Port - new String(lanaddr.array()), // internal client - "added via miniupnpc/JAVA !", // description - args[1], // protocol UDP or TCP - null, // remote host (useless) - "0"); // leaseDuration - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("AddPortMapping() failed with code " + ret); - ret = miniupnpc.UPNP_GetSpecificPortMappingEntry( - urls.controlURL.getString(0), new String(data.first.servicetype), - args[0], args[1], null, intClient, intPort, - desc, enabled, leaseDuration); - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("GetSpecificPortMappingEntry() failed with code " + ret); - System.out.println("InternalIP:Port = " + - new String(intClient.array()) + ":" + new String(intPort.array()) + - " (" + new String(desc.array()) + ")"); - ret = miniupnpc.UPNP_DeletePortMapping( - urls.controlURL.getString(0), - new String(data.first.servicetype), - args[0], args[1], null); - if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) - System.out.println("DelPortMapping() failed with code " + ret); - miniupnpc.FreeUPNPUrls(urls); - } else { - System.out.println("No valid UPNP Internet Gateway Device found."); - } - miniupnpc.freeUPNPDevlist(devlist); - } else { - System.out.println("No IGD UPnP Device found on the network !\n"); - } - } -} diff --git a/src/contrib/miniupnpc/java/testjava.bat b/src/contrib/miniupnpc/java/testjava.bat deleted file mode 100644 index b836da1..0000000 --- a/src/contrib/miniupnpc/java/testjava.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -set JAVA=java -set JAVAC=javac -REM notice the semicolon for Windows. Write once, run ... oh nevermind -set CP=miniupnpc_win32.jar;. - -%JAVAC% -cp "%CP%" JavaBridgeTest.java || exit 1 -%JAVA% -cp "%CP%" JavaBridgeTest 12345 UDP || exit 1 diff --git a/src/contrib/miniupnpc/java/testjava.sh b/src/contrib/miniupnpc/java/testjava.sh deleted file mode 100644 index 9880523..0000000 --- a/src/contrib/miniupnpc/java/testjava.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -JAVA=java -JAVAC=javac -CP=$(for i in *.jar; do echo -n $i:; done). - -$JAVAC -cp $CP JavaBridgeTest.java || exit 1 -$JAVA -cp $CP JavaBridgeTest 12345 UDP || exit 1 diff --git a/src/contrib/miniupnpc/man3/miniupnpc.3 b/src/contrib/miniupnpc/man3/miniupnpc.3 deleted file mode 100644 index 1b16647..0000000 --- a/src/contrib/miniupnpc/man3/miniupnpc.3 +++ /dev/null @@ -1,52 +0,0 @@ -.TH MINIUPNPC 3 -.SH NAME -miniupnpc \- UPnP client library -.SH SYNOPSIS -.SH DESCRIPTION -The miniupnpc library implement the UPnP protocol defined -to dialog with Internet Gateway Devices. It also has -the ability to use data gathered by minissdpd(1) about -UPnP devices up on the network in order to skip the -long UPnP device discovery process. -.PP -At first, upnpDiscover(3) has to be used to discover UPnP IGD present -on the network. Then UPNP_GetValidIGD(3) to select the right one. -Alternatively, UPNP_GetIGDFromUrl(3) could be used to bypass discovery -process if the root description url of the device to use is known. -Then all the UPNP_* functions can be used, such as -UPNP_GetConnectionTypeInfo(3), UPNP_AddPortMapping(3), etc... -.SH "HEADER FILES" -.IP miniupnpc.h -That's the main header file for the miniupnpc library API. -It contains all the functions and structures related to device discovery. -.IP upnpcommands.h -This header file contain the UPnP IGD methods that are accessible -through the miniupnpc API. The name of the C functions are matching -the UPnP methods names. ie: GetGenericPortMappingEntry is -UPNP_GetGenericPortMappingEntry. -.SH "API FUNCTIONS" -.IP "struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int sameport, int ipv6, int * error);" -execute the discovery process. -delay (in millisecond) is the maximum time for waiting any device response. -If available, device list will be obtained from MiniSSDPd. -Default path for minissdpd socket will be used if minissdpdsock argument is NULL. -If multicastif is not NULL, it will be used instead of the default multicast interface for sending SSDP discover packets. -If sameport is not null, SSDP packets will be sent from the source port 1900 (same as destination port) otherwise system assign a source port. -If ipv6 is not 0, IPv6 is used instead of IPv4 for the discovery process. -.IP "void freeUPNPDevlist(struct UPNPDev * devlist);" -free the list returned by upnpDiscover(). -.IP "int UPNP_GetValidIGD(struct UPNPDev * devlist, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" -browse the list of device returned by upnpDiscover(), find -a live UPnP internet gateway device and fill structures passed as arguments -with data used for UPNP methods invokation. -.IP "int UPNP_GetIGDFromUrl(const char * rootdescurl, struct UPNPUrls * urls, struct IGDdatas * data, char * lanaddr, int lanaddrlen);" -permit to bypass the upnpDiscover() call if the xml root description -URL of the UPnP IGD is known. -Fill structures passed as arguments -with data used for UPNP methods invokation. -.IP "void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);" -.IP "void FreeUPNPUrls(struct UPNPUrls *);" - -.SH "SEE ALSO" -minissdpd(1) -.SH BUGS diff --git a/src/contrib/miniupnpc/mingw32make.bat b/src/contrib/miniupnpc/mingw32make.bat deleted file mode 100644 index c5d3cc4..0000000 --- a/src/contrib/miniupnpc/mingw32make.bat +++ /dev/null @@ -1,8 +0,0 @@ -@mingw32-make -f Makefile.mingw %1 -@if errorlevel 1 goto end -@if not exist upnpc-static.exe goto end -@strip upnpc-static.exe -@upx --best upnpc-static.exe -@strip upnpc-shared.exe -@upx --best upnpc-shared.exe -:end diff --git a/src/contrib/miniupnpc/minihttptestserver.c b/src/contrib/miniupnpc/minihttptestserver.c deleted file mode 100644 index b719361..0000000 --- a/src/contrib/miniupnpc/minihttptestserver.c +++ /dev/null @@ -1,486 +0,0 @@ -/* $Id: minihttptestserver.c,v 1.13 2012/05/29 13:03:07 nanard Exp $ */ -/* Project : miniUPnP - * Author : Thomas Bernard - * Copyright (c) 2011-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CRAP_LENGTH (2048) - -volatile sig_atomic_t quit = 0; -volatile sig_atomic_t child_to_wait_for = 0; - -/** - * signal handler for SIGCHLD (child status has changed) - */ -void handle_signal_chld(int sig) -{ - printf("handle_signal_chld(%d)\n", sig); - ++child_to_wait_for; -} - -/** - * signal handler for SIGINT (CRTL C) - */ -#if 0 -void handle_signal_int(int sig) -{ - printf("handle_signal_int(%d)\n", sig); - quit = 1; -} -#endif - -/** - * build a text/plain content of the specified length - */ -void build_content(char * p, int n) -{ - char line_buffer[80]; - int k; - int i = 0; - - while(n > 0) { - k = snprintf(line_buffer, sizeof(line_buffer), - "%04d_ABCDEFGHIJKL_This_line_is_64_bytes_long_ABCDEFGHIJKL_%04d\r\n", - i, i); - if(k != 64) { - fprintf(stderr, "snprintf() returned %d in build_content()\n", k); - } - ++i; - if(n >= 64) { - memcpy(p, line_buffer, 64); - p += 64; - n -= 64; - } else { - memcpy(p, line_buffer, n); - p += n; - n = 0; - } - } -} - -/** - * build crappy content - */ -void build_crap(char * p, int n) -{ - static const char crap[] = "_CRAP_\r\n"; - int i; - - while(n > 0) { - i = sizeof(crap) - 1; - if(i > n) - i = n; - memcpy(p, crap, i); - p += i; - n -= i; - } -} - -/** - * build chunked response. - * return a malloc'ed buffer - */ -char * build_chunked_response(int content_length, int * response_len) { - char * response_buffer; - char * content_buffer; - int buffer_length; - int i, n; - - /* allocate to have some margin */ - buffer_length = 256 + content_length + (content_length >> 4); - response_buffer = malloc(buffer_length); - *response_len = snprintf(response_buffer, buffer_length, - "HTTP/1.1 200 OK\r\n" - "Content-Type: text/plain\r\n" - "Transfer-Encoding: chunked\r\n" - "\r\n"); - - /* build the content */ - content_buffer = malloc(content_length); - build_content(content_buffer, content_length); - - /* chunk it */ - i = 0; - while(i < content_length) { - n = (rand() % 199) + 1; - if(i + n > content_length) { - n = content_length - i; - } - /* TODO : check buffer size ! */ - *response_len += snprintf(response_buffer + *response_len, - buffer_length - *response_len, - "%x\r\n", n); - memcpy(response_buffer + *response_len, content_buffer + i, n); - *response_len += n; - i += n; - response_buffer[(*response_len)++] = '\r'; - response_buffer[(*response_len)++] = '\n'; - } - /* the last chunk : "0\r\n" a empty body and then - * the final "\r\n" */ - memcpy(response_buffer + *response_len, "0\r\n\r\n", 5); - *response_len += 5; - free(content_buffer); - - printf("resp_length=%d buffer_length=%d content_length=%d\n", - *response_len, buffer_length, content_length); - return response_buffer; -} - -enum modes { MODE_INVALID, MODE_CHUNKED, MODE_ADDCRAP, MODE_NORMAL }; -const struct { - const enum modes mode; - const char * text; -} modes_array[] = { - {MODE_CHUNKED, "chunked"}, - {MODE_ADDCRAP, "addcrap"}, - {MODE_NORMAL, "normal"}, - {MODE_INVALID, NULL} -}; - -/** - * write the response with random behaviour ! - */ -void send_response(int c, const char * buffer, int len) -{ - int n; - while(len > 0) { - n = (rand() % 99) + 1; - if(n > len) - n = len; - n = write(c, buffer, n); - if(n < 0) { - if(errno != EINTR) { - perror("write"); - return; - } - /* if errno == EINTR, try again */ - } else { - len -= n; - buffer += n; - } - usleep(10000); /* 10ms */ - } -} - -/** - * handle the HTTP connection - */ -void handle_http_connection(int c) -{ - char request_buffer[2048]; - int request_len = 0; - int headers_found = 0; - int n, i; - char request_method[16]; - char request_uri[256]; - char http_version[16]; - char * p; - char * response_buffer; - int response_len; - enum modes mode; - int content_length = 16*1024; - - /* read the request */ - while(request_len < (int)sizeof(request_buffer) && !headers_found) { - n = read(c, - request_buffer + request_len, - sizeof(request_buffer) - request_len); - if(n < 0) { - perror("read"); - return; - } else if(n==0) { - /* remote host closed the connection */ - break; - } else { - request_len += n; - for(i = 0; i < request_len - 3; i++) { - if(0 == memcmp(request_buffer + i, "\r\n\r\n", 4)) { - /* found the end of headers */ - headers_found = 1; - break; - } - } - } - } - if(!headers_found) { - /* error */ - return; - } - printf("headers :\n%.*s", request_len, request_buffer); - /* the request have been received, now parse the request line */ - p = request_buffer; - for(i = 0; i < (int)sizeof(request_method) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - request_method[i] = *p; - ++p; - } - request_method[i] = '\0'; - while(*p == ' ') - p++; - for(i = 0; i < (int)sizeof(request_uri) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - request_uri[i] = *p; - ++p; - } - request_uri[i] = '\0'; - while(*p == ' ') - p++; - for(i = 0; i < (int)sizeof(http_version) - 1; i++) { - if(*p == ' ' || *p == '\r') - break; - http_version[i] = *p; - ++p; - } - http_version[i] = '\0'; - printf("Method = %s, URI = %s, %s\n", - request_method, request_uri, http_version); - /* check if the request method is allowed */ - if(0 != strcmp(request_method, "GET")) { - const char response405[] = "HTTP/1.1 405 Method Not Allowed\r\n" - "Allow: GET\r\n\r\n"; - const char * pc; - /* 405 Method Not Allowed */ - /* The response MUST include an Allow header containing a list - * of valid methods for the requested resource. */ - n = sizeof(response405) - 1; - pc = response405; - while(n > 0) { - i = write(c, pc, n); - if(i<0) { - if(errno != EINTR) { - perror("write"); - return; - } - } else { - n -= i; - pc += i; - } - } - return; - } - - mode = MODE_INVALID; - /* use the request URI to know what to do */ - for(i = 0; modes_array[i].mode != MODE_INVALID; i++) { - if(strstr(request_uri, modes_array[i].text)) { - mode = modes_array[i].mode; /* found */ - break; - } - } - - switch(mode) { - case MODE_CHUNKED: - response_buffer = build_chunked_response(content_length, &response_len); - break; - case MODE_ADDCRAP: - response_len = content_length+256; - response_buffer = malloc(response_len); - n = snprintf(response_buffer, response_len, - "HTTP/1.1 200 OK\r\n" - "Server: minihttptestserver\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: %d\r\n" - "\r\n", content_length); - response_len = content_length+n+CRAP_LENGTH; - response_buffer = realloc(response_buffer, response_len); - build_content(response_buffer + n, content_length); - build_crap(response_buffer + n + content_length, CRAP_LENGTH); - break; - default: - response_len = content_length+256; - response_buffer = malloc(response_len); - n = snprintf(response_buffer, response_len, - "HTTP/1.1 200 OK\r\n" - "Server: minihttptestserver\r\n" - "Content-Type: text/plain\r\n" - "\r\n"); - response_len = content_length+n; - response_buffer = realloc(response_buffer, response_len); - build_content(response_buffer + n, response_len - n); - } - - if(response_buffer) { - send_response(c, response_buffer, response_len); - free(response_buffer); - } else { - /* Error 500 */ - } -} - -/** - */ -int main(int argc, char * * argv) { - int ipv6 = 0; - int s, c, i; - unsigned short port = 0; - struct sockaddr_storage server_addr; - socklen_t server_addrlen; - struct sockaddr_storage client_addr; - socklen_t client_addrlen; - pid_t pid; - int child = 0; - int status; - const char * expected_file_name = NULL; - - for(i = 1; i < argc; i++) { - if(argv[i][0] == '-') { - switch(argv[i][1]) { - case '6': - ipv6 = 1; - break; - case 'e': - /* write expected file ! */ - expected_file_name = argv[++i]; - break; - case 'p': - /* port */ - if(++i < argc) { - port = (unsigned short)atoi(argv[i]); - } - break; - default: - fprintf(stderr, "unknown command line switch '%s'\n", argv[i]); - } - } else { - fprintf(stderr, "unkown command line argument '%s'\n", argv[i]); - } - } - - srand(time(NULL)); - signal(SIGCHLD, handle_signal_chld); -#if 0 - signal(SIGINT, handle_signal_int); -#endif - - s = socket(ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0); - if(s < 0) { - perror("socket"); - return 1; - } - memset(&server_addr, 0, sizeof(struct sockaddr_storage)); - memset(&client_addr, 0, sizeof(struct sockaddr_storage)); - if(ipv6) { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; - addr->sin6_family = AF_INET6; - addr->sin6_port = htons(port); - addr->sin6_addr = in6addr_loopback; - } else { - struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; - addr->sin_family = AF_INET; - addr->sin_port = htons(port); - addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - if(bind(s, (struct sockaddr *)&server_addr, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) < 0) { - perror("bind"); - return 1; - } - if(listen(s, 5) < 0) { - perror("listen"); - } - if(port == 0) { - server_addrlen = sizeof(struct sockaddr_storage); - if(getsockname(s, (struct sockaddr *)&server_addr, &server_addrlen) < 0) { - perror("getsockname"); - return 1; - } - if(ipv6) { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&server_addr; - port = ntohs(addr->sin6_port); - } else { - struct sockaddr_in * addr = (struct sockaddr_in *)&server_addr; - port = ntohs(addr->sin_port); - } - printf("Listening on port %hu\n", port); - fflush(stdout); - } - - /* write expected file */ - if(expected_file_name) { - FILE * f; - f = fopen(expected_file_name, "wb"); - if(f) { - char * buffer; - buffer = malloc(16*1024); - build_content(buffer, 16*1024); - i = fwrite(buffer, 1, 16*1024, f); - if(i != 16*1024) { - fprintf(stderr, "error writing to file %s : %dbytes written (out of %d)\n", expected_file_name, i, 16*1024); - } - free(buffer); - fclose(f); - } else { - fprintf(stderr, "error opening file %s for writing\n", expected_file_name); - } - } - - /* fork() loop */ - while(!child && !quit) { - while(child_to_wait_for > 0) { - pid = wait(&status); - if(pid < 0) { - perror("wait"); - } else { - printf("child(%d) terminated with status %d\n", pid, status); - } - --child_to_wait_for; - } - /* TODO : add a select() call in order to handle the case - * when a signal is caught */ - client_addrlen = sizeof(struct sockaddr_storage); - c = accept(s, (struct sockaddr *)&client_addr, - &client_addrlen); - if(c < 0) { - perror("accept"); - return 1; - } - printf("accept...\n"); - pid = fork(); - if(pid < 0) { - perror("fork"); - return 1; - } else if(pid == 0) { - /* child */ - child = 1; - close(s); - s = -1; - handle_http_connection(c); - } - close(c); - } - if(s >= 0) { - close(s); - s = -1; - } - if(!child) { - while(child_to_wait_for > 0) { - pid = wait(&status); - if(pid < 0) { - perror("wait"); - } else { - printf("child(%d) terminated with status %d\n", pid, status); - } - --child_to_wait_for; - } - printf("Bye...\n"); - } - return 0; -} - diff --git a/src/contrib/miniupnpc/minisoap.c b/src/contrib/miniupnpc/minisoap.c deleted file mode 100644 index e45a481..0000000 --- a/src/contrib/miniupnpc/minisoap.c +++ /dev/null @@ -1,121 +0,0 @@ -/* $Id: minisoap.c,v 1.22 2012/01/21 13:30:31 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * - * Minimal SOAP implementation for UPnP protocol. - */ -#include -#include -#ifdef _WIN32 -#include -#include -#define snprintf _snprintf -#else -#include -#include -#include -#endif -#include "minisoap.h" -#include "miniupnpcstrings.h" - -/* only for malloc */ -#include - -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -/* httpWrite sends the headers and the body to the socket - * and returns the number of bytes sent */ -static int -httpWrite(int fd, const char * body, int bodysize, - const char * headers, int headerssize) -{ - int n = 0; - /*n = write(fd, headers, headerssize);*/ - /*if(bodysize>0) - n += write(fd, body, bodysize);*/ - /* Note : my old linksys router only took into account - * soap request that are sent into only one packet */ - char * p; - /* TODO: AVOID MALLOC */ - p = malloc(headerssize+bodysize); - if(!p) - return 0; - memcpy(p, headers, headerssize); - memcpy(p+headerssize, body, bodysize); - /*n = write(fd, p, headerssize+bodysize);*/ - n = send(fd, p, headerssize+bodysize, 0); - if(n<0) { - PRINT_SOCKET_ERROR("send"); - } - /* disable send on the socket */ - /* draytek routers dont seems to like that... */ -#if 0 -#ifdef _WIN32 - if(shutdown(fd, SD_SEND)<0) { -#else - if(shutdown(fd, SHUT_WR)<0) { /*SD_SEND*/ -#endif - PRINT_SOCKET_ERROR("shutdown"); - } -#endif - free(p); - return n; -} - -/* self explanatory */ -int soapPostSubmit(int fd, - const char * url, - const char * host, - unsigned short port, - const char * action, - const char * body, - const char * httpversion) -{ - int bodysize; - char headerbuf[512]; - int headerssize; - char portstr[8]; - bodysize = (int)strlen(body); - /* We are not using keep-alive HTTP connections. - * HTTP/1.1 needs the header Connection: close to do that. - * This is the default with HTTP/1.0 - * Using HTTP/1.1 means we need to support chunked transfer-encoding : - * When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked - * transfer encoding. */ - /* Connection: Close is normally there only in HTTP/1.1 but who knows */ - portstr[0] = '\0'; - if(port != 80) - snprintf(portstr, sizeof(portstr), ":%hu", port); - headerssize = snprintf(headerbuf, sizeof(headerbuf), - "POST %s HTTP/%s\r\n" - "Host: %s%s\r\n" - "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" - "Content-Length: %d\r\n" - "Content-Type: text/xml\r\n" - "SOAPAction: \"%s\"\r\n" - "Connection: Close\r\n" - "Cache-Control: no-cache\r\n" /* ??? */ - "Pragma: no-cache\r\n" - "\r\n", - url, httpversion, host, portstr, bodysize, action); -#ifdef DEBUG - /*printf("SOAP request : headersize=%d bodysize=%d\n", - headerssize, bodysize); - */ - printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n", - url, httpversion, host, portstr); - printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize); - printf("Headers :\n%s", headerbuf); - printf("Body :\n%s\n", body); -#endif - return httpWrite(fd, body, bodysize, headerbuf, headerssize); -} - - diff --git a/src/contrib/miniupnpc/minisoap.h b/src/contrib/miniupnpc/minisoap.h deleted file mode 100644 index 14c859d..0000000 --- a/src/contrib/miniupnpc/minisoap.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ -#ifndef MINISOAP_H_INCLUDED -#define MINISOAP_H_INCLUDED - -/*int httpWrite(int, const char *, int, const char *);*/ -int soapPostSubmit(int, const char *, const char *, unsigned short, - const char *, const char *, const char *); - -#endif - diff --git a/src/contrib/miniupnpc/minissdpc.c b/src/contrib/miniupnpc/minissdpc.c deleted file mode 100644 index c4913fb..0000000 --- a/src/contrib/miniupnpc/minissdpc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* $Id: minissdpc.c,v 1.16 2012/03/05 19:42:46 nanard Exp $ */ -/* Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2012 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -/*#include */ -#include -#include -#include -#include -#include -#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) -#ifdef _WIN32 -#include -#include -#include -#include -#include -#endif -#if defined(__amigaos__) || defined(__amigaos4__) -#include -#endif -#if defined(__amigaos__) -#define uint16_t unsigned short -#endif -/* Hack */ -#define UNIX_PATH_LEN 108 -struct sockaddr_un { - uint16_t sun_family; - char sun_path[UNIX_PATH_LEN]; -}; -#else -#include -#include -#endif - -#include "minissdpc.h" -#include "miniupnpc.h" - -#include "codelength.h" - -struct UPNPDev * -getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath) -{ - struct UPNPDev * tmp; - struct UPNPDev * devlist = NULL; - unsigned char buffer[2048]; - ssize_t n; - unsigned char * p; - unsigned char * url; - unsigned int i; - unsigned int urlsize, stsize, usnsize, l; - int s; - struct sockaddr_un addr; - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s < 0) - { - /*syslog(LOG_ERR, "socket(unix): %m");*/ - perror("socket(unix)"); - return NULL; - } - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path)); - /* TODO : check if we need to handle the EINTR */ - if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) - { - /*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/ - close(s); - return NULL; - } - stsize = strlen(devtype); - buffer[0] = 1; /* request type 1 : request devices/services by type */ - p = buffer + 1; - l = stsize; CODELENGTH(l, p); - if(p + stsize > buffer + sizeof(buffer)) - { - /* devtype is too long ! */ - close(s); - return NULL; - } - memcpy(p, devtype, stsize); - p += stsize; - if(write(s, buffer, p - buffer) < 0) - { - /*syslog(LOG_ERR, "write(): %m");*/ - perror("minissdpc.c: write()"); - close(s); - return NULL; - } - n = read(s, buffer, sizeof(buffer)); - if(n<=0) - { - perror("minissdpc.c: read()"); - close(s); - return NULL; - } - p = buffer + 1; - for(i = 0; i < buffer[0]; i++) - { - if(p+2>=buffer+sizeof(buffer)) - break; - DECODELENGTH(urlsize, p); - if(p+urlsize+2>=buffer+sizeof(buffer)) - break; - url = p; - p += urlsize; - DECODELENGTH(stsize, p); - if(p+stsize+2>=buffer+sizeof(buffer)) - break; - tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); - tmp->pNext = devlist; - tmp->descURL = tmp->buffer; - tmp->st = tmp->buffer + 1 + urlsize; - memcpy(tmp->buffer, url, urlsize); - tmp->buffer[urlsize] = '\0'; - memcpy(tmp->buffer + urlsize + 1, p, stsize); - p += stsize; - tmp->buffer[urlsize+1+stsize] = '\0'; - devlist = tmp; - /* added for compatibility with recent versions of MiniSSDPd - * >= 2007/12/19 */ - DECODELENGTH(usnsize, p); - p += usnsize; - if(p>buffer + sizeof(buffer)) - break; - } - close(s); - return devlist; -} - diff --git a/src/contrib/miniupnpc/minissdpc.h b/src/contrib/miniupnpc/minissdpc.h deleted file mode 100644 index 915b002..0000000 --- a/src/contrib/miniupnpc/minissdpc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2007 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINISSDPC_H_INCLUDED -#define MINISSDPC_H_INCLUDED - -struct UPNPDev * -getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); - -#endif - diff --git a/src/contrib/miniupnpc/miniupnpc.c b/src/contrib/miniupnpc/miniupnpc.c deleted file mode 100644 index f661c2e..0000000 --- a/src/contrib/miniupnpc/miniupnpc.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* $Id: miniupnpc.c,v 1.117 2014/01/31 14:19:13 nanard Exp $ */ -/* Project : miniupnp - * Web : http://miniupnp.free.fr/ - * Author : Thomas BERNARD - * copyright (c) 2005-2014 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENSE file. */ -#define __EXTENSIONS__ 1 -#if !defined(MACOSX) && !defined(__sun) -#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__) && !defined(__NetBSD__) -#ifndef __cplusplus -#define _XOPEN_SOURCE 600 -#endif -#endif -#ifndef __BSD_VISIBLE -#define __BSD_VISIBLE 1 -#endif -#endif - -#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) -#define HAS_IP_MREQN -#endif - -#include -#include -#include -#ifdef _WIN32 -/* Win32 Specific includes and defines */ -#include -#include -#include -#include -#define snprintf _snprintf -#define strdup _strdup -#ifndef strncasecmp -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define strncasecmp _memicmp -#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#define strncasecmp memicmp -#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#endif /* #ifndef strncasecmp */ -#define MAXHOSTNAMELEN 64 -#else /* #ifdef _WIN32 */ -/* Standard POSIX includes */ -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -/* Amiga OS 3 specific stuff */ -#define socklen_t int -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if !defined(__amigaos__) && !defined(__amigaos4__) -#include -#endif -#include -#include -#define closesocket close -#endif /* #else _WIN32 */ -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT -#include -#endif -#if defined(__amigaos__) || defined(__amigaos4__) -/* Amiga OS specific stuff */ -#define TIMEVAL struct timeval -#endif - - -#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) -/* Several versions of glibc don't define this structure, define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ -struct ip_mreqn -{ - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_address; /* local IP address of interface */ - int imr_ifindex; /* Interface index */ -}; -#endif - -#include "miniupnpc.h" -#include "minissdpc.h" -#include "miniwget.h" -#include "minisoap.h" -#include "minixml.h" -#include "upnpcommands.h" -#include "connecthostport.h" -#include "receivedata.h" - -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -#define SOAPPREFIX "s" -#define SERVICEPREFIX "u" -#define SERVICEPREFIX2 'u' - -/* root description parsing */ -LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) -{ - struct xmlparser parser; - /* xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parser.attfunc = 0; - parsexml(&parser); -#ifdef DEBUG - printIGD(data); -#endif -} - -/* simpleUPnPcommand2 : - * not so simple ! - * return values : - * pointer - OK - * NULL - error */ -char * simpleUPnPcommand2(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize, const char * httpversion) -{ - char hostname[MAXHOSTNAMELEN+1]; - unsigned short port = 0; - char * path; - char soapact[128]; - char soapbody[2048]; - char * buf; - int n; - - *bufsize = 0; - snprintf(soapact, sizeof(soapact), "%s#%s", service, action); - if(args==NULL) - { - /*soapbodylen = */snprintf(soapbody, sizeof(soapbody), - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">" - "" - "" - "\r\n", action, service, action); - } - else - { - char * p; - const char * pe, * pv; - int soapbodylen; - soapbodylen = snprintf(soapbody, sizeof(soapbody), - "\r\n" - "<" SOAPPREFIX ":Envelope " - "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" " - SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" - "<" SOAPPREFIX ":Body>" - "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">", - action, service); - p = soapbody + soapbodylen; - while(args->elt) - { - /* check that we are never overflowing the string... */ - if(soapbody + sizeof(soapbody) <= p + 100) - { - /* we keep a margin of at least 100 bytes */ - return NULL; - } - *(p++) = '<'; - pe = args->elt; - while(*pe) - *(p++) = *(pe++); - *(p++) = '>'; - if((pv = args->val)) - { - while(*pv) - *(p++) = *(pv++); - } - *(p++) = '<'; - *(p++) = '/'; - pe = args->elt; - while(*pe) - *(p++) = *(pe++); - *(p++) = '>'; - args++; - } - *(p++) = '<'; - *(p++) = '/'; - *(p++) = SERVICEPREFIX2; - *(p++) = ':'; - pe = action; - while(*pe) - *(p++) = *(pe++); - strncpy(p, ">\r\n", - soapbody + sizeof(soapbody) - p); - } - if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; - if(s < 0) { - s = connecthostport(hostname, port, 0); - if(s < 0) { - /* failed to connect */ - return NULL; - } - } - - n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion); - if(n<=0) { -#ifdef DEBUG - printf("Error sending SOAP request\n"); -#endif - closesocket(s); - return NULL; - } - - buf = getHTTPResponse(s, bufsize); -#ifdef DEBUG - if(*bufsize > 0 && buf) - { - printf("SOAP Response :\n%.*s\n", *bufsize, buf); - } -#endif - closesocket(s); - return buf; -} - -/* simpleUPnPcommand : - * not so simple ! - * return values : - * pointer - OK - * NULL - error */ -char * simpleUPnPcommand(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize) -{ - char * buf; - -#if 1 - buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); -#else - buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0"); - if (!buf || *bufsize == 0) - { -#if DEBUG - printf("Error or no result from SOAP request; retrying with HTTP/1.1\n"); -#endif - buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); - } -#endif - return buf; -} - -/* parseMSEARCHReply() - * the last 4 arguments are filled during the parsing : - * - location/locationsize : "location:" field of the SSDP reply packet - * - st/stsize : "st:" field of the SSDP reply packet. - * The strings are NOT null terminated */ -static void -parseMSEARCHReply(const char * reply, int size, - const char * * location, int * locationsize, - const char * * st, int * stsize) -{ - int a, b, i; - i = 0; - a = i; /* start of the line */ - b = 0; /* end of the "header" (position of the colon) */ - while(isin6_family = AF_INET6; - if(sameport) - p->sin6_port = htons(PORT); - p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ - } else { - struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; - p->sin_family = AF_INET; - if(sameport) - p->sin_port = htons(PORT); - p->sin_addr.s_addr = INADDR_ANY; - } -#ifdef _WIN32 -/* This code could help us to use the right Network interface for - * SSDP multicast traffic */ -/* Get IP associated with the index given in the ip_forward struct - * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ - if(!ipv6 - && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { - DWORD dwRetVal = 0; - PMIB_IPADDRTABLE pIPAddrTable; - DWORD dwSize = 0; -#ifdef DEBUG - IN_ADDR IPAddr; -#endif - int i; -#ifdef DEBUG - printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); -#endif - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); - if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { - free(pIPAddrTable); - pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); - } - if(pIPAddrTable) { - dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); -#ifdef DEBUG - printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); -#endif - for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { -#ifdef DEBUG - printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; - printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; - printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); - IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; - printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); - printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); - printf("\tType and State[%d]:", i); - printf("\n"); -#endif - if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { - /* Set the address of this interface to be used */ - struct in_addr mc_if; - memset(&mc_if, 0, sizeof(mc_if)); - mc_if.s_addr = pIPAddrTable->table[i].dwAddr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { - PRINT_SOCKET_ERROR("setsockopt"); - } - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; -#ifndef DEBUG - break; -#endif - } - } - free(pIPAddrTable); - pIPAddrTable = NULL; - } - } -#endif - -#ifdef _WIN32 - if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) -#else - if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) -#endif - { - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; - PRINT_SOCKET_ERROR("setsockopt"); - return NULL; - } - - if(multicastif) - { - if(ipv6) { -#if !defined(_WIN32) - /* according to MSDN, if_nametoindex() is supported since - * MS Windows Vista and MS Windows Server 2008. - * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ - unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ - if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#else -#ifdef DEBUG - printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); -#endif -#endif - } else { - struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ - if(mc_if.s_addr != INADDR_NONE) - { - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } - } else { -#ifdef HAS_IP_MREQN - /* was not an ip address, try with an interface name */ - struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ - memset(&reqn, 0, sizeof(struct ip_mreqn)); - reqn.imr_ifindex = if_nametoindex(multicastif); - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt"); - } -#else -#ifdef DEBUG - printf("Setting of multicast interface not supported with interface name.\n"); -#endif -#endif - } - } - } - - /* Before sending the packed, we first "bind" in order to be able - * to receive the response */ - if (bind(sudp, (const struct sockaddr *)&sockudp_r, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) - { - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; - PRINT_SOCKET_ERROR("bind"); - closesocket(sudp); - return NULL; - } - - if(error) - *error = UPNPDISCOVER_SUCCESS; - /* Calculating maximum response time in seconds */ - mx = ((unsigned int)delay) / 1000u; - if(mx == 0) { - mx = 1; - delay = 1000; - } - /* receiving SSDP response packet */ - for(n = 0; deviceList[deviceIndex]; deviceIndex++) - { - if(n == 0) - { - /* sending the SSDP M-SEARCH packet */ - n = snprintf(bufr, sizeof(bufr), - MSearchMsgFmt, - ipv6 ? - (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") - : UPNP_MCAST_ADDR, - deviceList[deviceIndex], mx); -#ifdef DEBUG - printf("Sending %s", bufr); -#endif -#ifdef NO_GETADDRINFO - /* the following code is not using getaddrinfo */ - /* emission */ - memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); - if(ipv6) { - struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; - p->sin6_family = AF_INET6; - p->sin6_port = htons(PORT); - inet_pton(AF_INET6, - linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, - &(p->sin6_addr)); - } else { - struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; - p->sin_family = AF_INET; - p->sin_port = htons(PORT); - p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); - } - n = sendto(sudp, bufr, n, 0, - &sockudp_w, - ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - if (n < 0) { - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; - PRINT_SOCKET_ERROR("sendto"); - break; - } -#else /* #ifdef NO_GETADDRINFO */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ - hints.ai_socktype = SOCK_DGRAM; - /*hints.ai_flags = */ - if ((rv = getaddrinfo(ipv6 - ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) - : UPNP_MCAST_ADDR, - XSTR(PORT), &hints, &servinfo)) != 0) { - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; -#ifdef _WIN32 - fprintf(stderr, "getaddrinfo() failed: %d\n", rv); -#else - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); -#endif - break; - } - for(p = servinfo; p; p = p->ai_next) { - n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); - if (n < 0) { -#ifdef DEBUG - char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; - if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, - sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { - fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); - } -#endif - PRINT_SOCKET_ERROR("sendto"); - continue; - } - } - freeaddrinfo(servinfo); - if(n < 0) { - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; - break; - } -#endif /* #ifdef NO_GETADDRINFO */ - } - /* Waiting for SSDP REPLY packet to M-SEARCH */ - n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); - if (n < 0) { - /* error */ - if(error) - *error = UPNPDISCOVER_SOCKET_ERROR; - break; - } else if (n == 0) { - /* no data or Time Out */ - if (devlist) { - /* no more device type to look for... */ - if(error) - *error = UPNPDISCOVER_SUCCESS; - break; - } - if(ipv6) { - if(linklocal) { - linklocal = 0; - --deviceIndex; - } else { - linklocal = 1; - } - } - } else { - const char * descURL=NULL; - int urlsize=0; - const char * st=NULL; - int stsize=0; - /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */ - parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize); - if(st&&descURL) - { -#ifdef DEBUG - printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", - stsize, st, urlsize, descURL); -#endif - for(tmp=devlist; tmp; tmp = tmp->pNext) { - if(memcmp(tmp->descURL, descURL, urlsize) == 0 && - tmp->descURL[urlsize] == '\0' && - memcmp(tmp->st, st, stsize) == 0 && - tmp->st[stsize] == '\0') - break; - } - /* at the exit of the loop above, tmp is null if - * no duplicate device was found */ - if(tmp) - continue; - tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); - if(!tmp) { - /* memory allocation error */ - if(error) - *error = UPNPDISCOVER_MEMORY_ERROR; - break; - } - tmp->pNext = devlist; - tmp->descURL = tmp->buffer; - tmp->st = tmp->buffer + 1 + urlsize; - memcpy(tmp->buffer, descURL, urlsize); - tmp->buffer[urlsize] = '\0'; - memcpy(tmp->buffer + urlsize + 1, st, stsize); - tmp->buffer[urlsize+1+stsize] = '\0'; - tmp->scope_id = scope_id; - devlist = tmp; - } - } - } - closesocket(sudp); - return devlist; -} - -/* freeUPNPDevlist() should be used to - * free the chained list returned by upnpDiscover() */ -LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist) -{ - struct UPNPDev * next; - while(devlist) - { - next = devlist->pNext; - free(devlist); - devlist = next; - } -} - -static void -url_cpy_or_cat(char * dst, const char * src, int n) -{ - if( (src[0] == 'h') - &&(src[1] == 't') - &&(src[2] == 't') - &&(src[3] == 'p') - &&(src[4] == ':') - &&(src[5] == '/') - &&(src[6] == '/')) - { - strncpy(dst, src, n); - } - else - { - int l = strlen(dst); - if(src[0] != '/') - dst[l++] = '/'; - if(l<=n) - strncpy(dst + l, src, n - l); - } -} - -/* Prepare the Urls for usage... - */ -LIBSPEC void -GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, - const char * descURL, unsigned int scope_id) -{ - char * p; - int n1, n2, n3, n4; -#ifdef IF_NAMESIZE - char ifname[IF_NAMESIZE]; -#else - char scope_str[8]; -#endif - - n1 = strlen(data->urlbase); - if(n1==0) - n1 = strlen(descURL); - if(scope_id != 0) { -#ifdef IF_NAMESIZE - if(if_indextoname(scope_id, ifname)) { - n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ - } -#else - /* under windows, scope is numerical */ - snprintf(scope_str, sizeof(scope_str), "%u", scope_id); -#endif - } - n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ - n2 = n1; n3 = n1; n4 = n1; - n1 += strlen(data->first.scpdurl); - n2 += strlen(data->first.controlurl); - n3 += strlen(data->CIF.controlurl); - n4 += strlen(data->IPv6FC.controlurl); - - /* allocate memory to store URLs */ - urls->ipcondescURL = (char *)malloc(n1); - urls->controlURL = (char *)malloc(n2); - urls->controlURL_CIF = (char *)malloc(n3); - urls->controlURL_6FC = (char *)malloc(n4); - - /* strdup descURL */ - urls->rootdescURL = strdup(descURL); - - /* get description of WANIPConnection */ - if(data->urlbase[0] != '\0') - strncpy(urls->ipcondescURL, data->urlbase, n1); - else - strncpy(urls->ipcondescURL, descURL, n1); - p = strchr(urls->ipcondescURL+7, '/'); - if(p) p[0] = '\0'; - if(scope_id != 0) { - if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { - /* this is a linklocal IPv6 address */ - p = strchr(urls->ipcondescURL, ']'); - if(p) { - /* insert %25 into URL */ -#ifdef IF_NAMESIZE - memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); - memcpy(p, "%25", 3); - memcpy(p + 3, ifname, strlen(ifname)); -#else - memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); - memcpy(p, "%25", 3); - memcpy(p + 3, scope_str, strlen(scope_str)); -#endif - } - } - } - strncpy(urls->controlURL, urls->ipcondescURL, n2); - strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); - strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); - - url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); - - url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); - - url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); - - url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4); - -#ifdef DEBUG - printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, - (unsigned)strlen(urls->ipcondescURL), n1); - printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, - (unsigned)strlen(urls->controlURL), n2); - printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF, - (unsigned)strlen(urls->controlURL_CIF), n3); - printf("urls->controlURL_6FC='%s' %u n4=%d\n", urls->controlURL_6FC, - (unsigned)strlen(urls->controlURL_6FC), n4); -#endif -} - -LIBSPEC void -FreeUPNPUrls(struct UPNPUrls * urls) -{ - if(!urls) - return; - free(urls->controlURL); - urls->controlURL = 0; - free(urls->ipcondescURL); - urls->ipcondescURL = 0; - free(urls->controlURL_CIF); - urls->controlURL_CIF = 0; - free(urls->controlURL_6FC); - urls->controlURL_6FC = 0; - free(urls->rootdescURL); - urls->rootdescURL = 0; -} - -int -UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) -{ - char status[64]; - unsigned int uptime; - status[0] = '\0'; - UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, - status, &uptime, NULL); - if(0 == strcmp("Connected", status)) - { - return 1; - } - else - return 0; -} - - -/* UPNP_GetValidIGD() : - * return values : - * -1 = Internal error - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as - * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD - * - * In any positive non zero return case, the urls and data structures - * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to - * free allocated memory. - */ -LIBSPEC int -UPNP_GetValidIGD(struct UPNPDev * devlist, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) -{ - struct xml_desc { - char * xml; - int size; - int is_igd; - } * desc = NULL; - struct UPNPDev * dev; - int ndev = 0; - int i; - int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ - int n_igd = 0; - char extIpAddr[16]; - if(!devlist) - { -#ifdef DEBUG - printf("Empty devlist\n"); -#endif - return 0; - } - /* counting total number of devices in the list */ - for(dev = devlist; dev; dev = dev->pNext) - ndev++; - if(ndev > 0) - { - desc = calloc(ndev, sizeof(struct xml_desc)); - if(!desc) - return -1; /* memory allocation error */ - } - /* Step 1 : downloading descriptions and testing type */ - for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) - { - /* we should choose an internet gateway device. - * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ - desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), - lanaddr, lanaddrlen, - dev->scope_id); -#ifdef DEBUG - if(!desc[i].xml) - { - printf("error getting XML description %s\n", dev->descURL); - } -#endif - if(desc[i].xml) - { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(desc[i].xml, desc[i].size, data); - if(0==strcmp(data->CIF.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) - { - desc[i].is_igd = 1; - n_igd++; - } - } - } - /* iterate the list to find a device depending on state */ - for(state = 1; state <= 3; state++) - { - for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) - { - if(desc[i].xml) - { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(desc[i].xml, desc[i].size, data); - if(desc[i].is_igd || state >= 3 ) - { - GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); - - /* in state 2 and 3 we dont test if device is connected ! */ - if(state >= 2) - goto free_and_return; -#ifdef DEBUG - printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, - UPNPIGD_IsConnected(urls, data)); -#endif - /* checks that status is connected AND there is a external IP address assigned */ - if(UPNPIGD_IsConnected(urls, data) - && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) - goto free_and_return; - FreeUPNPUrls(urls); - if(data->second.servicetype[0] != '\0') { -#ifdef DEBUG - printf("We tried %s, now we try %s !\n", - data->first.servicetype, data->second.servicetype); -#endif - /* swaping WANPPPConnection and WANIPConnection ! */ - memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); - memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); - memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); - GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); -#ifdef DEBUG - printf("UPNPIGD_IsConnected(%s) = %d\n", - urls->controlURL, - UPNPIGD_IsConnected(urls, data)); -#endif - if(UPNPIGD_IsConnected(urls, data) - && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) - goto free_and_return; - FreeUPNPUrls(urls); - } - } - memset(data, 0, sizeof(struct IGDdatas)); - } - } - } - state = 0; -free_and_return: - if(desc) { - for(i = 0; i < ndev; i++) { - if(desc[i].xml) { - free(desc[i].xml); - } - } - free(desc); - } - return state; -} - -/* UPNP_GetIGDFromUrl() - * Used when skipping the discovery process. - * return value : - * 0 - Not ok - * 1 - OK */ -int -UPNP_GetIGDFromUrl(const char * rootdescurl, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen) -{ - char * descXML; - int descXMLsize = 0; - descXML = miniwget_getaddr(rootdescurl, &descXMLsize, - lanaddr, lanaddrlen, 0); - if(descXML) { - memset(data, 0, sizeof(struct IGDdatas)); - memset(urls, 0, sizeof(struct UPNPUrls)); - parserootdesc(descXML, descXMLsize, data); - free(descXML); - descXML = NULL; - GetUPNPUrls(urls, data, rootdescurl, 0); - return 1; - } else { - return 0; - } -} - diff --git a/src/contrib/miniupnpc/miniupnpc.def b/src/contrib/miniupnpc/miniupnpc.def deleted file mode 100644 index 3343356..0000000 --- a/src/contrib/miniupnpc/miniupnpc.def +++ /dev/null @@ -1,43 +0,0 @@ -LIBRARY -; miniupnpc library - miniupnpc - -EXPORTS -; miniupnpc - upnpDiscover - freeUPNPDevlist - parserootdesc - UPNP_GetValidIGD - UPNP_GetIGDFromUrl - GetUPNPUrls - FreeUPNPUrls -; miniwget - miniwget - miniwget_getaddr -; upnpcommands - UPNP_GetTotalBytesSent - UPNP_GetTotalBytesReceived - UPNP_GetTotalPacketsSent - UPNP_GetTotalPacketsReceived - UPNP_GetStatusInfo - UPNP_GetConnectionTypeInfo - UPNP_GetExternalIPAddress - UPNP_GetLinkLayerMaxBitRates - UPNP_AddPortMapping - UPNP_DeletePortMapping - UPNP_GetPortMappingNumberOfEntries - UPNP_GetSpecificPortMappingEntry - UPNP_GetGenericPortMappingEntry - UPNP_GetListOfPortMappings - UPNP_AddPinhole - UPNP_CheckPinholeWorking - UPNP_UpdatePinhole - UPNP_GetPinholePackets - UPNP_DeletePinhole - UPNP_GetFirewallStatus - UPNP_GetOutboundPinholeTimeout -; upnperrors - strupnperror -; portlistingparse - ParsePortListing - FreePortListing diff --git a/src/contrib/miniupnpc/miniupnpc.h b/src/contrib/miniupnpc/miniupnpc.h deleted file mode 100644 index 3af109c..0000000 --- a/src/contrib/miniupnpc/miniupnpc.h +++ /dev/null @@ -1,130 +0,0 @@ -/* $Id: miniupnpc.h,v 1.35 2014/01/31 13:26:34 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ - * Author: Thomas Bernard - * Copyright (c) 2005-2012 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPC_H_INCLUDED -#define MINIUPNPC_H_INCLUDED - -#include "declspec.h" -#include "igd_desc_parse.h" - -/* error codes : */ -#define UPNPDISCOVER_SUCCESS (0) -#define UPNPDISCOVER_UNKNOWN_ERROR (-1) -#define UPNPDISCOVER_SOCKET_ERROR (-101) -#define UPNPDISCOVER_MEMORY_ERROR (-102) - -/* versions : */ -#define MINIUPNPC_VERSION "1.9.20140401" -#define MINIUPNPC_API_VERSION 10 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structures definitions : */ -struct UPNParg { const char * elt; const char * val; }; - -char * -simpleUPnPcommand(int, const char *, const char *, - const char *, struct UPNParg *, - int *); - -struct UPNPDev { - struct UPNPDev * pNext; - char * descURL; - char * st; - unsigned int scope_id; - char buffer[2]; -}; - -/* upnpDiscover() - * discover UPnP devices on the network. - * The discovered devices are returned as a chained list. - * It is up to the caller to free the list with freeUPNPDevlist(). - * delay (in millisecond) is the maximum time for waiting any device - * response. - * If available, device list will be obtained from MiniSSDPd. - * Default path for minissdpd socket will be used if minissdpdsock argument - * is NULL. - * If multicastif is not NULL, it will be used instead of the default - * multicast interface for sending SSDP discover packets. - * If sameport is not null, SSDP packets will be sent from the source port - * 1900 (same as destination port) otherwise system assign a source port. */ -LIBSPEC struct UPNPDev * -upnpDiscover(int delay, const char * multicastif, - const char * minissdpdsock, int sameport, - int ipv6, - int * error); -/* freeUPNPDevlist() - * free list returned by upnpDiscover() */ -LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); - -/* parserootdesc() : - * parse root XML description of a UPnP device and fill the IGDdatas - * structure. */ -LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); - -/* structure used to get fast access to urls - * controlURL: controlURL of the WANIPConnection - * ipcondescURL: url of the description of the WANIPConnection - * controlURL_CIF: controlURL of the WANCommonInterfaceConfig - * controlURL_6FC: controlURL of the WANIPv6FirewallControl - */ -struct UPNPUrls { - char * controlURL; - char * ipcondescURL; - char * controlURL_CIF; - char * controlURL_6FC; - char * rootdescURL; -}; - -/* UPNP_GetValidIGD() : - * return values : - * 0 = NO IGD found - * 1 = A valid connected IGD has been found - * 2 = A valid IGD has been found but it reported as - * not connected - * 3 = an UPnP device has been found but was not recognized as an IGD - * - * In any non zero return case, the urls and data structures - * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to - * free allocated memory. - */ -LIBSPEC int -UPNP_GetValidIGD(struct UPNPDev * devlist, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -/* UPNP_GetIGDFromUrl() - * Used when skipping the discovery process. - * return value : - * 0 - Not ok - * 1 - OK */ -LIBSPEC int -UPNP_GetIGDFromUrl(const char * rootdescurl, - struct UPNPUrls * urls, - struct IGDdatas * data, - char * lanaddr, int lanaddrlen); - -LIBSPEC void -GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, - const char *, unsigned int); - -LIBSPEC void -FreeUPNPUrls(struct UPNPUrls *); - -/* return 0 or 1 */ -LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnpc/miniupnpcmodule.c b/src/contrib/miniupnpc/miniupnpcmodule.c deleted file mode 100644 index 4654c98..0000000 --- a/src/contrib/miniupnpc/miniupnpcmodule.c +++ /dev/null @@ -1,545 +0,0 @@ -/* $Id: miniupnpcmodule.c,v 1.22 2014/01/31 13:18:25 nanard Exp $*/ -/* Project : miniupnp - * Author : Thomas BERNARD - * website : http://miniupnp.tuxfamily.org/ - * copyright (c) 2007-2014 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include -#define STATICLIB -#include "structmember.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "upnperrors.h" - -/* for compatibility with Python < 2.4 */ -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None -#endif - -#ifndef Py_RETURN_TRUE -#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True -#endif - -#ifndef Py_RETURN_FALSE -#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False -#endif - -/* for compatibility with Python < 3.0 */ -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -#ifndef Py_TYPE -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif - -typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ - struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; - unsigned int discoverdelay; /* value passed to upnpDiscover() */ - char lanaddr[40]; /* our ip address on the LAN */ - char * multicastif; - char * minissdpdsocket; -} UPnPObject; - -static PyMemberDef UPnP_members[] = { - {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr), - READONLY, "ip address on the LAN" - }, - {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay), - 0/*READWRITE*/, "value in ms used to wait for SSDP responses" - }, - /* T_STRING is allways readonly :( */ - {"multicastif", T_STRING, offsetof(UPnPObject, multicastif), - 0, "IP of the network interface to be used for multicast operations" - }, - {"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif), - 0, "path of the MiniSSDPd unix socket" - }, - {NULL} -}; - -static void -UPnPObject_dealloc(UPnPObject *self) -{ - freeUPNPDevlist(self->devlist); - FreeUPNPUrls(&self->urls); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -UPnP_discover(UPnPObject *self) -{ - struct UPNPDev * dev; - int i; - PyObject *res = NULL; - if(self->devlist) - { - freeUPNPDevlist(self->devlist); - self->devlist = 0; - } - Py_BEGIN_ALLOW_THREADS - self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/, - 0/* multicast if*/, - 0/*minissdpd socket*/, - 0/*sameport flag*/, - 0/*ip v6*/, - 0/*error */); - Py_END_ALLOW_THREADS - /* Py_RETURN_NONE ??? */ - for(dev = self->devlist, i = 0; dev; dev = dev->pNext) - i++; - res = Py_BuildValue("i", i); - return res; -} - -static PyObject * -UPnP_selectigd(UPnPObject *self) -{ - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data, - self->lanaddr, sizeof(self->lanaddr)); -Py_END_ALLOW_THREADS - if(r) - { - return Py_BuildValue("s", self->urls.controlURL); - } - else - { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, "No UPnP device discovered"); - return NULL; - } -} - -static PyObject * -UPnP_totalbytesent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS - return Py_BuildValue("I", i); -} - -static PyObject * -UPnP_totalbytereceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS - return Py_BuildValue("I", i); -} - -static PyObject * -UPnP_totalpacketsent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS - return Py_BuildValue("I", i); -} - -static PyObject * -UPnP_totalpacketreceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS - return Py_BuildValue("I", i); -} - -static PyObject * -UPnP_statusinfo(UPnPObject *self) -{ - char status[64]; - char lastconnerror[64]; - unsigned int uptime = 0; - int r; - status[0] = '\0'; - lastconnerror[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype, - status, &uptime, lastconnerror); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_connectiontype(UPnPObject *self) -{ - char connectionType[64]; - int r; - connectionType[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetConnectionTypeInfo(self->urls.controlURL, - self->data.first.servicetype, - connectionType); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", connectionType); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_externalipaddress(UPnPObject *self) -{ - char externalIPAddress[40]; - int r; - externalIPAddress[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetExternalIPAddress(self->urls.controlURL, - self->data.first.servicetype, - externalIPAddress); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", externalIPAddress); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc, - * remoteHost) - * protocol is 'UDP' or 'TCP' */ -static PyObject * -UPnP_addportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - char inPort[6]; - unsigned short iPort; - const char * proto; - const char * host; - const char * desc; - const char * remoteHost; - const char * leaseDuration = "0"; - int r; - if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto, - &host, &iPort, &desc, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - sprintf(inPort, "%hu", iPort); - r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, inPort, host, desc, proto, - remoteHost, leaseDuration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - Py_RETURN_TRUE; - } - else - { - // TODO: RAISE an Exception. See upnpcommands.h for errors codes. - // upnperrors.c - //Py_RETURN_FALSE; - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* DeletePortMapping(extPort, proto, removeHost='') - * proto = 'UDP', 'TCP' */ -static PyObject * -UPnP_deleteportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - int r; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, proto, remoteHost); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - Py_RETURN_TRUE; - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_getportmappingnumberofentries(UPnPObject *self) -{ - unsigned int n = 0; - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL, - self->data.first.servicetype, - &n); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("I", n); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* GetSpecificPortMapping(ePort, proto, remoteHost='') - * proto = 'UDP' or 'TCP' */ -static PyObject * -UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char desc[80]; - char enabled[4]; - char leaseDuration[16]; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; - extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0'; - desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - UPNP_GetSpecificPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - extPort, proto, remoteHost, - intClient, intPort, - desc, enabled, leaseDuration); -Py_END_ALLOW_THREADS - if(intClient[0]) - { - iPort = (unsigned short)atoi(intPort); - return Py_BuildValue("(s,H,s,O,i)", - intClient, iPort, desc, - PyBool_FromLong(atoi(enabled)), - atoi(leaseDuration)); - } - else - { - Py_RETURN_NONE; - } -} - -/* GetGenericPortMapping(index) */ -static PyObject * -UPnP_getgenericportmapping(UPnPObject *self, PyObject *args) -{ - int i, r; - char index[8]; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char extPort[6]; - unsigned short ePort; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; /* lease duration */ - unsigned int dur; - if(!PyArg_ParseTuple(args, "i", &i)) - return NULL; -Py_BEGIN_ALLOW_THREADS - snprintf(index, sizeof(index), "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, rHost, - duration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - ePort = (unsigned short)atoi(extPort); - iPort = (unsigned short)atoi(intPort); - dur = (unsigned int)strtoul(duration, 0, 0); - return Py_BuildValue("(H,s,(s,H),s,s,s,I)", - ePort, protocol, intClient, iPort, - desc, enabled, rHost, dur); - } - else - { - Py_RETURN_NONE; - } -} - -/* miniupnpc.UPnP object Method Table */ -static PyMethodDef UPnP_methods[] = { - {"discover", (PyCFunction)UPnP_discover, METH_NOARGS, - "discover UPnP IGD devices on the network" - }, - {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS, - "select a valid UPnP IGD among discovered devices" - }, - {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS, - "return the total number of bytes sent by UPnP IGD" - }, - {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS, - "return the total number of bytes received by UPnP IGD" - }, - {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS, - "return the total number of packets sent by UPnP IGD" - }, - {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS, - "return the total number of packets received by UPnP IGD" - }, - {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS, - "return status and uptime" - }, - {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS, - "return IGD WAN connection type" - }, - {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS, - "return external IP address" - }, - {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS, - "add a port mapping" - }, - {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS, - "delete a port mapping" - }, - {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS, - "-- non standard --" - }, - {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS, - "get details about a specific port mapping entry" - }, - {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS, - "get all details about the port mapping at index" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject UPnPType = { - PyVarObject_HEAD_INIT(NULL, - 0) /*ob_size*/ - "miniupnpc.UPnP", /*tp_name*/ - sizeof(UPnPObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)UPnPObject_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "UPnP objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - UPnP_methods, /* tp_methods */ - UPnP_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0,/*(initproc)UPnP_init,*/ /* tp_init */ - 0, /* tp_alloc */ -#ifndef _WIN32 - PyType_GenericNew,/*UPnP_new,*/ /* tp_new */ -#else - 0, -#endif -}; - -/* module methods */ -static PyMethodDef miniupnpc_methods[] = { - {NULL} /* Sentinel */ -}; - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "miniupnpc", /* m_name */ - "miniupnpc module.", /* m_doc */ - -1, /* m_size */ - miniupnpc_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; -#endif - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif - -PyMODINIT_FUNC -#if PY_MAJOR_VERSION >= 3 -PyInit_miniupnpc(void) -#else -initminiupnpc(void) -#endif -{ - PyObject* m; - -#ifdef _WIN32 - UPnPType.tp_new = PyType_GenericNew; -#endif - if (PyType_Ready(&UPnPType) < 0) - return; - -#if PY_MAJOR_VERSION >= 3 - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("miniupnpc", miniupnpc_methods, - "miniupnpc module."); -#endif - - Py_INCREF(&UPnPType); - PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType); - -#if PY_MAJOR_VERSION >= 3 - return m; -#endif -} - diff --git a/src/contrib/miniupnpc/miniupnpcstrings.h.cmake b/src/contrib/miniupnpc/miniupnpcstrings.h.cmake deleted file mode 100644 index 236b2dc..0000000 --- a/src/contrib/miniupnpc/miniupnpcstrings.h.cmake +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "${CMAKE_SYSTEM_NAME}" -#define MINIUPNPC_VERSION_STRING "${MINIUPNPC_VERSION}" - -#endif diff --git a/src/contrib/miniupnpc/miniupnpcstrings.h.in b/src/contrib/miniupnpc/miniupnpcstrings.h.in deleted file mode 100644 index c32e3a1..0000000 --- a/src/contrib/miniupnpc/miniupnpcstrings.h.in +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: miniupnpcstrings.h.in,v 1.5 2012/10/16 16:48:26 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef MINIUPNPCSTRINGS_H_INCLUDED -#define MINIUPNPCSTRINGS_H_INCLUDED - -#define OS_STRING "OS/version" -#define MINIUPNPC_VERSION_STRING "version" - -#endif - diff --git a/src/contrib/miniupnpc/miniupnpctypes.h b/src/contrib/miniupnpc/miniupnpctypes.h deleted file mode 100644 index 591c32f..0000000 --- a/src/contrib/miniupnpc/miniupnpctypes.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org - * Author : Thomas Bernard - * Copyright (c) 2011 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef MINIUPNPCTYPES_H_INCLUDED -#define MINIUPNPCTYPES_H_INCLUDED - -#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) -#define UNSIGNED_INTEGER unsigned long long -#define STRTOUI strtoull -#else -#define UNSIGNED_INTEGER unsigned int -#define STRTOUI strtoul -#endif - -#endif - diff --git a/src/contrib/miniupnpc/miniwget.c b/src/contrib/miniupnpc/miniwget.c deleted file mode 100644 index 813db93..0000000 --- a/src/contrib/miniupnpc/miniwget.c +++ /dev/null @@ -1,575 +0,0 @@ -/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */ -/* Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#include -#include -#ifdef _WIN32 -#include -#include -#include -#define MAXHOSTNAMELEN 64 -#define MIN(x,y) (((x)<(y))?(x):(y)) -#define snprintf _snprintf -#define socklen_t int -#ifndef strncasecmp -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define strncasecmp _memicmp -#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#define strncasecmp memicmp -#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ -#endif /* #ifndef strncasecmp */ -#else /* #ifdef _WIN32 */ -#include -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -#define socklen_t int -#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#include -#include -#include -#include -#define closesocket close -#endif /* #else _WIN32 */ -#if defined(__sun) || defined(sun) -#define MIN(x,y) (((x)<(y))?(x):(y)) -#endif - -#include "miniupnpcstrings.h" -#include "miniwget.h" -#include "connecthostport.h" -#include "receivedata.h" - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* - * Read a HTTP response from a socket. - * Process Content-Length and Transfer-encoding headers. - * return a pointer to the content buffer, which length is saved - * to the length parameter. - */ -void * -getHTTPResponse(int s, int * size) -{ - char buf[2048]; - int n; - int endofheaders = 0; - int chunked = 0; - int content_length = -1; - unsigned int chunksize = 0; - unsigned int bytestocopy = 0; - /* buffers : */ - char * header_buf; - unsigned int header_buf_len = 2048; - unsigned int header_buf_used = 0; - char * content_buf; - unsigned int content_buf_len = 2048; - unsigned int content_buf_used = 0; - char chunksize_buf[32]; - unsigned int chunksize_buf_index; - - header_buf = malloc(header_buf_len); - content_buf = malloc(content_buf_len); - chunksize_buf[0] = '\0'; - chunksize_buf_index = 0; - - while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0) - { - if(endofheaders == 0) - { - int i; - int linestart=0; - int colon=0; - int valuestart=0; - if(header_buf_used + n > header_buf_len) { - header_buf = realloc(header_buf, header_buf_used + n); - header_buf_len = header_buf_used + n; - } - memcpy(header_buf + header_buf_used, buf, n); - header_buf_used += n; - /* search for CR LF CR LF (end of headers) - * recognize also LF LF */ - i = 0; - while(i < ((int)header_buf_used-1) && (endofheaders == 0)) { - if(header_buf[i] == '\r') { - i++; - if(header_buf[i] == '\n') { - i++; - if(i < (int)header_buf_used && header_buf[i] == '\r') { - i++; - if(i < (int)header_buf_used && header_buf[i] == '\n') { - endofheaders = i+1; - } - } - } - } else if(header_buf[i] == '\n') { - i++; - if(header_buf[i] == '\n') { - endofheaders = i+1; - } - } - i++; - } - if(endofheaders == 0) - continue; - /* parse header lines */ - for(i = 0; i < endofheaders - 1; i++) { - if(colon <= linestart && header_buf[i]==':') - { - colon = i; - while(i < (endofheaders-1) - && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t')) - i++; - valuestart = i + 1; - } - /* detecting end of line */ - else if(header_buf[i]=='\r' || header_buf[i]=='\n') - { - if(colon > linestart && valuestart > colon) - { -#ifdef DEBUG - printf("header='%.*s', value='%.*s'\n", - colon-linestart, header_buf+linestart, - i-valuestart, header_buf+valuestart); -#endif - if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart)) - { - content_length = atoi(header_buf+valuestart); -#ifdef DEBUG - printf("Content-Length: %d\n", content_length); -#endif - } - else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart) - && 0==strncasecmp(header_buf+valuestart, "chunked", 7)) - { -#ifdef DEBUG - printf("chunked transfer-encoding!\n"); -#endif - chunked = 1; - } - } - while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) - i++; - linestart = i; - colon = linestart; - valuestart = 0; - } - } - /* copy the remaining of the received data back to buf */ - n = header_buf_used - endofheaders; - memcpy(buf, header_buf + endofheaders, n); - /* if(headers) */ - } - if(endofheaders) - { - /* content */ - if(chunked) - { - int i = 0; - while(i < n) - { - if(chunksize == 0) - { - /* reading chunk size */ - if(chunksize_buf_index == 0) { - /* skipping any leading CR LF */ - if(i= '0' - && chunksize_buf[j] <= '9') - chunksize = (chunksize << 4) + (chunksize_buf[j] - '0'); - else - chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10); - } - chunksize_buf[0] = '\0'; - chunksize_buf_index = 0; - i++; - } else { - /* not finished to get chunksize */ - continue; - } -#ifdef DEBUG - printf("chunksize = %u (%x)\n", chunksize, chunksize); -#endif - if(chunksize == 0) - { -#ifdef DEBUG - printf("end of HTTP content - %d %d\n", i, n); - /*printf("'%.*s'\n", n-i, buf+i);*/ -#endif - goto end_of_stream; - } - } - bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i); - if((content_buf_used + bytestocopy) > content_buf_len) - { - if(content_length >= (int)(content_buf_used + bytestocopy)) { - content_buf_len = content_length; - } else { - content_buf_len = content_buf_used + bytestocopy; - } - content_buf = (char *)realloc((void *)content_buf, - content_buf_len); - } - memcpy(content_buf + content_buf_used, buf + i, bytestocopy); - content_buf_used += bytestocopy; - i += bytestocopy; - chunksize -= bytestocopy; - } - } - else - { - /* not chunked */ - if(content_length > 0 - && (int)(content_buf_used + n) > content_length) { - /* skipping additional bytes */ - n = content_length - content_buf_used; - } - if(content_buf_used + n > content_buf_len) - { - if(content_length >= (int)(content_buf_used + n)) { - content_buf_len = content_length; - } else { - content_buf_len = content_buf_used + n; - } - content_buf = (char *)realloc((void *)content_buf, - content_buf_len); - } - memcpy(content_buf + content_buf_used, buf, n); - content_buf_used += n; - } - } - /* use the Content-Length header value if available */ - if(content_length > 0 && (int)content_buf_used >= content_length) - { -#ifdef DEBUG - printf("End of HTTP content\n"); -#endif - break; - } - } -end_of_stream: - free(header_buf); header_buf = NULL; - *size = content_buf_used; - if(content_buf_used == 0) - { - free(content_buf); - content_buf = NULL; - } - return content_buf; -} - -/* miniwget3() : - * do all the work. - * Return NULL if something failed. */ -static void * -miniwget3(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - const char * httpversion, unsigned int scope_id) -{ - char buf[2048]; - int s; - int n; - int len; - int sent; - void * content; - - *size = 0; - s = connecthostport(host, port, scope_id); - if(s < 0) - return NULL; - - /* get address for caller ! */ - if(addr_str) - { - struct sockaddr_storage saddr; - socklen_t saddrlen; - - saddrlen = sizeof(saddr); - if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0) - { - perror("getsockname"); - } - else - { -#if defined(__amigaos__) && !defined(__amigaos4__) - /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD); - * But his function make a string with the port : nn.nn.nn.nn:port */ -/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr), - NULL, addr_str, (DWORD *)&addr_str_len)) - { - printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError()); - }*/ - /* the following code is only compatible with ip v4 addresses */ - strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len); -#else -#if 0 - if(saddr.sa_family == AF_INET6) { - inet_ntop(AF_INET6, - &(((struct sockaddr_in6 *)&saddr)->sin6_addr), - addr_str, addr_str_len); - } else { - inet_ntop(AF_INET, - &(((struct sockaddr_in *)&saddr)->sin_addr), - addr_str, addr_str_len); - } -#endif - /* getnameinfo return ip v6 address with the scope identifier - * such as : 2a01:e35:8b2b:7330::%4281128194 */ - n = getnameinfo((const struct sockaddr *)&saddr, saddrlen, - addr_str, addr_str_len, - NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV); - if(n != 0) { -#ifdef _WIN32 - fprintf(stderr, "getnameinfo() failed : %d\n", n); -#else - fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n)); -#endif - } -#endif - } -#ifdef DEBUG - printf("address miniwget : %s\n", addr_str); -#endif - } - - len = snprintf(buf, sizeof(buf), - "GET %s HTTP/%s\r\n" - "Host: %s:%d\r\n" - "Connection: Close\r\n" - "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n" - - "\r\n", - path, httpversion, host, port); - sent = 0; - /* sending the HTTP request */ - while(sent < len) - { - n = send(s, buf+sent, len-sent, 0); - if(n < 0) - { - perror("send"); - closesocket(s); - return NULL; - } - else - { - sent += n; - } - } - content = getHTTPResponse(s, size); - closesocket(s); - return content; -} - -/* miniwget2() : - * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */ -static void * -miniwget2(const char * host, - unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len, - unsigned int scope_id) -{ - char * respbuffer; - -#if 1 - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", scope_id); -#else - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.0", scope_id); - if (*size == 0) - { -#ifdef DEBUG - printf("Retrying with HTTP/1.1\n"); -#endif - free(respbuffer); - respbuffer = miniwget3(host, port, path, size, - addr_str, addr_str_len, "1.1", scope_id); - } -#endif - return respbuffer; -} - - - - -/* parseURL() - * arguments : - * url : source string not modified - * hostname : hostname destination string (size of MAXHOSTNAMELEN+1) - * port : port (destination) - * path : pointer to the path part of the URL - * - * Return values : - * 0 - Failure - * 1 - Success */ -int -parseURL(const char * url, - char * hostname, unsigned short * port, - char * * path, unsigned int * scope_id) -{ - char * p1, *p2, *p3; - if(!url) - return 0; - p1 = strstr(url, "://"); - if(!p1) - return 0; - p1 += 3; - if( (url[0]!='h') || (url[1]!='t') - ||(url[2]!='t') || (url[3]!='p')) - return 0; - memset(hostname, 0, MAXHOSTNAMELEN + 1); - if(*p1 == '[') - { - /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ - char * scope; - scope = strchr(p1, '%'); - p2 = strchr(p1, ']'); - if(p2 && scope && scope < p2 && scope_id) { - /* parse scope */ -#ifdef IF_NAMESIZE - char tmp[IF_NAMESIZE]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= IF_NAMESIZE) - l = IF_NAMESIZE - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = if_nametoindex(tmp); - if(*scope_id == 0) { - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); - } -#else - /* under windows, scope is numerical */ - char tmp[8]; - int l; - scope++; - /* "%25" is just '%' in URL encoding */ - if(scope[0] == '2' && scope[1] == '5') - scope += 2; /* skip "25" */ - l = p2 - scope; - if(l >= sizeof(tmp)) - l = sizeof(tmp) - 1; - memcpy(tmp, scope, l); - tmp[l] = '\0'; - *scope_id = (unsigned int)strtoul(tmp, NULL, 10); -#endif - } - p3 = strchr(p1, '/'); - if(p2 && p3) - { - p2++; - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - if(*p2 == ':') - { - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) - { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - else - { - *port = 80; - } - *path = p3; - return 1; - } - } - p2 = strchr(p1, ':'); - p3 = strchr(p1, '/'); - if(!p3) - return 0; - if(!p2 || (p2>p3)) - { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); - *port = 80; - } - else - { - strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); - *port = 0; - p2++; - while( (*p2 >= '0') && (*p2 <= '9')) - { - *port *= 10; - *port += (unsigned short)(*p2 - '0'); - p2++; - } - } - *path = p3; - return 1; -} - -void * -miniwget(const char * url, int * size, unsigned int scope_id) -{ - unsigned short port; - char * path; - /* protocol://host:port/chemin */ - char hostname[MAXHOSTNAMELEN+1]; - *size = 0; - if(!parseURL(url, hostname, &port, &path, &scope_id)) - return NULL; -#ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", - hostname, port, path, scope_id); -#endif - return miniwget2(hostname, port, path, size, 0, 0, scope_id); -} - -void * -miniwget_getaddr(const char * url, int * size, - char * addr, int addrlen, unsigned int scope_id) -{ - unsigned short port; - char * path; - /* protocol://host:port/path */ - char hostname[MAXHOSTNAMELEN+1]; - *size = 0; - if(addr) - addr[0] = '\0'; - if(!parseURL(url, hostname, &port, &path, &scope_id)) - return NULL; -#ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", - hostname, port, path, scope_id); -#endif - return miniwget2(hostname, port, path, size, addr, addrlen, scope_id); -} - diff --git a/src/contrib/miniupnpc/miniwget.h b/src/contrib/miniupnpc/miniwget.h deleted file mode 100644 index 31bcea3..0000000 --- a/src/contrib/miniupnpc/miniwget.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIWGET_H_INCLUDED -#define MINIWGET_H_INCLUDED - -#include "declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -LIBSPEC void * getHTTPResponse(int s, int * size); - -LIBSPEC void * miniwget(const char *, int *, unsigned int); - -LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); - -int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnpc/minixml.c b/src/contrib/miniupnpc/minixml.c deleted file mode 100644 index 3e201ec..0000000 --- a/src/contrib/miniupnpc/minixml.c +++ /dev/null @@ -1,229 +0,0 @@ -/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ -/* minixml.c : the minimum size a xml parser can be ! */ -/* Project : miniupnp - * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard - -Copyright (c) 2005-2014, Thomas BERNARD -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ -#include -#include "minixml.h" - -/* parseatt : used to parse the argument list - * return 0 (false) in case of success and -1 (true) if the end - * of the xmlbuffer is reached. */ -static int parseatt(struct xmlparser * p) -{ - const char * attname; - int attnamelen; - const char * attvalue; - int attvaluelen; - while(p->xml < p->xmlend) - { - if(*p->xml=='/' || *p->xml=='>') - return 0; - if( !IS_WHITE_SPACE(*p->xml) ) - { - char sep; - attname = p->xml; - attnamelen = 0; - while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) ) - { - attnamelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - while(*(p->xml++) != '=') - { - if(p->xml >= p->xmlend) - return -1; - } - while(IS_WHITE_SPACE(*p->xml)) - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - sep = *p->xml; - if(sep=='\'' || sep=='\"') - { - p->xml++; - if(p->xml >= p->xmlend) - return -1; - attvalue = p->xml; - attvaluelen = 0; - while(*p->xml != sep) - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - else - { - attvalue = p->xml; - attvaluelen = 0; - while( !IS_WHITE_SPACE(*p->xml) - && *p->xml != '>' && *p->xml != '/') - { - attvaluelen++; p->xml++; - if(p->xml >= p->xmlend) - return -1; - } - } - /*printf("%.*s='%.*s'\n", - attnamelen, attname, attvaluelen, attvalue);*/ - if(p->attfunc) - p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen); - } - p->xml++; - } - return -1; -} - -/* parseelt parse the xml stream and - * call the callback functions when needed... */ -static void parseelt(struct xmlparser * p) -{ - int i; - const char * elementname; - while(p->xml < (p->xmlend - 1)) - { - if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); - p->xml += 3; - } - else if((p->xml)[0]=='<' && (p->xml)[1]!='?') - { - i = 0; elementname = ++p->xml; - while( !IS_WHITE_SPACE(*p->xml) - && (*p->xml!='>') && (*p->xml!='/') - ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - /* to ignore namespace : */ - if(*p->xml==':') - { - i = 0; - elementname = ++p->xml; - } - } - if(i>0) - { - if(p->starteltfunc) - p->starteltfunc(p->data, elementname, i); - if(parseatt(p)) - return; - if(*p->xml!='/') - { - const char * data; - i = 0; data = ++p->xml; - if (p->xml >= p->xmlend) - return; - while( IS_WHITE_SPACE(*p->xml) ) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(memcmp(p->xml, "xml += 9; - data = p->xml; - i = 0; - while(memcmp(p->xml, "]]>", 3) != 0) - { - i++; p->xml++; - if ((p->xml + 3) >= p->xmlend) - return; - } - if(i>0 && p->datafunc) - p->datafunc(p->data, data, i); - while(*p->xml!='<') - { - p->xml++; - if (p->xml >= p->xmlend) - return; - } - } - else - { - while(*p->xml!='<') - { - i++; p->xml++; - if ((p->xml + 1) >= p->xmlend) - return; - } - if(i>0 && p->datafunc && *(p->xml + 1) == '/') - p->datafunc(p->data, data, i); - } - } - } - else if(*p->xml == '/') - { - i = 0; elementname = ++p->xml; - if (p->xml >= p->xmlend) - return; - while((*p->xml != '>')) - { - i++; p->xml++; - if (p->xml >= p->xmlend) - return; - } - if(p->endeltfunc) - p->endeltfunc(p->data, elementname, i); - p->xml++; - } - } - else - { - p->xml++; - } - } -} - -/* the parser must be initialized before calling this function */ -void parsexml(struct xmlparser * parser) -{ - parser->xml = parser->xmlstart; - parser->xmlend = parser->xmlstart + parser->xmlsize; - parseelt(parser); -} - - diff --git a/src/contrib/miniupnpc/minixml.h b/src/contrib/miniupnpc/minixml.h deleted file mode 100644 index 9f43aa4..0000000 --- a/src/contrib/miniupnpc/minixml.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ -/* minimal xml parser - * - * Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#ifndef MINIXML_H_INCLUDED -#define MINIXML_H_INCLUDED -#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) - -/* if a callback function pointer is set to NULL, - * the function is not called */ -struct xmlparser { - const char *xmlstart; - const char *xmlend; - const char *xml; /* pointer to current character */ - int xmlsize; - void * data; - void (*starteltfunc) (void *, const char *, int); - void (*endeltfunc) (void *, const char *, int); - void (*datafunc) (void *, const char *, int); - void (*attfunc) (void *, const char *, int, const char *, int); -}; - -/* parsexml() - * the xmlparser structure must be initialized before the call - * the following structure members have to be initialized : - * xmlstart, xmlsize, data, *func - * xml is for internal usage, xmlend is computed automatically */ -void parsexml(struct xmlparser *); - -#endif - diff --git a/src/contrib/miniupnpc/minixmlvalid.c b/src/contrib/miniupnpc/minixmlvalid.c deleted file mode 100644 index 0a112bf..0000000 --- a/src/contrib/miniupnpc/minixmlvalid.c +++ /dev/null @@ -1,158 +0,0 @@ -/* $Id: minixmlvalid.c,v 1.6 2012/05/01 16:24:07 nanard Exp $ */ -/* MiniUPnP Project - * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ - * minixmlvalid.c : - * validation program for the minixml parser - * - * (c) 2006-2011 Thomas Bernard */ - -#include -#include -#include -#include "minixml.h" - -/* xml event structure */ -struct event { - enum { ELTSTART, ELTEND, ATT, CHARDATA } type; - const char * data; - int len; -}; - -struct eventlist { - int n; - struct event * events; -}; - -/* compare 2 xml event lists - * return 0 if the two lists are equals */ -int evtlistcmp(struct eventlist * a, struct eventlist * b) -{ - int i; - struct event * ae, * be; - if(a->n != b->n) - { - printf("event number not matching : %d != %d\n", a->n, b->n); - /*return 1;*/ - } - for(i=0; in; i++) - { - ae = a->events + i; - be = b->events + i; - if( (ae->type != be->type) - ||(ae->len != be->len) - ||memcmp(ae->data, be->data, ae->len)) - { - printf("Found a difference : %d '%.*s' != %d '%.*s'\n", - ae->type, ae->len, ae->data, - be->type, be->len, be->data); - return 1; - } - } - return 0; -} - -/* Test data */ -static const char xmldata[] = -"\n" -" " -"character data" -" \n \t" -"" -"\nstuff !\n ]]> \n\n" -" \tchardata1 chardata2 " -""; - -static const struct event evtref[] = -{ - {ELTSTART, "xmlroot", 7}, - {ELTSTART, "elt1", 4}, - /* attributes */ - {CHARDATA, "character data", 14}, - {ELTEND, "elt1", 4}, - {ELTSTART, "elt1b", 5}, - {ELTSTART, "elt1", 4}, - {CHARDATA, " stuff !\n ", 16}, - {ELTEND, "elt1", 4}, - {ELTSTART, "elt2a", 5}, - {ELTSTART, "elt2b", 5}, - {CHARDATA, "chardata1", 9}, - {ELTEND, "elt2b", 5}, - {ELTSTART, "elt2b", 5}, - {CHARDATA, " chardata2 ", 11}, - {ELTEND, "elt2b", 5}, - {ELTEND, "elt2a", 5}, - {ELTEND, "xmlroot", 7} -}; - -void startelt(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("startelt : %.*s\n", l, p);*/ - evt->type = ELTSTART; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -void endelt(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("endelt : %.*s\n", l, p);*/ - evt->type = ELTEND; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -void chardata(void * data, const char * p, int l) -{ - struct eventlist * evtlist = data; - struct event * evt; - evt = evtlist->events + evtlist->n; - /*printf("chardata : '%.*s'\n", l, p);*/ - evt->type = CHARDATA; - evt->data = p; - evt->len = l; - evtlist->n++; -} - -int testxmlparser(const char * xml, int size) -{ - int r; - struct eventlist evtlist; - struct eventlist evtlistref; - struct xmlparser parser; - evtlist.n = 0; - evtlist.events = malloc(sizeof(struct event)*100); - memset(&parser, 0, sizeof(parser)); - parser.xmlstart = xml; - parser.xmlsize = size; - parser.data = &evtlist; - parser.starteltfunc = startelt; - parser.endeltfunc = endelt; - parser.datafunc = chardata; - parsexml(&parser); - printf("%d events\n", evtlist.n); - /* compare */ - evtlistref.n = sizeof(evtref)/sizeof(struct event); - evtlistref.events = (struct event *)evtref; - r = evtlistcmp(&evtlistref, &evtlist); - free(evtlist.events); - return r; -} - -int main(int argc, char * * argv) -{ - int r; - (void)argc; (void)argv; - - r = testxmlparser(xmldata, sizeof(xmldata)-1); - if(r) - printf("minixml validation test failed\n"); - return r; -} - diff --git a/src/contrib/miniupnpc/msvc/miniupnpc.sln b/src/contrib/miniupnpc/msvc/miniupnpc.sln deleted file mode 100644 index b3da191..0000000 --- a/src/contrib/miniupnpc/msvc/miniupnpc.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "miniupnpc.vcproj", "{D28CE435-CB33-4BAE-8A52-C6EF915956F5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "upnpc-static", "upnpc-static.vcproj", "{469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}" - ProjectSection(ProjectDependencies) = postProject - {D28CE435-CB33-4BAE-8A52-C6EF915956F5} = {D28CE435-CB33-4BAE-8A52-C6EF915956F5} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.ActiveCfg = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Debug|Win32.Build.0 = Debug|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.ActiveCfg = Release|Win32 - {D28CE435-CB33-4BAE-8A52-C6EF915956F5}.Release|Win32.Build.0 = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.ActiveCfg = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Debug|Win32.Build.0 = Debug|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.ActiveCfg = Release|Win32 - {469E1CF6-08A2-4B7B-A2AA-5BDB089857C1}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/miniupnpc/msvc/miniupnpc.vcproj b/src/contrib/miniupnpc/msvc/miniupnpc.vcproj deleted file mode 100644 index 12a55aa..0000000 --- a/src/contrib/miniupnpc/msvc/miniupnpc.vcproj +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/miniupnpc/msvc/upnpc-static.vcproj b/src/contrib/miniupnpc/msvc/upnpc-static.vcproj deleted file mode 100644 index 2946138..0000000 --- a/src/contrib/miniupnpc/msvc/upnpc-static.vcproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/miniupnpc/portlistingparse.c b/src/contrib/miniupnpc/portlistingparse.c deleted file mode 100644 index 19e3054..0000000 --- a/src/contrib/miniupnpc/portlistingparse.c +++ /dev/null @@ -1,159 +0,0 @@ -/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include "portlistingparse.h" -#include "minixml.h" - -/* list of the elements */ -static const struct { - const portMappingElt code; - const char * const str; -} elements[] = { - { PortMappingEntry, "PortMappingEntry"}, - { NewRemoteHost, "NewRemoteHost"}, - { NewExternalPort, "NewExternalPort"}, - { NewProtocol, "NewProtocol"}, - { NewInternalPort, "NewInternalPort"}, - { NewInternalClient, "NewInternalClient"}, - { NewEnabled, "NewEnabled"}, - { NewDescription, "NewDescription"}, - { NewLeaseTime, "NewLeaseTime"}, - { PortMappingEltNone, NULL} -}; - -/* Helper function */ -static UNSIGNED_INTEGER -atoui(const char * p, int l) -{ - UNSIGNED_INTEGER r = 0; - while(l > 0 && *p) - { - if(*p >= '0' && *p <= '9') - r = r*10 + (*p - '0'); - else - break; - p++; - l--; - } - return r; -} - -/* Start element handler */ -static void -startelt(void * d, const char * name, int l) -{ - int i; - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - pdata->curelt = PortMappingEltNone; - for(i = 0; elements[i].str; i++) - { - if(memcmp(name, elements[i].str, l) == 0) - { - pdata->curelt = elements[i].code; - break; - } - } - if(pdata->curelt == PortMappingEntry) - { - struct PortMapping * pm; - pm = calloc(1, sizeof(struct PortMapping)); - LIST_INSERT_HEAD( &(pdata->head), pm, entries); - } -} - -/* End element handler */ -static void -endelt(void * d, const char * name, int l) -{ - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - (void)name; - (void)l; - pdata->curelt = PortMappingEltNone; -} - -/* Data handler */ -static void -data(void * d, const char * data, int l) -{ - struct PortMapping * pm; - struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; - pm = pdata->head.lh_first; - if(!pm) - return; - if(l > 63) - l = 63; - switch(pdata->curelt) - { - case NewRemoteHost: - memcpy(pm->remoteHost, data, l); - pm->remoteHost[l] = '\0'; - break; - case NewExternalPort: - pm->externalPort = (unsigned short)atoui(data, l); - break; - case NewProtocol: - if(l > 3) - l = 3; - memcpy(pm->protocol, data, l); - pm->protocol[l] = '\0'; - break; - case NewInternalPort: - pm->internalPort = (unsigned short)atoui(data, l); - break; - case NewInternalClient: - memcpy(pm->internalClient, data, l); - pm->internalClient[l] = '\0'; - break; - case NewEnabled: - pm->enabled = (unsigned char)atoui(data, l); - break; - case NewDescription: - memcpy(pm->description, data, l); - pm->description[l] = '\0'; - break; - case NewLeaseTime: - pm->leaseTime = atoui(data, l); - break; - default: - break; - } -} - - -/* Parse the PortMappingList XML document for IGD version 2 - */ -void -ParsePortListing(const char * buffer, int bufsize, - struct PortMappingParserData * pdata) -{ - struct xmlparser parser; - - memset(pdata, 0, sizeof(struct PortMappingParserData)); - LIST_INIT(&(pdata->head)); - /* init xmlparser */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = pdata; - parser.starteltfunc = startelt; - parser.endeltfunc = endelt; - parser.datafunc = data; - parser.attfunc = 0; - parsexml(&parser); -} - -void -FreePortListing(struct PortMappingParserData * pdata) -{ - struct PortMapping * pm; - while((pm = pdata->head.lh_first) != NULL) - { - LIST_REMOVE(pm, entries); - free(pm); - } -} - diff --git a/src/contrib/miniupnpc/portlistingparse.h b/src/contrib/miniupnpc/portlistingparse.h deleted file mode 100644 index bafa2a4..0000000 --- a/src/contrib/miniupnpc/portlistingparse.h +++ /dev/null @@ -1,71 +0,0 @@ -/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011-2012 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#ifndef PORTLISTINGPARSE_H_INCLUDED -#define PORTLISTINGPARSE_H_INCLUDED - -#include "declspec.h" -/* for the definition of UNSIGNED_INTEGER */ -#include "miniupnpctypes.h" - -#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) -#include "bsdqueue.h" -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* sample of PortMappingEntry : - - 202.233.2.1 - 2345 - TCP - 2345 - 192.168.1.137 - 1 - dooom - 345 - - */ -typedef enum { PortMappingEltNone, - PortMappingEntry, NewRemoteHost, - NewExternalPort, NewProtocol, - NewInternalPort, NewInternalClient, - NewEnabled, NewDescription, - NewLeaseTime } portMappingElt; - -struct PortMapping { - LIST_ENTRY(PortMapping) entries; - UNSIGNED_INTEGER leaseTime; - unsigned short externalPort; - unsigned short internalPort; - char remoteHost[64]; - char internalClient[64]; - char description[64]; - char protocol[4]; - unsigned char enabled; -}; - -struct PortMappingParserData { - LIST_HEAD(portmappinglisthead, PortMapping) head; - portMappingElt curelt; -}; - -LIBSPEC void -ParsePortListing(const char * buffer, int bufsize, - struct PortMappingParserData * pdata); - -LIBSPEC void -FreePortListing(struct PortMappingParserData * pdata); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/miniupnpc/pymoduletest.py b/src/contrib/miniupnpc/pymoduletest.py deleted file mode 100644 index d35a3b0..0000000 --- a/src/contrib/miniupnpc/pymoduletest.py +++ /dev/null @@ -1,52 +0,0 @@ -#! /usr/bin/python -# MiniUPnP project -# Author : Thomas Bernard -# This Sample code is public domain. -# website : http://miniupnp.tuxfamily.org/ - -# import the python miniupnpc module -import miniupnpc -import sys - -# create the object -u = miniupnpc.UPnP() -print 'inital(default) values :' -print ' discoverdelay', u.discoverdelay -print ' lanaddr', u.lanaddr -print ' multicastif', u.multicastif -print ' minissdpdsocket', u.minissdpdsocket -u.discoverdelay = 200; -#u.minissdpdsocket = '../minissdpd/minissdpd.sock' -# discovery process, it usualy takes several seconds (2 seconds or more) -print 'Discovering... delay=%ums' % u.discoverdelay -print u.discover(), 'device(s) detected' -# select an igd -try: - u.selectigd() -except Exception, e: - print 'Exception :', e - sys.exit(1) -# display information about the IGD and the internet connection -print 'local ip address :', u.lanaddr -print 'external ip address :', u.externalipaddress() -print u.statusinfo(), u.connectiontype() - -#print u.addportmapping(64000, 'TCP', -# '192.168.1.166', 63000, 'port mapping test', '') -#print u.deleteportmapping(64000, 'TCP') - -port = 0 -proto = 'UDP' -# list the redirections : -i = 0 -while True: - p = u.getgenericportmapping(i) - if p==None: - break - print i, p - (port, proto, (ihost,iport), desc, c, d, e) = p - #print port, desc - i = i + 1 - -print u.getspecificportmapping(port, proto) - diff --git a/src/contrib/miniupnpc/receivedata.c b/src/contrib/miniupnpc/receivedata.c deleted file mode 100644 index ffbfbea..0000000 --- a/src/contrib/miniupnpc/receivedata.c +++ /dev/null @@ -1,109 +0,0 @@ -/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */ -/* Project : miniupnp - * Website : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2011-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#ifdef _WIN32 -#include -#include -#else -#include -#if defined(__amigaos__) && !defined(__amigaos4__) -#define socklen_t int -#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ -#include -#include -#if !defined(__amigaos__) && !defined(__amigaos4__) -#include -#endif -#include -#define MINIUPNPC_IGNORE_EINTR -#endif - -#ifdef _WIN32 -#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); -#else -#define PRINT_SOCKET_ERROR(x) perror(x) -#endif - -#include "receivedata.h" - -int -receivedata(int socket, - char * data, int length, - int timeout, unsigned int * scope_id) -{ -#if MINIUPNPC_GET_SRC_ADDR -#ifdef DEBUG - /* to shut up valgrind about uninit value */ - struct sockaddr_storage src_addr = {0}; -#else - struct sockaddr_storage src_addr; -#endif - socklen_t src_addr_len = sizeof(src_addr); -#endif - int n; -#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) - /* using poll */ - struct pollfd fds[1]; /* for the poll */ -#ifdef MINIUPNPC_IGNORE_EINTR - do { -#endif - fds[0].fd = socket; - fds[0].events = POLLIN; - n = poll(fds, 1, timeout); -#ifdef MINIUPNPC_IGNORE_EINTR - } while(n < 0 && errno == EINTR); -#endif - if(n < 0) { - PRINT_SOCKET_ERROR("poll"); - return -1; - } else if(n == 0) { - /* timeout */ - return 0; - } -#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ - /* using select under _WIN32 and amigaos */ - fd_set socketSet; - TIMEVAL timeval; - FD_ZERO(&socketSet); - FD_SET(socket, &socketSet); - timeval.tv_sec = timeout / 1000; - timeval.tv_usec = (timeout % 1000) * 1000; - n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); - if(n < 0) { - PRINT_SOCKET_ERROR("select"); - return -1; - } else if(n == 0) { - return 0; - } -#endif -#if MINIUPNPC_GET_SRC_ADDR - n = recvfrom(socket, data, length, 0, - (struct sockaddr *)&src_addr, &src_addr_len); -#else - n = recv(socket, data, length, 0); -#endif - if(n<0) { - PRINT_SOCKET_ERROR("recv"); - } -#if MINIUPNPC_GET_SRC_ADDR - if (src_addr.ss_family == AF_INET6) { - const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; -#ifdef DEBUG - printf("scope_id=%u\n", src_addr6->sin6_scope_id); -#endif - if(scope_id) - *scope_id = src_addr6->sin6_scope_id; - } -#endif - return n; -} - - diff --git a/src/contrib/miniupnpc/receivedata.h b/src/contrib/miniupnpc/receivedata.h deleted file mode 100644 index 0520a11..0000000 --- a/src/contrib/miniupnpc/receivedata.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2011-2012 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENCE file provided within this distribution */ -#ifndef RECEIVEDATA_H_INCLUDED -#define RECEIVEDATA_H_INCLUDED - -/* Reads data from the specified socket. - * Returns the number of bytes read if successful, zero if no bytes were - * read or if we timed out. Returns negative if there was an error. */ -int receivedata(int socket, - char * data, int length, - int timeout, unsigned int * scope_id); - -#endif - diff --git a/src/contrib/miniupnpc/setup.py b/src/contrib/miniupnpc/setup.py deleted file mode 100644 index 63a275c..0000000 --- a/src/contrib/miniupnpc/setup.py +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/bin/python -# $Id: setup.py,v 1.9 2012/05/23 08:50:10 nanard Exp $ -# the MiniUPnP Project (c) 2007-2012 Thomas Bernard -# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ -# -# python script to build the miniupnpc module under unix -# -# replace libminiupnpc.a by libminiupnpc.so for shared library usage -from distutils.core import setup, Extension -from distutils import sysconfig -sysconfig.get_config_vars()["OPT"] = '' -sysconfig.get_config_vars()["CFLAGS"] = '' -setup(name="miniupnpc", version="1.7", - ext_modules=[ - Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], - extra_objects=["libminiupnpc.a"]) - ]) - diff --git a/src/contrib/miniupnpc/setupmingw32.py b/src/contrib/miniupnpc/setupmingw32.py deleted file mode 100644 index cb23d1d..0000000 --- a/src/contrib/miniupnpc/setupmingw32.py +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/bin/python -# $Id: setupmingw32.py,v 1.8 2012/05/23 08:50:10 nanard Exp $ -# the MiniUPnP Project (c) 2007-2012 Thomas Bernard -# http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/ -# -# python script to build the miniupnpc module under windows (using mingw32) -# -from distutils.core import setup, Extension -from distutils import sysconfig -sysconfig.get_config_vars()["OPT"] = '' -sysconfig.get_config_vars()["CFLAGS"] = '' -setup(name="miniupnpc", version="1.7", - ext_modules=[ - Extension(name="miniupnpc", sources=["miniupnpcmodule.c"], - libraries=["ws2_32", "iphlpapi"], - extra_objects=["libminiupnpc.a"]) - ]) - diff --git a/src/contrib/miniupnpc/testigddescparse.c b/src/contrib/miniupnpc/testigddescparse.c deleted file mode 100644 index 1c0028a..0000000 --- a/src/contrib/miniupnpc/testigddescparse.c +++ /dev/null @@ -1,64 +0,0 @@ -/* $Id: testigddescparse.c,v 1.4 2012/06/28 18:52:12 nanard Exp $ */ -/* Project : miniupnp - * http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2008-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include -#include "igd_desc_parse.h" -#include "minixml.h" -#include "miniupnpc.h" - -int test_igd_desc_parse(char * buffer, int len) -{ - struct IGDdatas igd; - struct xmlparser parser; - struct UPNPUrls urls; - memset(&igd, 0, sizeof(struct IGDdatas)); - memset(&parser, 0, sizeof(struct xmlparser)); - parser.xmlstart = buffer; - parser.xmlsize = len; - parser.data = &igd; - parser.starteltfunc = IGDstartelt; - parser.endeltfunc = IGDendelt; - parser.datafunc = IGDdata; - parsexml(&parser); - printIGD(&igd); - GetUPNPUrls(&urls, &igd, "http://fake/desc/url/file.xml", 0); - printf("ipcondescURL='%s'\n", urls.ipcondescURL); - printf("controlURL='%s'\n", urls.controlURL); - printf("controlURL_CIF='%s'\n", urls.controlURL_CIF); - FreeUPNPUrls(&urls); - return 0; -} - -int main(int argc, char * * argv) -{ - FILE * f; - char * buffer; - int len; - int r = 0; - if(argc<2) { - fprintf(stderr, "Usage: %s file.xml\n", argv[0]); - return 1; - } - f = fopen(argv[1], "r"); - if(!f) { - fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); - return 1; - } - fseek(f, 0, SEEK_END); - len = ftell(f); - fseek(f, 0, SEEK_SET); - buffer = malloc(len); - fread(buffer, 1, len, f); - fclose(f); - r = test_igd_desc_parse(buffer, len); - free(buffer); - return r; -} - diff --git a/src/contrib/miniupnpc/testminiwget.c b/src/contrib/miniupnpc/testminiwget.c deleted file mode 100644 index 8ae9032..0000000 --- a/src/contrib/miniupnpc/testminiwget.c +++ /dev/null @@ -1,53 +0,0 @@ -/* $Id: testminiwget.c,v 1.4 2012/06/23 22:35:59 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2012 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. - * */ -#include -#include -#include "miniwget.h" - -/** - * This program uses the miniwget / miniwget_getaddr function - * from miniwget.c in order to retreive a web ressource using - * a GET HTTP method, and store it in a file. - */ -int main(int argc, char * * argv) -{ - void * data; - int size, writtensize; - FILE *f; - char addr[64]; - - if(argc < 3) { - fprintf(stderr, "Usage:\t%s url file\n", argv[0]); - fprintf(stderr, "Example:\t%s http://www.google.com/ out.html\n", argv[0]); - return 1; - } - data = miniwget_getaddr(argv[1], &size, addr, sizeof(addr), 0); - if(!data) { - fprintf(stderr, "Error fetching %s\n", argv[1]); - return 1; - } - printf("local address : %s\n", addr); - printf("got %d bytes\n", size); - f = fopen(argv[2], "wb"); - if(!f) { - fprintf(stderr, "Cannot open file %s for writing\n", argv[2]); - free(data); - return 1; - } - writtensize = fwrite(data, 1, size, f); - if(writtensize != size) { - fprintf(stderr, "Could only write %d bytes out of %d to %s\n", - writtensize, size, argv[2]); - } else { - printf("%d bytes written to %s\n", writtensize, argv[2]); - } - fclose(f); - free(data); - return 0; -} - diff --git a/src/contrib/miniupnpc/testminiwget.sh b/src/contrib/miniupnpc/testminiwget.sh deleted file mode 100644 index 80e153b..0000000 --- a/src/contrib/miniupnpc/testminiwget.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -# $Id: testminiwget.sh,v 1.10 2013/11/13 15:08:08 nanard Exp $ -# project miniupnp : http://miniupnp.free.fr/ -# (c) 2011-2012 Thomas Bernard -# -# test program for miniwget.c -# is usually invoked by "make check" -# -# This test program : -# 1 - launches a local HTTP server (minihttptestserver) -# 2 - uses testminiwget to retreive data from this server -# 3 - compares served and received data -# 4 - kills the local HTTP server and exits -# -# The script was tested and works with ksh, bash -# it should now also run with dash - -TMPD=`mktemp -d miniwgetXXXXXXXXXX` -HTTPSERVEROUT="${TMPD}/httpserverout" -EXPECTEDFILE="${TMPD}/expectedfile" -DOWNLOADEDFILE="${TMPD}/downloadedfile" -PORT= -RET=0 - -case "$HAVE_IPV6" in - n|no|0) - ADDR=localhost - SERVERARGS="" - ;; - *) - ADDR="[::1]" - SERVERARGS="-6" - ;; - -esac - -#make minihttptestserver -#make testminiwget - -# launching the test HTTP server -./minihttptestserver $SERVERARGS -e $EXPECTEDFILE > $HTTPSERVEROUT & -SERVERPID=$! -while [ -z "$PORT" ]; do - sleep 1 - PORT=`cat $HTTPSERVEROUT | sed 's/Listening on port \([0-9]*\)/\1/' ` -done -echo "Test HTTP server is listening on $PORT" - -URL1="http://$ADDR:$PORT/index.html" -URL2="http://$ADDR:$PORT/chunked" -URL3="http://$ADDR:$PORT/addcrap" - -echo "standard test ..." -./testminiwget $URL1 "${DOWNLOADEDFILE}.1" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.1" ; then - echo "ok" -else - echo "standard test FAILED" - RET=1 -fi - -echo "chunked transfert encoding test ..." -./testminiwget $URL2 "${DOWNLOADEDFILE}.2" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.2" ; then - echo "ok" -else - echo "chunked transfert encoding test FAILED" - RET=1 -fi - -echo "response too long test ..." -./testminiwget $URL3 "${DOWNLOADEDFILE}.3" -if cmp $EXPECTEDFILE "${DOWNLOADEDFILE}.3" ; then - echo "ok" -else - echo "response too long test FAILED" - RET=1 -fi - -# kill the test HTTP server -kill $SERVERPID -wait $SERVERPID - -# remove temporary files (for success cases) -if [ $RET -eq 0 ]; then - rm -f "${DOWNLOADEDFILE}.1" - rm -f "${DOWNLOADEDFILE}.2" - rm -f "${DOWNLOADEDFILE}.3" - rm -f $EXPECTEDFILE $HTTPSERVEROUT - rmdir ${TMPD} -else - echo "at least one of the test FAILED" - echo "directory ${TMPD} is left intact" -fi -exit $RET - diff --git a/src/contrib/miniupnpc/testminixml.c b/src/contrib/miniupnpc/testminixml.c deleted file mode 100644 index d0fe794..0000000 --- a/src/contrib/miniupnpc/testminixml.c +++ /dev/null @@ -1,87 +0,0 @@ -/* $Id: testminixml.c,v 1.9 2013/05/14 19:50:49 nanard Exp $ - * MiniUPnP project - * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author : Thomas Bernard. - * Copyright (c) 2005-2013 Thomas Bernard - * - * testminixml.c - * test program for the "minixml" functions. - */ -#include -#include -#include -#include "minixml.h" -#include "igd_desc_parse.h" - -/* ---------------------------------------------------------------------- */ -void printeltname1(void * d, const char * name, int l) -{ - int i; - (void)d; - printf("element "); - for(i=0;i -123 -TCP - - - diff --git a/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue b/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue deleted file mode 100644 index 5aa75f8..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.namevalue +++ /dev/null @@ -1,2 +0,0 @@ -NewExternalIPAddress=1.2.3.4 - diff --git a/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.xml b/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.xml deleted file mode 100644 index db7ec1f..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetExternalIPAddress.xml +++ /dev/null @@ -1,2 +0,0 @@ -1.2.3.4 - diff --git a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue deleted file mode 100644 index 26b169c..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue +++ /dev/null @@ -1,3 +0,0 @@ -NewProtocol=UDP -NewExternalPort=12345 -NewRemoteHost= diff --git a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml deleted file mode 100644 index bbb540e..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml +++ /dev/null @@ -1,3 +0,0 @@ - -12345UDP - diff --git a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue deleted file mode 100644 index 2189789..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue +++ /dev/null @@ -1,5 +0,0 @@ -NewInternalPort=12345 -NewInternalClient=192.168.10.110 -NewEnabled=1 -NewPortMappingDescription=libminiupnpc -NewLeaseDuration=0 diff --git a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml deleted file mode 100644 index 77e8d9c..0000000 --- a/src/contrib/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml +++ /dev/null @@ -1,2 +0,0 @@ -12345192.168.10.1101libminiupnpc0 - diff --git a/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue b/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue deleted file mode 100644 index f78c7e2..0000000 --- a/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.namevalue +++ /dev/null @@ -1 +0,0 @@ -NewDefaultConnectionService=uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.xml b/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.xml deleted file mode 100644 index ac04c07..0000000 --- a/src/contrib/miniupnpc/testreplyparse/SetDefaultConnectionService.xml +++ /dev/null @@ -1 +0,0 @@ -uuid:c6c05a33-f704-48df-9910-e099b3471d81:WANConnectionDevice:1,INVALID_SERVICE_ID diff --git a/src/contrib/miniupnpc/testreplyparse/readme.txt b/src/contrib/miniupnpc/testreplyparse/readme.txt deleted file mode 100644 index 3eb1f01..0000000 --- a/src/contrib/miniupnpc/testreplyparse/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -This directory contains files used for validation of upnpreplyparse.c code. - -Each .xml file to parse should give the results which are in the .namevalue -file. - -A .namevalue file contain name=value lines. - diff --git a/src/contrib/miniupnpc/testupnpigd.py b/src/contrib/miniupnpc/testupnpigd.py deleted file mode 100644 index 6d167a4..0000000 --- a/src/contrib/miniupnpc/testupnpigd.py +++ /dev/null @@ -1,84 +0,0 @@ -#! /usr/bin/python -# $Id: testupnpigd.py,v 1.4 2008/10/11 10:27:20 nanard Exp $ -# MiniUPnP project -# Author : Thomas Bernard -# This Sample code is public domain. -# website : http://miniupnp.tuxfamily.org/ - -# import the python miniupnpc module -import miniupnpc -import socket -import BaseHTTPServer - -# function definition -def list_redirections(): - i = 0 - while True: - p = u.getgenericportmapping(i) - if p==None: - break - print i, p - i = i + 1 - -#define the handler class for HTTP connections -class handler_class(BaseHTTPServer.BaseHTTPRequestHandler): - def do_GET(self): - self.send_response(200) - self.end_headers() - self.wfile.write("OK MON GARS") - -# create the object -u = miniupnpc.UPnP() -#print 'inital(default) values :' -#print ' discoverdelay', u.discoverdelay -#print ' lanaddr', u.lanaddr -#print ' multicastif', u.multicastif -#print ' minissdpdsocket', u.minissdpdsocket -u.discoverdelay = 200; - -try: - print 'Discovering... delay=%ums' % u.discoverdelay - ndevices = u.discover() - print ndevices, 'device(s) detected' - - # select an igd - u.selectigd() - # display information about the IGD and the internet connection - print 'local ip address :', u.lanaddr - externalipaddress = u.externalipaddress() - print 'external ip address :', externalipaddress - print u.statusinfo(), u.connectiontype() - - #instanciate a HTTPd object. The port is assigned by the system. - httpd = BaseHTTPServer.HTTPServer((u.lanaddr, 0), handler_class) - eport = httpd.server_port - - # find a free port for the redirection - r = u.getspecificportmapping(eport, 'TCP') - while r != None and eport < 65536: - eport = eport + 1 - r = u.getspecificportmapping(eport, 'TCP') - - print 'trying to redirect %s port %u TCP => %s port %u TCP' % (externalipaddress, eport, u.lanaddr, httpd.server_port) - - b = u.addportmapping(eport, 'TCP', u.lanaddr, httpd.server_port, - 'UPnP IGD Tester port %u' % eport, '') - if b: - print 'Success. Now waiting for some HTTP request on http://%s:%u' % (externalipaddress ,eport) - try: - httpd.handle_request() - httpd.server_close() - except KeyboardInterrupt, details: - print "CTRL-C exception!", details - b = u.deleteportmapping(eport, 'TCP') - if b: - print 'Successfully deleted port mapping' - else: - print 'Failed to remove port mapping' - else: - print 'Failed' - - httpd.server_close() - -except Exception, e: - print 'Exception :', e diff --git a/src/contrib/miniupnpc/testupnpreplyparse.c b/src/contrib/miniupnpc/testupnpreplyparse.c deleted file mode 100644 index 7ba7131..0000000 --- a/src/contrib/miniupnpc/testupnpreplyparse.c +++ /dev/null @@ -1,96 +0,0 @@ -/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2014 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ -#include -#include -#include -#include "upnpreplyparse.h" - -int -test_parsing(const char * buf, int len, FILE * f) -{ - char line[1024]; - struct NameValueParserData pdata; - int ok = 1; - ParseNameValue(buf, len, &pdata); - /* check result */ - if(f != NULL) - { - while(fgets(line, sizeof(line), f)) - { - char * value; - char * equal; - char * parsedvalue; - int l; - l = strlen(line); - while((l > 0) && ((line[l-1] == '\r') || (line[l-1] == '\n'))) - line[--l] = '\0'; - /* skip empty lines */ - if(l == 0) - continue; - equal = strchr(line, '='); - if(equal == NULL) - { - fprintf(stderr, "Warning, line does not contain '=' : %s\n", line); - continue; - } - *equal = '\0'; - value = equal + 1; - parsedvalue = GetValueFromNameValueList(&pdata, line); - if((parsedvalue == NULL) || (strcmp(parsedvalue, value) != 0)) - { - fprintf(stderr, "Element <%s> : expecting value '%s', got '%s'\n", - line, value, parsedvalue ? parsedvalue : ""); - ok = 0; - } - } - } - ClearNameValueList(&pdata); - return ok; -} - -int main(int argc, char * * argv) -{ - FILE * f; - char buffer[4096]; - int l; - int ok; - - if(argc<2) - { - fprintf(stderr, "Usage: %s file.xml [file.namevalues]\n", argv[0]); - return 1; - } - f = fopen(argv[1], "r"); - if(!f) - { - fprintf(stderr, "Error : can not open file %s\n", argv[1]); - return 2; - } - l = fread(buffer, 1, sizeof(buffer)-1, f); - fclose(f); - f = NULL; - buffer[l] = '\0'; - if(argc > 2) - { - f = fopen(argv[2], "r"); - if(!f) - { - fprintf(stderr, "Error : can not open file %s\n", argv[2]); - return 2; - } - } -#ifdef DEBUG - DisplayNameValueList(buffer, l); -#endif - ok = test_parsing(buffer, l, f); - if(f) - { - fclose(f); - } - return ok ? 0 : 3; -} - diff --git a/src/contrib/miniupnpc/testupnpreplyparse.sh b/src/contrib/miniupnpc/testupnpreplyparse.sh deleted file mode 100644 index 992930b..0000000 --- a/src/contrib/miniupnpc/testupnpreplyparse.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -for f in testreplyparse/*.xml ; do - bf="`dirname $f`/`basename $f .xml`" - if ./testupnpreplyparse $f $bf.namevalue ; then - echo "$f : passed" - else - echo "$f : FAILED" - exit 1 - fi -done - -exit 0 - diff --git a/src/contrib/miniupnpc/updateminiupnpcstrings.sh b/src/contrib/miniupnpc/updateminiupnpcstrings.sh deleted file mode 100644 index dde4354..0000000 --- a/src/contrib/miniupnpc/updateminiupnpcstrings.sh +++ /dev/null @@ -1,53 +0,0 @@ -#! /bin/sh -# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $ -# project miniupnp : http://miniupnp.free.fr/ -# (c) 2009 Thomas Bernard - -FILE=miniupnpcstrings.h -TMPFILE=miniupnpcstrings.h.tmp -TEMPLATE_FILE=${FILE}.in - -# detecting the OS name and version -OS_NAME=`uname -s` -OS_VERSION=`uname -r` -if [ -f /etc/debian_version ]; then - OS_NAME=Debian - OS_VERSION=`cat /etc/debian_version` -fi -# use lsb_release (Linux Standard Base) when available -LSB_RELEASE=`which lsb_release` -if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then - OS_NAME=`${LSB_RELEASE} -i -s` - OS_VERSION=`${LSB_RELEASE} -r -s` - case $OS_NAME in - Debian) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - Ubuntu) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - esac -fi - -# on AmigaOS 3, uname -r returns "unknown", so we use uname -v -if [ "$OS_NAME" = "AmigaOS" ]; then - if [ "$OS_VERSION" = "unknown" ]; then - OS_VERSION=`uname -v` - fi -fi - -echo "Detected OS [$OS_NAME] version [$OS_VERSION]" -MINIUPNPC_VERSION=`cat VERSION` -echo "MiniUPnPc version [${MINIUPNPC_VERSION}]" - -EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|" -#echo $EXPR -test -f ${FILE}.in -echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE." -sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE - -EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|" -echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE." -sed -e "$EXPR" < $TMPFILE > $FILE -rm $TMPFILE - diff --git a/src/contrib/miniupnpc/upnpc.c b/src/contrib/miniupnpc/upnpc.c deleted file mode 100644 index 70c9a54..0000000 --- a/src/contrib/miniupnpc/upnpc.c +++ /dev/null @@ -1,720 +0,0 @@ -/* $Id: upnpc.c,v 1.102 2014/02/05 17:27:14 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include -#include -#include -#include -#ifdef _WIN32 -#include -#define snprintf _snprintf -#else -/* for IPPROTO_TCP / IPPROTO_UDP */ -#include -#endif -#include "miniwget.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "upnperrors.h" - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto) -{ - static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; - static const char proto_udp[4] = { 'U', 'D', 'P', 0}; - int i, b; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_tcp[i]) - || (proto[i] == (proto_tcp[i] | 32)) ); - if(b) - return proto_tcp; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_udp[i]) - || (proto[i] == (proto_udp[i] | 32)) ); - if(b) - return proto_udp; - return 0; -} - -static void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - char externalIPAddress[40]; - char connectionType[64]; - char status[64]; - char lastconnerr[64]; - unsigned int uptime; - unsigned int brUp, brDown; - time_t timenow, timestarted; - int r; - if(UPNP_GetConnectionTypeInfo(urls->controlURL, - data->first.servicetype, - connectionType) != UPNPCOMMAND_SUCCESS) - printf("GetConnectionTypeInfo failed.\n"); - else - printf("Connection Type : %s\n", connectionType); - if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, - status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) - printf("GetStatusInfo failed.\n"); - else - printf("Status : %s, uptime=%us, LastConnectionError : %s\n", - status, uptime, lastconnerr); - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); - if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, - &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { - printf("GetLinkLayerMaxBitRates failed.\n"); - } else { - printf("MaxBitRateDown : %u bps", brDown); - if(brDown >= 1000000) { - printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); - } else if(brDown >= 1000) { - printf(" (%u Kbps)", brDown / 1000); - } - printf(" MaxBitRateUp %u bps", brUp); - if(brUp >= 1000000) { - printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); - } else if(brUp >= 1000) { - printf(" (%u Kbps)", brUp / 1000); - } - printf("\n"); - } - r = UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) { - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - } else { - printf("ExternalIPAddress = %s\n", externalIPAddress); - } -} - -static void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - DisplayInfos(urls, data); - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -static void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - char index[6]; - char intClient[40]; - char intPort[6]; - char extPort[6]; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; - /*unsigned int num=0; - UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); - printf("PortMappingNumberOfEntries : %u\n", num);*/ - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - do { - snprintf(index, 6, "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(urls->controlURL, - data->first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, - rHost, duration); - if(r==0) - /* - printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" - " desc='%s' rHost='%s'\n", - i, protocol, extPort, intClient, intPort, - enabled, duration, - desc, rHost); - */ - printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", - i, protocol, extPort, intClient, intPort, - desc, rHost, duration); - else - printf("GetGenericPortMappingEntry() returned %d (%s)\n", - r, strupnperror(r)); - i++; - } while(r==0); -} - -static void NewListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - struct PortMappingParserData pdata; - struct PortMapping * pm; - - memset(&pdata, 0, sizeof(struct PortMappingParserData)); - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "TCP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "UDP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } -} - -/* Test function - * 1 - get connection type - * 2 - get extenal ip address - * 3 - Add port mapping - * 4 - get this port mapping from the IGD */ -static void SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char * leaseDuration, - const char * description) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char duration[16]; - int r; - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return; - } - - UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else - printf("GetExternalIPAddress failed.\n"); - - r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration); - if(r!=UPNPCOMMAND_SUCCESS) - printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - - if(intClient[0]) { - printf("InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } -} - -static void -RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto) -{ - int r; - if(!proto || !eport) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return; - } - r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0); - printf("UPNP_DeletePortMapping() returned : %d\n", r); -} - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - int firewallEnabled = 0, inboundPinholeAllowed = 0; - - UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); - printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); - printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); - - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -/* Test function - * 1 - Add pinhole - * 2 - Check if pinhole is working from the IGD side */ -static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto, const char * lease_time) -{ - char uniqueID[8]; - /*int isWorking = 0;*/ - int r; - char proto_tmp[8]; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - if(atoi(proto) == 0) - { - const char * protocol; - protocol = protofix(proto); - if(protocol && (strcmp("TCP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP); - proto = proto_tmp; - } - else if(protocol && (strcmp("UDP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP); - proto = proto_tmp; - } - else - { - fprintf(stderr, "invalid protocol\n"); - return; - } - } - r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); - if(r!=UPNPCOMMAND_SUCCESS) - printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - remoteaddr, eport, intaddr, iport, r, strupnperror(r)); - else - { - printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", - remoteaddr, eport, intaddr, iport, uniqueID); - /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ - } -} - -/* Test function - * 1 - Check if pinhole is working from the IGD side - * 2 - Update pinhole */ -static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, - const char * uniqueID, const char * lease_time) -{ - int isWorking = 0; - int r; - - if(!uniqueID || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - if(isWorking || r==709) - { - r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); - printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); - if(r!=UPNPCOMMAND_SUCCESS) - printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); - } -} - -/* Test function - * Get pinhole timeout - */ -static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto) -{ - int timeout = 0; - int r; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - - r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - intaddr, iport, remoteaddr, eport, r, strupnperror(r)); - else - printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); -} - -static void -GetPinholePackets(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, pinholePackets = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); -} - -static void -CheckPinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, isWorking = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); -} - -static void -RemovePinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); - printf("UPNP_DeletePinhole() returned : %d\n", r); -} - - -/* sample upnp client program */ -int main(int argc, char ** argv) -{ - char command = 0; - char ** commandargv = 0; - int commandargc = 0; - struct UPNPDev * devlist = 0; - char lanaddr[64]; /* my ip address on the LAN */ - int i; - const char * rootdescurl = 0; - const char * multicastif = 0; - const char * minissdpdpath = 0; - int retcode = 0; - int error = 0; - int ipv6 = 0; - const char * description = 0; - -#ifdef _WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n"); - printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" - "for more information.\n"); - /* command line processing */ - for(i=1; ipNext) - { - printf(" desc: %s\n st: %s\n\n", - device->descURL, device->st); - } - } - else - { - printf("upnpDiscover() error code=%d\n", error); - } - i = 1; - if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) - || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) - { - switch(i) { - case 1: - printf("Found valid IGD : %s\n", urls.controlURL); - break; - case 2: - printf("Found a (not connected?) IGD : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - case 3: - printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - default: - printf("Found device (igd ?) : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - } - printf("Local LAN ip address : %s\n", lanaddr); - #if 0 - printf("getting \"%s\"\n", urls.ipcondescURL); - descXML = miniwget(urls.ipcondescURL, &descXMLsize); - if(descXML) - { - /*fwrite(descXML, 1, descXMLsize, stdout);*/ - free(descXML); descXML = NULL; - } - #endif - - switch(command) - { - case 'l': - DisplayInfos(&urls, &data); - ListRedirections(&urls, &data); - break; - case 'L': - NewListRedirections(&urls, &data); - break; - case 'a': - SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)?commandargv[4]:"0", - description); - break; - case 'd': - for(i=0; i -#include -#include -#include "upnpcommands.h" -#include "miniupnpc.h" -#include "portlistingparse.h" - -static UNSIGNED_INTEGER -my_atoui(const char * s) -{ - return s ? ((UNSIGNED_INTEGER)STRTOUI(s, NULL, 0)) : 0; -} - -/* - * */ -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesSent(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalBytesSent", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesReceived(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalBytesReceived", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsSent(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalPacketsSent", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* - * */ -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsReceived(const char * controlURL, - const char * servicetype) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - unsigned int r = 0; - char * p; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetTotalPacketsReceived", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived"); - r = my_atoui(p); - ClearNameValueList(&pdata); - return r; -} - -/* UPNP_GetStatusInfo() call the corresponding UPNP method - * returns the current status and uptime */ -LIBSPEC int -UPNP_GetStatusInfo(const char * controlURL, - const char * servicetype, - char * status, - unsigned int * uptime, - char * lastconnerror) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - char * up; - char * err; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!status && !uptime) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetStatusInfo", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - /*DisplayNameValueList(buffer, bufsize);*/ - free(buffer); buffer = NULL; - up = GetValueFromNameValueList(&pdata, "NewUptime"); - p = GetValueFromNameValueList(&pdata, "NewConnectionStatus"); - err = GetValueFromNameValueList(&pdata, "NewLastConnectionError"); - if(p && up) - ret = UPNPCOMMAND_SUCCESS; - - if(status) { - if(p){ - strncpy(status, p, 64 ); - status[63] = '\0'; - }else - status[0]= '\0'; - } - - if(uptime) { - if(up) - sscanf(up,"%u",uptime); - else - uptime = 0; - } - - if(lastconnerror) { - if(err) { - strncpy(lastconnerror, err, 64 ); - lastconnerror[63] = '\0'; - } else - lastconnerror[0] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method - * returns the connection type */ -LIBSPEC int -UPNP_GetConnectionTypeInfo(const char * controlURL, - const char * servicetype, - char * connectionType) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!connectionType) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetConnectionTypeInfo", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "NewConnectionType"); - /*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/ - /* PossibleConnectionTypes will have several values.... */ - if(p) { - strncpy(connectionType, p, 64 ); - connectionType[63] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - connectionType[0] = '\0'; - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method. - * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth. - * One of the values can be null - * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only - * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */ -LIBSPEC int -UPNP_GetLinkLayerMaxBitRates(const char * controlURL, - const char * servicetype, - unsigned int * bitrateDown, - unsigned int * bitrateUp) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - char * down; - char * up; - char * p; - - if(!bitrateDown && !bitrateUp) - return UPNPCOMMAND_INVALID_ARGS; - - /* shouldn't we use GetCommonLinkProperties ? */ - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetCommonLinkProperties", 0, &bufsize))) { - /*"GetLinkLayerMaxBitRates", 0, &bufsize);*/ - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - /*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/ - /*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/ - down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate"); - up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate"); - /*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/ - /*GetValueFromNameValueList(&pdata, "NewPhysicalLinkStatus");*/ - if(down && up) - ret = UPNPCOMMAND_SUCCESS; - - if(bitrateDown) { - if(down) - sscanf(down,"%u",bitrateDown); - else - *bitrateDown = 0; - } - - if(bitrateUp) { - if(up) - sscanf(up,"%u",bitrateUp); - else - *bitrateUp = 0; - } - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - - -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - */ -LIBSPEC int -UPNP_GetExternalIPAddress(const char * controlURL, - const char * servicetype, - char * extIpAdd) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!extIpAdd || !controlURL || !servicetype) - return UPNPCOMMAND_INVALID_ARGS; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetExternalIPAddress", 0, &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - /*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/ - p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress"); - if(p) { - strncpy(extIpAdd, p, 16 ); - extIpAdd[15] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - extIpAdd[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -LIBSPEC int -UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration) -{ - struct UPNParg * AddPortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!inPort || !inClient || !proto || !extPort) - return UPNPCOMMAND_INVALID_ARGS; - - AddPortMappingArgs = calloc(9, sizeof(struct UPNParg)); - AddPortMappingArgs[0].elt = "NewRemoteHost"; - AddPortMappingArgs[0].val = remoteHost; - AddPortMappingArgs[1].elt = "NewExternalPort"; - AddPortMappingArgs[1].val = extPort; - AddPortMappingArgs[2].elt = "NewProtocol"; - AddPortMappingArgs[2].val = proto; - AddPortMappingArgs[3].elt = "NewInternalPort"; - AddPortMappingArgs[3].val = inPort; - AddPortMappingArgs[4].elt = "NewInternalClient"; - AddPortMappingArgs[4].val = inClient; - AddPortMappingArgs[5].elt = "NewEnabled"; - AddPortMappingArgs[5].val = "1"; - AddPortMappingArgs[6].elt = "NewPortMappingDescription"; - AddPortMappingArgs[6].val = desc?desc:"libminiupnpc"; - AddPortMappingArgs[7].elt = "NewLeaseDuration"; - AddPortMappingArgs[7].val = leaseDuration?leaseDuration:"0"; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddPortMapping", AddPortMappingArgs, - &bufsize))) { - free(AddPortMappingArgs); - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - /*buffer[bufsize] = '\0';*/ - /*puts(buffer);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - free(AddPortMappingArgs); - return ret; -} - -LIBSPEC int -UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost) -{ - /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePortMappingArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!extPort || !proto) - return UPNPCOMMAND_INVALID_ARGS; - - DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg)); - DeletePortMappingArgs[0].elt = "NewRemoteHost"; - DeletePortMappingArgs[0].val = remoteHost; - DeletePortMappingArgs[1].elt = "NewExternalPort"; - DeletePortMappingArgs[1].val = extPort; - DeletePortMappingArgs[2].elt = "NewProtocol"; - DeletePortMappingArgs[2].val = proto; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePortMapping", - DeletePortMappingArgs, &bufsize))) { - free(DeletePortMappingArgs); - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } else { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - free(DeletePortMappingArgs); - return ret; -} - -LIBSPEC int -UPNP_GetGenericPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; - char * buffer; - int bufsize; - char * p; - int r = UPNPCOMMAND_UNKNOWN_ERROR; - if(!index) - return UPNPCOMMAND_INVALID_ARGS; - intClient[0] = '\0'; - intPort[0] = '\0'; - GetPortMappingArgs = calloc(2, sizeof(struct UPNParg)); - GetPortMappingArgs[0].elt = "NewPortMappingIndex"; - GetPortMappingArgs[0].val = index; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetGenericPortMappingEntry", - GetPortMappingArgs, &bufsize))) { - free(GetPortMappingArgs); - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewRemoteHost"); - if(p && rHost) - { - strncpy(rHost, p, 64); - rHost[63] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewExternalPort"); - if(p && extPort) - { - strncpy(extPort, p, 6); - extPort[5] = '\0'; - r = UPNPCOMMAND_SUCCESS; - } - p = GetValueFromNameValueList(&pdata, "NewProtocol"); - if(p && protocol) - { - strncpy(protocol, p, 4); - protocol[3] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewInternalClient"); - if(p && intClient) - { - strncpy(intClient, p, 16); - intClient[15] = '\0'; - r = 0; - } - p = GetValueFromNameValueList(&pdata, "NewInternalPort"); - if(p && intPort) - { - strncpy(intPort, p, 6); - intPort[5] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewEnabled"); - if(p && enabled) - { - strncpy(enabled, p, 4); - enabled[3] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); - if(p && desc) - { - strncpy(desc, p, 80); - desc[79] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); - if(p && duration) - { - strncpy(duration, p, 16); - duration[15] = '\0'; - } - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - r = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &r); - } - ClearNameValueList(&pdata); - free(GetPortMappingArgs); - return r; -} - -LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char * controlURL, - const char * servicetype, - unsigned int * numEntries) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char* p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetPortMappingNumberOfEntries", 0, - &bufsize))) { - return UPNPCOMMAND_HTTP_ERROR; - } -#ifdef DEBUG - DisplayNameValueList(buffer, bufsize); -#endif - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries"); - if(numEntries && p) { - *numEntries = 0; - sscanf(p, "%u", numEntries); - ret = UPNPCOMMAND_SUCCESS; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - return ret; -} - -/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping - * the result is returned in the intClient and intPort strings - * please provide 16 and 6 bytes of data */ -LIBSPEC int -UPNP_GetSpecificPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * extPort, - const char * proto, - const char * remoteHost, - char * intClient, - char * intPort, - char * desc, - char * enabled, - char * leaseDuration) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPortMappingArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!intPort || !intClient || !extPort || !proto) - return UPNPCOMMAND_INVALID_ARGS; - - GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); - GetPortMappingArgs[0].elt = "NewRemoteHost"; - GetPortMappingArgs[0].val = remoteHost; - GetPortMappingArgs[1].elt = "NewExternalPort"; - GetPortMappingArgs[1].val = extPort; - GetPortMappingArgs[2].elt = "NewProtocol"; - GetPortMappingArgs[2].val = proto; - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetSpecificPortMappingEntry", - GetPortMappingArgs, &bufsize))) { - free(GetPortMappingArgs); - return UPNPCOMMAND_HTTP_ERROR; - } - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "NewInternalClient"); - if(p) { - strncpy(intClient, p, 16); - intClient[15] = '\0'; - ret = UPNPCOMMAND_SUCCESS; - } else - intClient[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "NewInternalPort"); - if(p) { - strncpy(intPort, p, 6); - intPort[5] = '\0'; - } else - intPort[0] = '\0'; - - p = GetValueFromNameValueList(&pdata, "NewEnabled"); - if(p && enabled) { - strncpy(enabled, p, 4); - enabled[3] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription"); - if(p && desc) { - strncpy(desc, p, 80); - desc[79] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "NewLeaseDuration"); - if(p && leaseDuration) - { - strncpy(leaseDuration, p, 16); - leaseDuration[15] = '\0'; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - free(GetPortMappingArgs); - return ret; -} - -/* UPNP_GetListOfPortMappings() - * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. - */ -LIBSPEC int -UPNP_GetListOfPortMappings(const char * controlURL, - const char * servicetype, - const char * startPort, - const char * endPort, - const char * protocol, - const char * numberOfPorts, - struct PortMappingParserData * data) -{ - struct NameValueParserData pdata; - struct UPNParg * GetListOfPortMappingsArgs; - const char * p; - char * buffer; - int bufsize; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!startPort || !endPort || !protocol) - return UPNPCOMMAND_INVALID_ARGS; - - GetListOfPortMappingsArgs = calloc(6, sizeof(struct UPNParg)); - GetListOfPortMappingsArgs[0].elt = "NewStartPort"; - GetListOfPortMappingsArgs[0].val = startPort; - GetListOfPortMappingsArgs[1].elt = "NewEndPort"; - GetListOfPortMappingsArgs[1].val = endPort; - GetListOfPortMappingsArgs[2].elt = "NewProtocol"; - GetListOfPortMappingsArgs[2].val = protocol; - GetListOfPortMappingsArgs[3].elt = "NewManage"; - GetListOfPortMappingsArgs[3].val = "1"; - GetListOfPortMappingsArgs[4].elt = "NewNumberOfPorts"; - GetListOfPortMappingsArgs[4].val = numberOfPorts?numberOfPorts:"1000"; - - if(!(buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetListOfPortMappings", - GetListOfPortMappingsArgs, &bufsize))) { - free(GetListOfPortMappingsArgs); - return UPNPCOMMAND_HTTP_ERROR; - } - free(GetListOfPortMappingsArgs); - - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - /*p = GetValueFromNameValueList(&pdata, "NewPortListing");*/ - /*if(p) { - printf("NewPortListing : %s\n", p); - }*/ - /*printf("NewPortListing(%d chars) : %s\n", - pdata.portListingLength, pdata.portListing);*/ - if(pdata.portListing) - { - /*struct PortMapping * pm; - int i = 0;*/ - ParsePortListing(pdata.portListing, pdata.portListingLength, - data); - ret = UPNPCOMMAND_SUCCESS; - /* - for(pm = data->head.lh_first; pm != NULL; pm = pm->entries.le_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s'\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost); - i++; - } - */ - /*FreePortListing(&data);*/ - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - - /*printf("%.*s", bufsize, buffer);*/ - - return ret; -} - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -LIBSPEC int -UPNP_GetFirewallStatus(const char * controlURL, - const char * servicetype, - int * firewallEnabled, - int * inboundPinholeAllowed) -{ - struct NameValueParserData pdata; - char * buffer; - int bufsize; - char * fe, *ipa, *p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!firewallEnabled || !inboundPinholeAllowed) - return UPNPCOMMAND_INVALID_ARGS; - - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetFirewallStatus", 0, &bufsize); - if(!buffer) { - return UPNPCOMMAND_HTTP_ERROR; - } - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - fe = GetValueFromNameValueList(&pdata, "FirewallEnabled"); - ipa = GetValueFromNameValueList(&pdata, "InboundPinholeAllowed"); - if(ipa && fe) - ret = UPNPCOMMAND_SUCCESS; - if(fe) - *firewallEnabled = my_atoui(fe); - /*else - *firewallEnabled = 0;*/ - if(ipa) - *inboundPinholeAllowed = my_atoui(ipa); - /*else - *inboundPinholeAllowed = 0;*/ - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - ClearNameValueList(&pdata); - return ret; -} - -LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - int * opTimeout) -{ - struct UPNParg * GetOutboundPinholeTimeoutArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - char * p; - int ret; - - if(!intPort || !intClient || !proto || !remotePort || !remoteHost) - return UPNPCOMMAND_INVALID_ARGS; - - GetOutboundPinholeTimeoutArgs = calloc(6, sizeof(struct UPNParg)); - GetOutboundPinholeTimeoutArgs[0].elt = "RemoteHost"; - GetOutboundPinholeTimeoutArgs[0].val = remoteHost; - GetOutboundPinholeTimeoutArgs[1].elt = "RemotePort"; - GetOutboundPinholeTimeoutArgs[1].val = remotePort; - GetOutboundPinholeTimeoutArgs[2].elt = "Protocol"; - GetOutboundPinholeTimeoutArgs[2].val = proto; - GetOutboundPinholeTimeoutArgs[3].elt = "InternalPort"; - GetOutboundPinholeTimeoutArgs[3].val = intPort; - GetOutboundPinholeTimeoutArgs[4].elt = "InternalClient"; - GetOutboundPinholeTimeoutArgs[4].val = intClient; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - p = GetValueFromNameValueList(&pdata, "OutboundPinholeTimeout"); - if(p) - *opTimeout = my_atoui(p); - } - ClearNameValueList(&pdata); - free(GetOutboundPinholeTimeoutArgs); - return ret; -} - -LIBSPEC int -UPNP_AddPinhole(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - const char * leaseTime, - char * uniqueID) -{ - struct UPNParg * AddPinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - char * p; - int ret; - - if(!intPort || !intClient || !proto || !remoteHost || !remotePort || !leaseTime) - return UPNPCOMMAND_INVALID_ARGS; - - AddPinholeArgs = calloc(7, sizeof(struct UPNParg)); - /* RemoteHost can be wilcarded */ - if(strncmp(remoteHost, "empty", 5)==0) - { - AddPinholeArgs[0].elt = "RemoteHost"; - AddPinholeArgs[0].val = ""; - } - else - { - AddPinholeArgs[0].elt = "RemoteHost"; - AddPinholeArgs[0].val = remoteHost; - } - AddPinholeArgs[1].elt = "RemotePort"; - AddPinholeArgs[1].val = remotePort; - AddPinholeArgs[2].elt = "Protocol"; - AddPinholeArgs[2].val = proto; - AddPinholeArgs[3].elt = "InternalPort"; - AddPinholeArgs[3].val = intPort; - if(strncmp(intClient, "empty", 5)==0) - { - AddPinholeArgs[4].elt = "InternalClient"; - AddPinholeArgs[4].val = ""; - } - else - { - AddPinholeArgs[4].elt = "InternalClient"; - AddPinholeArgs[4].val = intClient; - } - AddPinholeArgs[5].elt = "LeaseTime"; - AddPinholeArgs[5].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "AddPinhole", AddPinholeArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - p = GetValueFromNameValueList(&pdata, "UniqueID"); - if(p) - { - strncpy(uniqueID, p, 8); - uniqueID[7] = '\0'; - } - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - /*printf("AddPortMapping errorCode = '%s'\n", resVal);*/ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - free(AddPinholeArgs); - return ret; -} - -LIBSPEC int -UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, - const char * uniqueID, - const char * leaseTime) -{ - struct UPNParg * UpdatePinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!uniqueID || !leaseTime) - return UPNPCOMMAND_INVALID_ARGS; - - UpdatePinholeArgs = calloc(3, sizeof(struct UPNParg)); - UpdatePinholeArgs[0].elt = "UniqueID"; - UpdatePinholeArgs[0].val = uniqueID; - UpdatePinholeArgs[1].elt = "NewLeaseTime"; - UpdatePinholeArgs[1].val = leaseTime; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "UpdatePinhole", UpdatePinholeArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - /*printf("AddPortMapping errorCode = '%s'\n", resVal); */ - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - free(UpdatePinholeArgs); - return ret; -} - -LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID) -{ - /*struct NameValueParserData pdata;*/ - struct UPNParg * DeletePinholeArgs; - char * buffer; - int bufsize; - struct NameValueParserData pdata; - const char * resVal; - int ret; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - DeletePinholeArgs = calloc(2, sizeof(struct UPNParg)); - DeletePinholeArgs[0].elt = "UniqueID"; - DeletePinholeArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "DeletePinhole", DeletePinholeArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - /*DisplayNameValueList(buffer, bufsize);*/ - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - resVal = GetValueFromNameValueList(&pdata, "errorCode"); - if(resVal) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(resVal, "%d", &ret); - } - else - { - ret = UPNPCOMMAND_SUCCESS; - } - ClearNameValueList(&pdata); - free(DeletePinholeArgs); - return ret; -} - -LIBSPEC int -UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, - const char * uniqueID, int * isWorking) -{ - struct NameValueParserData pdata; - struct UPNParg * CheckPinholeWorkingArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - CheckPinholeWorkingArgs = calloc(4, sizeof(struct UPNParg)); - CheckPinholeWorkingArgs[0].elt = "UniqueID"; - CheckPinholeWorkingArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "CheckPinholeWorking", CheckPinholeWorkingArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "IsWorking"); - if(p) - { - *isWorking=my_atoui(p); - ret = UPNPCOMMAND_SUCCESS; - } - else - *isWorking = 0; - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - free(CheckPinholeWorkingArgs); - return ret; -} - -LIBSPEC int -UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, - const char * uniqueID, int * packets) -{ - struct NameValueParserData pdata; - struct UPNParg * GetPinholePacketsArgs; - char * buffer; - int bufsize; - char * p; - int ret = UPNPCOMMAND_UNKNOWN_ERROR; - - if(!uniqueID) - return UPNPCOMMAND_INVALID_ARGS; - - GetPinholePacketsArgs = calloc(4, sizeof(struct UPNParg)); - GetPinholePacketsArgs[0].elt = "UniqueID"; - GetPinholePacketsArgs[0].val = uniqueID; - buffer = simpleUPnPcommand(-1, controlURL, servicetype, - "GetPinholePackets", GetPinholePacketsArgs, &bufsize); - if(!buffer) - return UPNPCOMMAND_HTTP_ERROR; - ParseNameValue(buffer, bufsize, &pdata); - free(buffer); buffer = NULL; - - p = GetValueFromNameValueList(&pdata, "PinholePackets"); - if(p) - { - *packets=my_atoui(p); - ret = UPNPCOMMAND_SUCCESS; - } - - p = GetValueFromNameValueList(&pdata, "errorCode"); - if(p) - { - ret = UPNPCOMMAND_UNKNOWN_ERROR; - sscanf(p, "%d", &ret); - } - - ClearNameValueList(&pdata); - free(GetPinholePacketsArgs); - return ret; -} - - diff --git a/src/contrib/miniupnpc/upnpcommands.h b/src/contrib/miniupnpc/upnpcommands.h deleted file mode 100644 index 93d9f3d..0000000 --- a/src/contrib/miniupnpc/upnpcommands.h +++ /dev/null @@ -1,293 +0,0 @@ -/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */ -/* Miniupnp project : http://miniupnp.free.fr/ - * Author : Thomas Bernard - * Copyright (c) 2005-2014 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided within this distribution */ -#ifndef UPNPCOMMANDS_H_INCLUDED -#define UPNPCOMMANDS_H_INCLUDED - -#include "upnpreplyparse.h" -#include "portlistingparse.h" -#include "declspec.h" -#include "miniupnpctypes.h" - -/* MiniUPnPc return codes : */ -#define UPNPCOMMAND_SUCCESS (0) -#define UPNPCOMMAND_UNKNOWN_ERROR (-1) -#define UPNPCOMMAND_INVALID_ARGS (-2) -#define UPNPCOMMAND_HTTP_ERROR (-3) - -#ifdef __cplusplus -extern "C" { -#endif - -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesSent(const char * controlURL, - const char * servicetype); - -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalBytesReceived(const char * controlURL, - const char * servicetype); - -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsSent(const char * controlURL, - const char * servicetype); - -LIBSPEC UNSIGNED_INTEGER -UPNP_GetTotalPacketsReceived(const char * controlURL, - const char * servicetype); - -/* UPNP_GetStatusInfo() - * status and lastconnerror are 64 byte buffers - * Return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -LIBSPEC int -UPNP_GetStatusInfo(const char * controlURL, - const char * servicetype, - char * status, - unsigned int * uptime, - char * lastconnerror); - -/* UPNP_GetConnectionTypeInfo() - * argument connectionType is a 64 character buffer - * Return Values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error code */ -LIBSPEC int -UPNP_GetConnectionTypeInfo(const char * controlURL, - const char * servicetype, - char * connectionType); - -/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. - * if the third arg is not null the value is copied to it. - * at least 16 bytes must be available - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR Either an UPnP error code or an unknown error. - * - * possible UPnP Errors : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. */ -LIBSPEC int -UPNP_GetExternalIPAddress(const char * controlURL, - const char * servicetype, - char * extIpAdd); - -/* UPNP_GetLinkLayerMaxBitRates() - * call WANCommonInterfaceConfig:1#GetCommonLinkProperties - * - * return values : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ -LIBSPEC int -UPNP_GetLinkLayerMaxBitRates(const char* controlURL, - const char* servicetype, - unsigned int * bitrateDown, - unsigned int * bitrateUp); - -/* UPNP_AddPortMapping() - * if desc is NULL, it will be defaulted to "libminiupnpc" - * remoteHost is usually NULL because IGD don't support it. - * - * Return values : - * 0 : SUCCESS - * NON ZERO : ERROR. Either an UPnP error code or an unknown error. - * - * List of possible UPnP errors for AddPortMapping : - * errorCode errorDescription (short) - Description (long) - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization and - * the sender was not authorized. - * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be - * wild-carded - * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded - * 718 ConflictInMappingEntry - The port mapping entry specified conflicts - * with a mapping assigned previously to another client - * 724 SamePortValuesRequired - Internal and External port values - * must be the same - * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports - * permanent lease times on port mappings - * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard - * and cannot be a specific IP address or DNS name - * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value - * 728 NoPortMapsAvailable - There are not enough free ports available to - * complete port mapping. - * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed - * due to conflict with other mechanisms. - * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded - */ -LIBSPEC int -UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - const char * extPort, - const char * inPort, - const char * inClient, - const char * desc, - const char * proto, - const char * remoteHost, - const char * leaseDuration); - -/* UPNP_DeletePortMapping() - * Use same argument values as what was used for AddPortMapping(). - * remoteHost is usually NULL because IGD don't support it. - * Return Values : - * 0 : SUCCESS - * NON ZERO : error. Either an UPnP error code or an undefined error. - * - * List of possible UPnP errors for DeletePortMapping : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array */ -LIBSPEC int -UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, - const char * extPort, const char * proto, - const char * remoteHost); - -/* UPNP_GetPortMappingNumberOfEntries() - * not supported by all routers */ -LIBSPEC int -UPNP_GetPortMappingNumberOfEntries(const char* controlURL, - const char* servicetype, - unsigned int * num); - -/* UPNP_GetSpecificPortMappingEntry() - * retrieves an existing port mapping - * params : - * in extPort - * in proto - * in remoteHost - * out intClient (16 bytes) - * out intPort (6 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out leaseDuration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * List of possible UPnP errors for _GetSpecificPortMappingEntry : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 501 Action Failed - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 714 NoSuchEntryInArray - The specified value does not exist in the array. - */ -LIBSPEC int -UPNP_GetSpecificPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * extPort, - const char * proto, - const char * remoteHost, - char * intClient, - char * intPort, - char * desc, - char * enabled, - char * leaseDuration); - -/* UPNP_GetGenericPortMappingEntry() - * params : - * in index - * out extPort (6 bytes) - * out intClient (16 bytes) - * out intPort (6 bytes) - * out protocol (4 bytes) - * out desc (80 bytes) - * out enabled (4 bytes) - * out rHost (64 bytes) - * out duration (16 bytes) - * - * return value : - * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. - * - * Possible UPNP Error codes : - * 402 Invalid Args - See UPnP Device Architecture section on Control. - * 606 Action not authorized - The action requested REQUIRES authorization - * and the sender was not authorized. - * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds - */ -LIBSPEC int -UPNP_GetGenericPortMappingEntry(const char * controlURL, - const char * servicetype, - const char * index, - char * extPort, - char * intClient, - char * intPort, - char * protocol, - char * desc, - char * enabled, - char * rHost, - char * duration); - -/* UPNP_GetListOfPortMappings() Available in IGD v2 - * - * - * Possible UPNP Error codes : - * 606 Action not Authorized - * 730 PortMappingNotFound - no port mapping is found in the specified range. - * 733 InconsistantParameters - NewStartPort and NewEndPort values are not - * consistent. - */ -LIBSPEC int -UPNP_GetListOfPortMappings(const char * controlURL, - const char * servicetype, - const char * startPort, - const char * endPort, - const char * protocol, - const char * numberOfPorts, - struct PortMappingParserData * data); - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -LIBSPEC int -UPNP_GetFirewallStatus(const char * controlURL, - const char * servicetype, - int * firewallEnabled, - int * inboundPinholeAllowed); - -LIBSPEC int -UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - int * opTimeout); - -LIBSPEC int -UPNP_AddPinhole(const char * controlURL, const char * servicetype, - const char * remoteHost, - const char * remotePort, - const char * intClient, - const char * intPort, - const char * proto, - const char * leaseTime, - char * uniqueID); - -LIBSPEC int -UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, - const char * uniqueID, - const char * leaseTime); - -LIBSPEC int -UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); - -LIBSPEC int -UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, - const char * uniqueID, int * isWorking); - -LIBSPEC int -UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, - const char * uniqueID, int * packets); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnpc/upnperrors.c b/src/contrib/miniupnpc/upnperrors.c deleted file mode 100644 index 644098f..0000000 --- a/src/contrib/miniupnpc/upnperrors.c +++ /dev/null @@ -1,104 +0,0 @@ -/* $Id: upnperrors.c,v 1.6 2012/03/15 01:02:03 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2007 Thomas Bernard - * All Right reserved. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include -#include "upnperrors.h" -#include "upnpcommands.h" -#include "miniupnpc.h" - -const char * strupnperror(int err) -{ - const char * s = NULL; - switch(err) { - case UPNPCOMMAND_SUCCESS: - s = "Success"; - break; - case UPNPCOMMAND_UNKNOWN_ERROR: - s = "Miniupnpc Unknown Error"; - break; - case UPNPCOMMAND_INVALID_ARGS: - s = "Miniupnpc Invalid Arguments"; - break; - case UPNPDISCOVER_SOCKET_ERROR: - s = "Miniupnpc Socket error"; - break; - case UPNPDISCOVER_MEMORY_ERROR: - s = "Miniupnpc Memory allocation error"; - break; - case 401: - s = "Invalid Action"; - break; - case 402: - s = "Invalid Args"; - break; - case 501: - s = "Action Failed"; - break; - case 606: - s = "Action not authorized"; - break; - case 701: - s = "PinholeSpaceExhausted"; - break; - case 702: - s = "FirewallDisabled"; - break; - case 703: - s = "InboundPinholeNotAllowed"; - break; - case 704: - s = "NoSuchEntry"; - break; - case 705: - s = "ProtocolNotSupported"; - break; - case 706: - s = "InternalPortWildcardingNotAllowed"; - break; - case 707: - s = "ProtocolWildcardingNotAllowed"; - break; - case 708: - s = "WildcardNotPermittedInSrcIP"; - break; - case 709: - s = "NoPacketSent"; - break; - case 713: - s = "SpecifiedArrayIndexInvalid"; - break; - case 714: - s = "NoSuchEntryInArray"; - break; - case 715: - s = "WildCardNotPermittedInSrcIP"; - break; - case 716: - s = "WildCardNotPermittedInExtPort"; - break; - case 718: - s = "ConflictInMappingEntry"; - break; - case 724: - s = "SamePortValuesRequired"; - break; - case 725: - s = "OnlyPermanentLeasesSupported"; - break; - case 726: - s = "RemoteHostOnlySupportsWildcard"; - break; - case 727: - s = "ExternalPortOnlySupportsWildcard"; - break; - default: - s = "UnknownError"; - break; - } - return s; -} diff --git a/src/contrib/miniupnpc/upnperrors.h b/src/contrib/miniupnpc/upnperrors.h deleted file mode 100644 index 077d693..0000000 --- a/src/contrib/miniupnpc/upnperrors.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: upnperrors.h,v 1.4 2012/09/27 15:42:11 nanard Exp $ */ -/* (c) 2007 Thomas Bernard - * All rights reserved. - * MiniUPnP Project. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef UPNPERRORS_H_INCLUDED -#define UPNPERRORS_H_INCLUDED - -#include "declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* strupnperror() - * Return a string description of the UPnP error code - * or NULL for undefinded errors */ -LIBSPEC const char * strupnperror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/miniupnpc/upnpreplyparse.c b/src/contrib/miniupnpc/upnpreplyparse.c deleted file mode 100644 index dafa263..0000000 --- a/src/contrib/miniupnpc/upnpreplyparse.c +++ /dev/null @@ -1,183 +0,0 @@ -/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#include -#include -#include - -#include "upnpreplyparse.h" -#include "minixml.h" - -static void -NameValueParserStartElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - data->topelt = 1; - if(l>63) - l = 63; - memcpy(data->curelt, name, l); - data->curelt[l] = '\0'; - data->cdata = NULL; - data->cdatalen = 0; -} - -static void -NameValueParserEndElt(void * d, const char * name, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - struct NameValue * nv; - (void)name; - (void)l; - if(!data->topelt) - return; - if(strcmp(data->curelt, "NewPortListing") != 0) - { - int l; - /* standard case. Limited to n chars strings */ - l = data->cdatalen; - nv = malloc(sizeof(struct NameValue)); - if(l>=(int)sizeof(nv->value)) - l = sizeof(nv->value) - 1; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - if(data->cdata != NULL) - { - memcpy(nv->value, data->cdata, l); - nv->value[l] = '\0'; - } - else - { - nv->value[0] = '\0'; - } - LIST_INSERT_HEAD( &(data->head), nv, entries); - } - data->cdata = NULL; - data->cdatalen = 0; - data->topelt = 0; -} - -static void -NameValueParserGetData(void * d, const char * datas, int l) -{ - struct NameValueParserData * data = (struct NameValueParserData *)d; - if(strcmp(data->curelt, "NewPortListing") == 0) - { - /* specific case for NewPortListing which is a XML Document */ - data->portListing = malloc(l + 1); - if(!data->portListing) - { - /* malloc error */ - return; - } - memcpy(data->portListing, datas, l); - data->portListing[l] = '\0'; - data->portListingLength = l; - } - else - { - /* standard case. */ - data->cdata = datas; - data->cdatalen = l; - } -} - -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data) -{ - struct xmlparser parser; - LIST_INIT(&(data->head)); - data->portListing = NULL; - data->portListingLength = 0; - /* init xmlparser object */ - parser.xmlstart = buffer; - parser.xmlsize = bufsize; - parser.data = data; - parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = NameValueParserEndElt; - parser.datafunc = NameValueParserGetData; - parser.attfunc = 0; - parsexml(&parser); -} - -void -ClearNameValueList(struct NameValueParserData * pdata) -{ - struct NameValue * nv; - if(pdata->portListing) - { - free(pdata->portListing); - pdata->portListing = NULL; - pdata->portListingLength = 0; - } - while((nv = pdata->head.lh_first) != NULL) - { - LIST_REMOVE(nv, entries); - free(nv); - } -} - -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - if(strcmp(nv->name, Name) == 0) - p = nv->value; - } - return p; -} - -#if 0 -/* useless now that minixml ignores namespaces by itself */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name) -{ - struct NameValue * nv; - char * p = NULL; - char * pname; - for(nv = pdata->head.lh_first; - (nv != NULL) && (p == NULL); - nv = nv->entries.le_next) - { - pname = strrchr(nv->name, ':'); - if(pname) - pname++; - else - pname = nv->name; - if(strcmp(pname, Name)==0) - p = nv->value; - } - return p; -} -#endif - -/* debug all-in-one function - * do parsing then display to stdout */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize) -{ - struct NameValueParserData pdata; - struct NameValue * nv; - ParseNameValue(buffer, bufsize, &pdata); - for(nv = pdata.head.lh_first; - nv != NULL; - nv = nv->entries.le_next) - { - printf("%s = %s\n", nv->name, nv->value); - } - ClearNameValueList(&pdata); -} -#endif - diff --git a/src/contrib/miniupnpc/upnpreplyparse.h b/src/contrib/miniupnpc/upnpreplyparse.h deleted file mode 100644 index d4e3757..0000000 --- a/src/contrib/miniupnpc/upnpreplyparse.h +++ /dev/null @@ -1,69 +0,0 @@ -/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */ -/* MiniUPnP project - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard - * This software is subject to the conditions detailed - * in the LICENCE file provided within the distribution */ - -#ifndef UPNPREPLYPARSE_H_INCLUDED -#define UPNPREPLYPARSE_H_INCLUDED - -#if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) -#include "bsdqueue.h" -#else -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -struct NameValue { - LIST_ENTRY(NameValue) entries; - char name[64]; - char value[128]; -}; - -struct NameValueParserData { - LIST_HEAD(listhead, NameValue) head; - char curelt[64]; - char * portListing; - int portListingLength; - int topelt; - const char * cdata; - int cdatalen; -}; - -/* ParseNameValue() */ -void -ParseNameValue(const char * buffer, int bufsize, - struct NameValueParserData * data); - -/* ClearNameValueList() */ -void -ClearNameValueList(struct NameValueParserData * pdata); - -/* GetValueFromNameValueList() */ -char * -GetValueFromNameValueList(struct NameValueParserData * pdata, - const char * Name); - -#if 0 -/* GetValueFromNameValueListIgnoreNS() */ -char * -GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, - const char * Name); -#endif - -/* DisplayNameValueList() */ -#ifdef DEBUG -void -DisplayNameValueList(char * buffer, int bufsize); -#endif - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/contrib/miniupnpc/wingenminiupnpcstrings.c b/src/contrib/miniupnpc/wingenminiupnpcstrings.c deleted file mode 100644 index ed289f4..0000000 --- a/src/contrib/miniupnpc/wingenminiupnpcstrings.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id: wingenminiupnpcstrings.c,v 1.3 2012/03/05 19:42:48 nanard Exp $ */ -/* Project: miniupnp - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * Author: Thomas Bernard - * Copyright (c) 2005-2009 Thomas Bernard - * This software is subjects to the conditions detailed - * in the LICENSE file provided within this distribution */ -#include -#include - -/* This program display the Windows version and is used to - * generate the miniupnpcstrings.h - * wingenminiupnpcstrings miniupnpcstrings.h.in miniupnpcstrings.h - */ -int main(int argc, char * * argv) { - char buffer[256]; - OSVERSIONINFO osvi; - FILE * fin; - FILE * fout; - int n; - char miniupnpcVersion[32]; - /* dwMajorVersion : - The major version number of the operating system. For more information, see Remarks. - dwMinorVersion : - The minor version number of the operating system. For more information, see Remarks. - dwBuildNumber : - The build number of the operating system. - dwPlatformId - The operating system platform. This member can be the following value. - szCSDVersion - A null-terminated string, such as "Service Pack 3", that indicates the - latest Service Pack installed on the system. If no Service Pack has - been installed, the string is empty. - */ - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - printf("Windows %lu.%lu Build %lu %s\n", - osvi.dwMajorVersion, osvi.dwMinorVersion, - osvi.dwBuildNumber, (const char *)&(osvi.szCSDVersion)); - - fin = fopen("VERSION", "r"); - fgets(miniupnpcVersion, sizeof(miniupnpcVersion), fin); - fclose(fin); - for(n = 0; n < sizeof(miniupnpcVersion); n++) { - if(miniupnpcVersion[n] < ' ') - miniupnpcVersion[n] = '\0'; - } - printf("MiniUPnPc version %s\n", miniupnpcVersion); - - if(argc >= 3) { - fin = fopen(argv[1], "r"); - if(!fin) { - fprintf(stderr, "Cannot open %s for reading.\n", argv[1]); - return 1; - } - fout = fopen(argv[2], "w"); - if(!fout) { - fprintf(stderr, "Cannot open %s for writing.\n", argv[2]); - return 1; - } - n = 0; - while(fgets(buffer, sizeof(buffer), fin)) { - if(0 == memcmp(buffer, "#define OS_STRING \"OS/version\"", 30)) { - sprintf(buffer, "#define OS_STRING \"MSWindows/%ld.%ld.%ld\"\n", - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); - } else if(0 == memcmp(buffer, "#define MINIUPNPC_VERSION_STRING \"version\"", 42)) { - sprintf(buffer, "#define MINIUPNPC_VERSION_STRING \"%s\"\n", - miniupnpcVersion); - } - /*fputs(buffer, stdout);*/ - fputs(buffer, fout); - n++; - } - fclose(fin); - fclose(fout); - printf("%d lines written to %s.\n", n, argv[2]); - } - return 0; -} diff --git a/src/contrib/zlib/CMakeLists.txt b/src/contrib/zlib/CMakeLists.txt deleted file mode 100644 index 696b9f5..0000000 --- a/src/contrib/zlib/CMakeLists.txt +++ /dev/null @@ -1,249 +0,0 @@ -cmake_minimum_required(VERSION 2.4.4) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) - -project(zlib C) - -set(VERSION "1.2.11") - -option(ASM686 "Enable building i686 assembly implementation") -option(AMD64 "Enable building amd64 assembly implementation") - -set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") -set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") -set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") -set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") - -include(CheckTypeSize) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -enable_testing() - -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) -# We add these other definitions here because CheckTypeSize.cmake -# in CMake 2.4.x does not automatically do so and we want -# compatibility with CMake 2.4.x. -if(HAVE_SYS_TYPES_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) -endif() -if(HAVE_STDINT_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) -endif() -if(HAVE_STDDEF_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) -endif() -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1) -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() - -# -# Check for unistd.h -# -check_include_file(unistd.h Z_HAVE_UNISTD_H) - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -endif() - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - # If we're doing an out of source build and the user has a zconf.h - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") - message(STATUS "to 'zconf.h.included' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) - endif() -endif() - -set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h - zlib.h -) -set(ZLIB_PRIVATE_HDRS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - compress.c - crc32.c - deflate.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -) - -if(NOT MINGW) - set(ZLIB_DLL_SRCS - win32/zlib1.rc # If present will override custom build rule below. - ) -endif() - -if(CMAKE_COMPILER_IS_GNUCC) - if(ASM686) - set(ZLIB_ASMS contrib/asm686/match.S) - elseif (AMD64) - set(ZLIB_ASMS contrib/amd64/amd64-match.S) - endif () - - if(ZLIB_ASMS) - add_definitions(-DASMV) - set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) - endif() -endif() - -if(MSVC) - if(ASM686) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx86/inffas32.asm - contrib/masmx86/match686.asm - ) - elseif (AMD64) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx64/gvmat64.asm - contrib/masmx64/inffasx64.asm - ) - endif() - - if(ZLIB_ASMS) - add_definitions(-DASMV -DASMINF) - endif() -endif() - -# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" - "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) - -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif(MINGW) - -#add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -# set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) -# set_target_properties(zlib PROPERTIES SOVERSION 1) - -if(NOT CYGWIN) - # This property causes shared libraries on Linux to have the full version - # encoded into their final filename. We disable this on Cygwin because - # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll - # seems to be the default. - # - # This has no effect with MSVC, on that platform the version info for - # the DLL comes from the resource file win32/zlib1.rc -# set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) -endif() - -if(UNIX) - # On unix-like platforms the library is almost always called libz - set_target_properties( zlibstatic PROPERTIES OUTPUT_NAME z) - if(NOT APPLE) - #set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") - endif() -elseif(BUILD_SHARED_LIBS AND WIN32) - # Creates zlib1.dll when building shared library version - # set_target_properties(zlib PROPERTIES SUFFIX "1.dll") -endif() - -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS zlibstatic - RUNTIME DESTINATION "${INSTALL_BIN_DIR}" - ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) -endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) - install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") -endif() - -#============================================================================ -# Example binaries -#============================================================================ - -#add_executable(example test/example.c) -#target_link_libraries(example zlib) -#add_test(example example) - -#add_executable(minigzip test/minigzip.c) -#target_link_libraries(minigzip zlib) - -if(HAVE_OFF64_T) -# add_executable(example64 test/example.c) -# target_link_libraries(example64 zlib) -# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -# add_test(example64 example64) - -# add_executable(minigzip64 test/minigzip.c) -# target_link_libraries(minigzip64 zlib) -# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") -endif() diff --git a/src/contrib/zlib/ChangeLog b/src/contrib/zlib/ChangeLog deleted file mode 100644 index 30199a6..0000000 --- a/src/contrib/zlib/ChangeLog +++ /dev/null @@ -1,1515 +0,0 @@ - - ChangeLog file for zlib - -Changes in 1.2.11 (15 Jan 2017) -- Fix deflate stored bug when pulling last block from window -- Permit immediate deflateParams changes before any deflate input - -Changes in 1.2.10 (2 Jan 2017) -- Avoid warnings on snprintf() return value -- Fix bug in deflate_stored() for zero-length input -- Fix bug in gzwrite.c that produced corrupt gzip files -- Remove files to be installed before copying them in Makefile.in -- Add warnings when compiling with assembler code - -Changes in 1.2.9 (31 Dec 2016) -- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] -- Improve contrib/blast to return unused bytes -- Assure that gzoffset() is correct when appending -- Improve compress() and uncompress() to support large lengths -- Fix bug in test/example.c where error code not saved -- Remedy Coverity warning [Randers-Pehrson] -- Improve speed of gzprintf() in transparent mode -- Fix inflateInit2() bug when windowBits is 16 or 32 -- Change DEBUG macro to ZLIB_DEBUG -- Avoid uninitialized access by gzclose_w() -- Allow building zlib outside of the source directory -- Fix bug that accepted invalid zlib header when windowBits is zero -- Fix gzseek() problem on MinGW due to buggy _lseeki64 there -- Loop on write() calls in gzwrite.c in case of non-blocking I/O -- Add --warn (-w) option to ./configure for more compiler warnings -- Reject a window size of 256 bytes if not using the zlib wrapper -- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE -- Add --debug (-d) option to ./configure to define ZLIB_DEBUG -- Fix bugs in creating a very large gzip header -- Add uncompress2() function, which returns the input size used -- Assure that deflateParams() will not switch functions mid-block -- Dramatically speed up deflation for level 0 (storing) -- Add gzfread(), duplicating the interface of fread() -- Add gzfwrite(), duplicating the interface of fwrite() -- Add deflateGetDictionary() function -- Use snprintf() for later versions of Microsoft C -- Fix *Init macros to use z_ prefix when requested -- Replace as400 with os400 for OS/400 support [Monnerat] -- Add crc32_z() and adler32_z() functions with size_t lengths -- Update Visual Studio project files [AraHaan] - -Changes in 1.2.8 (28 Apr 2013) -- Update contrib/minizip/iowin32.c for Windows RT [Vollant] -- Do not force Z_CONST for C++ -- Clean up contrib/vstudio [Roß] -- Correct spelling error in zlib.h -- Fix mixed line endings in contrib/vstudio - -Changes in 1.2.7.3 (13 Apr 2013) -- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc - -Changes in 1.2.7.2 (13 Apr 2013) -- Change check for a four-byte type back to hexadecimal -- Fix typo in win32/Makefile.msc -- Add casts in gzwrite.c for pointer differences - -Changes in 1.2.7.1 (24 Mar 2013) -- Replace use of unsafe string functions with snprintf if available -- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] -- Fix gzgetc undefine when Z_PREFIX set [Turk] -- Eliminate use of mktemp in Makefile (not always available) -- Fix bug in 'F' mode for gzopen() -- Add inflateGetDictionary() function -- Correct comment in deflate.h -- Use _snprintf for snprintf in Microsoft C -- On Darwin, only use /usr/bin/libtool if libtool is not Apple -- Delete "--version" file if created by "ar --version" [Richard G.] -- Fix configure check for veracity of compiler error return codes -- Fix CMake compilation of static lib for MSVC2010 x64 -- Remove unused variable in infback9.c -- Fix argument checks in gzlog_compress() and gzlog_write() -- Clean up the usage of z_const and respect const usage within zlib -- Clean up examples/gzlog.[ch] comparisons of different types -- Avoid shift equal to bits in type (caused endless loop) -- Fix uninitialized value bug in gzputc() introduced by const patches -- Fix memory allocation error in examples/zran.c [Nor] -- Fix bug where gzopen(), gzclose() would write an empty file -- Fix bug in gzclose() when gzwrite() runs out of memory -- Check for input buffer malloc failure in examples/gzappend.c -- Add note to contrib/blast to use binary mode in stdio -- Fix comparisons of differently signed integers in contrib/blast -- Check for invalid code length codes in contrib/puff -- Fix serious but very rare decompression bug in inftrees.c -- Update inflateBack() comments, since inflate() can be faster -- Use underscored I/O function names for WINAPI_FAMILY -- Add _tr_flush_bits to the external symbols prefixed by --zprefix -- Add contrib/vstudio/vc10 pre-build step for static only -- Quote --version-script argument in CMakeLists.txt -- Don't specify --version-script on Apple platforms in CMakeLists.txt -- Fix casting error in contrib/testzlib/testzlib.c -- Fix types in contrib/minizip to match result of get_crc_table() -- Simplify contrib/vstudio/vc10 with 'd' suffix -- Add TOP support to win32/Makefile.msc -- Suport i686 and amd64 assembler builds in CMakeLists.txt -- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h -- Add vc11 and vc12 build files to contrib/vstudio -- Add gzvprintf() as an undocumented function in zlib -- Fix configure for Sun shell -- Remove runtime check in configure for four-byte integer type -- Add casts and consts to ease user conversion to C++ -- Add man pages for minizip and miniunzip -- In Makefile uninstall, don't rm if preceding cd fails -- Do not return Z_BUF_ERROR if deflateParam() has nothing to write - -Changes in 1.2.7 (2 May 2012) -- Replace use of memmove() with a simple copy for portability -- Test for existence of strerror -- Restore gzgetc_ for backward compatibility with 1.2.6 -- Fix build with non-GNU make on Solaris -- Require gcc 4.0 or later on Mac OS X to use the hidden attribute -- Include unistd.h for Watcom C -- Use __WATCOMC__ instead of __WATCOM__ -- Do not use the visibility attribute if NO_VIZ defined -- Improve the detection of no hidden visibility attribute -- Avoid using __int64 for gcc or solo compilation -- Cast to char * in gzprintf to avoid warnings [Zinser] -- Fix make_vms.com for VAX [Zinser] -- Don't use library or built-in byte swaps -- Simplify test and use of gcc hidden attribute -- Fix bug in gzclose_w() when gzwrite() fails to allocate memory -- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() -- Fix bug in test/minigzip.c for configure --solo -- Fix contrib/vstudio project link errors [Mohanathas] -- Add ability to choose the builder in make_vms.com [Schweda] -- Add DESTDIR support to mingw32 win32/Makefile.gcc -- Fix comments in win32/Makefile.gcc for proper usage -- Allow overriding the default install locations for cmake -- Generate and install the pkg-config file with cmake -- Build both a static and a shared version of zlib with cmake -- Include version symbols for cmake builds -- If using cmake with MSVC, add the source directory to the includes -- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] -- Move obsolete emx makefile to old [Truta] -- Allow the use of -Wundef when compiling or using zlib -- Avoid the use of the -u option with mktemp -- Improve inflate() documentation on the use of Z_FINISH -- Recognize clang as gcc -- Add gzopen_w() in Windows for wide character path names -- Rename zconf.h in CMakeLists.txt to move it out of the way -- Add source directory in CMakeLists.txt for building examples -- Look in build directory for zlib.pc in CMakeLists.txt -- Remove gzflags from zlibvc.def in vc9 and vc10 -- Fix contrib/minizip compilation in the MinGW environment -- Update ./configure for Solaris, support --64 [Mooney] -- Remove -R. from Solaris shared build (possible security issue) -- Avoid race condition for parallel make (-j) running example -- Fix type mismatch between get_crc_table() and crc_table -- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] -- Fix the path to zlib.map in CMakeLists.txt -- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] -- Add instructions to win32/Makefile.gcc for shared install [Torri] - -Changes in 1.2.6.1 (12 Feb 2012) -- Avoid the use of the Objective-C reserved name "id" -- Include io.h in gzguts.h for Microsoft compilers -- Fix problem with ./configure --prefix and gzgetc macro -- Include gz_header definition when compiling zlib solo -- Put gzflags() functionality back in zutil.c -- Avoid library header include in crc32.c for Z_SOLO -- Use name in GCC_CLASSIC as C compiler for coverage testing, if set -- Minor cleanup in contrib/minizip/zip.c [Vollant] -- Update make_vms.com [Zinser] -- Remove unnecessary gzgetc_ function -- Use optimized byte swap operations for Microsoft and GNU [Snyder] -- Fix minor typo in zlib.h comments [Rzesniowiecki] - -Changes in 1.2.6 (29 Jan 2012) -- Update the Pascal interface in contrib/pascal -- Fix function numbers for gzgetc_ in zlibvc.def files -- Fix configure.ac for contrib/minizip [Schiffer] -- Fix large-entry detection in minizip on 64-bit systems [Schiffer] -- Have ./configure use the compiler return code for error indication -- Fix CMakeLists.txt for cross compilation [McClure] -- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] -- Fix compilation of contrib/minizip on FreeBSD [Marquez] -- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] -- Include io.h for Turbo C / Borland C on all platforms [Truta] -- Make version explicit in contrib/minizip/configure.ac [Bosmans] -- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] -- Minor cleanup up contrib/minizip/unzip.c [Vollant] -- Fix bug when compiling minizip with C++ [Vollant] -- Protect for long name and extra fields in contrib/minizip [Vollant] -- Avoid some warnings in contrib/minizip [Vollant] -- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip -- Add missing libs to minizip linker command -- Add support for VPATH builds in contrib/minizip -- Add an --enable-demos option to contrib/minizip/configure -- Add the generation of configure.log by ./configure -- Exit when required parameters not provided to win32/Makefile.gcc -- Have gzputc return the character written instead of the argument -- Use the -m option on ldconfig for BSD systems [Tobias] -- Correct in zlib.map when deflateResetKeep was added - -Changes in 1.2.5.3 (15 Jan 2012) -- Restore gzgetc function for binary compatibility -- Do not use _lseeki64 under Borland C++ [Truta] -- Update win32/Makefile.msc to build test/*.c [Truta] -- Remove old/visualc6 given CMakefile and other alternatives -- Update AS400 build files and documentation [Monnerat] -- Update win32/Makefile.gcc to build test/*.c [Truta] -- Permit stronger flushes after Z_BLOCK flushes -- Avoid extraneous empty blocks when doing empty flushes -- Permit Z_NULL arguments to deflatePending -- Allow deflatePrime() to insert bits in the middle of a stream -- Remove second empty static block for Z_PARTIAL_FLUSH -- Write out all of the available bits when using Z_BLOCK -- Insert the first two strings in the hash table after a flush - -Changes in 1.2.5.2 (17 Dec 2011) -- fix ld error: unable to find version dependency 'ZLIB_1.2.5' -- use relative symlinks for shared libs -- Avoid searching past window for Z_RLE strategy -- Assure that high-water mark initialization is always applied in deflate -- Add assertions to fill_window() in deflate.c to match comments -- Update python link in README -- Correct spelling error in gzread.c -- Fix bug in gzgets() for a concatenated empty gzip stream -- Correct error in comment for gz_make() -- Change gzread() and related to ignore junk after gzip streams -- Allow gzread() and related to continue after gzclearerr() -- Allow gzrewind() and gzseek() after a premature end-of-file -- Simplify gzseek() now that raw after gzip is ignored -- Change gzgetc() to a macro for speed (~40% speedup in testing) -- Fix gzclose() to return the actual error last encountered -- Always add large file support for windows -- Include zconf.h for windows large file support -- Include zconf.h.cmakein for windows large file support -- Update zconf.h.cmakein on make distclean -- Merge vestigial vsnprintf determination from zutil.h to gzguts.h -- Clarify how gzopen() appends in zlib.h comments -- Correct documentation of gzdirect() since junk at end now ignored -- Add a transparent write mode to gzopen() when 'T' is in the mode -- Update python link in zlib man page -- Get inffixed.h and MAKEFIXED result to match -- Add a ./config --solo option to make zlib subset with no library use -- Add undocumented inflateResetKeep() function for CAB file decoding -- Add --cover option to ./configure for gcc coverage testing -- Add #define ZLIB_CONST option to use const in the z_stream interface -- Add comment to gzdopen() in zlib.h to use dup() when using fileno() -- Note behavior of uncompress() to provide as much data as it can -- Add files in contrib/minizip to aid in building libminizip -- Split off AR options in Makefile.in and configure -- Change ON macro to Z_ARG to avoid application conflicts -- Facilitate compilation with Borland C++ for pragmas and vsnprintf -- Include io.h for Turbo C / Borland C++ -- Move example.c and minigzip.c to test/ -- Simplify incomplete code table filling in inflate_table() -- Remove code from inflate.c and infback.c that is impossible to execute -- Test the inflate code with full coverage -- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) -- Add deflateResetKeep and fix inflateResetKeep to retain dictionary -- Fix gzwrite.c to accommodate reduced memory zlib compilation -- Have inflate() with Z_FINISH avoid the allocation of a window -- Do not set strm->adler when doing raw inflate -- Fix gzeof() to behave just like feof() when read is not past end of file -- Fix bug in gzread.c when end-of-file is reached -- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF -- Document gzread() capability to read concurrently written files -- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] - -Changes in 1.2.5.1 (10 Sep 2011) -- Update FAQ entry on shared builds (#13) -- Avoid symbolic argument to chmod in Makefile.in -- Fix bug and add consts in contrib/puff [Oberhumer] -- Update contrib/puff/zeros.raw test file to have all block types -- Add full coverage test for puff in contrib/puff/Makefile -- Fix static-only-build install in Makefile.in -- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] -- Add libz.a dependency to shared in Makefile.in for parallel builds -- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out -- Replace $(...) with `...` in configure for non-bash sh [Bowler] -- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] -- Add solaris* to Linux* in configure to allow gcc use [Groffen] -- Add *bsd* to Linux* case in configure [Bar-Lev] -- Add inffast.obj to dependencies in win32/Makefile.msc -- Correct spelling error in deflate.h [Kohler] -- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc -- Add test to configure for GNU C looking for gcc in output of $cc -v -- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] -- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not -- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense -- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) -- Make stronger test in zconf.h to include unistd.h for LFS -- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] -- Fix zlib.h LFS support when Z_PREFIX used -- Add updated as400 support (removed from old) [Monnerat] -- Avoid deflate sensitivity to volatile input data -- Avoid division in adler32_combine for NO_DIVIDE -- Clarify the use of Z_FINISH with deflateBound() amount of space -- Set binary for output file in puff.c -- Use u4 type for crc_table to avoid conversion warnings -- Apply casts in zlib.h to avoid conversion warnings -- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] -- Improve inflateSync() documentation to note indeterminancy -- Add deflatePending() function to return the amount of pending output -- Correct the spelling of "specification" in FAQ [Randers-Pehrson] -- Add a check in configure for stdarg.h, use for gzprintf() -- Check that pointers fit in ints when gzprint() compiled old style -- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] -- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] -- Add debug records in assmebler code [Londer] -- Update RFC references to use http://tools.ietf.org/html/... [Li] -- Add --archs option, use of libtool to configure for Mac OS X [Borstel] - -Changes in 1.2.5 (19 Apr 2010) -- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] -- Default to libdir as sharedlibdir in configure [Nieder] -- Update copyright dates on modified source files -- Update trees.c to be able to generate modified trees.h -- Exit configure for MinGW, suggesting win32/Makefile.gcc -- Check for NULL path in gz_open [Homurlu] - -Changes in 1.2.4.5 (18 Apr 2010) -- Set sharedlibdir in configure [Torok] -- Set LDFLAGS in Makefile.in [Bar-Lev] -- Avoid mkdir objs race condition in Makefile.in [Bowler] -- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays -- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C -- Don't use hidden attribute when it is a warning generator (e.g. Solaris) - -Changes in 1.2.4.4 (18 Apr 2010) -- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] -- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty -- Try to use bash or ksh regardless of functionality of /bin/sh -- Fix configure incompatibility with NetBSD sh -- Remove attempt to run under bash or ksh since have better NetBSD fix -- Fix win32/Makefile.gcc for MinGW [Bar-Lev] -- Add diagnostic messages when using CROSS_PREFIX in configure -- Added --sharedlibdir option to configure [Weigelt] -- Use hidden visibility attribute when available [Frysinger] - -Changes in 1.2.4.3 (10 Apr 2010) -- Only use CROSS_PREFIX in configure for ar and ranlib if they exist -- Use CROSS_PREFIX for nm [Bar-Lev] -- Assume _LARGEFILE64_SOURCE defined is equivalent to true -- Avoid use of undefined symbols in #if with && and || -- Make *64 prototypes in gzguts.h consistent with functions -- Add -shared load option for MinGW in configure [Bowler] -- Move z_off64_t to public interface, use instead of off64_t -- Remove ! from shell test in configure (not portable to Solaris) -- Change +0 macro tests to -0 for possibly increased portability - -Changes in 1.2.4.2 (9 Apr 2010) -- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 -- Really provide prototypes for *64 functions when building without LFS -- Only define unlink() in minigzip.c if unistd.h not included -- Update README to point to contrib/vstudio project files -- Move projects/vc6 to old/ and remove projects/ -- Include stdlib.h in minigzip.c for setmode() definition under WinCE -- Clean up assembler builds in win32/Makefile.msc [Rowe] -- Include sys/types.h for Microsoft for off_t definition -- Fix memory leak on error in gz_open() -- Symbolize nm as $NM in configure [Weigelt] -- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] -- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined -- Fix bug in gzeof() to take into account unused input data -- Avoid initialization of structures with variables in puff.c -- Updated win32/README-WIN32.txt [Rowe] - -Changes in 1.2.4.1 (28 Mar 2010) -- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] -- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] -- Restore "for debugging" comment on sprintf() in gzlib.c -- Remove fdopen for MVS from gzguts.h -- Put new README-WIN32.txt in win32 [Rowe] -- Add check for shell to configure and invoke another shell if needed -- Fix big fat stinking bug in gzseek() on uncompressed files -- Remove vestigial F_OPEN64 define in zutil.h -- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE -- Avoid errors on non-LFS systems when applications define LFS macros -- Set EXE to ".exe" in configure for MINGW [Kahle] -- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] -- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] -- Add DLL install in win32/makefile.gcc [Bar-Lev] -- Allow Linux* or linux* from uname in configure [Bar-Lev] -- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] -- Add cross-compilation prefixes to configure [Bar-Lev] -- Match type exactly in gz_load() invocation in gzread.c -- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func -- Provide prototypes for *64 functions when building zlib without LFS -- Don't use -lc when linking shared library on MinGW -- Remove errno.h check in configure and vestigial errno code in zutil.h - -Changes in 1.2.4 (14 Mar 2010) -- Fix VER3 extraction in configure for no fourth subversion -- Update zlib.3, add docs to Makefile.in to make .pdf out of it -- Add zlib.3.pdf to distribution -- Don't set error code in gzerror() if passed pointer is NULL -- Apply destination directory fixes to CMakeLists.txt [Lowman] -- Move #cmakedefine's to a new zconf.in.cmakein -- Restore zconf.h for builds that don't use configure or cmake -- Add distclean to dummy Makefile for convenience -- Update and improve INDEX, README, and FAQ -- Update CMakeLists.txt for the return of zconf.h [Lowman] -- Update contrib/vstudio/vc9 and vc10 [Vollant] -- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc -- Apply license and readme changes to contrib/asm686 [Raiter] -- Check file name lengths and add -c option in minigzip.c [Li] -- Update contrib/amd64 and contrib/masmx86/ [Vollant] -- Avoid use of "eof" parameter in trees.c to not shadow library variable -- Update make_vms.com for removal of zlibdefs.h [Zinser] -- Update assembler code and vstudio projects in contrib [Vollant] -- Remove outdated assembler code contrib/masm686 and contrib/asm586 -- Remove old vc7 and vc8 from contrib/vstudio -- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] -- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() -- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] -- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) -- Fix bug in void-returning vsprintf() case in gzwrite.c -- Fix name change from inflate.h in contrib/inflate86/inffas86.c -- Check if temporary file exists before removing in make_vms.com [Zinser] -- Fix make install and uninstall for --static option -- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] -- Update readme.txt in contrib/masmx64 and masmx86 to assemble - -Changes in 1.2.3.9 (21 Feb 2010) -- Expunge gzio.c -- Move as400 build information to old -- Fix updates in contrib/minizip and contrib/vstudio -- Add const to vsnprintf test in configure to avoid warnings [Weigelt] -- Delete zconf.h (made by configure) [Weigelt] -- Change zconf.in.h to zconf.h.in per convention [Weigelt] -- Check for NULL buf in gzgets() -- Return empty string for gzgets() with len == 1 (like fgets()) -- Fix description of gzgets() in zlib.h for end-of-file, NULL return -- Update minizip to 1.1 [Vollant] -- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c -- Note in zlib.h that gzerror() should be used to distinguish from EOF -- Remove use of snprintf() from gzlib.c -- Fix bug in gzseek() -- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] -- Fix zconf.h generation in CMakeLists.txt [Lowman] -- Improve comments in zconf.h where modified by configure - -Changes in 1.2.3.8 (13 Feb 2010) -- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] -- Use z_off64_t in gz_zero() and gz_skip() to match state->skip -- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) -- Revert to Makefile.in from 1.2.3.6 (live with the clutter) -- Fix missing error return in gzflush(), add zlib.h note -- Add *64 functions to zlib.map [Levin] -- Fix signed/unsigned comparison in gz_comp() -- Use SFLAGS when testing shared linking in configure -- Add --64 option to ./configure to use -m64 with gcc -- Fix ./configure --help to correctly name options -- Have make fail if a test fails [Levin] -- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] -- Remove assembler object files from contrib - -Changes in 1.2.3.7 (24 Jan 2010) -- Always gzopen() with O_LARGEFILE if available -- Fix gzdirect() to work immediately after gzopen() or gzdopen() -- Make gzdirect() more precise when the state changes while reading -- Improve zlib.h documentation in many places -- Catch memory allocation failure in gz_open() -- Complete close operation if seek forward in gzclose_w() fails -- Return Z_ERRNO from gzclose_r() if close() fails -- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL -- Return zero for gzwrite() errors to match zlib.h description -- Return -1 on gzputs() error to match zlib.h description -- Add zconf.in.h to allow recovery from configure modification [Weigelt] -- Fix static library permissions in Makefile.in [Weigelt] -- Avoid warnings in configure tests that hide functionality [Weigelt] -- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] -- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] -- Avoid access of uninitialized data for first inflateReset2 call [Gomes] -- Keep object files in subdirectories to reduce the clutter somewhat -- Remove default Makefile and zlibdefs.h, add dummy Makefile -- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ -- Remove zlibdefs.h completely -- modify zconf.h instead - -Changes in 1.2.3.6 (17 Jan 2010) -- Avoid void * arithmetic in gzread.c and gzwrite.c -- Make compilers happier with const char * for gz_error message -- Avoid unused parameter warning in inflate.c -- Avoid signed-unsigned comparison warning in inflate.c -- Indent #pragma's for traditional C -- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() -- Correct email address in configure for system options -- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] -- Update zlib.map [Brown] -- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] -- Apply various fixes to CMakeLists.txt [Lowman] -- Add checks on len in gzread() and gzwrite() -- Add error message for no more room for gzungetc() -- Remove zlib version check in gzwrite() -- Defer compression of gzprintf() result until need to -- Use snprintf() in gzdopen() if available -- Remove USE_MMAP configuration determination (only used by minigzip) -- Remove examples/pigz.c (available separately) -- Update examples/gun.c to 1.6 - -Changes in 1.2.3.5 (8 Jan 2010) -- Add space after #if in zutil.h for some compilers -- Fix relatively harmless bug in deflate_fast() [Exarevsky] -- Fix same problem in deflate_slow() -- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] -- Add deflate_rle() for faster Z_RLE strategy run-length encoding -- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding -- Change name of "write" variable in inffast.c to avoid library collisions -- Fix premature EOF from gzread() in gzio.c [Brown] -- Use zlib header window size if windowBits is 0 in inflateInit2() -- Remove compressBound() call in deflate.c to avoid linking compress.o -- Replace use of errno in gz* with functions, support WinCE [Alves] -- Provide alternative to perror() in minigzip.c for WinCE [Alves] -- Don't use _vsnprintf on later versions of MSVC [Lowman] -- Add CMake build script and input file [Lowman] -- Update contrib/minizip to 1.1 [Svensson, Vollant] -- Moved nintendods directory from contrib to . -- Replace gzio.c with a new set of routines with the same functionality -- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above -- Update contrib/minizip to 1.1b -- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h - -Changes in 1.2.3.4 (21 Dec 2009) -- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility -- Update comments in configure and Makefile.in for default --shared -- Fix test -z's in configure [Marquess] -- Build examplesh and minigzipsh when not testing -- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h -- Import LDFLAGS from the environment in configure -- Fix configure to populate SFLAGS with discovered CFLAGS options -- Adapt make_vms.com to the new Makefile.in [Zinser] -- Add zlib2ansi script for C++ compilation [Marquess] -- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) -- Add AMD64 assembler code for longest match to contrib [Teterin] -- Include options from $SFLAGS when doing $LDSHARED -- Simplify 64-bit file support by introducing z_off64_t type -- Make shared object files in objs directory to work around old Sun cc -- Use only three-part version number for Darwin shared compiles -- Add rc option to ar in Makefile.in for when ./configure not run -- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* -- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile -- Protect against _FILE_OFFSET_BITS being defined when compiling zlib -- Rename Makefile.in targets allstatic to static and allshared to shared -- Fix static and shared Makefile.in targets to be independent -- Correct error return bug in gz_open() by setting state [Brown] -- Put spaces before ;;'s in configure for better sh compatibility -- Add pigz.c (parallel implementation of gzip) to examples/ -- Correct constant in crc32.c to UL [Leventhal] -- Reject negative lengths in crc32_combine() -- Add inflateReset2() function to work like inflateEnd()/inflateInit2() -- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] -- Correct typo in doc/algorithm.txt [Janik] -- Fix bug in adler32_combine() [Zhu] -- Catch missing-end-of-block-code error in all inflates and in puff - Assures that random input to inflate eventually results in an error -- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ -- Update ENOUGH and its usage to reflect discovered bounds -- Fix gzerror() error report on empty input file [Brown] -- Add ush casts in trees.c to avoid pedantic runtime errors -- Fix typo in zlib.h uncompress() description [Reiss] -- Correct inflate() comments with regard to automatic header detection -- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) -- Put new version of gzlog (2.0) in examples with interruption recovery -- Add puff compile option to permit invalid distance-too-far streams -- Add puff TEST command options, ability to read piped input -- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but - _LARGEFILE64_SOURCE not defined -- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart -- Fix deflateSetDictionary() to use all 32K for output consistency -- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) -- Clear bytes after deflate lookahead to avoid use of uninitialized data -- Change a limit in inftrees.c to be more transparent to Coverity Prevent -- Update win32/zlib.def with exported symbols from zlib.h -- Correct spelling errors in zlib.h [Willem, Sobrado] -- Allow Z_BLOCK for deflate() to force a new block -- Allow negative bits in inflatePrime() to delete existing bit buffer -- Add Z_TREES flush option to inflate() to return at end of trees -- Add inflateMark() to return current state information for random access -- Add Makefile for NintendoDS to contrib [Costa] -- Add -w in configure compile tests to avoid spurious warnings [Beucler] -- Fix typos in zlib.h comments for deflateSetDictionary() -- Fix EOF detection in transparent gzread() [Maier] - -Changes in 1.2.3.3 (2 October 2006) -- Make --shared the default for configure, add a --static option -- Add compile option to permit invalid distance-too-far streams -- Add inflateUndermine() function which is required to enable above -- Remove use of "this" variable name for C++ compatibility [Marquess] -- Add testing of shared library in make test, if shared library built -- Use ftello() and fseeko() if available instead of ftell() and fseek() -- Provide two versions of all functions that use the z_off_t type for - binary compatibility -- a normal version and a 64-bit offset version, - per the Large File Support Extension when _LARGEFILE64_SOURCE is - defined; use the 64-bit versions by default when _FILE_OFFSET_BITS - is defined to be 64 -- Add a --uname= option to configure to perhaps help with cross-compiling - -Changes in 1.2.3.2 (3 September 2006) -- Turn off silly Borland warnings [Hay] -- Use off64_t and define _LARGEFILE64_SOURCE when present -- Fix missing dependency on inffixed.h in Makefile.in -- Rig configure --shared to build both shared and static [Teredesai, Truta] -- Remove zconf.in.h and instead create a new zlibdefs.h file -- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] -- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] - -Changes in 1.2.3.1 (16 August 2006) -- Add watcom directory with OpenWatcom make files [Daniel] -- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] -- Update make_vms.com [Zinser] -- Use -fPIC for shared build in configure [Teredesai, Nicholson] -- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] -- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] -- Add some FAQ entries about the contrib directory -- Update the MVS question in the FAQ -- Avoid extraneous reads after EOF in gzio.c [Brown] -- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] -- Add comments to zlib.h about gzerror() usage [Brown] -- Set extra flags in gzip header in gzopen() like deflate() does -- Make configure options more compatible with double-dash conventions - [Weigelt] -- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] -- Fix uninstall target in Makefile.in [Truta] -- Add pkgconfig support [Weigelt] -- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] -- Replace set_data_type() with a more accurate detect_data_type() in - trees.c, according to the txtvsbin.txt document [Truta] -- Swap the order of #include and #include "zlib.h" in - gzio.c, example.c and minigzip.c [Truta] -- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, - Truta] (where?) -- Fix target "clean" from win32/Makefile.bor [Truta] -- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] -- Update zlib www home address in win32/DLL_FAQ.txt [Truta] -- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] -- Enable browse info in the "Debug" and "ASM Debug" configurations in - the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] -- Add pkgconfig support [Weigelt] -- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, - for use in win32/zlib1.rc [Polushin, Rowe, Truta] -- Add a document that explains the new text detection scheme to - doc/txtvsbin.txt [Truta] -- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] -- Move algorithm.txt into doc/ [Truta] -- Synchronize FAQ with website -- Fix compressBound(), was low for some pathological cases [Fearnley] -- Take into account wrapper variations in deflateBound() -- Set examples/zpipe.c input and output to binary mode for Windows -- Update examples/zlib_how.html with new zpipe.c (also web site) -- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems - that gcc became pickier in 4.0) -- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain - un-versioned, the patch adds versioning only for symbols introduced in - zlib-1.2.0 or later. It also declares as local those symbols which are - not designed to be exported." [Levin] -- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure -- Do not initialize global static by default in trees.c, add a response - NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] -- Don't use strerror() in gzio.c under WinCE [Yakimov] -- Don't use errno.h in zutil.h under WinCE [Yakimov] -- Move arguments for AR to its usage to allow replacing ar [Marot] -- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] -- Improve inflateInit() and inflateInit2() documentation -- Fix structure size comment in inflate.h -- Change configure help option from --h* to --help [Santos] - -Changes in 1.2.3 (18 July 2005) -- Apply security vulnerability fixes to contrib/infback9 as well -- Clean up some text files (carriage returns, trailing space) -- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] - -Changes in 1.2.2.4 (11 July 2005) -- Add inflatePrime() function for starting inflation at bit boundary -- Avoid some Visual C warnings in deflate.c -- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit - compile -- Fix some spelling errors in comments [Betts] -- Correct inflateInit2() error return documentation in zlib.h -- Add zran.c example of compressed data random access to examples - directory, shows use of inflatePrime() -- Fix cast for assignments to strm->state in inflate.c and infback.c -- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] -- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] -- Add cast in trees.c t avoid a warning [Oberhumer] -- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] -- Update make_vms.com [Zinser] -- Initialize state->write in inflateReset() since copied in inflate_fast() -- Be more strict on incomplete code sets in inflate_table() and increase - ENOUGH and MAXD -- this repairs a possible security vulnerability for - invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for - discovering the vulnerability and providing test cases. -- Add ia64 support to configure for HP-UX [Smith] -- Add error return to gzread() for format or i/o error [Levin] -- Use malloc.h for OS/2 [Necasek] - -Changes in 1.2.2.3 (27 May 2005) -- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile -- Typecast fread() return values in gzio.c [Vollant] -- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) -- Fix crc check bug in gzread() after gzungetc() [Heiner] -- Add the deflateTune() function to adjust internal compression parameters -- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) -- Remove an incorrect assertion in examples/zpipe.c -- Add C++ wrapper in infback9.h [Donais] -- Fix bug in inflateCopy() when decoding fixed codes -- Note in zlib.h how much deflateSetDictionary() actually uses -- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) -- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] -- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] -- Add gzdirect() function to indicate transparent reads -- Update contrib/minizip [Vollant] -- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] -- Add casts in crc32.c to avoid warnings [Oberhumer] -- Add contrib/masmx64 [Vollant] -- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] - -Changes in 1.2.2.2 (30 December 2004) -- Replace structure assignments in deflate.c and inflate.c with zmemcpy to - avoid implicit memcpy calls (portability for no-library compilation) -- Increase sprintf() buffer size in gzdopen() to allow for large numbers -- Add INFLATE_STRICT to check distances against zlib header -- Improve WinCE errno handling and comments [Chang] -- Remove comment about no gzip header processing in FAQ -- Add Z_FIXED strategy option to deflateInit2() to force fixed trees -- Add updated make_vms.com [Coghlan], update README -- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. -- Add FAQ entry and comments in deflate.c on uninitialized memory access -- Add Solaris 9 make options in configure [Gilbert] -- Allow strerror() usage in gzio.c for STDC -- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] -- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] -- Use z_off_t for adler32_combine() and crc32_combine() lengths -- Make adler32() much faster for small len -- Use OS_CODE in deflate() default gzip header - -Changes in 1.2.2.1 (31 October 2004) -- Allow inflateSetDictionary() call for raw inflate -- Fix inflate header crc check bug for file names and comments -- Add deflateSetHeader() and gz_header structure for custom gzip headers -- Add inflateGetheader() to retrieve gzip headers -- Add crc32_combine() and adler32_combine() functions -- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list -- Use zstreamp consistently in zlib.h (inflate_back functions) -- Remove GUNZIP condition from definition of inflate_mode in inflate.h - and in contrib/inflate86/inffast.S [Truta, Anderson] -- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] -- Update projects/README.projects and projects/visualc6 [Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] -- Deprecate Z_ASCII; use Z_TEXT instead [Truta] -- Use a new algorithm for setting strm->data_type in trees.c [Truta] -- Do not define an exit() prototype in zutil.c unless DEBUG defined -- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] -- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() -- Fix Darwin build version identification [Peterson] - -Changes in 1.2.2 (3 October 2004) -- Update zlib.h comments on gzip in-memory processing -- Set adler to 1 in inflateReset() to support Java test suite [Walles] -- Add contrib/dotzlib [Ravn] -- Update win32/DLL_FAQ.txt [Truta] -- Update contrib/minizip [Vollant] -- Move contrib/visual-basic.txt to old/ [Truta] -- Fix assembler builds in projects/visualc6/ [Truta] - -Changes in 1.2.1.2 (9 September 2004) -- Update INDEX file -- Fix trees.c to update strm->data_type (no one ever noticed!) -- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] -- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) -- Add limited multitasking protection to DYNAMIC_CRC_TABLE -- Add NO_vsnprintf for VMS in zutil.h [Mozilla] -- Don't declare strerror() under VMS [Mozilla] -- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize -- Update contrib/ada [Anisimkov] -- Update contrib/minizip [Vollant] -- Fix configure to not hardcode directories for Darwin [Peterson] -- Fix gzio.c to not return error on empty files [Brown] -- Fix indentation; update version in contrib/delphi/ZLib.pas and - contrib/pascal/zlibpas.pas [Truta] -- Update mkasm.bat in contrib/masmx86 [Truta] -- Update contrib/untgz [Truta] -- Add projects/README.projects [Truta] -- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] -- Update win32/DLL_FAQ.txt [Truta] -- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] -- Remove an unnecessary assignment to curr in inftrees.c [Truta] -- Add OS/2 to exe builds in configure [Poltorak] -- Remove err dummy parameter in zlib.h [Kientzle] - -Changes in 1.2.1.1 (9 January 2004) -- Update email address in README -- Several FAQ updates -- Fix a big fat bug in inftrees.c that prevented decoding valid - dynamic blocks with only literals and no distance codes -- - Thanks to "Hot Emu" for the bug report and sample file -- Add a note to puff.c on no distance codes case. - -Changes in 1.2.1 (17 November 2003) -- Remove a tab in contrib/gzappend/gzappend.c -- Update some interfaces in contrib for new zlib functions -- Update zlib version number in some contrib entries -- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] -- Support shared libraries on Hurd and KFreeBSD [Brown] -- Fix error in NO_DIVIDE option of adler32.c - -Changes in 1.2.0.8 (4 November 2003) -- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas -- Add experimental NO_DIVIDE #define in adler32.c - - Possibly faster on some processors (let me know if it is) -- Correct Z_BLOCK to not return on first inflate call if no wrap -- Fix strm->data_type on inflate() return to correctly indicate EOB -- Add deflatePrime() function for appending in the middle of a byte -- Add contrib/gzappend for an example of appending to a stream -- Update win32/DLL_FAQ.txt [Truta] -- Delete Turbo C comment in README [Truta] -- Improve some indentation in zconf.h [Truta] -- Fix infinite loop on bad input in configure script [Church] -- Fix gzeof() for concatenated gzip files [Johnson] -- Add example to contrib/visual-basic.txt [Michael B.] -- Add -p to mkdir's in Makefile.in [vda] -- Fix configure to properly detect presence or lack of printf functions -- Add AS400 support [Monnerat] -- Add a little Cygwin support [Wilson] - -Changes in 1.2.0.7 (21 September 2003) -- Correct some debug formats in contrib/infback9 -- Cast a type in a debug statement in trees.c -- Change search and replace delimiter in configure from % to # [Beebe] -- Update contrib/untgz to 0.2 with various fixes [Truta] -- Add build support for Amiga [Nikl] -- Remove some directories in old that have been updated to 1.2 -- Add dylib building for Mac OS X in configure and Makefile.in -- Remove old distribution stuff from Makefile -- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X -- Update links in README - -Changes in 1.2.0.6 (13 September 2003) -- Minor FAQ updates -- Update contrib/minizip to 1.00 [Vollant] -- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] -- Update POSTINC comment for 68060 [Nikl] -- Add contrib/infback9 with deflate64 decoding (unsupported) -- For MVS define NO_vsnprintf and undefine FAR [van Burik] -- Add pragma for fdopen on MVS [van Burik] - -Changes in 1.2.0.5 (8 September 2003) -- Add OF to inflateBackEnd() declaration in zlib.h -- Remember start when using gzdopen in the middle of a file -- Use internal off_t counters in gz* functions to properly handle seeks -- Perform more rigorous check for distance-too-far in inffast.c -- Add Z_BLOCK flush option to return from inflate at block boundary -- Set strm->data_type on return from inflate - - Indicate bits unused, if at block boundary, and if in last block -- Replace size_t with ptrdiff_t in crc32.c, and check for correct size -- Add condition so old NO_DEFLATE define still works for compatibility -- FAQ update regarding the Windows DLL [Truta] -- INDEX update: add qnx entry, remove aix entry [Truta] -- Install zlib.3 into mandir [Wilson] -- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] -- Adapt the zlib interface to the new DLL convention guidelines [Truta] -- Introduce ZLIB_WINAPI macro to allow the export of functions using - the WINAPI calling convention, for Visual Basic [Vollant, Truta] -- Update msdos and win32 scripts and makefiles [Truta] -- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] -- Add contrib/ada [Anisimkov] -- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] -- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] -- Add contrib/masm686 [Truta] -- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm - [Truta, Vollant] -- Update contrib/delphi; rename to contrib/pascal; add example [Truta] -- Remove contrib/delphi2; add a new contrib/delphi [Truta] -- Avoid inclusion of the nonstandard in contrib/iostream, - and fix some method prototypes [Truta] -- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip - [Truta] -- Avoid the use of backslash (\) in contrib/minizip [Vollant] -- Fix file time handling in contrib/untgz; update makefiles [Truta] -- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines - [Vollant] -- Remove contrib/vstudio/vc15_16 [Vollant] -- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] -- Update README.contrib [Truta] -- Invert the assignment order of match_head and s->prev[...] in - INSERT_STRING [Truta] -- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings - [Truta] -- Compare function pointers with 0, not with NULL or Z_NULL [Truta] -- Fix prototype of syncsearch in inflate.c [Truta] -- Introduce ASMINF macro to be enabled when using an ASM implementation - of inflate_fast [Truta] -- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] -- Modify test_gzio in example.c to take a single file name as a - parameter [Truta] -- Exit the example.c program if gzopen fails [Truta] -- Add type casts around strlen in example.c [Truta] -- Remove casting to sizeof in minigzip.c; give a proper type - to the variable compared with SUFFIX_LEN [Truta] -- Update definitions of STDC and STDC99 in zconf.h [Truta] -- Synchronize zconf.h with the new Windows DLL interface [Truta] -- Use SYS16BIT instead of __32BIT__ to distinguish between - 16- and 32-bit platforms [Truta] -- Use far memory allocators in small 16-bit memory models for - Turbo C [Truta] -- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in - zlibCompileFlags [Truta] -- Cygwin has vsnprintf [Wilson] -- In Windows16, OS_CODE is 0, as in MSDOS [Truta] -- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] - -Changes in 1.2.0.4 (10 August 2003) -- Minor FAQ updates -- Be more strict when checking inflateInit2's windowBits parameter -- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well -- Add gzip wrapper option to deflateInit2 using windowBits -- Add updated QNX rule in configure and qnx directory [Bonnefoy] -- Make inflate distance-too-far checks more rigorous -- Clean up FAR usage in inflate -- Add casting to sizeof() in gzio.c and minigzip.c - -Changes in 1.2.0.3 (19 July 2003) -- Fix silly error in gzungetc() implementation [Vollant] -- Update contrib/minizip and contrib/vstudio [Vollant] -- Fix printf format in example.c -- Correct cdecl support in zconf.in.h [Anisimkov] -- Minor FAQ updates - -Changes in 1.2.0.2 (13 July 2003) -- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons -- Attempt to avoid warnings in crc32.c for pointer-int conversion -- Add AIX to configure, remove aix directory [Bakker] -- Add some casts to minigzip.c -- Improve checking after insecure sprintf() or vsprintf() calls -- Remove #elif's from crc32.c -- Change leave label to inf_leave in inflate.c and infback.c to avoid - library conflicts -- Remove inflate gzip decoding by default--only enable gzip decoding by - special request for stricter backward compatibility -- Add zlibCompileFlags() function to return compilation information -- More typecasting in deflate.c to avoid warnings -- Remove leading underscore from _Capital #defines [Truta] -- Fix configure to link shared library when testing -- Add some Windows CE target adjustments [Mai] -- Remove #define ZLIB_DLL in zconf.h [Vollant] -- Add zlib.3 [Rodgers] -- Update RFC URL in deflate.c and algorithm.txt [Mai] -- Add zlib_dll_FAQ.txt to contrib [Truta] -- Add UL to some constants [Truta] -- Update minizip and vstudio [Vollant] -- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h -- Expand use of NO_DUMMY_DECL to avoid all dummy structures -- Added iostream3 to contrib [Schwardt] -- Replace rewind() with fseek() for WinCE [Truta] -- Improve setting of zlib format compression level flags - - Report 0 for huffman and rle strategies and for level == 0 or 1 - - Report 2 only for level == 6 -- Only deal with 64K limit when necessary at compile time [Truta] -- Allow TOO_FAR check to be turned off at compile time [Truta] -- Add gzclearerr() function [Souza] -- Add gzungetc() function - -Changes in 1.2.0.1 (17 March 2003) -- Add Z_RLE strategy for run-length encoding [Truta] - - When Z_RLE requested, restrict matches to distance one - - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE -- Correct FASTEST compilation to allow level == 0 -- Clean up what gets compiled for FASTEST -- Incorporate changes to zconf.in.h [Vollant] - - Refine detection of Turbo C need for dummy returns - - Refine ZLIB_DLL compilation - - Include additional header file on VMS for off_t typedef -- Try to use _vsnprintf where it supplants vsprintf [Vollant] -- Add some casts in inffast.c -- Enchance comments in zlib.h on what happens if gzprintf() tries to - write more than 4095 bytes before compression -- Remove unused state from inflateBackEnd() -- Remove exit(0) from minigzip.c, example.c -- Get rid of all those darn tabs -- Add "check" target to Makefile.in that does the same thing as "test" -- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in -- Update contrib/inflate86 [Anderson] -- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] -- Add msdos and win32 directories with makefiles [Truta] -- More additions and improvements to the FAQ - -Changes in 1.2.0 (9 March 2003) -- New and improved inflate code - - About 20% faster - - Does not allocate 32K window unless and until needed - - Automatically detects and decompresses gzip streams - - Raw inflate no longer needs an extra dummy byte at end - - Added inflateBack functions using a callback interface--even faster - than inflate, useful for file utilities (gzip, zip) - - Added inflateCopy() function to record state for random access on - externally generated deflate streams (e.g. in gzip files) - - More readable code (I hope) -- New and improved crc32() - - About 50% faster, thanks to suggestions from Rodney Brown -- Add deflateBound() and compressBound() functions -- Fix memory leak in deflateInit2() -- Permit setting dictionary for raw deflate (for parallel deflate) -- Fix const declaration for gzwrite() -- Check for some malloc() failures in gzio.c -- Fix bug in gzopen() on single-byte file 0x1f -- Fix bug in gzread() on concatenated file with 0x1f at end of buffer - and next buffer doesn't start with 0x8b -- Fix uncompress() to return Z_DATA_ERROR on truncated input -- Free memory at end of example.c -- Remove MAX #define in trees.c (conflicted with some libraries) -- Fix static const's in deflate.c, gzio.c, and zutil.[ch] -- Declare malloc() and free() in gzio.c if STDC not defined -- Use malloc() instead of calloc() in zutil.c if int big enough -- Define STDC for AIX -- Add aix/ with approach for compiling shared library on AIX -- Add HP-UX support for shared libraries in configure -- Add OpenUNIX support for shared libraries in configure -- Use $cc instead of gcc to build shared library -- Make prefix directory if needed when installing -- Correct Macintosh avoidance of typedef Byte in zconf.h -- Correct Turbo C memory allocation when under Linux -- Use libz.a instead of -lz in Makefile (assure use of compiled library) -- Update configure to check for snprintf or vsnprintf functions and their - return value, warn during make if using an insecure function -- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that - is lost when library is used--resolution is to build new zconf.h -- Documentation improvements (in zlib.h): - - Document raw deflate and inflate - - Update RFCs URL - - Point out that zlib and gzip formats are different - - Note that Z_BUF_ERROR is not fatal - - Document string limit for gzprintf() and possible buffer overflow - - Note requirement on avail_out when flushing - - Note permitted values of flush parameter of inflate() -- Add some FAQs (and even answers) to the FAQ -- Add contrib/inflate86/ for x86 faster inflate -- Add contrib/blast/ for PKWare Data Compression Library decompression -- Add contrib/puff/ simple inflate for deflate format description - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K. -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occurring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Løvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generate bad compressed data. -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count). -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. - -Changes in 0.7 (14 April 95) -- Added full inflate support. -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. -- added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. -- added Z_HUFFMAN_ONLY -- added gzerror() diff --git a/src/contrib/zlib/FAQ b/src/contrib/zlib/FAQ deleted file mode 100644 index 99b7cf9..0000000 --- a/src/contrib/zlib/FAQ +++ /dev/null @@ -1,368 +0,0 @@ - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://marknelson.us/1997/01/01/zlib-engine/ - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress(), the length of the compressed - buffer is equal to the available size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not zero. - When setting the parameter flush equal to Z_FINISH, also make sure that - avail_out is big enough to allow processing all pending input. Note that a - Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be - made with more input or output space. A Z_BUF_ERROR may in fact be - unavoidable depending on how the functions are used, since it is not - possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a - heavily annotated example. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h . Examples of zlib usage are in the files test/example.c - and test/minigzip.c, with more in examples/ . - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple package. - zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of zlib. - Please try to reproduce the problem with a small program and send the - corresponding source to us at zlib@gzip.org . Do not send multi-megabyte - data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - By default a shared (and a static) library is built for Unix. So: - - make distclean - ./configure - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to - it. You can check the version at the top of zlib.h or with the - ZLIB_VERSION symbol defined in zlib.h . - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip formats - use the same compressed data format internally, but have different headers - and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about a - single file, such as the name and last modification date. The zlib format - on the other hand was designed for in-memory and communication channel - applications, and has a much more compact header and trailer and uses a - faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode the - gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's *Init* functions - allow for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - Yes. It has been tested on 64-bit machines, and has no dependence on any - data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format than - does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically use - Z_FULL_FLUSH, carefully write all the pending data at those points, and - keep an index of those locations, then you can start decompression at those - points. You have to be careful to not use Z_FULL_FLUSH too often, since it - can significantly degrade compression. Alternatively, you can scan a - deflate stream once to generate an index, and then use that index for - random access. See examples/zran.c . - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - It has in the past, but we have not heard of any recent evidence. There - were working ports of zlib 1.1.4 to MVS, but those links no longer work. - If you know of recent, successful applications of zlib on these operating - systems, please let us know. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at to - understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit only - if the compiler's "long" type is 32 bits. If the compiler's "long" type is - 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib is - compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of an 8K string space (or other value as set by - gzbuffer()), other than the caller of gzprintf() assuring that the output - will not exceed 8K. On the other hand, if zlib is compiled to use - snprintf() or vsnprintf(), which should normally be the case, then there is - no vulnerability. The ./configure script will display warnings if an - insecure variation of sprintf() will be used by gzprintf(). Also the - zlibCompileFlags() function will return information on what variant of - sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability, and versions - 1.2.1 and 1.2.2 were subject to an access exception when decompressing - invalid compressed data. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly as well as contradicted each other. So now, we simply - make sure that the code always works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of deflate - is not affected. This only started showing up recently since zlib 1.2.x - uses malloc() by default for allocations, whereas earlier versions used - calloc(), which zeros out the allocated memory. Even though the code was - correct, versions 1.2.4 and later was changed to not stimulate these - checkers. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very - weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib - compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion with - the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specification in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. In - any case, the compression improvements are so modest compared to other more - modern approaches, that it's not worth the effort to implement. - -41. I'm having a problem with the zip functions in zlib, can you help? - - There are no zip functions in zlib. You are probably using minizip by - Giles Vollant, which is found in the contrib directory of zlib. It is not - part of zlib. In fact none of the stuff in contrib is part of zlib. The - files in there are not supported by the zlib authors. You need to contact - the authors of the respective contribution for help. - -42. The match.asm code in contrib is under the GNU General Public License. - Since it's part of zlib, doesn't that mean that all of zlib falls under the - GNU GPL? - - No. The files in contrib are not part of zlib. They were contributed by - other authors and are provided as a convenience to the user within the zlib - distribution. Each item in contrib has its own license. - -43. Is zlib subject to export controls? What is its ECCN? - - zlib is not subject to export controls, and so is classified as EAR99. - -44. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. diff --git a/src/contrib/zlib/INDEX b/src/contrib/zlib/INDEX deleted file mode 100644 index 2ba0641..0000000 --- a/src/contrib/zlib/INDEX +++ /dev/null @@ -1,68 +0,0 @@ -CMakeLists.txt cmake build file -ChangeLog history of changes -FAQ Frequently Asked Questions about zlib -INDEX this file -Makefile dummy Makefile that tells you to ./configure -Makefile.in template for Unix Makefile -README guess what -configure configure script for Unix -make_vms.com makefile for VMS -test/example.c zlib usages examples for build testing -test/minigzip.c minimal gzip-like functionality for build testing -test/infcover.c inf*.c code coverage for build coverage testing -treebuild.xml XML description of source file dependencies -zconf.h.cmakein zconf.h template for cmake -zconf.h.in zconf.h template for configure -zlib.3 Man page for zlib -zlib.3.pdf Man page in PDF format -zlib.map Linux symbol information -zlib.pc.in Template for pkg-config descriptor -zlib.pc.cmakein zlib.pc template for cmake -zlib2ansi perl script to convert source files for C++ compilation - -amiga/ makefiles for Amiga SAS C -as400/ makefiles for AS/400 -doc/ documentation for formats and algorithms -msdos/ makefiles for MSDOS -nintendods/ makefile for Nintendo DS -old/ makefiles for various architectures and zlib documentation - files that have not yet been updated for zlib 1.2.x -qnx/ makefiles for QNX -watcom/ makefiles for OpenWatcom -win32/ makefiles for Windows - - zlib public header files (required for library use): -zconf.h -zlib.h - - private source files used to build the zlib library: -adler32.c -compress.c -crc32.c -crc32.h -deflate.c -deflate.h -gzclose.c -gzguts.h -gzlib.c -gzread.c -gzwrite.c -infback.c -inffast.c -inffast.h -inffixed.h -inflate.c -inflate.h -inftrees.c -inftrees.h -trees.c -trees.h -uncompr.c -zutil.c -zutil.h - - source files for sample programs -See examples/README.examples - - unsupported contributions by third parties -See contrib/README.contrib diff --git a/src/contrib/zlib/Makefile b/src/contrib/zlib/Makefile deleted file mode 100644 index 6bba86c..0000000 --- a/src/contrib/zlib/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: - -@echo "Please use ./configure first. Thank you." - -distclean: - make -f Makefile.in distclean diff --git a/src/contrib/zlib/Makefile.in b/src/contrib/zlib/Makefile.in deleted file mode 100644 index 5a77949..0000000 --- a/src/contrib/zlib/Makefile.in +++ /dev/null @@ -1,410 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# ./configure; make test -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static - -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -CC=cc - -CFLAGS=-O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DZLIB_DEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -SFLAGS=-O -LDFLAGS= -TEST_LDFLAGS=-L. libz.a -LDSHARED=$(CC) -CPP=$(CC) -E - -STATICLIB=libz.a -SHAREDLIB=libz.so -SHAREDLIBV=libz.so.1.2.11 -SHAREDLIBM=libz.so.1 -LIBS=$(STATICLIB) $(SHAREDLIBV) - -AR=ar -ARFLAGS=rc -RANLIB=ranlib -LDCONFIG=ldconfig -LDSHAREDLIBC=-lc -TAR=tar -SHELL=/bin/sh -EXE= - -prefix = /usr/local -exec_prefix = ${prefix} -libdir = ${exec_prefix}/lib -sharedlibdir = ${libdir} -includedir = ${prefix}/include -mandir = ${prefix}/share/man -man3dir = ${mandir}/man3 -pkgconfigdir = ${libdir}/pkgconfig -SRCDIR= -ZINC= -ZINCOUT=-I. - -OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o -OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o -OBJC = $(OBJZ) $(OBJG) - -PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo -PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo -PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) - -# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo -OBJA = -PIC_OBJA = - -OBJS = $(OBJC) $(OBJA) - -PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) - -all: static shared - -static: example$(EXE) minigzip$(EXE) - -shared: examplesh$(EXE) minigzipsh$(EXE) - -all64: example64$(EXE) minigzip64$(EXE) - -check: test - -test: all teststatic testshared - -teststatic: static - @TMPST=tmpst_$$; \ - if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; false; \ - fi; \ - rm -f $$TMPST - -testshared: shared - @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ - DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ - SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ - TMPSH=tmpsh_$$; \ - if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ - echo ' *** zlib shared test OK ***'; \ - else \ - echo ' *** zlib shared test FAILED ***'; false; \ - fi; \ - rm -f $$TMPSH - -test64: all64 - @TMP64=tmp64_$$; \ - if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ - echo ' *** zlib 64-bit test OK ***'; \ - else \ - echo ' *** zlib 64-bit test FAILED ***'; false; \ - fi; \ - rm -f $$TMP64 - -infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c - -infcover: infcover.o libz.a - $(CC) $(CFLAGS) -o $@ infcover.o libz.a - -cover: infcover - rm -f *.gcda - ./infcover - gcov inf*.c - -libz.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -match.o: match.S - $(CPP) match.S > _match.s - $(CC) -c _match.s - mv _match.o match.o - rm -f _match.s - -match.lo: match.S - $(CPP) match.S > _match.s - $(CC) -c -fPIC _match.s - mv _match.o match.lo - rm -f _match.s - -example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c - -minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c - -example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c - -minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h - $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c - - -adler32.o: $(SRCDIR)adler32.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c - -crc32.o: $(SRCDIR)crc32.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c - -deflate.o: $(SRCDIR)deflate.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c - -infback.o: $(SRCDIR)infback.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c - -inffast.o: $(SRCDIR)inffast.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c - -inflate.o: $(SRCDIR)inflate.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c - -inftrees.o: $(SRCDIR)inftrees.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c - -trees.o: $(SRCDIR)trees.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c - -zutil.o: $(SRCDIR)zutil.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c - -compress.o: $(SRCDIR)compress.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c - -uncompr.o: $(SRCDIR)uncompr.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c - -gzclose.o: $(SRCDIR)gzclose.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c - -gzlib.o: $(SRCDIR)gzlib.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c - -gzread.o: $(SRCDIR)gzread.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c - -gzwrite.o: $(SRCDIR)gzwrite.c - $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c - - -adler32.lo: $(SRCDIR)adler32.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c - -@mv objs/adler32.o $@ - -crc32.lo: $(SRCDIR)crc32.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c - -@mv objs/crc32.o $@ - -deflate.lo: $(SRCDIR)deflate.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c - -@mv objs/deflate.o $@ - -infback.lo: $(SRCDIR)infback.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c - -@mv objs/infback.o $@ - -inffast.lo: $(SRCDIR)inffast.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c - -@mv objs/inffast.o $@ - -inflate.lo: $(SRCDIR)inflate.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c - -@mv objs/inflate.o $@ - -inftrees.lo: $(SRCDIR)inftrees.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c - -@mv objs/inftrees.o $@ - -trees.lo: $(SRCDIR)trees.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c - -@mv objs/trees.o $@ - -zutil.lo: $(SRCDIR)zutil.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c - -@mv objs/zutil.o $@ - -compress.lo: $(SRCDIR)compress.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c - -@mv objs/compress.o $@ - -uncompr.lo: $(SRCDIR)uncompr.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c - -@mv objs/uncompr.o $@ - -gzclose.lo: $(SRCDIR)gzclose.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c - -@mv objs/gzclose.o $@ - -gzlib.lo: $(SRCDIR)gzlib.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c - -@mv objs/gzlib.o $@ - -gzread.lo: $(SRCDIR)gzread.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c - -@mv objs/gzread.o $@ - -gzwrite.lo: $(SRCDIR)gzwrite.c - -@mkdir objs 2>/dev/null || test -d objs - $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c - -@mv objs/gzwrite.o $@ - - -placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a - $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) - rm -f $(SHAREDLIB) $(SHAREDLIBM) - ln -s $@ $(SHAREDLIB) - ln -s $@ $(SHAREDLIBM) - -@rmdir objs - -example$(EXE): example.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) - -minigzip$(EXE): minigzip.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) - -examplesh$(EXE): example.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) - -minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) - $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) - -example64$(EXE): example64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) - -minigzip64$(EXE): minigzip64.o $(STATICLIB) - $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) - -install-libs: $(LIBS) - -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi - -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi - -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi - -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi - -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi - rm -f $(DESTDIR)$(libdir)/$(STATICLIB) - cp $(STATICLIB) $(DESTDIR)$(libdir) - chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) - -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 - -@if test -n "$(SHAREDLIBV)"; then \ - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ - cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ - echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ - chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ - echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ - ($(LDCONFIG) || true) >/dev/null 2>&1; \ - fi - rm -f $(DESTDIR)$(man3dir)/zlib.3 - cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) - chmod 644 $(DESTDIR)$(man3dir)/zlib.3 - rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc - cp zlib.pc $(DESTDIR)$(pkgconfigdir) - chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc -# The ranlib in install is needed on NeXTSTEP which checks file times -# ldconfig is for Linux - -install: install-libs - -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi - rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h - cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) - chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h - -uninstall: - cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h - cd $(DESTDIR)$(libdir) && rm -f libz.a; \ - if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ - rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ - fi - cd $(DESTDIR)$(man3dir) && rm -f zlib.3 - cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc - -docs: zlib.3.pdf - -zlib.3.pdf: $(SRCDIR)zlib.3 - groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ - -zconf.h.cmakein: $(SRCDIR)zconf.h.in - -@ TEMPFILE=zconfh_$$; \ - echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ - sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ - touch -r $(SRCDIR)zconf.h.in $@ &&\ - rm $$TEMPFILE - -zconf: $(SRCDIR)zconf.h.in - cp -p $(SRCDIR)zconf.h.in zconf.h - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ \ - example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ - example64$(EXE) minigzip64$(EXE) \ - infcover \ - libz.* foo.gz so_locations \ - _match.s maketree contrib/infback9/*.o - rm -rf objs - rm -f *.gcda *.gcno *.gcov - rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov - -maintainer-clean: distclean -distclean: clean zconf zconf.h.cmakein docs - rm -f Makefile zlib.pc configure.log - -@rm -f .DS_Store - @if [ -f Makefile.in ]; then \ - printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ - printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ - touch -r $(SRCDIR)Makefile.in Makefile ; fi - @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi - @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi - -tags: - etags $(SRCDIR)*.[ch] - -adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h -compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h -crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h -deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h -inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h -inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h -trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h - -adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h -compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h -crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h -deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h -infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h -inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h -inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h -trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h diff --git a/src/contrib/zlib/README b/src/contrib/zlib/README deleted file mode 100644 index 51106de..0000000 --- a/src/contrib/zlib/README +++ /dev/null @@ -1,115 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and -rfc1952 (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file test/example.c which also tests that -the library is working correctly. Another example is given in the file -test/minigzip.c. The compression library itself is composed of all source -files in the root directory. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use -one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use -make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available at -http://marknelson.us/1997/01/01/zlib-engine/ . - -The changes made in version 1.2.11 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory contrib/ . - -zlib is available in Java using the java.util.zip package, documented at -http://java.sun.com/developer/technicalArticles/Programming/compression/ . - -A Perl interface to zlib written by Paul Marquess is available -at CPAN (Comprehensive Perl Archive Network) sites, including -http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://docs.python.org/library/zlib.html . - -zlib is built into tcl: http://wiki.tcl.tk/4610 . - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS or BEOS. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate and - zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; they - are too numerous to cite here. - -Copyright notice: - - (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/src/contrib/zlib/adler32.c b/src/contrib/zlib/adler32.c deleted file mode 100644 index d0be438..0000000 --- a/src/contrib/zlib/adler32.c +++ /dev/null @@ -1,186 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - -#define BASE 65521U /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware -- - try it both ways to see which is faster */ -#ifdef NO_DIVIDE -/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 - (thank you to John Reiser for pointing this out) */ -# define CHOP(a) \ - do { \ - unsigned long tmp = a >> 16; \ - a &= 0xffffUL; \ - a += (tmp << 4) - tmp; \ - } while (0) -# define MOD28(a) \ - do { \ - CHOP(a); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD(a) \ - do { \ - CHOP(a); \ - MOD28(a); \ - } while (0) -# define MOD63(a) \ - do { /* this assumes a is not negative */ \ - z_off64_t tmp = a >> 32; \ - a &= 0xffffffffL; \ - a += (tmp << 8) - (tmp << 5) + tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - tmp = a >> 16; \ - a &= 0xffffL; \ - a += (tmp << 4) - tmp; \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD28(a) a %= BASE -# define MOD63(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32_z(adler, buf, len) - uLong adler; - const Bytef *buf; - z_size_t len; -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD28(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - return adler32_z(adler, buf, len); -} - -/* ========================================================================= */ -local uLong adler32_combine_(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffffUL; - - /* the derivation of this formula is left as an exercise for the reader */ - MOD63(len2); /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ - return adler32_combine_(adler1, adler2, len2); -} - -uLong ZEXPORT adler32_combine64(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ - return adler32_combine_(adler1, adler2, len2); -} diff --git a/src/contrib/zlib/amiga/Makefile.pup b/src/contrib/zlib/amiga/Makefile.pup deleted file mode 100644 index 8940c12..0000000 --- a/src/contrib/zlib/amiga/Makefile.pup +++ /dev/null @@ -1,69 +0,0 @@ -# Amiga powerUP (TM) Makefile -# makefile for libpng and SAS C V6.58/7.00 PPC compiler -# Copyright (C) 1998 by Andreas R. Kleinert - -LIBNAME = libzip.a - -CC = scppc -CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ - OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER -AR = ppc-amigaos-ar cr -RANLIB = ppc-amigaos-ranlib -LD = ppc-amigaos-ld -r -LDFLAGS = -o -LDLIBS = LIB:scppc.a LIB:end.o -RM = delete quiet - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: example minigzip - -check: test -test: all - example - echo hello world | minigzip | minigzip -d - -$(LIBNAME): $(OBJS) - $(AR) $@ $(OBJS) - -$(RANLIB) $@ - -example: example.o $(LIBNAME) - $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) - -minigzip: minigzip.o $(LIBNAME) - $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) - -mostlyclean: clean -clean: - $(RM) *.o example minigzip $(LIBNAME) foo.gz - -zip: - zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ - descrip.mms *.[ch] - -tgz: - cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ - zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzclose.o: zlib.h zconf.h gzguts.h -gzlib.o: zlib.h zconf.h gzguts.h -gzread.o: zlib.h zconf.h gzguts.h -gzwrite.o: zlib.h zconf.h gzguts.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/src/contrib/zlib/amiga/Makefile.sas b/src/contrib/zlib/amiga/Makefile.sas deleted file mode 100644 index 749e291..0000000 --- a/src/contrib/zlib/amiga/Makefile.sas +++ /dev/null @@ -1,68 +0,0 @@ -# SMakefile for zlib -# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly -# Osma Ahvenlampi -# Amiga, SAS/C 6.56 & Smake - -CC=sc -CFLAGS=OPT -#CFLAGS=OPT CPU=68030 -#CFLAGS=DEBUG=LINE -LDFLAGS=LIB z.lib - -SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ - NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \ - DEF=POSTINC - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: SCOPTIONS example minigzip - -check: test -test: all - example - echo hello world | minigzip | minigzip -d - -install: z.lib - copy clone zlib.h zconf.h INCLUDE: - copy clone z.lib LIB: - -z.lib: $(OBJS) - oml z.lib r $(OBJS) - -example: example.o z.lib - $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) - -minigzip: minigzip.o z.lib - $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) - -mostlyclean: clean -clean: - -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS - -SCOPTIONS: Makefile.sas - copy to $@ (uLong)max ? max : (uInt)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; - sourceLen -= stream.avail_in; - } - err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); - } while (err == Z_OK); - - *destLen = stream.total_out; - deflateEnd(&stream); - return err == Z_STREAM_END ? Z_OK : err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound (sourceLen) - uLong sourceLen; -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13; -} diff --git a/src/contrib/zlib/configure b/src/contrib/zlib/configure deleted file mode 100644 index e974d1f..0000000 --- a/src/contrib/zlib/configure +++ /dev/null @@ -1,921 +0,0 @@ -#!/bin/sh -# configure script for zlib. -# -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static -# -# To impose specific compiler or flags or install directory, use for example: -# prefix=$HOME CC=cc CFLAGS="-O4" ./configure -# or for csh/tcsh users: -# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) - -# Incorrect settings of CC or CFLAGS may prevent creating a shared library. -# If you have problems, try without defining CC and CFLAGS before reporting -# an error. - -# start off configure.log -echo -------------------- >> configure.log -echo $0 $* >> configure.log -date >> configure.log - -# get source directory -SRCDIR=`dirname $0` -if test $SRCDIR = "."; then - ZINC="" - ZINCOUT="-I." - SRCDIR="" -else - ZINC='-include zconf.h' - ZINCOUT='-I. -I$(SRCDIR)' - SRCDIR="$SRCDIR/" -fi - -# set command prefix for cross-compilation -if [ -n "${CHOST}" ]; then - uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" - CROSS_PREFIX="${CHOST}-" -fi - -# destination name for static library -STATICLIB=libz.a - -# extract zlib version numbers from zlib.h -VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` -VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` -VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` -VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` - -# establish commands for library building -if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then - AR=${AR-"${CROSS_PREFIX}ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -else - AR=${AR-"ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -fi -ARFLAGS=${ARFLAGS-"rc"} -if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then - RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} - test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log -else - RANLIB=${RANLIB-"ranlib"} -fi -if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then - NM=${NM-"${CROSS_PREFIX}nm"} - test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log -else - NM=${NM-"nm"} -fi - -# set defaults before processing command line options -LDCONFIG=${LDCONFIG-"ldconfig"} -LDSHAREDLIBC="${LDSHAREDLIBC--lc}" -ARCHS= -prefix=${prefix-/usr/local} -exec_prefix=${exec_prefix-'${prefix}'} -libdir=${libdir-'${exec_prefix}/lib'} -sharedlibdir=${sharedlibdir-'${libdir}'} -includedir=${includedir-'${prefix}/include'} -mandir=${mandir-'${prefix}/share/man'} -shared_ext='.so' -shared=1 -solo=0 -cover=0 -zprefix=0 -zconst=0 -build64=0 -gcc=0 -warn=0 -debug=0 -old_cc="$CC" -old_cflags="$CFLAGS" -OBJC='$(OBJZ) $(OBJG)' -PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)' - -# leave this script, optionally in a bad way -leave() -{ - if test "$*" != "0"; then - echo "** $0 aborting." | tee -a configure.log - fi - rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version - echo -------------------- >> configure.log - echo >> configure.log - echo >> configure.log - exit $1 -} - -# process command line options -while test $# -ge 1 -do -case "$1" in - -h* | --help) - echo 'usage:' | tee -a configure.log - echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log - echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log - echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log - exit 0 ;; - -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; - --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; - -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; - -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; - -p* | --prefix) prefix="$2"; shift; shift ;; - -e* | --eprefix) exec_prefix="$2"; shift; shift ;; - -l* | --libdir) libdir="$2"; shift; shift ;; - -i* | --includedir) includedir="$2"; shift; shift ;; - -s* | --shared | --enable-shared) shared=1; shift ;; - -t | --static) shared=0; shift ;; - --solo) solo=1; shift ;; - --cover) cover=1; shift ;; - -z* | --zprefix) zprefix=1; shift ;; - -6* | --64) build64=1; shift ;; - -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; - --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; - --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; - -c* | --const) zconst=1; shift ;; - -w* | --warn) warn=1; shift ;; - -d* | --debug) debug=1; shift ;; - *) - echo "unknown option: $1" | tee -a configure.log - echo "$0 --help for help" | tee -a configure.log - leave 1;; - esac -done - -# temporary file name -test=ztest$$ - -# put arguments in log, also put test file in log if used in arguments -show() -{ - case "$*" in - *$test.c*) - echo === $test.c === >> configure.log - cat $test.c >> configure.log - echo === >> configure.log;; - esac - echo $* >> configure.log -} - -# check for gcc vs. cc and set compile and link flags based on the system identified by uname -cat > $test.c <&1` in - *gcc*) gcc=1 ;; - *clang*) gcc=1 ;; -esac - -show $cc -c $test.c -if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then - echo ... using gcc >> configure.log - CC="$cc" - CFLAGS="${CFLAGS--O3}" - SFLAGS="${CFLAGS--O3} -fPIC" - if test "$ARCHS"; then - CFLAGS="${CFLAGS} ${ARCHS}" - LDFLAGS="${LDFLAGS} ${ARCHS}" - fi - if test $build64 -eq 1; then - CFLAGS="${CFLAGS} -m64" - SFLAGS="${SFLAGS} -m64" - fi - if test "$warn" -eq 1; then - if test "$zconst" -eq 1; then - CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" - else - CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" - fi - fi - if test $debug -eq 1; then - CFLAGS="${CFLAGS} -DZLIB_DEBUG" - SFLAGS="${SFLAGS} -DZLIB_DEBUG" - fi - if test -z "$uname"; then - uname=`(uname -s || echo unknown) 2>/dev/null` - fi - case "$uname" in - Linux* | linux* | GNU | GNU/* | solaris*) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; - *BSD | *bsd* | DragonFly) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} - LDCONFIG="ldconfig -m" ;; - CYGWIN* | Cygwin* | cygwin* | OS/2*) - EXE='.exe' ;; - MINGW* | mingw*) -# temporary bypass - rm -f $test.[co] $test $test$shared_ext - echo "Please use win32/Makefile.gcc instead." | tee -a configure.log - leave 1 - LDSHARED=${LDSHARED-"$cc -shared"} - LDSHAREDLIBC="" - EXE='.exe' ;; - QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; - HP-UX*) - LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - Darwin* | darwin*) - shared_ext='.dylib' - SHAREDLIB=libz$shared_ext - SHAREDLIBV=libz.$VER$shared_ext - SHAREDLIBM=libz.$VER1$shared_ext - LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} - if libtool -V 2>&1 | grep Apple > /dev/null; then - AR="libtool" - else - AR="/usr/bin/libtool" - fi - ARFLAGS="-o" ;; - *) LDSHARED=${LDSHARED-"$cc -shared"} ;; - esac -else - # find system name and corresponding cc options - CC=${CC-cc} - gcc=0 - echo ... using $CC >> configure.log - if test -z "$uname"; then - uname=`(uname -sr || echo unknown) 2>/dev/null` - fi - case "$uname" in - HP-UX*) SFLAGS=${CFLAGS-"-O +z"} - CFLAGS=${CFLAGS-"-O"} -# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} - LDSHARED=${LDSHARED-"ld -b"} - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='libz.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='libz.sl' ;; - esac ;; - IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} - CFLAGS=${CFLAGS-"-ansi -O2"} - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; - OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDFLAGS="${LDFLAGS} -Wl,-rpath,." - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; - OSF1*) SFLAGS=${CFLAGS-"-O -std1"} - CFLAGS=${CFLAGS-"-O -std1"} - LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; - QNX*) SFLAGS=${CFLAGS-"-4 -O"} - CFLAGS=${CFLAGS-"-4 -O"} - LDSHARED=${LDSHARED-"cc"} - RANLIB=${RANLIB-"true"} - AR="cc" - ARFLAGS="-A" ;; - SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} - CFLAGS=${CFLAGS-"-O3"} - LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; - SunOS\ 5* | solaris*) - LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"} - SFLAGS=${CFLAGS-"-fast -KPIC"} - CFLAGS=${CFLAGS-"-fast"} - if test $build64 -eq 1; then - # old versions of SunPRO/Workshop/Studio don't support -m64, - # but newer ones do. Check for it. - flag64=`$CC -flags | egrep -- '^-m64'` - if test x"$flag64" != x"" ; then - CFLAGS="${CFLAGS} -m64" - SFLAGS="${SFLAGS} -m64" - else - case `(uname -m || echo unknown) 2>/dev/null` in - i86*) - SFLAGS="$SFLAGS -xarch=amd64" - CFLAGS="$CFLAGS -xarch=amd64" ;; - *) - SFLAGS="$SFLAGS -xarch=v9" - CFLAGS="$CFLAGS -xarch=v9" ;; - esac - fi - fi - if test -n "$ZINC"; then - ZINC='-I- -I. -I$(SRCDIR)' - fi - ;; - SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} - CFLAGS=${CFLAGS-"-O2"} - LDSHARED=${LDSHARED-"ld"} ;; - SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} - CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} - LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; - UNIX_System_V\ 4.2.0) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - UNIX_SV\ 4.2MP) - SFLAGS=${CFLAGS-"-Kconform_pic -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - OpenUNIX\ 5) - SFLAGS=${CFLAGS-"-KPIC -O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -G"} ;; - AIX*) # Courtesy of dbakker@arrayasolutions.com - SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - LDSHARED=${LDSHARED-"xlc -G"} ;; - # send working options for other systems to zlib@gzip.org - *) SFLAGS=${CFLAGS-"-O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc -shared"} ;; - esac -fi - -# destination names for shared library if not defined above -SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} -SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} -SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} - -echo >> configure.log - -# define functions for testing compiler and library characteristics and logging the results - -cat > $test.c </dev/null; then - try() - { - show $* - test "`( $* ) 2>&1 | tee -a configure.log`" = "" - } - echo - using any output from compiler to indicate an error >> configure.log -else - try() - { - show $* - ( $* ) >> configure.log 2>&1 - ret=$? - if test $ret -ne 0; then - echo "(exit code "$ret")" >> configure.log - fi - return $ret - } -fi - -tryboth() -{ - show $* - got=`( $* ) 2>&1` - ret=$? - printf %s "$got" >> configure.log - if test $ret -ne 0; then - return $ret - fi - test "$got" = "" -} - -cat > $test.c << EOF -int foo() { return 0; } -EOF -echo "Checking for obsessive-compulsive compiler options..." >> configure.log -if try $CC -c $CFLAGS $test.c; then - : -else - echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log - leave 1 -fi - -echo >> configure.log - -# see if shared library build supported -cat > $test.c <> configure.log - show "$NM $test.o | grep _hello" - if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then - CPP="$CPP -DNO_UNDERLINE" - echo Checking for underline in external names... No. | tee -a configure.log - else - echo Checking for underline in external names... Yes. | tee -a configure.log - fi ;; -esac - -echo >> configure.log - -# check for size_t -cat > $test.c < -#include -size_t dummy = 0; -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Checking for size_t... Yes." | tee -a configure.log - need_sizet=0 -else - echo "Checking for size_t... No." | tee -a configure.log - need_sizet=1 -fi - -echo >> configure.log - -# find the size_t integer type, if needed -if test $need_sizet -eq 1; then - cat > $test.c < $test.c < -int main(void) { - if (sizeof(void *) <= sizeof(int)) puts("int"); - else if (sizeof(void *) <= sizeof(long)) puts("long"); - else puts("z_longlong"); - return 0; -} -EOF - else - echo "Checking for long long... No." | tee -a configure.log - cat > $test.c < -int main(void) { - if (sizeof(void *) <= sizeof(int)) puts("int"); - else puts("long"); - return 0; -} -EOF - fi - if try $CC $CFLAGS -o $test $test.c; then - sizet=`./$test` - echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log - else - echo "Failed to find a pointer-size integer type." | tee -a configure.log - leave 1 - fi -fi - -if test $need_sizet -eq 1; then - CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}" - SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}" -fi - -echo >> configure.log - -# check for large file support, and if none, check for fseeko() -cat > $test.c < -off64_t dummy = 0; -EOF -if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then - CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" - SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" - ALL="${ALL} all64" - TEST="${TEST} test64" - echo "Checking for off64_t... Yes." | tee -a configure.log - echo "Checking for fseeko... Yes." | tee -a configure.log -else - echo "Checking for off64_t... No." | tee -a configure.log - echo >> configure.log - cat > $test.c < -int main(void) { - fseeko(NULL, 0, 0); - return 0; -} -EOF - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for fseeko... Yes." | tee -a configure.log - else - CFLAGS="${CFLAGS} -DNO_FSEEKO" - SFLAGS="${SFLAGS} -DNO_FSEEKO" - echo "Checking for fseeko... No." | tee -a configure.log - fi -fi - -echo >> configure.log - -# check for strerror() for use by gz* functions -cat > $test.c < -#include -int main() { return strlen(strerror(errno)); } -EOF -if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for strerror... Yes." | tee -a configure.log -else - CFLAGS="${CFLAGS} -DNO_STRERROR" - SFLAGS="${SFLAGS} -DNO_STRERROR" - echo "Checking for strerror... No." | tee -a configure.log -fi - -# copy clean zconf.h for subsequent edits -cp -p ${SRCDIR}zconf.h.in zconf.h - -echo >> configure.log - -# check for unistd.h and save result in zconf.h -cat > $test.c < -int main() { return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo "Checking for unistd.h... Yes." | tee -a configure.log -else - echo "Checking for unistd.h... No." | tee -a configure.log -fi - -echo >> configure.log - -# check for stdarg.h and save result in zconf.h -cat > $test.c < -int main() { return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo "Checking for stdarg.h... Yes." | tee -a configure.log -else - echo "Checking for stdarg.h... No." | tee -a configure.log -fi - -# if the z_ prefix was requested, save that in zconf.h -if test $zprefix -eq 1; then - sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h - mv zconf.temp.h zconf.h - echo >> configure.log - echo "Using z_ prefix on all symbols." | tee -a configure.log -fi - -# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists -if test $solo -eq 1; then - sed '/#define ZCONF_H/a\ -#define Z_SOLO - -' < zconf.h > zconf.temp.h - mv zconf.temp.h zconf.h -OBJC='$(OBJZ)' -PIC_OBJC='$(PIC_OBJZ)' -fi - -# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X -if test $cover -eq 1; then - CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" - if test -n "$GCC_CLASSIC"; then - CC=$GCC_CLASSIC - fi -fi - -echo >> configure.log - -# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions -# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a -# return value. The most secure result is vsnprintf() with a return value. snprintf() with a -# return value is secure as well, but then gzprintf() will be limited to 20 arguments. -cat > $test.c < -#include -#include "zconf.h" -int main() -{ -#ifndef STDC - choke me -#endif - return 0; -} -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log - - echo >> configure.log - cat > $test.c < -#include -int mytest(const char *fmt, ...) -{ - char buf[20]; - va_list ap; - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return 0; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -#include -int mytest(const char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - va_start(ap, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return n; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_vsnprintf_void" - SFLAGS="$SFLAGS -DHAS_vsnprintf_void" - echo "Checking for return value of vsnprintf()... No." | tee -a configure.log - echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - else - CFLAGS="$CFLAGS -DNO_vsnprintf" - SFLAGS="$SFLAGS -DNO_vsnprintf" - echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log - echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log - echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -#include -int mytest(const char *fmt, ...) -{ - int n; - char buf[20]; - va_list ap; - va_start(ap, fmt); - n = vsprintf(buf, fmt, ap); - va_end(ap); - return n; -} -int main() -{ - return (mytest("Hello%d\n", 1)); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_vsprintf_void" - SFLAGS="$SFLAGS -DHAS_vsprintf_void" - echo "Checking for return value of vsprintf()... No." | tee -a configure.log - echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - fi -else - echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - snprintf(buf, sizeof(buf), "%s", "foo"); - return 0; -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC $CFLAGS -o $test $test.c; then - echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - return snprintf(buf, sizeof(buf), "%s", "foo"); -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of snprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_snprintf_void" - SFLAGS="$SFLAGS -DHAS_snprintf_void" - echo "Checking for return value of snprintf()... No." | tee -a configure.log - echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - else - CFLAGS="$CFLAGS -DNO_snprintf" - SFLAGS="$SFLAGS -DNO_snprintf" - echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log - echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log - echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - - echo >> configure.log - cat >$test.c < -int mytest() -{ - char buf[20]; - return sprintf(buf, "%s", "foo"); -} -int main() -{ - return (mytest()); -} -EOF - - if try $CC -c $CFLAGS $test.c; then - echo "Checking for return value of sprintf()... Yes." | tee -a configure.log - else - CFLAGS="$CFLAGS -DHAS_sprintf_void" - SFLAGS="$SFLAGS -DHAS_sprintf_void" - echo "Checking for return value of sprintf()... No." | tee -a configure.log - echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log - echo " can build but will be open to possible string-format security" | tee -a configure.log - echo " vulnerabilities." | tee -a configure.log - fi - fi -fi - -# see if we can hide zlib internal symbols that are linked between separate source files -if test "$gcc" -eq 1; then - echo >> configure.log - cat > $test.c <> configure.log -echo ALL = $ALL >> configure.log -echo AR = $AR >> configure.log -echo ARFLAGS = $ARFLAGS >> configure.log -echo CC = $CC >> configure.log -echo CFLAGS = $CFLAGS >> configure.log -echo CPP = $CPP >> configure.log -echo EXE = $EXE >> configure.log -echo LDCONFIG = $LDCONFIG >> configure.log -echo LDFLAGS = $LDFLAGS >> configure.log -echo LDSHARED = $LDSHARED >> configure.log -echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log -echo OBJC = $OBJC >> configure.log -echo PIC_OBJC = $PIC_OBJC >> configure.log -echo RANLIB = $RANLIB >> configure.log -echo SFLAGS = $SFLAGS >> configure.log -echo SHAREDLIB = $SHAREDLIB >> configure.log -echo SHAREDLIBM = $SHAREDLIBM >> configure.log -echo SHAREDLIBV = $SHAREDLIBV >> configure.log -echo STATICLIB = $STATICLIB >> configure.log -echo TEST = $TEST >> configure.log -echo VER = $VER >> configure.log -echo Z_U4 = $Z_U4 >> configure.log -echo SRCDIR = $SRCDIR >> configure.log -echo exec_prefix = $exec_prefix >> configure.log -echo includedir = $includedir >> configure.log -echo libdir = $libdir >> configure.log -echo mandir = $mandir >> configure.log -echo prefix = $prefix >> configure.log -echo sharedlibdir = $sharedlibdir >> configure.log -echo uname = $uname >> configure.log - -# udpate Makefile with the configure results -sed < ${SRCDIR}Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^SFLAGS *=/s#=.*#=$SFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^CPP *=/s#=.*#=$CPP# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^LDCONFIG *=/s#=.*#=$LDCONFIG# -/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# -/^EXE *=/s#=.*#=$EXE# -/^SRCDIR *=/s#=.*#=$SRCDIR# -/^ZINC *=/s#=.*#=$ZINC# -/^ZINCOUT *=/s#=.*#=$ZINCOUT# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^libdir *=/s#=.*#=$libdir# -/^sharedlibdir *=/s#=.*#=$sharedlibdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^OBJC *=/s#=.*#= $OBJC# -/^PIC_OBJC *=/s#=.*#= $PIC_OBJC# -/^all: */s#:.*#: $ALL# -/^test: */s#:.*#: $TEST# -" > Makefile - -# create zlib.pc with the configure results -sed < ${SRCDIR}zlib.pc.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^CPP *=/s#=.*#=$CPP# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^EXE *=/s#=.*#=$EXE# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^libdir *=/s#=.*#=$libdir# -/^sharedlibdir *=/s#=.*#=$sharedlibdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -" | sed -e " -s/\@VERSION\@/$VER/g; -" > zlib.pc - -# done -leave 0 diff --git a/src/contrib/zlib/contrib/README.contrib b/src/contrib/zlib/contrib/README.contrib deleted file mode 100644 index a411d5c..0000000 --- a/src/contrib/zlib/contrib/README.contrib +++ /dev/null @@ -1,78 +0,0 @@ -All files under this contrib directory are UNSUPPORTED. There were -provided by users of zlib and were not tested by the authors of zlib. -Use at your own risk. Please contact the authors of the contributions -for help about these, not the zlib authors. Thanks. - - -ada/ by Dmitriy Anisimkov - Support for Ada - See http://zlib-ada.sourceforge.net/ - -amd64/ by Mikhail Teterin - asm code for AMD64 - See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 - -asm686/ by Brian Raiter - asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax - See http://www.muppetlabs.com/~breadbox/software/assembly.html - -blast/ by Mark Adler - Decompressor for output of PKWare Data Compression Library (DCL) - -delphi/ by Cosmin Truta - Support for Delphi and C++ Builder - -dotzlib/ by Henrik Ravn - Support for Microsoft .Net and Visual C++ .Net - -gcc_gvmat64/by Gilles Vollant - GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64 - assembler to replace longest_match() and inflate_fast() - -infback9/ by Mark Adler - Unsupported diffs to infback to decode the deflate64 format - -inflate86/ by Chris Anderson - Tuned x86 gcc asm code to replace inflate_fast() - -iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - -iostream2/ by Tyge Løvset - Another C++ I/O streams interface - -iostream3/ by Ludwig Schwardt - and Kevin Ruland - Yet another C++ I/O streams interface - -masmx64/ by Gilles Vollant - x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to - replace longest_match() and inflate_fast(), also masm x86 - 64-bits translation of Chris Anderson inflate_fast() - -masmx86/ by Gilles Vollant - x86 asm code to replace longest_match() and inflate_fast(), - for Visual C++ and MASM (32 bits). - Based on Brian Raiter (asm686) and Chris Anderson (inflate86) - -minizip/ by Gilles Vollant - Mini zip and unzip based on zlib - Includes Zip64 support by Mathias Svensson - See http://www.winimage.com/zLibDll/minizip.html - -pascal/ by Bob Dellaca et al. - Support for Pascal - -puff/ by Mark Adler - Small, low memory usage inflate. Also serves to provide an - unambiguous description of the deflate format. - -testzlib/ by Gilles Vollant - Example of the use of zlib - -untgz/ by Pedro A. Aranda Gutierrez - A very simple tar.gz file extractor using zlib - -vstudio/ by Gilles Vollant - Building a minizip-enhanced zlib with Microsoft Visual Studio - Includes vc11 from kreuzerkrieg and vc12 from davispuh diff --git a/src/contrib/zlib/contrib/ada/buffer_demo.adb b/src/contrib/zlib/contrib/ada/buffer_demo.adb deleted file mode 100644 index 46b8638..0000000 --- a/src/contrib/zlib/contrib/ada/buffer_demo.adb +++ /dev/null @@ -1,106 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- --- --- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $ - --- This demo program provided by Dr Steve Sangwine --- --- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer --- of exactly the correct size is used for decompressed data, and the last --- few bytes passed in to Zlib are checksum bytes. - --- This program compresses a string of text, and then decompresses the --- compressed text into a buffer of the same size as the original text. - -with Ada.Streams; use Ada.Streams; -with Ada.Text_IO; - -with ZLib; use ZLib; - -procedure Buffer_Demo is - EOL : Character renames ASCII.LF; - Text : constant String - := "Four score and seven years ago our fathers brought forth," & EOL & - "upon this continent, a new nation, conceived in liberty," & EOL & - "and dedicated to the proposition that `all men are created equal'."; - - Source : Stream_Element_Array (1 .. Text'Length); - for Source'Address use Text'Address; - -begin - Ada.Text_IO.Put (Text); - Ada.Text_IO.New_Line; - Ada.Text_IO.Put_Line - ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes"); - - declare - Compressed_Data : Stream_Element_Array (1 .. Text'Length); - L : Stream_Element_Offset; - begin - Compress : declare - Compressor : Filter_Type; - I : Stream_Element_Offset; - begin - Deflate_Init (Compressor); - - -- Compress the whole of T at once. - - Translate (Compressor, Source, I, Compressed_Data, L, Finish); - pragma Assert (I = Source'Last); - - Close (Compressor); - - Ada.Text_IO.Put_Line - ("Compressed size : " - & Stream_Element_Offset'Image (L) & " bytes"); - end Compress; - - -- Now we decompress the data, passing short blocks of data to Zlib - -- (because this demonstrates the problem - the last block passed will - -- contain checksum information and there will be no output, only a - -- check inside Zlib that the checksum is correct). - - Decompress : declare - Decompressor : Filter_Type; - - Uncompressed_Data : Stream_Element_Array (1 .. Text'Length); - - Block_Size : constant := 4; - -- This makes sure that the last block contains - -- only Adler checksum data. - - P : Stream_Element_Offset := Compressed_Data'First - 1; - O : Stream_Element_Offset; - begin - Inflate_Init (Decompressor); - - loop - Translate - (Decompressor, - Compressed_Data - (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)), - P, - Uncompressed_Data - (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last), - O, - No_Flush); - - Ada.Text_IO.Put_Line - ("Total in : " & Count'Image (Total_In (Decompressor)) & - ", out : " & Count'Image (Total_Out (Decompressor))); - - exit when P = L; - end loop; - - Ada.Text_IO.New_Line; - Ada.Text_IO.Put_Line - ("Decompressed text matches original text : " - & Boolean'Image (Uncompressed_Data = Source)); - end Decompress; - end; -end Buffer_Demo; diff --git a/src/contrib/zlib/contrib/ada/mtest.adb b/src/contrib/zlib/contrib/ada/mtest.adb deleted file mode 100644 index c4dfd08..0000000 --- a/src/contrib/zlib/contrib/ada/mtest.adb +++ /dev/null @@ -1,156 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- --- Continuous test for ZLib multithreading. If the test would fail --- we should provide thread safe allocation routines for the Z_Stream. --- --- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $ - -with ZLib; -with Ada.Streams; -with Ada.Numerics.Discrete_Random; -with Ada.Text_IO; -with Ada.Exceptions; -with Ada.Task_Identification; - -procedure MTest is - use Ada.Streams; - use ZLib; - - Stop : Boolean := False; - - pragma Atomic (Stop); - - subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is - new Ada.Numerics.Discrete_Random (Visible_Symbols); - - task type Test_Task; - - task body Test_Task is - Buffer : Stream_Element_Array (1 .. 100_000); - Gen : Random_Elements.Generator; - - Buffer_First : Stream_Element_Offset; - Compare_First : Stream_Element_Offset; - - Deflate : Filter_Type; - Inflate : Filter_Type; - - procedure Further (Item : in Stream_Element_Array); - - procedure Read_Buffer - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - - ------------- - -- Further -- - ------------- - - procedure Further (Item : in Stream_Element_Array) is - - procedure Compare (Item : in Stream_Element_Array); - - ------------- - -- Compare -- - ------------- - - procedure Compare (Item : in Stream_Element_Array) is - Next_First : Stream_Element_Offset := Compare_First + Item'Length; - begin - if Buffer (Compare_First .. Next_First - 1) /= Item then - raise Program_Error; - end if; - - Compare_First := Next_First; - end Compare; - - procedure Compare_Write is new ZLib.Write (Write => Compare); - begin - Compare_Write (Inflate, Item, No_Flush); - end Further; - - ----------------- - -- Read_Buffer -- - ----------------- - - procedure Read_Buffer - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset) - is - Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First; - Next_First : Stream_Element_Offset; - begin - if Item'Length <= Buff_Diff then - Last := Item'Last; - - Next_First := Buffer_First + Item'Length; - - Item := Buffer (Buffer_First .. Next_First - 1); - - Buffer_First := Next_First; - else - Last := Item'First + Buff_Diff; - Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last); - Buffer_First := Buffer'Last + 1; - end if; - end Read_Buffer; - - procedure Translate is new Generic_Translate - (Data_In => Read_Buffer, - Data_Out => Further); - - begin - Random_Elements.Reset (Gen); - - Buffer := (others => 20); - - Main : loop - for J in Buffer'Range loop - Buffer (J) := Random_Elements.Random (Gen); - - Deflate_Init (Deflate); - Inflate_Init (Inflate); - - Buffer_First := Buffer'First; - Compare_First := Buffer'First; - - Translate (Deflate); - - if Compare_First /= Buffer'Last + 1 then - raise Program_Error; - end if; - - Ada.Text_IO.Put_Line - (Ada.Task_Identification.Image - (Ada.Task_Identification.Current_Task) - & Stream_Element_Offset'Image (J) - & ZLib.Count'Image (Total_Out (Deflate))); - - Close (Deflate); - Close (Inflate); - - exit Main when Stop; - end loop; - end loop Main; - exception - when E : others => - Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); - Stop := True; - end Test_Task; - - Test : array (1 .. 4) of Test_Task; - - pragma Unreferenced (Test); - - Dummy : Character; - -begin - Ada.Text_IO.Get_Immediate (Dummy); - Stop := True; -end MTest; diff --git a/src/contrib/zlib/contrib/ada/read.adb b/src/contrib/zlib/contrib/ada/read.adb deleted file mode 100644 index 1f2efbf..0000000 --- a/src/contrib/zlib/contrib/ada/read.adb +++ /dev/null @@ -1,156 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $ - --- Test/demo program for the generic read interface. - -with Ada.Numerics.Discrete_Random; -with Ada.Streams; -with Ada.Text_IO; - -with ZLib; - -procedure Read is - - use Ada.Streams; - - ------------------------------------ - -- Test configuration parameters -- - ------------------------------------ - - File_Size : Stream_Element_Offset := 100_000; - - Continuous : constant Boolean := False; - -- If this constant is True, the test would be repeated again and again, - -- with increment File_Size for every iteration. - - Header : constant ZLib.Header_Type := ZLib.Default; - -- Do not use Header other than Default in ZLib versions 1.1.4 and older. - - Init_Random : constant := 8; - -- We are using the same random sequence, in case of we catch bug, - -- so we would be able to reproduce it. - - -- End -- - - Pack_Size : Stream_Element_Offset; - Offset : Stream_Element_Offset; - - Filter : ZLib.Filter_Type; - - subtype Visible_Symbols - is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is new - Ada.Numerics.Discrete_Random (Visible_Symbols); - - Gen : Random_Elements.Generator; - Period : constant Stream_Element_Offset := 200; - -- Period constant variable for random generator not to be very random. - -- Bigger period, harder random. - - Read_Buffer : Stream_Element_Array (1 .. 2048); - Read_First : Stream_Element_Offset; - Read_Last : Stream_Element_Offset; - - procedure Reset; - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - -- this procedure is for generic instantiation of - -- ZLib.Read - -- reading data from the File_In. - - procedure Read is new ZLib.Read - (Read, - Read_Buffer, - Rest_First => Read_First, - Rest_Last => Read_Last); - - ---------- - -- Read -- - ---------- - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Last := Stream_Element_Offset'Min - (Item'Last, - Item'First + File_Size - Offset); - - for J in Item'First .. Last loop - if J < Item'First + Period then - Item (J) := Random_Elements.Random (Gen); - else - Item (J) := Item (J - Period); - end if; - - Offset := Offset + 1; - end loop; - end Read; - - ----------- - -- Reset -- - ----------- - - procedure Reset is - begin - Random_Elements.Reset (Gen, Init_Random); - Pack_Size := 0; - Offset := 1; - Read_First := Read_Buffer'Last + 1; - Read_Last := Read_Buffer'Last; - end Reset; - -begin - Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); - - loop - for Level in ZLib.Compression_Level'Range loop - - Ada.Text_IO.Put ("Level =" - & ZLib.Compression_Level'Image (Level)); - - -- Deflate using generic instantiation. - - ZLib.Deflate_Init - (Filter, - Level, - Header => Header); - - Reset; - - Ada.Text_IO.Put - (Stream_Element_Offset'Image (File_Size) & " ->"); - - loop - declare - Buffer : Stream_Element_Array (1 .. 1024); - Last : Stream_Element_Offset; - begin - Read (Filter, Buffer, Last); - - Pack_Size := Pack_Size + Last - Buffer'First + 1; - - exit when Last < Buffer'Last; - end; - end loop; - - Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size)); - - ZLib.Close (Filter); - end loop; - - exit when not Continuous; - - File_Size := File_Size + 1; - end loop; -end Read; diff --git a/src/contrib/zlib/contrib/ada/readme.txt b/src/contrib/zlib/contrib/ada/readme.txt deleted file mode 100644 index ce4d2ca..0000000 --- a/src/contrib/zlib/contrib/ada/readme.txt +++ /dev/null @@ -1,65 +0,0 @@ - ZLib for Ada thick binding (ZLib.Ada) - Release 1.3 - -ZLib.Ada is a thick binding interface to the popular ZLib data -compression library, available at http://www.gzip.org/zlib/. -It provides Ada-style access to the ZLib C library. - - - Here are the main changes since ZLib.Ada 1.2: - -- Attension: ZLib.Read generic routine have a initialization requirement - for Read_Last parameter now. It is a bit incompartible with previous version, - but extends functionality, we could use new parameters Allow_Read_Some and - Flush now. - -- Added Is_Open routines to ZLib and ZLib.Streams packages. - -- Add pragma Assert to check Stream_Element is 8 bit. - -- Fix extraction to buffer with exact known decompressed size. Error reported by - Steve Sangwine. - -- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits - computers. Patch provided by Pascal Obry. - -- Add Status_Error exception definition. - -- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit. - - - How to build ZLib.Ada under GNAT - -You should have the ZLib library already build on your computer, before -building ZLib.Ada. Make the directory of ZLib.Ada sources current and -issue the command: - - gnatmake test -largs -L -lz - -Or use the GNAT project file build for GNAT 3.15 or later: - - gnatmake -Pzlib.gpr -L - - - How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2 - -1. Make a project with all *.ads and *.adb files from the distribution. -2. Build the libz.a library from the ZLib C sources. -3. Rename libz.a to z.lib. -4. Add the library z.lib to the project. -5. Add the libc.lib library from the ObjectAda distribution to the project. -6. Build the executable using test.adb as a main procedure. - - - How to use ZLib.Ada - -The source files test.adb and read.adb are small demo programs that show -the main functionality of ZLib.Ada. - -The routines from the package specifications are commented. - - -Homepage: http://zlib-ada.sourceforge.net/ -Author: Dmitriy Anisimkov - -Contributors: Pascal Obry , Steve Sangwine diff --git a/src/contrib/zlib/contrib/ada/test.adb b/src/contrib/zlib/contrib/ada/test.adb deleted file mode 100644 index 90773ac..0000000 --- a/src/contrib/zlib/contrib/ada/test.adb +++ /dev/null @@ -1,463 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $ - --- The program has a few aims. --- 1. Test ZLib.Ada95 thick binding functionality. --- 2. Show the example of use main functionality of the ZLib.Ada95 binding. --- 3. Build this program automatically compile all ZLib.Ada95 packages under --- GNAT Ada95 compiler. - -with ZLib.Streams; -with Ada.Streams.Stream_IO; -with Ada.Numerics.Discrete_Random; - -with Ada.Text_IO; - -with Ada.Calendar; - -procedure Test is - - use Ada.Streams; - use Stream_IO; - - ------------------------------------ - -- Test configuration parameters -- - ------------------------------------ - - File_Size : Count := 100_000; - Continuous : constant Boolean := False; - - Header : constant ZLib.Header_Type := ZLib.Default; - -- ZLib.None; - -- ZLib.Auto; - -- ZLib.GZip; - -- Do not use Header other then Default in ZLib versions 1.1.4 - -- and older. - - Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy; - Init_Random : constant := 10; - - -- End -- - - In_File_Name : constant String := "testzlib.in"; - -- Name of the input file - - Z_File_Name : constant String := "testzlib.zlb"; - -- Name of the compressed file. - - Out_File_Name : constant String := "testzlib.out"; - -- Name of the decompressed file. - - File_In : File_Type; - File_Out : File_Type; - File_Back : File_Type; - File_Z : ZLib.Streams.Stream_Type; - - Filter : ZLib.Filter_Type; - - Time_Stamp : Ada.Calendar.Time; - - procedure Generate_File; - -- Generate file of spetsified size with some random data. - -- The random data is repeatable, for the good compression. - - procedure Compare_Streams - (Left, Right : in out Root_Stream_Type'Class); - -- The procedure compearing data in 2 streams. - -- It is for compare data before and after compression/decompression. - - procedure Compare_Files (Left, Right : String); - -- Compare files. Based on the Compare_Streams. - - procedure Copy_Streams - (Source, Target : in out Root_Stream_Type'Class; - Buffer_Size : in Stream_Element_Offset := 1024); - -- Copying data from one stream to another. It is for test stream - -- interface of the library. - - procedure Data_In - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - -- this procedure is for generic instantiation of - -- ZLib.Generic_Translate. - -- reading data from the File_In. - - procedure Data_Out (Item : in Stream_Element_Array); - -- this procedure is for generic instantiation of - -- ZLib.Generic_Translate. - -- writing data to the File_Out. - - procedure Stamp; - -- Store the timestamp to the local variable. - - procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count); - -- Print the time statistic with the message. - - procedure Translate is new ZLib.Generic_Translate - (Data_In => Data_In, - Data_Out => Data_Out); - -- This procedure is moving data from File_In to File_Out - -- with compression or decompression, depend on initialization of - -- Filter parameter. - - ------------------- - -- Compare_Files -- - ------------------- - - procedure Compare_Files (Left, Right : String) is - Left_File, Right_File : File_Type; - begin - Open (Left_File, In_File, Left); - Open (Right_File, In_File, Right); - Compare_Streams (Stream (Left_File).all, Stream (Right_File).all); - Close (Left_File); - Close (Right_File); - end Compare_Files; - - --------------------- - -- Compare_Streams -- - --------------------- - - procedure Compare_Streams - (Left, Right : in out Ada.Streams.Root_Stream_Type'Class) - is - Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#); - Left_Last, Right_Last : Stream_Element_Offset; - begin - loop - Read (Left, Left_Buffer, Left_Last); - Read (Right, Right_Buffer, Right_Last); - - if Left_Last /= Right_Last then - Ada.Text_IO.Put_Line ("Compare error :" - & Stream_Element_Offset'Image (Left_Last) - & " /= " - & Stream_Element_Offset'Image (Right_Last)); - - raise Constraint_Error; - - elsif Left_Buffer (0 .. Left_Last) - /= Right_Buffer (0 .. Right_Last) - then - Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal."); - raise Constraint_Error; - - end if; - - exit when Left_Last < Left_Buffer'Last; - end loop; - end Compare_Streams; - - ------------------ - -- Copy_Streams -- - ------------------ - - procedure Copy_Streams - (Source, Target : in out Ada.Streams.Root_Stream_Type'Class; - Buffer_Size : in Stream_Element_Offset := 1024) - is - Buffer : Stream_Element_Array (1 .. Buffer_Size); - Last : Stream_Element_Offset; - begin - loop - Read (Source, Buffer, Last); - Write (Target, Buffer (1 .. Last)); - - exit when Last < Buffer'Last; - end loop; - end Copy_Streams; - - ------------- - -- Data_In -- - ------------- - - procedure Data_In - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Read (File_In, Item, Last); - end Data_In; - - -------------- - -- Data_Out -- - -------------- - - procedure Data_Out (Item : in Stream_Element_Array) is - begin - Write (File_Out, Item); - end Data_Out; - - ------------------- - -- Generate_File -- - ------------------- - - procedure Generate_File is - subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; - - package Random_Elements is - new Ada.Numerics.Discrete_Random (Visible_Symbols); - - Gen : Random_Elements.Generator; - Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10; - - Buffer_Count : constant Count := File_Size / Buffer'Length; - -- Number of same buffers in the packet. - - Density : constant Count := 30; -- from 0 to Buffer'Length - 2; - - procedure Fill_Buffer (J, D : in Count); - -- Change the part of the buffer. - - ----------------- - -- Fill_Buffer -- - ----------------- - - procedure Fill_Buffer (J, D : in Count) is - begin - for K in 0 .. D loop - Buffer - (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1)) - := Random_Elements.Random (Gen); - - end loop; - end Fill_Buffer; - - begin - Random_Elements.Reset (Gen, Init_Random); - - Create (File_In, Out_File, In_File_Name); - - Fill_Buffer (1, Buffer'Length - 2); - - for J in 1 .. Buffer_Count loop - Write (File_In, Buffer); - - Fill_Buffer (J, Density); - end loop; - - -- fill remain size. - - Write - (File_In, - Buffer - (1 .. Stream_Element_Offset - (File_Size - Buffer'Length * Buffer_Count))); - - Flush (File_In); - Close (File_In); - end Generate_File; - - --------------------- - -- Print_Statistic -- - --------------------- - - procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is - use Ada.Calendar; - use Ada.Text_IO; - - package Count_IO is new Integer_IO (ZLib.Count); - - Curr_Dur : Duration := Clock - Time_Stamp; - begin - Put (Msg); - - Set_Col (20); - Ada.Text_IO.Put ("size ="); - - Count_IO.Put - (Data_Size, - Width => Stream_IO.Count'Image (File_Size)'Length); - - Put_Line (" duration =" & Duration'Image (Curr_Dur)); - end Print_Statistic; - - ----------- - -- Stamp -- - ----------- - - procedure Stamp is - begin - Time_Stamp := Ada.Calendar.Clock; - end Stamp; - -begin - Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); - - loop - Generate_File; - - for Level in ZLib.Compression_Level'Range loop - - Ada.Text_IO.Put_Line ("Level =" - & ZLib.Compression_Level'Image (Level)); - - -- Test generic interface. - Open (File_In, In_File, In_File_Name); - Create (File_Out, Out_File, Z_File_Name); - - Stamp; - - -- Deflate using generic instantiation. - - ZLib.Deflate_Init - (Filter => Filter, - Level => Level, - Strategy => Strategy, - Header => Header); - - Translate (Filter); - Print_Statistic ("Generic compress", ZLib.Total_Out (Filter)); - ZLib.Close (Filter); - - Close (File_In); - Close (File_Out); - - Open (File_In, In_File, Z_File_Name); - Create (File_Out, Out_File, Out_File_Name); - - Stamp; - - -- Inflate using generic instantiation. - - ZLib.Inflate_Init (Filter, Header => Header); - - Translate (Filter); - Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter)); - - ZLib.Close (Filter); - - Close (File_In); - Close (File_Out); - - Compare_Files (In_File_Name, Out_File_Name); - - -- Test stream interface. - - -- Compress to the back stream. - - Open (File_In, In_File, In_File_Name); - Create (File_Back, Out_File, Z_File_Name); - - Stamp; - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.Out_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => True, - Level => Level, - Strategy => Strategy, - Header => Header); - - Copy_Streams - (Source => Stream (File_In).all, - Target => File_Z); - - -- Flushing internal buffers to the back stream. - - ZLib.Streams.Flush (File_Z, ZLib.Finish); - - Print_Statistic ("Write compress", - ZLib.Streams.Write_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - - Close (File_In); - Close (File_Back); - - -- Compare reading from original file and from - -- decompression stream. - - Open (File_In, In_File, In_File_Name); - Open (File_Back, In_File, Z_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.In_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => True, - Header => Header); - - Stamp; - Compare_Streams (Stream (File_In).all, File_Z); - - Print_Statistic ("Read decompress", - ZLib.Streams.Read_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - Close (File_In); - Close (File_Back); - - -- Compress by reading from compression stream. - - Open (File_Back, In_File, In_File_Name); - Create (File_Out, Out_File, Z_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.In_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => False, - Level => Level, - Strategy => Strategy, - Header => Header); - - Stamp; - Copy_Streams - (Source => File_Z, - Target => Stream (File_Out).all); - - Print_Statistic ("Read compress", - ZLib.Streams.Read_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - - Close (File_Out); - Close (File_Back); - - -- Decompress to decompression stream. - - Open (File_In, In_File, Z_File_Name); - Create (File_Back, Out_File, Out_File_Name); - - ZLib.Streams.Create - (Stream => File_Z, - Mode => ZLib.Streams.Out_Stream, - Back => ZLib.Streams.Stream_Access - (Stream (File_Back)), - Back_Compressed => False, - Header => Header); - - Stamp; - - Copy_Streams - (Source => Stream (File_In).all, - Target => File_Z); - - Print_Statistic ("Write decompress", - ZLib.Streams.Write_Total_Out (File_Z)); - - ZLib.Streams.Close (File_Z); - Close (File_In); - Close (File_Back); - - Compare_Files (In_File_Name, Out_File_Name); - end loop; - - Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok."); - - exit when not Continuous; - - File_Size := File_Size + 1; - end loop; -end Test; diff --git a/src/contrib/zlib/contrib/ada/zlib-streams.adb b/src/contrib/zlib/contrib/ada/zlib-streams.adb deleted file mode 100644 index b6497ba..0000000 --- a/src/contrib/zlib/contrib/ada/zlib-streams.adb +++ /dev/null @@ -1,225 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $ - -with Ada.Unchecked_Deallocation; - -package body ZLib.Streams is - - ----------- - -- Close -- - ----------- - - procedure Close (Stream : in out Stream_Type) is - procedure Free is new Ada.Unchecked_Deallocation - (Stream_Element_Array, Buffer_Access); - begin - if Stream.Mode = Out_Stream or Stream.Mode = Duplex then - -- We should flush the data written by the writer. - - Flush (Stream, Finish); - - Close (Stream.Writer); - end if; - - if Stream.Mode = In_Stream or Stream.Mode = Duplex then - Close (Stream.Reader); - Free (Stream.Buffer); - end if; - end Close; - - ------------ - -- Create -- - ------------ - - procedure Create - (Stream : out Stream_Type; - Mode : in Stream_Mode; - Back : in Stream_Access; - Back_Compressed : in Boolean; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Header : in Header_Type := Default; - Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size) - is - - subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size); - - procedure Init_Filter - (Filter : in out Filter_Type; - Compress : in Boolean); - - ----------------- - -- Init_Filter -- - ----------------- - - procedure Init_Filter - (Filter : in out Filter_Type; - Compress : in Boolean) is - begin - if Compress then - Deflate_Init - (Filter, Level, Strategy, Header => Header); - else - Inflate_Init (Filter, Header => Header); - end if; - end Init_Filter; - - begin - Stream.Back := Back; - Stream.Mode := Mode; - - if Mode = Out_Stream or Mode = Duplex then - Init_Filter (Stream.Writer, Back_Compressed); - Stream.Buffer_Size := Write_Buffer_Size; - else - Stream.Buffer_Size := 0; - end if; - - if Mode = In_Stream or Mode = Duplex then - Init_Filter (Stream.Reader, not Back_Compressed); - - Stream.Buffer := new Buffer_Subtype; - Stream.Rest_First := Stream.Buffer'Last + 1; - Stream.Rest_Last := Stream.Buffer'Last; - end if; - end Create; - - ----------- - -- Flush -- - ----------- - - procedure Flush - (Stream : in out Stream_Type; - Mode : in Flush_Mode := Sync_Flush) - is - Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); - Last : Stream_Element_Offset; - begin - loop - Flush (Stream.Writer, Buffer, Last, Mode); - - Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last)); - - exit when Last < Buffer'Last; - end loop; - end Flush; - - ------------- - -- Is_Open -- - ------------- - - function Is_Open (Stream : Stream_Type) return Boolean is - begin - return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer); - end Is_Open; - - ---------- - -- Read -- - ---------- - - procedure Read - (Stream : in out Stream_Type; - Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) - is - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset); - - ---------- - -- Read -- - ---------- - - procedure Read - (Item : out Stream_Element_Array; - Last : out Stream_Element_Offset) is - begin - Ada.Streams.Read (Stream.Back.all, Item, Last); - end Read; - - procedure Read is new ZLib.Read - (Read => Read, - Buffer => Stream.Buffer.all, - Rest_First => Stream.Rest_First, - Rest_Last => Stream.Rest_Last); - - begin - Read (Stream.Reader, Item, Last); - end Read; - - ------------------- - -- Read_Total_In -- - ------------------- - - function Read_Total_In (Stream : in Stream_Type) return Count is - begin - return Total_In (Stream.Reader); - end Read_Total_In; - - -------------------- - -- Read_Total_Out -- - -------------------- - - function Read_Total_Out (Stream : in Stream_Type) return Count is - begin - return Total_Out (Stream.Reader); - end Read_Total_Out; - - ----------- - -- Write -- - ----------- - - procedure Write - (Stream : in out Stream_Type; - Item : in Stream_Element_Array) - is - - procedure Write (Item : in Stream_Element_Array); - - ----------- - -- Write -- - ----------- - - procedure Write (Item : in Stream_Element_Array) is - begin - Ada.Streams.Write (Stream.Back.all, Item); - end Write; - - procedure Write is new ZLib.Write - (Write => Write, - Buffer_Size => Stream.Buffer_Size); - - begin - Write (Stream.Writer, Item, No_Flush); - end Write; - - -------------------- - -- Write_Total_In -- - -------------------- - - function Write_Total_In (Stream : in Stream_Type) return Count is - begin - return Total_In (Stream.Writer); - end Write_Total_In; - - --------------------- - -- Write_Total_Out -- - --------------------- - - function Write_Total_Out (Stream : in Stream_Type) return Count is - begin - return Total_Out (Stream.Writer); - end Write_Total_Out; - -end ZLib.Streams; diff --git a/src/contrib/zlib/contrib/ada/zlib-streams.ads b/src/contrib/zlib/contrib/ada/zlib-streams.ads deleted file mode 100644 index 8e26cd4..0000000 --- a/src/contrib/zlib/contrib/ada/zlib-streams.ads +++ /dev/null @@ -1,114 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $ - -package ZLib.Streams is - - type Stream_Mode is (In_Stream, Out_Stream, Duplex); - - type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; - - type Stream_Type is - new Ada.Streams.Root_Stream_Type with private; - - procedure Read - (Stream : in out Stream_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - - procedure Write - (Stream : in out Stream_Type; - Item : in Ada.Streams.Stream_Element_Array); - - procedure Flush - (Stream : in out Stream_Type; - Mode : in Flush_Mode := Sync_Flush); - -- Flush the written data to the back stream, - -- all data placed to the compressor is flushing to the Back stream. - -- Should not be used until necessary, because it is decreasing - -- compression. - - function Read_Total_In (Stream : in Stream_Type) return Count; - pragma Inline (Read_Total_In); - -- Return total number of bytes read from back stream so far. - - function Read_Total_Out (Stream : in Stream_Type) return Count; - pragma Inline (Read_Total_Out); - -- Return total number of bytes read so far. - - function Write_Total_In (Stream : in Stream_Type) return Count; - pragma Inline (Write_Total_In); - -- Return total number of bytes written so far. - - function Write_Total_Out (Stream : in Stream_Type) return Count; - pragma Inline (Write_Total_Out); - -- Return total number of bytes written to the back stream. - - procedure Create - (Stream : out Stream_Type; - Mode : in Stream_Mode; - Back : in Stream_Access; - Back_Compressed : in Boolean; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Header : in Header_Type := Default; - Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size); - -- Create the Comression/Decompression stream. - -- If mode is In_Stream then Write operation is disabled. - -- If mode is Out_Stream then Read operation is disabled. - - -- If Back_Compressed is true then - -- Data written to the Stream is compressing to the Back stream - -- and data read from the Stream is decompressed data from the Back stream. - - -- If Back_Compressed is false then - -- Data written to the Stream is decompressing to the Back stream - -- and data read from the Stream is compressed data from the Back stream. - - -- !!! When the Need_Header is False ZLib-Ada is using undocumented - -- ZLib 1.1.4 functionality to do not create/wait for ZLib headers. - - function Is_Open (Stream : Stream_Type) return Boolean; - - procedure Close (Stream : in out Stream_Type); - -private - - use Ada.Streams; - - type Buffer_Access is access all Stream_Element_Array; - - type Stream_Type - is new Root_Stream_Type with - record - Mode : Stream_Mode; - - Buffer : Buffer_Access; - Rest_First : Stream_Element_Offset; - Rest_Last : Stream_Element_Offset; - -- Buffer for Read operation. - -- We need to have this buffer in the record - -- because not all read data from back stream - -- could be processed during the read operation. - - Buffer_Size : Stream_Element_Offset; - -- Buffer size for write operation. - -- We do not need to have this buffer - -- in the record because all data could be - -- processed in the write operation. - - Back : Stream_Access; - Reader : Filter_Type; - Writer : Filter_Type; - end record; - -end ZLib.Streams; diff --git a/src/contrib/zlib/contrib/ada/zlib-thin.adb b/src/contrib/zlib/contrib/ada/zlib-thin.adb deleted file mode 100644 index 0ca4a71..0000000 --- a/src/contrib/zlib/contrib/ada/zlib-thin.adb +++ /dev/null @@ -1,141 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $ - -package body ZLib.Thin is - - ZLIB_VERSION : constant Chars_Ptr := zlibVersion; - - Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit; - - -------------- - -- Avail_In -- - -------------- - - function Avail_In (Strm : in Z_Stream) return UInt is - begin - return Strm.Avail_In; - end Avail_In; - - --------------- - -- Avail_Out -- - --------------- - - function Avail_Out (Strm : in Z_Stream) return UInt is - begin - return Strm.Avail_Out; - end Avail_Out; - - ------------------ - -- Deflate_Init -- - ------------------ - - function Deflate_Init - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int) - return Int is - begin - return deflateInit2 - (strm, - level, - method, - windowBits, - memLevel, - strategy, - ZLIB_VERSION, - Z_Stream_Size); - end Deflate_Init; - - ------------------ - -- Inflate_Init -- - ------------------ - - function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is - begin - return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size); - end Inflate_Init; - - ------------------------ - -- Last_Error_Message -- - ------------------------ - - function Last_Error_Message (Strm : in Z_Stream) return String is - use Interfaces.C.Strings; - begin - if Strm.msg = Null_Ptr then - return ""; - else - return Value (Strm.msg); - end if; - end Last_Error_Message; - - ------------ - -- Set_In -- - ------------ - - procedure Set_In - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt) is - begin - Strm.Next_In := Buffer; - Strm.Avail_In := Size; - end Set_In; - - ------------------ - -- Set_Mem_Func -- - ------------------ - - procedure Set_Mem_Func - (Strm : in out Z_Stream; - Opaque : in Voidp; - Alloc : in alloc_func; - Free : in free_func) is - begin - Strm.opaque := Opaque; - Strm.zalloc := Alloc; - Strm.zfree := Free; - end Set_Mem_Func; - - ------------- - -- Set_Out -- - ------------- - - procedure Set_Out - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt) is - begin - Strm.Next_Out := Buffer; - Strm.Avail_Out := Size; - end Set_Out; - - -------------- - -- Total_In -- - -------------- - - function Total_In (Strm : in Z_Stream) return ULong is - begin - return Strm.Total_In; - end Total_In; - - --------------- - -- Total_Out -- - --------------- - - function Total_Out (Strm : in Z_Stream) return ULong is - begin - return Strm.Total_Out; - end Total_Out; - -end ZLib.Thin; diff --git a/src/contrib/zlib/contrib/ada/zlib-thin.ads b/src/contrib/zlib/contrib/ada/zlib-thin.ads deleted file mode 100644 index 810173c..0000000 --- a/src/contrib/zlib/contrib/ada/zlib-thin.ads +++ /dev/null @@ -1,450 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2003 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $ - -with Interfaces.C.Strings; - -with System; - -private package ZLib.Thin is - - -- From zconf.h - - MAX_MEM_LEVEL : constant := 9; -- zconf.h:105 - -- zconf.h:105 - MAX_WBITS : constant := 15; -- zconf.h:115 - -- 32K LZ77 window - -- zconf.h:115 - SEEK_SET : constant := 8#0000#; -- zconf.h:244 - -- Seek from beginning of file. - -- zconf.h:244 - SEEK_CUR : constant := 1; -- zconf.h:245 - -- Seek from current position. - -- zconf.h:245 - SEEK_END : constant := 2; -- zconf.h:246 - -- Set file pointer to EOF plus "offset" - -- zconf.h:246 - - type Byte is new Interfaces.C.unsigned_char; -- 8 bits - -- zconf.h:214 - type UInt is new Interfaces.C.unsigned; -- 16 bits or more - -- zconf.h:216 - type Int is new Interfaces.C.int; - - type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more - -- zconf.h:217 - subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr; - - type ULong_Access is access ULong; - type Int_Access is access Int; - - subtype Voidp is System.Address; -- zconf.h:232 - - subtype Byte_Access is Voidp; - - Nul : constant Voidp := System.Null_Address; - -- end from zconf - - Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125 - -- zlib.h:125 - Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126 - -- will be removed, use - -- Z_SYNC_FLUSH instead - -- zlib.h:126 - Z_SYNC_FLUSH : constant := 2; -- zlib.h:127 - -- zlib.h:127 - Z_FULL_FLUSH : constant := 3; -- zlib.h:128 - -- zlib.h:128 - Z_FINISH : constant := 4; -- zlib.h:129 - -- zlib.h:129 - Z_OK : constant := 8#0000#; -- zlib.h:132 - -- zlib.h:132 - Z_STREAM_END : constant := 1; -- zlib.h:133 - -- zlib.h:133 - Z_NEED_DICT : constant := 2; -- zlib.h:134 - -- zlib.h:134 - Z_ERRNO : constant := -1; -- zlib.h:135 - -- zlib.h:135 - Z_STREAM_ERROR : constant := -2; -- zlib.h:136 - -- zlib.h:136 - Z_DATA_ERROR : constant := -3; -- zlib.h:137 - -- zlib.h:137 - Z_MEM_ERROR : constant := -4; -- zlib.h:138 - -- zlib.h:138 - Z_BUF_ERROR : constant := -5; -- zlib.h:139 - -- zlib.h:139 - Z_VERSION_ERROR : constant := -6; -- zlib.h:140 - -- zlib.h:140 - Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145 - -- zlib.h:145 - Z_BEST_SPEED : constant := 1; -- zlib.h:146 - -- zlib.h:146 - Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147 - -- zlib.h:147 - Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148 - -- zlib.h:148 - Z_FILTERED : constant := 1; -- zlib.h:151 - -- zlib.h:151 - Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152 - -- zlib.h:152 - Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153 - -- zlib.h:153 - Z_BINARY : constant := 8#0000#; -- zlib.h:156 - -- zlib.h:156 - Z_ASCII : constant := 1; -- zlib.h:157 - -- zlib.h:157 - Z_UNKNOWN : constant := 2; -- zlib.h:158 - -- zlib.h:158 - Z_DEFLATED : constant := 8; -- zlib.h:161 - -- zlib.h:161 - Z_NULL : constant := 8#0000#; -- zlib.h:164 - -- for initializing zalloc, zfree, opaque - -- zlib.h:164 - type gzFile is new Voidp; -- zlib.h:646 - - type Z_Stream is private; - - type Z_Streamp is access all Z_Stream; -- zlib.h:89 - - type alloc_func is access function - (Opaque : Voidp; - Items : UInt; - Size : UInt) - return Voidp; -- zlib.h:63 - - type free_func is access procedure (opaque : Voidp; address : Voidp); - - function zlibVersion return Chars_Ptr; - - function Deflate (strm : Z_Streamp; flush : Int) return Int; - - function DeflateEnd (strm : Z_Streamp) return Int; - - function Inflate (strm : Z_Streamp; flush : Int) return Int; - - function InflateEnd (strm : Z_Streamp) return Int; - - function deflateSetDictionary - (strm : Z_Streamp; - dictionary : Byte_Access; - dictLength : UInt) - return Int; - - function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int; - -- zlib.h:478 - - function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495 - - function deflateParams - (strm : Z_Streamp; - level : Int; - strategy : Int) - return Int; -- zlib.h:506 - - function inflateSetDictionary - (strm : Z_Streamp; - dictionary : Byte_Access; - dictLength : UInt) - return Int; -- zlib.h:548 - - function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565 - - function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580 - - function compress - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong) - return Int; -- zlib.h:601 - - function compress2 - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong; - level : Int) - return Int; -- zlib.h:615 - - function uncompress - (dest : Byte_Access; - destLen : ULong_Access; - source : Byte_Access; - sourceLen : ULong) - return Int; - - function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile; - - function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile; - - function gzsetparams - (file : gzFile; - level : Int; - strategy : Int) - return Int; - - function gzread - (file : gzFile; - buf : Voidp; - len : UInt) - return Int; - - function gzwrite - (file : in gzFile; - buf : in Voidp; - len : in UInt) - return Int; - - function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int; - - function gzputs (file : in gzFile; s : in Chars_Ptr) return Int; - - function gzgets - (file : gzFile; - buf : Chars_Ptr; - len : Int) - return Chars_Ptr; - - function gzputc (file : gzFile; char : Int) return Int; - - function gzgetc (file : gzFile) return Int; - - function gzflush (file : gzFile; flush : Int) return Int; - - function gzseek - (file : gzFile; - offset : Int; - whence : Int) - return Int; - - function gzrewind (file : gzFile) return Int; - - function gztell (file : gzFile) return Int; - - function gzeof (file : gzFile) return Int; - - function gzclose (file : gzFile) return Int; - - function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr; - - function adler32 - (adler : ULong; - buf : Byte_Access; - len : UInt) - return ULong; - - function crc32 - (crc : ULong; - buf : Byte_Access; - len : UInt) - return ULong; - - function deflateInit - (strm : Z_Streamp; - level : Int; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function deflateInit2 - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function Deflate_Init - (strm : Z_Streamp; - level : Int; - method : Int; - windowBits : Int; - memLevel : Int; - strategy : Int) - return Int; - pragma Inline (Deflate_Init); - - function inflateInit - (strm : Z_Streamp; - version : Chars_Ptr; - stream_size : Int) - return Int; - - function inflateInit2 - (strm : in Z_Streamp; - windowBits : in Int; - version : in Chars_Ptr; - stream_size : in Int) - return Int; - - function inflateBackInit - (strm : in Z_Streamp; - windowBits : in Int; - window : in Byte_Access; - version : in Chars_Ptr; - stream_size : in Int) - return Int; - -- Size of window have to be 2**windowBits. - - function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int; - pragma Inline (Inflate_Init); - - function zError (err : Int) return Chars_Ptr; - - function inflateSyncPoint (z : Z_Streamp) return Int; - - function get_crc_table return ULong_Access; - - -- Interface to the available fields of the z_stream structure. - -- The application must update next_in and avail_in when avail_in has - -- dropped to zero. It must update next_out and avail_out when avail_out - -- has dropped to zero. The application must initialize zalloc, zfree and - -- opaque before calling the init function. - - procedure Set_In - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt); - pragma Inline (Set_In); - - procedure Set_Out - (Strm : in out Z_Stream; - Buffer : in Voidp; - Size : in UInt); - pragma Inline (Set_Out); - - procedure Set_Mem_Func - (Strm : in out Z_Stream; - Opaque : in Voidp; - Alloc : in alloc_func; - Free : in free_func); - pragma Inline (Set_Mem_Func); - - function Last_Error_Message (Strm : in Z_Stream) return String; - pragma Inline (Last_Error_Message); - - function Avail_Out (Strm : in Z_Stream) return UInt; - pragma Inline (Avail_Out); - - function Avail_In (Strm : in Z_Stream) return UInt; - pragma Inline (Avail_In); - - function Total_In (Strm : in Z_Stream) return ULong; - pragma Inline (Total_In); - - function Total_Out (Strm : in Z_Stream) return ULong; - pragma Inline (Total_Out); - - function inflateCopy - (dest : in Z_Streamp; - Source : in Z_Streamp) - return Int; - - function compressBound (Source_Len : in ULong) return ULong; - - function deflateBound - (Strm : in Z_Streamp; - Source_Len : in ULong) - return ULong; - - function gzungetc (C : in Int; File : in gzFile) return Int; - - function zlibCompileFlags return ULong; - -private - - type Z_Stream is record -- zlib.h:68 - Next_In : Voidp := Nul; -- next input byte - Avail_In : UInt := 0; -- number of bytes available at next_in - Total_In : ULong := 0; -- total nb of input bytes read so far - Next_Out : Voidp := Nul; -- next output byte should be put there - Avail_Out : UInt := 0; -- remaining free space at next_out - Total_Out : ULong := 0; -- total nb of bytes output so far - msg : Chars_Ptr; -- last error message, NULL if no error - state : Voidp; -- not visible by applications - zalloc : alloc_func := null; -- used to allocate the internal state - zfree : free_func := null; -- used to free the internal state - opaque : Voidp; -- private data object passed to - -- zalloc and zfree - data_type : Int; -- best guess about the data type: - -- ascii or binary - adler : ULong; -- adler32 value of the uncompressed - -- data - reserved : ULong; -- reserved for future use - end record; - - pragma Convention (C, Z_Stream); - - pragma Import (C, zlibVersion, "zlibVersion"); - pragma Import (C, Deflate, "deflate"); - pragma Import (C, DeflateEnd, "deflateEnd"); - pragma Import (C, Inflate, "inflate"); - pragma Import (C, InflateEnd, "inflateEnd"); - pragma Import (C, deflateSetDictionary, "deflateSetDictionary"); - pragma Import (C, deflateCopy, "deflateCopy"); - pragma Import (C, deflateReset, "deflateReset"); - pragma Import (C, deflateParams, "deflateParams"); - pragma Import (C, inflateSetDictionary, "inflateSetDictionary"); - pragma Import (C, inflateSync, "inflateSync"); - pragma Import (C, inflateReset, "inflateReset"); - pragma Import (C, compress, "compress"); - pragma Import (C, compress2, "compress2"); - pragma Import (C, uncompress, "uncompress"); - pragma Import (C, gzopen, "gzopen"); - pragma Import (C, gzdopen, "gzdopen"); - pragma Import (C, gzsetparams, "gzsetparams"); - pragma Import (C, gzread, "gzread"); - pragma Import (C, gzwrite, "gzwrite"); - pragma Import (C, gzprintf, "gzprintf"); - pragma Import (C, gzputs, "gzputs"); - pragma Import (C, gzgets, "gzgets"); - pragma Import (C, gzputc, "gzputc"); - pragma Import (C, gzgetc, "gzgetc"); - pragma Import (C, gzflush, "gzflush"); - pragma Import (C, gzseek, "gzseek"); - pragma Import (C, gzrewind, "gzrewind"); - pragma Import (C, gztell, "gztell"); - pragma Import (C, gzeof, "gzeof"); - pragma Import (C, gzclose, "gzclose"); - pragma Import (C, gzerror, "gzerror"); - pragma Import (C, adler32, "adler32"); - pragma Import (C, crc32, "crc32"); - pragma Import (C, deflateInit, "deflateInit_"); - pragma Import (C, inflateInit, "inflateInit_"); - pragma Import (C, deflateInit2, "deflateInit2_"); - pragma Import (C, inflateInit2, "inflateInit2_"); - pragma Import (C, zError, "zError"); - pragma Import (C, inflateSyncPoint, "inflateSyncPoint"); - pragma Import (C, get_crc_table, "get_crc_table"); - - -- since zlib 1.2.0: - - pragma Import (C, inflateCopy, "inflateCopy"); - pragma Import (C, compressBound, "compressBound"); - pragma Import (C, deflateBound, "deflateBound"); - pragma Import (C, gzungetc, "gzungetc"); - pragma Import (C, zlibCompileFlags, "zlibCompileFlags"); - - pragma Import (C, inflateBackInit, "inflateBackInit_"); - - -- I stopped binding the inflateBack routines, because realize that - -- it does not support zlib and gzip headers for now, and have no - -- symmetric deflateBack routines. - -- ZLib-Ada is symmetric regarding deflate/inflate data transformation - -- and has a similar generic callback interface for the - -- deflate/inflate transformation based on the regular Deflate/Inflate - -- routines. - - -- pragma Import (C, inflateBack, "inflateBack"); - -- pragma Import (C, inflateBackEnd, "inflateBackEnd"); - -end ZLib.Thin; diff --git a/src/contrib/zlib/contrib/ada/zlib.adb b/src/contrib/zlib/contrib/ada/zlib.adb deleted file mode 100644 index 8b6fd68..0000000 --- a/src/contrib/zlib/contrib/ada/zlib.adb +++ /dev/null @@ -1,701 +0,0 @@ ----------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- Open source license information is in the zlib.ads file. -- ----------------------------------------------------------------- - --- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $ - -with Ada.Exceptions; -with Ada.Unchecked_Conversion; -with Ada.Unchecked_Deallocation; - -with Interfaces.C.Strings; - -with ZLib.Thin; - -package body ZLib is - - use type Thin.Int; - - type Z_Stream is new Thin.Z_Stream; - - type Return_Code_Enum is - (OK, - STREAM_END, - NEED_DICT, - ERRNO, - STREAM_ERROR, - DATA_ERROR, - MEM_ERROR, - BUF_ERROR, - VERSION_ERROR); - - type Flate_Step_Function is access - function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; - pragma Convention (C, Flate_Step_Function); - - type Flate_End_Function is access - function (Ctrm : in Thin.Z_Streamp) return Thin.Int; - pragma Convention (C, Flate_End_Function); - - type Flate_Type is record - Step : Flate_Step_Function; - Done : Flate_End_Function; - end record; - - subtype Footer_Array is Stream_Element_Array (1 .. 8); - - Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) - := (16#1f#, 16#8b#, -- Magic header - 16#08#, -- Z_DEFLATED - 16#00#, -- Flags - 16#00#, 16#00#, 16#00#, 16#00#, -- Time - 16#00#, -- XFlags - 16#03# -- OS code - ); - -- The simplest gzip header is not for informational, but just for - -- gzip format compatibility. - -- Note that some code below is using assumption - -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make - -- Simple_GZip_Header'Last <= Footer_Array'Last. - - Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum - := (0 => OK, - 1 => STREAM_END, - 2 => NEED_DICT, - -1 => ERRNO, - -2 => STREAM_ERROR, - -3 => DATA_ERROR, - -4 => MEM_ERROR, - -5 => BUF_ERROR, - -6 => VERSION_ERROR); - - Flate : constant array (Boolean) of Flate_Type - := (True => (Step => Thin.Deflate'Access, - Done => Thin.DeflateEnd'Access), - False => (Step => Thin.Inflate'Access, - Done => Thin.InflateEnd'Access)); - - Flush_Finish : constant array (Boolean) of Flush_Mode - := (True => Finish, False => No_Flush); - - procedure Raise_Error (Stream : in Z_Stream); - pragma Inline (Raise_Error); - - procedure Raise_Error (Message : in String); - pragma Inline (Raise_Error); - - procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); - - procedure Free is new Ada.Unchecked_Deallocation - (Z_Stream, Z_Stream_Access); - - function To_Thin_Access is new Ada.Unchecked_Conversion - (Z_Stream_Access, Thin.Z_Streamp); - - procedure Translate_GZip - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- Separate translate routine for make gzip header. - - procedure Translate_Auto - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- translate routine without additional headers. - - ----------------- - -- Check_Error -- - ----------------- - - procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is - use type Thin.Int; - begin - if Code /= Thin.Z_OK then - Raise_Error - (Return_Code_Enum'Image (Return_Code (Code)) - & ": " & Last_Error_Message (Stream)); - end if; - end Check_Error; - - ----------- - -- Close -- - ----------- - - procedure Close - (Filter : in out Filter_Type; - Ignore_Error : in Boolean := False) - is - Code : Thin.Int; - begin - if not Ignore_Error and then not Is_Open (Filter) then - raise Status_Error; - end if; - - Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); - - if Ignore_Error or else Code = Thin.Z_OK then - Free (Filter.Strm); - else - declare - Error_Message : constant String - := Last_Error_Message (Filter.Strm.all); - begin - Free (Filter.Strm); - Ada.Exceptions.Raise_Exception - (ZLib_Error'Identity, - Return_Code_Enum'Image (Return_Code (Code)) - & ": " & Error_Message); - end; - end if; - end Close; - - ----------- - -- CRC32 -- - ----------- - - function CRC32 - (CRC : in Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) - return Unsigned_32 - is - use Thin; - begin - return Unsigned_32 (crc32 (ULong (CRC), - Data'Address, - Data'Length)); - end CRC32; - - procedure CRC32 - (CRC : in out Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) is - begin - CRC := CRC32 (CRC, Data); - end CRC32; - - ------------------ - -- Deflate_Init -- - ------------------ - - procedure Deflate_Init - (Filter : in out Filter_Type; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Method : in Compression_Method := Deflated; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Memory_Level : in Memory_Level_Type := Default_Memory_Level; - Header : in Header_Type := Default) - is - use type Thin.Int; - Win_Bits : Thin.Int := Thin.Int (Window_Bits); - begin - if Is_Open (Filter) then - raise Status_Error; - end if; - - -- We allow ZLib to make header only in case of default header type. - -- Otherwise we would either do header by ourselfs, or do not do - -- header at all. - - if Header = None or else Header = GZip then - Win_Bits := -Win_Bits; - end if; - - -- For the GZip CRC calculation and make headers. - - if Header = GZip then - Filter.CRC := 0; - Filter.Offset := Simple_GZip_Header'First; - else - Filter.Offset := Simple_GZip_Header'Last + 1; - end if; - - Filter.Strm := new Z_Stream; - Filter.Compression := True; - Filter.Stream_End := False; - Filter.Header := Header; - - if Thin.Deflate_Init - (To_Thin_Access (Filter.Strm), - Level => Thin.Int (Level), - method => Thin.Int (Method), - windowBits => Win_Bits, - memLevel => Thin.Int (Memory_Level), - strategy => Thin.Int (Strategy)) /= Thin.Z_OK - then - Raise_Error (Filter.Strm.all); - end if; - end Deflate_Init; - - ----------- - -- Flush -- - ----------- - - procedure Flush - (Filter : in out Filter_Type; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - No_Data : Stream_Element_Array := (1 .. 0 => 0); - Last : Stream_Element_Offset; - begin - Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); - end Flush; - - ----------------------- - -- Generic_Translate -- - ----------------------- - - procedure Generic_Translate - (Filter : in out ZLib.Filter_Type; - In_Buffer_Size : in Integer := Default_Buffer_Size; - Out_Buffer_Size : in Integer := Default_Buffer_Size) - is - In_Buffer : Stream_Element_Array - (1 .. Stream_Element_Offset (In_Buffer_Size)); - Out_Buffer : Stream_Element_Array - (1 .. Stream_Element_Offset (Out_Buffer_Size)); - Last : Stream_Element_Offset; - In_Last : Stream_Element_Offset; - In_First : Stream_Element_Offset; - Out_Last : Stream_Element_Offset; - begin - Main : loop - Data_In (In_Buffer, Last); - - In_First := In_Buffer'First; - - loop - Translate - (Filter => Filter, - In_Data => In_Buffer (In_First .. Last), - In_Last => In_Last, - Out_Data => Out_Buffer, - Out_Last => Out_Last, - Flush => Flush_Finish (Last < In_Buffer'First)); - - if Out_Buffer'First <= Out_Last then - Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); - end if; - - exit Main when Stream_End (Filter); - - -- The end of in buffer. - - exit when In_Last = Last; - - In_First := In_Last + 1; - end loop; - end loop Main; - - end Generic_Translate; - - ------------------ - -- Inflate_Init -- - ------------------ - - procedure Inflate_Init - (Filter : in out Filter_Type; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Header : in Header_Type := Default) - is - use type Thin.Int; - Win_Bits : Thin.Int := Thin.Int (Window_Bits); - - procedure Check_Version; - -- Check the latest header types compatibility. - - procedure Check_Version is - begin - if Version <= "1.1.4" then - Raise_Error - ("Inflate header type " & Header_Type'Image (Header) - & " incompatible with ZLib version " & Version); - end if; - end Check_Version; - - begin - if Is_Open (Filter) then - raise Status_Error; - end if; - - case Header is - when None => - Check_Version; - - -- Inflate data without headers determined - -- by negative Win_Bits. - - Win_Bits := -Win_Bits; - when GZip => - Check_Version; - - -- Inflate gzip data defined by flag 16. - - Win_Bits := Win_Bits + 16; - when Auto => - Check_Version; - - -- Inflate with automatic detection - -- of gzip or native header defined by flag 32. - - Win_Bits := Win_Bits + 32; - when Default => null; - end case; - - Filter.Strm := new Z_Stream; - Filter.Compression := False; - Filter.Stream_End := False; - Filter.Header := Header; - - if Thin.Inflate_Init - (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK - then - Raise_Error (Filter.Strm.all); - end if; - end Inflate_Init; - - ------------- - -- Is_Open -- - ------------- - - function Is_Open (Filter : in Filter_Type) return Boolean is - begin - return Filter.Strm /= null; - end Is_Open; - - ----------------- - -- Raise_Error -- - ----------------- - - procedure Raise_Error (Message : in String) is - begin - Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); - end Raise_Error; - - procedure Raise_Error (Stream : in Z_Stream) is - begin - Raise_Error (Last_Error_Message (Stream)); - end Raise_Error; - - ---------- - -- Read -- - ---------- - - procedure Read - (Filter : in out Filter_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode := No_Flush) - is - In_Last : Stream_Element_Offset; - Item_First : Ada.Streams.Stream_Element_Offset := Item'First; - V_Flush : Flush_Mode := Flush; - - begin - pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); - pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); - - loop - if Rest_Last = Buffer'First - 1 then - V_Flush := Finish; - - elsif Rest_First > Rest_Last then - Read (Buffer, Rest_Last); - Rest_First := Buffer'First; - - if Rest_Last < Buffer'First then - V_Flush := Finish; - end if; - end if; - - Translate - (Filter => Filter, - In_Data => Buffer (Rest_First .. Rest_Last), - In_Last => In_Last, - Out_Data => Item (Item_First .. Item'Last), - Out_Last => Last, - Flush => V_Flush); - - Rest_First := In_Last + 1; - - exit when Stream_End (Filter) - or else Last = Item'Last - or else (Last >= Item'First and then Allow_Read_Some); - - Item_First := Last + 1; - end loop; - end Read; - - ---------------- - -- Stream_End -- - ---------------- - - function Stream_End (Filter : in Filter_Type) return Boolean is - begin - if Filter.Header = GZip and Filter.Compression then - return Filter.Stream_End - and then Filter.Offset = Footer_Array'Last + 1; - else - return Filter.Stream_End; - end if; - end Stream_End; - - -------------- - -- Total_In -- - -------------- - - function Total_In (Filter : in Filter_Type) return Count is - begin - return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); - end Total_In; - - --------------- - -- Total_Out -- - --------------- - - function Total_Out (Filter : in Filter_Type) return Count is - begin - return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); - end Total_Out; - - --------------- - -- Translate -- - --------------- - - procedure Translate - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) is - begin - if Filter.Header = GZip and then Filter.Compression then - Translate_GZip - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data, - Out_Last => Out_Last, - Flush => Flush); - else - Translate_Auto - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data, - Out_Last => Out_Last, - Flush => Flush); - end if; - end Translate; - - -------------------- - -- Translate_Auto -- - -------------------- - - procedure Translate_Auto - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - use type Thin.Int; - Code : Thin.Int; - - begin - if not Is_Open (Filter) then - raise Status_Error; - end if; - - if Out_Data'Length = 0 and then In_Data'Length = 0 then - raise Constraint_Error; - end if; - - Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); - Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); - - Code := Flate (Filter.Compression).Step - (To_Thin_Access (Filter.Strm), - Thin.Int (Flush)); - - if Code = Thin.Z_STREAM_END then - Filter.Stream_End := True; - else - Check_Error (Filter.Strm.all, Code); - end if; - - In_Last := In_Data'Last - - Stream_Element_Offset (Avail_In (Filter.Strm.all)); - Out_Last := Out_Data'Last - - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); - end Translate_Auto; - - -------------------- - -- Translate_GZip -- - -------------------- - - procedure Translate_GZip - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode) - is - Out_First : Stream_Element_Offset; - - procedure Add_Data (Data : in Stream_Element_Array); - -- Add data to stream from the Filter.Offset till necessary, - -- used for add gzip headr/footer. - - procedure Put_32 - (Item : in out Stream_Element_Array; - Data : in Unsigned_32); - pragma Inline (Put_32); - - -------------- - -- Add_Data -- - -------------- - - procedure Add_Data (Data : in Stream_Element_Array) is - Data_First : Stream_Element_Offset renames Filter.Offset; - Data_Last : Stream_Element_Offset; - Data_Len : Stream_Element_Offset; -- -1 - Out_Len : Stream_Element_Offset; -- -1 - begin - Out_First := Out_Last + 1; - - if Data_First > Data'Last then - return; - end if; - - Data_Len := Data'Last - Data_First; - Out_Len := Out_Data'Last - Out_First; - - if Data_Len <= Out_Len then - Out_Last := Out_First + Data_Len; - Data_Last := Data'Last; - else - Out_Last := Out_Data'Last; - Data_Last := Data_First + Out_Len; - end if; - - Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); - - Data_First := Data_Last + 1; - Out_First := Out_Last + 1; - end Add_Data; - - ------------ - -- Put_32 -- - ------------ - - procedure Put_32 - (Item : in out Stream_Element_Array; - Data : in Unsigned_32) - is - D : Unsigned_32 := Data; - begin - for J in Item'First .. Item'First + 3 loop - Item (J) := Stream_Element (D and 16#FF#); - D := Shift_Right (D, 8); - end loop; - end Put_32; - - begin - Out_Last := Out_Data'First - 1; - - if not Filter.Stream_End then - Add_Data (Simple_GZip_Header); - - Translate_Auto - (Filter => Filter, - In_Data => In_Data, - In_Last => In_Last, - Out_Data => Out_Data (Out_First .. Out_Data'Last), - Out_Last => Out_Last, - Flush => Flush); - - CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); - end if; - - if Filter.Stream_End and then Out_Last <= Out_Data'Last then - -- This detection method would work only when - -- Simple_GZip_Header'Last > Footer_Array'Last - - if Filter.Offset = Simple_GZip_Header'Last + 1 then - Filter.Offset := Footer_Array'First; - end if; - - declare - Footer : Footer_Array; - begin - Put_32 (Footer, Filter.CRC); - Put_32 (Footer (Footer'First + 4 .. Footer'Last), - Unsigned_32 (Total_In (Filter))); - Add_Data (Footer); - end; - end if; - end Translate_GZip; - - ------------- - -- Version -- - ------------- - - function Version return String is - begin - return Interfaces.C.Strings.Value (Thin.zlibVersion); - end Version; - - ----------- - -- Write -- - ----------- - - procedure Write - (Filter : in out Filter_Type; - Item : in Ada.Streams.Stream_Element_Array; - Flush : in Flush_Mode := No_Flush) - is - Buffer : Stream_Element_Array (1 .. Buffer_Size); - In_Last : Stream_Element_Offset; - Out_Last : Stream_Element_Offset; - In_First : Stream_Element_Offset := Item'First; - begin - if Item'Length = 0 and Flush = No_Flush then - return; - end if; - - loop - Translate - (Filter => Filter, - In_Data => Item (In_First .. Item'Last), - In_Last => In_Last, - Out_Data => Buffer, - Out_Last => Out_Last, - Flush => Flush); - - if Out_Last >= Buffer'First then - Write (Buffer (1 .. Out_Last)); - end if; - - exit when In_Last = Item'Last or Stream_End (Filter); - - In_First := In_Last + 1; - end loop; - end Write; - -end ZLib; diff --git a/src/contrib/zlib/contrib/ada/zlib.ads b/src/contrib/zlib/contrib/ada/zlib.ads deleted file mode 100644 index 79ffc40..0000000 --- a/src/contrib/zlib/contrib/ada/zlib.ads +++ /dev/null @@ -1,328 +0,0 @@ ------------------------------------------------------------------------------- --- ZLib for Ada thick binding. -- --- -- --- Copyright (C) 2002-2004 Dmitriy Anisimkov -- --- -- --- This library is free software; you can redistribute it and/or modify -- --- it under the terms of the GNU General Public License as published by -- --- the Free Software Foundation; either version 2 of the License, or (at -- --- your option) any later version. -- --- -- --- This library is distributed in the hope that it will be useful, but -- --- WITHOUT ANY WARRANTY; without even the implied warranty of -- --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- --- General Public License for more details. -- --- -- --- You should have received a copy of the GNU General Public License -- --- along with this library; if not, write to the Free Software Foundation, -- --- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- --- -- --- As a special exception, if other files instantiate generics from this -- --- unit, or you link this unit with other files to produce an executable, -- --- this unit does not by itself cause the resulting executable to be -- --- covered by the GNU General Public License. This exception does not -- --- however invalidate any other reasons why the executable file might be -- --- covered by the GNU Public License. -- ------------------------------------------------------------------------------- - --- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $ - -with Ada.Streams; - -with Interfaces; - -package ZLib is - - ZLib_Error : exception; - Status_Error : exception; - - type Compression_Level is new Integer range -1 .. 9; - - type Flush_Mode is private; - - type Compression_Method is private; - - type Window_Bits_Type is new Integer range 8 .. 15; - - type Memory_Level_Type is new Integer range 1 .. 9; - - type Unsigned_32 is new Interfaces.Unsigned_32; - - type Strategy_Type is private; - - type Header_Type is (None, Auto, Default, GZip); - -- Header type usage have a some limitation for inflate. - -- See comment for Inflate_Init. - - subtype Count is Ada.Streams.Stream_Element_Count; - - Default_Memory_Level : constant Memory_Level_Type := 8; - Default_Window_Bits : constant Window_Bits_Type := 15; - - ---------------------------------- - -- Compression method constants -- - ---------------------------------- - - Deflated : constant Compression_Method; - -- Only one method allowed in this ZLib version - - --------------------------------- - -- Compression level constants -- - --------------------------------- - - No_Compression : constant Compression_Level := 0; - Best_Speed : constant Compression_Level := 1; - Best_Compression : constant Compression_Level := 9; - Default_Compression : constant Compression_Level := -1; - - -------------------------- - -- Flush mode constants -- - -------------------------- - - No_Flush : constant Flush_Mode; - -- Regular way for compression, no flush - - Partial_Flush : constant Flush_Mode; - -- Will be removed, use Z_SYNC_FLUSH instead - - Sync_Flush : constant Flush_Mode; - -- All pending output is flushed to the output buffer and the output - -- is aligned on a byte boundary, so that the decompressor can get all - -- input data available so far. (In particular avail_in is zero after the - -- call if enough output space has been provided before the call.) - -- Flushing may degrade compression for some compression algorithms and so - -- it should be used only when necessary. - - Block_Flush : constant Flush_Mode; - -- Z_BLOCK requests that inflate() stop - -- if and when it get to the next deflate block boundary. When decoding the - -- zlib or gzip format, this will cause inflate() to return immediately - -- after the header and before the first block. When doing a raw inflate, - -- inflate() will go ahead and process the first block, and will return - -- when it gets to the end of that block, or when it runs out of data. - - Full_Flush : constant Flush_Mode; - -- All output is flushed as with SYNC_FLUSH, and the compression state - -- is reset so that decompression can restart from this point if previous - -- compressed data has been damaged or if random access is desired. Using - -- Full_Flush too often can seriously degrade the compression. - - Finish : constant Flush_Mode; - -- Just for tell the compressor that input data is complete. - - ------------------------------------ - -- Compression strategy constants -- - ------------------------------------ - - -- RLE stategy could be used only in version 1.2.0 and later. - - Filtered : constant Strategy_Type; - Huffman_Only : constant Strategy_Type; - RLE : constant Strategy_Type; - Default_Strategy : constant Strategy_Type; - - Default_Buffer_Size : constant := 4096; - - type Filter_Type is tagged limited private; - -- The filter is for compression and for decompression. - -- The usage of the type is depend of its initialization. - - function Version return String; - pragma Inline (Version); - -- Return string representation of the ZLib version. - - procedure Deflate_Init - (Filter : in out Filter_Type; - Level : in Compression_Level := Default_Compression; - Strategy : in Strategy_Type := Default_Strategy; - Method : in Compression_Method := Deflated; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Memory_Level : in Memory_Level_Type := Default_Memory_Level; - Header : in Header_Type := Default); - -- Compressor initialization. - -- When Header parameter is Auto or Default, then default zlib header - -- would be provided for compressed data. - -- When Header is GZip, then gzip header would be set instead of - -- default header. - -- When Header is None, no header would be set for compressed data. - - procedure Inflate_Init - (Filter : in out Filter_Type; - Window_Bits : in Window_Bits_Type := Default_Window_Bits; - Header : in Header_Type := Default); - -- Decompressor initialization. - -- Default header type mean that ZLib default header is expecting in the - -- input compressed stream. - -- Header type None mean that no header is expecting in the input stream. - -- GZip header type mean that GZip header is expecting in the - -- input compressed stream. - -- Auto header type mean that header type (GZip or Native) would be - -- detected automatically in the input stream. - -- Note that header types parameter values None, GZip and Auto are - -- supported for inflate routine only in ZLib versions 1.2.0.2 and later. - -- Deflate_Init is supporting all header types. - - function Is_Open (Filter : in Filter_Type) return Boolean; - pragma Inline (Is_Open); - -- Is the filter opened for compression or decompression. - - procedure Close - (Filter : in out Filter_Type; - Ignore_Error : in Boolean := False); - -- Closing the compression or decompressor. - -- If stream is closing before the complete and Ignore_Error is False, - -- The exception would be raised. - - generic - with procedure Data_In - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - with procedure Data_Out - (Item : in Ada.Streams.Stream_Element_Array); - procedure Generic_Translate - (Filter : in out Filter_Type; - In_Buffer_Size : in Integer := Default_Buffer_Size; - Out_Buffer_Size : in Integer := Default_Buffer_Size); - -- Compress/decompress data fetch from Data_In routine and pass the result - -- to the Data_Out routine. User should provide Data_In and Data_Out - -- for compression/decompression data flow. - -- Compression or decompression depend on Filter initialization. - - function Total_In (Filter : in Filter_Type) return Count; - pragma Inline (Total_In); - -- Returns total number of input bytes read so far - - function Total_Out (Filter : in Filter_Type) return Count; - pragma Inline (Total_Out); - -- Returns total number of bytes output so far - - function CRC32 - (CRC : in Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array) - return Unsigned_32; - pragma Inline (CRC32); - -- Compute CRC32, it could be necessary for make gzip format - - procedure CRC32 - (CRC : in out Unsigned_32; - Data : in Ada.Streams.Stream_Element_Array); - pragma Inline (CRC32); - -- Compute CRC32, it could be necessary for make gzip format - - ------------------------------------------------- - -- Below is more complex low level routines. -- - ------------------------------------------------- - - procedure Translate - (Filter : in out Filter_Type; - In_Data : in Ada.Streams.Stream_Element_Array; - In_Last : out Ada.Streams.Stream_Element_Offset; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - -- Compress/decompress the In_Data buffer and place the result into - -- Out_Data. In_Last is the index of last element from In_Data accepted by - -- the Filter. Out_Last is the last element of the received data from - -- Filter. To tell the filter that incoming data are complete put the - -- Flush parameter to Finish. - - function Stream_End (Filter : in Filter_Type) return Boolean; - pragma Inline (Stream_End); - -- Return the true when the stream is complete. - - procedure Flush - (Filter : in out Filter_Type; - Out_Data : out Ada.Streams.Stream_Element_Array; - Out_Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode); - pragma Inline (Flush); - -- Flushing the data from the compressor. - - generic - with procedure Write - (Item : in Ada.Streams.Stream_Element_Array); - -- User should provide this routine for accept - -- compressed/decompressed data. - - Buffer_Size : in Ada.Streams.Stream_Element_Offset - := Default_Buffer_Size; - -- Buffer size for Write user routine. - - procedure Write - (Filter : in out Filter_Type; - Item : in Ada.Streams.Stream_Element_Array; - Flush : in Flush_Mode := No_Flush); - -- Compress/Decompress data from Item to the generic parameter procedure - -- Write. Output buffer size could be set in Buffer_Size generic parameter. - - generic - with procedure Read - (Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset); - -- User should provide data for compression/decompression - -- thru this routine. - - Buffer : in out Ada.Streams.Stream_Element_Array; - -- Buffer for keep remaining data from the previous - -- back read. - - Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset; - -- Rest_First have to be initialized to Buffer'Last + 1 - -- Rest_Last have to be initialized to Buffer'Last - -- before usage. - - Allow_Read_Some : in Boolean := False; - -- Is it allowed to return Last < Item'Last before end of data. - - procedure Read - (Filter : in out Filter_Type; - Item : out Ada.Streams.Stream_Element_Array; - Last : out Ada.Streams.Stream_Element_Offset; - Flush : in Flush_Mode := No_Flush); - -- Compress/Decompress data from generic parameter procedure Read to the - -- Item. User should provide Buffer and initialized Rest_First, Rest_Last - -- indicators. If Allow_Read_Some is True, Read routines could return - -- Last < Item'Last only at end of stream. - -private - - use Ada.Streams; - - pragma Assert (Ada.Streams.Stream_Element'Size = 8); - pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8); - - type Flush_Mode is new Integer range 0 .. 5; - - type Compression_Method is new Integer range 8 .. 8; - - type Strategy_Type is new Integer range 0 .. 3; - - No_Flush : constant Flush_Mode := 0; - Partial_Flush : constant Flush_Mode := 1; - Sync_Flush : constant Flush_Mode := 2; - Full_Flush : constant Flush_Mode := 3; - Finish : constant Flush_Mode := 4; - Block_Flush : constant Flush_Mode := 5; - - Filtered : constant Strategy_Type := 1; - Huffman_Only : constant Strategy_Type := 2; - RLE : constant Strategy_Type := 3; - Default_Strategy : constant Strategy_Type := 0; - - Deflated : constant Compression_Method := 8; - - type Z_Stream; - - type Z_Stream_Access is access all Z_Stream; - - type Filter_Type is tagged limited record - Strm : Z_Stream_Access; - Compression : Boolean; - Stream_End : Boolean; - Header : Header_Type; - CRC : Unsigned_32; - Offset : Stream_Element_Offset; - -- Offset for gzip header/footer output. - end record; - -end ZLib; diff --git a/src/contrib/zlib/contrib/ada/zlib.gpr b/src/contrib/zlib/contrib/ada/zlib.gpr deleted file mode 100644 index 296b22a..0000000 --- a/src/contrib/zlib/contrib/ada/zlib.gpr +++ /dev/null @@ -1,20 +0,0 @@ -project Zlib is - - for Languages use ("Ada"); - for Source_Dirs use ("."); - for Object_Dir use "."; - for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo"); - - package Compiler is - for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst"); - end Compiler; - - package Linker is - for Default_Switches ("ada") use ("-lz"); - end Linker; - - package Builder is - for Default_Switches ("ada") use ("-s", "-gnatQ"); - end Builder; - -end Zlib; diff --git a/src/contrib/zlib/contrib/amd64/amd64-match.S b/src/contrib/zlib/contrib/amd64/amd64-match.S deleted file mode 100644 index 81d4a1c..0000000 --- a/src/contrib/zlib/contrib/amd64/amd64-match.S +++ /dev/null @@ -1,452 +0,0 @@ -/* - * match.S -- optimized version of longest_match() - * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the BSD License. Use by owners of Che Guevarra - * parafernalia is prohibited, where possible, and highly discouraged - * elsewhere. - */ - -#ifndef NO_UNDERLINE -# define match_init _match_init -# define longest_match _longest_match -#endif - -#define scanend ebx -#define scanendw bx -#define chainlenwmask edx /* high word: current chain len low word: s->wmask */ -#define curmatch rsi -#define curmatchd esi -#define windowbestlen r8 -#define scanalign r9 -#define scanalignd r9d -#define window r10 -#define bestlen r11 -#define bestlend r11d -#define scanstart r12d -#define scanstartw r12w -#define scan r13 -#define nicematch r14d -#define limit r15 -#define limitd r15d -#define prev rcx - -/* - * The 258 is a "magic number, not a parameter -- changing it - * breaks the hell loose - */ -#define MAX_MATCH (258) -#define MIN_MATCH (3) -#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) - -/* stack frame offsets */ -#define LocalVarsSize (112) -#define _chainlenwmask ( 8-LocalVarsSize)(%rsp) -#define _windowbestlen (16-LocalVarsSize)(%rsp) -#define save_r14 (24-LocalVarsSize)(%rsp) -#define save_rsi (32-LocalVarsSize)(%rsp) -#define save_rbx (40-LocalVarsSize)(%rsp) -#define save_r12 (56-LocalVarsSize)(%rsp) -#define save_r13 (64-LocalVarsSize)(%rsp) -#define save_r15 (80-LocalVarsSize)(%rsp) - - -.globl match_init, longest_match - -/* - * On AMD64 the first argument of a function (in our case -- the pointer to - * deflate_state structure) is passed in %rdi, hence our offsets below are - * all off of that. - */ - -/* you can check the structure offset by running - -#include -#include -#include "deflate.h" - -void print_depl() -{ -deflate_state ds; -deflate_state *s=&ds; -printf("size pointer=%u\n",(int)sizeof(void*)); - -printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s))); -printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s))); -printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s))); -printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s))); -printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s))); -printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s))); -printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s))); -printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s))); -printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s))); -printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s))); -printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); -printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s))); -printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s))); -} - -*/ - - -/* - to compile for XCode 3.2 on MacOSX x86_64 - - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S" - */ - - -#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE -#define dsWSize ( 68)(%rdi) -#define dsWMask ( 76)(%rdi) -#define dsWindow ( 80)(%rdi) -#define dsPrev ( 96)(%rdi) -#define dsMatchLen (144)(%rdi) -#define dsPrevMatch (148)(%rdi) -#define dsStrStart (156)(%rdi) -#define dsMatchStart (160)(%rdi) -#define dsLookahead (164)(%rdi) -#define dsPrevLen (168)(%rdi) -#define dsMaxChainLen (172)(%rdi) -#define dsGoodMatch (188)(%rdi) -#define dsNiceMatch (192)(%rdi) - -#else - -#ifndef STRUCT_OFFSET -# define STRUCT_OFFSET (0) -#endif - - -#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) -#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) -#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) -#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) -#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) -#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) -#define dsStrStart (148 + STRUCT_OFFSET)(%rdi) -#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) -#define dsLookahead (156 + STRUCT_OFFSET)(%rdi) -#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) -#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) -#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) -#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) - -#endif - - - - -.text - -/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ - -longest_match: -/* - * Retrieve the function arguments. %curmatch will hold cur_match - * throughout the entire function (passed via rsi on amd64). - * rdi will hold the pointer to the deflate_state (first arg on amd64) - */ - mov %rsi, save_rsi - mov %rbx, save_rbx - mov %r12, save_r12 - mov %r13, save_r13 - mov %r14, save_r14 - mov %r15, save_r15 - -/* uInt wmask = s->w_mask; */ -/* unsigned chain_length = s->max_chain_length; */ -/* if (s->prev_length >= s->good_match) { */ -/* chain_length >>= 2; */ -/* } */ - - movl dsPrevLen, %eax - movl dsGoodMatch, %ebx - cmpl %ebx, %eax - movl dsWMask, %eax - movl dsMaxChainLen, %chainlenwmask - jl LastMatchGood - shrl $2, %chainlenwmask -LastMatchGood: - -/* chainlen is decremented once beforehand so that the function can */ -/* use the sign flag instead of the zero flag for the exit test. */ -/* It is then shifted into the high word, to make room for the wmask */ -/* value, which it will always accompany. */ - - decl %chainlenwmask - shll $16, %chainlenwmask - orl %eax, %chainlenwmask - -/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ - - movl dsNiceMatch, %eax - movl dsLookahead, %ebx - cmpl %eax, %ebx - jl LookaheadLess - movl %eax, %ebx -LookaheadLess: movl %ebx, %nicematch - -/* register Bytef *scan = s->window + s->strstart; */ - - mov dsWindow, %window - movl dsStrStart, %limitd - lea (%limit, %window), %scan - -/* Determine how many bytes the scan ptr is off from being */ -/* dword-aligned. */ - - mov %scan, %scanalign - negl %scanalignd - andl $3, %scanalignd - -/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ - - movl dsWSize, %eax - subl $MIN_LOOKAHEAD, %eax - xorl %ecx, %ecx - subl %eax, %limitd - cmovng %ecx, %limitd - -/* int best_len = s->prev_length; */ - - movl dsPrevLen, %bestlend - -/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ - - lea (%window, %bestlen), %windowbestlen - mov %windowbestlen, _windowbestlen - -/* register ush scan_start = *(ushf*)scan; */ -/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -/* Posf *prev = s->prev; */ - - movzwl (%scan), %scanstart - movzwl -1(%scan, %bestlen), %scanend - mov dsPrev, %prev - -/* Jump into the main loop. */ - - movl %chainlenwmask, _chainlenwmask - jmp LoopEntry - -.balign 16 - -/* do { - * match = s->window + cur_match; - * if (*(ushf*)(match+best_len-1) != scan_end || - * *(ushf*)match != scan_start) continue; - * [...] - * } while ((cur_match = prev[cur_match & wmask]) > limit - * && --chain_length != 0); - * - * Here is the inner loop of the function. The function will spend the - * majority of its time in this loop, and majority of that time will - * be spent in the first ten instructions. - */ -LookupLoop: - andl %chainlenwmask, %curmatchd - movzwl (%prev, %curmatch, 2), %curmatchd - cmpl %limitd, %curmatchd - jbe LeaveNow - subl $0x00010000, %chainlenwmask - js LeaveNow -LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw - jne LookupLoop - cmpw %scanstartw, (%window, %curmatch) - jne LookupLoop - -/* Store the current value of chainlen. */ - movl %chainlenwmask, _chainlenwmask - -/* %scan is the string under scrutiny, and %prev to the string we */ -/* are hoping to match it up with. In actuality, %esi and %edi are */ -/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -/* initialized to -(MAX_MATCH_8 - scanalign). */ - - mov $(-MAX_MATCH_8), %rdx - lea (%curmatch, %window), %windowbestlen - lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen - lea MAX_MATCH_8(%scan, %scanalign), %prev - -/* the prefetching below makes very little difference... */ - prefetcht1 (%windowbestlen, %rdx) - prefetcht1 (%prev, %rdx) - -/* - * Test the strings for equality, 8 bytes at a time. At the end, - * adjust %rdx so that it is offset to the exact byte that mismatched. - * - * It should be confessed that this loop usually does not represent - * much of the total running time. Replacing it with a more - * straightforward "rep cmpsb" would not drastically degrade - * performance -- unrolling it, for example, makes no difference. - */ - -#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ - -LoopCmps: -#ifdef USE_SSE - /* Preload the SSE registers */ - movdqu (%windowbestlen, %rdx), %xmm1 - movdqu (%prev, %rdx), %xmm2 - pcmpeqb %xmm2, %xmm1 - movdqu 16(%windowbestlen, %rdx), %xmm3 - movdqu 16(%prev, %rdx), %xmm4 - pcmpeqb %xmm4, %xmm3 - movdqu 32(%windowbestlen, %rdx), %xmm5 - movdqu 32(%prev, %rdx), %xmm6 - pcmpeqb %xmm6, %xmm5 - movdqu 48(%windowbestlen, %rdx), %xmm7 - movdqu 48(%prev, %rdx), %xmm8 - pcmpeqb %xmm8, %xmm7 - - /* Check the comparisions' results */ - pmovmskb %xmm1, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - /* this is the only iteration of the loop with a possibility of having - incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 - and (0x40*4)+8=0x108 */ - add $8, %rdx - jz LenMaximum - add $8, %rdx - - - pmovmskb %xmm3, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - - add $16, %rdx - - - pmovmskb %xmm5, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - add $16, %rdx - - - pmovmskb %xmm7, %rax - notw %ax - bsfw %ax, %ax - jnz LeaveLoopCmps - - add $16, %rdx - - jmp LoopCmps -LeaveLoopCmps: add %rax, %rdx -#else - mov (%windowbestlen, %rdx), %rax - xor (%prev, %rdx), %rax - jnz LeaveLoopCmps - - mov 8(%windowbestlen, %rdx), %rax - xor 8(%prev, %rdx), %rax - jnz LeaveLoopCmps8 - - mov 16(%windowbestlen, %rdx), %rax - xor 16(%prev, %rdx), %rax - jnz LeaveLoopCmps16 - - add $24, %rdx - jnz LoopCmps - jmp LenMaximum -# if 0 -/* - * This three-liner is tantalizingly simple, but bsf is a slow instruction, - * and the complicated alternative down below is quite a bit faster. Sad... - */ - -LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ - shrl $3, %eax /* divide by 8 to get the byte */ - add %rax, %rdx -# else -LeaveLoopCmps16: - add $8, %rdx -LeaveLoopCmps8: - add $8, %rdx -LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ - jnz Check16 - add $4, %rdx - shr $32, %rax -Check16: testw $0xFFFF, %ax - jnz LenLower - add $2, %rdx - shrl $16, %eax -LenLower: subb $1, %al - adc $0, %rdx -# endif -#endif - -/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -/* then automatically accept it as the best possible match and leave. */ - - lea (%prev, %rdx), %rax - sub %scan, %rax - cmpl $MAX_MATCH, %eax - jge LenMaximum - -/* If the length of the match is not longer than the best match we */ -/* have so far, then forget it and return to the lookup loop. */ - - cmpl %bestlend, %eax - jg LongerMatch - mov _windowbestlen, %windowbestlen - mov dsPrev, %prev - movl _chainlenwmask, %edx - jmp LookupLoop - -/* s->match_start = cur_match; */ -/* best_len = len; */ -/* if (len >= nice_match) break; */ -/* scan_end = *(ushf*)(scan+best_len-1); */ - -LongerMatch: - movl %eax, %bestlend - movl %curmatchd, dsMatchStart - cmpl %nicematch, %eax - jge LeaveNow - - lea (%window, %bestlen), %windowbestlen - mov %windowbestlen, _windowbestlen - - movzwl -1(%scan, %rax), %scanend - mov dsPrev, %prev - movl _chainlenwmask, %chainlenwmask - jmp LookupLoop - -/* Accept the current string, with the maximum possible length. */ - -LenMaximum: - movl $MAX_MATCH, %bestlend - movl %curmatchd, dsMatchStart - -/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -/* return s->lookahead; */ - -LeaveNow: - movl dsLookahead, %eax - cmpl %eax, %bestlend - cmovngl %bestlend, %eax -LookaheadRet: - -/* Restore the registers and return from whence we came. */ - - mov save_rsi, %rsi - mov save_rbx, %rbx - mov save_r12, %r12 - mov save_r13, %r13 - mov save_r14, %r14 - mov save_r15, %r15 - - ret - -match_init: ret diff --git a/src/contrib/zlib/contrib/asm686/README.686 b/src/contrib/zlib/contrib/asm686/README.686 deleted file mode 100644 index a0bf3be..0000000 --- a/src/contrib/zlib/contrib/asm686/README.686 +++ /dev/null @@ -1,51 +0,0 @@ -This is a patched version of zlib, modified to use -Pentium-Pro-optimized assembly code in the deflation algorithm. The -files changed/added by this patch are: - -README.686 -match.S - -The speedup that this patch provides varies, depending on whether the -compiler used to build the original version of zlib falls afoul of the -PPro's speed traps. My own tests show a speedup of around 10-20% at -the default compression level, and 20-30% using -9, against a version -compiled using gcc 2.7.2.3. Your mileage may vary. - -Note that this code has been tailored for the PPro/PII in particular, -and will not perform particuarly well on a Pentium. - -If you are using an assembler other than GNU as, you will have to -translate match.S to use your assembler's syntax. (Have fun.) - -Brian Raiter -breadbox@muppetlabs.com -April, 1998 - - -Added for zlib 1.1.3: - -The patches come from -http://www.muppetlabs.com/~breadbox/software/assembly.html - -To compile zlib with this asm file, copy match.S to the zlib directory -then do: - -CFLAGS="-O3 -DASMV" ./configure -make OBJA=match.o - - -Update: - -I've been ignoring these assembly routines for years, believing that -gcc's generated code had caught up with it sometime around gcc 2.95 -and the major rearchitecting of the Pentium 4. However, I recently -learned that, despite what I believed, this code still has some life -in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% -faster than the code produced by gcc 4.1. - -In acknowledgement of its continuing usefulness, I've altered the -license to match that of the rest of zlib. Share and Enjoy! - -Brian Raiter -breadbox@muppetlabs.com -April, 2007 diff --git a/src/contrib/zlib/contrib/asm686/match.S b/src/contrib/zlib/contrib/asm686/match.S deleted file mode 100644 index fa42109..0000000 --- a/src/contrib/zlib/contrib/asm686/match.S +++ /dev/null @@ -1,357 +0,0 @@ -/* match.S -- x86 assembly version of the zlib longest_match() function. - * Optimized for the Intel 686 chips (PPro and later). - * - * Copyright (C) 1998, 2007 Brian Raiter - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef NO_UNDERLINE -#define match_init _match_init -#define longest_match _longest_match -#endif - -#define MAX_MATCH (258) -#define MIN_MATCH (3) -#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) -#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) - -/* stack frame offsets */ - -#define chainlenwmask 0 /* high word: current chain len */ - /* low word: s->wmask */ -#define window 4 /* local copy of s->window */ -#define windowbestlen 8 /* s->window + bestlen */ -#define scanstart 16 /* first two bytes of string */ -#define scanend 12 /* last two bytes of string */ -#define scanalign 20 /* dword-misalignment of string */ -#define nicematch 24 /* a good enough match size */ -#define bestlen 28 /* size of best match so far */ -#define scan 32 /* ptr to string wanting match */ - -#define LocalVarsSize (36) -/* saved ebx 36 */ -/* saved edi 40 */ -/* saved esi 44 */ -/* saved ebp 48 */ -/* return address 52 */ -#define deflatestate 56 /* the function arguments */ -#define curmatch 60 - -/* All the +zlib1222add offsets are due to the addition of fields - * in zlib in the deflate_state structure since the asm code was first written - * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). - * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). - * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - */ - -#define zlib1222add (8) - -#define dsWSize (36+zlib1222add) -#define dsWMask (44+zlib1222add) -#define dsWindow (48+zlib1222add) -#define dsPrev (56+zlib1222add) -#define dsMatchLen (88+zlib1222add) -#define dsPrevMatch (92+zlib1222add) -#define dsStrStart (100+zlib1222add) -#define dsMatchStart (104+zlib1222add) -#define dsLookahead (108+zlib1222add) -#define dsPrevLen (112+zlib1222add) -#define dsMaxChainLen (116+zlib1222add) -#define dsGoodMatch (132+zlib1222add) -#define dsNiceMatch (136+zlib1222add) - - -.file "match.S" - -.globl match_init, longest_match - -.text - -/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ -.cfi_sections .debug_frame - -longest_match: - -.cfi_startproc -/* Save registers that the compiler may be using, and adjust %esp to */ -/* make room for our stack frame. */ - - pushl %ebp - .cfi_def_cfa_offset 8 - .cfi_offset ebp, -8 - pushl %edi - .cfi_def_cfa_offset 12 - pushl %esi - .cfi_def_cfa_offset 16 - pushl %ebx - .cfi_def_cfa_offset 20 - subl $LocalVarsSize, %esp - .cfi_def_cfa_offset LocalVarsSize+20 - -/* Retrieve the function arguments. %ecx will hold cur_match */ -/* throughout the entire function. %edx will hold the pointer to the */ -/* deflate_state structure during the function's setup (before */ -/* entering the main loop). */ - - movl deflatestate(%esp), %edx - movl curmatch(%esp), %ecx - -/* uInt wmask = s->w_mask; */ -/* unsigned chain_length = s->max_chain_length; */ -/* if (s->prev_length >= s->good_match) { */ -/* chain_length >>= 2; */ -/* } */ - - movl dsPrevLen(%edx), %eax - movl dsGoodMatch(%edx), %ebx - cmpl %ebx, %eax - movl dsWMask(%edx), %eax - movl dsMaxChainLen(%edx), %ebx - jl LastMatchGood - shrl $2, %ebx -LastMatchGood: - -/* chainlen is decremented once beforehand so that the function can */ -/* use the sign flag instead of the zero flag for the exit test. */ -/* It is then shifted into the high word, to make room for the wmask */ -/* value, which it will always accompany. */ - - decl %ebx - shll $16, %ebx - orl %eax, %ebx - movl %ebx, chainlenwmask(%esp) - -/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ - - movl dsNiceMatch(%edx), %eax - movl dsLookahead(%edx), %ebx - cmpl %eax, %ebx - jl LookaheadLess - movl %eax, %ebx -LookaheadLess: movl %ebx, nicematch(%esp) - -/* register Bytef *scan = s->window + s->strstart; */ - - movl dsWindow(%edx), %esi - movl %esi, window(%esp) - movl dsStrStart(%edx), %ebp - lea (%esi,%ebp), %edi - movl %edi, scan(%esp) - -/* Determine how many bytes the scan ptr is off from being */ -/* dword-aligned. */ - - movl %edi, %eax - negl %eax - andl $3, %eax - movl %eax, scanalign(%esp) - -/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ -/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ - - movl dsWSize(%edx), %eax - subl $MIN_LOOKAHEAD, %eax - subl %eax, %ebp - jg LimitPositive - xorl %ebp, %ebp -LimitPositive: - -/* int best_len = s->prev_length; */ - - movl dsPrevLen(%edx), %eax - movl %eax, bestlen(%esp) - -/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ - - addl %eax, %esi - movl %esi, windowbestlen(%esp) - -/* register ush scan_start = *(ushf*)scan; */ -/* register ush scan_end = *(ushf*)(scan+best_len-1); */ -/* Posf *prev = s->prev; */ - - movzwl (%edi), %ebx - movl %ebx, scanstart(%esp) - movzwl -1(%edi,%eax), %ebx - movl %ebx, scanend(%esp) - movl dsPrev(%edx), %edi - -/* Jump into the main loop. */ - - movl chainlenwmask(%esp), %edx - jmp LoopEntry - -.balign 16 - -/* do { - * match = s->window + cur_match; - * if (*(ushf*)(match+best_len-1) != scan_end || - * *(ushf*)match != scan_start) continue; - * [...] - * } while ((cur_match = prev[cur_match & wmask]) > limit - * && --chain_length != 0); - * - * Here is the inner loop of the function. The function will spend the - * majority of its time in this loop, and majority of that time will - * be spent in the first ten instructions. - * - * Within this loop: - * %ebx = scanend - * %ecx = curmatch - * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) - * %esi = windowbestlen - i.e., (window + bestlen) - * %edi = prev - * %ebp = limit - */ -LookupLoop: - andl %edx, %ecx - movzwl (%edi,%ecx,2), %ecx - cmpl %ebp, %ecx - jbe LeaveNow - subl $0x00010000, %edx - js LeaveNow -LoopEntry: movzwl -1(%esi,%ecx), %eax - cmpl %ebx, %eax - jnz LookupLoop - movl window(%esp), %eax - movzwl (%eax,%ecx), %eax - cmpl scanstart(%esp), %eax - jnz LookupLoop - -/* Store the current value of chainlen. */ - - movl %edx, chainlenwmask(%esp) - -/* Point %edi to the string under scrutiny, and %esi to the string we */ -/* are hoping to match it up with. In actuality, %esi and %edi are */ -/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ -/* initialized to -(MAX_MATCH_8 - scanalign). */ - - movl window(%esp), %esi - movl scan(%esp), %edi - addl %ecx, %esi - movl scanalign(%esp), %eax - movl $(-MAX_MATCH_8), %edx - lea MAX_MATCH_8(%edi,%eax), %edi - lea MAX_MATCH_8(%esi,%eax), %esi - -/* Test the strings for equality, 8 bytes at a time. At the end, - * adjust %edx so that it is offset to the exact byte that mismatched. - * - * We already know at this point that the first three bytes of the - * strings match each other, and they can be safely passed over before - * starting the compare loop. So what this code does is skip over 0-3 - * bytes, as much as necessary in order to dword-align the %edi - * pointer. (%esi will still be misaligned three times out of four.) - * - * It should be confessed that this loop usually does not represent - * much of the total running time. Replacing it with a more - * straightforward "rep cmpsb" would not drastically degrade - * performance. - */ -LoopCmps: - movl (%esi,%edx), %eax - xorl (%edi,%edx), %eax - jnz LeaveLoopCmps - movl 4(%esi,%edx), %eax - xorl 4(%edi,%edx), %eax - jnz LeaveLoopCmps4 - addl $8, %edx - jnz LoopCmps - jmp LenMaximum -LeaveLoopCmps4: addl $4, %edx -LeaveLoopCmps: testl $0x0000FFFF, %eax - jnz LenLower - addl $2, %edx - shrl $16, %eax -LenLower: subb $1, %al - adcl $0, %edx - -/* Calculate the length of the match. If it is longer than MAX_MATCH, */ -/* then automatically accept it as the best possible match and leave. */ - - lea (%edi,%edx), %eax - movl scan(%esp), %edi - subl %edi, %eax - cmpl $MAX_MATCH, %eax - jge LenMaximum - -/* If the length of the match is not longer than the best match we */ -/* have so far, then forget it and return to the lookup loop. */ - - movl deflatestate(%esp), %edx - movl bestlen(%esp), %ebx - cmpl %ebx, %eax - jg LongerMatch - movl windowbestlen(%esp), %esi - movl dsPrev(%edx), %edi - movl scanend(%esp), %ebx - movl chainlenwmask(%esp), %edx - jmp LookupLoop - -/* s->match_start = cur_match; */ -/* best_len = len; */ -/* if (len >= nice_match) break; */ -/* scan_end = *(ushf*)(scan+best_len-1); */ - -LongerMatch: movl nicematch(%esp), %ebx - movl %eax, bestlen(%esp) - movl %ecx, dsMatchStart(%edx) - cmpl %ebx, %eax - jge LeaveNow - movl window(%esp), %esi - addl %eax, %esi - movl %esi, windowbestlen(%esp) - movzwl -1(%edi,%eax), %ebx - movl dsPrev(%edx), %edi - movl %ebx, scanend(%esp) - movl chainlenwmask(%esp), %edx - jmp LookupLoop - -/* Accept the current string, with the maximum possible length. */ - -LenMaximum: movl deflatestate(%esp), %edx - movl $MAX_MATCH, bestlen(%esp) - movl %ecx, dsMatchStart(%edx) - -/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ -/* return s->lookahead; */ - -LeaveNow: - movl deflatestate(%esp), %edx - movl bestlen(%esp), %ebx - movl dsLookahead(%edx), %eax - cmpl %eax, %ebx - jg LookaheadRet - movl %ebx, %eax -LookaheadRet: - -/* Restore the stack and return from whence we came. */ - - addl $LocalVarsSize, %esp - .cfi_def_cfa_offset 20 - popl %ebx - .cfi_def_cfa_offset 16 - popl %esi - .cfi_def_cfa_offset 12 - popl %edi - .cfi_def_cfa_offset 8 - popl %ebp - .cfi_def_cfa_offset 4 -.cfi_endproc -match_init: ret diff --git a/src/contrib/zlib/contrib/blast/Makefile b/src/contrib/zlib/contrib/blast/Makefile deleted file mode 100644 index 9be80ba..0000000 --- a/src/contrib/zlib/contrib/blast/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -blast: blast.c blast.h - cc -DTEST -o blast blast.c - -test: blast - blast < test.pk | cmp - test.txt - -clean: - rm -f blast blast.o diff --git a/src/contrib/zlib/contrib/blast/README b/src/contrib/zlib/contrib/blast/README deleted file mode 100644 index e3a60b3..0000000 --- a/src/contrib/zlib/contrib/blast/README +++ /dev/null @@ -1,4 +0,0 @@ -Read blast.h for purpose and usage. - -Mark Adler -madler@alumni.caltech.edu diff --git a/src/contrib/zlib/contrib/blast/blast.c b/src/contrib/zlib/contrib/blast/blast.c deleted file mode 100644 index e6e6590..0000000 --- a/src/contrib/zlib/contrib/blast/blast.c +++ /dev/null @@ -1,466 +0,0 @@ -/* blast.c - * Copyright (C) 2003, 2012, 2013 Mark Adler - * For conditions of distribution and use, see copyright notice in blast.h - * version 1.3, 24 Aug 2013 - * - * blast.c decompresses data compressed by the PKWare Compression Library. - * This function provides functionality similar to the explode() function of - * the PKWare library, hence the name "blast". - * - * This decompressor is based on the excellent format description provided by - * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the - * example Ben provided in the post is incorrect. The distance 110001 should - * instead be 111000. When corrected, the example byte stream becomes: - * - * 00 04 82 24 25 8f 80 7f - * - * which decompresses to "AIAIAIAIAIAIA" (without the quotes). - */ - -/* - * Change history: - * - * 1.0 12 Feb 2003 - First version - * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data - * 1.2 24 Oct 2012 - Add note about using binary mode in stdio - * - Fix comparisons of differently signed integers - * 1.3 24 Aug 2013 - Return unused input from blast() - * - Fix test code to correctly report unused input - * - Enable the provision of initial input to blast() - */ - -#include /* for NULL */ -#include /* for setjmp(), longjmp(), and jmp_buf */ -#include "blast.h" /* prototype for blast() */ - -#define local static /* for local function definitions */ -#define MAXBITS 13 /* maximum code length */ -#define MAXWIN 4096 /* maximum window size */ - -/* input and output state */ -struct state { - /* input state */ - blast_in infun; /* input function provided by user */ - void *inhow; /* opaque information passed to infun() */ - unsigned char *in; /* next input location */ - unsigned left; /* available input at in */ - int bitbuf; /* bit buffer */ - int bitcnt; /* number of bits in bit buffer */ - - /* input limit error return state for bits() and decode() */ - jmp_buf env; - - /* output state */ - blast_out outfun; /* output function provided by user */ - void *outhow; /* opaque information passed to outfun() */ - unsigned next; /* index of next write location in out[] */ - int first; /* true to check distances (for first 4K) */ - unsigned char out[MAXWIN]; /* output buffer and sliding window */ -}; - -/* - * Return need bits from the input stream. This always leaves less than - * eight bits in the buffer. bits() works properly for need == 0. - * - * Format notes: - * - * - Bits are stored in bytes from the least significant bit to the most - * significant bit. Therefore bits are dropped from the bottom of the bit - * buffer, using shift right, and new bytes are appended to the top of the - * bit buffer, using shift left. - */ -local int bits(struct state *s, int need) -{ - int val; /* bit accumulator */ - - /* load at least need bits into val */ - val = s->bitbuf; - while (s->bitcnt < need) { - if (s->left == 0) { - s->left = s->infun(s->inhow, &(s->in)); - if (s->left == 0) longjmp(s->env, 1); /* out of input */ - } - val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ - s->left--; - s->bitcnt += 8; - } - - /* drop need bits and update buffer, always zero to seven bits left */ - s->bitbuf = val >> need; - s->bitcnt -= need; - - /* return need bits, zeroing the bits above that */ - return val & ((1 << need) - 1); -} - -/* - * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of - * each length, which for a canonical code are stepped through in order. - * symbol[] are the symbol values in canonical order, where the number of - * entries is the sum of the counts in count[]. The decoding process can be - * seen in the function decode() below. - */ -struct huffman { - short *count; /* number of symbols of each length */ - short *symbol; /* canonically ordered symbols */ -}; - -/* - * Decode a code from the stream s using huffman table h. Return the symbol or - * a negative value if there is an error. If all of the lengths are zero, i.e. - * an empty code, or if the code is incomplete and an invalid code is received, - * then -9 is returned after reading MAXBITS bits. - * - * Format notes: - * - * - The codes as stored in the compressed data are bit-reversed relative to - * a simple integer ordering of codes of the same lengths. Hence below the - * bits are pulled from the compressed data one at a time and used to - * build the code value reversed from what is in the stream in order to - * permit simple integer comparisons for decoding. - * - * - The first code for the shortest length is all ones. Subsequent codes of - * the same length are simply integer decrements of the previous code. When - * moving up a length, a one bit is appended to the code. For a complete - * code, the last code of the longest length will be all zeros. To support - * this ordering, the bits pulled during decoding are inverted to apply the - * more "natural" ordering starting with all zeros and incrementing. - */ -local int decode(struct state *s, struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - int bitbuf; /* bits from stream */ - int left; /* bits left in next or left to process */ - short *next; /* next number of codes */ - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while (1) { - while (left--) { - code |= (bitbuf & 1) ^ 1; /* invert code */ - bitbuf >>= 1; - count = *next++; - if (code < first + count) { /* if length len, return symbol */ - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS+1) - len; - if (left == 0) break; - if (s->left == 0) { - s->left = s->infun(s->inhow, &(s->in)); - if (s->left == 0) longjmp(s->env, 1); /* out of input */ - } - bitbuf = *(s->in)++; - s->left--; - if (left > 8) left = 8; - } - return -9; /* ran out of codes */ -} - -/* - * Given a list of repeated code lengths rep[0..n-1], where each byte is a - * count (high four bits + 1) and a code length (low four bits), generate the - * list of code lengths. This compaction reduces the size of the object code. - * Then given the list of code lengths length[0..n-1] representing a canonical - * Huffman code for n symbols, construct the tables required to decode those - * codes. Those tables are the number of codes of each length, and the symbols - * sorted by length, retaining their original order within each length. The - * return value is zero for a complete code set, negative for an over- - * subscribed code set, and positive for an incomplete code set. The tables - * can be used if the return value is zero or positive, but they cannot be used - * if the return value is negative. If the return value is zero, it is not - * possible for decode() using that table to return an error--any stream of - * enough bits will resolve to a symbol. If the return value is positive, then - * it is possible for decode() using that table to return an error for received - * codes past the end of the incomplete lengths. - */ -local int construct(struct huffman *h, const unsigned char *rep, int n) -{ - int symbol; /* current symbol when stepping through length[] */ - int len; /* current length when stepping through h->count[] */ - int left; /* number of possible codes left of current length */ - short offs[MAXBITS+1]; /* offsets in symbol table for each length */ - short length[256]; /* code lengths */ - - /* convert compact repeat counts into symbol bit length list */ - symbol = 0; - do { - len = *rep++; - left = (len >> 4) + 1; - len &= 15; - do { - length[symbol++] = len; - } while (--left); - } while (--n); - n = symbol; - - /* count number of codes of each length */ - for (len = 0; len <= MAXBITS; len++) - h->count[len] = 0; - for (symbol = 0; symbol < n; symbol++) - (h->count[length[symbol]])++; /* assumes lengths are within bounds */ - if (h->count[0] == n) /* no codes! */ - return 0; /* complete, but decode() will fail */ - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; /* one possible code of zero length */ - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; /* one more bit, double codes left */ - left -= h->count[len]; /* deduct count from possible codes */ - if (left < 0) return left; /* over-subscribed--return negative */ - } /* left > 0 means incomplete */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + h->count[len]; - - /* - * put symbols in table sorted by length, by symbol order within each - * length - */ - for (symbol = 0; symbol < n; symbol++) - if (length[symbol] != 0) - h->symbol[offs[length[symbol]]++] = symbol; - - /* return zero for complete set, positive for incomplete set */ - return left; -} - -/* - * Decode PKWare Compression Library stream. - * - * Format notes: - * - * - First byte is 0 if literals are uncoded or 1 if they are coded. Second - * byte is 4, 5, or 6 for the number of extra bits in the distance code. - * This is the base-2 logarithm of the dictionary size minus six. - * - * - Compressed data is a combination of literals and length/distance pairs - * terminated by an end code. Literals are either Huffman coded or - * uncoded bytes. A length/distance pair is a coded length followed by a - * coded distance to represent a string that occurs earlier in the - * uncompressed data that occurs again at the current location. - * - * - A bit preceding a literal or length/distance pair indicates which comes - * next, 0 for literals, 1 for length/distance. - * - * - If literals are uncoded, then the next eight bits are the literal, in the - * normal bit order in the stream, i.e. no bit-reversal is needed. Similarly, - * no bit reversal is needed for either the length extra bits or the distance - * extra bits. - * - * - Literal bytes are simply written to the output. A length/distance pair is - * an instruction to copy previously uncompressed bytes to the output. The - * copy is from distance bytes back in the output stream, copying for length - * bytes. - * - * - Distances pointing before the beginning of the output data are not - * permitted. - * - * - Overlapped copies, where the length is greater than the distance, are - * allowed and common. For example, a distance of one and a length of 518 - * simply copies the last byte 518 times. A distance of four and a length of - * twelve copies the last four bytes three times. A simple forward copy - * ignoring whether the length is greater than the distance or not implements - * this correctly. - */ -local int decomp(struct state *s) -{ - int lit; /* true if literals are coded */ - int dict; /* log2(dictionary size) - 6 */ - int symbol; /* decoded symbol, extra bits for distance */ - int len; /* length for copy */ - unsigned dist; /* distance for copy */ - int copy; /* copy counter */ - unsigned char *from, *to; /* copy pointers */ - static int virgin = 1; /* build tables once */ - static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ - static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ - static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ - static struct huffman litcode = {litcnt, litsym}; /* length code */ - static struct huffman lencode = {lencnt, lensym}; /* length code */ - static struct huffman distcode = {distcnt, distsym};/* distance code */ - /* bit lengths of literal codes */ - static const unsigned char litlen[] = { - 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, - 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, - 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, - 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, - 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, - 44, 173}; - /* bit lengths of length codes 0..15 */ - static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; - /* bit lengths of distance codes 0..63 */ - static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; - static const short base[16] = { /* base for length codes */ - 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; - static const char extra[16] = { /* extra bits for length codes */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; - - /* set up decoding tables (once--might not be thread-safe) */ - if (virgin) { - construct(&litcode, litlen, sizeof(litlen)); - construct(&lencode, lenlen, sizeof(lenlen)); - construct(&distcode, distlen, sizeof(distlen)); - virgin = 0; - } - - /* read header */ - lit = bits(s, 8); - if (lit > 1) return -1; - dict = bits(s, 8); - if (dict < 4 || dict > 6) return -2; - - /* decode literals and length/distance pairs */ - do { - if (bits(s, 1)) { - /* get length */ - symbol = decode(s, &lencode); - len = base[symbol] + bits(s, extra[symbol]); - if (len == 519) break; /* end code */ - - /* get distance */ - symbol = len == 2 ? 2 : dict; - dist = decode(s, &distcode) << symbol; - dist += bits(s, symbol); - dist++; - if (s->first && dist > s->next) - return -3; /* distance too far back */ - - /* copy length bytes from distance bytes back */ - do { - to = s->out + s->next; - from = to - dist; - copy = MAXWIN; - if (s->next < dist) { - from += copy; - copy = dist; - } - copy -= s->next; - if (copy > len) copy = len; - len -= copy; - s->next += copy; - do { - *to++ = *from++; - } while (--copy); - if (s->next == MAXWIN) { - if (s->outfun(s->outhow, s->out, s->next)) return 1; - s->next = 0; - s->first = 0; - } - } while (len != 0); - } - else { - /* get literal and write it */ - symbol = lit ? decode(s, &litcode) : bits(s, 8); - s->out[s->next++] = symbol; - if (s->next == MAXWIN) { - if (s->outfun(s->outhow, s->out, s->next)) return 1; - s->next = 0; - s->first = 0; - } - } - } while (1); - return 0; -} - -/* See comments in blast.h */ -int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, - unsigned *left, unsigned char **in) -{ - struct state s; /* input/output state */ - int err; /* return value */ - - /* initialize input state */ - s.infun = infun; - s.inhow = inhow; - if (left != NULL && *left) { - s.left = *left; - s.in = *in; - } - else - s.left = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - /* initialize output state */ - s.outfun = outfun; - s.outhow = outhow; - s.next = 0; - s.first = 1; - - /* return if bits() or decode() tries to read past available input */ - if (setjmp(s.env) != 0) /* if came back here via longjmp(), */ - err = 2; /* then skip decomp(), return error */ - else - err = decomp(&s); /* decompress */ - - /* return unused input */ - if (left != NULL) - *left = s.left; - if (in != NULL) - *in = s.left ? s.in : NULL; - - /* write any leftover output and update the error code if needed */ - if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0) - err = 1; - return err; -} - -#ifdef TEST -/* Example of how to use blast() */ -#include -#include - -#define CHUNK 16384 - -local unsigned inf(void *how, unsigned char **buf) -{ - static unsigned char hold[CHUNK]; - - *buf = hold; - return fread(hold, 1, CHUNK, (FILE *)how); -} - -local int outf(void *how, unsigned char *buf, unsigned len) -{ - return fwrite(buf, 1, len, (FILE *)how) != len; -} - -/* Decompress a PKWare Compression Library stream from stdin to stdout */ -int main(void) -{ - int ret; - unsigned left; - - /* decompress to stdout */ - left = 0; - ret = blast(inf, stdin, outf, stdout, &left, NULL); - if (ret != 0) - fprintf(stderr, "blast error: %d\n", ret); - - /* count any leftover bytes */ - while (getchar() != EOF) - left++; - if (left) - fprintf(stderr, "blast warning: %u unused bytes of input\n", left); - - /* return blast() error code */ - return ret; -} -#endif diff --git a/src/contrib/zlib/contrib/blast/blast.h b/src/contrib/zlib/contrib/blast/blast.h deleted file mode 100644 index 6cf65ed..0000000 --- a/src/contrib/zlib/contrib/blast/blast.h +++ /dev/null @@ -1,83 +0,0 @@ -/* blast.h -- interface for blast.c - Copyright (C) 2003, 2012, 2013 Mark Adler - version 1.3, 24 Aug 2013 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - - -/* - * blast() decompresses the PKWare Data Compression Library (DCL) compressed - * format. It provides the same functionality as the explode() function in - * that library. (Note: PKWare overused the "implode" verb, and the format - * used by their library implode() function is completely different and - * incompatible with the implode compression method supported by PKZIP.) - * - * The binary mode for stdio functions should be used to assure that the - * compressed data is not corrupted when read or written. For example: - * fopen(..., "rb") and fopen(..., "wb"). - */ - - -typedef unsigned (*blast_in)(void *how, unsigned char **buf); -typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); -/* Definitions for input/output functions passed to blast(). See below for - * what the provided functions need to do. - */ - - -int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, - unsigned *left, unsigned char **in); -/* Decompress input to output using the provided infun() and outfun() calls. - * On success, the return value of blast() is zero. If there is an error in - * the source data, i.e. it is not in the proper format, then a negative value - * is returned. If there is not enough input available or there is not enough - * output space, then a positive error is returned. - * - * The input function is invoked: len = infun(how, &buf), where buf is set by - * infun() to point to the input buffer, and infun() returns the number of - * available bytes there. If infun() returns zero, then blast() returns with - * an input error. (blast() only asks for input if it needs it.) inhow is for - * use by the application to pass an input descriptor to infun(), if desired. - * - * If left and in are not NULL and *left is not zero when blast() is called, - * then the *left bytes are *in are consumed for input before infun() is used. - * - * The output function is invoked: err = outfun(how, buf, len), where the bytes - * to be written are buf[0..len-1]. If err is not zero, then blast() returns - * with an output error. outfun() is always called with len <= 4096. outhow - * is for use by the application to pass an output descriptor to outfun(), if - * desired. - * - * If there is any unused input, *left is set to the number of bytes that were - * read and *in points to them. Otherwise *left is set to zero and *in is set - * to NULL. If left or in are NULL, then they are not set. - * - * The return codes are: - * - * 2: ran out of input before completing decompression - * 1: output error before completing decompression - * 0: successful decompression - * -1: literal flag not zero or one - * -2: dictionary size not in 4..6 - * -3: distance is too far back - * - * At the bottom of blast.c is an example program that uses blast() that can be - * compiled to produce a command-line decompression filter by defining TEST. - */ diff --git a/src/contrib/zlib/contrib/blast/test.pk b/src/contrib/zlib/contrib/blast/test.pk deleted file mode 100644 index be10b2bbb251759ffdf6da49fadd1a3f137a54c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 PcmZQzX;M+`Z>R?V2c!aC diff --git a/src/contrib/zlib/contrib/blast/test.txt b/src/contrib/zlib/contrib/blast/test.txt deleted file mode 100644 index bfdf1c5..0000000 --- a/src/contrib/zlib/contrib/blast/test.txt +++ /dev/null @@ -1 +0,0 @@ -AIAIAIAIAIAIA \ No newline at end of file diff --git a/src/contrib/zlib/contrib/delphi/ZLib.pas b/src/contrib/zlib/contrib/delphi/ZLib.pas deleted file mode 100644 index 060e199..0000000 --- a/src/contrib/zlib/contrib/delphi/ZLib.pas +++ /dev/null @@ -1,557 +0,0 @@ -{*******************************************************} -{ } -{ Borland Delphi Supplemental Components } -{ ZLIB Data Compression Interface Unit } -{ } -{ Copyright (c) 1997,99 Borland Corporation } -{ } -{*******************************************************} - -{ Updated for zlib 1.2.x by Cosmin Truta } - -unit ZLib; - -interface - -uses SysUtils, Classes; - -type - TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl; - TFree = procedure (AppData, Block: Pointer); cdecl; - - // Internal structure. Ignore. - TZStreamRec = packed record - next_in: PChar; // next input byte - avail_in: Integer; // number of bytes available at next_in - total_in: Longint; // total nb of input bytes read so far - - next_out: PChar; // next output byte should be put here - avail_out: Integer; // remaining free space at next_out - total_out: Longint; // total nb of bytes output so far - - msg: PChar; // last error message, NULL if no error - internal: Pointer; // not visible by applications - - zalloc: TAlloc; // used to allocate the internal state - zfree: TFree; // used to free the internal state - AppData: Pointer; // private data object passed to zalloc and zfree - - data_type: Integer; // best guess about the data type: ascii or binary - adler: Longint; // adler32 value of the uncompressed data - reserved: Longint; // reserved for future use - end; - - // Abstract ancestor class - TCustomZlibStream = class(TStream) - private - FStrm: TStream; - FStrmPos: Integer; - FOnProgress: TNotifyEvent; - FZRec: TZStreamRec; - FBuffer: array [Word] of Char; - protected - procedure Progress(Sender: TObject); dynamic; - property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; - constructor Create(Strm: TStream); - end; - -{ TCompressionStream compresses data on the fly as data is written to it, and - stores the compressed data to another stream. - - TCompressionStream is write-only and strictly sequential. Reading from the - stream will raise an exception. Using Seek to move the stream pointer - will raise an exception. - - Output data is cached internally, written to the output stream only when - the internal output buffer is full. All pending output data is flushed - when the stream is destroyed. - - The Position property returns the number of uncompressed bytes of - data that have been written to the stream so far. - - CompressionRate returns the on-the-fly percentage by which the original - data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 - If raw data size = 100 and compressed data size = 25, the CompressionRate - is 75% - - The OnProgress event is called each time the output buffer is filled and - written to the output stream. This is useful for updating a progress - indicator when you are writing a large chunk of data to the compression - stream in a single call.} - - - TCompressionLevel = (clNone, clFastest, clDefault, clMax); - - TCompressionStream = class(TCustomZlibStream) - private - function GetCompressionRate: Single; - public - constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); - destructor Destroy; override; - function Read(var Buffer; Count: Longint): Longint; override; - function Write(const Buffer; Count: Longint): Longint; override; - function Seek(Offset: Longint; Origin: Word): Longint; override; - property CompressionRate: Single read GetCompressionRate; - property OnProgress; - end; - -{ TDecompressionStream decompresses data on the fly as data is read from it. - - Compressed data comes from a separate source stream. TDecompressionStream - is read-only and unidirectional; you can seek forward in the stream, but not - backwards. The special case of setting the stream position to zero is - allowed. Seeking forward decompresses data until the requested position in - the uncompressed data has been reached. Seeking backwards, seeking relative - to the end of the stream, requesting the size of the stream, and writing to - the stream will raise an exception. - - The Position property returns the number of bytes of uncompressed data that - have been read from the stream so far. - - The OnProgress event is called each time the internal input buffer of - compressed data is exhausted and the next block is read from the input stream. - This is useful for updating a progress indicator when you are reading a - large chunk of data from the decompression stream in a single call.} - - TDecompressionStream = class(TCustomZlibStream) - public - constructor Create(Source: TStream); - destructor Destroy; override; - function Read(var Buffer; Count: Longint): Longint; override; - function Write(const Buffer; Count: Longint): Longint; override; - function Seek(Offset: Longint; Origin: Word): Longint; override; - property OnProgress; - end; - - - -{ CompressBuf compresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - Out: OutBuf = ptr to newly allocated buffer containing decompressed data - OutBytes = number of bytes in OutBuf } -procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; - out OutBuf: Pointer; out OutBytes: Integer); - - -{ DecompressBuf decompresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - OutEstimate = zero, or est. size of the decompressed data - Out: OutBuf = ptr to newly allocated buffer containing decompressed data - OutBytes = number of bytes in OutBuf } -procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; - OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); - -{ DecompressToUserBuf decompresses data, buffer to buffer, in one call. - In: InBuf = ptr to compressed data - InBytes = number of bytes in InBuf - Out: OutBuf = ptr to user-allocated buffer to contain decompressed data - BufSize = number of bytes in OutBuf } -procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; - const OutBuf: Pointer; BufSize: Integer); - -const - zlib_version = '1.2.11'; - -type - EZlibError = class(Exception); - ECompressionError = class(EZlibError); - EDecompressionError = class(EZlibError); - -implementation - -uses ZLibConst; - -const - Z_NO_FLUSH = 0; - Z_PARTIAL_FLUSH = 1; - Z_SYNC_FLUSH = 2; - Z_FULL_FLUSH = 3; - Z_FINISH = 4; - - Z_OK = 0; - Z_STREAM_END = 1; - Z_NEED_DICT = 2; - Z_ERRNO = (-1); - Z_STREAM_ERROR = (-2); - Z_DATA_ERROR = (-3); - Z_MEM_ERROR = (-4); - Z_BUF_ERROR = (-5); - Z_VERSION_ERROR = (-6); - - Z_NO_COMPRESSION = 0; - Z_BEST_SPEED = 1; - Z_BEST_COMPRESSION = 9; - Z_DEFAULT_COMPRESSION = (-1); - - Z_FILTERED = 1; - Z_HUFFMAN_ONLY = 2; - Z_RLE = 3; - Z_DEFAULT_STRATEGY = 0; - - Z_BINARY = 0; - Z_ASCII = 1; - Z_UNKNOWN = 2; - - Z_DEFLATED = 8; - - -{$L adler32.obj} -{$L compress.obj} -{$L crc32.obj} -{$L deflate.obj} -{$L infback.obj} -{$L inffast.obj} -{$L inflate.obj} -{$L inftrees.obj} -{$L trees.obj} -{$L uncompr.obj} -{$L zutil.obj} - -procedure adler32; external; -procedure compressBound; external; -procedure crc32; external; -procedure deflateInit2_; external; -procedure deflateParams; external; - -function _malloc(Size: Integer): Pointer; cdecl; -begin - Result := AllocMem(Size); -end; - -procedure _free(Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; -begin - FillChar(P^, count, B); -end; - -procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; -begin - Move(source^, dest^, count); -end; - - - -// deflate compresses data -function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; - recsize: Integer): Integer; external; -function deflate(var strm: TZStreamRec; flush: Integer): Integer; external; -function deflateEnd(var strm: TZStreamRec): Integer; external; - -// inflate decompresses data -function inflateInit_(var strm: TZStreamRec; version: PChar; - recsize: Integer): Integer; external; -function inflate(var strm: TZStreamRec; flush: Integer): Integer; external; -function inflateEnd(var strm: TZStreamRec): Integer; external; -function inflateReset(var strm: TZStreamRec): Integer; external; - - -function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl; -begin -// GetMem(Result, Items*Size); - Result := AllocMem(Items * Size); -end; - -procedure zlibFreeMem(AppData, Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -{function zlibCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise EZlibError.Create('error'); //!! -end;} - -function CCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise ECompressionError.Create('error'); //!! -end; - -function DCheck(code: Integer): Integer; -begin - Result := code; - if code < 0 then - raise EDecompressionError.Create('error'); //!! -end; - -procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; - out OutBuf: Pointer; out OutBytes: Integer); -var - strm: TZStreamRec; - P: Pointer; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; - GetMem(OutBuf, OutBytes); - try - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := OutBytes; - CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm))); - try - while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do - begin - P := OutBuf; - Inc(OutBytes, 256); - ReallocMem(OutBuf, OutBytes); - strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); - strm.avail_out := 256; - end; - finally - CCheck(deflateEnd(strm)); - end; - ReallocMem(OutBuf, strm.total_out); - OutBytes := strm.total_out; - except - FreeMem(OutBuf); - raise - end; -end; - - -procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; - OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); -var - strm: TZStreamRec; - P: Pointer; - BufInc: Integer; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - BufInc := (InBytes + 255) and not 255; - if OutEstimate = 0 then - OutBytes := BufInc - else - OutBytes := OutEstimate; - GetMem(OutBuf, OutBytes); - try - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := OutBytes; - DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); - try - while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do - begin - P := OutBuf; - Inc(OutBytes, BufInc); - ReallocMem(OutBuf, OutBytes); - strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); - strm.avail_out := BufInc; - end; - finally - DCheck(inflateEnd(strm)); - end; - ReallocMem(OutBuf, strm.total_out); - OutBytes := strm.total_out; - except - FreeMem(OutBuf); - raise - end; -end; - -procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; - const OutBuf: Pointer; BufSize: Integer); -var - strm: TZStreamRec; -begin - FillChar(strm, sizeof(strm), 0); - strm.zalloc := zlibAllocMem; - strm.zfree := zlibFreeMem; - strm.next_in := InBuf; - strm.avail_in := InBytes; - strm.next_out := OutBuf; - strm.avail_out := BufSize; - DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); - try - if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then - raise EZlibError.CreateRes(@sTargetBufferTooSmall); - finally - DCheck(inflateEnd(strm)); - end; -end; - -// TCustomZlibStream - -constructor TCustomZLibStream.Create(Strm: TStream); -begin - inherited Create; - FStrm := Strm; - FStrmPos := Strm.Position; - FZRec.zalloc := zlibAllocMem; - FZRec.zfree := zlibFreeMem; -end; - -procedure TCustomZLibStream.Progress(Sender: TObject); -begin - if Assigned(FOnProgress) then FOnProgress(Sender); -end; - - -// TCompressionStream - -constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; - Dest: TStream); -const - Levels: array [TCompressionLevel] of ShortInt = - (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); -begin - inherited Create(Dest); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); -end; - -destructor TCompressionStream.Destroy; -begin - FZRec.next_in := nil; - FZRec.avail_in := 0; - try - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) - and (FZRec.avail_out = 0) do - begin - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - end; - if FZRec.avail_out < sizeof(FBuffer) then - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); - finally - deflateEnd(FZRec); - end; - inherited Destroy; -end; - -function TCompressionStream.Read(var Buffer; Count: Longint): Longint; -begin - raise ECompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TCompressionStream.Write(const Buffer; Count: Longint): Longint; -begin - FZRec.next_in := @Buffer; - FZRec.avail_in := Count; - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (FZRec.avail_in > 0) do - begin - CCheck(deflate(FZRec, 0)); - if FZRec.avail_out = 0 then - begin - FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); - FZRec.next_out := FBuffer; - FZRec.avail_out := sizeof(FBuffer); - FStrmPos := FStrm.Position; - Progress(Self); - end; - end; - Result := Count; -end; - -function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; -begin - if (Offset = 0) and (Origin = soFromCurrent) then - Result := FZRec.total_in - else - raise ECompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TCompressionStream.GetCompressionRate: Single; -begin - if FZRec.total_in = 0 then - Result := 0 - else - Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; -end; - - -// TDecompressionStream - -constructor TDecompressionStream.Create(Source: TStream); -begin - inherited Create(Source); - FZRec.next_in := FBuffer; - FZRec.avail_in := 0; - DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); -end; - -destructor TDecompressionStream.Destroy; -begin - FStrm.Seek(-FZRec.avail_in, 1); - inflateEnd(FZRec); - inherited Destroy; -end; - -function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; -begin - FZRec.next_out := @Buffer; - FZRec.avail_out := Count; - if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; - while (FZRec.avail_out > 0) do - begin - if FZRec.avail_in = 0 then - begin - FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); - if FZRec.avail_in = 0 then - begin - Result := Count - FZRec.avail_out; - Exit; - end; - FZRec.next_in := FBuffer; - FStrmPos := FStrm.Position; - Progress(Self); - end; - CCheck(inflate(FZRec, 0)); - end; - Result := Count; -end; - -function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; -begin - raise EDecompressionError.CreateRes(@sInvalidStreamOp); -end; - -function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; -var - I: Integer; - Buf: array [0..4095] of Char; -begin - if (Offset = 0) and (Origin = soFromBeginning) then - begin - DCheck(inflateReset(FZRec)); - FZRec.next_in := FBuffer; - FZRec.avail_in := 0; - FStrm.Position := 0; - FStrmPos := 0; - end - else if ( (Offset >= 0) and (Origin = soFromCurrent)) or - ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then - begin - if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); - if Offset > 0 then - begin - for I := 1 to Offset div sizeof(Buf) do - ReadBuffer(Buf, sizeof(Buf)); - ReadBuffer(Buf, Offset mod sizeof(Buf)); - end; - end - else - raise EDecompressionError.CreateRes(@sInvalidStreamOp); - Result := FZRec.total_out; -end; - - -end. diff --git a/src/contrib/zlib/contrib/delphi/ZLibConst.pas b/src/contrib/zlib/contrib/delphi/ZLibConst.pas deleted file mode 100644 index cdfe136..0000000 --- a/src/contrib/zlib/contrib/delphi/ZLibConst.pas +++ /dev/null @@ -1,11 +0,0 @@ -unit ZLibConst; - -interface - -resourcestring - sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; - sInvalidStreamOp = 'Invalid stream operation'; - -implementation - -end. diff --git a/src/contrib/zlib/contrib/delphi/readme.txt b/src/contrib/zlib/contrib/delphi/readme.txt deleted file mode 100644 index 2dc9a8b..0000000 --- a/src/contrib/zlib/contrib/delphi/readme.txt +++ /dev/null @@ -1,76 +0,0 @@ - -Overview -======== - -This directory contains an update to the ZLib interface unit, -distributed by Borland as a Delphi supplemental component. - -The original ZLib unit is Copyright (c) 1997,99 Borland Corp., -and is based on zlib version 1.0.4. There are a series of bugs -and security problems associated with that old zlib version, and -we recommend the users to update their ZLib unit. - - -Summary of modifications -======================== - -- Improved makefile, adapted to zlib version 1.2.1. - -- Some field types from TZStreamRec are changed from Integer to - Longint, for consistency with the zlib.h header, and for 64-bit - readiness. - -- The zlib_version constant is updated. - -- The new Z_RLE strategy has its corresponding symbolic constant. - -- The allocation and deallocation functions and function types - (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, - and _malloc and _free are added as C RTL stubs. As a result, - the original C sources of zlib can be compiled out of the box, - and linked to the ZLib unit. - - -Suggestions for improvements -============================ - -Currently, the ZLib unit provides only a limited wrapper around -the zlib library, and much of the original zlib functionality is -missing. Handling compressed file formats like ZIP/GZIP or PNG -cannot be implemented without having this functionality. -Applications that handle these formats are either using their own, -duplicated code, or not using the ZLib unit at all. - -Here are a few suggestions: - -- Checksum class wrappers around adler32() and crc32(), similar - to the Java classes that implement the java.util.zip.Checksum - interface. - -- The ability to read and write raw deflate streams, without the - zlib stream header and trailer. Raw deflate streams are used - in the ZIP file format. - -- The ability to read and write gzip streams, used in the GZIP - file format, and normally produced by the gzip program. - -- The ability to select a different compression strategy, useful - to PNG and MNG image compression, and to multimedia compression - in general. Besides the compression level - - TCompressionLevel = (clNone, clFastest, clDefault, clMax); - - which, in fact, could have used the 'z' prefix and avoided - TColor-like symbols - - TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); - - there could be a compression strategy - - TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); - -- ZIP and GZIP stream handling via TStreams. - - --- -Cosmin Truta diff --git a/src/contrib/zlib/contrib/delphi/zlibd32.mak b/src/contrib/zlib/contrib/delphi/zlibd32.mak deleted file mode 100644 index 9bb00b7..0000000 --- a/src/contrib/zlib/contrib/delphi/zlibd32.mak +++ /dev/null @@ -1,99 +0,0 @@ -# Makefile for zlib -# For use with Delphi and C++ Builder under Win32 -# Updated for zlib 1.2.x by Cosmin Truta - -# ------------ Borland C++ ------------ - -# This project uses the Delphi (fastcall/register) calling convention: -LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl - -CC = bcc32 -LD = bcc32 -AR = tlib -# do not use "-pr" in CFLAGS -CFLAGS = -a -d -k- -O2 $(LOC) -LDFLAGS = - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del *.obj - -del *.exe - -del *.lib - -del *.tds - -del zlib.bak - -del foo.gz - diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib.build b/src/contrib/zlib/contrib/dotzlib/DotZLib.build deleted file mode 100644 index e69630c..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib.build +++ /dev/null @@ -1,33 +0,0 @@ - - - A .Net wrapper library around ZLib1.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib.chm b/src/contrib/zlib/contrib/dotzlib/DotZLib.chm deleted file mode 100644 index f214a444aebb20950fb3e8499b36731e1f12be95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72726 zcmeGEby!tR_Xmt0Lb^-3ySqWUyF;2oNq0+kgMffYgLESxDJ4jYNJ^JTHv%sx-r#-v zJooqc<9Geu_qyC%`^?@mpEY~UXU(jcS?6pdRg}fR004mg^$Bu)%1mlyL4X4QNEaZU zg&sr5>2QFIcf>23$bY-P!QUL1KN5iJZK}ffiW3R5Bgdsi#SjndZHoZ7pFgTx{Kvz zl?C`=WYS*WsmLox3SSrcy2a>U->NFfT;oBWza%PF`f;lwBm?q1PBTK{x+--^IT3kv zWsrnPVqY0p22wFe6GwAd19NMT#CmhT0wib#Qh6aMNjYT|ki;D7XOGYsNY&K^9UN?o z%ncmPoq;mu)=wO6G{*aFfr7n_EzsW4?OK=|9Qg(!4Rmv{u{Zup4&xu0LMrw^AV|WL zwQsr1_s9JrB4XfZ0FoHNo#>AC4@p@ATad(TRwb-|l-$z;f)Is4#Ky?U3TW+k-2@wJ zdNVU4khpqL-+b49mOKH8pXU?Axt4I$k})@=7c{m6+6$Wjjh;9-S<#z0T3Lel_6kK{ z(ESI5s;#ksBT&!A8E9{5V_>Yu@xs_Wvg1a4XW~9`%&`_aeeJ)((#LPDYM4 z_P1bvf^b5Le+4t$qN5&#DE~W}`4*jo5@tpG`?_U;R)#?PTaA4`Y7~qAN1&sbjq%T> zWj@XEAo#1spY)0Yt%3FicWv5~3zH%HFDNCT1JLn@j{f;lA>2&=1^aiq+%n<6i4ckN zzsTKk;{Vw>0`q^7yX^=5y$_%1{V#H?x9w}T45wlIzqjv}X#aBXD6{`Yp_+lE6Y%yC zvAiK_cU|-!MiDY_0MhFjIoaD^52PO=0n>~j#w7n)tM4M;$Bh3eRfG)Hzaa0~Gw=m` zs1Vz~;Qxb71J`(?*#1}9Te}8M!9+6uud=tc4Qv-omi%93Z|xgc;}Ido`oFdJ*2aN( z^3k;aM(sU22kdBss?h)UNBzUU1eD1|h%o%0g>FYzz#EiM{{OqwtqlS?6~amWr9oom zK+B)rBw)xPoR9jy>-LME3J7$1rTMP{_xx4B8EuxqoyY&}(72s(%z?LN30Ou87rAra z|B(4bBfn$pD4YKZzNd|U3Q8pBf8povn)nAnhqK(dWnmj*pwacbW_&kE-I^B!eDF&e= zzkBj6o3~FM*9s%~T{Et&W?*UVerwo}d9M&^{NJ?pzHvh~C_>#H{s#2jz(Kp%;Y`0X z@Dm{?6BD4l@?Q@N9w7}8yj%Eu9}3^ukhlI#J3|f#Lu`Imul>!!L*B{pj=c-S5S`y4 zuW`RxEi}+F4Eb+k>_&rsc--J>v|t0ge>Pdv`Fi@j?J1$rUSY<+!QA(b!HrIlD!<|P z7ylFVO}b9F@p~coG=qg7vHB_q7h1r3{n#+fe>h8z0>mi+=#_ zX%duU7QywmcK=kGfX+b6A00F_2Rs_*9zsc&h52vBsv-z? zxaaqOLHvF7!SbWlux6I~D}CYrCUa}Xurk*BEB#+Y{?RW&zi8fH>HjD2txFF*a=X9M z|4-;!FBN(vbAP4(3;Gueg|?vFU+Mo1c+XN{VO%*LcisJ$K_+2feY3f`rELr zJe2%;+xxr25HSWJ1O5n30L~7!4rT+I2HFJ51=0yZ?STQf6qqY$0th@v6o4OK0=U`# z(?Z#%dGKq@!3>E)vb-&IgQ7?o;=7W_=qr> zNUgi+?Ow4A(Aw1TcD)h#nk|C;w;CzfIGF#4Gu%WAB0HW$-1E`*YP;h!s!S#M_hj8* zgxr3T71aY9N_}U>dv)CrA2rMt#dbI1e!)22Z$Q*%iwK9`QgzQfQJXr6F2AkqJLpce zXn&Px?7JE8?y>*quMx{0VfuHY_qWJf?-jA59i{Lu&|B9PaYYk}@H?aZG7ch=$@^7* zkGeM!B8TPM>3-Mfzt1s|5nQqE@PBor@4d&jfGZ37&XGx4{})FVlcay&k^L5X>&Rjv zaql~_zo5T3vY33K`;P1{(0xZ1Q|25>e&=)k!hBagI?g&=^sZC?Ec}NJqsO^|#qK)d zPuwqDN2jyg_c?c%drU{qJ}t$&v&S{YhF-$JK?G>%WcvN)yH>F=tRbQ|p}HR-xx0dx zdfYJazlq;0_T)|EO-%lZ4aFwAg(%#)nD630PzpBY);E*PkEdixhA8~fCL8)6FjdK) z0gu>1tPrWYF>|jfRT&#=)7y$FjY8z^hQfD{ssqsBI*NK7EwgmHS#{nb8<|3M?iM=V zk!siBwC_R68|M+*fe<3}t4{y0Ma&+4@T0rs)=ee9*dgYvQ7O;eChVsC@BKLDR3}mW zZY6XR_!M92`IrQfOLS5E*Rk&7G})H(ik4)Z7FlAp$%Y z4&gf2#?j;^r0_j6e%mn^_g0`xVT42e~2LWd0%_zvdF;1&76%6hF32tv=dGj!U z1uoUU;;%KbzUf2&LnwxS1*_N_SUZ^5*jq7tSD%+$?|%^S;1CmL=Hy~!q~j7{VWMMV z61lz-V&Jxr-`6Pf_{Lii%x zdZoL)i++*|5t=&fa-*N3>gCP@d3pHNAOm#Lr_Lg7m#Xz(9Ql|at87Hcm8)v z@Si*TA8W$9;J}}&KMed~;12_T82H1$9|ry~@P~mv4E$l>4+DP~_`|>-2L3c!ufYge={Z>GIXM`auggilzhiMD^ZmVvAHsn0 zKJ~2h7aczvcilR8z|YX(O$-PC20*yZxc3480OC5w_?Mgq0BC@$gR!*)(9#wFdHt+1 zD5GMy>-6Th<_bxLL|OI~aW%-zV}ict{&<7q_VSmvJZ^r~@%Q5f_m_%4h5n>}82H1$ z9|ry~@P~mv4E$l>4+DP~_`|>-2L3Schk-u~{J)9;#M@W^64Fidgau511pq))O(ryd z1lkJ<4U}b!vlFh=$D7i8MMuk2Nz7V{XY;j|=6tiZHcmtQJY)|M{NXWUF#tfqtS<@y zkOZWYRRSyJ)PzW-rIW-?Bok@f2oou!{V6E}wf86Bn|cRo9k!a1=<6%bC$jZADJ=&a z7pWfWw>tNp1R$Ovql(VwWf2_s5U3IgsvhL#TSH^So#=o{Uuy^+Qqys*;DvUL}rA?=4`lbR=jsW0?YvR*h$HnNhp= zC!izu;7A+DiZ@kulAlK{n{*^;+WBXnvVm^`j#IMvXU-V}_qao1<69ICjx z#>je?dOT5Wl|%`3vbEPHG~%aFZzYFws0JrvGib&2P+KG9gm@|Na;`dR;@hXdF0GoZ zA-H|QH*e*41=$Iq5bI%HN<7~G#@%@RB7i{JIIaZ}5Wwy4o<;eoy+hDvrhjIDL?wm@1uB1Q#CKL+EnX#od_o5Ll)IMaO z7NBj&@^Kd;)<%OES%^J;dru5(Byz|)wNe231+*1B;m&Izkxf{~q>@M^K5oRE!sTob zc|{J+dp9AWy9VYkT9+9Xs~h za7ux3s^H@U1XPuqE^Qhl@AX5bvU0-YlbYY7u#DLoD@_$+y~NzrtM0>7+1`o^!%<4#Gz6nx%!45)1j#*6H%w}%lL>bkPU;E?AJ8F+BF#1h*)IhVyMi_Ov zsP^M0U`mpo15%jKwLnIhv>I@EEM%1`z#gA-uZa|{w;0Fa<;p*AlslXpj&U`@7sC2t z^zDl(eNUPt;1!(3LTitPAQ;BOW~318lc{z8PH}Qizn}}TOCKI8urso=eH&5)*=8`` zp2~o#l&9$#hnp<9m0A6^0!0mYp=~A0p6kv&f``RmG&`p&3S1xA1q#Z&mWDQ+e8$QU zdYCmRYx5Uo_^3Kpt2*gWb+llW=!(}qid*e*;K%r3yXT@z9M~6J6s4W)yAYFWe5HLK zLzt|wA*)yYu{qhsS{D>18jm#IH$G*d<0Wc!%;ZV=R!Zbb{^7V)aDh~#YlpjpjKM9N=; z>p{p}tsH%-GWJ_W?06|`VM8Q3<;UnLcV=dbQ(dHnG(Sljt7YptrcYv!i*oOTH}{dKWA=+9*g{ZYWJuh2k-7#a>5t$bF)tT%YE zXknN}yshg~aR3ihYrf2JAi1;`U>8O3G~wXHJT%z47}=uULl5)|GbC{@3l!y+B2*~f z5DjcU3lNj0L9LvJs2$yYo&PnlA$`0mw8lE44re*ay-w$)@TQd*clNAR(%5uPdB1zi z$VV@;e2am|gwU=bi3Ahc2-#RQ@Nj4ZR|M%yV{F)u1EjT!9~IyGxH=6o=bI!9tM4V9 zbj_g>xz2R!1`{swDfWX?J_xn2!x`6(1sn7`%cIC}oA8KLKFZ6G`1-{Mb%Gh{twcVN zq6VA;DyiF|ZA@EJ=2F1GleU)erF@D~9hw9hVXb^lDkhymJIUFHVbQAc(AH!-KEV8w zAjx)Vwy>U^Iw=20(<2uf(23nLxb!{&gdH4nxP_*xYF?fdBUT{!B>#)%AdnKLLoAd% zF)T0&Lw=ZSZHt59{(K>Bkvty(DpM`l82!)rC-3lEYU$}o8c0{qipkSGIh)_p6+1p# zvQ=^Jkc`a9Sh>;&={E<<*3Q65XH(xKGsk_s8o{X6xD&4X*)r4CLE#*tde3<2Ftz&J z-bRK2D)TE^O0lz+q_}32BSXH1giVjkV-(CZqm^v#z3`3d>Q)Jlz#WZ2C|%q+1=V7( zOL<5p{(S34Nr@ks)(@gEk0mIzP1K$3)Az#HKgrY=yXS2rUBJ+Y=+H1-R5Fa~QBCT! z;f*{V=ue75&_o`g?M=eV>fF=Ze+=&v4p)Cx6@aLwjlc>kTCyq1q@mr`ZM7q*a8^Ly z7rz}o$wn8ZUHU<+Y8&|JQlkt+Luh{UZ0GGW=pkwJ@fV_I9S-k7!Cuo$&2Vpl9RZKd zRQCZ-s|f59qfG4gNx(e7C8Y721+6zf4~s=w7U|a_o6;>swO!S`4CNDZwO@EKZpwjQ z@Pb_6ThX|78nr(WG{ROYB;F7^oFX=zE~dK9y4#dXex!BgnaRaZU$J?%%%?&@hbFD_ z%Ej3Yq2$%}j60QKxp?1@dHrs(8ZPvf(sVTU+E_+p@nQTY&2sr@D^;-;ho|sPO(8yoxcfqEqX?w-F68l>x{*l95$+F#fzj1+VJ-K+ktL;m{t$ zn*%I&+651%T{a&pFy@uVK)CaMp}j?{^FkcEfLYv<4xTgo(Wqm$#Om052eiCYmD5DZ z&ijs8rrC14S&PxVisY*Kk%D6meU3**RHOwGs&qZsrpG0M*RMk9!HROcM%3-mu)-(XZb)E($w()#z-L!EMb*e%#1Z&iG(gpF+| zPXJUKk3eY3l_H->hMO+$C1jVgFKG1?m&zkX*b&7{SCJIYlb(0r-{B6Oe9N(5)5M=Uak}sB*b)ZU~ghv z(IG(iUu5B<3fH9T^vKy~ats%hi{$1Kr^pY|L96c7P4Ov5#}w|2zlD{iskUo=IVpM& z5&@Ix^_sV=wO8TrX-WhxY#pk%*a8z;q0z?Y<$dMxBn;Zozj{YZV2o7z&>-DtLB`*fMufc%%(P`up2-<26ztjiYl_%skr?=WwAIm-DJTPl3SZ?3yXxi-;#GI?^qq0Vz>4 z17s=BFD^xg9QS3XB!9=mS(}0@iPiJn9F_P{+q@xoiB?Pdx_epH5dJ=0UgN)10zR@>e3E?b9{{ zu=7O-DJXpk$DfkL>3b_qCwqJZ(UJ*8MzM^gggLS^N`54;Yct-#~H$Opm6;`8YGxoQ}nH}tDm6C{>AWzyOt zc*q%{(5GjR-L*c-SM-qC8rWtpJ}eyPLfs2(;`=O)&pfpP?+S}`2*d-mA)Gz(@Ft?R zt2G~BJg^gwVe2)myY~)kl+hL5HM6v*|CE5I0N*l$uUwYfeSNjeS z`)!3Mh4u&uQ#rhcI;Damwu(b;3wdYGeE#~QH2~Q}43<5R`+2?}n;|>zyo?cv{eTw- zriS0vVZYvMCV^{zOFyle9<$auzW9~f7(b#M^>`otrAN#T%&-+lM;i#CcGV|Kq`IIT zf;N?5q-`97b)<>Z5tBoK^NWxKcbHM5957zsdeFKAo1-weVs;pe$jiL8B7qK@+Se1& zXa+-)2$2@;Eb2y4lmv>Y)31$JA!c467rmo)o3P%2aapVL?BrhZdYJdl$-%C~;;j&o&8+sIuC5Hud||g|)0M~D+^e+JPOja>HqYSdkF2!= zgGe!}hQQ_+Gkdd(J=c=$`tfz|1&_XOo>|5>oW#%Vf*atEtQXbgyN&#ESLSPS$QOmq8~BiXU;z6*+xu=JQSQ+JU~{t_=sVL>ii(V-}H6M-2+xf>cp> zIMCfb4tePxIM{PVzTgVEX~XBfSH@ArgQ?rgVuj+KEw;e1sYH^vCBEZf@jht=o(vh0 zn~>wHx`X_i$*#mR0uKVRmx_9rR7y)Dk54veWKQB*0V(P+L<65F)^;aRpkKp|uzBQ# zo}#0DW&>}U>Y9$o;AA+UuF9WZo{;{aJKq%kvUXhy@=*89D=Ub?a*T7eU=t2h+ju^F zT_5)2dY8%7pe$0{d=*6%?4Gze7XqdRlwH+q2?g_SN?906dm++;hlki%IqQRNO@&Q% z!SKZIOzqvXZ3rpRV5U&ucY9@~&?Y0Necd9wZF3id>w>~;lKJf8M9mK061%TP^D8Kb zef?xC;PJJB%t}etmuBPK6ZAmAKR04Yp&^}d-hxC0@DY`!5%Sq1AU0k}@zaS<{_efl zXBtzKcG?TAhz9f?RcZV09+=C0U0L^`zEC%$(&r{GWIUWFL1Kp=f_aO?8DHW53I-`u z4V*tDLS-;4uBl^929^3*t!}ClMZqHi{2n<)AM5OlG$KK6{1ii(a#N**5Ev=Xup_*I zEX8BvB%cD69?VhC-nAo5&*$&7D^H~kO6|04QqmFHP9^o}rY89F+v6*7?T|%yH4v}_ zE7|Rc_i_q_AM$%n)CxcyESmRZrjxoq=Pt^|TMQqH9t&kO(dBN?7O_MO`NhuVg&e2`KMd?Bt{8q+~=86vNUk!`z}G?0+n9sB%)sDV^{OiS*9!yH7{@mmZ){U%dVb_5R?MpzGt|H7&>z1wlHDwoin!&tU!a z1pS$dTb84Jqm{4~VT0ck=J#;p?w26bGjL)w$3pSqz17UwhJQp&f<52e$)-SwkIoJw zl3+6_my0ke)>r#ck&~DB_0+Q~Vzkg@UHqpJX6b<>II!X;$L}{tsz%|S$N!8RZ3f;J|*8y zv-j+r-|k1;Y=AN`lLUfxzTlPCpSoT%X|6@lc?;IY1ayVOOgT^2PUUS?)o#U^i0_9i zTu0o-kv;+dSXi&KzyNDt1QPnyF)2_WG$5e-t!3@@=)yKWI$x^$+nv9bmT8PRmo~bD zTUb3gZZ0YLI@35=QnR}on^ZU%wOiL+*w_`uz&o<4W#t;GZfYG72->_;5iCFmzHkm8 z0sxSiz_J;Anjg)cZyn8SUCk)h%|rk-s~&!~t{r>w^`p5;&Wi+D79=|DR7aDT0%}$$ znXClJbk}rfKOa!P9H=m6P(q(aKK_8{y+`dCnBfFzgtyO?}e)*?u*m%?G=5O*z`2edwRd!QC4AjE(XI{AQK2_nUv53>yY}6 zXY1or!u*R;p2vY6(a9ttr!Wah^~>vqHMv#|;cYFG!>CPR>D$x7>7(4Vy0WcXIZ`{L zMdOi2Gu)UBX-RrtJW^m~;VGc4ww$%#wNmA?CnLF%QyG~(_IfAiAJDb83#6H<)E#XQ zuNPlD*h$;|@vFy<+50j@lULpkJNe-tbg#!CXGM}dThN0wY zd0vvwsyF$cYcB;lFx7re)zbU6b@2G|M z7#N0IF?1Tz^kwo`N`MlDJc%7H?5U1E970xI&R&U>=N~t!|BzT>?G{ zi2LohH00cJBGqih8UXLB-)vMXOm3E3*_x>%MGb6Y*y6F)mhTS!iL>*b#!5PiqhZVI z$~m()Do1J`!oH-CrLC+9)HTDH#iJkwaWSOy-Fjc6o?NPaY;+0=vs?I+Cm=_x2Z|CR1tz2#D!j>Ky_mvG8YTe#^)P^=aWIVm1W+!q?2PpDdy z!?>rDk1u3$O-du}p_t;`9-r~}ifx7sI7ctJyM|jq=E%Y+ZHXdcB zD^_NV)L~*WNzzaAmMIcvsT0)5a$murA&+jb$#ZTbm|7gO7-y_K@f>_1uX}=w2i-cq z3Pgw{kejSq7cPDurWz?n7QAO!Up7fOsNC)kOZ6%f0n7IE+-wRwcoT0G;tFO) z-D^=T48wu}uwoZAI&#b^nC--lEY|;+K+tdXLkEM^s;5z6fD1eq!>Mln*iy&K(k|_n z41HBF3y`~EyqV0J<~){HJ`eWDtFVWNBZG8ao-{tJXhE7?6wKn9IxDDEEZ>{D>*8Jd%etAphHkuB|@oH-*n(2lBVC9(vdED#>(+ zPWLRJ5*Ngw5`y@2p;3Pe_UJ>x(r>Nf7auUlUg8-s^P41)A=Q=dZCpA!A6hLDt+LA| z#*1MGMjyYYqYw){pTOjse_3HF?t+M)T&}IaG?+S%vc0mabYi&Onw27s-2Ub)D4cg! zv2j0;48?)7!zjwIEmYd9mTo6&9S)IGqO9jjw-v)dq*XUur=Nj_*7SNoq8MageL`!0 zvh=ahxC!Zp)kZZU0?{*yOkC1cD$Ycwrn!BkS6oW_jJcl4!AzQ4A*QX05lbN2!U4Fd z=-qF@_K4l1bn6V*o*T-okqm#pPB+? z{(?uujG%lulY0g%vS13?ZExpbCw;v|ZPVT!z-7_e`l*Z%Q}ihmEkjcw)QY*k5@?3z zgSF{yM+-+$;8+kBO9(v^)9~_Wh64SDZUE=kgiD%|+x$8vZb$D!$mAfnCLfV2pPBka zXsh$GcwRb!mARyeN5ckNa}F3e?TU=1Q5kc0lBQyCI8#`ON-V31H9%9|#x_cZEj~tG zAH2g0*bA=kBxYBc2!ebgIWLGFNJd8Rn9iJ;lFOm{NFZp346wiUsI0G;DPY={^i4cI zI@8<-nmOwDp32#z_uHhSC;IU_M3&tvexDsqgxF3h`}BkkEGDu!mx;D(`bC>Q4ahLH z&4+doE0`V5H80hmcXz>?vI+q*w&HWnTiQ#4-y~r|M7$m)BxS&Go6kv90$D00N-P3< zz4?s;&W$~kK64y%dKg*grOr|DLA{}Ltu%&o_i1DoDsfWT4zh+23WO)N;n2cKWIDmi zUbup8~!V0J%e5xsHP@-#daiW)*n9C+tON1&Rc~%Smt}T>mS- z?vjE;;;Zfhe{&Kz#E3o9Md^CLGSqueKlR4g?6Ad0d{W}dC@;3A&ex~wqAx^0=O+j8 zoSH?vieTcMugR+RL8b$fjsF5|>nv% zxEn^)8#(2^009s{*V&13z&H9 z=*@0}=T0=^)#^QZHrcEYR>9P=P#Zqx%0ZpZzE}04u)l#zd(QQw8PWQoedN2vehh{S zbg_5OM_Va2DOu)11^5`q*9J1I%fVlMa)DlWpWt-{B_+(zU#IJ&lz_?0pGne~AOl^; zDN_$LN%cyYbPfu@dz@t77=x}Gh-#|y`G`(vf%8`+8erGxC=cKT}~!RUv|^lX+J+VF^7FRJIUc*hvsNK$Y+Yr z=`FWwRA)%e9qe-$9`q;_)uzR3ww`gPN>&PI!A9s(sb}Xso%|H9RZ!zfm+0VSyccH+ z!K)XJRQMZjRyZO+;} z6#GxzQqxEQ{VY#pc%R3A9DSYV;(2jMiErqwYZM zTvm6f1&%lib=g>dzUEcF&^HkmAB?!3nf&FV%`$Nk#7C}L zgxtM7h-S1Omi*i>+54-v(JIqg>Qs8ss2T9EUAi#=E!HnONh1p%KTxh! z_o^5o|N2P;7Y{YgQ{>@=pD>_0YAqLy^#qgyCnmqA;4CiV%p5n_9-a<=x&XtMTA>0~ zfhmX`Hq#5mOPMxA{%T|-)*AEyAjfSv=}R4)-(V>*;d=l+7kj~rRf*Fj*fi?8@aC<8 zUFq_9HFaZ`*{g>PxSg7!JS{SkGcbNNwW$PWae-szqRcd*L+Xe$g#Wj~c{cr$J$g#||a$w_zoQDn}38gsA#hiNTz=exy zcJRYD#5Uxrr&WOn$J(nI+2boL5fAJx4Ij&cDxxvtKC3Bddzv=&DpI2-jkw64qgORN zc$m=nL3+khHT^M(vnTp7!3L%JRAUn-odw!^%RaNL=Nyy!yX+9nm_kU44x%7X=c$S& zY%7e`HA56^;uSA2O1_HM2n{Z$Lt+Yk?86qO;A!Kw4Y8k8^q(AT^;FV!psmj0DiAl( z7Wo#b>?Qu9`+@MMN!nFQk}1xx7$rwbLOe)A#V5ua@a4mvHR0|tG(2Mm zdQ!tsw~%b}t<$!DA`IpY>xEnx663d%D%!2xEpv}kPOx>VQ57w18LH3fvxvEZ6NJG| z3M+unT*e<;5YKrZ0!<7G>3LqNpoyl6K&`|$8+L+Lz+oL|6-I439VQiuy$)BndftMp z8m#Ee2SvW!;v+kt@%*FSGpJ1eWHiuc2+ixo^V&hGh6*I&vdI+B-&Henmq^IiscUY2 z!$?vj{IJb5QjZb!HA~n%P54RpWYMrRTCGl~H`_VAj7WulF;G)6Ed=rdCG~z zxs?L3y*5#mq+|(wzmfLQn#I2y)XUS-;RT zxKe2?d;DaKx=Hywz1Q>vfB~a#UP7n(G+YA*+Y?)Ca-f%GG~%2P>nF2>aI@Ly4y5nX zsinVFN8qb6(g_#}_@c3TP&_0ywbf0t%zTBtEJU{5Z(O_?;J&pr1jF_~`6*aT4>zFNJ%Y8>&WmbBO%?!Un`jw`rG}8sB%ohe6 zbBev?3Gr@gmI&03t)mlNf*Ok<|8Nj#;T2^KY=TApTsc$5@sZ*4i-7Q_+>Zk1#+_#} z^HERFrc#S8-!*t!&f1uP#RiT8N-f?lvJ9cGFk5nz)u?FE@Ml(i%1=EYb01v`KS;q&H)QEwZ|;4l-{Y0H_h7?d#(eWX zjsKRi<`y2Dlg#PQy7^3|_o1t7p*E?=Cc*RWK4hlY4mcQQCONBp5_(bE%lJBSB{|lC zx=o==x?WSWRJJS8py0i(0Joe<@fqF`m;6thPkWMwFNh3mJ3J%`%_Bd^usic|O36xC zWUmCdlyVuO`0&xIiQ3T*K;Tc2S@<7#w8ZbfA#b0qf!}1*j}r!M?jqr!RUzcYJEsFD znO#>H6gr2T;V6MJc>HzgQ`r^KVIX}?+>*GU@PMMc()cCHr@~kaX>6+)LQ#_opFBk! z`CMpGYdf3?F8yh-JT3Pli<~sLJ>oBn>WcOgZ=-h%C#9B1!E-b=Uc8nJL-qVDp``D2 zWg6{sNa{X2-Oc|jmZI|=4Y{?}6P%Hel5@@ogSH}rCmnq_V=_&ZxI_`VVr}Un9k^=)>b%#rc`Pr6D!se2|f9-X&6=t5!Sl0V+;$Re8Au!aFETzne2n z1q6BMfq<&}ER4R)ZVCjQ;XDJuYnIQ|XiLM!s=}oK;m&>Q)TOve#(n?B#LBVFS_f zq})=lXaLeyI0b+YnDZGx;5H0m^!!jH6565`;nIu&G8J%MDbwE?WP z!nHFz%Y)7hjmZ=9Z?aCnKspZtE&u@Il~OYRU~`TD6x2KbTL>D`7is52yBL9$RG?P1 zuhZSR?v&1yWA@B?AZ4a;%7$*-eu~eFzPECEcejKhu@W!ubDh;dS9jf;izoCY3qfUr zwI|?#@o%(g2>^&Z(zv?-0dRns$y^2^oX7UprlYNyt*V))9(mfa{dljo+^4>b*OXX| z^-~H@cIZe6LVduVdQ)8@Ed~uO2`vPLiE@xn8Um#uO6CpXV+TU(4FDzDrvVM|0i<|W zF}-qIJPpOx1vX|r=Lan? zWrk@FJ8A{nnrR1hN4_FCgod}IN~(tGYwSL$D&)Ym$2NgSYVIj2!2$o`xy@=GP%-7j zh5SYn%dfUJn+R6>EKZcx#ib#Q}#owtZNV&s)&e&)QlB_KmssY0AFq7Dlh;GkuRPVhCz^b)q3{DRlE8|=TZPo zjln9~$nKn}%npe#$-SGGq< zuA1#U)^I;K$nc~9=wgq=WVCWvmDju>KJc|-e=?i-{q}+ zD1<_NO-EnM4Z4oGmrXaq7nYJB{SdgV+kM*b*87Z9)u;in_|j{tqqK=w&Yf31F3RhW|d`J?28 zOzzY-EKi?fMX2~3`M`a~8tFH7hpGEEckig`$ut6x{4$CjmxTEYLz!c|rS`yQlM!OkS!6 z&%Jn77(OTL^6+ElHr=L9^SGs%!Je4&hbPIXnYpF!3rD7|?A`3b#orbzN1Mn|MoHBK zmy|%Rmwkyt3vhW@Gbf`MDjIzZ!x#Q^IY75krD!(x6H2z!YaMT9+bAa~Hqgp}MFEu}*)km1lIMv5^2`;0Ce`;wbZ+u*0)9?M@DS6da ziCz^2)#-|G#o@8N@|2gg^0fAptaG?I32}D?yUmhaw^b(y@lyqsD~aVHo(BEUZ^i=G z-$0`d=?p#@8+fu-dM4{jdA^t-EY5a<g3?d=X5U1J@mfoh>gdfGr?3Wv7)4k*m^w$YcgyNw*4$~V*)k)dyrF@Af1FvkaL zXdj}n>MO(=qk^{%xe%e~v%yV$em;1(tjBFtFwY{3s3KnlfmoHTB5mh|wA*Cxa3u@IbHZ9TLnZcjP1#j%N|pQpwTVS ziJS|JT;-W#!qsuaXBZUf0%J@tcbEtK7&%X{mp9-T1sFw=srhn=xbWsUgr?rr*G*J+ zJ+ICq8#Le0)HC6H9aLuSiDbt->LD0Lo=r*A!P%Y#yXy~SogvVAYW$KBTp12+n&<4#;QY@G@*kGtLj_WBe`8Z(W&F@~ z{zWu2Ys?PTq5VKFC?c$8dU-#66kE~rTzA2m0!xI;e_r;PzLk1hcqj7X3FC0wl}PS% zm;62UruR`239S1~AbJoCzO1m1OPA_f4W}}{Olw?J74}y?k>3517c&|gXUV|zFumJZ z_}$U7lIDlcdE<*DyF>3zA*>jv@|3dW(e2D&wCs2;>@-q30r$ze_20wn_%TV0-wxZ~pfqPPKfwjl{ zNa?KjDx3l@1`|?gd+eMRS3Wf)2K$k7?Pdw@n~bp#+(Rrk^$V!{N4s7xx3@t z93hkt&y0gNG3f_)eLq0vFN+AdiAHUp@S?DNtd>Z9)s-!H2+b79fdpwkWz|1=$g+s7 z=Lm4FU|y3|0>h2FOz+Y{;n?LJ+khC+03K#5B&lCoP&I#+wAH5MXX);nR!@=v^% zgL;ny(*`YTtm=CGcfM9MuNXY$bUxZRQf3fQ<+0x4Cz_<9aTwD9y&6!RAjGdk%U>e3 z!7|1p1AE9NTMA2Z>X2crMo8O0@BZo2uqmh}+vv6)B6>H=Qq3E@d6`G98%U808lLsRy{2R!zBIcX3N$|2((bsfL1;gNMBtc`9~`L7~ceO(JSh9udrT(pD}Y z4d5R;@;j~vJF8mMu!rSDzf?0+8N?cWcG8=j{HamY-8I`jMPAIY1-+C+NtUi!$=!UPGqz1PuMvpU0TOsKk2{4{h%=R}_0AmL5> z$!9OLQ*@D15|?0T@Dr1tE^=Dc{Nrc;rRLEw6L6XRg%dSq+gh=+OT)B0j9EGelj z2gNN~OnwmRrAzP@t%)y{fCme-oY;YgDIzlWfD!;3CarFr6x3Z`ueYeG>3Xn$`@Hgz z=LI0YH#YiwD{NfI?h7Ujl-E%*L;_-J5uOGg?W~`fRRF>wE*(rJhHKv5v!P|1^F}U} zbYHFp6C7Y26BpSmY0Xg=dqIMJ)hzKUqR=zg1Uw~-#--Jg;$;ap!4G1rsmgMxXAUL~ zQYtEqBcjmH#>%e$RRsS|25bZX4FK>-2Z@3A09?+^#EwR7HG!!B8UTP%M5J+^!bAwC zGw-8$W?vd_SW5If1WFAlwejJZz=Flhu?%2K`7)ly>v21(gEhbh;yOXYz>&;D6vsZ- z%G7jkOolgZdknpW0eA|J<~Aw&Yz@E`iKIu_Yw@KF)_FK4Q^L2%r&?ar7Lec_^wq&v z$jDUhTAOVSkJ7_Vn7I(B^P4gj7k}A0v?*Jk(ovmpuh)EpQ&O>MPP^zvXilA0M054& z@gU8|IC@PLuoXh5XZTA_pNh5Q7oM}~KYNA?lL}e5As@n41U*Ki_CSS$1;LpJgom%s zNiOA+Eb#5(stw%k96dVXX;55i$bOH}ljcmK)`_o0^@omM@LbwqJFJ)srzOPk%$dyQ za2MS_wUI0`7WjE<%nK357caqjyo|tpFhlt4qC82+5h&IFQFrz!X3r-~^XB(^0jw|9}G}I;-J!=Vj zJqEkBF|Y1JFznYMh`O^J@_r5@%R=Iy=t;v?HqDgVn~;wzJ0O3s(;4oAGMh zztEo;!|q*-ja#eL8G$qf1Rbtb7MbNQR|`s#Aq1r<*FhtD!>G}mHO_(bmcOjA*465Tl3ZL1<01_5IS)wR)nuQ<$%i^iDATzYrJ>9OyUM8TW(UB-u z?5`l!>H>h{Sj{LW+zD+N<8KCLYtgdhnF0-2;F?92XbG?8ULNwR!Dkpsp0OHteloGm z=6%2-I%!6oDVZ3g@6As@p+q@@yM=D(;qy_cBB@#QM20e`#}yXwVMgv?!ROMJ$6bR> z9V+oJELlepgL?U!H!~cctUf0&qFhHJZ%P0;Z0qskCvxmtZ^Wx_F0L>Zeoq!ZOB5&NuCD8s&p+ouk*dav|C-G8zq0`>m>E zQ6PG3U#f(jtoA^pB)|^_P)rC5@D#ZIGO87TnZZ>Ka7hLbUOR@Po44E!K#*m~IJ)Y+ zOxP923V}=oJa4H#NL4?7ADDG6X_!)~UiADCYKbTm0p*njZV%Mo&*TP(gwcvY!9*O4{sWSi&A$A`5#I29xqJQ6^D-#(tZRa=p+!n! z{)#4nF|z)AjSV^k2BlILn{5e+R-wDLm=YuL(?{eK4|tb44&b2GN9&PZGd;yiU%soUJpEO=nmJ=7)0-tTH6;_3ja!or z{S#Y9&V8SayCcf%Dx3#^-*!u^s-EpeCT%CGJ*45^HSB}XYy+{e1&s$M^a0pi|EPwl zqmUKQB))yx>{5H&G=(=-Sn}K%kIY5A#%fB3M>W}0Q)LW0Q$&{ZN;^;vg-Fp?(OcyI z0ark%zZSj%6cTVa@Hq|~zySdcoWqCt7@rLPBmI*V8Il5N7_ua>lW55di$@ca3GNh< zZc}9R$v$dRm5szKF2&`C)f|xAT}H8(lV)vDVEZkqoz|L z(ivRGV%%7EcI-?*#IPB&C9#{u%_mL$_(zdS^ZrE>oh;q(vW|m)eeak2h>4ccGUPI| zs`!k#$tt}3%$%8kOxA{DjqXitm^8zP+hPgAYTmiNa?Iq(Q)65kk9WZ5CQW#3sqnhyu-025`t}*CP zyYZVk9kK(FYaX(yRjse6E)$F2vfY2}GAznjX!qRz)DRZlx-GCAQ^qr`8D6@sl?DEI z%BN24x8ice67z*w6}!~$F(Ze7OJd=@U=TGz#iC7d0tCxYX}|@c@;XZ%1VUzD_FMUqWC5Rg4HL(5{lz# z@cOk?8RN&lFP~)a%273(-baQWyS6$Rc1s-RiS_8NTOG=&wwviFt6}1CFvU4Cq|n1# z=4DPEnUj{v()#3a+^mT4 zeZmcLn7d}Yz(vt7LhMrmmxFHS?3hTTfn++U4 zBf*9TF%4=%hto~p#TRQV;d`IO9EK1L3m z{J<0+B}r!*FCKnw051q(4=T&yq084fLbX5#al*=aj15sPO*1M%|Xvor8?;swt$avlw^{#mX1Yq6M2*6@Dt# z=h51|W}clgxU?92u_KeiMArOK;F#?>waDM<9;u#`C|!FH+`f-84_z)*aRi-O>gQ_y zFRYjXEP`*I%?QtmdfKpQpN^{n&N~*|ZDGUp5@0m7cx|6sYB|&N?=*%1X<*4N?b0FX zRCNNw^oI6y^uQouha~he?O)V~8KLB7y9$N?A$JWgP9SC}XoOi;O}U%Y!l_o@29i&Q z6}XwOip+{^hxAu?-`~P}&5-u~GsX<_U4=^eJsOePqX!bUNjFCKUf+;s8;#ICyunE; za9e{d8fwPBf8G0|Lp0D9vFoSP6QDqkJd?ln2J{Ns2>SgfYF6!Sfs4n8kjjQ?-e?&# zJ#1P}N|Pn)nt>q+Pn`gOsO9*T?2!HPAgJqvj2S}|g2?Mosc&m@l{A)o-`Y)lHeoS0 ziZrArO(K^cS?lt$kf*)rYm0ToAq+or=z7axIwvDIY@ja9#I2hT(i^#k<)NgH?!e^J zkgMb8HMi%Io`W8souPy(2hQ7Co5r|FkA!YT+5aUmvzBY*eiK@A5qJYeJ8@acW{&R~ zmp|>%!EOiR9-|?S1_u)uFASLNQ{ig!y5IL2&+1|L%|XwUP(k3hJE-0v5$F44VP!(aAVECl4(O-aMO1M@Q<0kGD&`YjPFN+YRcak zJ*+6+{b6PL&nUI!*Mqjena*M_G32<74x5IN3YdLm za9tIT;Bi#BbCqFTN4=p!Vn<}y3=Gs^?H30>lwvcXNM6@xJEbJKsj0o?EMx>I9ilif z%IFykN<2*nHPk>L+Z}Prmpl22a$=17I%AUkA0BQHlE}t+*f+VekYDNBe#rU+d4lHv zkhhcV?i;v*DHGVxJv(vy0R#)`@v0|PXPN-6MS~!?tgMaT1+gTUu!U_yV}tL#FArw0 z_3aPVw5s|(=x}aIRjC$rD3!#E%^20u0bqV5Y7Nxl&H1xby~HvdI_a@?SebKtifvcP zerl5SjqZrJgFreo#tiJxp153Hr~~3V=FFImkIcXGJFM;xIy~_ayx_>jKJ`~Na|Uw| z2o(dd6ZSC|!oAib1hIi$k8a_5+F-)TcUUk66^=AgIZkQ1H9rSg?aASYGkbP)vNo?L z2L=75+t{2))Zj)Vy(l4cgGk7XVY`#x1^jq~StjN>pVZ~hGK(*B@Bu&b1EC2CtDAo= z-YV4~%_25?IHq-4h`aUpswqeOiG#hXbniaaxjDDjk-;betlThW1v3(E-n?Q3n79=N zfL95tbmERnp?3Rf&CN%D9F#{iauErzym}VC&agD_(1~g!i!#G+F@6PGt8~NWI;$m< zz2PxK$nF<@Rp}hq*1}+@@4uwTk|0D^NJY^TFci^xn!}_(qbZy9priKar5njuBt!rJ zy8+Dz2z|m(NITDC8}Z%a`P7_`yk$b7JYS@2tRP(1PY#pAdqa7{pHL9wT;2Jv9)Z!} z!2Ii@T7rN-!PGiM^u@2x{Z|jh! ziV9DJ{H~$9>cOQHc;AURg_rym0sjTF9UibtXVcUgButGt)K267*GoRtm@!YZm9>Kv z5GqRQGL}vR)(h(=<&2U(5HSTf9ri?sfeydHjs)>w7e7ZNy_CynV3bUv8AJep%>gw2 z2zF2@zj+AS^`J{ipyEFmkAlC25cNU-L&gIa000mN007`S000000002WmZD!~z9bmK zgt%9jm_FZ0XteP+xEQ*`GK9lHI_(U>Z=ith9S4+_sBIWC42Xbxg! zWw|8$sIBFgZlSb}dV?i8XUvdW#buw1Xzr~F8ll>5HuMyjSTnqSZnE!$_Bq%Xd zz2Q`-gCeAL-V}sBm+g(Et)Uc`!($t5=~6h2B;q7_-%^ZCR=CYq`-x70 z*^}|ojXCs*U{B_ap#PS+>_+mxM2mjyccCV!8d85?-to<+wft*G(Z5|}o(ar#2sNgY zyvAT&HQ1x*MPLL<10xRlmT$$Rfl57W0k+4Uk%RdSW$(<8U^2&)!h(f=r=9i%>|G*n z9qqr5m7l${b9AKJLbq|J>oI2fbJgp9y$ zM`A~qC1{Ib{u@mUfd>F1!^4kf1{fV0OwNI7)rI9g__EmF`(SH@Gm3tdte}8N*5S#g z7^{QP=Mlic&z53D@xforIEkI8B8!W@n9UDsO4GVw#IzSl<45%(U5Bt&p5?^Yw}}wA zDRZ{!QF=@X8%zn&=QQis(-Hb@<+E;hnZcueXCo5yN zRq8)V-X@c~R$(^lDmQ*k)P#Mh08zpI44TO6W|Tjc@bL}1s*T~i?bS$oK%BEdxb^}> zKcfsk;4xIduS>~>*3Ff~FszPklu|#CND_)o6*>E&Hfb4=sVcH$WxJicKH*o)1MJoA z(jt9PMJ$(`Hk_(=Nc9jg$Trft>{j-4EJ)_ik97D3kOnI8VI4y4ikSdn7$Ud7Rf>ri ztfJR|N44KTD~3u+3H{zlCKhoNsbZe+--p|Yo(weMFeRP*cUBV%SXrbkLo&Lw*w_V+ zM|6 zpxuWN%iqurQM1Qf-7lR^1gpyG8ffY2b$#A~ub8($t7*WcW}+&|mvA@xLDjKZXt^sl zO?hR!6G>z4*lc3{dQoDXbqpkOUaOtQ47{UI~S3-4QW(eujpBg7*qqdK~=t@fAOht7nA_B697m-833H1 z3IG6L0NQv4DgYNK04UZp000mW0ssI2G$UX&004b(yW91;rQ>zH7N^zHVfxsKy_0eZ9T+YPU47EM+j3*hUeEW{QO|0|Wt~K@eJc z<*_y(Bmlr4YE=-3AQpcNm;eC)8JV!60{~F~rzVZE*(Jp!5=GBQSn){`H0s3KPZL{8 z0e9UTqmWI#_d;%M+wN{w2Hb4-J6$%m)V?_!Ms00+a!T9UDSmli*A}gOe6%XAR=!Tb z9YsMoGP%P6D3D0p9I|PWKsW#ZW(3S=3;^d1`JQg?+wNVvnJu=q5M8&L?q0jw?RVF% zEn5`Ux9@S(Q8JK#Ig&^SVkt2)QGf^t5{*I;0VId{5#a~;AL2of=?8#4 zeSelr1Oq$&B?}V;j}danNe@Vc0rk&7EQR`n6l9JI`ox8fISPg_dP<~#DoSBwVyQWw zh9;{^LWh(WDNSsU|bTF+8NNvq5}^elRTwTX`PMHVTdHk zdz|d+X;g&Fb~GtDRn;miNLgRlmAE*5`urz(`$C&vChH}UjgkvtktxWPkI= zXa4!G@gkR|7iXK!iEfXXm7x%x)nd!-_4jkvnMQo(1m1hPlqyURcBTQbrXb$Rm*E_RSbHve$x8Hc1dK64AxdG z5+~@w#BdUzMuC+buoF7^+v&dqk+@oEGGFS{_ya?KpY(kCH6`#W$HYBGPE@+sDsDO& zB?vM#Kun^1bak(%vxVo39TCzl(=&NPq_7#!)HKG<>e!b$TTf1qOPY)kyIQtkiC3Il zsMHhES@H)uryGnO;OapY<8F0hW2n%GwVu;Xk}Qg28ppLZQj8BOQ(E0d$r zR&*WvCS`{);FiUY-3NtnY8%hTGdc98DXLD(F}*CC^wy#6ElB~#s07RuolH^bICR7SrQk_<$^js*X;hw0m z&3toUHC)Kg+6y+Q>5r@v6LK2Oib}F3nDsfYgNSlhP7ECJRclRMnORl>oAe z)tAnxxuMiycRCV~WHiI7P(Cfj{SmYk7sDeC=eDY{|H;?Bg(N5|?t<+cW6u}Hd1t!00z zZ|oQ=aF)3g#&;za=IJjT{B%vzg4dqN#+TyhtvO=i4VAwy&y}2s8{(yCk`}?ROMW0P z@cH?ZBhfd~)Fc~zrBAA#8(Yl%wXSTq?IWVfU9OQ1ZUHoHGSY73+>#y;pPYj)XnPJD zjrWQ)Kj5|zCh!!hAprcSe>OY;qG`}AI@y{)X%&#I7=jIPCuW3zV6|g>{}cLXgLI;$ z_HR0YHCNNbW*tlPiPll*RBAM41gsyZTPPqq;3P}^08SfWAq*Afoea(wGBem=@P`S^ z&brVMB2*KI_X7)yZ)DH*ogzdk;Ie>*o209q)!y+!@ zl5Z%1LycpA9zRVL9YL)tb|(ZI_Op>J(o6Yg^)3b8_5C}%tKAR&0pdf-VqO)XcO>oX zsetukIqivRnSoJMvKjUV1T3wsW62jI9og_$-zWqeF0;l*YT;JT02sTRer3}#TzSWI zK|#aBrxH3RVgQf8;h(^_L}fRM=VlpN$HihLUf-}XIOp>#?sLw7$vm*Nq~9O&0id1g4gLCHu{J-cz4vZxjxXaxs2Uu`j6TTT#(ypN;VDmG7RAq~vT9 zdk*4?>sakGUR}Y~tmHFDhQ(h*s{$L}j?g=2nk0=PbYUC#1wZlee-q3qYwOBBC~=qs zRhk~N_&7w7u#<$gIwK;twpvAh`|+Qg^0Wu9hTTb&Y>*D8^yml^FcYH1yDc&JzGWF@E?1g_>i?As1M(v}E{BwK)NZu^v&GP}axG4~>mgZ|#qXOY!DLf>o}y%TI*mvj zs;;gRlp(SYGllv|ZTNC_vr!2*Msvoy zomLUsPRh0B*t?HF)3oEs!@}L@a=Hf0($2?Qml?oi&X(y!?c^m2#5@lkjGLKP8vl>+ ziGyA=vs>Ed`{MhqXWR5$(2`k@t(>Zy@`6&1aP4~6kY`DS?Wk`etBTCco!%!+(@L_2 z;dA$~u$y)vvlrgmycfH2n-+p*9Pb$o@oK6-FI^rxt*)(ySZ|Tk3YY3k6Ipw*tzicf z1NJsxDr_~`{_j`13boWQCqf|wum>_|OT&+#=haCj?hX-Jb>n+w;+RSyG$+LqV6lXc zW77o3+rMCNeiFIOvDcK>LTB$~+^I4L8`9>-{O}rpn%L{%XZZ30y8uze6D)jEH;}8) zNWS?ZaR3KU0WG@Xbl4NzAAL{6V~0b6kV84-Lk^hl$Xd(z=N5>CFqc8Lt@;61X20zA z24)yh<=Z!9z_bjuZ&9Txm+IA*`kw*=K2UvtxBWL>*wvAE-^>B$#}Q(}y!;xJ6an>zjQ9w6Kc?kx1%acIvUYc%Hi`g-Aw_Zh@$*oG#Si#nM9Z!5 z)u`(o1`{|D)DL-?02R?htoVb!op^hB`9bWH0F48Rn)0xp6#>LYFx9AlaayNX`2yTr zCd+3^MZo#-<97o14=dA(D%e~TInzfFZz4RAgc{Y$6UU3RO;{|nA_DjiE?LQjP_)34 zI!)gs*N=Q8ak?8his_vWgBuMUD%pU=Rh~^PoSi?}?(%z%3Fw`gNZ0p&sw$o5ojzhF zl-q`;YlvyAtK>hUfs`wXMzm>luSyVC5=nJkQuYy9&w~*IJIz_|D1v!%3NtVAy1Ol=q6ZJGg0@pup$^2y>3pxN!&%HM!S@Av^%pyuXkW)HvvT4vRzFm2T4iPT{07haIG2e)}F`r z^!q&hKXsUw)GLc)LS8|!zRn$o2(yv1n65m3v|O~zemXsWBR3N~Ao=r+3;+*GO!a4) z-n-mx$Zpl~Yhj15K1@d=RlRN(6i5^exSxq@zVdWTr1ZRUVI+BHBQ@73 zwl*MNp~vX3X(g1bTw=0!3@#{X2A;I#tueri0V3m?=$@LJVLykmZ?*<~ z5^!i8Hig}EakkB{3E6;B93F9EA~v5!-*(wkKM+3PLiJ6yJU`c=YvF9;{pP||W~5A} zX4j&d@O;YmJ2&5^UP5(omeC%%fw#_y=G5*K=ZF&B&w1ftdr z-Eg1%j{uvT`4M5;v-XPP2fagdagJ`0PB91Jo*}~;SiAB!#C`z9J24;b%ZJ>2ju(mQ zS$Kyi1@Zcan&B^QWLGIBGJk){k!oxgh>2AWmHR*=P!a3Ss0lFdjy^ljI?ZVB7e>E1 zQCXh#c9V?g2V~H$-W?eKfLbcocnWQL(2g}A^l5_YkaFQUZP4j#=p;*#xxF7qi}Yc3 z3kHet;94zG7Aj^<;v-RK88Ntcw?Bl20*-?qwjnxpypnTU zZw<-<*Rv^%GzkQ%p8MiSN?7x#9mD?7U%QWV>&!*?AQ9J(=@*SLkKG{=2n`tF-ClBK zgBsGXoELbF4$8wUfGgo7SfF0|qsZ}-7d&4Ws~?f%Tub>-qz})}K;x#O(oW6whaU~K^UOE@Q#fs;?xy=WHR2*%j zW?p8kN*7Ai>|(0hd)5wi%N4#UrUPrOmbb2Wtyv%MYc;%41?1CmzHj4%hLFjKW231V zT}Vucl82SYEhetcW319nkYGDyjM;kTrf-=wU-x0mlQUxio-rAWMvRz#9#j2{>hMhQ zV)b`S+cQ^-XM!~jwCHRQ-J}gk#;b7Ce$S-tEMvvnRq3FZ?OwbaFF%t)I^6-MJb#Mu z-Gw`reLcy9pH26Y^-e7WrL%x+>ADH1rFwAZ73c>ltiNmacUCay7>M+ShiD{ikwSqA z*x6FjQWX;O2v=T+_Cf{|8tH~lvu#o_Sp%Ih8-2idj8x0kW2X?>9@1}*lbnks9()m+ zXQ2ft8sAb~luEe9O9*Am_#kT?0{SA63uH!)GWI0{=AsMXPv+Q0XT&}l0B&TOjkE@f z>3teI+f1FTF6mMsCp)fa#9tHP)9KBb(Ef} zg`!k3>U5)+nNmDzo83I>(BJl>fbH^8C6<2pq6R{V4uz9=DXf8|Iz_^Yn7>NhH9Ne~2#g!wX(}&&ShDMNSzj+})qfoNb2E8G`#eHKbXMdjl4;!sh&F!e`Kf{{Jyy-FiT6bTr4qb^Xb zLBZXksuZ;D2D?;~Tu_Q=YzaZpl68=5T1C5=aiGuI6=hM-fn4*FXh$q)poU>w?%u0I zS+R#`reTdEZneqmlUDLMlhEg7?*J#FN;@7R+IgR4)DWR-#~eTSc|=%~ZY@X9cS(*D zj+HrpUGLxsy(_Ffc~8_3*#%W#%ZZX}~lBb`HJ^yn;DC$XOq-8k6Y#<4sXHr1xv=5J)$A~^-?%3iH{Ba+T`4bts z!`#NiYg#h#x$m-Ytoeta{~=G$xBTSm<<#Nxi`?KqPjcKB7Y~#VftkN~FyR!~oSc`! z@WNhP87EWxuHT;FulUV*A@luX|7FV!`S6c732SfcH@x>RWVw8k7{~Q{r~PE>xN>3t zi-xcLgMReh?;QQ(8J9fzCtv#mv;Oh&%YI{|94;}*({DpI_ z!InWtqTkOwinlQ4kKB9bWBlg#r+#qbW_*wXFy`N!dAgzCXFp5Yl>4VY*)aci-0IIf zN*#U|3;jCw_C8-nxC(!i+vvCyKjhl<_!|qqzJmO44@Au8-)lS=STJV1_ES>T6Pf3O za^~;27huAv*8LR|d6jX%XCHxz4E_zQ|MJ4$U$F3t0DgmC{p{aE?=|xfK2Y-S|2XYe z+3$f*>oL4<{%w|L^TVJgFy2mF;}uPw`_G=&0}eX(UJvu1)_wi~^ZF=pMP}I)A6e+h zCGG?>bUE9fa%g{uFPvkT!h9&Zlt4ab#F=5x%PcW+1hI_d#l#A+S%ml*2Rn4Q*C66i<@s`M-~w; zUeb;g6Fztn4`7A>4DbdNK!AQB0HFW?AreHID*)>~d;Ryi>-~P#EZfVLle^YtyRlbF zH?o^G6Ag0>5D~;P_#l2n{4n*=0*D9ukL2N$a0edlqkS3QL#1ts&G??TnpxuPH8dX9 zcrZ8~drDem0s?3sY-qcy7bNzI^bQ=c&hECn%?|NOT6L<4w{>vL-S%hmUAElq1-Fds z6>vryb=&yjX+QYrt7?HkmMm?{!>%`CJ|k9DcAPJ`!tSv6I&MVn0H>@|D4Uv#JY z8*`8KF>z)G&fphm_nKT+2@kkR(=|dX?lqu%M22s$(9Vs1RmhL$pyu@XKp*_Ujicm+ z-nh~uopLuZ@(g~b1RE1J8ybk48hJMSYzRLlx4iNY_%#r0NZ7y55H~gQZ1~s^{YW># z@(}nn5Nu4?2#XnRYvkDQupv8=>ydWMH)Nz8&DBXnDJLVSoF`Cd5vLFojG(`NAt*sj zixP6iIEA2y1cf0e3PDi_z>_SJ@5-4QaaKv#$Q>f~`A32gG)KroPSS{$XpBxFC?dp` ze~eBcQ5^v?qeR0|QGObNnjPJIvmataG3&IP(v6fXE8jy#mPAbw5|PA3fk!J5QJU!_ zWU2FH3XS3vf+7$Ug`h(OO%x&krZeHSye2+Pk9nfm5-~Dcl_e`98M#PS*^@mIKO&6C zITA3U)|oT&60`Z_@e%!PN$xhT9FdjJY!QrXlcAa0Gdyyiwl3Z+JIM8?BAmhVJ~rQx1Ux z;NjKAwUDl4rQkWwJgpRdKXPdhxrsG9uJvM=>b;v#Hj9&{+aBPNi+1)+-!7tTc{xTt zQ~z(W>r@qQL9{ir9^LVbfIEf0#-Y8%E_s3%IpPiug|%)s7xJ%{zCricCl7hZ8O%Sw zJHIiT@yR}T(wVCSHtIdw#9qxD#yqa)v54(1qQ>|IS6s1p(K~8n_-*PWRR@+S*ryOP{mGNy#tyW;l-o$J8stskU@W4Nu->B|dqqi@-JG=2~UAxU+ zX!>(6gI*iog6U=pJGs~Kd-|T0#Icv~{rj^jyMFZ<@BWzDn&O%}>Dk)}wcz3QuWr$& z@{5MF1>br^0`nSvhm6A0qrf4CQ+xS;`45K39+7%7|2EMP4hydxhoK%)NP^QTq4%9n z28;gc*~H#VCoyQ_51-h-am9jwtQ_l@Yyi>eI-liLIbD2shD2xt+OhdwAiLza3UMY0 z*Tilf9y7Mp!I9hS^zq0ScBP3{jnRs?i0-uc>k#C@r5B%f6FHC(!Htn$?@2`JKR}+l zZH>mUjkmRz%6t&LoE$THSupAi-Y=o#8hf}^kqM#k)f(&STMm95ssznhPseCI~sma(`Ob_4qeJD8FLc%?Th)~&F63%Zyr z(j-DI8|8jn>XkkXBUBUcI&O>k(lJOM^njOkUje_+JFPUGerC!JwXF}8O|ISQ#B&mz z$GQyLI`p{^s@HWI{XDNGw4ScaJ5f6*i{3Qq9nf&kp~@1M+k>tghk8(e6qh2bD&~L| z^qsHVqzNxhsV`^*sK{CYQZnqsWdn24IvfUdK^LIHd8c&LgRp3PN9yQ|kPq{@oG#PP zeVJT4gQJI)>N*vC+vb2yV@_Ij8xo6pTJty@xd=T;Bp;OSN`_A}hwVh7q25q$9LQwU zW?G*6C5tcNw9-6ulZj|N7I#P(p-=)`a)RaN(xED#A!&`(jsSOOFht^fC5;5}?Npsj z=PU23F8YLqvml=4Zf z^H2T`oNY6Tm{QLs`9WjnK>MlQ^@hxtlB;*3=LDswuPR_-u_By}*PS~9I|wfaSN?6+ zEPVH~X$$A^1O6#JL}zpOBklhTOX4s?I}_^NF$eqebdu40QJV~$@WG3=RX&U#evmsm zeo#NOF00dESloaf4MjppeWFl{nSt_C;wiJ8>lA}vrcq~h-f9{m;_Y{nq>V>`n67y{ z(;Zf$Cv<7hbtm&3VbjE6-)ZrcIUX!ubb2Hk8ozh28f4S}y;;m2#pstnc2IiK>KscM zrKJ9vOlykS(C6beOPq~shok+G;-zP+X36W;-QA8pN?#$ad|ytE-;9YTc?`%4KOPUD;yn z-GN{R>!JabKV{P2(4(fqgO@W)u&KD_=tGwE@dLN-n-JVb)c_<#l0s~j=pyRg6Er$- zLqxf~Ysq8>wX<|Hxsl@`o*aNcnH?Ha$xdjvoH_?sGS^?aq%B z`W_@$oyav-T|rs`QQ`Jsv(-wNWQ9Sc_J^37oi%?NC?-f0&nrl;Q1?e^^DbNXOp0hdEs9?45`8l-X0%C{5Zs zR~RQI?kvPrxjs@${Im;g>7is{19b*U8^YlN=8Gr_B9GSe$}ePshf`!b zzR2vGtM;~KG2vm4I{<`*pqKD-;oaU}*L;ep1$*~PwhK^E+BvMV*d@-v?pRZVGDu`) zA)W`DVj%Ggh3?!>Wz8r+wYevrY86_zZ&%Y-?`$=2M}}g(%qRBI?ryAZu^+1IUM=S{ zTW-&gdb3o7V+7-dgj}L~?j~9tF#B zoQ7XW5ceX-kdFPEYK&7UK{ZO<G?pQnp}U35=tM>5{AlucddT?fAp$^GACf)h0#wuT6DwPjxU2%4}E| zYFbcfiv46?9cTRvt8L%)&WXfRI@zU=vSrUZ5d}l|B*F-o7$TgIN$rwbY3)gDX>6%( zId6i>hy{snj8+q2VvgeD#XrbodxYE&JxrF^b*C|ASCp++dx-gLBNr}8K`tZAr^DAT z?Dx&1iD`0A>naSa>X>!ewfN@I%C;Wx>@+$n2Z7d7Qia{jDtJf+L4nM3+Yxp?@PljdGrKmg>ebBZ208BGAPsx02-;$J)2 z#Xe(R0Qyl?{VM3`0JX<5SQI>8w1OtNW0?ew*txHC{qjbIG&iu-WLfn##0hT9s*MnZ;0=P}V@8y658@#^ zm$y2kkU}d?^x%`DP#lUX7tkE7_?SVRau~A*Y9H+VfR>?qj>&N3b1N{I?W1j9*oJco z??C3UCw2fU;VQLFrlwkh(9;nR^JUfn8#RDV2CgtG4B*%MtlMIs3}cRhv%otBurZ-j z3m;i{nFB9mxtdUccP!SnT~HX>0m$`TA%N+QEP#et>x~~s#uoW>7Q$E70)+8IO;95> zRjh}*wtQdEiO2YbxJ{rRIu?uZbD+=s1bU~dBwb(qpbm%O#bpy*oU&e7V3xRkMeGHy zm88);b3eFqY(L{MqN=p?>tTbl=8uA7t^=!xigp7LH#s?@H@6L_G!oa(a;MTo@2)pi zB9r_A?cu7&@YgNU_v{|MhN}lk)r$sAVMO_(F|?Ke^-Qox$SU2@#B&6lqI1!`09z8= ze=-9JdqQCC3)?3ym-W(WCpjMcxB)^Iu1^o%5)gjE@Rk)`o>@{yHwyh2D*&62yC!M= zWf39ZS3hgMKLamW=(I&=@jV zseC>1tQlN&#R1i-u@BIjqpFZPIcK?s)&na@N*HI}a)N`nEt6qLl*zE#{duV)28Tre z0Jrgbul52z#l;14q%B!^k5YnBs=P)8fo1ZDpbc{>^&7W~5NC|3g}4C5UULPip&<0j z$lA{lrvXybB6Y8*s#cL z!XKwPEFaV2J@9sr2r(pTJqY8-Euuj}ifJ?;!En&3{$QEWN_*Cn8KF7y0LH6#SQW5z z>Ca|Sg%PxDhJj+AQph>rLyaci-!tw1?7NZ6<^2;NkD7`rQK-oP32wXiNh@y4<_73F zkFf@oJ|GEuMfG}&NKQ=t-%rfUGi`Pc5@!c5LvU?U#Y z8JL>w%Yx}q9(X+QZInZ|uoM)p3Rr-n2B=Xv6>~v{3|L{58O;Z^tz*C4@(IgCg{^_Q zeb_9Q!_(0EHZa)W11+P;Tab@lxnQ;i)mhG%q}QYQ4Cc|42JAkzc7uc-q?0vR_}F7F zr^#C)n{79+?!fMH7x-|1UP&%B-|qFe!k^ZBQ`(aD13|;|t>9rz&WPJEU?H$y95YY5 z^f{lg-35Y2AcCL=QS0l6^Oy70`YD6II{7E75Nbz%Y_@^gHpce;Q8#AC6UWRqS z^Bp=&jkOAfAbz+q&yD|{rQ_NLJ70u2YVr*91C84T;BE)r^Vmy|lP(5$8UAjeUe67D zzOu%H1CJTW4(XZmPP7#WUke6VZ{G4C!DG;NG2CzBKyT{uMwJrP(ETddR7@yyMo$|x z`$_}&mLMi;pHMT(>l{)}{Xo}9sA2_{gZ=tZ6NoTnK1%7w2C_4jn9Yk-@D4I#0B9BD zbqXq~gJq*_z%tuT4CM378#zW0A-86k9!TbnKt8Pz^=1D{B%pv;_8Hlm5qU`sH*x$J z{cQ>P{mM2W(l?THeQI|g04`*`6}%EBaPd*2cl01mB`Q-JsG>Jm8JQNA8|P*q&7WdB z*9eX8(nmcMWN_~ynKpYvnNi|tP=5wgV|tN_lwiT8^%yCbmEoIAWy7-t#|&+?3|?96 z)rG-g11#4uvkoJM=PqMA^$2Ffdp_s}5E%)xrK%r*j~dy%5*yOBG$#b9TP5)IXb^w% zd4Z}t03KExS@uK83W;ZmNj2kEEpUE}3!u{8IjXR4tFZ1qrl=HuPnGF6+%ECsbOh$@ zFS{X_e3`Fc4%}ZdhDcbdJ=)}OXXe~|HK)|Y(LIu@^98Rwjq zEO&ww2X`QqG>k;k&u3J)q`q%4PYLG;8G@dkywL_Egjyn%EWuGjQtGglX3ouX38{u+ z<*FC>=RzLkm44PPJnHo6fxk%lTucuE`TsOyZ^-+B`=9y1pn)gF7v&Vqz@Hh3`=bbE z06`2n~(ndGFHE-`TDsJm&c%*4wdHl%Cv_~m$IrCAxhA) zVkxpADbeLZP?0v9q;+hF3bnaVC?FdmVl5(;EgO__ZZ2XoX<`$qd}fb{8_7$bHMUqNsY+)BDW8TYRLzA_6~+m5HlYeq zW+$3Zuo6T;RMrggd!s>+?-J;D?h9Ch-qKg z;i^(o#GR(D>&Bp3R4B?nt!}BPSE>FlGd5^Fu1#NdsQFu9B+CYK?^G)C_eUB44`nNLh+2AIGkpV?(RF`Yp%u`@UnHu1!N zhLkekBqjbAjw2Yz5}24+DI*Hf?+9-nQDB&98_H6`Z^>=oiL(TrCiHeq=8?OH|1uC~ z^%x`5do3pt1k%{jb~`~yJ5lSo1iiG#+SVrd(jaWRo9jyi!L+}&pH7gc0q}Mcq?+R! zZv=Uo;9F29h_udIzbDAF)!e@)2sGNbp-+%$zqx=-5UM@6^Gy(`Y0MQ}f{~gC-NGj% zwUD}qPl0M6c}a;SYUJ(^O@!dd@I0ZLa73X$ zY4C(&DjcD?&|@C=`=KNtl#MqNF4e#U)WFCW(?UDU?J> zNhFF&qESo|C1O%2iIb8^6qH1wm?TQYq)`$kC6XvSp_{lw!J+x7FXD;b#1m6Q=ab&& z6TgHfCK8Pg4uww%$G?9s{3|~Lru*1^5}OeB-Vn%y1~QUxH2`-9002|tSVLnP5+DWx zP4+|@8uV`1J&>N8e`9wxu-MRy?(!CJ--aDz$GF=~0`8AU+E*(XpV1#mY*w+*Nb$B- zkv=R+@moB3EG%pKY1gmTlFr+2TfdE#uUDh#l`12%swy)XA~?9Bqm`yHsJK>KhN`ND zFs$<%<9-|n2{=X=bZhg?ki!}U1V6YTtQMyU(WDeL6g5&^X=%Z7uBRPPRo`86-%047 zDUycoRo_7DliD=kuBv0G?_OH+&ik93l~WlA&wKCL#c}8J-Fm~!c?tZ)=-HUSpIK*( z009&g0RR9I4Mzb%lw*j(!QL3DjQOf6tGr38*%$8b-$C+G*9DU1&ind7r#V1tuIsFN zBkl7EUH%d?)qHbu*@yc7zed%``ERx7;KMmS21SX(*O1|^U98zy(#r?cNXe5S{srFe z-UILhvR+$=yb=MVJsU_O8?@8BfInXNxYzjwuk+^1mhf)EX4h(HlI5gNUI?S8@8Gw(3WE>eiT8VJ=)DL$|0o zijEGvk*u&AHUf9%j5r0JxNQVh&<`IG5ksd_$dQw~_Q95qSdG&~=W${iKjBxbSg=>3 z^{kKGdj!r)S8@6vy_>E-rfVdwh^L=>dt%gMg^@8@QDBU2tiU&@?on4c)atnf9jPDO z-Ps?buLj#vVL&t$qNdVQ)tmSwU%sCOGuaUT`Y31E6?lpBVl&$5h|@A?7g9xxrBt4 z)P;rS)G(4Pdx75s*5>TFbMjC-EoKzwpIsoQBObRz(w}NS5}#^1QjBVDU6;D1=JT(A z!c#;5RU?uDRr`^hRV7K!s)!_K)ivV;TH22atu09sRE$B1G4OW`9e(XGfGs=Ns(5+y`@u4Ns6kz^;5U)rYS6+-SuaM zCG+cn8I~R2*S+IAi&Z;)txUXF9v+c7$1pYatyiEoYql>|=<*A~Xa6sAoly3lTi=>) z`vvXf?Xl0MiS`P%kNIl=dmn}F zKyhu39+F5=d8lb2|G{nZA?k9r4$VwyaI_mRhbWl2(utSM!=bNQ>Gw?yor0`$=8i}9 zWNDCt80oCCTG_9Ld(ZTs=SdOVyKFz@=P{1Y$vchDg%9w5s#?gzK`|_RSXnw7De5KX zLSyX|Eb5eeRPQ6(N@|uY;sg{=>hZq|b{Cg(*cZz&e<74q(X)psI=C3H4gFj*_72cK zIB7|c0){I8`f?Fn;~#i-g||)1ao&*igeU%|7Y=PHzkf!_mUaY54LANg5w>Yf-*}Jj9W{}U-4y_psf4ipJ{s(}3 zziTSQS0Xy#eoounOqV9W%T!X(^IU`L3lk(oB>O{OE;=T}C^I1&68^(yV?}WSAr&zq zSsB{GM^R7<1PsLFiMb@82mAx$R7+L$A0bPUZZ2eS7{aki8F}iBvgkq`)|X*RlTx`} z?nYKAt;fs3Y#gj+DKJUnm5)r8C0d!Boyh?@+q)Ua;b+NZDPa~6zhcLT+@vwTjs#m0 zuo>3}GB_?@lA#(Wp~MbSdRg0rOwmpn50wn50$R?J=9bhct#@$6GpRbQZ=BK`nbqo) zM4FVh03T$ICLi&^LGKb{B6i}R8CPTy5Fa5{7+$p>^h(72LEkHj^WuCcCI`R#yA zed&d7lLRN|wN(G6cA3&s*C04EFKcb)n=F~cn%Sc^bWzkfin!~phnx8RfEiTP%DOPx z{s#oOt}5rByn8WrfAckvPEu~;1J|PXGoU3g_$}{jw;ky5UI?W5)mT&sVZJ&SDpY$I zWUx~T4-keI_llDDm@l)u*-xqaJJc5GUBRo<1sb-_*F0)3aUY$;4_m+W$bi5oxQ14f z{yuJO6fFnfpBL3e)Z3txy5YAL2SdlNCx23#8@lV=klhQrgCtCK^6iq&yiGFX5gCk? zJi$U8oA&ueV5a4Hibx?Jp{Wc)@yX=My*( zL7_7NhVB~}!;y46N@yX6=YrUu?q0n2-ayE&8Ho^2BXfon%n2sU9aqf$oy;6~8J}>H zA=e6|(V|~0e$zg3m8eUa8xk-7JsYyzuqpOft-`Rs zH^+xTx^N`$Z(RqLP=&Cgt{C(VUdUC!mI((V)P4m!0wiLB9-ShsWtBKhe;Uo=S~*pirGTs*K95*3FV&@Z1ZZvE zs5;LRT(8aVhx$2Rw2m9u0ed~~K_>+K?D zQ->Y$as3~}ncAQf`Px+BhWYurUqwNYCk}Ae9}f!cSZ}aN419)jz}OD?14EuQj7E8X z%#CFCGLl{2KeqR z93I_m2RRq+EpkhL`5qeZZZFA@Dd>i!S9QL#ocuX<;Di515AeJnM5)m&{DwdT6}UGZ z?Uh#$Y6g>e%;_3}a`FG(76i>` zmP&lVdBNoMCUt}+xUcScH_sZfJF@aMJ)L>t4NOU#VH&1h(E9s5WOKHKC=ly-4$9jM zEE55DTxES{$aq3gb#=7Xg1ESn06x3_JrvU+xr;S91oUY&5OtS?NMJf*nj>gnH;|xK!p;vm&%_V^CrBt#gE)ST&-YNyWb6|sl#a@W0#~i; z>m$o(W>{vB=VoSS*c^DP8JSff`(OOoRt{y=K8i6ijAu^8kQOiFVY9A6YRG}3WZtmf zkfh?J<7%3aopW%u8OKyPCuxSr0oa(YMje=_9za>@!5@Kol$Wr2q)=Bq{%R!EunQm% ztoS>ixZ&obHjK|T+tb7Le3)`4dNMDRk&f~7`9jv>k+LQ<4;-g(@S%OL4_-Ptc@aJr zk`wpgV9(o5$pjM9{~2-P@y*dEad{cg54z|u5EJ3W&!*{eT{hXjfJ%vY@F;a0u z<@HFN*82RvNu61V2%s4i!^wbFKSOa-c}QPvs-( zb*|>|LLp>$ExD{S(NZG@#Cpwc;n>Whycyunvc`pAE{1-#>?b?RWqK22XyaN<5izLq zG3}x#N<8`Ivbh*zRrd}i%cXMRd}MQ~*Y|+#F6@H~+cQQ)+==?`zmk5$Th*v>#)!6daf6%pp=)r>m|T!9zXv%$ zALcUT6Mtq3n2oAw!Kk14-vkwTET!yNzq8HH5YQa2_Xi z6ArY?2h91VXJre5ABlpB7?R_uPC+ir!7GnbV#s+GP7EJgiPPA@5S(diaorAAD8cTF zo(+{hTmwJS?xrM^9vJ3Cjb7lKA2tJXefPF*(qK0H+>WP%5ZR?E0W`87l_1-d}X zD5lzwmnGk^*g}kFDKoSYTC`RLhX8ULYgRbqRFhv&BaU?N1mOv`CREcA&Ol-s3LLOM zHC|%Ag~wplRiIqM)G*!|=tLR$*5C{C!vov@H`};}Zp%9qGHhg$A0$Zngj}Sk zteKOn-C%ZcLK1SB+AGzQ|wl z(}r`j%?N8sv?Bl?>1bK7jJJ04HGUE{IkB<^jm!^`)U~VD9>-i1enVWHf=1p#&r( zmW0s>DifF>2x~^{;aMSkj}M&%D=XDMuESWZdpS~JRQpQx2qm6g0dBkhc+@^B0pv|_ zA4B|gY7X?aDh2$T*C?k~Ad>?3ZX{SCg<#yJtuvTSKL;8$`A7cht-N$XeNOMa8Ucv0 zrh&TsHQV*=PJxg2RW#lIXFh{(*HiUu9H!!&8X3A$mS}|ga|I3Kdt?+z(%LX`jzS!~lz3XM#v-%kdpx-a|XEtI#F%U`ccf zvTc)Df*4cU@J({p*ZhEm)`)|q1x@yPo?`3uKr};Qua`i!$&&kVx5UlOip)w^oEaQ> z!%%0aOxpsfQFv71R;G*s9C<0(+17TatOJbmV@@&gRIsiV48}%#=lF8BYliTqKl$J@j~wsTyyg=-C z%jEV3!BoWtTqx4?vMyIR2#~9;wT(D5-~$gCg3A?r^3X?$xE5tbNzGbB=&dmhH)cvO zh%rh4Jjn*eCN_$3n^#0^0dYCLV{dzC~ zLJRO}{N-*0x*=|8i+NN*e3?lRr9eQ#E zJ5{&Y+2F>)$J$A*c^}yUIO;G_z{M3|F6t>&WmF< z>e*q@&`PqvSrhE(m8s@FO5RNiH4=Um+Uu4-0N2@VsZl|!+dFxvD#Ew4c>R?IaO#)j z)M(w-=J7+y-}_yi#H*_ye~s4Cl5M%E&#i4osmC?6bB9`X$Q<7LqlT_72UQ%bNJ?4o zj!yVuk6+V>+#&NXlvuni4lgdZEu3(caof~1^%hy^f;Mjy-qNLuCXsjsANoH%MVb+s zZh5(!ie|UNAxx0j2?AR%M##dN;-J zr&q-Om)4Juy{qW;GA*batgd@?!W!q}OH?yUAY5WRkB^_

%dT8#&n9#M4$?9@Y?VN*Gm zQh*ImiczOIq+ZN{uW30x~l`HRP05Dv~bD&u=G@#VmT^5$vc`F_8(9=LYd#i41CDLuvw^ zqdb4_T43cmGV6G|ib0EcMXb0NvV2d#EUJe_8tb-4i~s%eeKd`(pRsGD^PA|Ztgx_O zxL`WtIz!xfbn++z0gErnIuNr)GxZnW-4FXSGj>GRO^D#8;6AXF@U2z-KSpCtVETcS z>Tn(TCutUdBN_?AoFMHyb?Yd=mNCoWG@(Y!^K8|ntt)e^WH$YiN3;h)26}}dg&HBy zw{i0G<~B-qGu;)e%cb|3GwnPGJ~Vux?<22kf8Tp|B+M*sj$>`#JuCeSV?QqGFiPM3 zUiZqsSj70Z*717psJ18be7Q>%=kV5sr~S?=nn&)N!?N{4*Wq};ZK?2+;THUt*SPKX>TVOcvx(9DehL2kE5VxhlK#W``B_UT~M)b-{wNe&h)f{iuq{xhIlN6nwkuZkN^RNEmkpb(u zJ>{@Ws1|r>+cYwAFPTe|FI2eeDb7IjTOu8dN(4O;jVA-Iqh0jZCB>rRhZjV`mEh;E zv4=gJB~s6nYjXf~_4k=lJL6(T-DcS=&fA5ift~P<23wu1zlUdpCj3&*k>;%r_@Hp) zO8feale4nvVut#oos9V1F27CFD+Q6 z=eF9e3<`1Q1r(@H6;u{J%m0QF*%#OfxuYdoze#UW32}$wmo+OakTj>1kOY266f(48 zFmXv3oho8S371zT?iV0pBsvrfXG@fgtr7r&Y1j3<>c`w&wzIb=2SKUols zm@5hUC+#f|m?*u&EEr^P^wrUZ{UP$Kp-h<;6#jVKx$-yy&j44XY1J~4*vfPjwf!e8 z8DDCOZS$vjk>u?lGBkJFg3EVA5yhXZ1#&CCp|aFh&jeW#chFs`*}~SbE2CK+Hd_e~ zXY>TA2*KRzmWSnYUB8MtgmJA3FvWF;J@m`_I08=>P=DOuM0Uj{8^Zsakk-^R?OVUj zFsAu3{p)i*-~1)a#9qu64W zK6(&B=UQsYE}iRZK!BKse_Vw;#$v9B|0`yisQu7SuQ`U!7VcB|Lcm7&2*4bA4A{7h ziN*||P?^%vU;zM`cOrOP9;1={tL10R^TGgjK%bRp2&Pv|0iX%jPUL%3jjaGs^Ui8i zg|(`rDm;aD_X>2Hs$884=^LOLUCv=URG!MSn7~fEv}SGf`~oXqb$2&H(F(<+LWALA{DXneuceudigxm0wH1e&!I4**O zj6I7UtXHsXP)T&8lX}a*-6!BPb`H;(!d(){Ky6m=T0ANDM9)yTtBXpFrgD{p8!-s> z*|Vk2+NgMa19>`MJzZ!aU+ms!|5}BoCZdT}i~7-bRz5$ZF(-^$1!lp+B{3Vq}vWrtsPqs`D zMujwD*2(DRn|DNms-{>H^;BbGF_*U!wG{_6~nZLbaIllfK+ zW9zNz{d$($weHX+^$EugEChgLTivu4y8ZQqs`oNDsjgMV)_a1mVLUOlRf2)mT61@) zHi=2{>I6`v%0 zPdQr}5i$A%otU;S%@b;N26duH`uxi2cFm&QD4*H*eJ?UWPbBS}e}|S3?ED4PEQw8Z z9yYcmjrj{j#644<+F}abTacRE%TlG2H!{)Z|AzM)sYrdStuvEzu|lmDWS+kN3wMkI z$&uN@^TV4^MNb9PDk%?{XxTuj?|7gn zL#uLwyvJaGaE$9cvp-ZPyx0jise7z{$@JgfA zuH9;>oXTdjcx&tJCbqMLFa4o(G#1jXb9B7o)D!p`^)VZ9p>?r}B%lAioF>`e;cyZZ zzo0Yd;-)7pbnMHOW-jKJewesPN+3sbFEcgQqLb-i$tG+`zH4(?wT1jWEa(p(UCLWx z=74``aaRKWtZ67s_e&QZNHLQ$Zt$=<1(H3q+1Cv8h8ZfWtwFy0zHRoi@Od$Xdp8o8 zghrhBPbz69j^E@ODc^yvEN7oP_Pp%(sO)UUkx>&aqPu~nb&~V#R0uhu1k02Y&4cK5 zZP$Il$a2v1%}Kdv8%!4|Lv??GpMEsvym{bMy;_w`Mj|RE2-=g=J~4Bx3g!RY9~p{{ zulG+8RS`5|Oon~x=@DqHQ0l1YDjCXZmsHiV8Z#T_@2ge2k&R6xCGCu)+?Jzfk96ma z6;n2KQLeQST3}e~KaZL;@Fkw41YMPbbv=m!chGkLtzV3)Yqs5g1MA z)1I!gRMNcObKAqU-0nFy-+HF;d{YIQV zfiYfp=R_TFF6nN;im(rB7}vd^Laq>?E&(8&lI=8!Ih zlX@-k)fk@_@kCSXbLYZK8%GzlO5jZ2C~*`+sKx%|y7s0i>X@SC*z1|b#xN$XRdG@a z{xbcGyZRYqwr$Lb^pvu4L#UCgnzWKCxY0*s7Vz9D`6*LqA6--+Tl~+yk4o9&kwndV z`CrMx8C9DsU$p=i;J%t&ij$I+e~QM3U#aPFKVQ40e|=>2u7z$}t+$Q>FQ>(gOnJP& zJg3Hso6q|EcVVATSN7d9O;+2a=94C-W^QS8BUSQrONX?uO!d3!BNEMSElKx+g0lD) zI3w?V^4Tm#rw$+_rMJ%HdbG-)lt|%gU81*7io7^!pVI8vCd2lHs}l4y#o8@-h`qbL zo5pC=KhXLcN9~n*+RuMye1uEc*^%Xk&KFjS(d#_oX03+f*V6=Q^C)zEHJ@N#!X(Js zWSZ1%^3%@1z(!qXAy-rlf{=)viyKI;zz%F~DEuQzsg@-tDh8+h6PDJKgi7@6X-i>p;g6vy4Kq z2g;>6eJ!vx#(HtZH|u?9e~$N>9YnpA@wi5vT1Kp(_>7;VW#{ zgr_E4&Z8>4udKgQfeiSMgG`sFQlh+tk$%e!*V2slVYbnL$~6C>zbTw=o8~5YgX5)N zfs)hcl3Kz*?K!CD#rL*ZTYnd|_NIa=YUs)QHf;Ep%BHa4c$I+I>1gXq(aUUXi;pri ze`Dk0KUQYa>Ghk*=}7+hCdMNQqfXmDq3MzkCu96_Dmqo0eun1Ke{M=mQlUo0gkr1v z`78tNhGI$Jh;xXC)O8 zx5{%W!+wpju7C_XuGoz@ld!?w6=$Fq^^FOjON<~clW}Ii4a=5R1F)-0g(H)CZj;Uu zG5@5e5MQl736sQi{9`0$yA)~Z-EV(0PWX9R1CFl_rf<;jP05mg|3Wz!%p>M@K;mFH z4qgt!hODR`Hq!GiH@C$I_3rTJSWqnnj@9(lqeK}TD*)-Jaj@RPH_|p;J#U!9pn9s{ z*ey0Ia`q&6raf2@%O|144(oV$EIG1u755ebGx>9yHX(X)#|4r!|Vgmm(NEuG^uV!5tq6a;cG&FQ~-e`1#|#_n^-%j#~eQM{-^m^L1It82X z$<7YTR;|L|zQ(Sinh(u_M4<)A4@=5-(dK9~0{g$G{(HEICy?+tv4*S^hzlR20|RJ| zdj#-qUy+#wxfly+m1X;`s-fSvaH!>QoNiA%77n#I7z;Qj#xtV(IW(ME=A^MpdIv*i z14!^LqxDe44cqa{< zCM-1oTJs#nD`rXP=`$3MmEU+MStO2G-CL2Y3EyKzPcrNE*iCDv{k`12jBHOQbeXmN z&{lNk=Bt?^4Y=1RYBQMij^lyHbZ1vBaOR_vSD8AvZ>JpAD@^2`APTt7BU@RtB`(CG;WX# z_RQ5BEu3L1H-hhecR<}E)?MDcQ_fw*nLbfTu<^MrM^PIfd)8=&;~S0} zZ;jQ-bu}b6zJT$#eFsk*YbI(O@+cIFMGFC(8sY07RwIeZQViuO zjBtrt^jU>@YI`ozwOJDSV>$bfHQ5nfhQqJEE%KhR?O_;qQQ2VXUiz&6Fl^BJnIerE zfV{%#F?SkonE|B&XdPyv;0Tn0xQ1R0n(Sl3%Y2fRg?ZH_%DE629uETC5wAh;`RWuL z9iE;jL*!GKw7e8n)uSpijw`21#NtGL-GQ9jsUi=V80O(sB3FdFkyvTKM3DXS;re)q8URhms>n}^ zgM6Y-hI+JKRypuqI%I)&8)6Q#uC%&{_tk<-0$5CDwabSy=WLpU)(e~s#}TF9#Aq^j zV%LhCaLhfpz?l+P&iiFya!~10#&Gr#a;$u&sb7g`=A?&1kbV-nz@x{SkI=xL)yB?s z7ceZT!_UG`Yq!dW>PPpvTQBz-iNr=lRc;BUrOwuw^SFNQPcn}~JrfD>$yg)7X*DER z;=)u&gq813e_NWhvtX_q0=5whrYL7q2lVAD#S*gh`V!~a45%#K4Qy<_^}O-78d$%| zt$u9XC+%D$KrtM=;Nvm6+vYyn+5dDI)OCWd9VT4okqZiaD1j~Ry>Y4c8c)r3IfWu>K$WAcjf**K z&al;n&39w@?{M$DK&Ndiq-oabJRcu4L$>pO&XcbZ9Mv_*$lq*j2kkFc zAJs=bh*tPB~$MlcPFV$jnbMm}g!5o`;Bp|N1 z28rdpqSDVcn$rbWm7yHBH6NVX%PojfS`Lr+nx|Gy-p5oMELo=1mLQK9dc6&Q5FH6z z{j5;sG$Uuk?4f^ciLIL{XZ5epRELw@nOK6<+OX-9fXfA%#xzV@BPA4U&>`4LYrQu~ z9$?vOEJj~noJKsZ9H+4HWi??f^_3BNK>plWc_}|UPcxHc@@=~D{dfo$fk-At@tW5H z^+%7vHBj(&Ewv}pzTH7haUtt)DtP!7hZo0+A|54MfDEj$yQ!Xvprfh!3$*MxEXX&K za8D^n;zO*wImeWM0wf>%4@FYkiyk3k{2c3?@81WFTzkX3^Z^yj_p3d+Doh+5(ep1!l8LF~?6MfW}7i8-mPZ>$(56DC~=I(miVX=mn=U!co=yJEt>##vo z<2@144><`uy4GVqNF&GPLk<1}i}lKDz?)TQwJg#Y&E&h(Fu+nCCvhV!M<0aM4T%@| zN+&atOoW&iDjtIbR%dB=!Yz79;~XY1)j;_3$l9^2D?>%+de}VJoQ96*fBy%@vyJZJ z+Css?b*)(L6K;^gLfy>q&P@qhNxFhpbYS>qK}~#7(BP)c&jM}!gnbi(!lHiK-hh`oRKArv@THS%ioaci zx>@||wtWduQJnP>6$6rh4{Y!kO?(@v>atJk&lWwy%uBfOj*IpC?X-wZe=VI`HHa!e z<{1g1cL8=H8i}5y&3jZr(&&=zQxRE2Y#6ITN{NBdVyxqJu;W1K7v6S!8&<+143~ki za$)W=TUO92f}+JS6{$@5DkW;SdXUOZQ6*=c;) z@39yMnRaH$j>u6lG!j879lX=~u zS}G*%aI_($dNS-q>uIR%^={dXuX$HKYU=+b zq}%mpeP%1v(ulJ@G&q5Gz|UV$Z3{K)o4Qle#s_vfzf)utLROLfo1&7u9B+bgfwK%x_~?$`{NTt3eb$t;9bi(|QHm&T zok}ZgV8nwK#l^aNOdyhDMY-R2Jj`$O`+I+-i3JQ01zz%mAR$l4B@j5pKmJp>@*K=( zCL*Qd@F&s`6ZKvPwrDHyGwAiHKC@hKz}$5OV>AG|WklCe-$KBeQF?w7w>;)?i$3N( zmtvCi57sxWBab!#bEl{12@p$UZ9LIwjH-Kaq*&{urdpyP4dz~^VllD_rksewMJP@U zM}Rxhdz$pemy2djDTgS;c{4aT4Uu?k-t`clpFmQ3rb3e~>LzByvQ_ zqD(k)NSY~r#3zmQKYRDzqw9brpkpx}aY^^ml|u_%E{FoqH3|VL;}-XGFCN}DNXgI( zy~%`tZ)VnmT-gV!RhqnJsWIy#JzBu<2Tw?gQ~J9ez*bqyXM(qX%C~@5xxB4!fqY5) z3h)GW#diVsCp9DV7=tU6;|Pth;dow)XLBpTafb+sv50C?TQ|~iVSKip`^rl=1)`{&I!IH**I}yR68)qMSDJQEYkayXD264bd^nDG# zPx4f7jzLC8I9L%D#!kv*MNAWUsc1Dtdc?>>L`M93x&JQM60r}Gju4khG@#&h3N6Sx zcjiRsC|J1?4QDMzL;XEX4B>aUX}buOB8(9bFN?01|UL(?nxH!!3#V+O*vN~xBv{ftiL8Bj+TDb-n1Q0M_R&FG3=pX zcVhD$f|vg<1jC$cxlPvA+|*)I71$_tCVcPFU&=}M)^D{n0EybZ!uGEs7vO#!zu8`# zUJ*zhrlw$o5v5!wpE*M4X$SN3z|tk!eWf`WL$ZuUx6ffdTqT3SB7fF!tc)3~eoD{X z8(twEYJF(KsQ>uSe!Y8`!}}A#U;G2#I;1p&vX$1|UkNk_0?^|7joKA4?Mijp1dDvR z|6Ko33tO60`%x1U=YS;Zt#H_-;|9>VW-Z4O)-+Z6)@a71OZ>cgw+i${lO<{XkVgNs znyMBKBIgWHEdx#TNCa1{h#TP?Y3IBaw5@(?Y+4eQ^G;2r(`8#uQNVyFwFDjTIP#r1zm(y#pZ;d^-EsVBI7HvbZ)JAp_S$jdn5Gu^r?h*0G)P45s8s`{YKl zK-z2{txmOiRYL-tjfQ=cUDs5G4HCru{mdbtyIfI%a&}#DNsn)BD z`owEEA+>(5WNvx)(=9S6;3;7s=HW)TBo@rBo^v6X(hp`b5sD=1wmi*AvX~c@Ib(uU z)-(nhM>!1V7lipBAk5`Z5F>#vpacMD3STB9w#a5+^FW}H^#=}SFOrc$Tn7>_evD*q zL)`(8Zb+X9-zbhMk{k-EDGv@+9hNL!LD*;^OgAzSfNr~np+cbkA!a0hy6g+xuzOgK zT6h!EH31Iz{VFqcgDr%*aC5<&$fY14^y-9@1LVg(Ke_HGTY>O*rI8Sp-vG(`xr$fR zL_7BA*`5*;Gy;F|2P^}ord=0t$42l?4sFtZc!O#P}#w&$FkXy7^)-uo+67>ZLtU2`l z0!6DHpPO-+A~5jK)hfL_kyd_jZH9t1B_YC3D`*h=id6^+^>A*zJbp+uo5znQkMZ~q zn;_L7n#s;TJ(m(NR)O8O_Ed!VXvbHLSTz=yF8rH@$CN4*M_?TFuwsno>C*^8Gby z7^q67?F2&l*Srd&wgQ`LXfGj5wimmJ?*l+(l`y@hdxTSS+G}d&CAa1BB||o?MHwfb z)#k_Y^Fr$o&KltTsP7k?A@)U4=@tIR<_BhH#I}DV+r62Uh7C-lnmY|$w!_i!&H;+y zB`2d(<&++a_psBYle2zoX9ro^*O$h-Sjl0>aLjH}yVkn|AkH4^J@G)S<5Z%}xe8 z_&lyBml~0jUeklXssGcQC1vn(i=ik8(P_Ct=Q~KCLmh?Mas>KC zLgR#t0utD$a^7|RBKOIteX?WTAj!e`M?k_}ss$oj8fS^t?aXD>)Jf>sN%qAj*drv3 z6c^i95lr{7h+_WYzY3Iei+nNx6>6;>X&U0s-3D|cl-uePgL-kWD`Iz8emOeJ{)AtF zYm>TU(<($qKIQ5{a~i@y8I>N$#8C-CbTeOD7_w#mN3!C#Iv>HrM^a5u22G`h``D$@@yZf>}T6p5ZJfg$+@0xclvnEx9q=CF|z?VB*#`&ICO2sAOy}Ym$qc?c7UakgAHth3Dxew3hKDg{rU&o-t z^AT0_)pFcy=w`G+l^8u8KI(qBjmKv7T!S$ttHk2u;+oyHqFLkDnjyo654R1uqt?AK z&#}8UrOg^3j1Uug9tI)9g~v0)^ap%kD6aEpscVY$`ODE_v@P1`=FHdwu1y|(tgvZm zn-nAhj@az_Wpt4C&ug9LNinF@89J@9EEJ>?8gg(Pds~>AuNb@%wk~PQBRHdB8u}Uv z8P(b&^e^5|^(wKWNVH`V=PY>yadBsBK6fnjEK;XJ*yN=n<9F7=X&J;{tztWyUYA3J zd>|TBVwJptxMA;p@7>-mnPX^+^CDdj81Ztf(5->xGer$Wgmk*2LA|gaFi8&Nd@v?_ zdHd7v=1LFkDA=}vm^_KtE!t^LO%d5*UbkERd4yQ5AyA*vlxcm8o{A`3ohiJ?H>Xfh zF6;2Bp!{zI4}vttj>;5;hXW@#4+%x^y+3$6>&mi0vHX}`pN;fJqNZVr;1S`RGn-+= zI>jV#zTh(4_R#~r!&!Af)z|Mm4(PU{RqQNR`R*t8g}XN1W)t+j+P3gWO+c0~M{T1W zuAXAFBDQ5+!tG<`q^q`eY-v?$=IRNy$g*5FeJwnhiQiS?i^o7$J&#u-@>MQf8_J!{ z=^E3>v9F_PTL#>i{`xk}(}4P7Gpai4VzNzAK+g*?+mtETzzygQheUTJKTy1rRA zjcSf7E9k2}=7|HU1ZUKqsH)0tz@u7@z$qN>Otqz6{@>_t+Qn$79VqzNf$yp?b&%tH8QAwpN8${htEzMU&Fi)P17o>I zlj%!u%LUI~7Ctzp>7KH~EeU#Jo(ZMV)hs z-eTQAWY>f8>K9{^2Mad{Rwu-TY^P1Z6PK&b5Ujso`2w^;^z=>346>e;Uva3uRNGYa z$y>YQ`*iK%Kx>?*@x-cYACs8fG+H#~v*=P_T|X|kzzv}`dbwT2k)y{4b3Z4nGvYj% z*#yvjcfIOe_?zVMt|kHhgWBb9Vut6q5nfxMOlpC}jlGW@4!!J!c4>7iZ9)0}zJbN7 zE^AK>UBM@OI>REsd~FcL82nGeT}ajj5(tmrAIHQy)zW~tFWxL2f*CjaNze6v;}Lbr zQPV|0OW{h1*eykXQ$rfIn@9IcjR7$(A^u(G1wZI6r!z_P^x!#~<515nHg#8riDqzU z5%h;Sx4Jb9lebB>i@ey+FEt$HCY<)n*crV}VT*MdEt#A!#l|#+z9+;OgvKipUH+7X z)+~B;=Lt38yWDOFz3pK$c2x@;sq9wX{tvL!g-LX=_Yw`nO)7z-CmQgVSzQB?2!ytX z@1dtsoxbQEhB#$;F@hikLX&Lb%F<;)a$rP{eT_t38=RAdkd5F}8t_s@4QTC`a^O&g zAm%O0^xJ3K#L-^uwU(F`fGG(SZ{=29Ru4neYyQUa=5T82?R?X3dsMXn zCcfEEr1!5sXOobAD_3zzzmsZ`jAfnJHhRFjNvud*>9j9OHrptChnGozDuxL-+A0{G z(7yEq=NcTQjLDB5DUr_gaMV@OHZEMtMeQ=84K+O^EmTr+^_Hg!$+v(f*^HN~d}wP% z%2!1uP3iQ_V_NzWKN@NwuM@-qwqXp(L29x9DDRBaJT7?Um#}-PAMa3{P}PNPiQj@+%ukoQJl+ z0wOj7arm=SwX~-sxglw{N_P2A1$z5g7<9ePjvU&bicQO(pDvPqUZ`i2+){gcn|QRF z9^OMOg?K8zGspJrxRwan?%Cj<^cgML_I6f7Y^v|5-hgv~qz_yRw_#5{z7(yCiLpBp zwHb=Q#WZ*`=o_HoZmU1O^sXeXj~4#{D=Sj->Qwes#&yS2y|3;|*5{=%mz>cJ@)!Jh3UT8`>ZKJi}Z7vn@_nADIl>guS%x|wCtZ=AzhWUx7 z^!6u<$F6-VwzYcWd#>qBSQ-|0hA{QiLLF8WX1SF9s@WE9zbQ7!)p$ZKsKN19qe#io zyGzbdoaduP+kStfZ@>}!#Id3#fuck4wB$SKXKkR{8NJu(;=iQfN$a4pou2IdrAAu< zzRfe4s%~BtzDK9b;^eBNA3{IOOy8I^8_F4U&1#sY?~*3s_gi=c-l%#n|AeiFV?@s-~79~q4W?4&Oj6D1M2d9?&|@)=>i8^ z=gA0-Ak;2*OLv0I!*>Tz&f7re2p|UlaT5TrbO1FW0B`^R|8MVoW_#w@Z}`xoQsc4> zLA%3#CVXH_EyKONo4wo9^WNLr)iI}cwxH5F3F~z)w+h#`X^j~n zvC$ zB18b!Qx(N9z!XL2#@NTpXq##G5|ZS!-Wj}ddCTuVrOp;u#!}!q-Vm7NC}sxb@)$~1 z2n#hp8cZX(d#7TWLN9f}7h_5b*&DRbG>}f+&)&Sfqkpu~3q zA&Metm2o)VA2w%<@FU0kB*X()*ifces~7bCIAsgIh3O^fR>@C4D_z+54kZX7C53Eo zAylL0FEI)&nDz_Z`w^3|Qky~}P|5`)%5UG{?cQjHFClo$n_pNI-!$^FQD4T=Rl@`6 zV#;+#juZ|B{BDcoLeoO=p9dGJiMN1f|6(sq?+pDs!buUt8FY?XIZq1LOT$ZHa(TK( zO*#si%yg;`%?D1f4viO+f1cc9CN#x2ozmF6I#h&}N*}2-7$;M&J&Pd-<7TGdrlNxz zkWC*rb)x|qY&t?EcSBc71~!5s!i6Hp^^i4WE0BpZo5xqyEHGGw6|$#(VUHZDXVd2t@mlyt@> zp`Pn-QVFtAi%Afs(MOuL|H}9nQWi!cM#4hMme_|7GB3WG=1^5oxg)JG#ec3ckufs! zSbDNXT$PH^ENz*m!0c4V)LH<4zeeFrL6jj)XgfJVl2YbnO)exOC0(5sc~H)I<)s@p zcu|E7qrOFIO5Uf4l5n#^w@8cXHI%}>dz2k1mZ+dNaoX3vQS?tTRj;QSI`m)n3ZF_L z+;|4$VVd-wgcps8=Xy8NOl%DAfDIpy?$z+kasF7<1%k?pwqvi z=$n+gvH@{Lnj1MS{uTaV;pyDv!k?PCpi_OD?-Cm`G$|5Otq#(6k589WPzIT!riFXG z_{CEx9Lc0PndW4tdbZ+C5*UhTjZLKL`$rg0(II@KR)ZVLxcu|4zms{uWE_2#{(qW>n5lt%FNy7tVhE~k-HF`FeDDF!~wH_6WhTe!)tKd4^R@x%orzN zHHOW)kntFcNlDDxE{f1XT4u2i_3@TYJDiQ!%SXR6{zIIg@DiaDT!7M#Fh?Zxo7syB zw-JV-6!DHqPw5~>UTF`^(dX1j0q*WekLuuv-jyWmBUs0$^F9U{th*CKdff;=lu)6x zcv7vBUY#1A)e8qWlk<;(=XRtbCfTI{eJU{-3QIpF9b}?|zzn4)8N%BictmU=h5KAD z-1ynY@f1$q@1Ei5QMtqAqf}+|Ut4N^8}29IJ^qWf*5nXX{76Pe=Ixx$TZ@|t??CdP zU#^u&v*Aw8^TifOiY#&E#P4ZNsE}_z(q9;m9(YlbuRrjZ2yss-LVs=n3-M z+At%-&iqx$sbPF+9YO-6t5tsg7Ms^eIpKk-=}>#{@rP7iJOk@YW1 z95lC#6}eV^#lM6e{%#Q7$FVKLUS%WnYs=)S!fSVxLAKa5&2Oc@*uFks8?l8<2QR5; zM2#q3Z&A>AcBo>MXFr)FbF+fXi;){GC$O4Ac`x=0DSdjXWLhYb#xxG7yI`I=|E6G? zgTsPkI0PYKW$!j|w+&B%Bf0zu<#Ww6C6Y+G!lOJM*I6W6jH%9y!p5^w{F=H7nQ?{G z<5#o4OtmqE$CCv1&FGTADTiIM)o1JUy!v+3`I_bU{(!f%Z@CiiuZDMhj&YsHe4*)c zHl__1RFFc;LB$^O!7`SsC$;s>1MdjumF25dRETuqrV#1=k=zw3@zbA7c9TsqxT^|2 zRn75^wO7?N3+iOC=N>o6;Kyytq{jBwRc8&8;D` zuPp=gJzcTvStJf3_I>S>#cqS}F4^QB#`4DxWX^Usl`|(-*rzoyI)gkIVbs(woTeRx zXEDYwTD%YbaPyf~}rbE%Do}7o7MjYF$zn*qYV4lHcae%D-VRvHG6WWDc?TPi5WrX1S9b zTIgxv352@nhq|W+Tg?zz!ApLhZIJtLtxxC2Me@X5snSk8XZ)p0cO{;n%LkHLHky)e zZdlFRYXxU<+ObEIoH7O#gnf6s=v~OZGx99?R(1hEhX$=J+`M?_IWjD}HE`UCH=71~ zlfLUvbDpHIU%Bsv(#DAAx1t||6t8-%nD3&MIGsA1-j}VQbPtlQZwZ=Dk-D+kH?9_I zcJ^+2V`Oc9XxZa1qaodvnVCWKH@?sJx27XHXkix9X$o~hA!z7wyB*fzXJajiIgR_g zvMhDtE7qlYgE4PfU+GLxYUG<#ec3&b7hM(01t02CX0!s2KyBuF=*%t^&1sBu zoxmFP4iF;EE=Nd);DpFwN8F69+qwC*f!ordQJ$!3InI~D6HsYVr*&_+{hiL4Uy05; zzC?9Tmq2#Gx(at~G)IHHP2mYTSm0?bX9q?eYxYYU5OJn%%OR)*#J6nr-^_S?urVHlCv9%v*Wh5z!R@~g>ac(?} z(2uCmJe`t@Y@LHDkU<&8iN=4w-ZRSsE`R}Gz!)$F3;_ecfV_XK)Lw|u%_*Qz?)+!F z0CP1fDa8tPvUfIRHysJE3xEM&z!)$F3;_ecfG}VT82JaCRa7sDc-YOOP*?VethW3w zM^mP`Nf>Yj3;_ecfG}VT7y|}?9S00c_PQs0`;#XL9`UOMS7SI_%iXap0*v z3|j!Zmyhsahke2B@`DS-)z0$B3zO$D8Uut+Smq{OacGrzNQ+tS2L26R4De58py14R z0mTK(?xla>8?9G9#{hkq1!%XB!W`|^7a!gDiS!$?pu7Sj3kKi(4d)b)tAHOfXY3{~-`1H+g0sb0W| zo)b+zZRmL^**g?gX*V7?^$Z~o-T_wl_{6}jy*o^{YhLbN9Ab0|=8`uchR;p>m_=|j zMw}M1_!R{l9o~C}AOhMLUPC$DMJyDh&5rWu24?}si|rXtjSnWcoPQM(Bz)KM37%q% z-!@<|_=a%6ie?XhTL#c@*Z^ANxHMJ1ps<1O77Qja8U-;{lm7q<5@qfia5sRq_u(fC zcuwy_umz58{1cac7xHO4YWXtnijoJD1qkD^J3xNT4~?Jc;Two2fZk(*P6@7tcVHGD zG<$81Yug6G<68`Af&O<-t*{9I<@M-(cR(=JaeRwF*rwdCWBpx?O| zhWGf2j!=hQRluwP<9dLpBp2?&&!n#6hYE1G7?yZ}NYxea0Vo3SIC^j_P#3>Buqb`p zVB$cy^ssz06;n0%{JjnzF#+FtMh`j$kQ*vv&@N)X`2eaS)TM>w z#hUtzbetLe0XV&{_yaH0^!ekaknB#{DF70mOQ43HOF@;&YKlQFFtZ?7YCl~8d8QX& zK)`@I^+in<00DSDXEdH={`|D~(LK6>T?Rt!B^s^(9hu!oxAf7uK(VU>qvI2+sr=vp zO?z;QS{wyf72*Jpes&APe02la1<>gr4EGuWcYnIos0W9l;*blo=fLb5W`6bq$N_L> zLh7%(l;lHZj8{Qhw>C(Xr1Je`2 z{4zo+LlT$FHMiw$YYup3sw|xAwXZ~<|YAGPdAQew6D&oB>=OzB7LISq=s`R=GO9Qsp@~31~%%+#(K;xpdv8xXU zZ@u|131XtuDsmu%3E23GMO?ia9j$2RlEE5GFq2`*`7gVH%T02hLZ}3YQuqaDu|r=e zh(Yj7OCILHX=0VW1)N8t{<6r=&8Yma=h$sk=H(;EMauC@U{dZNYxcHH>FC|9VAaU- znlk@Ay*dN6V(rzzZbU-oK zq)y!Q(@6BWu}d?Qnz%t^MJ>dx-R)_A%#0@~$g9}7U?am7x87_`caTS+LQ}x4_Y>&j zs0Vs`E>(Kb(}or^T8@=AOxj^=zNyQvu^2v1j&|y1d9~dm#!s-te~8(mg0-W&7W)RD zy~DK|AyR$s)8gbxM}oszups71{womfBLuuRo1qu}8fy)efs1#u1vD~>Uk0fCqg6L> z%Mg_jZ&}0c%c~9PhsoKGj@-+jD&pY8#oH}$czc?wy&{L@R?}pdm1aZVaD{53nQqbp)OPBs!`?JXvFBuF5*2h$McO>EdOpfvz#Rz z(~c_&EOPedb=)v|eU(irPAwgUoc@Ro_*fYx$Ns_X<{Q(zJRdAWp{!SMy@D6LfY#|N z{DO1U|3D;d-X6K2S&0_C9VcJCX+cc|O?}F}dV46hsLN#6F?G3Q(24<3!F2CgP~%fN zv0t?yYeTHkB*33p--Lm7i#KIozhG&@ocj)Z$rTOwF|C7q!u_ z!7Ry7>L*}7emk<0Z$|r_0(+>d1=6h^{156Cm!6cXj<17@f=(C36$xJ&CO4c*Lin-F zP00>~@4WB8|LX5bm>-YAb0GinJvwcC0~EFfxLT&M;Ni%Dlcy%6Q?Oc-^e6x7(GA>| z^llJZ&`h`KY5*vUXt|(wZ6BpWCp%mX%%*djYu#cdyAB6prlqjt+4rN*7EVS%~3YKz&^u~H)Fj8c7 zxn6d8vs3+&RBHdD*`>AY!UlA#V*=(Y&_7bL>!lpYdkNpvM|(^7k0sEQGR|n()Kps< z4GB3b!Ei!&<+{zxI*@75I^HVl-M-d)OH_6iNa2@ZV{eo-{`eX_+HQPo*z8Z`G5INN!?Y-_E&k` z_vI;+ee#sbzjsO{XNCVP63@R0M{AN*B1!j6<8|Uzf0q|x!(?qL{96fb{H6)nM=&*# zxeV=O!nTxat;`55-*4?m4MO^IWdt#`lbc#q*aMrHo-$IfN(iOzxBg4;Es!>;Hz(}aMo(4Tf$+YT zJvtK!%Nm1>MUszE<5u-yYde@0#!;MXp&PSyO(`-z(EepIslC+C-k*ejmu8Qggj1^m z^UG>pn+eNRmGHl`5_*sNY6MXA%hhxkc0UzMzeo2@z|_wYrK*|eDhW;#S}TX5hAgfA z|3?>Q|BEVK38;56w5J&`77}efDdOk27!QVhXxtfXVN(z3zNqM1ZH>DnVZYtq_VwAnCzxp5oAuQ7pEwu3w(2MwDT<#o)r(!+47=1gcbr-*x*6MX3 z-Jr*WBlkWJTEp5wPJrGB-=c46F9eHTM*0odz4v)BE_a44TLrIvgM@dDQ-pX#$)J~s z{8K7=5ke!oYA$NjyQMLWx@s@>on)SMHGAD_wxbXK$XK(AX7>MNg0fC%b^Vw*pe7N( z&4?K7cai. For example, if your KeyFile is -// located in the project directory, you would specify the AssemblyKeyFile -// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] -// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework -// documentation for more information on this. -// -[assembly: AssemblyDelaySign(false)] -[assembly: AssemblyKeyFile("")] -[assembly: AssemblyKeyName("")] diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs deleted file mode 100644 index b110dae..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs +++ /dev/null @@ -1,202 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Runtime.InteropServices; -using System.Text; - - -namespace DotZLib -{ - #region ChecksumGeneratorBase - ///

- /// Implements the common functionality needed for all s - /// - /// - public abstract class ChecksumGeneratorBase : ChecksumGenerator - { - /// - /// The value of the current checksum - /// - protected uint _current; - - /// - /// Initializes a new instance of the checksum generator base - the current checksum is - /// set to zero - /// - public ChecksumGeneratorBase() - { - _current = 0; - } - - /// - /// Initializes a new instance of the checksum generator basewith a specified value - /// - /// The value to set the current checksum to - public ChecksumGeneratorBase(uint initialValue) - { - _current = initialValue; - } - - /// - /// Resets the current checksum to zero - /// - public void Reset() { _current = 0; } - - /// - /// Gets the current checksum value - /// - public uint Value { get { return _current; } } - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - /// All the other Update methods are implmeneted in terms of this one. - /// This is therefore the only method a derived class has to implement - public abstract void Update(byte[] data, int offset, int count); - - /// - /// Updates the current checksum with an array of bytes. - /// - /// The data to update the checksum with - public void Update(byte[] data) - { - Update(data, 0, data.Length); - } - - /// - /// Updates the current checksum with the data from a string - /// - /// The string to update the checksum with - /// The characters in the string are converted by the UTF-8 encoding - public void Update(string data) - { - Update(Encoding.UTF8.GetBytes(data)); - } - - /// - /// Updates the current checksum with the data from a string, using a specific encoding - /// - /// The string to update the checksum with - /// The encoding to use - public void Update(string data, Encoding encoding) - { - Update(encoding.GetBytes(data)); - } - - } - #endregion - - #region CRC32 - /// - /// Implements a CRC32 checksum generator - /// - public sealed class CRC32Checksum : ChecksumGeneratorBase - { - #region DLL imports - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint crc32(uint crc, int data, uint length); - - #endregion - - /// - /// Initializes a new instance of the CRC32 checksum generator - /// - public CRC32Checksum() : base() {} - - /// - /// Initializes a new instance of the CRC32 checksum generator with a specified value - /// - /// The value to set the current checksum to - public CRC32Checksum(uint initialValue) : base(initialValue) {} - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - public override void Update(byte[] data, int offset, int count) - { - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); - } - finally - { - hData.Free(); - } - } - - } - #endregion - - #region Adler - /// - /// Implements a checksum generator that computes the Adler checksum on data - /// - public sealed class AdlerChecksum : ChecksumGeneratorBase - { - #region DLL imports - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint adler32(uint adler, int data, uint length); - - #endregion - - /// - /// Initializes a new instance of the Adler checksum generator - /// - public AdlerChecksum() : base() {} - - /// - /// Initializes a new instance of the Adler checksum generator with a specified value - /// - /// The value to set the current checksum to - public AdlerChecksum(uint initialValue) : base(initialValue) {} - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - public override void Update(byte[] data, int offset, int count) - { - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); - try - { - _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); - } - finally - { - hData.Free(); - } - } - - } - #endregion - -} \ No newline at end of file diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs deleted file mode 100644 index 9c8d601..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; - -namespace DotZLib -{ - - /// - /// This class implements a circular buffer - /// - internal class CircularBuffer - { - #region Private data - private int _capacity; - private int _head; - private int _tail; - private int _size; - private byte[] _buffer; - #endregion - - public CircularBuffer(int capacity) - { - Debug.Assert( capacity > 0 ); - _buffer = new byte[capacity]; - _capacity = capacity; - _head = 0; - _tail = 0; - _size = 0; - } - - public int Size { get { return _size; } } - - public int Put(byte[] source, int offset, int count) - { - Debug.Assert( count > 0 ); - int trueCount = Math.Min(count, _capacity - Size); - for (int i = 0; i < trueCount; ++i) - _buffer[(_tail+i) % _capacity] = source[offset+i]; - _tail += trueCount; - _tail %= _capacity; - _size += trueCount; - return trueCount; - } - - public bool Put(byte b) - { - if (Size == _capacity) // no room - return false; - _buffer[_tail++] = b; - _tail %= _capacity; - ++_size; - return true; - } - - public int Get(byte[] destination, int offset, int count) - { - int trueCount = Math.Min(count,Size); - for (int i = 0; i < trueCount; ++i) - destination[offset + i] = _buffer[(_head+i) % _capacity]; - _head += trueCount; - _head %= _capacity; - _size -= trueCount; - return trueCount; - } - - public int Get() - { - if (Size == 0) - return -1; - - int result = (int)_buffer[_head++ % _capacity]; - --_size; - return result; - } - - } -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs deleted file mode 100644 index b0eb78a..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs +++ /dev/null @@ -1,198 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - /// - /// Implements the common functionality needed for all s - /// - public abstract class CodecBase : Codec, IDisposable - { - - #region Data members - - /// - /// Instance of the internal zlib buffer structure that is - /// passed to all functions in the zlib dll - /// - internal ZStream _ztream = new ZStream(); - - /// - /// True if the object instance has been disposed, false otherwise - /// - protected bool _isDisposed = false; - - /// - /// The size of the internal buffers - /// - protected const int kBufferSize = 16384; - - private byte[] _outBuffer = new byte[kBufferSize]; - private byte[] _inBuffer = new byte[kBufferSize]; - - private GCHandle _hInput; - private GCHandle _hOutput; - - private uint _checksum = 0; - - #endregion - - /// - /// Initializes a new instance of the CodeBase class. - /// - public CodecBase() - { - try - { - _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); - _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); - } - catch (Exception) - { - CleanUp(false); - throw; - } - } - - - #region Codec Members - - /// - /// Occurs when more processed data are available. - /// - public event DataAvailableHandler DataAvailable; - - /// - /// Fires the event - /// - protected void OnDataAvailable() - { - if (_ztream.total_out > 0) - { - if (DataAvailable != null) - DataAvailable( _outBuffer, 0, (int)_ztream.total_out); - resetOutput(); - } - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// Adding data may, or may not, raise the DataAvailable event - public void Add(byte[] data) - { - Add(data,0,data.Length); - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - /// This must be implemented by a derived class - public abstract void Add(byte[] data, int offset, int count); - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - /// This must be implemented by a derived class - public abstract void Finish(); - - /// - /// Gets the checksum of the data that has been added so far - /// - public uint Checksum { get { return _checksum; } } - - #endregion - - #region Destructor & IDisposable stuff - - /// - /// Destroys this instance - /// - ~CodecBase() - { - CleanUp(false); - } - - /// - /// Releases any unmanaged resources and calls the method of the derived class - /// - public void Dispose() - { - CleanUp(true); - } - - /// - /// Performs any codec specific cleanup - /// - /// This must be implemented by a derived class - protected abstract void CleanUp(); - - // performs the release of the handles and calls the dereived CleanUp() - private void CleanUp(bool isDisposing) - { - if (!_isDisposed) - { - CleanUp(); - if (_hInput.IsAllocated) - _hInput.Free(); - if (_hOutput.IsAllocated) - _hOutput.Free(); - - _isDisposed = true; - } - } - - - #endregion - - #region Helper methods - - /// - /// Copies a number of bytes to the internal codec buffer - ready for proccesing - /// - /// The byte array that contains the data to copy - /// The index of the first byte to copy - /// The number of bytes to copy from data - protected void copyInput(byte[] data, int startIndex, int count) - { - Array.Copy(data, startIndex, _inBuffer,0, count); - _ztream.next_in = _hInput.AddrOfPinnedObject(); - _ztream.total_in = 0; - _ztream.avail_in = (uint)count; - - } - - /// - /// Resets the internal output buffers to a known state - ready for processing - /// - protected void resetOutput() - { - _ztream.total_out = 0; - _ztream.avail_out = kBufferSize; - _ztream.next_out = _hOutput.AddrOfPinnedObject(); - } - - /// - /// Updates the running checksum property - /// - /// The new checksum value - protected void setChecksum(uint newSum) - { - _checksum = newSum; - } - #endregion - - } -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs deleted file mode 100644 index 9039f41..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs +++ /dev/null @@ -1,106 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - - /// - /// Implements a data compressor, using the deflate algorithm in the ZLib dll - /// - public sealed class Deflater : CodecBase - { - #region Dll imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflate(ref ZStream sz, int flush); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflateReset(ref ZStream sz); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int deflateEnd(ref ZStream sz); - #endregion - - /// - /// Constructs an new instance of the Deflater - /// - /// The compression level to use for this Deflater - public Deflater(CompressLevel level) : base() - { - int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); - if (retval != 0) - throw new ZLibException(retval, "Could not initialize deflater"); - - resetOutput(); - } - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - public override void Add(byte[] data, int offset, int count) - { - if (data == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - - int total = count; - int inputIndex = offset; - int err = 0; - - while (err >= 0 && inputIndex < total) - { - copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); - while (err >= 0 && _ztream.avail_in > 0) - { - err = deflate(ref _ztream, (int)FlushTypes.None); - if (err == 0) - while (_ztream.avail_out == 0) - { - OnDataAvailable(); - err = deflate(ref _ztream, (int)FlushTypes.None); - } - inputIndex += (int)_ztream.total_in; - } - } - setChecksum( _ztream.adler ); - } - - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - public override void Finish() - { - int err; - do - { - err = deflate(ref _ztream, (int)FlushTypes.Finish); - OnDataAvailable(); - } - while (err == 0); - setChecksum( _ztream.adler ); - deflateReset(ref _ztream); - resetOutput(); - } - - /// - /// Closes the internal zlib deflate stream - /// - protected override void CleanUp() { deflateEnd(ref _ztream); } - - } -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs deleted file mode 100644 index 90c7c3b..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs +++ /dev/null @@ -1,288 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; - - -namespace DotZLib -{ - - #region Internal types - - /// - /// Defines constants for the various flush types used with zlib - /// - internal enum FlushTypes - { - None, Partial, Sync, Full, Finish, Block - } - - #region ZStream structure - // internal mapping of the zlib zstream structure for marshalling - [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] - internal struct ZStream - { - public IntPtr next_in; - public uint avail_in; - public uint total_in; - - public IntPtr next_out; - public uint avail_out; - public uint total_out; - - [MarshalAs(UnmanagedType.LPStr)] - string msg; - uint state; - - uint zalloc; - uint zfree; - uint opaque; - - int data_type; - public uint adler; - uint reserved; - } - - #endregion - - #endregion - - #region Public enums - /// - /// Defines constants for the available compression levels in zlib - /// - public enum CompressLevel : int - { - /// - /// The default compression level with a reasonable compromise between compression and speed - /// - Default = -1, - /// - /// No compression at all. The data are passed straight through. - /// - None = 0, - /// - /// The maximum compression rate available. - /// - Best = 9, - /// - /// The fastest available compression level. - /// - Fastest = 1 - } - #endregion - - #region Exception classes - /// - /// The exception that is thrown when an error occurs on the zlib dll - /// - public class ZLibException : ApplicationException - { - /// - /// Initializes a new instance of the class with a specified - /// error message and error code - /// - /// The zlib error code that caused the exception - /// A message that (hopefully) describes the error - public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) - { - } - - /// - /// Initializes a new instance of the class with a specified - /// error code - /// - /// The zlib error code that caused the exception - public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) - { - } - } - #endregion - - #region Interfaces - - /// - /// Declares methods and properties that enables a running checksum to be calculated - /// - public interface ChecksumGenerator - { - /// - /// Gets the current value of the checksum - /// - uint Value { get; } - - /// - /// Clears the current checksum to 0 - /// - void Reset(); - - /// - /// Updates the current checksum with an array of bytes - /// - /// The data to update the checksum with - void Update(byte[] data); - - /// - /// Updates the current checksum with part of an array of bytes - /// - /// The data to update the checksum with - /// Where in data to start updating - /// The number of bytes from data to use - /// The sum of offset and count is larger than the length of data - /// data is a null reference - /// Offset or count is negative. - void Update(byte[] data, int offset, int count); - - /// - /// Updates the current checksum with the data from a string - /// - /// The string to update the checksum with - /// The characters in the string are converted by the UTF-8 encoding - void Update(string data); - - /// - /// Updates the current checksum with the data from a string, using a specific encoding - /// - /// The string to update the checksum with - /// The encoding to use - void Update(string data, Encoding encoding); - } - - - /// - /// Represents the method that will be called from a codec when new data - /// are available. - /// - /// The byte array containing the processed data - /// The index of the first processed byte in data - /// The number of processed bytes available - /// On return from this method, the data may be overwritten, so grab it while you can. - /// You cannot assume that startIndex will be zero. - /// - public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); - - /// - /// Declares methods and events for implementing compressors/decompressors - /// - public interface Codec - { - /// - /// Occurs when more processed data are available. - /// - event DataAvailableHandler DataAvailable; - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// Adding data may, or may not, raise the DataAvailable event - void Add(byte[] data); - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - void Add(byte[] data, int offset, int count); - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - void Finish(); - - /// - /// Gets the checksum of the data that has been added so far - /// - uint Checksum { get; } - - - } - - #endregion - - #region Classes - /// - /// Encapsulates general information about the ZLib library - /// - public class Info - { - #region DLL imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern uint zlibCompileFlags(); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern string zlibVersion(); - #endregion - - #region Private stuff - private uint _flags; - - // helper function that unpacks a bitsize mask - private static int bitSize(uint bits) - { - switch (bits) - { - case 0: return 16; - case 1: return 32; - case 2: return 64; - } - return -1; - } - #endregion - - /// - /// Constructs an instance of the Info class. - /// - public Info() - { - _flags = zlibCompileFlags(); - } - - /// - /// True if the library is compiled with debug info - /// - public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } - - /// - /// True if the library is compiled with assembly optimizations - /// - public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } - - /// - /// Gets the size of the unsigned int that was compiled into Zlib - /// - public int SizeOfUInt { get { return bitSize(_flags & 3); } } - - /// - /// Gets the size of the unsigned long that was compiled into Zlib - /// - public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } - - /// - /// Gets the size of the pointers that were compiled into Zlib - /// - public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } - - /// - /// Gets the size of the z_off_t type that was compiled into Zlib - /// - public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } - - /// - /// Gets the version of ZLib as a string, e.g. "1.2.1" - /// - public static string Version { get { return zlibVersion(); } } - } - - #endregion - -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj b/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj deleted file mode 100644 index dea7fb1..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs deleted file mode 100644 index f0eada1..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs +++ /dev/null @@ -1,301 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - /// - /// Implements a compressed , in GZip (.gz) format. - /// - public class GZipStream : Stream, IDisposable - { - #region Dll Imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern IntPtr gzopen(string name, string mode); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzclose(IntPtr gzFile); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzwrite(IntPtr gzFile, int data, int length); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzread(IntPtr gzFile, int data, int length); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzgetc(IntPtr gzFile); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int gzputc(IntPtr gzFile, int c); - - #endregion - - #region Private data - private IntPtr _gzFile; - private bool _isDisposed = false; - private bool _isWriting; - #endregion - - #region Constructors - /// - /// Creates a new file as a writeable GZipStream - /// - /// The name of the compressed file to create - /// The compression level to use when adding data - /// If an error occurred in the internal zlib function - public GZipStream(string fileName, CompressLevel level) - { - _isWriting = true; - _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); - if (_gzFile == IntPtr.Zero) - throw new ZLibException(-1, "Could not open " + fileName); - } - - /// - /// Opens an existing file as a readable GZipStream - /// - /// The name of the file to open - /// If an error occurred in the internal zlib function - public GZipStream(string fileName) - { - _isWriting = false; - _gzFile = gzopen(fileName, "rb"); - if (_gzFile == IntPtr.Zero) - throw new ZLibException(-1, "Could not open " + fileName); - - } - #endregion - - #region Access properties - /// - /// Returns true of this stream can be read from, false otherwise - /// - public override bool CanRead - { - get - { - return !_isWriting; - } - } - - - /// - /// Returns false. - /// - public override bool CanSeek - { - get - { - return false; - } - } - - /// - /// Returns true if this tsream is writeable, false otherwise - /// - public override bool CanWrite - { - get - { - return _isWriting; - } - } - #endregion - - #region Destructor & IDispose stuff - - /// - /// Destroys this instance - /// - ~GZipStream() - { - cleanUp(false); - } - - /// - /// Closes the external file handle - /// - public void Dispose() - { - cleanUp(true); - } - - // Does the actual closing of the file handle. - private void cleanUp(bool isDisposing) - { - if (!_isDisposed) - { - gzclose(_gzFile); - _isDisposed = true; - } - } - #endregion - - #region Basic reading and writing - /// - /// Attempts to read a number of bytes from the stream. - /// - /// The destination data buffer - /// The index of the first destination byte in buffer - /// The number of bytes requested - /// The number of bytes read - /// If buffer is null - /// If count or offset are negative - /// If offset + count is > buffer.Length - /// If this stream is not readable. - /// If this stream has been disposed. - public override int Read(byte[] buffer, int offset, int count) - { - if (!CanRead) throw new NotSupportedException(); - if (buffer == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > buffer.Length) throw new ArgumentException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); - int result; - try - { - result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); - if (result < 0) - throw new IOException(); - } - finally - { - h.Free(); - } - return result; - } - - /// - /// Attempts to read a single byte from the stream. - /// - /// The byte that was read, or -1 in case of error or End-Of-File - public override int ReadByte() - { - if (!CanRead) throw new NotSupportedException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - return gzgetc(_gzFile); - } - - /// - /// Writes a number of bytes to the stream - /// - /// - /// - /// - /// If buffer is null - /// If count or offset are negative - /// If offset + count is > buffer.Length - /// If this stream is not writeable. - /// If this stream has been disposed. - public override void Write(byte[] buffer, int offset, int count) - { - if (!CanWrite) throw new NotSupportedException(); - if (buffer == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > buffer.Length) throw new ArgumentException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); - try - { - int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); - if (result < 0) - throw new IOException(); - } - finally - { - h.Free(); - } - } - - /// - /// Writes a single byte to the stream - /// - /// The byte to add to the stream. - /// If this stream is not writeable. - /// If this stream has been disposed. - public override void WriteByte(byte value) - { - if (!CanWrite) throw new NotSupportedException(); - if (_isDisposed) throw new ObjectDisposedException("GZipStream"); - - int result = gzputc(_gzFile, (int)value); - if (result < 0) - throw new IOException(); - } - #endregion - - #region Position & length stuff - /// - /// Not supported. - /// - /// - /// Always thrown - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// - /// Not suppported. - /// - /// - /// - /// - /// Always thrown - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - /// Flushes the GZipStream. - /// - /// In this implementation, this method does nothing. This is because excessive - /// flushing may degrade the achievable compression rates. - public override void Flush() - { - // left empty on purpose - } - - /// - /// Gets/sets the current position in the GZipStream. Not suppported. - /// - /// In this implementation this property is not supported - /// Always thrown - public override long Position - { - get - { - throw new NotSupportedException(); - } - set - { - throw new NotSupportedException(); - } - } - - /// - /// Gets the size of the stream. Not suppported. - /// - /// In this implementation this property is not supported - /// Always thrown - public override long Length - { - get - { - throw new NotSupportedException(); - } - } - #endregion - } -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs deleted file mode 100644 index d295f26..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace DotZLib -{ - - /// - /// Implements a data decompressor, using the inflate algorithm in the ZLib dll - /// - public class Inflater : CodecBase - { - #region Dll imports - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] - private static extern int inflateInit_(ref ZStream sz, string vs, int size); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflate(ref ZStream sz, int flush); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflateReset(ref ZStream sz); - - [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] - private static extern int inflateEnd(ref ZStream sz); - #endregion - - /// - /// Constructs an new instance of the Inflater - /// - public Inflater() : base() - { - int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); - if (retval != 0) - throw new ZLibException(retval, "Could not initialize inflater"); - - resetOutput(); - } - - - /// - /// Adds more data to the codec to be processed. - /// - /// Byte array containing the data to be added to the codec - /// The index of the first byte to add from data - /// The number of bytes to add - /// Adding data may, or may not, raise the DataAvailable event - public override void Add(byte[] data, int offset, int count) - { - if (data == null) throw new ArgumentNullException(); - if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); - if ((offset+count) > data.Length) throw new ArgumentException(); - - int total = count; - int inputIndex = offset; - int err = 0; - - while (err >= 0 && inputIndex < total) - { - copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); - err = inflate(ref _ztream, (int)FlushTypes.None); - if (err == 0) - while (_ztream.avail_out == 0) - { - OnDataAvailable(); - err = inflate(ref _ztream, (int)FlushTypes.None); - } - - inputIndex += (int)_ztream.total_in; - } - setChecksum( _ztream.adler ); - } - - - /// - /// Finishes up any pending data that needs to be processed and handled. - /// - public override void Finish() - { - int err; - do - { - err = inflate(ref _ztream, (int)FlushTypes.Finish); - OnDataAvailable(); - } - while (err == 0); - setChecksum( _ztream.adler ); - inflateReset(ref _ztream); - resetOutput(); - } - - /// - /// Closes the internal zlib inflate stream - /// - protected override void CleanUp() { inflateEnd(ref _ztream); } - - - } -} diff --git a/src/contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/src/contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs deleted file mode 100644 index 6d8aebb..0000000 --- a/src/contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs +++ /dev/null @@ -1,274 +0,0 @@ -// -// © Copyright Henrik Ravn 2004 -// -// Use, modification and distribution are subject to the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -using System; -using System.Collections; -using System.IO; - -// uncomment the define below to include unit tests -//#define nunit -#if nunit -using NUnit.Framework; - -// Unit tests for the DotZLib class library -// ---------------------------------------- -// -// Use this with NUnit 2 from http://www.nunit.org -// - -namespace DotZLibTests -{ - using DotZLib; - - // helper methods - internal class Utils - { - public static bool byteArrEqual( byte[] lhs, byte[] rhs ) - { - if (lhs.Length != rhs.Length) - return false; - for (int i = lhs.Length-1; i >= 0; --i) - if (lhs[i] != rhs[i]) - return false; - return true; - } - - } - - - [TestFixture] - public class CircBufferTests - { - #region Circular buffer tests - [Test] - public void SinglePutGet() - { - CircularBuffer buf = new CircularBuffer(10); - Assert.AreEqual( 0, buf.Size ); - Assert.AreEqual( -1, buf.Get() ); - - Assert.IsTrue(buf.Put( 1 )); - Assert.AreEqual( 1, buf.Size ); - Assert.AreEqual( 1, buf.Get() ); - Assert.AreEqual( 0, buf.Size ); - Assert.AreEqual( -1, buf.Get() ); - } - - [Test] - public void BlockPutGet() - { - CircularBuffer buf = new CircularBuffer(10); - byte[] arr = {1,2,3,4,5,6,7,8,9,10}; - Assert.AreEqual( 10, buf.Put(arr,0,10) ); - Assert.AreEqual( 10, buf.Size ); - Assert.IsFalse( buf.Put(11) ); - Assert.AreEqual( 1, buf.Get() ); - Assert.IsTrue( buf.Put(11) ); - - byte[] arr2 = (byte[])arr.Clone(); - Assert.AreEqual( 9, buf.Get(arr2,1,9) ); - Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); - } - - #endregion - } - - [TestFixture] - public class ChecksumTests - { - #region CRC32 Tests - [Test] - public void CRC32_Null() - { - CRC32Checksum crc32 = new CRC32Checksum(); - Assert.AreEqual( 0, crc32.Value ); - - crc32 = new CRC32Checksum(1); - Assert.AreEqual( 1, crc32.Value ); - - crc32 = new CRC32Checksum(556); - Assert.AreEqual( 556, crc32.Value ); - } - - [Test] - public void CRC32_Data() - { - CRC32Checksum crc32 = new CRC32Checksum(); - byte[] data = { 1,2,3,4,5,6,7 }; - crc32.Update(data); - Assert.AreEqual( 0x70e46888, crc32.Value ); - - crc32 = new CRC32Checksum(); - crc32.Update("penguin"); - Assert.AreEqual( 0x0e5c1a120, crc32.Value ); - - crc32 = new CRC32Checksum(1); - crc32.Update("penguin"); - Assert.AreEqual(0x43b6aa94, crc32.Value); - - } - #endregion - - #region Adler tests - - [Test] - public void Adler_Null() - { - AdlerChecksum adler = new AdlerChecksum(); - Assert.AreEqual(0, adler.Value); - - adler = new AdlerChecksum(1); - Assert.AreEqual( 1, adler.Value ); - - adler = new AdlerChecksum(556); - Assert.AreEqual( 556, adler.Value ); - } - - [Test] - public void Adler_Data() - { - AdlerChecksum adler = new AdlerChecksum(1); - byte[] data = { 1,2,3,4,5,6,7 }; - adler.Update(data); - Assert.AreEqual( 0x5b001d, adler.Value ); - - adler = new AdlerChecksum(); - adler.Update("penguin"); - Assert.AreEqual(0x0bcf02f6, adler.Value ); - - adler = new AdlerChecksum(1); - adler.Update("penguin"); - Assert.AreEqual(0x0bd602f7, adler.Value); - - } - #endregion - } - - [TestFixture] - public class InfoTests - { - #region Info tests - [Test] - public void Info_Version() - { - Info info = new Info(); - Assert.AreEqual("1.2.11", Info.Version); - Assert.AreEqual(32, info.SizeOfUInt); - Assert.AreEqual(32, info.SizeOfULong); - Assert.AreEqual(32, info.SizeOfPointer); - Assert.AreEqual(32, info.SizeOfOffset); - } - #endregion - } - - [TestFixture] - public class DeflateInflateTests - { - #region Deflate tests - [Test] - public void Deflate_Init() - { - using (Deflater def = new Deflater(CompressLevel.Default)) - { - } - } - - private ArrayList compressedData = new ArrayList(); - private uint adler1; - - private ArrayList uncompressedData = new ArrayList(); - private uint adler2; - - public void CDataAvail(byte[] data, int startIndex, int count) - { - for (int i = 0; i < count; ++i) - compressedData.Add(data[i+startIndex]); - } - - [Test] - public void Deflate_Compress() - { - compressedData.Clear(); - - byte[] testData = new byte[35000]; - for (int i = 0; i < testData.Length; ++i) - testData[i] = 5; - - using (Deflater def = new Deflater((CompressLevel)5)) - { - def.DataAvailable += new DataAvailableHandler(CDataAvail); - def.Add(testData); - def.Finish(); - adler1 = def.Checksum; - } - } - #endregion - - #region Inflate tests - [Test] - public void Inflate_Init() - { - using (Inflater inf = new Inflater()) - { - } - } - - private void DDataAvail(byte[] data, int startIndex, int count) - { - for (int i = 0; i < count; ++i) - uncompressedData.Add(data[i+startIndex]); - } - - [Test] - public void Inflate_Expand() - { - uncompressedData.Clear(); - - using (Inflater inf = new Inflater()) - { - inf.DataAvailable += new DataAvailableHandler(DDataAvail); - inf.Add((byte[])compressedData.ToArray(typeof(byte))); - inf.Finish(); - adler2 = inf.Checksum; - } - Assert.AreEqual( adler1, adler2 ); - } - #endregion - } - - [TestFixture] - public class GZipStreamTests - { - #region GZipStream test - [Test] - public void GZipStream_WriteRead() - { - using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) - { - BinaryWriter writer = new BinaryWriter(gzOut); - writer.Write("hi there"); - writer.Write(Math.PI); - writer.Write(42); - } - - using (GZipStream gzIn = new GZipStream("gzstream.gz")) - { - BinaryReader reader = new BinaryReader(gzIn); - string s = reader.ReadString(); - Assert.AreEqual("hi there",s); - double d = reader.ReadDouble(); - Assert.AreEqual(Math.PI, d); - int i = reader.ReadInt32(); - Assert.AreEqual(42,i); - } - - } - #endregion - } -} - -#endif diff --git a/src/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt b/src/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt deleted file mode 100644 index 127a5bc..0000000 --- a/src/contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/src/contrib/zlib/contrib/dotzlib/readme.txt b/src/contrib/zlib/contrib/dotzlib/readme.txt deleted file mode 100644 index 4d8c2dd..0000000 --- a/src/contrib/zlib/contrib/dotzlib/readme.txt +++ /dev/null @@ -1,58 +0,0 @@ -This directory contains a .Net wrapper class library for the ZLib1.dll - -The wrapper includes support for inflating/deflating memory buffers, -.Net streaming wrappers for the gz streams part of zlib, and wrappers -for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. - -Directory structure: --------------------- - -LICENSE_1_0.txt - License file. -readme.txt - This file. -DotZLib.chm - Class library documentation -DotZLib.build - NAnt build file -DotZLib.sln - Microsoft Visual Studio 2003 solution file - -DotZLib\*.cs - Source files for the class library - -Unit tests: ------------ -The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. -To include unit tests in the build, define nunit before building. - - -Build instructions: -------------------- - -1. Using Visual Studio.Net 2003: - Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) - will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on - you are building the release or debug version of the library. Check - DotZLib/UnitTests.cs for instructions on how to include unit tests in the - build. - -2. Using NAnt: - Open a command prompt with access to the build environment and run nant - in the same directory as the DotZLib.build file. - You can define 2 properties on the nant command-line to control the build: - debug={true|false} to toggle between release/debug builds (default=true). - nunit={true|false} to include or esclude unit tests (default=true). - Also the target clean will remove binaries. - Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release - or ./DotZLib/bin/debug, depending on whether you are building the release - or debug version of the library. - - Examples: - nant -D:debug=false -D:nunit=false - will build a release mode version of the library without unit tests. - nant - will build a debug version of the library with unit tests - nant clean - will remove all previously built files. - - ---------------------------------- -Copyright (c) Henrik Ravn 2004 - -Use, modification and distribution are subject to the Boost Software License, Version 1.0. -(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/src/contrib/zlib/contrib/gcc_gvmat64/gvmat64.S b/src/contrib/zlib/contrib/gcc_gvmat64/gvmat64.S deleted file mode 100644 index 23309fa..0000000 --- a/src/contrib/zlib/contrib/gcc_gvmat64/gvmat64.S +++ /dev/null @@ -1,574 +0,0 @@ -/* -;uInt longest_match_x64( -; deflate_state *s, -; IPos cur_match); // current match - -; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 -; (AMD64 on Athlon 64, Opteron, Phenom -; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) -; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) -; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; -; File written by Gilles Vollant, by converting to assembly the longest_match -; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. -; and by taking inspiration on asm686 with masm, optimised assembly code -; from Brian Raiter, written 1998 -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software -; 3. This notice may not be removed or altered from any source distribution. -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; to compile this file for zLib, I use option: -; gcc -c -arch x86_64 gvmat64.S - - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; // current match / -; -; with XCode for Mac, I had strange error with some jump on intel syntax -; this is why BEFORE_JMP and AFTER_JMP are used - */ - - -#define BEFORE_JMP .att_syntax -#define AFTER_JMP .intel_syntax noprefix - -#ifndef NO_UNDERLINE -# define match_init _match_init -# define longest_match _longest_match -#endif - -.intel_syntax noprefix - -.globl match_init, longest_match -.text -longest_match: - - - -#define LocalVarsSize 96 -/* -; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 -; free register : r14,r15 -; register can be saved : rsp -*/ - -#define chainlenwmask (rsp + 8 - LocalVarsSize) -#define nicematch (rsp + 16 - LocalVarsSize) - -#define save_rdi (rsp + 24 - LocalVarsSize) -#define save_rsi (rsp + 32 - LocalVarsSize) -#define save_rbx (rsp + 40 - LocalVarsSize) -#define save_rbp (rsp + 48 - LocalVarsSize) -#define save_r12 (rsp + 56 - LocalVarsSize) -#define save_r13 (rsp + 64 - LocalVarsSize) -#define save_r14 (rsp + 72 - LocalVarsSize) -#define save_r15 (rsp + 80 - LocalVarsSize) - - -/* -; all the +4 offsets are due to the addition of pending_buf_size (in zlib -; in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, remove the +4). -; Note : these value are good with a 8 bytes boundary pack structure -*/ - -#define MAX_MATCH 258 -#define MIN_MATCH 3 -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) - -/* -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). -*/ - - - -/* you can check the structure offset by running - -#include -#include -#include "deflate.h" - -void print_depl() -{ -deflate_state ds; -deflate_state *s=&ds; -printf("size pointer=%u\n",(int)sizeof(void*)); - -printf("#define dsWSize %u\n",(int)(((char*)&(s->w_size))-((char*)s))); -printf("#define dsWMask %u\n",(int)(((char*)&(s->w_mask))-((char*)s))); -printf("#define dsWindow %u\n",(int)(((char*)&(s->window))-((char*)s))); -printf("#define dsPrev %u\n",(int)(((char*)&(s->prev))-((char*)s))); -printf("#define dsMatchLen %u\n",(int)(((char*)&(s->match_length))-((char*)s))); -printf("#define dsPrevMatch %u\n",(int)(((char*)&(s->prev_match))-((char*)s))); -printf("#define dsStrStart %u\n",(int)(((char*)&(s->strstart))-((char*)s))); -printf("#define dsMatchStart %u\n",(int)(((char*)&(s->match_start))-((char*)s))); -printf("#define dsLookahead %u\n",(int)(((char*)&(s->lookahead))-((char*)s))); -printf("#define dsPrevLen %u\n",(int)(((char*)&(s->prev_length))-((char*)s))); -printf("#define dsMaxChainLen %u\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); -printf("#define dsGoodMatch %u\n",(int)(((char*)&(s->good_match))-((char*)s))); -printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s))); -} -*/ - -#define dsWSize 68 -#define dsWMask 76 -#define dsWindow 80 -#define dsPrev 96 -#define dsMatchLen 144 -#define dsPrevMatch 148 -#define dsStrStart 156 -#define dsMatchStart 160 -#define dsLookahead 164 -#define dsPrevLen 168 -#define dsMaxChainLen 172 -#define dsGoodMatch 188 -#define dsNiceMatch 192 - -#define window_size [ rcx + dsWSize] -#define WMask [ rcx + dsWMask] -#define window_ad [ rcx + dsWindow] -#define prev_ad [ rcx + dsPrev] -#define strstart [ rcx + dsStrStart] -#define match_start [ rcx + dsMatchStart] -#define Lookahead [ rcx + dsLookahead] //; 0ffffffffh on infozip -#define prev_length [ rcx + dsPrevLen] -#define max_chain_length [ rcx + dsMaxChainLen] -#define good_match [ rcx + dsGoodMatch] -#define nice_match [ rcx + dsNiceMatch] - -/* -; windows: -; parameter 1 in rcx(deflate state s), param 2 in rdx (cur match) - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. - -; -; gcc on macosx-linux: -; see http://www.x86-64.org/documentation/abi-0.99.pdf -; param 1 in rdi, param 2 in rsi -; rbx, rsp, rbp, r12 to r15 must be preserved - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - -;;; Retrieve the function arguments. r8d will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - -; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) -; mac: param 1 in rdi, param 2 rsi -; this clear high 32 bits of r8, which can be garbage in both r8 and rdx -*/ - mov [save_rbx],rbx - mov [save_rbp],rbp - - - mov rcx,rdi - - mov r8d,esi - - - mov [save_r12],r12 - mov [save_r13],r13 - mov [save_r14],r14 - mov [save_r15],r15 - - -//;;; uInt wmask = s->w_mask; -//;;; unsigned chain_length = s->max_chain_length; -//;;; if (s->prev_length >= s->good_match) { -//;;; chain_length >>= 2; -//;;; } - - - mov edi, prev_length - mov esi, good_match - mov eax, WMask - mov ebx, max_chain_length - cmp edi, esi - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -//;;; chainlen is decremented once beforehand so that the function can -//;;; use the sign flag instead of the zero flag for the exit test. -//;;; It is then shifted into the high word, to make room for the wmask -//;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - -//;;; on zlib only -//;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - - - mov eax, nice_match - mov [chainlenwmask], ebx - mov r10d, Lookahead - cmp r10d, eax - cmovnl r10d, eax - mov [nicematch],r10d - - - -//;;; register Bytef *scan = s->window + s->strstart; - mov r10, window_ad - mov ebp, strstart - lea r13, [r10 + rbp] - -//;;; Determine how many bytes the scan ptr is off from being -//;;; dword-aligned. - - mov r9,r13 - neg r13 - and r13,3 - -//;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -//;;; s->strstart - (IPos)MAX_DIST(s) : NIL; - - - mov eax, window_size - sub eax, MIN_LOOKAHEAD - - - xor edi,edi - sub ebp, eax - - mov r11d, prev_length - - cmovng ebp,edi - -//;;; int best_len = s->prev_length; - - -//;;; Store the sum of s->window + best_len in esi locally, and in esi. - - lea rsi,[r10+r11] - -//;;; register ush scan_start = *(ushf*)scan; -//;;; register ush scan_end = *(ushf*)(scan+best_len-1); -//;;; Posf *prev = s->prev; - - movzx r12d,word ptr [r9] - movzx ebx, word ptr [r9 + r11 - 1] - - mov rdi, prev_ad - -//;;; Jump into the main loop. - - mov edx, [chainlenwmask] - - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - - - -LookupLoop1: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - - - - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry1: - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jz LookupLoopIsZero - AFTER_JMP - -LookupLoop2: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry2: - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jz LookupLoopIsZero - AFTER_JMP - -LookupLoop4: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry4: - - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jnz LookupLoop1 - jmp LookupLoopIsZero - AFTER_JMP -/* -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; r8d = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit -*/ -.balign 16 -LookupLoop: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - BEFORE_JMP - jbe LeaveNow - AFTER_JMP - sub edx, 0x00010000 - BEFORE_JMP - js LeaveNow - AFTER_JMP - -LoopEntry: - - cmp bx,word ptr [rsi + r8 - 1] - BEFORE_JMP - jnz LookupLoop1 - AFTER_JMP -LookupLoopIsZero: - cmp r12w, word ptr [r10 + r8] - BEFORE_JMP - jnz LookupLoop1 - AFTER_JMP - - -//;;; Store the current value of chainlen. - mov [chainlenwmask], edx -/* -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). -*/ - lea rsi,[r8+r10] - mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8) - lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8] - lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8] - - prefetcht1 [rsi+rdx] - prefetcht1 [rdi+rdx] - -/* -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust rdx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (rsi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. -*/ - -LoopCmps: - mov rax, [rsi + rdx] - xor rax, [rdi + rdx] - jnz LeaveLoopCmps - - mov rax, [rsi + rdx + 8] - xor rax, [rdi + rdx + 8] - jnz LeaveLoopCmps8 - - - mov rax, [rsi + rdx + 8+8] - xor rax, [rdi + rdx + 8+8] - jnz LeaveLoopCmps16 - - add rdx,8+8+8 - - BEFORE_JMP - jnz LoopCmps - jmp LenMaximum - AFTER_JMP - -LeaveLoopCmps16: add rdx,8 -LeaveLoopCmps8: add rdx,8 -LeaveLoopCmps: - - test eax, 0x0000FFFF - jnz LenLower - - test eax,0xffffffff - - jnz LenLower32 - - add rdx,4 - shr rax,32 - or ax,ax - BEFORE_JMP - jnz LenLower - AFTER_JMP - -LenLower32: - shr eax,16 - add rdx,2 - -LenLower: - sub al, 1 - adc rdx, 0 -//;;; Calculate the length of the match. If it is longer than MAX_MATCH, -//;;; then automatically accept it as the best possible match and leave. - - lea rax, [rdi + rdx] - sub rax, r9 - cmp eax, MAX_MATCH - BEFORE_JMP - jge LenMaximum - AFTER_JMP -/* -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. -;/////////////////////////////////// -*/ - cmp eax, r11d - jg LongerMatch - - lea rsi,[r10+r11] - - mov rdi, prev_ad - mov edx, [chainlenwmask] - BEFORE_JMP - jmp LookupLoop - AFTER_JMP -/* -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); -*/ -LongerMatch: - mov r11d, eax - mov match_start, r8d - cmp eax, [nicematch] - BEFORE_JMP - jge LeaveNow - AFTER_JMP - - lea rsi,[r10+rax] - - movzx ebx, word ptr [r9 + rax - 1] - mov rdi, prev_ad - mov edx, [chainlenwmask] - BEFORE_JMP - jmp LookupLoop - AFTER_JMP - -//;;; Accept the current string, with the maximum possible length. - -LenMaximum: - mov r11d,MAX_MATCH - mov match_start, r8d - -//;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -//;;; return s->lookahead; - -LeaveNow: - mov eax, Lookahead - cmp r11d, eax - cmovng eax, r11d - - - -//;;; Restore the stack and return from whence we came. - - -// mov rsi,[save_rsi] -// mov rdi,[save_rdi] - mov rbx,[save_rbx] - mov rbp,[save_rbp] - mov r12,[save_r12] - mov r13,[save_r13] - mov r14,[save_r14] - mov r15,[save_r15] - - - ret 0 -//; please don't remove this string ! -//; Your can freely use gvmat64 in any free or commercial app -//; but it is far better don't remove the string in the binary! - // db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 - - -match_init: - ret 0 - - diff --git a/src/contrib/zlib/contrib/infback9/README b/src/contrib/zlib/contrib/infback9/README deleted file mode 100644 index e75ed13..0000000 --- a/src/contrib/zlib/contrib/infback9/README +++ /dev/null @@ -1 +0,0 @@ -See infback9.h for what this is and how to use it. diff --git a/src/contrib/zlib/contrib/infback9/infback9.c b/src/contrib/zlib/contrib/infback9/infback9.c deleted file mode 100644 index 05fb3e3..0000000 --- a/src/contrib/zlib/contrib/infback9/infback9.c +++ /dev/null @@ -1,615 +0,0 @@ -/* infback9.c -- inflate deflate64 data using a call-back interface - * Copyright (C) 1995-2008 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infback9.h" -#include "inftree9.h" -#include "inflate9.h" - -#define WSIZE 65536UL - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - window is a user-supplied window and output buffer that is 64K bytes. - */ -int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) -z_stream FAR *strm; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (voidpf)state; - state->window = window; - return Z_OK; -} - -/* - Build and output length and distance decoding tables for fixed code - decoding. - */ -#ifdef MAKEFIXED -#include - -void makefixed9(void) -{ - unsigned sym, bits, low, size; - code *next, *lenfix, *distfix; - struct inflate_state state; - code fixed[544]; - - /* literal/length table */ - sym = 0; - while (sym < 144) state.lens[sym++] = 8; - while (sym < 256) state.lens[sym++] = 9; - while (sym < 280) state.lens[sym++] = 7; - while (sym < 288) state.lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work); - - /* distance table */ - sym = 0; - while (sym < 32) state.lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work); - - /* write tables */ - puts(" /* inffix9.h -- table for decoding deflate64 fixed codes"); - puts(" * Generated automatically by makefixed9()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits, - lenfix[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 5) == 0) printf("\n "); - printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits, - distfix[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* Macros for inflateBack(): */ - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n <= 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = window; \ - left = WSIZE; \ - wrap = 1; \ - if (out(out_desc, put, (unsigned)left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) -z_stream FAR *strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have; /* available input */ - unsigned long left; /* available output */ - inflate_mode mode; /* current inflate mode */ - int lastblock; /* true if processing last block */ - int wrap; /* true if the window has wrapped */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned extra; /* extra bits needed */ - unsigned long length; /* literal or length of data to copy */ - unsigned long offset; /* distance back to copy string from */ - unsigned long copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; -#include "inffix9.h" - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - mode = TYPE; - lastblock = 0; - wrap = 0; - window = state->window; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = window; - left = WSIZE; - lencode = Z_NULL; - distcode = Z_NULL; - - /* Inflate until end of block marked as last */ - for (;;) - switch (mode) { - case TYPE: - /* determine and dispatch block type */ - if (lastblock) { - BYTEBITS(); - mode = DONE; - break; - } - NEEDBITS(3); - lastblock = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - lastblock ? " (last)" : "")); - mode = STORED; - break; - case 1: /* fixed block */ - lencode = lenfix; - lenbits = 9; - distcode = distfix; - distbits = 5; - Tracev((stderr, "inflate: fixed codes block%s\n", - lastblock ? " (last)" : "")); - mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - lastblock ? " (last)" : "")); - mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - mode = BAD; - break; - } - length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %lu\n", - length)); - INITBITS(); - - /* copy stored block from input to output */ - while (length != 0) { - copy = length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); - if (state->nlen > 286) { - strm->msg = (char *)"too many length symbols"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - lencode = (code const FAR *)(state->next); - lenbits = 7; - ret = inflate_table9(CODES, state->lens, 19, &(state->next), - &(lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = lencode[BITS(lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - NEEDBITS(here.bits); - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftree9.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - lencode = (code const FAR *)(state->next); - lenbits = 9; - ret = inflate_table9(LENS, state->lens, state->nlen, - &(state->next), &(lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - mode = BAD; - break; - } - distcode = (code const FAR *)(state->next); - distbits = 6; - ret = inflate_table9(DISTS, state->lens + state->nlen, - state->ndist, &(state->next), &(distbits), - state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - mode = LEN; - - case LEN: - /* get a literal, length, or end-of-block code */ - for (;;) { - here = lencode[BITS(lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(length); - left--; - mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - extra = (unsigned)(here.op) & 31; - if (extra != 0) { - NEEDBITS(extra); - length += BITS(extra); - DROPBITS(extra); - } - Tracevv((stderr, "inflate: length %lu\n", length)); - - /* get distance code */ - for (;;) { - here = distcode[BITS(distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - mode = BAD; - break; - } - offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - extra = (unsigned)(here.op) & 15; - if (extra != 0) { - NEEDBITS(extra); - offset += BITS(extra); - DROPBITS(extra); - } - if (offset > WSIZE - (wrap ? 0: left)) { - strm->msg = (char *)"invalid distance too far back"; - mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %lu\n", offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = WSIZE - offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - offset; - copy = left; - } - if (copy > length) copy = length; - length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < WSIZE) { - if (out(out_desc, window, (unsigned)(WSIZE - left))) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBack9End(strm) -z_stream FAR *strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/src/contrib/zlib/contrib/infback9/infback9.h b/src/contrib/zlib/contrib/infback9/infback9.h deleted file mode 100644 index 1073c0a..0000000 --- a/src/contrib/zlib/contrib/infback9/infback9.h +++ /dev/null @@ -1,37 +0,0 @@ -/* infback9.h -- header for using inflateBack9 functions - * Copyright (C) 2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * This header file and associated patches provide a decoder for PKWare's - * undocumented deflate64 compression method (method 9). Use with infback9.c, - * inftree9.h, inftree9.c, and inffix9.h. These patches are not supported. - * This should be compiled with zlib, since it uses zutil.h and zutil.o. - * This code has not yet been tested on 16-bit architectures. See the - * comments in zlib.h for inflateBack() usage. These functions are used - * identically, except that there is no windowBits parameter, and a 64K - * window must be provided. Also if int's are 16 bits, then a zero for - * the third parameter of the "out" function actually means 65536UL. - * zlib.h must be included before this header file. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); -ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define inflateBack9Init(strm, window) \ - inflateBack9Init_((strm), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/zlib/contrib/infback9/inffix9.h b/src/contrib/zlib/contrib/infback9/inffix9.h deleted file mode 100644 index ee5671d..0000000 --- a/src/contrib/zlib/contrib/infback9/inffix9.h +++ /dev/null @@ -1,107 +0,0 @@ - /* inffix9.h -- table for decoding deflate64 fixed codes - * Generated automatically by makefixed9(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112}, - {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160}, - {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88}, - {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208}, - {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136}, - {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227}, - {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232}, - {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124}, - {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184}, - {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82}, - {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196}, - {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130}, - {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148}, - {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106}, - {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244}, - {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118}, - {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172}, - {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94}, - {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220}, - {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131}, - {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97}, - {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226}, - {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121}, - {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178}, - {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85}, - {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202}, - {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133}, - {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154}, - {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109}, - {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250}, - {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115}, - {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166}, - {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91}, - {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214}, - {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139}, - {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0}, - {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103}, - {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238}, - {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127}, - {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80}, - {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193}, - {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128}, - {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145}, - {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104}, - {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241}, - {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116}, - {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169}, - {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92}, - {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217}, - {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140}, - {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163}, - {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98}, - {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122}, - {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181}, - {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86}, - {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205}, - {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134}, - {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157}, - {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253}, - {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113}, - {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163}, - {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89}, - {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211}, - {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137}, - {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3}, - {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101}, - {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235}, - {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125}, - {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187}, - {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83}, - {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199}, - {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151}, - {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107}, - {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247}, - {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119}, - {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175}, - {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95}, - {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223}, - {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143}, - {0,8,79},{0,9,255} - }; - - static const code distfix[32] = { - {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5}, - {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513}, - {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129}, - {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145}, - {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4}, - {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073}, - {134,5,193},{142,5,49153} - }; diff --git a/src/contrib/zlib/contrib/infback9/inflate9.h b/src/contrib/zlib/contrib/infback9/inflate9.h deleted file mode 100644 index ee9a793..0000000 --- a/src/contrib/zlib/contrib/infback9/inflate9.h +++ /dev/null @@ -1,47 +0,0 @@ -/* inflate9.h -- internal inflate state definition - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Possible inflate modes between inflate() calls */ -typedef enum { - TYPE, /* i: waiting for type bits, including last-flag bit */ - STORED, /* i: waiting for stored size (length and complement) */ - TABLE, /* i: waiting for dynamic block table lengths */ - LEN, /* i: waiting for length/lit code */ - DONE, /* finished check, done -- remain here until reset */ - BAD /* got a data error -- remain here until reset */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to the BAD mode -- not shown for clarity) - - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or DONE - STORED -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LEN or TYPE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ -struct inflate_state { - /* sliding window */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ -}; diff --git a/src/contrib/zlib/contrib/infback9/inftree9.c b/src/contrib/zlib/contrib/infback9/inftree9.c deleted file mode 100644 index 5f4a767..0000000 --- a/src/contrib/zlib/contrib/infback9/inftree9.c +++ /dev/null @@ -1,324 +0,0 @@ -/* inftree9.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftree9.h" - -#define MAXBITS 15 - -const char inflate9_copyright[] = - " inflate9 1.2.11 Copyright 1995-2017 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int inflate_table9(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code this; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, - 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, - 131, 163, 195, 227, 3, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, - 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, - 133, 133, 133, 133, 144, 77, 202}; - static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, - 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, - 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153}; - static const unsigned short dext[32] = { /* Distance codes 0..31 extra */ - 128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, - 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, - 139, 139, 140, 140, 141, 141, 142, 142}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) return -1; /* no codes! */ - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftree9.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - this.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - this.op = (unsigned char)0; - this.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - this.op = (unsigned char)(extra[work[sym]]); - this.val = base[work[sym]]; - } - else { - this.op = (unsigned char)(32 + 64); /* end of block */ - this.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - do { - fill -= incr; - next[(huff >> drop) + fill] = this; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += 1U << curr; - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)(len - drop); - this.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - curr = root; - this.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = this; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/src/contrib/zlib/contrib/infback9/inftree9.h b/src/contrib/zlib/contrib/infback9/inftree9.h deleted file mode 100644 index 5ab21f0..0000000 --- a/src/contrib/zlib/contrib/infback9/inftree9.h +++ /dev/null @@ -1,61 +0,0 @@ -/* inftree9.h -- header to use inftree9.c - * Copyright (C) 1995-2008 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 100eeeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1446, which is the sum of 852 for literal/length codes and 594 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 32 6 15" for distance codes returns 594. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in infback9.c. If the root table size is changed, - then these maximum sizes would be need to be recalculated and updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 594 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table9() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/contrib/zlib/contrib/inflate86/inffas86.c b/src/contrib/zlib/contrib/inflate86/inffas86.c deleted file mode 100644 index 7292f67..0000000 --- a/src/contrib/zlib/contrib/inflate86/inffas86.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* inffas86.c is a hand tuned assembler version of - * - * inffast.c -- fast decoding - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } ar; - -#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->wnext; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - -#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) - __asm__ __volatile__ ( -" leaq %0, %%rax\n" -" movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ -" movq %%rsp, (%%rax)\n" -" movq %%rax, %%rsp\n" /* make rsp point to &ar */ -" movq 16(%%rsp), %%rsi\n" /* rsi = in */ -" movq 32(%%rsp), %%rdi\n" /* rdi = out */ -" movq 24(%%rsp), %%r9\n" /* r9 = last */ -" movq 48(%%rsp), %%r10\n" /* r10 = end */ -" movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ -" movq 72(%%rsp), %%r11\n" /* r11 = dcode */ -" movq 80(%%rsp), %%rdx\n" /* rdx = hold */ -" movl 88(%%rsp), %%ebx\n" /* ebx = bits */ -" movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ -" movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ - /* r14d = len */ - /* r15d = dist */ -" cld\n" -" cmpq %%rdi, %%r10\n" -" je .L_one_time\n" /* if only one decode left */ -" cmpq %%rsi, %%r9\n" -" je .L_one_time\n" -" jmp .L_do_loop\n" - -".L_one_time:\n" -" movq %%r12, %%r8\n" /* r8 = lmask */ -" cmpb $32, %%bl\n" -" ja .L_get_length_code_one_time\n" - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ -" jmp .L_get_length_code_one_time\n" - -".align 32,0x90\n" -".L_while_test:\n" -" cmpq %%rdi, %%r10\n" -" jbe .L_break_loop\n" -" cmpq %%rsi, %%r9\n" -" jbe .L_break_loop\n" - -".L_do_loop:\n" -" movq %%r12, %%r8\n" /* r8 = lmask */ -" cmpb $32, %%bl\n" -" ja .L_get_length_code\n" /* if (32 < bits) */ - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ - -".L_get_length_code:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" movq %%r12, %%r8\n" /* r8 = lmask */ -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" - -".L_get_length_code_one_time:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -".L_dolen:\n" -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_length_base:\n" -" movl %%eax, %%r14d\n" /* len = this */ -" shrl $16, %%r14d\n" /* len = this.val */ -" movb %%al, %%cl\n" - -" testb $16, %%al\n" -" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_decode_distance\n" /* if (!op) */ - -".L_add_bits_to_len:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrq %%cl, %%rdx\n" -" addl %%eax, %%r14d\n" /* len += hold & mask[op] */ - -".L_decode_distance:\n" -" movq %%r13, %%r8\n" /* r8 = dmask */ -" cmpb $32, %%bl\n" -" ja .L_get_distance_code\n" /* if (32 < bits) */ - -" lodsl\n" /* eax = *(uint *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $32, %%bl\n" /* bits += 32 */ -" shlq %%cl, %%rax\n" -" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ - -".L_get_distance_code:\n" -" andq %%rdx, %%r8\n" /* r8 &= hold */ -" movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ - -".L_dodist:\n" -" movl %%eax, %%r15d\n" /* dist = this */ -" shrl $16, %%r15d\n" /* dist = this.val */ -" movb %%ah, %%cl\n" -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ -" movb %%al, %%cl\n" /* cl = this.op */ - -" testb $16, %%al\n" /* if ((op & 16) == 0) */ -" jz .L_test_for_second_level_dist\n" -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_check_dist_one\n" - -".L_add_bits_to_dist:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" /* (1 << op) - 1 */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrq %%cl, %%rdx\n" -" addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ - -".L_check_window:\n" -" movq %%rsi, %%r8\n" /* save in so from can use it's reg */ -" movq %%rdi, %%rax\n" -" subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ - -" cmpl %%r15d, %%eax\n" -" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ - -" movl %%r14d, %%ecx\n" /* ecx = len */ -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ - -" sarl %%ecx\n" -" jnc .L_copy_two\n" /* if len % 2 == 0 */ - -" rep movsw\n" -" movb (%%rsi), %%al\n" -" movb %%al, (%%rdi)\n" -" incq %%rdi\n" - -" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ -" jmp .L_while_test\n" - -".L_copy_two:\n" -" rep movsw\n" -" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_check_dist_one:\n" -" cmpl $1, %%r15d\n" /* if dist 1, is a memset */ -" jne .L_check_window\n" -" cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ -" je .L_check_window\n" - -" movl %%r14d, %%ecx\n" /* ecx = len */ -" movb -1(%%rdi), %%al\n" -" movb %%al, %%ah\n" - -" sarl %%ecx\n" -" jnc .L_set_two\n" -" movb %%al, (%%rdi)\n" -" incq %%rdi\n" - -".L_set_two:\n" -" rep stosw\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_second_level_length:\n" -" testb $64, %%al\n" -" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%r14d, %%eax\n" /* eax += len */ -" movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ -" jmp .L_dolen\n" - -".align 32,0x90\n" -".L_test_for_second_level_dist:\n" -" testb $64, %%al\n" -" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%r15d, %%eax\n" /* eax += dist */ -" movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ -" jmp .L_dodist\n" - -".align 32,0x90\n" -".L_clip_window:\n" -" movl %%eax, %%ecx\n" /* ecx = nbytes */ -" movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ -" negl %%ecx\n" /* nbytes = -nbytes */ - -" cmpl %%r15d, %%eax\n" -" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ - -" addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ -" cmpl $0, 96(%%rsp)\n" -" jne .L_wrap_around_window\n" /* if (write != 0) */ - -" movq 56(%%rsp), %%rsi\n" /* from = window */ -" subl %%ecx, %%eax\n" /* eax -= nbytes */ -" addq %%rax, %%rsi\n" /* from += wsize - nbytes */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%r14d\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* eax -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_wrap_around_window:\n" -" movl 96(%%rsp), %%eax\n" /* eax = write */ -" cmpl %%eax, %%ecx\n" -" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ - -" movl 92(%%rsp), %%esi\n" /* from = wsize */ -" addq 56(%%rsp), %%rsi\n" /* from += window */ -" addq %%rax, %%rsi\n" /* from += write */ -" subq %%rcx, %%rsi\n" /* from -= nbytes */ -" subl %%eax, %%ecx\n" /* nbytes -= write */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq 56(%%rsp), %%rsi\n" /* from = window */ -" movl 96(%%rsp), %%ecx\n" /* nbytes = write */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_contiguous_in_window:\n" -" movq 56(%%rsp), %%rsi\n" /* rsi = window */ -" addq %%rax, %%rsi\n" -" subq %%rcx, %%rsi\n" /* from += write - nbytes */ - -" movl %%r14d, %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movq %%rdi, %%rsi\n" -" subq %%r15, %%rsi\n" /* from = out - dist */ -" jmp .L_do_copy\n" /* if (nbytes >= len) */ - -".align 32,0x90\n" -".L_do_copy:\n" -" movl %%eax, %%ecx\n" /* ecx = len */ -" rep movsb\n" - -" movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ -" jmp .L_while_test\n" - -".L_test_for_end_of_block:\n" -" testb $32, %%al\n" -" jz .L_invalid_literal_length_code\n" -" movl $1, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_literal_length_code:\n" -" movl $2, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_code:\n" -" movl $3, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_too_far:\n" -" movl $4, 116(%%rsp)\n" -" jmp .L_break_loop_with_status\n" - -".L_break_loop:\n" -" movl $0, 116(%%rsp)\n" - -".L_break_loop_with_status:\n" -/* put in, out, bits, and hold back into ar and pop esp */ -" movq %%rsi, 16(%%rsp)\n" /* in */ -" movq %%rdi, 32(%%rsp)\n" /* out */ -" movl %%ebx, 88(%%rsp)\n" /* bits */ -" movq %%rdx, 80(%%rsp)\n" /* hold */ -" movq (%%rsp), %%rax\n" /* restore rbp and rsp */ -" movq 8(%%rsp), %%rbp\n" -" movq %%rax, %%rsp\n" - : - : "m" (ar) - : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" - ); -#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) - __asm__ __volatile__ ( -" leal %0, %%eax\n" -" movl %%esp, (%%eax)\n" /* save esp, ebp */ -" movl %%ebp, 4(%%eax)\n" -" movl %%eax, %%esp\n" -" movl 8(%%esp), %%esi\n" /* esi = in */ -" movl 16(%%esp), %%edi\n" /* edi = out */ -" movl 40(%%esp), %%edx\n" /* edx = hold */ -" movl 44(%%esp), %%ebx\n" /* ebx = bits */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ - -" cld\n" -" jmp .L_do_loop\n" - -".align 32,0x90\n" -".L_while_test:\n" -" cmpl %%edi, 24(%%esp)\n" /* out < end */ -" jbe .L_break_loop\n" -" cmpl %%esi, 12(%%esp)\n" /* in < last */ -" jbe .L_break_loop\n" - -".L_do_loop:\n" -" cmpb $15, %%bl\n" -" ja .L_get_length_code\n" /* if (15 < bits) */ - -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ - -".L_get_length_code:\n" -" movl 56(%%esp), %%eax\n" /* eax = lmask */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ - -".L_dolen:\n" -" movb %%ah, %%cl\n" /* cl = this.bits */ -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrl %%cl, %%edx\n" /* hold >>= this.bits */ - -" testb %%al, %%al\n" -" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ - -" shrl $16, %%eax\n" /* output this.val char */ -" stosb\n" -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_length_base:\n" -" movl %%eax, %%ecx\n" /* len = this */ -" shrl $16, %%ecx\n" /* len = this.val */ -" movl %%ecx, 64(%%esp)\n" /* save len */ -" movb %%al, %%cl\n" - -" testb $16, %%al\n" -" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_decode_distance\n" /* if (!op) */ -" cmpb %%cl, %%bl\n" -" jae .L_add_bits_to_len\n" /* if (op <= bits) */ - -" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ -" movb %%ch, %%cl\n" /* move op back to ecx */ - -".L_add_bits_to_len:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrl %%cl, %%edx\n" -" addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ - -".L_decode_distance:\n" -" cmpb $15, %%bl\n" -" ja .L_get_distance_code\n" /* if (15 < bits) */ - -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ - -".L_get_distance_code:\n" -" movl 60(%%esp), %%eax\n" /* eax = dmask */ -" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ - -".L_dodist:\n" -" movl %%eax, %%ebp\n" /* dist = this */ -" shrl $16, %%ebp\n" /* dist = this.val */ -" movb %%ah, %%cl\n" -" subb %%ah, %%bl\n" /* bits -= this.bits */ -" shrl %%cl, %%edx\n" /* hold >>= this.bits */ -" movb %%al, %%cl\n" /* cl = this.op */ - -" testb $16, %%al\n" /* if ((op & 16) == 0) */ -" jz .L_test_for_second_level_dist\n" -" andb $15, %%cl\n" /* op &= 15 */ -" jz .L_check_dist_one\n" -" cmpb %%cl, %%bl\n" -" jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ - -" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ -" xorl %%eax, %%eax\n" -" lodsw\n" /* al = *(ushort *)in++ */ -" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ -" addb $16, %%bl\n" /* bits += 16 */ -" shll %%cl, %%eax\n" -" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ -" movb %%ch, %%cl\n" /* move op back to ecx */ - -".L_add_bits_to_dist:\n" -" subb %%cl, %%bl\n" -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" /* (1 << op) - 1 */ -" andl %%edx, %%eax\n" /* eax &= hold */ -" shrl %%cl, %%edx\n" -" addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ - -".L_check_window:\n" -" movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ -" movl %%edi, %%eax\n" -" subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ - -" cmpl %%ebp, %%eax\n" -" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ - -" movl 64(%%esp), %%ecx\n" /* ecx = len */ -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ - -" sarl %%ecx\n" -" jnc .L_copy_two\n" /* if len % 2 == 0 */ - -" rep movsw\n" -" movb (%%esi), %%al\n" -" movb %%al, (%%edi)\n" -" incl %%edi\n" - -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".L_copy_two:\n" -" rep movsw\n" -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_check_dist_one:\n" -" cmpl $1, %%ebp\n" /* if dist 1, is a memset */ -" jne .L_check_window\n" -" cmpl %%edi, 20(%%esp)\n" -" je .L_check_window\n" /* out == beg, if outside window */ - -" movl 64(%%esp), %%ecx\n" /* ecx = len */ -" movb -1(%%edi), %%al\n" -" movb %%al, %%ah\n" - -" sarl %%ecx\n" -" jnc .L_set_two\n" -" movb %%al, (%%edi)\n" -" incl %%edi\n" - -".L_set_two:\n" -" rep stosw\n" -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".align 32,0x90\n" -".L_test_for_second_level_length:\n" -" testb $64, %%al\n" -" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl 64(%%esp), %%eax\n" /* eax += len */ -" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ -" jmp .L_dolen\n" - -".align 32,0x90\n" -".L_test_for_second_level_dist:\n" -" testb $64, %%al\n" -" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ - -" xorl %%eax, %%eax\n" -" incl %%eax\n" -" shll %%cl, %%eax\n" -" decl %%eax\n" -" andl %%edx, %%eax\n" /* eax &= hold */ -" addl %%ebp, %%eax\n" /* eax += dist */ -" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ -" movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ -" jmp .L_dodist\n" - -".align 32,0x90\n" -".L_clip_window:\n" -" movl %%eax, %%ecx\n" -" movl 48(%%esp), %%eax\n" /* eax = wsize */ -" negl %%ecx\n" /* nbytes = -nbytes */ -" movl 28(%%esp), %%esi\n" /* from = window */ - -" cmpl %%ebp, %%eax\n" -" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ - -" addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ -" cmpl $0, 52(%%esp)\n" -" jne .L_wrap_around_window\n" /* if (write != 0) */ - -" subl %%ecx, %%eax\n" -" addl %%eax, %%esi\n" /* from += wsize - nbytes */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_wrap_around_window:\n" -" movl 52(%%esp), %%eax\n" /* eax = write */ -" cmpl %%eax, %%ecx\n" -" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ - -" addl 48(%%esp), %%esi\n" /* from += wsize */ -" addl %%eax, %%esi\n" /* from += write */ -" subl %%ecx, %%esi\n" /* from -= nbytes */ -" subl %%eax, %%ecx\n" /* nbytes -= write */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl 28(%%esp), %%esi\n" /* from = window */ -" movl 52(%%esp), %%ecx\n" /* nbytes = write */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" - -".align 32,0x90\n" -".L_contiguous_in_window:\n" -" addl %%eax, %%esi\n" -" subl %%ecx, %%esi\n" /* from += write - nbytes */ - -" movl 64(%%esp), %%eax\n" /* eax = len */ -" cmpl %%ecx, %%eax\n" -" jbe .L_do_copy\n" /* if (nbytes >= len) */ - -" subl %%ecx, %%eax\n" /* len -= nbytes */ -" rep movsb\n" -" movl %%edi, %%esi\n" -" subl %%ebp, %%esi\n" /* from = out - dist */ -" jmp .L_do_copy\n" /* if (nbytes >= len) */ - -".align 32,0x90\n" -".L_do_copy:\n" -" movl %%eax, %%ecx\n" -" rep movsb\n" - -" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ -" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ -" jmp .L_while_test\n" - -".L_test_for_end_of_block:\n" -" testb $32, %%al\n" -" jz .L_invalid_literal_length_code\n" -" movl $1, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_literal_length_code:\n" -" movl $2, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_code:\n" -" movl $3, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_invalid_distance_too_far:\n" -" movl 8(%%esp), %%esi\n" -" movl $4, 72(%%esp)\n" -" jmp .L_break_loop_with_status\n" - -".L_break_loop:\n" -" movl $0, 72(%%esp)\n" - -".L_break_loop_with_status:\n" -/* put in, out, bits, and hold back into ar and pop esp */ -" movl %%esi, 8(%%esp)\n" /* save in */ -" movl %%edi, 16(%%esp)\n" /* save out */ -" movl %%ebx, 44(%%esp)\n" /* save bits */ -" movl %%edx, 40(%%esp)\n" /* save hold */ -" movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ -" movl (%%esp), %%esp\n" - : - : "m" (ar) - : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" - ); -#elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) - __asm { - lea eax, ar - mov [eax], esp /* save esp, ebp */ - mov [eax+4], ebp - mov esp, eax - mov esi, [esp+8] /* esi = in */ - mov edi, [esp+16] /* edi = out */ - mov edx, [esp+40] /* edx = hold */ - mov ebx, [esp+44] /* ebx = bits */ - mov ebp, [esp+32] /* ebp = lcode */ - - cld - jmp L_do_loop - -ALIGN 4 -L_while_test: - cmp [esp+24], edi - jbe L_break_loop - cmp [esp+12], esi - jbe L_break_loop - -L_do_loop: - cmp bl, 15 - ja L_get_length_code /* if (15 < bits) */ - - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - -L_get_length_code: - mov eax, [esp+56] /* eax = lmask */ - and eax, edx /* eax &= hold */ - mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ - -L_dolen: - mov cl, ah /* cl = this.bits */ - sub bl, ah /* bits -= this.bits */ - shr edx, cl /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base /* if (op != 0) 45.7% */ - - shr eax, 16 /* output this.val char */ - stosb - jmp L_while_test - -ALIGN 4 -L_test_for_length_base: - mov ecx, eax /* len = this */ - shr ecx, 16 /* len = this.val */ - mov [esp+64], ecx /* save len */ - mov cl, al - - test al, 16 - jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ - and cl, 15 /* op &= 15 */ - jz L_decode_distance /* if (!op) */ - cmp bl, cl - jae L_add_bits_to_len /* if (op <= bits) */ - - mov ch, cl /* stash op in ch, freeing cl */ - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - mov cl, ch /* move op back to ecx */ - -L_add_bits_to_len: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - shr edx, cl - add [esp+64], eax /* len += hold & mask[op] */ - -L_decode_distance: - cmp bl, 15 - ja L_get_distance_code /* if (15 < bits) */ - - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - -L_get_distance_code: - mov eax, [esp+60] /* eax = dmask */ - mov ecx, [esp+36] /* ecx = dcode */ - and eax, edx /* eax &= hold */ - mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ - -L_dodist: - mov ebp, eax /* dist = this */ - shr ebp, 16 /* dist = this.val */ - mov cl, ah - sub bl, ah /* bits -= this.bits */ - shr edx, cl /* hold >>= this.bits */ - mov cl, al /* cl = this.op */ - - test al, 16 /* if ((op & 16) == 0) */ - jz L_test_for_second_level_dist - and cl, 15 /* op &= 15 */ - jz L_check_dist_one - cmp bl, cl - jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ - - mov ch, cl /* stash op in ch, freeing cl */ - xor eax, eax - lodsw /* al = *(ushort *)in++ */ - mov cl, bl /* cl = bits, needs it for shifting */ - add bl, 16 /* bits += 16 */ - shl eax, cl - or edx, eax /* hold |= *((ushort *)in)++ << bits */ - mov cl, ch /* move op back to ecx */ - -L_add_bits_to_dist: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax /* (1 << op) - 1 */ - and eax, edx /* eax &= hold */ - shr edx, cl - add ebp, eax /* dist += hold & ((1 << op) - 1) */ - -L_check_window: - mov [esp+8], esi /* save in so from can use it's reg */ - mov eax, edi - sub eax, [esp+20] /* nbytes = out - beg */ - - cmp eax, ebp - jb L_clip_window /* if (dist > nbytes) 4.2% */ - - mov ecx, [esp+64] /* ecx = len */ - mov esi, edi - sub esi, ebp /* from = out - dist */ - - sar ecx, 1 - jnc L_copy_two - - rep movsw - mov al, [esi] - mov [edi], al - inc edi - - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -L_copy_two: - rep movsw - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp ebp, 1 /* if dist 1, is a memset */ - jne L_check_window - cmp [esp+20], edi - je L_check_window /* out == beg, if outside window */ - - mov ecx, [esp+64] /* ecx = len */ - mov al, [edi-1] - mov ah, al - - sar ecx, 1 - jnc L_set_two - mov [edi], al /* memset out with from[-1] */ - inc edi - -L_set_two: - rep stosw - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - test al, 64 - jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - add eax, [esp+64] /* eax += len */ - mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - test al, 64 - jnz L_invalid_distance_code /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx /* eax &= hold */ - add eax, ebp /* eax += dist */ - mov ecx, [esp+36] /* ecx = dcode */ - mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ - jmp L_dodist - -ALIGN 4 -L_clip_window: - mov ecx, eax - mov eax, [esp+48] /* eax = wsize */ - neg ecx /* nbytes = -nbytes */ - mov esi, [esp+28] /* from = window */ - - cmp eax, ebp - jb L_invalid_distance_too_far /* if (dist > wsize) */ - - add ecx, ebp /* nbytes = dist - nbytes */ - cmp dword ptr [esp+52], 0 - jne L_wrap_around_window /* if (write != 0) */ - - sub eax, ecx - add esi, eax /* from += wsize - nbytes */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_wrap_around_window: - mov eax, [esp+52] /* eax = write */ - cmp ecx, eax - jbe L_contiguous_in_window /* if (write >= nbytes) */ - - add esi, [esp+48] /* from += wsize */ - add esi, eax /* from += write */ - sub esi, ecx /* from -= nbytes */ - sub ecx, eax /* nbytes -= write */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, [esp+28] /* from = window */ - mov ecx, [esp+52] /* nbytes = write */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_contiguous_in_window: - add esi, eax - sub esi, ecx /* from += write - nbytes */ - - mov eax, [esp+64] /* eax = len */ - cmp eax, ecx - jbe L_do_copy /* if (nbytes >= len) */ - - sub eax, ecx /* len -= nbytes */ - rep movsb - mov esi, edi - sub esi, ebp /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_do_copy: - mov ecx, eax - rep movsb - - mov esi, [esp+8] /* move in back to %esi, toss from */ - mov ebp, [esp+32] /* ebp = lcode */ - jmp L_while_test - -L_test_for_end_of_block: - test al, 32 - jz L_invalid_literal_length_code - mov dword ptr [esp+72], 1 - jmp L_break_loop_with_status - -L_invalid_literal_length_code: - mov dword ptr [esp+72], 2 - jmp L_break_loop_with_status - -L_invalid_distance_code: - mov dword ptr [esp+72], 3 - jmp L_break_loop_with_status - -L_invalid_distance_too_far: - mov esi, [esp+4] - mov dword ptr [esp+72], 4 - jmp L_break_loop_with_status - -L_break_loop: - mov dword ptr [esp+72], 0 - -L_break_loop_with_status: -/* put in, out, bits, and hold back into ar and pop esp */ - mov [esp+8], esi /* save in */ - mov [esp+16], edi /* save out */ - mov [esp+44], ebx /* save bits */ - mov [esp+40], edx /* save hold */ - mov ebp, [esp+4] /* restore esp, ebp */ - mov esp, [esp] - } -#else -#error "x86 architecture not defined" -#endif - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = ar.hold; - state->bits = ar.bits; - return; -} - diff --git a/src/contrib/zlib/contrib/inflate86/inffast.S b/src/contrib/zlib/contrib/inflate86/inffast.S deleted file mode 100644 index 2245a29..0000000 --- a/src/contrib/zlib/contrib/inflate86/inffast.S +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * inffast.S is a hand tuned assembler version of: - * - * inffast.c -- fast decoding - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * This version (Jan-23-2003) of inflate_fast was coded and tested under - * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that - * machine, I found that gzip style archives decompressed about 20% faster than - * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will - * depend on how large of a buffer is used for z_stream.next_in & next_out - * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in - * stream processing I/O and crc32/addler32. In my case, this routine used - * 70% of the cpu time and crc32 used 20%. - * - * I am confident that this version will work in the general case, but I have - * not tested a wide variety of datasets or a wide variety of platforms. - * - * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. - * It should be a runtime flag instead of compile time flag... - * - * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. - * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code - * is compiled. Without either option, runtime detection is enabled. Runtime - * detection should work on all modern cpus and the recomended algorithm (flip - * ID bit on eflags and then use the cpuid instruction) is used in many - * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 - * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o - * inffast.obj generates a COFF object which can then be linked with MSVC++ - * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. - * - * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and - * slower than compiler generated code). Adjusted cpuid check to use the MMX - * code only for Pentiums < P4 until I have more data on the P4. Speed - * improvment is only about 15% on the Athlon when compared with code generated - * with MSVC++. Not sure yet, but I think the P4 will also be slower using the - * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and - * have less latency than MMX ops. Added code to buffer the last 11 bytes of - * the input stream since the MMX code grabs bits in chunks of 32, which - * differs from the inffast.c algorithm. I don't think there would have been - * read overruns where a page boundary was crossed (a segfault), but there - * could have been overruns when next_in ends on unaligned memory (unintialized - * memory read). - * - * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C - * version of the non-MMX code so that it doesn't depend on zstrm and zstate - * structure offsets which are hard coded in this file. This was last tested - * with zlib-1.2.0 which is currently in beta testing, newer versions of this - * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and - * http://www.charm.net/~christop/zlib/ - */ - - -/* - * if you have underscore linking problems (_inflate_fast undefined), try - * using -DGAS_COFF - */ -#if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) - -#if defined( WIN32 ) || defined( __CYGWIN__ ) -#define GAS_COFF /* windows object format */ -#else -#define GAS_ELF -#endif - -#endif /* ! GAS_COFF && ! GAS_ELF */ - - -#if defined( GAS_COFF ) - -/* coff externals have underscores */ -#define inflate_fast _inflate_fast -#define inflate_fast_use_mmx _inflate_fast_use_mmx - -#endif /* GAS_COFF */ - - -.file "inffast.S" - -.globl inflate_fast - -.text -.align 4,0 -.L_invalid_literal_length_code_msg: -.string "invalid literal/length code" - -.align 4,0 -.L_invalid_distance_code_msg: -.string "invalid distance code" - -.align 4,0 -.L_invalid_distance_too_far_msg: -.string "invalid distance too far back" - -#if ! defined( NO_MMX ) -.align 4,0 -.L_mask: /* mask[N] = ( 1 << N ) - 1 */ -.long 0 -.long 1 -.long 3 -.long 7 -.long 15 -.long 31 -.long 63 -.long 127 -.long 255 -.long 511 -.long 1023 -.long 2047 -.long 4095 -.long 8191 -.long 16383 -.long 32767 -.long 65535 -.long 131071 -.long 262143 -.long 524287 -.long 1048575 -.long 2097151 -.long 4194303 -.long 8388607 -.long 16777215 -.long 33554431 -.long 67108863 -.long 134217727 -.long 268435455 -.long 536870911 -.long 1073741823 -.long 2147483647 -.long 4294967295 -#endif /* NO_MMX */ - -.text - -/* - * struct z_stream offsets, in zlib.h - */ -#define next_in_strm 0 /* strm->next_in */ -#define avail_in_strm 4 /* strm->avail_in */ -#define next_out_strm 12 /* strm->next_out */ -#define avail_out_strm 16 /* strm->avail_out */ -#define msg_strm 24 /* strm->msg */ -#define state_strm 28 /* strm->state */ - -/* - * struct inflate_state offsets, in inflate.h - */ -#define mode_state 0 /* state->mode */ -#define wsize_state 32 /* state->wsize */ -#define write_state 40 /* state->write */ -#define window_state 44 /* state->window */ -#define hold_state 48 /* state->hold */ -#define bits_state 52 /* state->bits */ -#define lencode_state 68 /* state->lencode */ -#define distcode_state 72 /* state->distcode */ -#define lenbits_state 76 /* state->lenbits */ -#define distbits_state 80 /* state->distbits */ - -/* - * inflate_fast's activation record - */ -#define local_var_size 64 /* how much local space for vars */ -#define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ -#define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ - -/* - * offsets for local vars on stack - */ -#define out 60 /* unsigned char* */ -#define window 56 /* unsigned char* */ -#define wsize 52 /* unsigned int */ -#define write 48 /* unsigned int */ -#define in 44 /* unsigned char* */ -#define beg 40 /* unsigned char* */ -#define buf 28 /* char[ 12 ] */ -#define len 24 /* unsigned int */ -#define last 20 /* unsigned char* */ -#define end 16 /* unsigned char* */ -#define dcode 12 /* code* */ -#define lcode 8 /* code* */ -#define dmask 4 /* unsigned int */ -#define lmask 0 /* unsigned int */ - -/* - * typedef enum inflate_mode consts, in inflate.h - */ -#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ -#define INFLATE_MODE_BAD 26 - - -#if ! defined( USE_MMX ) && ! defined( NO_MMX ) - -#define RUN_TIME_MMX - -#define CHECK_MMX 1 -#define DO_USE_MMX 2 -#define DONT_USE_MMX 3 - -.globl inflate_fast_use_mmx - -.data - -.align 4,0 -inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ -.long CHECK_MMX - -#if defined( GAS_ELF ) -/* elf info */ -.type inflate_fast_use_mmx,@object -.size inflate_fast_use_mmx,4 -#endif - -#endif /* RUN_TIME_MMX */ - -#if defined( GAS_COFF ) -/* coff info: scl 2 = extern, type 32 = function */ -.def inflate_fast; .scl 2; .type 32; .endef -#endif - -.text - -.align 32,0x90 -inflate_fast: - pushl %edi - pushl %esi - pushl %ebp - pushl %ebx - pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ - subl $local_var_size, %esp - cld - -#define strm_r %esi -#define state_r %edi - - movl strm_sp(%esp), strm_r - movl state_strm(strm_r), state_r - - /* in = strm->next_in; - * out = strm->next_out; - * last = in + strm->avail_in - 11; - * beg = out - (start - strm->avail_out); - * end = out + (strm->avail_out - 257); - */ - movl avail_in_strm(strm_r), %edx - movl next_in_strm(strm_r), %eax - - addl %eax, %edx /* avail_in += next_in */ - subl $11, %edx /* avail_in -= 11 */ - - movl %eax, in(%esp) - movl %edx, last(%esp) - - movl start_sp(%esp), %ebp - movl avail_out_strm(strm_r), %ecx - movl next_out_strm(strm_r), %ebx - - subl %ecx, %ebp /* start -= avail_out */ - negl %ebp /* start = -start */ - addl %ebx, %ebp /* start += next_out */ - - subl $257, %ecx /* avail_out -= 257 */ - addl %ebx, %ecx /* avail_out += out */ - - movl %ebx, out(%esp) - movl %ebp, beg(%esp) - movl %ecx, end(%esp) - - /* wsize = state->wsize; - * write = state->write; - * window = state->window; - * hold = state->hold; - * bits = state->bits; - * lcode = state->lencode; - * dcode = state->distcode; - * lmask = ( 1 << state->lenbits ) - 1; - * dmask = ( 1 << state->distbits ) - 1; - */ - - movl lencode_state(state_r), %eax - movl distcode_state(state_r), %ecx - - movl %eax, lcode(%esp) - movl %ecx, dcode(%esp) - - movl $1, %eax - movl lenbits_state(state_r), %ecx - shll %cl, %eax - decl %eax - movl %eax, lmask(%esp) - - movl $1, %eax - movl distbits_state(state_r), %ecx - shll %cl, %eax - decl %eax - movl %eax, dmask(%esp) - - movl wsize_state(state_r), %eax - movl write_state(state_r), %ecx - movl window_state(state_r), %edx - - movl %eax, wsize(%esp) - movl %ecx, write(%esp) - movl %edx, window(%esp) - - movl hold_state(state_r), %ebp - movl bits_state(state_r), %ebx - -#undef strm_r -#undef state_r - -#define in_r %esi -#define from_r %esi -#define out_r %edi - - movl in(%esp), in_r - movl last(%esp), %ecx - cmpl in_r, %ecx - ja .L_align_long /* if in < last */ - - addl $11, %ecx /* ecx = &in[ avail_in ] */ - subl in_r, %ecx /* ecx = avail_in */ - movl $12, %eax - subl %ecx, %eax /* eax = 12 - avail_in */ - leal buf(%esp), %edi - rep movsb /* memcpy( buf, in, avail_in ) */ - movl %eax, %ecx - xorl %eax, %eax - rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ - leal buf(%esp), in_r /* in = buf */ - movl in_r, last(%esp) /* last = in, do just one iteration */ - jmp .L_is_aligned - - /* align in_r on long boundary */ -.L_align_long: - testl $3, in_r - jz .L_is_aligned - xorl %eax, %eax - movb (in_r), %al - incl in_r - movl %ebx, %ecx - addl $8, %ebx - shll %cl, %eax - orl %eax, %ebp - jmp .L_align_long - -.L_is_aligned: - movl out(%esp), out_r - -#if defined( NO_MMX ) - jmp .L_do_loop -#endif - -#if defined( USE_MMX ) - jmp .L_init_mmx -#endif - -/*** Runtime MMX check ***/ - -#if defined( RUN_TIME_MMX ) -.L_check_mmx: - cmpl $DO_USE_MMX, inflate_fast_use_mmx - je .L_init_mmx - ja .L_do_loop /* > 2 */ - - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - pushf - movl (%esp), %eax /* copy eflags to eax */ - xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) - * to see if cpu supports cpuid... - * ID bit method not supported by NexGen but - * bios may load a cpuid instruction and - * cpuid may be disabled on Cyrix 5-6x86 */ - popf - pushf - popl %edx /* copy new eflags to edx */ - xorl %eax, %edx /* test if ID bit is flipped */ - jz .L_dont_use_mmx /* not flipped if zero */ - xorl %eax, %eax - cpuid - cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ - jne .L_dont_use_mmx - cmpl $0x6c65746e, %ecx - jne .L_dont_use_mmx - cmpl $0x49656e69, %edx - jne .L_dont_use_mmx - movl $1, %eax - cpuid /* get cpu features */ - shrl $8, %eax - andl $15, %eax - cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ - jne .L_dont_use_mmx - testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ - jnz .L_use_mmx - jmp .L_dont_use_mmx -.L_use_mmx: - movl $DO_USE_MMX, inflate_fast_use_mmx - jmp .L_check_mmx_pop -.L_dont_use_mmx: - movl $DONT_USE_MMX, inflate_fast_use_mmx -.L_check_mmx_pop: - popl %edx - popl %ecx - popl %ebx - popl %eax - jmp .L_check_mmx -#endif - - -/*** Non-MMX code ***/ - -#if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) - -#define hold_r %ebp -#define bits_r %bl -#define bitslong_r %ebx - -.align 32,0x90 -.L_while_test: - /* while (in < last && out < end) - */ - cmpl out_r, end(%esp) - jbe .L_break_loop /* if (out >= end) */ - - cmpl in_r, last(%esp) - jbe .L_break_loop - -.L_do_loop: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out - * - * do { - * if (bits < 15) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * this = lcode[hold & lmask] - */ - cmpb $15, bits_r - ja .L_get_length_code /* if (15 < bits) */ - - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - -.L_get_length_code: - movl lmask(%esp), %edx /* edx = lmask */ - movl lcode(%esp), %ecx /* ecx = lcode */ - andl hold_r, %edx /* edx &= hold */ - movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ - -.L_dolen: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out - * - * dolen: - * bits -= this.bits; - * hold >>= this.bits - */ - movb %ah, %cl /* cl = this.bits */ - subb %ah, bits_r /* bits -= this.bits */ - shrl %cl, hold_r /* hold >>= this.bits */ - - /* check if op is a literal - * if (op == 0) { - * PUP(out) = this.val; - * } - */ - testb %al, %al - jnz .L_test_for_length_base /* if (op != 0) 45.7% */ - - shrl $16, %eax /* output this.val char */ - stosb - jmp .L_while_test - -.L_test_for_length_base: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len - * - * else if (op & 16) { - * len = this.val - * op &= 15 - * if (op) { - * if (op > bits) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * len += hold & mask[op]; - * bits -= op; - * hold >>= op; - * } - */ -#define len_r %edx - movl %eax, len_r /* len = this */ - shrl $16, len_r /* len = this.val */ - movb %al, %cl - - testb $16, %al - jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ - andb $15, %cl /* op &= 15 */ - jz .L_save_len /* if (!op) */ - cmpb %cl, bits_r - jae .L_add_bits_to_len /* if (op <= bits) */ - - movb %cl, %ch /* stash op in ch, freeing cl */ - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - movb %ch, %cl /* move op back to ecx */ - -.L_add_bits_to_len: - movl $1, %eax - shll %cl, %eax - decl %eax - subb %cl, bits_r - andl hold_r, %eax /* eax &= hold */ - shrl %cl, hold_r - addl %eax, len_r /* len += hold & mask[op] */ - -.L_save_len: - movl len_r, len(%esp) /* save len */ -#undef len_r - -.L_decode_distance: - /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * - * if (bits < 15) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * this = dcode[hold & dmask]; - * dodist: - * bits -= this.bits; - * hold >>= this.bits; - * op = this.op; - */ - - cmpb $15, bits_r - ja .L_get_distance_code /* if (15 < bits) */ - - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - -.L_get_distance_code: - movl dmask(%esp), %edx /* edx = dmask */ - movl dcode(%esp), %ecx /* ecx = dcode */ - andl hold_r, %edx /* edx &= hold */ - movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ - -#define dist_r %edx -.L_dodist: - movl %eax, dist_r /* dist = this */ - shrl $16, dist_r /* dist = this.val */ - movb %ah, %cl - subb %ah, bits_r /* bits -= this.bits */ - shrl %cl, hold_r /* hold >>= this.bits */ - - /* if (op & 16) { - * dist = this.val - * op &= 15 - * if (op > bits) { - * hold |= *((unsigned short *)in)++ << bits; - * bits += 16 - * } - * dist += hold & mask[op]; - * bits -= op; - * hold >>= op; - */ - movb %al, %cl /* cl = this.op */ - - testb $16, %al /* if ((op & 16) == 0) */ - jz .L_test_for_second_level_dist - andb $15, %cl /* op &= 15 */ - jz .L_check_dist_one - cmpb %cl, bits_r - jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ - - movb %cl, %ch /* stash op in ch, freeing cl */ - xorl %eax, %eax - lodsw /* al = *(ushort *)in++ */ - movb bits_r, %cl /* cl = bits, needs it for shifting */ - addb $16, bits_r /* bits += 16 */ - shll %cl, %eax - orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ - movb %ch, %cl /* move op back to ecx */ - -.L_add_bits_to_dist: - movl $1, %eax - shll %cl, %eax - decl %eax /* (1 << op) - 1 */ - subb %cl, bits_r - andl hold_r, %eax /* eax &= hold */ - shrl %cl, hold_r - addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ - jmp .L_check_window - -.L_check_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes - * - * nbytes = out - beg; - * if (dist <= nbytes) { - * from = out - dist; - * do { - * PUP(out) = PUP(from); - * } while (--len > 0) { - * } - */ - - movl in_r, in(%esp) /* save in so from can use it's reg */ - movl out_r, %eax - subl beg(%esp), %eax /* nbytes = out - beg */ - - cmpl dist_r, %eax - jb .L_clip_window /* if (dist > nbytes) 4.2% */ - - movl len(%esp), %ecx - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - - subl $3, %ecx - movb (from_r), %al - movb %al, (out_r) - movb 1(from_r), %al - movb 2(from_r), %dl - addl $3, from_r - movb %al, 1(out_r) - movb %dl, 2(out_r) - addl $3, out_r - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - jmp .L_while_test - -.align 16,0x90 -.L_check_dist_one: - cmpl $1, dist_r - jne .L_check_window - cmpl out_r, beg(%esp) - je .L_check_window - - decl out_r - movl len(%esp), %ecx - movb (out_r), %al - subl $3, %ecx - - movb %al, 1(out_r) - movb %al, 2(out_r) - movb %al, 3(out_r) - addl $4, out_r - rep stosb - - jmp .L_while_test - -.align 16,0x90 -.L_test_for_second_level_length: - /* else if ((op & 64) == 0) { - * this = lcode[this.val + (hold & mask[op])]; - * } - */ - testb $64, %al - jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ - - movl $1, %eax - shll %cl, %eax - decl %eax - andl hold_r, %eax /* eax &= hold */ - addl %edx, %eax /* eax += this.val */ - movl lcode(%esp), %edx /* edx = lcode */ - movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ - jmp .L_dolen - -.align 16,0x90 -.L_test_for_second_level_dist: - /* else if ((op & 64) == 0) { - * this = dcode[this.val + (hold & mask[op])]; - * } - */ - testb $64, %al - jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ - - movl $1, %eax - shll %cl, %eax - decl %eax - andl hold_r, %eax /* eax &= hold */ - addl %edx, %eax /* eax += this.val */ - movl dcode(%esp), %edx /* edx = dcode */ - movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ - jmp .L_dodist - -.align 16,0x90 -.L_clip_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes - * - * else { - * if (dist > wsize) { - * invalid distance - * } - * from = window; - * nbytes = dist - nbytes; - * if (write == 0) { - * from += wsize - nbytes; - */ -#define nbytes_r %ecx - movl %eax, nbytes_r - movl wsize(%esp), %eax /* prepare for dist compare */ - negl nbytes_r /* nbytes = -nbytes */ - movl window(%esp), from_r /* from = window */ - - cmpl dist_r, %eax - jb .L_invalid_distance_too_far /* if (dist > wsize) */ - - addl dist_r, nbytes_r /* nbytes = dist - nbytes */ - cmpl $0, write(%esp) - jne .L_wrap_around_window /* if (write != 0) */ - - subl nbytes_r, %eax - addl %eax, from_r /* from += wsize - nbytes */ - - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = len - * - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = out - dist; - * } - * } - */ -#define len_r %eax - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - -.L_wrap_around_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = write, %eax = len - * - * else if (write < nbytes) { - * from += wsize + write - nbytes; - * nbytes -= write; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = window; - * nbytes = write; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while(--nbytes); - * from = out - dist; - * } - * } - * } - */ -#define write_r %eax - movl write(%esp), write_r - cmpl write_r, nbytes_r - jbe .L_contiguous_in_window /* if (write >= nbytes) */ - - addl wsize(%esp), from_r - addl write_r, from_r - subl nbytes_r, from_r /* from += wsize + write - nbytes */ - subl write_r, nbytes_r /* nbytes -= write */ -#undef write_r - - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl window(%esp), from_r /* from = window */ - movl write(%esp), nbytes_r /* nbytes = write */ - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1 - -.L_contiguous_in_window: - /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist - * %ecx = nbytes, %eax = write, %eax = len - * - * else { - * from += write - nbytes; - * if (nbytes < len) { - * len -= nbytes; - * do { - * PUP(out) = PUP(from); - * } while (--nbytes); - * from = out - dist; - * } - * } - */ -#define write_r %eax - addl write_r, from_r - subl nbytes_r, from_r /* from += write - nbytes */ -#undef write_r - - movl len(%esp), len_r - cmpl nbytes_r, len_r - jbe .L_do_copy1 /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - -.L_do_copy1: - /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out - * %eax = len - * - * while (len > 0) { - * PUP(out) = PUP(from); - * len--; - * } - * } - * } while (in < last && out < end); - */ -#undef nbytes_r -#define in_r %esi - movl len_r, %ecx - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - jmp .L_while_test - -#undef len_r -#undef dist_r - -#endif /* NO_MMX || RUN_TIME_MMX */ - - -/*** MMX code ***/ - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -.align 32,0x90 -.L_init_mmx: - emms - -#undef bits_r -#undef bitslong_r -#define bitslong_r %ebp -#define hold_mm %mm0 - movd %ebp, hold_mm - movl %ebx, bitslong_r - -#define used_mm %mm1 -#define dmask2_mm %mm2 -#define lmask2_mm %mm3 -#define lmask_mm %mm4 -#define dmask_mm %mm5 -#define tmp_mm %mm6 - - movd lmask(%esp), lmask_mm - movq lmask_mm, lmask2_mm - movd dmask(%esp), dmask_mm - movq dmask_mm, dmask2_mm - pxor used_mm, used_mm - movl lcode(%esp), %ebx /* ebx = lcode */ - jmp .L_do_loop_mmx - -.align 32,0x90 -.L_while_test_mmx: - /* while (in < last && out < end) - */ - cmpl out_r, end(%esp) - jbe .L_break_loop /* if (out >= end) */ - - cmpl in_r, last(%esp) - jbe .L_break_loop - -.L_do_loop_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - - cmpl $32, bitslong_r - ja .L_get_length_code_mmx /* if (32 < bits) */ - - movd bitslong_r, tmp_mm - movd (in_r), %mm7 - addl $4, in_r - psllq tmp_mm, %mm7 - addl $32, bitslong_r - por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ - -.L_get_length_code_mmx: - pand hold_mm, lmask_mm - movd lmask_mm, %eax - movq lmask2_mm, lmask_mm - movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ - -.L_dolen_mmx: - movzbl %ah, %ecx /* ecx = this.bits */ - movd %ecx, used_mm - subl %ecx, bitslong_r /* bits -= this.bits */ - - testb %al, %al - jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ - - shrl $16, %eax /* output this.val char */ - stosb - jmp .L_while_test_mmx - -.L_test_for_length_base_mmx: -#define len_r %edx - movl %eax, len_r /* len = this */ - shrl $16, len_r /* len = this.val */ - - testb $16, %al - jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ - andl $15, %eax /* op &= 15 */ - jz .L_decode_distance_mmx /* if (!op) */ - - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd %eax, used_mm - movd hold_mm, %ecx - subl %eax, bitslong_r - andl .L_mask(,%eax,4), %ecx - addl %ecx, len_r /* len += hold & mask[op] */ - -.L_decode_distance_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - - cmpl $32, bitslong_r - ja .L_get_dist_code_mmx /* if (32 < bits) */ - - movd bitslong_r, tmp_mm - movd (in_r), %mm7 - addl $4, in_r - psllq tmp_mm, %mm7 - addl $32, bitslong_r - por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ - -.L_get_dist_code_mmx: - movl dcode(%esp), %ebx /* ebx = dcode */ - pand hold_mm, dmask_mm - movd dmask_mm, %eax - movq dmask2_mm, dmask_mm - movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ - -.L_dodist_mmx: -#define dist_r %ebx - movzbl %ah, %ecx /* ecx = this.bits */ - movl %eax, dist_r - shrl $16, dist_r /* dist = this.val */ - subl %ecx, bitslong_r /* bits -= this.bits */ - movd %ecx, used_mm - - testb $16, %al /* if ((op & 16) == 0) */ - jz .L_test_for_second_level_dist_mmx - andl $15, %eax /* op &= 15 */ - jz .L_check_dist_one_mmx - -.L_add_bits_to_dist_mmx: - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd %eax, used_mm /* save bit length of current op */ - movd hold_mm, %ecx /* get the next bits on input stream */ - subl %eax, bitslong_r /* bits -= op bits */ - andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ - addl %ecx, dist_r /* dist += hold & mask[op] */ - -.L_check_window_mmx: - movl in_r, in(%esp) /* save in so from can use it's reg */ - movl out_r, %eax - subl beg(%esp), %eax /* nbytes = out - beg */ - - cmpl dist_r, %eax - jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ - - movl len_r, %ecx - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - - subl $3, %ecx - movb (from_r), %al - movb %al, (out_r) - movb 1(from_r), %al - movb 2(from_r), %dl - addl $3, from_r - movb %al, 1(out_r) - movb %dl, 2(out_r) - addl $3, out_r - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -.align 16,0x90 -.L_check_dist_one_mmx: - cmpl $1, dist_r - jne .L_check_window_mmx - cmpl out_r, beg(%esp) - je .L_check_window_mmx - - decl out_r - movl len_r, %ecx - movb (out_r), %al - subl $3, %ecx - - movb %al, 1(out_r) - movb %al, 2(out_r) - movb %al, 3(out_r) - addl $4, out_r - rep stosb - - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -.align 16,0x90 -.L_test_for_second_level_length_mmx: - testb $64, %al - jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ - - andl $15, %eax - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ecx - andl .L_mask(,%eax,4), %ecx - addl len_r, %ecx - movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ - jmp .L_dolen_mmx - -.align 16,0x90 -.L_test_for_second_level_dist_mmx: - testb $64, %al - jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ - - andl $15, %eax - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ecx - andl .L_mask(,%eax,4), %ecx - movl dcode(%esp), %eax /* ecx = dcode */ - addl dist_r, %ecx - movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ - jmp .L_dodist_mmx - -.align 16,0x90 -.L_clip_window_mmx: -#define nbytes_r %ecx - movl %eax, nbytes_r - movl wsize(%esp), %eax /* prepare for dist compare */ - negl nbytes_r /* nbytes = -nbytes */ - movl window(%esp), from_r /* from = window */ - - cmpl dist_r, %eax - jb .L_invalid_distance_too_far /* if (dist > wsize) */ - - addl dist_r, nbytes_r /* nbytes = dist - nbytes */ - cmpl $0, write(%esp) - jne .L_wrap_around_window_mmx /* if (write != 0) */ - - subl nbytes_r, %eax - addl %eax, from_r /* from += wsize - nbytes */ - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - -.L_wrap_around_window_mmx: -#define write_r %eax - movl write(%esp), write_r - cmpl write_r, nbytes_r - jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ - - addl wsize(%esp), from_r - addl write_r, from_r - subl nbytes_r, from_r /* from += wsize + write - nbytes */ - subl write_r, nbytes_r /* nbytes -= write */ -#undef write_r - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl window(%esp), from_r /* from = window */ - movl write(%esp), nbytes_r /* nbytes = write */ - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - jmp .L_do_copy1_mmx - -.L_contiguous_in_window_mmx: -#define write_r %eax - addl write_r, from_r - subl nbytes_r, from_r /* from += write - nbytes */ -#undef write_r - - cmpl nbytes_r, len_r - jbe .L_do_copy1_mmx /* if (nbytes >= len) */ - - subl nbytes_r, len_r /* len -= nbytes */ - rep movsb - movl out_r, from_r - subl dist_r, from_r /* from = out - dist */ - -.L_do_copy1_mmx: -#undef nbytes_r -#define in_r %esi - movl len_r, %ecx - rep movsb - - movl in(%esp), in_r /* move in back to %esi, toss from */ - movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ - jmp .L_while_test_mmx - -#undef hold_r -#undef bitslong_r - -#endif /* USE_MMX || RUN_TIME_MMX */ - - -/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ - -.L_invalid_distance_code: - /* else { - * strm->msg = "invalid distance code"; - * state->mode = BAD; - * } - */ - movl $.L_invalid_distance_code_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_test_for_end_of_block: - /* else if (op & 32) { - * state->mode = TYPE; - * break; - * } - */ - testb $32, %al - jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ - - movl $0, %ecx - movl $INFLATE_MODE_TYPE, %edx - jmp .L_update_stream_state - -.L_invalid_literal_length_code: - /* else { - * strm->msg = "invalid literal/length code"; - * state->mode = BAD; - * } - */ - movl $.L_invalid_literal_length_code_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_invalid_distance_too_far: - /* strm->msg = "invalid distance too far back"; - * state->mode = BAD; - */ - movl in(%esp), in_r /* from_r has in's reg, put in back */ - movl $.L_invalid_distance_too_far_msg, %ecx - movl $INFLATE_MODE_BAD, %edx - jmp .L_update_stream_state - -.L_update_stream_state: - /* set strm->msg = %ecx, strm->state->mode = %edx */ - movl strm_sp(%esp), %eax - testl %ecx, %ecx /* if (msg != NULL) */ - jz .L_skip_msg - movl %ecx, msg_strm(%eax) /* strm->msg = msg */ -.L_skip_msg: - movl state_strm(%eax), %eax /* state = strm->state */ - movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ - jmp .L_break_loop - -.align 32,0x90 -.L_break_loop: - -/* - * Regs: - * - * bits = %ebp when mmx, and in %ebx when non-mmx - * hold = %hold_mm when mmx, and in %ebp when non-mmx - * in = %esi - * out = %edi - */ - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -#if defined( RUN_TIME_MMX ) - - cmpl $DO_USE_MMX, inflate_fast_use_mmx - jne .L_update_next_in - -#endif /* RUN_TIME_MMX */ - - movl %ebp, %ebx - -.L_update_next_in: - -#endif - -#define strm_r %eax -#define state_r %edx - - /* len = bits >> 3; - * in -= len; - * bits -= len << 3; - * hold &= (1U << bits) - 1; - * state->hold = hold; - * state->bits = bits; - * strm->next_in = in; - * strm->next_out = out; - */ - movl strm_sp(%esp), strm_r - movl %ebx, %ecx - movl state_strm(strm_r), state_r - shrl $3, %ecx - subl %ecx, in_r - shll $3, %ecx - subl %ecx, %ebx - movl out_r, next_out_strm(strm_r) - movl %ebx, bits_state(state_r) - movl %ebx, %ecx - - leal buf(%esp), %ebx - cmpl %ebx, last(%esp) - jne .L_buf_not_used /* if buf != last */ - - subl %ebx, in_r /* in -= buf */ - movl next_in_strm(strm_r), %ebx - movl %ebx, last(%esp) /* last = strm->next_in */ - addl %ebx, in_r /* in += strm->next_in */ - movl avail_in_strm(strm_r), %ebx - subl $11, %ebx - addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ - -.L_buf_not_used: - movl in_r, next_in_strm(strm_r) - - movl $1, %ebx - shll %cl, %ebx - decl %ebx - -#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) - -#if defined( RUN_TIME_MMX ) - - cmpl $DO_USE_MMX, inflate_fast_use_mmx - jne .L_update_hold - -#endif /* RUN_TIME_MMX */ - - psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ - movd hold_mm, %ebp - - emms - -.L_update_hold: - -#endif /* USE_MMX || RUN_TIME_MMX */ - - andl %ebx, %ebp - movl %ebp, hold_state(state_r) - -#define last_r %ebx - - /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ - movl last(%esp), last_r - cmpl in_r, last_r - jbe .L_last_is_smaller /* if (in >= last) */ - - subl in_r, last_r /* last -= in */ - addl $11, last_r /* last += 11 */ - movl last_r, avail_in_strm(strm_r) - jmp .L_fixup_out -.L_last_is_smaller: - subl last_r, in_r /* in -= last */ - negl in_r /* in = -in */ - addl $11, in_r /* in += 11 */ - movl in_r, avail_in_strm(strm_r) - -#undef last_r -#define end_r %ebx - -.L_fixup_out: - /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ - movl end(%esp), end_r - cmpl out_r, end_r - jbe .L_end_is_smaller /* if (out >= end) */ - - subl out_r, end_r /* end -= out */ - addl $257, end_r /* end += 257 */ - movl end_r, avail_out_strm(strm_r) - jmp .L_done -.L_end_is_smaller: - subl end_r, out_r /* out -= end */ - negl out_r /* out = -out */ - addl $257, out_r /* out += 257 */ - movl out_r, avail_out_strm(strm_r) - -#undef end_r -#undef strm_r -#undef state_r - -.L_done: - addl $local_var_size, %esp - popf - popl %ebx - popl %ebp - popl %esi - popl %edi - ret - -#if defined( GAS_ELF ) -/* elf info */ -.type inflate_fast,@function -.size inflate_fast,.-inflate_fast -#endif diff --git a/src/contrib/zlib/contrib/iostream/test.cpp b/src/contrib/zlib/contrib/iostream/test.cpp deleted file mode 100644 index 7d265b3..0000000 --- a/src/contrib/zlib/contrib/iostream/test.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -#include "zfstream.h" - -int main() { - - // Construct a stream object with this filebuffer. Anything sent - // to this stream will go to standard out. - gzofstream os( 1, ios::out ); - - // This text is getting compressed and sent to stdout. - // To prove this, run 'test | zcat'. - os << "Hello, Mommy" << endl; - - os << setcompressionlevel( Z_NO_COMPRESSION ); - os << "hello, hello, hi, ho!" << endl; - - setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) - << "I'm compressing again" << endl; - - os.close(); - - return 0; - -} diff --git a/src/contrib/zlib/contrib/iostream/zfstream.cpp b/src/contrib/zlib/contrib/iostream/zfstream.cpp deleted file mode 100644 index d0cd85f..0000000 --- a/src/contrib/zlib/contrib/iostream/zfstream.cpp +++ /dev/null @@ -1,329 +0,0 @@ - -#include "zfstream.h" - -gzfilebuf::gzfilebuf() : - file(NULL), - mode(0), - own_file_descriptor(0) -{ } - -gzfilebuf::~gzfilebuf() { - - sync(); - if ( own_file_descriptor ) - close(); - -} - -gzfilebuf *gzfilebuf::open( const char *name, - int io_mode ) { - - if ( is_open() ) - return NULL; - - char char_mode[10]; - char *p = char_mode; - - if ( io_mode & ios::in ) { - mode = ios::in; - *p++ = 'r'; - } else if ( io_mode & ios::app ) { - mode = ios::app; - *p++ = 'a'; - } else { - mode = ios::out; - *p++ = 'w'; - } - - if ( io_mode & ios::binary ) { - mode |= ios::binary; - *p++ = 'b'; - } - - // Hard code the compression level - if ( io_mode & (ios::out|ios::app )) { - *p++ = '9'; - } - - // Put the end-of-string indicator - *p = '\0'; - - if ( (file = gzopen(name, char_mode)) == NULL ) - return NULL; - - own_file_descriptor = 1; - - return this; - -} - -gzfilebuf *gzfilebuf::attach( int file_descriptor, - int io_mode ) { - - if ( is_open() ) - return NULL; - - char char_mode[10]; - char *p = char_mode; - - if ( io_mode & ios::in ) { - mode = ios::in; - *p++ = 'r'; - } else if ( io_mode & ios::app ) { - mode = ios::app; - *p++ = 'a'; - } else { - mode = ios::out; - *p++ = 'w'; - } - - if ( io_mode & ios::binary ) { - mode |= ios::binary; - *p++ = 'b'; - } - - // Hard code the compression level - if ( io_mode & (ios::out|ios::app )) { - *p++ = '9'; - } - - // Put the end-of-string indicator - *p = '\0'; - - if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) - return NULL; - - own_file_descriptor = 0; - - return this; - -} - -gzfilebuf *gzfilebuf::close() { - - if ( is_open() ) { - - sync(); - gzclose( file ); - file = NULL; - - } - - return this; - -} - -int gzfilebuf::setcompressionlevel( int comp_level ) { - - return gzsetparams(file, comp_level, -2); - -} - -int gzfilebuf::setcompressionstrategy( int comp_strategy ) { - - return gzsetparams(file, -2, comp_strategy); - -} - - -streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { - - return streampos(EOF); - -} - -int gzfilebuf::underflow() { - - // If the file hasn't been opened for reading, error. - if ( !is_open() || !(mode & ios::in) ) - return EOF; - - // if a buffer doesn't exists, allocate one. - if ( !base() ) { - - if ( (allocate()) == EOF ) - return EOF; - setp(0,0); - - } else { - - if ( in_avail() ) - return (unsigned char) *gptr(); - - if ( out_waiting() ) { - if ( flushbuf() == EOF ) - return EOF; - } - - } - - // Attempt to fill the buffer. - - int result = fillbuf(); - if ( result == EOF ) { - // disable get area - setg(0,0,0); - return EOF; - } - - return (unsigned char) *gptr(); - -} - -int gzfilebuf::overflow( int c ) { - - if ( !is_open() || !(mode & ios::out) ) - return EOF; - - if ( !base() ) { - if ( allocate() == EOF ) - return EOF; - setg(0,0,0); - } else { - if (in_avail()) { - return EOF; - } - if (out_waiting()) { - if (flushbuf() == EOF) - return EOF; - } - } - - int bl = blen(); - setp( base(), base() + bl); - - if ( c != EOF ) { - - *pptr() = c; - pbump(1); - - } - - return 0; - -} - -int gzfilebuf::sync() { - - if ( !is_open() ) - return EOF; - - if ( out_waiting() ) - return flushbuf(); - - return 0; - -} - -int gzfilebuf::flushbuf() { - - int n; - char *q; - - q = pbase(); - n = pptr() - q; - - if ( gzwrite( file, q, n) < n ) - return EOF; - - setp(0,0); - - return 0; - -} - -int gzfilebuf::fillbuf() { - - int required; - char *p; - - p = base(); - - required = blen(); - - int t = gzread( file, p, required ); - - if ( t <= 0) return EOF; - - setg( base(), base(), base()+t); - - return t; - -} - -gzfilestream_common::gzfilestream_common() : - ios( gzfilestream_common::rdbuf() ) -{ } - -gzfilestream_common::~gzfilestream_common() -{ } - -void gzfilestream_common::attach( int fd, int io_mode ) { - - if ( !buffer.attach( fd, io_mode) ) - clear( ios::failbit | ios::badbit ); - else - clear(); - -} - -void gzfilestream_common::open( const char *name, int io_mode ) { - - if ( !buffer.open( name, io_mode ) ) - clear( ios::failbit | ios::badbit ); - else - clear(); - -} - -void gzfilestream_common::close() { - - if ( !buffer.close() ) - clear( ios::failbit | ios::badbit ); - -} - -gzfilebuf *gzfilestream_common::rdbuf() -{ - return &buffer; -} - -gzifstream::gzifstream() : - ios( gzfilestream_common::rdbuf() ) -{ - clear( ios::badbit ); -} - -gzifstream::gzifstream( const char *name, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::open( name, io_mode ); -} - -gzifstream::gzifstream( int fd, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::attach( fd, io_mode ); -} - -gzifstream::~gzifstream() { } - -gzofstream::gzofstream() : - ios( gzfilestream_common::rdbuf() ) -{ - clear( ios::badbit ); -} - -gzofstream::gzofstream( const char *name, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::open( name, io_mode ); -} - -gzofstream::gzofstream( int fd, int io_mode ) : - ios( gzfilestream_common::rdbuf() ) -{ - gzfilestream_common::attach( fd, io_mode ); -} - -gzofstream::~gzofstream() { } diff --git a/src/contrib/zlib/contrib/iostream/zfstream.h b/src/contrib/zlib/contrib/iostream/zfstream.h deleted file mode 100644 index ed79098..0000000 --- a/src/contrib/zlib/contrib/iostream/zfstream.h +++ /dev/null @@ -1,128 +0,0 @@ - -#ifndef zfstream_h -#define zfstream_h - -#include -#include "zlib.h" - -class gzfilebuf : public streambuf { - -public: - - gzfilebuf( ); - virtual ~gzfilebuf(); - - gzfilebuf *open( const char *name, int io_mode ); - gzfilebuf *attach( int file_descriptor, int io_mode ); - gzfilebuf *close(); - - int setcompressionlevel( int comp_level ); - int setcompressionstrategy( int comp_strategy ); - - inline int is_open() const { return (file !=NULL); } - - virtual streampos seekoff( streamoff, ios::seek_dir, int ); - - virtual int sync(); - -protected: - - virtual int underflow(); - virtual int overflow( int = EOF ); - -private: - - gzFile file; - short mode; - short own_file_descriptor; - - int flushbuf(); - int fillbuf(); - -}; - -class gzfilestream_common : virtual public ios { - - friend class gzifstream; - friend class gzofstream; - friend gzofstream &setcompressionlevel( gzofstream &, int ); - friend gzofstream &setcompressionstrategy( gzofstream &, int ); - -public: - virtual ~gzfilestream_common(); - - void attach( int fd, int io_mode ); - void open( const char *name, int io_mode ); - void close(); - -protected: - gzfilestream_common(); - -private: - gzfilebuf *rdbuf(); - - gzfilebuf buffer; - -}; - -class gzifstream : public gzfilestream_common, public istream { - -public: - - gzifstream(); - gzifstream( const char *name, int io_mode = ios::in ); - gzifstream( int fd, int io_mode = ios::in ); - - virtual ~gzifstream(); - -}; - -class gzofstream : public gzfilestream_common, public ostream { - -public: - - gzofstream(); - gzofstream( const char *name, int io_mode = ios::out ); - gzofstream( int fd, int io_mode = ios::out ); - - virtual ~gzofstream(); - -}; - -template class gzomanip { - friend gzofstream &operator<<(gzofstream &, const gzomanip &); -public: - gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } -private: - gzofstream &(*func)(gzofstream &, T); - T val; -}; - -template gzofstream &operator<<(gzofstream &s, const gzomanip &m) -{ - return (*m.func)(s, m.val); -} - -inline gzofstream &setcompressionlevel( gzofstream &s, int l ) -{ - (s.rdbuf())->setcompressionlevel(l); - return s; -} - -inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) -{ - (s.rdbuf())->setcompressionstrategy(l); - return s; -} - -inline gzomanip setcompressionlevel(int l) -{ - return gzomanip(&setcompressionlevel,l); -} - -inline gzomanip setcompressionstrategy(int l) -{ - return gzomanip(&setcompressionstrategy,l); -} - -#endif diff --git a/src/contrib/zlib/contrib/iostream2/zstream.h b/src/contrib/zlib/contrib/iostream2/zstream.h deleted file mode 100644 index 43d2332..0000000 --- a/src/contrib/zlib/contrib/iostream2/zstream.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * - * Copyright (c) 1997 - * Christian Michelsen Research AS - * Advanced Computing - * Fantoftvegen 38, 5036 BERGEN, Norway - * http://www.cmr.no - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Christian Michelsen Research AS makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -#ifndef ZSTREAM__H -#define ZSTREAM__H - -/* - * zstream.h - C++ interface to the 'zlib' general purpose compression library - * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ - */ - -#include -#include -#include -#include "zlib.h" - -#if defined(_WIN32) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -class zstringlen { -public: - zstringlen(class izstream&); - zstringlen(class ozstream&, const char*); - size_t value() const { return val.word; } -private: - struct Val { unsigned char byte; size_t word; } val; -}; - -// ----------------------------- izstream ----------------------------- - -class izstream -{ - public: - izstream() : m_fp(0) {} - izstream(FILE* fp) : m_fp(0) { open(fp); } - izstream(const char* name) : m_fp(0) { open(name); } - ~izstream() { close(); } - - /* Opens a gzip (.gz) file for reading. - * open() can be used to read a file which is not in gzip format; - * in this case read() will directly read from the file without - * decompression. errno can be checked to distinguish two error - * cases (if errno is zero, the zlib error is Z_MEM_ERROR). - */ - void open(const char* name) { - if (m_fp) close(); - m_fp = ::gzopen(name, "rb"); - } - - void open(FILE* fp) { - SET_BINARY_MODE(fp); - if (m_fp) close(); - m_fp = ::gzdopen(fileno(fp), "rb"); - } - - /* Flushes all pending input if necessary, closes the compressed file - * and deallocates all the (de)compression state. The return value is - * the zlib error number (see function error() below). - */ - int close() { - int r = ::gzclose(m_fp); - m_fp = 0; return r; - } - - /* Binary read the given number of bytes from the compressed file. - */ - int read(void* buf, size_t len) { - return ::gzread(m_fp, buf, len); - } - - /* Returns the error message for the last error which occurred on the - * given compressed file. errnum is set to zlib error number. If an - * error occurred in the file system and not in the compression library, - * errnum is set to Z_ERRNO and the application may consult errno - * to get the exact error code. - */ - const char* error(int* errnum) { - return ::gzerror(m_fp, errnum); - } - - gzFile fp() { return m_fp; } - - private: - gzFile m_fp; -}; - -/* - * Binary read the given (array of) object(s) from the compressed file. - * If the input file was not in gzip format, read() copies the objects number - * of bytes into the buffer. - * returns the number of uncompressed bytes actually read - * (0 for end of file, -1 for error). - */ -template -inline int read(izstream& zs, T* x, Items items) { - return ::gzread(zs.fp(), x, items*sizeof(T)); -} - -/* - * Binary input with the '>' operator. - */ -template -inline izstream& operator>(izstream& zs, T& x) { - ::gzread(zs.fp(), &x, sizeof(T)); - return zs; -} - - -inline zstringlen::zstringlen(izstream& zs) { - zs > val.byte; - if (val.byte == 255) zs > val.word; - else val.word = val.byte; -} - -/* - * Read length of string + the string with the '>' operator. - */ -inline izstream& operator>(izstream& zs, char* x) { - zstringlen len(zs); - ::gzread(zs.fp(), x, len.value()); - x[len.value()] = '\0'; - return zs; -} - -inline char* read_string(izstream& zs) { - zstringlen len(zs); - char* x = new char[len.value()+1]; - ::gzread(zs.fp(), x, len.value()); - x[len.value()] = '\0'; - return x; -} - -// ----------------------------- ozstream ----------------------------- - -class ozstream -{ - public: - ozstream() : m_fp(0), m_os(0) { - } - ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) - : m_fp(0), m_os(0) { - open(fp, level); - } - ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) - : m_fp(0), m_os(0) { - open(name, level); - } - ~ozstream() { - close(); - } - - /* Opens a gzip (.gz) file for writing. - * The compression level parameter should be in 0..9 - * errno can be checked to distinguish two error cases - * (if errno is zero, the zlib error is Z_MEM_ERROR). - */ - void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { - char mode[4] = "wb\0"; - if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; - if (m_fp) close(); - m_fp = ::gzopen(name, mode); - } - - /* open from a FILE pointer. - */ - void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { - SET_BINARY_MODE(fp); - char mode[4] = "wb\0"; - if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; - if (m_fp) close(); - m_fp = ::gzdopen(fileno(fp), mode); - } - - /* Flushes all pending output if necessary, closes the compressed file - * and deallocates all the (de)compression state. The return value is - * the zlib error number (see function error() below). - */ - int close() { - if (m_os) { - ::gzwrite(m_fp, m_os->str(), m_os->pcount()); - delete[] m_os->str(); delete m_os; m_os = 0; - } - int r = ::gzclose(m_fp); m_fp = 0; return r; - } - - /* Binary write the given number of bytes into the compressed file. - */ - int write(const void* buf, size_t len) { - return ::gzwrite(m_fp, (voidp) buf, len); - } - - /* Flushes all pending output into the compressed file. The parameter - * _flush is as in the deflate() function. The return value is the zlib - * error number (see function gzerror below). flush() returns Z_OK if - * the flush_ parameter is Z_FINISH and all output could be flushed. - * flush() should be called only when strictly necessary because it can - * degrade compression. - */ - int flush(int _flush) { - os_flush(); - return ::gzflush(m_fp, _flush); - } - - /* Returns the error message for the last error which occurred on the - * given compressed file. errnum is set to zlib error number. If an - * error occurred in the file system and not in the compression library, - * errnum is set to Z_ERRNO and the application may consult errno - * to get the exact error code. - */ - const char* error(int* errnum) { - return ::gzerror(m_fp, errnum); - } - - gzFile fp() { return m_fp; } - - ostream& os() { - if (m_os == 0) m_os = new ostrstream; - return *m_os; - } - - void os_flush() { - if (m_os && m_os->pcount()>0) { - ostrstream* oss = new ostrstream; - oss->fill(m_os->fill()); - oss->flags(m_os->flags()); - oss->precision(m_os->precision()); - oss->width(m_os->width()); - ::gzwrite(m_fp, m_os->str(), m_os->pcount()); - delete[] m_os->str(); delete m_os; m_os = oss; - } - } - - private: - gzFile m_fp; - ostrstream* m_os; -}; - -/* - * Binary write the given (array of) object(s) into the compressed file. - * returns the number of uncompressed bytes actually written - * (0 in case of error). - */ -template -inline int write(ozstream& zs, const T* x, Items items) { - return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); -} - -/* - * Binary output with the '<' operator. - */ -template -inline ozstream& operator<(ozstream& zs, const T& x) { - ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); - return zs; -} - -inline zstringlen::zstringlen(ozstream& zs, const char* x) { - val.byte = 255; val.word = ::strlen(x); - if (val.word < 255) zs < (val.byte = val.word); - else zs < val; -} - -/* - * Write length of string + the string with the '<' operator. - */ -inline ozstream& operator<(ozstream& zs, const char* x) { - zstringlen len(zs, x); - ::gzwrite(zs.fp(), (voidp) x, len.value()); - return zs; -} - -#ifdef _MSC_VER -inline ozstream& operator<(ozstream& zs, char* const& x) { - return zs < (const char*) x; -} -#endif - -/* - * Ascii write with the << operator; - */ -template -inline ostream& operator<<(ozstream& zs, const T& x) { - zs.os_flush(); - return zs.os() << x; -} - -#endif diff --git a/src/contrib/zlib/contrib/iostream2/zstream_test.cpp b/src/contrib/zlib/contrib/iostream2/zstream_test.cpp deleted file mode 100644 index 6273f62..0000000 --- a/src/contrib/zlib/contrib/iostream2/zstream_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "zstream.h" -#include -#include -#include - -void main() { - char h[256] = "Hello"; - char* g = "Goodbye"; - ozstream out("temp.gz"); - out < "This works well" < h < g; - out.close(); - - izstream in("temp.gz"); // read it back - char *x = read_string(in), *y = new char[256], z[256]; - in > y > z; - in.close(); - cout << x << endl << y << endl << z << endl; - - out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results - out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; - out << z << endl << y << endl << x << endl; - out << 1.1234567890123456789 << endl; - - delete[] x; delete[] y; -} diff --git a/src/contrib/zlib/contrib/iostream3/README b/src/contrib/zlib/contrib/iostream3/README deleted file mode 100644 index f7b319a..0000000 --- a/src/contrib/zlib/contrib/iostream3/README +++ /dev/null @@ -1,35 +0,0 @@ -These classes provide a C++ stream interface to the zlib library. It allows you -to do things like: - - gzofstream outf("blah.gz"); - outf << "These go into the gzip file " << 123 << endl; - -It does this by deriving a specialized stream buffer for gzipped files, which is -the way Stroustrup would have done it. :-> - -The gzifstream and gzofstream classes were originally written by Kevin Ruland -and made available in the zlib contrib/iostream directory. The older version still -compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of -this version. - -The new classes are as standard-compliant as possible, closely following the -approach of the standard library's fstream classes. It compiles under gcc versions -3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard -library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs -from the previous one in the following respects: -- added showmanyc -- added setbuf, with support for unbuffered output via setbuf(0,0) -- a few bug fixes of stream behavior -- gzipped output file opened with default compression level instead of maximum level -- setcompressionlevel()/strategy() members replaced by single setcompression() - -The code is provided "as is", with the permission to use, copy, modify, distribute -and sell it for any purpose without fee. - -Ludwig Schwardt - - -DSP Lab -Electrical & Electronic Engineering Department -University of Stellenbosch -South Africa diff --git a/src/contrib/zlib/contrib/iostream3/TODO b/src/contrib/zlib/contrib/iostream3/TODO deleted file mode 100644 index 7032f97..0000000 --- a/src/contrib/zlib/contrib/iostream3/TODO +++ /dev/null @@ -1,17 +0,0 @@ -Possible upgrades to gzfilebuf: - -- The ability to do putback (e.g. putbackfail) - -- The ability to seek (zlib supports this, but could be slow/tricky) - -- Simultaneous read/write access (does it make sense?) - -- Support for ios_base::ate open mode - -- Locale support? - -- Check public interface to see which calls give problems - (due to dependence on library internals) - -- Override operator<<(ostream&, gzfilebuf*) to allow direct copying - of stream buffer to stream ( i.e. os << is.rdbuf(); ) diff --git a/src/contrib/zlib/contrib/iostream3/test.cc b/src/contrib/zlib/contrib/iostream3/test.cc deleted file mode 100644 index 9423533..0000000 --- a/src/contrib/zlib/contrib/iostream3/test.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Test program for gzifstream and gzofstream - * - * by Ludwig Schwardt - * original version by Kevin Ruland - */ - -#include "zfstream.h" -#include // for cout - -int main() { - - gzofstream outf; - gzifstream inf; - char buf[80]; - - outf.open("test1.txt.gz"); - outf << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - outf.close(); - std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n" - << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - - std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n"; - inf.open("test1.txt.gz"); - while (inf.getline(buf,80,'\n')) { - std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; - } - inf.close(); - - outf.rdbuf()->pubsetbuf(0,0); - outf.open("test2.txt.gz"); - outf << setcompression(Z_NO_COMPRESSION) - << "The quick brown fox sidestepped the lazy canine\n" - << 1.3 << "\nPlan " << 9 << std::endl; - outf.close(); - std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form"; - - std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n"; - inf.rdbuf()->pubsetbuf(0,0); - inf.open("test2.txt.gz"); - while (inf.getline(buf,80,'\n')) { - std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; - } - inf.close(); - - return 0; - -} diff --git a/src/contrib/zlib/contrib/iostream3/zfstream.cc b/src/contrib/zlib/contrib/iostream3/zfstream.cc deleted file mode 100644 index 94eb933..0000000 --- a/src/contrib/zlib/contrib/iostream3/zfstream.cc +++ /dev/null @@ -1,479 +0,0 @@ -/* - * A C++ I/O streams interface to the zlib gz* functions - * - * by Ludwig Schwardt - * original version by Kevin Ruland - * - * This version is standard-compliant and compatible with gcc 3.x. - */ - -#include "zfstream.h" -#include // for strcpy, strcat, strlen (mode strings) -#include // for BUFSIZ - -// Internal buffer sizes (default and "unbuffered" versions) -#define BIGBUFSIZE BUFSIZ -#define SMALLBUFSIZE 1 - -/*****************************************************************************/ - -// Default constructor -gzfilebuf::gzfilebuf() -: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), - buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) -{ - // No buffers to start with - this->disable_buffer(); -} - -// Destructor -gzfilebuf::~gzfilebuf() -{ - // Sync output buffer and close only if responsible for file - // (i.e. attached streams should be left open at this stage) - this->sync(); - if (own_fd) - this->close(); - // Make sure internal buffer is deallocated - this->disable_buffer(); -} - -// Set compression level and strategy -int -gzfilebuf::setcompression(int comp_level, - int comp_strategy) -{ - return gzsetparams(file, comp_level, comp_strategy); -} - -// Open gzipped file -gzfilebuf* -gzfilebuf::open(const char *name, - std::ios_base::openmode mode) -{ - // Fail if file already open - if (this->is_open()) - return NULL; - // Don't support simultaneous read/write access (yet) - if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) - return NULL; - - // Build mode string for gzopen and check it [27.8.1.3.2] - char char_mode[6] = "\0\0\0\0\0"; - if (!this->open_mode(mode, char_mode)) - return NULL; - - // Attempt to open file - if ((file = gzopen(name, char_mode)) == NULL) - return NULL; - - // On success, allocate internal buffer and set flags - this->enable_buffer(); - io_mode = mode; - own_fd = true; - return this; -} - -// Attach to gzipped file -gzfilebuf* -gzfilebuf::attach(int fd, - std::ios_base::openmode mode) -{ - // Fail if file already open - if (this->is_open()) - return NULL; - // Don't support simultaneous read/write access (yet) - if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) - return NULL; - - // Build mode string for gzdopen and check it [27.8.1.3.2] - char char_mode[6] = "\0\0\0\0\0"; - if (!this->open_mode(mode, char_mode)) - return NULL; - - // Attempt to attach to file - if ((file = gzdopen(fd, char_mode)) == NULL) - return NULL; - - // On success, allocate internal buffer and set flags - this->enable_buffer(); - io_mode = mode; - own_fd = false; - return this; -} - -// Close gzipped file -gzfilebuf* -gzfilebuf::close() -{ - // Fail immediately if no file is open - if (!this->is_open()) - return NULL; - // Assume success - gzfilebuf* retval = this; - // Attempt to sync and close gzipped file - if (this->sync() == -1) - retval = NULL; - if (gzclose(file) < 0) - retval = NULL; - // File is now gone anyway (postcondition [27.8.1.3.8]) - file = NULL; - own_fd = false; - // Destroy internal buffer if it exists - this->disable_buffer(); - return retval; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Convert int open mode to mode string -bool -gzfilebuf::open_mode(std::ios_base::openmode mode, - char* c_mode) const -{ - bool testb = mode & std::ios_base::binary; - bool testi = mode & std::ios_base::in; - bool testo = mode & std::ios_base::out; - bool testt = mode & std::ios_base::trunc; - bool testa = mode & std::ios_base::app; - - // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) - // Original zfstream hardcoded the compression level to maximum here... - // Double the time for less than 1% size improvement seems - // excessive though - keeping it at the default level - // To change back, just append "9" to the next three mode strings - if (!testi && testo && !testt && !testa) - strcpy(c_mode, "w"); - if (!testi && testo && !testt && testa) - strcpy(c_mode, "a"); - if (!testi && testo && testt && !testa) - strcpy(c_mode, "w"); - if (testi && !testo && !testt && !testa) - strcpy(c_mode, "r"); - // No read/write mode yet -// if (testi && testo && !testt && !testa) -// strcpy(c_mode, "r+"); -// if (testi && testo && testt && !testa) -// strcpy(c_mode, "w+"); - - // Mode string should be empty for invalid combination of flags - if (strlen(c_mode) == 0) - return false; - if (testb) - strcat(c_mode, "b"); - return true; -} - -// Determine number of characters in internal get buffer -std::streamsize -gzfilebuf::showmanyc() -{ - // Calls to underflow will fail if file not opened for reading - if (!this->is_open() || !(io_mode & std::ios_base::in)) - return -1; - // Make sure get area is in use - if (this->gptr() && (this->gptr() < this->egptr())) - return std::streamsize(this->egptr() - this->gptr()); - else - return 0; -} - -// Fill get area from gzipped file -gzfilebuf::int_type -gzfilebuf::underflow() -{ - // If something is left in the get area by chance, return it - // (this shouldn't normally happen, as underflow is only supposed - // to be called when gptr >= egptr, but it serves as error check) - if (this->gptr() && (this->gptr() < this->egptr())) - return traits_type::to_int_type(*(this->gptr())); - - // If the file hasn't been opened for reading, produce error - if (!this->is_open() || !(io_mode & std::ios_base::in)) - return traits_type::eof(); - - // Attempt to fill internal buffer from gzipped file - // (buffer must be guaranteed to exist...) - int bytes_read = gzread(file, buffer, buffer_size); - // Indicates error or EOF - if (bytes_read <= 0) - { - // Reset get area - this->setg(buffer, buffer, buffer); - return traits_type::eof(); - } - // Make all bytes read from file available as get area - this->setg(buffer, buffer, buffer + bytes_read); - - // Return next character in get area - return traits_type::to_int_type(*(this->gptr())); -} - -// Write put area to gzipped file -gzfilebuf::int_type -gzfilebuf::overflow(int_type c) -{ - // Determine whether put area is in use - if (this->pbase()) - { - // Double-check pointer range - if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) - return traits_type::eof(); - // Add extra character to buffer if not EOF - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - *(this->pptr()) = traits_type::to_char_type(c); - this->pbump(1); - } - // Number of characters to write to file - int bytes_to_write = this->pptr() - this->pbase(); - // Overflow doesn't fail if nothing is to be written - if (bytes_to_write > 0) - { - // If the file hasn't been opened for writing, produce error - if (!this->is_open() || !(io_mode & std::ios_base::out)) - return traits_type::eof(); - // If gzipped file won't accept all bytes written to it, fail - if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) - return traits_type::eof(); - // Reset next pointer to point to pbase on success - this->pbump(-bytes_to_write); - } - } - // Write extra character to file if not EOF - else if (!traits_type::eq_int_type(c, traits_type::eof())) - { - // If the file hasn't been opened for writing, produce error - if (!this->is_open() || !(io_mode & std::ios_base::out)) - return traits_type::eof(); - // Impromptu char buffer (allows "unbuffered" output) - char_type last_char = traits_type::to_char_type(c); - // If gzipped file won't accept this character, fail - if (gzwrite(file, &last_char, 1) != 1) - return traits_type::eof(); - } - - // If you got here, you have succeeded (even if c was EOF) - // The return value should therefore be non-EOF - if (traits_type::eq_int_type(c, traits_type::eof())) - return traits_type::not_eof(c); - else - return c; -} - -// Assign new buffer -std::streambuf* -gzfilebuf::setbuf(char_type* p, - std::streamsize n) -{ - // First make sure stuff is sync'ed, for safety - if (this->sync() == -1) - return NULL; - // If buffering is turned off on purpose via setbuf(0,0), still allocate one... - // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at - // least a buffer of size 1 (very inefficient though, therefore make it bigger?) - // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) - if (!p || !n) - { - // Replace existing buffer (if any) with small internal buffer - this->disable_buffer(); - buffer = NULL; - buffer_size = 0; - own_buffer = true; - this->enable_buffer(); - } - else - { - // Replace existing buffer (if any) with external buffer - this->disable_buffer(); - buffer = p; - buffer_size = n; - own_buffer = false; - this->enable_buffer(); - } - return this; -} - -// Write put area to gzipped file (i.e. ensures that put area is empty) -int -gzfilebuf::sync() -{ - return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Allocate internal buffer -void -gzfilebuf::enable_buffer() -{ - // If internal buffer required, allocate one - if (own_buffer && !buffer) - { - // Check for buffered vs. "unbuffered" - if (buffer_size > 0) - { - // Allocate internal buffer - buffer = new char_type[buffer_size]; - // Get area starts empty and will be expanded by underflow as need arises - this->setg(buffer, buffer, buffer); - // Setup entire internal buffer as put area. - // The one-past-end pointer actually points to the last element of the buffer, - // so that overflow(c) can safely add the extra character c to the sequence. - // These pointers remain in place for the duration of the buffer - this->setp(buffer, buffer + buffer_size - 1); - } - else - { - // Even in "unbuffered" case, (small?) get buffer is still required - buffer_size = SMALLBUFSIZE; - buffer = new char_type[buffer_size]; - this->setg(buffer, buffer, buffer); - // "Unbuffered" means no put buffer - this->setp(0, 0); - } - } - else - { - // If buffer already allocated, reset buffer pointers just to make sure no - // stale chars are lying around - this->setg(buffer, buffer, buffer); - this->setp(buffer, buffer + buffer_size - 1); - } -} - -// Destroy internal buffer -void -gzfilebuf::disable_buffer() -{ - // If internal buffer exists, deallocate it - if (own_buffer && buffer) - { - // Preserve unbuffered status by zeroing size - if (!this->pbase()) - buffer_size = 0; - delete[] buffer; - buffer = NULL; - this->setg(0, 0, 0); - this->setp(0, 0); - } - else - { - // Reset buffer pointers to initial state if external buffer exists - this->setg(buffer, buffer, buffer); - if (buffer) - this->setp(buffer, buffer + buffer_size - 1); - else - this->setp(0, 0); - } -} - -/*****************************************************************************/ - -// Default constructor initializes stream buffer -gzifstream::gzifstream() -: std::istream(NULL), sb() -{ this->init(&sb); } - -// Initialize stream buffer and open file -gzifstream::gzifstream(const char* name, - std::ios_base::openmode mode) -: std::istream(NULL), sb() -{ - this->init(&sb); - this->open(name, mode); -} - -// Initialize stream buffer and attach to file -gzifstream::gzifstream(int fd, - std::ios_base::openmode mode) -: std::istream(NULL), sb() -{ - this->init(&sb); - this->attach(fd, mode); -} - -// Open file and go into fail() state if unsuccessful -void -gzifstream::open(const char* name, - std::ios_base::openmode mode) -{ - if (!sb.open(name, mode | std::ios_base::in)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Attach to file and go into fail() state if unsuccessful -void -gzifstream::attach(int fd, - std::ios_base::openmode mode) -{ - if (!sb.attach(fd, mode | std::ios_base::in)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Close file -void -gzifstream::close() -{ - if (!sb.close()) - this->setstate(std::ios_base::failbit); -} - -/*****************************************************************************/ - -// Default constructor initializes stream buffer -gzofstream::gzofstream() -: std::ostream(NULL), sb() -{ this->init(&sb); } - -// Initialize stream buffer and open file -gzofstream::gzofstream(const char* name, - std::ios_base::openmode mode) -: std::ostream(NULL), sb() -{ - this->init(&sb); - this->open(name, mode); -} - -// Initialize stream buffer and attach to file -gzofstream::gzofstream(int fd, - std::ios_base::openmode mode) -: std::ostream(NULL), sb() -{ - this->init(&sb); - this->attach(fd, mode); -} - -// Open file and go into fail() state if unsuccessful -void -gzofstream::open(const char* name, - std::ios_base::openmode mode) -{ - if (!sb.open(name, mode | std::ios_base::out)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Attach to file and go into fail() state if unsuccessful -void -gzofstream::attach(int fd, - std::ios_base::openmode mode) -{ - if (!sb.attach(fd, mode | std::ios_base::out)) - this->setstate(std::ios_base::failbit); - else - this->clear(); -} - -// Close file -void -gzofstream::close() -{ - if (!sb.close()) - this->setstate(std::ios_base::failbit); -} diff --git a/src/contrib/zlib/contrib/iostream3/zfstream.h b/src/contrib/zlib/contrib/iostream3/zfstream.h deleted file mode 100644 index 8574479..0000000 --- a/src/contrib/zlib/contrib/iostream3/zfstream.h +++ /dev/null @@ -1,466 +0,0 @@ -/* - * A C++ I/O streams interface to the zlib gz* functions - * - * by Ludwig Schwardt - * original version by Kevin Ruland - * - * This version is standard-compliant and compatible with gcc 3.x. - */ - -#ifndef ZFSTREAM_H -#define ZFSTREAM_H - -#include // not iostream, since we don't need cin/cout -#include -#include "zlib.h" - -/*****************************************************************************/ - -/** - * @brief Gzipped file stream buffer class. - * - * This class implements basic_filebuf for gzipped files. It doesn't yet support - * seeking (allowed by zlib but slow/limited), putback and read/write access - * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard - * file streambuf. -*/ -class gzfilebuf : public std::streambuf -{ -public: - // Default constructor. - gzfilebuf(); - - // Destructor. - virtual - ~gzfilebuf(); - - /** - * @brief Set compression level and strategy on the fly. - * @param comp_level Compression level (see zlib.h for allowed values) - * @param comp_strategy Compression strategy (see zlib.h for allowed values) - * @return Z_OK on success, Z_STREAM_ERROR otherwise. - * - * Unfortunately, these parameters cannot be modified separately, as the - * previous zfstream version assumed. Since the strategy is seldom changed, - * it can default and setcompression(level) then becomes like the old - * setcompressionlevel(level). - */ - int - setcompression(int comp_level, - int comp_strategy = Z_DEFAULT_STRATEGY); - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() const { return (file != NULL); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - open(const char* name, - std::ios_base::openmode mode); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - attach(int fd, - std::ios_base::openmode mode); - - /** - * @brief Close gzipped file. - * @return @c this on success, NULL on failure. - */ - gzfilebuf* - close(); - -protected: - /** - * @brief Convert ios open mode int to mode string used by zlib. - * @return True if valid mode flag combination. - */ - bool - open_mode(std::ios_base::openmode mode, - char* c_mode) const; - - /** - * @brief Number of characters available in stream buffer. - * @return Number of characters. - * - * This indicates number of characters in get area of stream buffer. - * These characters can be read without accessing the gzipped file. - */ - virtual std::streamsize - showmanyc(); - - /** - * @brief Fill get area from gzipped file. - * @return First character in get area on success, EOF on error. - * - * This actually reads characters from gzipped file to stream - * buffer. Always buffered. - */ - virtual int_type - underflow(); - - /** - * @brief Write put area to gzipped file. - * @param c Extra character to add to buffer contents. - * @return Non-EOF on success, EOF on error. - * - * This actually writes characters in stream buffer to - * gzipped file. With unbuffered output this is done one - * character at a time. - */ - virtual int_type - overflow(int_type c = traits_type::eof()); - - /** - * @brief Installs external stream buffer. - * @param p Pointer to char buffer. - * @param n Size of external buffer. - * @return @c this on success, NULL on failure. - * - * Call setbuf(0,0) to enable unbuffered output. - */ - virtual std::streambuf* - setbuf(char_type* p, - std::streamsize n); - - /** - * @brief Flush stream buffer to file. - * @return 0 on success, -1 on error. - * - * This calls underflow(EOF) to do the job. - */ - virtual int - sync(); - -// -// Some future enhancements -// -// virtual int_type uflow(); -// virtual int_type pbackfail(int_type c = traits_type::eof()); -// virtual pos_type -// seekoff(off_type off, -// std::ios_base::seekdir way, -// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); -// virtual pos_type -// seekpos(pos_type sp, -// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); - -private: - /** - * @brief Allocate internal buffer. - * - * This function is safe to call multiple times. It will ensure - * that a proper internal buffer exists if it is required. If the - * buffer already exists or is external, the buffer pointers will be - * reset to their original state. - */ - void - enable_buffer(); - - /** - * @brief Destroy internal buffer. - * - * This function is safe to call multiple times. It will ensure - * that the internal buffer is deallocated if it exists. In any - * case, it will also reset the buffer pointers. - */ - void - disable_buffer(); - - /** - * Underlying file pointer. - */ - gzFile file; - - /** - * Mode in which file was opened. - */ - std::ios_base::openmode io_mode; - - /** - * @brief True if this object owns file descriptor. - * - * This makes the class responsible for closing the file - * upon destruction. - */ - bool own_fd; - - /** - * @brief Stream buffer. - * - * For simplicity this remains allocated on the free store for the - * entire life span of the gzfilebuf object, unless replaced by setbuf. - */ - char_type* buffer; - - /** - * @brief Stream buffer size. - * - * Defaults to system default buffer size (typically 8192 bytes). - * Modified by setbuf. - */ - std::streamsize buffer_size; - - /** - * @brief True if this object owns stream buffer. - * - * This makes the class responsible for deleting the buffer - * upon destruction. - */ - bool own_buffer; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file input stream class. - * - * This class implements ifstream for gzipped files. Seeking and putback - * is not supported yet. -*/ -class gzifstream : public std::istream -{ -public: - // Default constructor - gzifstream(); - - /** - * @brief Construct stream on gzipped file to be opened. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::in). - */ - explicit - gzifstream(const char* name, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Construct stream on already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::in). - */ - explicit - gzifstream(int fd, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * Obtain underlying stream buffer. - */ - gzfilebuf* - rdbuf() const - { return const_cast(&sb); } - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() { return sb.is_open(); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::in). - * - * Stream will be in state good() if file opens successfully; - * otherwise in state fail(). This differs from the behavior of - * ifstream, which never sets the state to good() and therefore - * won't allow you to reuse the stream for a second file unless - * you manually clear() the state. The choice is a matter of - * convenience. - */ - void - open(const char* name, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::in). - * - * Stream will be in state good() if attach succeeded; otherwise - * in state fail(). - */ - void - attach(int fd, - std::ios_base::openmode mode = std::ios_base::in); - - /** - * @brief Close gzipped file. - * - * Stream will be in state fail() if close failed. - */ - void - close(); - -private: - /** - * Underlying stream buffer. - */ - gzfilebuf sb; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file output stream class. - * - * This class implements ofstream for gzipped files. Seeking and putback - * is not supported yet. -*/ -class gzofstream : public std::ostream -{ -public: - // Default constructor - gzofstream(); - - /** - * @brief Construct stream on gzipped file to be opened. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::out). - */ - explicit - gzofstream(const char* name, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Construct stream on already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::out). - */ - explicit - gzofstream(int fd, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * Obtain underlying stream buffer. - */ - gzfilebuf* - rdbuf() const - { return const_cast(&sb); } - - /** - * @brief Check if file is open. - * @return True if file is open. - */ - bool - is_open() { return sb.is_open(); } - - /** - * @brief Open gzipped file. - * @param name File name. - * @param mode Open mode flags (forced to contain ios::out). - * - * Stream will be in state good() if file opens successfully; - * otherwise in state fail(). This differs from the behavior of - * ofstream, which never sets the state to good() and therefore - * won't allow you to reuse the stream for a second file unless - * you manually clear() the state. The choice is a matter of - * convenience. - */ - void - open(const char* name, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Attach to already open gzipped file. - * @param fd File descriptor. - * @param mode Open mode flags (forced to contain ios::out). - * - * Stream will be in state good() if attach succeeded; otherwise - * in state fail(). - */ - void - attach(int fd, - std::ios_base::openmode mode = std::ios_base::out); - - /** - * @brief Close gzipped file. - * - * Stream will be in state fail() if close failed. - */ - void - close(); - -private: - /** - * Underlying stream buffer. - */ - gzfilebuf sb; -}; - -/*****************************************************************************/ - -/** - * @brief Gzipped file output stream manipulator class. - * - * This class defines a two-argument manipulator for gzofstream. It is used - * as base for the setcompression(int,int) manipulator. -*/ -template - class gzomanip2 - { - public: - // Allows insertor to peek at internals - template - friend gzofstream& - operator<<(gzofstream&, - const gzomanip2&); - - // Constructor - gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), - T1 v1, - T2 v2); - private: - // Underlying manipulator function - gzofstream& - (*func)(gzofstream&, T1, T2); - - // Arguments for manipulator function - T1 val1; - T2 val2; - }; - -/*****************************************************************************/ - -// Manipulator function thunks through to stream buffer -inline gzofstream& -setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) -{ - (gzs.rdbuf())->setcompression(l, s); - return gzs; -} - -// Manipulator constructor stores arguments -template - inline - gzomanip2::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), - T1 v1, - T2 v2) - : func(f), val1(v1), val2(v2) - { } - -// Insertor applies underlying manipulator function to stream -template - inline gzofstream& - operator<<(gzofstream& s, const gzomanip2& m) - { return (*m.func)(s, m.val1, m.val2); } - -// Insert this onto stream to simplify setting of compression level -inline gzomanip2 -setcompression(int l, int s = Z_DEFAULT_STRATEGY) -{ return gzomanip2(&setcompression, l, s); } - -#endif // ZFSTREAM_H diff --git a/src/contrib/zlib/contrib/masmx64/bld_ml64.bat b/src/contrib/zlib/contrib/masmx64/bld_ml64.bat deleted file mode 100644 index f74bcef..0000000 --- a/src/contrib/zlib/contrib/masmx64/bld_ml64.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -ml64.exe /Flgvmat64 /c /Zi gvmat64.asm diff --git a/src/contrib/zlib/contrib/masmx64/gvmat64.asm b/src/contrib/zlib/contrib/masmx64/gvmat64.asm deleted file mode 100644 index c1817f1..0000000 --- a/src/contrib/zlib/contrib/masmx64/gvmat64.asm +++ /dev/null @@ -1,553 +0,0 @@ -;uInt longest_match_x64( -; deflate_state *s, -; IPos cur_match); /* current match */ - -; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 -; (AMD64 on Athlon 64, Opteron, Phenom -; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) -; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; -; File written by Gilles Vollant, by converting to assembly the longest_match -; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. -; -; and by taking inspiration on asm686 with masm, optimised assembly code -; from Brian Raiter, written 1998 -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software -; 3. This notice may not be removed or altered from any source distribution. -; -; -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; to compile this file for infozip Zip, I use option: -; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm -; -; to compile this file for zLib, I use option: -; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm -; Be carrefull to adapt zlib1222add below to your version of zLib -; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change -; value of zlib1222add later) -; -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ -.code -longest_match PROC - - -;LocalVarsSize equ 88 - LocalVarsSize equ 72 - -; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 -; free register : r14,r15 -; register can be saved : rsp - - chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len - ; low word: s->wmask -;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 -;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 -;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w -;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx -;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 -;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d -;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 -IFDEF INFOZIP -ELSE - nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size -ENDIF - -save_rdi equ rsp + 24 - LocalVarsSize -save_rsi equ rsp + 32 - LocalVarsSize -save_rbx equ rsp + 40 - LocalVarsSize -save_rbp equ rsp + 48 - LocalVarsSize -save_r12 equ rsp + 56 - LocalVarsSize -save_r13 equ rsp + 64 - LocalVarsSize -;save_r14 equ rsp + 72 - LocalVarsSize -;save_r15 equ rsp + 80 - LocalVarsSize - - -; summary of register usage -; scanend ebx -; scanendw bx -; chainlenwmask edx -; curmatch rsi -; curmatchd esi -; windowbestlen r8 -; scanalign r9 -; scanalignd r9d -; window r10 -; bestlen r11 -; bestlend r11d -; scanstart r12d -; scanstartw r12w -; scan r13 -; nicematch r14d -; limit r15 -; limitd r15d -; prev rcx - -; all the +4 offsets are due to the addition of pending_buf_size (in zlib -; in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, remove the +4). -; Note : these value are good with a 8 bytes boundary pack structure - - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - -IFDEF INFOZIP - -_DATA SEGMENT -COMM window_size:DWORD -; WMask ; 7fff -COMM window:BYTE:010040H -COMM prev:WORD:08000H -; MatchLen : unused -; PrevMatch : unused -COMM strstart:DWORD -COMM match_start:DWORD -; Lookahead : ignore -COMM prev_length:DWORD ; PrevLen -COMM max_chain_length:DWORD -COMM good_match:DWORD -COMM nice_match:DWORD -prev_ad equ OFFSET prev -window_ad equ OFFSET window -nicematch equ nice_match -_DATA ENDS -WMask equ 07fffh - -ELSE - - IFNDEF zlib1222add - zlib1222add equ 8 - ENDIF -dsWSize equ 56+zlib1222add+(zlib1222add/2) -dsWMask equ 64+zlib1222add+(zlib1222add/2) -dsWindow equ 72+zlib1222add -dsPrev equ 88+zlib1222add -dsMatchLen equ 128+zlib1222add -dsPrevMatch equ 132+zlib1222add -dsStrStart equ 140+zlib1222add -dsMatchStart equ 144+zlib1222add -dsLookahead equ 148+zlib1222add -dsPrevLen equ 152+zlib1222add -dsMaxChainLen equ 156+zlib1222add -dsGoodMatch equ 172+zlib1222add -dsNiceMatch equ 176+zlib1222add - -window_size equ [ rcx + dsWSize] -WMask equ [ rcx + dsWMask] -window_ad equ [ rcx + dsWindow] -prev_ad equ [ rcx + dsPrev] -strstart equ [ rcx + dsStrStart] -match_start equ [ rcx + dsMatchStart] -Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip -prev_length equ [ rcx + dsPrevLen] -max_chain_length equ [ rcx + dsMaxChainLen] -good_match equ [ rcx + dsGoodMatch] -nice_match equ [ rcx + dsNiceMatch] -ENDIF - -; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. - - - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - -;;; Retrieve the function arguments. r8d will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - -; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) - -; this clear high 32 bits of r8, which can be garbage in both r8 and rdx - - mov [save_rdi],rdi - mov [save_rsi],rsi - mov [save_rbx],rbx - mov [save_rbp],rbp -IFDEF INFOZIP - mov r8d,ecx -ELSE - mov r8d,edx -ENDIF - mov [save_r12],r12 - mov [save_r13],r13 -; mov [save_r14],r14 -; mov [save_r15],r15 - - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov edi, prev_length - mov esi, good_match - mov eax, WMask - mov ebx, max_chain_length - cmp edi, esi - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - -;;; on zlib only -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - -IFDEF INFOZIP - mov [chainlenwmask], ebx -; on infozip nice_match = [nice_match] -ELSE - mov eax, nice_match - mov [chainlenwmask], ebx - mov r10d, Lookahead - cmp r10d, eax - cmovnl r10d, eax - mov [nicematch],r10d -ENDIF - -;;; register Bytef *scan = s->window + s->strstart; - mov r10, window_ad - mov ebp, strstart - lea r13, [r10 + rbp] - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov r9,r13 - neg r13 - and r13,3 - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; -IFDEF INFOZIP - mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) -ELSE - mov eax, window_size - sub eax, MIN_LOOKAHEAD -ENDIF - xor edi,edi - sub ebp, eax - - mov r11d, prev_length - - cmovng ebp,edi - -;;; int best_len = s->prev_length; - - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - lea rsi,[r10+r11] - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx r12d,word ptr [r9] - movzx ebx, word ptr [r9 + r11 - 1] - - mov rdi, prev_ad - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop1: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry1: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop2: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry2: - cmp bx,word ptr [rsi + r8 - 1] - jz LookupLoopIsZero - -LookupLoop4: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry4: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 - jmp LookupLoopIsZero - - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; r8d = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and r8d, edx - - movzx r8d, word ptr [rdi + r8*2] - cmp r8d, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow - -LoopEntry: - - cmp bx,word ptr [rsi + r8 - 1] - jnz LookupLoop1 -LookupLoopIsZero: - cmp r12w, word ptr [r10 + r8] - jnz LookupLoop1 - - -;;; Store the current value of chainlen. - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - lea rsi,[r8+r10] - mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) - lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] - lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] - - prefetcht1 [rsi+rdx] - prefetcht1 [rdi+rdx] - - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust rdx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (rsi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - - -LoopCmps: - mov rax, [rsi + rdx] - xor rax, [rdi + rdx] - jnz LeaveLoopCmps - - mov rax, [rsi + rdx + 8] - xor rax, [rdi + rdx + 8] - jnz LeaveLoopCmps8 - - - mov rax, [rsi + rdx + 8+8] - xor rax, [rdi + rdx + 8+8] - jnz LeaveLoopCmps16 - - add rdx,8+8+8 - - jnz short LoopCmps - jmp short LenMaximum -LeaveLoopCmps16: add rdx,8 -LeaveLoopCmps8: add rdx,8 -LeaveLoopCmps: - - test eax, 0000FFFFh - jnz LenLower - - test eax,0ffffffffh - - jnz LenLower32 - - add rdx,4 - shr rax,32 - or ax,ax - jnz LenLower - -LenLower32: - shr eax,16 - add rdx,2 -LenLower: sub al, 1 - adc rdx, 0 -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea rax, [rdi + rdx] - sub rax, r9 - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. -;/////////////////////////////////// - - cmp eax, r11d - jg LongerMatch - - lea rsi,[r10+r11] - - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: - mov r11d, eax - mov match_start, r8d - cmp eax, [nicematch] - jge LeaveNow - - lea rsi,[r10+rax] - - movzx ebx, word ptr [r9 + rax - 1] - mov rdi, prev_ad - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: - mov r11d,MAX_MATCH - mov match_start, r8d - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: -IFDEF INFOZIP - mov eax,r11d -ELSE - mov eax, Lookahead - cmp r11d, eax - cmovng eax, r11d -ENDIF - -;;; Restore the stack and return from whence we came. - - - mov rsi,[save_rsi] - mov rdi,[save_rdi] - mov rbx,[save_rbx] - mov rbp,[save_rbp] - mov r12,[save_r12] - mov r13,[save_r13] -; mov r14,[save_r14] -; mov r15,[save_r15] - - - ret 0 -; please don't remove this string ! -; Your can freely use gvmat64 in any free or commercial app -; but it is far better don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 -longest_match ENDP - -match_init PROC - ret 0 -match_init ENDP - - -END diff --git a/src/contrib/zlib/contrib/masmx64/inffas8664.c b/src/contrib/zlib/contrib/masmx64/inffas8664.c deleted file mode 100644 index aa861a3..0000000 --- a/src/contrib/zlib/contrib/masmx64/inffas8664.c +++ /dev/null @@ -1,186 +0,0 @@ -/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding - * version for AMD64 on Windows using Microsoft C compiler - * - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant - * - * inffas8664.c call function inffas8664fnc in inffasx64.asm - * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - * - */ - -#include -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ - - - - typedef struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } type_ar; -#ifdef ASMINF - -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - type_ar ar; - void inffas8664fnc(struct inffast_ar * par); - - - -#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->wnext; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - - inffas8664fnc(&ar); - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = (unsigned long)ar.hold; - state->bits = ar.bits; - return; -} - -#endif diff --git a/src/contrib/zlib/contrib/masmx64/inffasx64.asm b/src/contrib/zlib/contrib/masmx64/inffasx64.asm deleted file mode 100644 index 41ec823..0000000 --- a/src/contrib/zlib/contrib/masmx64/inffasx64.asm +++ /dev/null @@ -1,396 +0,0 @@ -; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding -; version for AMD64 on Windows using Microsoft C compiler -; -; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c -; inffasx64.asm is called by inffas8664.c, which contain more info. - - -; to compile this file, I use option -; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm -; with Microsoft Macro Assembler (x64) for AMD64 -; - -; This file compile with Microsoft Macro Assembler (x64) for AMD64 -; -; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK -; -; (you can get Windows WDK with ml64 for AMD64 from -; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) -; - - -.code -inffas8664fnc PROC - -; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and -; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp -; -; All registers must be preserved across the call, except for -; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. - - - mov [rsp-8],rsi - mov [rsp-16],rdi - mov [rsp-24],r12 - mov [rsp-32],r13 - mov [rsp-40],r14 - mov [rsp-48],r15 - mov [rsp-56],rbx - - mov rax,rcx - - mov [rax+8], rbp ; /* save regs rbp and rsp */ - mov [rax], rsp - - mov rsp, rax ; /* make rsp point to &ar */ - - mov rsi, [rsp+16] ; /* rsi = in */ - mov rdi, [rsp+32] ; /* rdi = out */ - mov r9, [rsp+24] ; /* r9 = last */ - mov r10, [rsp+48] ; /* r10 = end */ - mov rbp, [rsp+64] ; /* rbp = lcode */ - mov r11, [rsp+72] ; /* r11 = dcode */ - mov rdx, [rsp+80] ; /* rdx = hold */ - mov ebx, [rsp+88] ; /* ebx = bits */ - mov r12d, [rsp+100] ; /* r12d = lmask */ - mov r13d, [rsp+104] ; /* r13d = dmask */ - ; /* r14d = len */ - ; /* r15d = dist */ - - - cld - cmp r10, rdi - je L_one_time ; /* if only one decode left */ - cmp r9, rsi - - jne L_do_loop - - -L_one_time: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code_one_time - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - jmp L_get_length_code_one_time - -ALIGN 4 -L_while_test: - cmp r10, rdi - jbe L_break_loop - cmp r9, rsi - jbe L_break_loop - -L_do_loop: - mov r8, r12 ; /* r8 = lmask */ - cmp bl, 32 - ja L_get_length_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_length_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - mov r8, r12 ; /* r8 = lmask */ - shr eax, 16 ; /* output this.val char */ - stosb - -L_get_length_code_one_time: - and r8, rdx ; /* r8 &= hold */ - mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ - -L_dolen: - mov cl, ah ; /* cl = this.bits */ - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - - test al, al - jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ - - shr eax, 16 ; /* output this.val char */ - stosb - jmp L_while_test - -ALIGN 4 -L_test_for_length_base: - mov r14d, eax ; /* len = this */ - shr r14d, 16 ; /* len = this.val */ - mov cl, al - - test al, 16 - jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ - and cl, 15 ; /* op &= 15 */ - jz L_decode_distance ; /* if (!op) */ - -L_add_bits_to_len: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r14d, eax ; /* len += hold & mask[op] */ - -L_decode_distance: - mov r8, r13 ; /* r8 = dmask */ - cmp bl, 32 - ja L_get_distance_code ; /* if (32 < bits) */ - - lodsd ; /* eax = *(uint *)in++ */ - mov cl, bl ; /* cl = bits, needs it for shifting */ - add bl, 32 ; /* bits += 32 */ - shl rax, cl - or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ - -L_get_distance_code: - and r8, rdx ; /* r8 &= hold */ - mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ - -L_dodist: - mov r15d, eax ; /* dist = this */ - shr r15d, 16 ; /* dist = this.val */ - mov cl, ah - sub bl, ah ; /* bits -= this.bits */ - shr rdx, cl ; /* hold >>= this.bits */ - mov cl, al ; /* cl = this.op */ - - test al, 16 ; /* if ((op & 16) == 0) */ - jz L_test_for_second_level_dist - and cl, 15 ; /* op &= 15 */ - jz L_check_dist_one - -L_add_bits_to_dist: - sub bl, cl - xor eax, eax - inc eax - shl eax, cl - dec eax ; /* (1 << op) - 1 */ - and eax, edx ; /* eax &= hold */ - shr rdx, cl - add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ - -L_check_window: - mov r8, rsi ; /* save in so from can use it's reg */ - mov rax, rdi - sub rax, [rsp+40] ; /* nbytes = out - beg */ - - cmp eax, r15d - jb L_clip_window ; /* if (dist > nbytes) 4.2% */ - - mov ecx, r14d ; /* ecx = len */ - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - - sar ecx, 1 - jnc L_copy_two ; /* if len % 2 == 0 */ - - rep movsw - mov al, [rsi] - mov [rdi], al - inc rdi - - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -L_copy_two: - rep movsw - mov rsi, r8 ; /* move in back to %rsi, toss from */ - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp r15d, 1 ; /* if dist 1, is a memset */ - jne L_check_window - cmp [rsp+40], rdi ; /* if out == beg, outside window */ - je L_check_window - - mov ecx, r14d ; /* ecx = len */ - mov al, [rdi-1] - mov ah, al - - sar ecx, 1 - jnc L_set_two - mov [rdi], al - inc rdi - -L_set_two: - rep stosw - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - test al, 64 - jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r14d ; /* eax += len */ - mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - test al, 64 - jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ - - xor eax, eax - inc eax - shl eax, cl - dec eax - and eax, edx ; /* eax &= hold */ - add eax, r15d ; /* eax += dist */ - mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ - jmp L_dodist - -ALIGN 4 -L_clip_window: - mov ecx, eax ; /* ecx = nbytes */ - mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ - neg ecx ; /* nbytes = -nbytes */ - - cmp eax, r15d - jb L_invalid_distance_too_far ; /* if (dist > wsize) */ - - add ecx, r15d ; /* nbytes = dist - nbytes */ - cmp dword ptr [rsp+96], 0 - jne L_wrap_around_window ; /* if (write != 0) */ - - mov rsi, [rsp+56] ; /* from = window */ - sub eax, ecx ; /* eax -= nbytes */ - add rsi, rax ; /* from += wsize - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp r14d, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* eax -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = &out[ -dist ] */ - jmp L_do_copy - -ALIGN 4 -L_wrap_around_window: - mov eax, [rsp+96] ; /* eax = write */ - cmp ecx, eax - jbe L_contiguous_in_window ; /* if (write >= nbytes) */ - - mov esi, [rsp+92] ; /* from = wsize */ - add rsi, [rsp+56] ; /* from += window */ - add rsi, rax ; /* from += write */ - sub rsi, rcx ; /* from -= nbytes */ - sub ecx, eax ; /* nbytes -= write */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, [rsp+56] ; /* from = window */ - mov ecx, [rsp+96] ; /* nbytes = write */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy - -ALIGN 4 -L_contiguous_in_window: - mov rsi, [rsp+56] ; /* rsi = window */ - add rsi, rax - sub rsi, rcx ; /* from += write - nbytes */ - - mov eax, r14d ; /* eax = len */ - cmp eax, ecx - jbe L_do_copy ; /* if (nbytes >= len) */ - - sub eax, ecx ; /* len -= nbytes */ - rep movsb - mov rsi, rdi - sub rsi, r15 ; /* from = out - dist */ - jmp L_do_copy ; /* if (nbytes >= len) */ - -ALIGN 4 -L_do_copy: - mov ecx, eax ; /* ecx = len */ - rep movsb - - mov rsi, r8 ; /* move in back to %esi, toss from */ - jmp L_while_test - -L_test_for_end_of_block: - test al, 32 - jz L_invalid_literal_length_code - mov dword ptr [rsp+116], 1 - jmp L_break_loop_with_status - -L_invalid_literal_length_code: - mov dword ptr [rsp+116], 2 - jmp L_break_loop_with_status - -L_invalid_distance_code: - mov dword ptr [rsp+116], 3 - jmp L_break_loop_with_status - -L_invalid_distance_too_far: - mov dword ptr [rsp+116], 4 - jmp L_break_loop_with_status - -L_break_loop: - mov dword ptr [rsp+116], 0 - -L_break_loop_with_status: -; /* put in, out, bits, and hold back into ar and pop esp */ - mov [rsp+16], rsi ; /* in */ - mov [rsp+32], rdi ; /* out */ - mov [rsp+88], ebx ; /* bits */ - mov [rsp+80], rdx ; /* hold */ - - mov rax, [rsp] ; /* restore rbp and rsp */ - mov rbp, [rsp+8] - mov rsp, rax - - - - mov rsi,[rsp-8] - mov rdi,[rsp-16] - mov r12,[rsp-24] - mov r13,[rsp-32] - mov r14,[rsp-40] - mov r15,[rsp-48] - mov rbx,[rsp-56] - - ret 0 -; : -; : "m" (ar) -; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", -; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" -; ); - -inffas8664fnc ENDP -;_TEXT ENDS -END diff --git a/src/contrib/zlib/contrib/masmx64/readme.txt b/src/contrib/zlib/contrib/masmx64/readme.txt deleted file mode 100644 index 652571c..0000000 --- a/src/contrib/zlib/contrib/masmx64/readme.txt +++ /dev/null @@ -1,31 +0,0 @@ -Summary -------- -This directory contains ASM implementations of the functions -longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t), -for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits. - -gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits - assembly optimized version from Jean-loup Gailly original longest_match function - -inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing - original function from Mark Adler - -Use instructions ----------------- -Assemble the .asm files using MASM and put the object files into the zlib source -directory. You can also get object files here: - - http://www.winimage.com/zLibDll/zlib124_masm_obj.zip - -define ASMV and ASMINF in your project. Include inffas8664.c in your source tree, -and inffasx64.obj and gvmat64.obj as object to link. - - -Build instructions ------------------- -run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe) - -ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK - -You can get Windows 2003 server DDK with ml64 and cl for AMD64 from - http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) diff --git a/src/contrib/zlib/contrib/masmx86/bld_ml32.bat b/src/contrib/zlib/contrib/masmx86/bld_ml32.bat deleted file mode 100644 index fcf5755..0000000 --- a/src/contrib/zlib/contrib/masmx86/bld_ml32.bat +++ /dev/null @@ -1,2 +0,0 @@ -ml /coff /Zi /c /Flmatch686.lst match686.asm -ml /coff /Zi /c /Flinffas32.lst inffas32.asm diff --git a/src/contrib/zlib/contrib/masmx86/inffas32.asm b/src/contrib/zlib/contrib/masmx86/inffas32.asm deleted file mode 100644 index cb37a81..0000000 --- a/src/contrib/zlib/contrib/masmx86/inffas32.asm +++ /dev/null @@ -1,1080 +0,0 @@ -;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding -; * -; * inffas32.asm is derivated from inffas86.c, with translation of assembly code -; * -; * Copyright (C) 1995-2003 Mark Adler -; * For conditions of distribution and use, see copyright notice in zlib.h -; * -; * Copyright (C) 2003 Chris Anderson -; * Please use the copyright conditions above. -; * -; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from -; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at -; * the moment. I have successfully compiled and tested this code with gcc2.96, -; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S -; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX -; * enabled. I will attempt to merge the MMX code into this version. Newer -; * versions of this and inffast.S can be found at -; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ -; * -; * 2005 : modification by Gilles Vollant -; */ -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is in directory \MASM611C of Win95 DDK -; ml.exe is also distributed in http://www.masm32.com/masmdl.htm -; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ -; -; -; compile with command line option -; ml /coff /Zi /c /Flinffas32.lst inffas32.asm - -; if you define NO_GZIP (see inflate.h), compile with -; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm - - -; zlib122sup is 0 fort zlib 1.2.2.1 and lower -; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head -; in inflate_state in inflate.h) -zlib1222sup equ 8 - - -IFDEF GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 -ELSE - IFNDEF NO_GUNZIP - INFLATE_MODE_TYPE equ 11 - INFLATE_MODE_BAD equ 26 - ELSE - INFLATE_MODE_TYPE equ 3 - INFLATE_MODE_BAD equ 17 - ENDIF -ENDIF - - -; 75 "inffast.S" -;FILE "inffast.S" - -;;;GLOBAL _inflate_fast - -;;;SECTION .text - - - - .586p - .mmx - - name inflate_fast_x86 - .MODEL FLAT - -_DATA segment -inflate_fast_use_mmx: - dd 1 - - -_TEXT segment - - - -ALIGN 4 - db 'Fast decoding Code from Chris Anderson' - db 0 - -ALIGN 4 -invalid_literal_length_code_msg: - db 'invalid literal/length code' - db 0 - -ALIGN 4 -invalid_distance_code_msg: - db 'invalid distance code' - db 0 - -ALIGN 4 -invalid_distance_too_far_msg: - db 'invalid distance too far back' - db 0 - - -ALIGN 4 -inflate_fast_mask: -dd 0 -dd 1 -dd 3 -dd 7 -dd 15 -dd 31 -dd 63 -dd 127 -dd 255 -dd 511 -dd 1023 -dd 2047 -dd 4095 -dd 8191 -dd 16383 -dd 32767 -dd 65535 -dd 131071 -dd 262143 -dd 524287 -dd 1048575 -dd 2097151 -dd 4194303 -dd 8388607 -dd 16777215 -dd 33554431 -dd 67108863 -dd 134217727 -dd 268435455 -dd 536870911 -dd 1073741823 -dd 2147483647 -dd 4294967295 - - -mode_state equ 0 ;/* state->mode */ -wsize_state equ (32+zlib1222sup) ;/* state->wsize */ -write_state equ (36+4+zlib1222sup) ;/* state->write */ -window_state equ (40+4+zlib1222sup) ;/* state->window */ -hold_state equ (44+4+zlib1222sup) ;/* state->hold */ -bits_state equ (48+4+zlib1222sup) ;/* state->bits */ -lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ -distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ -lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ -distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ - - -;;SECTION .text -; 205 "inffast.S" -;GLOBAL inflate_fast_use_mmx - -;SECTION .data - - -; GLOBAL inflate_fast_use_mmx:object -;.size inflate_fast_use_mmx, 4 -; 226 "inffast.S" -;SECTION .text - -ALIGN 4 -_inflate_fast proc near -.FPO (16, 4, 0, 0, 1, 0) - push edi - push esi - push ebp - push ebx - pushfd - sub esp,64 - cld - - - - - mov esi, [esp+88] - mov edi, [esi+28] - - - - - - - - mov edx, [esi+4] - mov eax, [esi+0] - - add edx,eax - sub edx,11 - - mov [esp+44],eax - mov [esp+20],edx - - mov ebp, [esp+92] - mov ecx, [esi+16] - mov ebx, [esi+12] - - sub ebp,ecx - neg ebp - add ebp,ebx - - sub ecx,257 - add ecx,ebx - - mov [esp+60],ebx - mov [esp+40],ebp - mov [esp+16],ecx -; 285 "inffast.S" - mov eax, [edi+lencode_state] - mov ecx, [edi+distcode_state] - - mov [esp+8],eax - mov [esp+12],ecx - - mov eax,1 - mov ecx, [edi+lenbits_state] - shl eax,cl - dec eax - mov [esp+0],eax - - mov eax,1 - mov ecx, [edi+distbits_state] - shl eax,cl - dec eax - mov [esp+4],eax - - mov eax, [edi+wsize_state] - mov ecx, [edi+write_state] - mov edx, [edi+window_state] - - mov [esp+52],eax - mov [esp+48],ecx - mov [esp+56],edx - - mov ebp, [edi+hold_state] - mov ebx, [edi+bits_state] -; 321 "inffast.S" - mov esi, [esp+44] - mov ecx, [esp+20] - cmp ecx,esi - ja L_align_long - - add ecx,11 - sub ecx,esi - mov eax,12 - sub eax,ecx - lea edi, [esp+28] - rep movsb - mov ecx,eax - xor eax,eax - rep stosb - lea esi, [esp+28] - mov [esp+20],esi - jmp L_is_aligned - - -L_align_long: - test esi,3 - jz L_is_aligned - xor eax,eax - mov al, [esi] - inc esi - mov ecx,ebx - add ebx,8 - shl eax,cl - or ebp,eax - jmp L_align_long - -L_is_aligned: - mov edi, [esp+60] -; 366 "inffast.S" -L_check_mmx: - cmp dword ptr [inflate_fast_use_mmx],2 - je L_init_mmx - ja L_do_loop - - push eax - push ebx - push ecx - push edx - pushfd - mov eax, [esp] - xor dword ptr [esp],0200000h - - - - - popfd - pushfd - pop edx - xor edx,eax - jz L_dont_use_mmx - xor eax,eax - cpuid - cmp ebx,0756e6547h - jne L_dont_use_mmx - cmp ecx,06c65746eh - jne L_dont_use_mmx - cmp edx,049656e69h - jne L_dont_use_mmx - mov eax,1 - cpuid - shr eax,8 - and eax,15 - cmp eax,6 - jne L_dont_use_mmx - test edx,0800000h - jnz L_use_mmx - jmp L_dont_use_mmx -L_use_mmx: - mov dword ptr [inflate_fast_use_mmx],2 - jmp L_check_mmx_pop -L_dont_use_mmx: - mov dword ptr [inflate_fast_use_mmx],3 -L_check_mmx_pop: - pop edx - pop ecx - pop ebx - pop eax - jmp L_check_mmx -; 426 "inffast.S" -ALIGN 4 -L_do_loop: -; 437 "inffast.S" - cmp bl,15 - ja L_get_length_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_length_code: - mov edx, [esp+0] - mov ecx, [esp+8] - and edx,ebp - mov eax, [ecx+edx*4] - -L_dolen: - - - - - - - mov cl,ah - sub bl,ah - shr ebp,cl - - - - - - - test al,al - jnz L_test_for_length_base - - shr eax,16 - stosb - -L_while_test: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop - jmp L_break_loop - -L_test_for_length_base: -; 502 "inffast.S" - mov edx,eax - shr edx,16 - mov cl,al - - test al,16 - jz L_test_for_second_level_length - and cl,15 - jz L_save_len - cmp bl,cl - jae L_add_bits_to_len - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_len: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - -L_save_len: - mov [esp+24],edx - - -L_decode_distance: -; 549 "inffast.S" - cmp bl,15 - ja L_get_distance_code - - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - -L_get_distance_code: - mov edx, [esp+4] - mov ecx, [esp+12] - and edx,ebp - mov eax, [ecx+edx*4] - - -L_dodist: - mov edx,eax - shr edx,16 - mov cl,ah - sub bl,ah - shr ebp,cl -; 584 "inffast.S" - mov cl,al - - test al,16 - jz L_test_for_second_level_dist - and cl,15 - jz L_check_dist_one - cmp bl,cl - jae L_add_bits_to_dist - - mov ch,cl - xor eax,eax - lodsw - mov cl,bl - add bl,16 - shl eax,cl - or ebp,eax - mov cl,ch - -L_add_bits_to_dist: - mov eax,1 - shl eax,cl - dec eax - sub bl,cl - and eax,ebp - shr ebp,cl - add edx,eax - jmp L_check_window - -L_check_window: -; 625 "inffast.S" - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,edx - jb L_clip_window - - mov ecx, [esp+24] - mov esi,edi - sub esi,edx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - jmp L_while_test - -ALIGN 4 -L_check_dist_one: - cmp edx,1 - jne L_check_window - cmp [esp+40],edi - je L_check_window - - dec edi - mov ecx, [esp+24] - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - jmp L_while_test - -ALIGN 4 -L_test_for_second_level_length: - - - - - test al,64 - jnz L_test_for_end_of_block - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+8] - mov eax, [edx+eax*4] - jmp L_dolen - -ALIGN 4 -L_test_for_second_level_dist: - - - - - test al,64 - jnz L_invalid_distance_code - - mov eax,1 - shl eax,cl - dec eax - and eax,ebp - add eax,edx - mov edx, [esp+12] - mov eax, [edx+eax*4] - jmp L_dodist - -ALIGN 4 -L_clip_window: -; 721 "inffast.S" - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,edx - jb L_invalid_distance_too_far - - add ecx,edx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window - - sub eax,ecx - add esi,eax -; 749 "inffast.S" - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_wrap_around_window: -; 793 "inffast.S" - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - jmp L_do_copy1 - -L_contiguous_in_window: -; 836 "inffast.S" - add esi,eax - sub esi,ecx - - - mov eax, [esp+24] - cmp eax,ecx - jbe L_do_copy1 - - sub eax,ecx - rep movsb - mov esi,edi - sub esi,edx - -L_do_copy1: -; 862 "inffast.S" - mov ecx,eax - rep movsb - - mov esi, [esp+44] - jmp L_while_test -; 878 "inffast.S" -ALIGN 4 -L_init_mmx: - emms - - - - - - movd mm0,ebp - mov ebp,ebx -; 896 "inffast.S" - movd mm4,dword ptr [esp+0] - movq mm3,mm4 - movd mm5,dword ptr [esp+4] - movq mm2,mm5 - pxor mm1,mm1 - mov ebx, [esp+8] - jmp L_do_loop_mmx - -ALIGN 4 -L_do_loop_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_length_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_length_code_mmx: - pand mm4,mm0 - movd eax,mm4 - movq mm4,mm3 - mov eax, [ebx+eax*4] - -L_dolen_mmx: - movzx ecx,ah - movd mm1,ecx - sub ebp,ecx - - test al,al - jnz L_test_for_length_base_mmx - - shr eax,16 - stosb - -L_while_test_mmx: - - - cmp [esp+16],edi - jbe L_break_loop - - cmp [esp+20],esi - ja L_do_loop_mmx - jmp L_break_loop - -L_test_for_length_base_mmx: - - mov edx,eax - shr edx,16 - - test al,16 - jz L_test_for_second_level_length_mmx - and eax,15 - jz L_decode_distance_mmx - - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add edx,ecx - -L_decode_distance_mmx: - psrlq mm0,mm1 - - cmp ebp,32 - ja L_get_dist_code_mmx - - movd mm6,ebp - movd mm7,dword ptr [esi] - add esi,4 - psllq mm7,mm6 - add ebp,32 - por mm0,mm7 - -L_get_dist_code_mmx: - mov ebx, [esp+12] - pand mm5,mm0 - movd eax,mm5 - movq mm5,mm2 - mov eax, [ebx+eax*4] - -L_dodist_mmx: - - movzx ecx,ah - mov ebx,eax - shr ebx,16 - sub ebp,ecx - movd mm1,ecx - - test al,16 - jz L_test_for_second_level_dist_mmx - and eax,15 - jz L_check_dist_one_mmx - -L_add_bits_to_dist_mmx: - psrlq mm0,mm1 - movd mm1,eax - movd ecx,mm0 - sub ebp,eax - and ecx, [inflate_fast_mask+eax*4] - add ebx,ecx - -L_check_window_mmx: - mov [esp+44],esi - mov eax,edi - sub eax, [esp+40] - - cmp eax,ebx - jb L_clip_window_mmx - - mov ecx,edx - mov esi,edi - sub esi,ebx - - sub ecx,3 - mov al, [esi] - mov [edi],al - mov al, [esi+1] - mov dl, [esi+2] - add esi,3 - mov [edi+1],al - mov [edi+2],dl - add edi,3 - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_check_dist_one_mmx: - cmp ebx,1 - jne L_check_window_mmx - cmp [esp+40],edi - je L_check_window_mmx - - dec edi - mov ecx,edx - mov al, [edi] - sub ecx,3 - - mov [edi+1],al - mov [edi+2],al - mov [edi+3],al - add edi,4 - rep stosb - - mov ebx, [esp+8] - jmp L_while_test_mmx - -ALIGN 4 -L_test_for_second_level_length_mmx: - test al,64 - jnz L_test_for_end_of_block - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - add ecx,edx - mov eax, [ebx+ecx*4] - jmp L_dolen_mmx - -ALIGN 4 -L_test_for_second_level_dist_mmx: - test al,64 - jnz L_invalid_distance_code - - and eax,15 - psrlq mm0,mm1 - movd ecx,mm0 - and ecx, [inflate_fast_mask+eax*4] - mov eax, [esp+12] - add ecx,ebx - mov eax, [eax+ecx*4] - jmp L_dodist_mmx - -ALIGN 4 -L_clip_window_mmx: - - mov ecx,eax - mov eax, [esp+52] - neg ecx - mov esi, [esp+56] - - cmp eax,ebx - jb L_invalid_distance_too_far - - add ecx,ebx - cmp dword ptr [esp+48],0 - jne L_wrap_around_window_mmx - - sub eax,ecx - add esi,eax - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_wrap_around_window_mmx: - - mov eax, [esp+48] - cmp ecx,eax - jbe L_contiguous_in_window_mmx - - add esi, [esp+52] - add esi,eax - sub esi,ecx - sub ecx,eax - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi, [esp+56] - mov ecx, [esp+48] - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - jmp L_do_copy1_mmx - -L_contiguous_in_window_mmx: - - add esi,eax - sub esi,ecx - - - cmp edx,ecx - jbe L_do_copy1_mmx - - sub edx,ecx - rep movsb - mov esi,edi - sub esi,ebx - -L_do_copy1_mmx: - - - mov ecx,edx - rep movsb - - mov esi, [esp+44] - mov ebx, [esp+8] - jmp L_while_test_mmx -; 1174 "inffast.S" -L_invalid_distance_code: - - - - - - mov ecx, invalid_distance_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_test_for_end_of_block: - - - - - - test al,32 - jz L_invalid_literal_length_code - - mov ecx,0 - mov edx,INFLATE_MODE_TYPE - jmp L_update_stream_state - -L_invalid_literal_length_code: - - - - - - mov ecx, invalid_literal_length_code_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_invalid_distance_too_far: - - - - mov esi, [esp+44] - mov ecx, invalid_distance_too_far_msg - mov edx,INFLATE_MODE_BAD - jmp L_update_stream_state - -L_update_stream_state: - - mov eax, [esp+88] - test ecx,ecx - jz L_skip_msg - mov [eax+24],ecx -L_skip_msg: - mov eax, [eax+28] - mov [eax+mode_state],edx - jmp L_break_loop - -ALIGN 4 -L_break_loop: -; 1243 "inffast.S" - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_next_in - - - - mov ebx,ebp - -L_update_next_in: -; 1266 "inffast.S" - mov eax, [esp+88] - mov ecx,ebx - mov edx, [eax+28] - shr ecx,3 - sub esi,ecx - shl ecx,3 - sub ebx,ecx - mov [eax+12],edi - mov [edx+bits_state],ebx - mov ecx,ebx - - lea ebx, [esp+28] - cmp [esp+20],ebx - jne L_buf_not_used - - sub esi,ebx - mov ebx, [eax+0] - mov [esp+20],ebx - add esi,ebx - mov ebx, [eax+4] - sub ebx,11 - add [esp+20],ebx - -L_buf_not_used: - mov [eax+0],esi - - mov ebx,1 - shl ebx,cl - dec ebx - - - - - - cmp dword ptr [inflate_fast_use_mmx],2 - jne L_update_hold - - - - psrlq mm0,mm1 - movd ebp,mm0 - - emms - -L_update_hold: - - - - and ebp,ebx - mov [edx+hold_state],ebp - - - - - mov ebx, [esp+20] - cmp ebx,esi - jbe L_last_is_smaller - - sub ebx,esi - add ebx,11 - mov [eax+4],ebx - jmp L_fixup_out -L_last_is_smaller: - sub esi,ebx - neg esi - add esi,11 - mov [eax+4],esi - - - - -L_fixup_out: - - mov ebx, [esp+16] - cmp ebx,edi - jbe L_end_is_smaller - - sub ebx,edi - add ebx,257 - mov [eax+16],ebx - jmp L_done -L_end_is_smaller: - sub edi,ebx - neg edi - add edi,257 - mov [eax+16],edi - - - - - -L_done: - add esp,64 - popfd - pop ebx - pop ebp - pop esi - pop edi - ret -_inflate_fast endp - -_TEXT ends -end diff --git a/src/contrib/zlib/contrib/masmx86/match686.asm b/src/contrib/zlib/contrib/masmx86/match686.asm deleted file mode 100644 index 69e0eed..0000000 --- a/src/contrib/zlib/contrib/masmx86/match686.asm +++ /dev/null @@ -1,479 +0,0 @@ -; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 -; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. -; File written by Gilles Vollant, by converting match686.S from Brian Raiter -; for MASM. This is as assembly version of longest_match -; from Jean-loup Gailly in deflate.c -; -; http://www.zlib.net -; http://www.winimage.com/zLibDll -; http://www.muppetlabs.com/~breadbox/software/assembly.html -; -; For Visual C++ 4.x and higher and ML 6.x and higher -; ml.exe is distributed in -; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 -; -; this file contain two implementation of longest_match -; -; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro -; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) -; -; for using an assembly version of longest_match, you need define ASMV in project -; -; compile the asm file running -; ml /coff /Zi /c /Flmatch686.lst match686.asm -; and do not include match686.obj in your project -; -; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for -; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor -; with autoselect (with cpu detection code) -; if you want support the old pentium optimization, you can still use these version -; -; this file is not optimized for old pentium, but it compatible with all x86 32 bits -; processor (starting 80386) -; -; -; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 - -;uInt longest_match(s, cur_match) -; deflate_state *s; -; IPos cur_match; /* current match */ - - NbStack equ 76 - cur_match equ dword ptr[esp+NbStack-0] - str_s equ dword ptr[esp+NbStack-4] -; 5 dword on top (ret,ebp,esi,edi,ebx) - adrret equ dword ptr[esp+NbStack-8] - pushebp equ dword ptr[esp+NbStack-12] - pushedi equ dword ptr[esp+NbStack-16] - pushesi equ dword ptr[esp+NbStack-20] - pushebx equ dword ptr[esp+NbStack-24] - - chain_length equ dword ptr [esp+NbStack-28] - limit equ dword ptr [esp+NbStack-32] - best_len equ dword ptr [esp+NbStack-36] - window equ dword ptr [esp+NbStack-40] - prev equ dword ptr [esp+NbStack-44] - scan_start equ word ptr [esp+NbStack-48] - wmask equ dword ptr [esp+NbStack-52] - match_start_ptr equ dword ptr [esp+NbStack-56] - nice_match equ dword ptr [esp+NbStack-60] - scan equ dword ptr [esp+NbStack-64] - - windowlen equ dword ptr [esp+NbStack-68] - match_start equ dword ptr [esp+NbStack-72] - strend equ dword ptr [esp+NbStack-76] - NbStackAdd equ (NbStack-24) - - .386p - - name gvmatch - .MODEL FLAT - - - -; all the +zlib1222add offsets are due to the addition of fields -; in zlib in the deflate_state structure since the asm code was first written -; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). -; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). -; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). - - zlib1222add equ 8 - -; Note : these value are good with a 8 bytes boundary pack structure - dep_chain_length equ 74h+zlib1222add - dep_window equ 30h+zlib1222add - dep_strstart equ 64h+zlib1222add - dep_prev_length equ 70h+zlib1222add - dep_nice_match equ 88h+zlib1222add - dep_w_size equ 24h+zlib1222add - dep_prev equ 38h+zlib1222add - dep_w_mask equ 2ch+zlib1222add - dep_good_match equ 84h+zlib1222add - dep_match_start equ 68h+zlib1222add - dep_lookahead equ 6ch+zlib1222add - - -_TEXT segment - -IFDEF NOUNDERLINE - public longest_match - public match_init -ELSE - public _longest_match - public _match_init -ENDIF - - MAX_MATCH equ 258 - MIN_MATCH equ 3 - MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) - - - -MAX_MATCH equ 258 -MIN_MATCH equ 3 -MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) -MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) - - -;;; stack frame offsets - -chainlenwmask equ esp + 0 ; high word: current chain len - ; low word: s->wmask -window equ esp + 4 ; local copy of s->window -windowbestlen equ esp + 8 ; s->window + bestlen -scanstart equ esp + 16 ; first two bytes of string -scanend equ esp + 12 ; last two bytes of string -scanalign equ esp + 20 ; dword-misalignment of string -nicematch equ esp + 24 ; a good enough match size -bestlen equ esp + 28 ; size of best match so far -scan equ esp + 32 ; ptr to string wanting match - -LocalVarsSize equ 36 -; saved ebx byte esp + 36 -; saved edi byte esp + 40 -; saved esi byte esp + 44 -; saved ebp byte esp + 48 -; return address byte esp + 52 -deflatestate equ esp + 56 ; the function arguments -curmatch equ esp + 60 - -;;; Offsets for fields in the deflate_state structure. These numbers -;;; are calculated from the definition of deflate_state, with the -;;; assumption that the compiler will dword-align the fields. (Thus, -;;; changing the definition of deflate_state could easily cause this -;;; program to crash horribly, without so much as a warning at -;;; compile time. Sigh.) - -dsWSize equ 36+zlib1222add -dsWMask equ 44+zlib1222add -dsWindow equ 48+zlib1222add -dsPrev equ 56+zlib1222add -dsMatchLen equ 88+zlib1222add -dsPrevMatch equ 92+zlib1222add -dsStrStart equ 100+zlib1222add -dsMatchStart equ 104+zlib1222add -dsLookahead equ 108+zlib1222add -dsPrevLen equ 112+zlib1222add -dsMaxChainLen equ 116+zlib1222add -dsGoodMatch equ 132+zlib1222add -dsNiceMatch equ 136+zlib1222add - - -;;; match686.asm -- Pentium-Pro-optimized version of longest_match() -;;; Written for zlib 1.1.2 -;;; Copyright (C) 1998 Brian Raiter -;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html -;;; -;; -;; This software is provided 'as-is', without any express or implied -;; warranty. In no event will the authors be held liable for any damages -;; arising from the use of this software. -;; -;; Permission is granted to anyone to use this software for any purpose, -;; including commercial applications, and to alter it and redistribute it -;; freely, subject to the following restrictions: -;; -;; 1. The origin of this software must not be misrepresented; you must not -;; claim that you wrote the original software. If you use this software -;; in a product, an acknowledgment in the product documentation would be -;; appreciated but is not required. -;; 2. Altered source versions must be plainly marked as such, and must not be -;; misrepresented as being the original software -;; 3. This notice may not be removed or altered from any source distribution. -;; - -;GLOBAL _longest_match, _match_init - - -;SECTION .text - -;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) - -;_longest_match: - IFDEF NOUNDERLINE - longest_match proc near - ELSE - _longest_match proc near - ENDIF -.FPO (9, 4, 0, 0, 1, 0) - -;;; Save registers that the compiler may be using, and adjust esp to -;;; make room for our stack frame. - - push ebp - push edi - push esi - push ebx - sub esp, LocalVarsSize - -;;; Retrieve the function arguments. ecx will hold cur_match -;;; throughout the entire function. edx will hold the pointer to the -;;; deflate_state structure during the function's setup (before -;;; entering the main loop. - - mov edx, [deflatestate] - mov ecx, [curmatch] - -;;; uInt wmask = s->w_mask; -;;; unsigned chain_length = s->max_chain_length; -;;; if (s->prev_length >= s->good_match) { -;;; chain_length >>= 2; -;;; } - - mov eax, [edx + dsPrevLen] - mov ebx, [edx + dsGoodMatch] - cmp eax, ebx - mov eax, [edx + dsWMask] - mov ebx, [edx + dsMaxChainLen] - jl LastMatchGood - shr ebx, 2 -LastMatchGood: - -;;; chainlen is decremented once beforehand so that the function can -;;; use the sign flag instead of the zero flag for the exit test. -;;; It is then shifted into the high word, to make room for the wmask -;;; value, which it will always accompany. - - dec ebx - shl ebx, 16 - or ebx, eax - mov [chainlenwmask], ebx - -;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - mov eax, [edx + dsNiceMatch] - mov ebx, [edx + dsLookahead] - cmp ebx, eax - jl LookaheadLess - mov ebx, eax -LookaheadLess: mov [nicematch], ebx - -;;; register Bytef *scan = s->window + s->strstart; - - mov esi, [edx + dsWindow] - mov [window], esi - mov ebp, [edx + dsStrStart] - lea edi, [esi + ebp] - mov [scan], edi - -;;; Determine how many bytes the scan ptr is off from being -;;; dword-aligned. - - mov eax, edi - neg eax - and eax, 3 - mov [scanalign], eax - -;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? -;;; s->strstart - (IPos)MAX_DIST(s) : NIL; - - mov eax, [edx + dsWSize] - sub eax, MIN_LOOKAHEAD - sub ebp, eax - jg LimitPositive - xor ebp, ebp -LimitPositive: - -;;; int best_len = s->prev_length; - - mov eax, [edx + dsPrevLen] - mov [bestlen], eax - -;;; Store the sum of s->window + best_len in esi locally, and in esi. - - add esi, eax - mov [windowbestlen], esi - -;;; register ush scan_start = *(ushf*)scan; -;;; register ush scan_end = *(ushf*)(scan+best_len-1); -;;; Posf *prev = s->prev; - - movzx ebx, word ptr [edi] - mov [scanstart], ebx - movzx ebx, word ptr [edi + eax - 1] - mov [scanend], ebx - mov edi, [edx + dsPrev] - -;;; Jump into the main loop. - - mov edx, [chainlenwmask] - jmp short LoopEntry - -align 4 - -;;; do { -;;; match = s->window + cur_match; -;;; if (*(ushf*)(match+best_len-1) != scan_end || -;;; *(ushf*)match != scan_start) continue; -;;; [...] -;;; } while ((cur_match = prev[cur_match & wmask]) > limit -;;; && --chain_length != 0); -;;; -;;; Here is the inner loop of the function. The function will spend the -;;; majority of its time in this loop, and majority of that time will -;;; be spent in the first ten instructions. -;;; -;;; Within this loop: -;;; ebx = scanend -;;; ecx = curmatch -;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) -;;; esi = windowbestlen - i.e., (window + bestlen) -;;; edi = prev -;;; ebp = limit - -LookupLoop: - and ecx, edx - movzx ecx, word ptr [edi + ecx*2] - cmp ecx, ebp - jbe LeaveNow - sub edx, 00010000h - js LeaveNow -LoopEntry: movzx eax, word ptr [esi + ecx - 1] - cmp eax, ebx - jnz LookupLoop - mov eax, [window] - movzx eax, word ptr [eax + ecx] - cmp eax, [scanstart] - jnz LookupLoop - -;;; Store the current value of chainlen. - - mov [chainlenwmask], edx - -;;; Point edi to the string under scrutiny, and esi to the string we -;;; are hoping to match it up with. In actuality, esi and edi are -;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is -;;; initialized to -(MAX_MATCH_8 - scanalign). - - mov esi, [window] - mov edi, [scan] - add esi, ecx - mov eax, [scanalign] - mov edx, 0fffffef8h; -(MAX_MATCH_8) - lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] - lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] - -;;; Test the strings for equality, 8 bytes at a time. At the end, -;;; adjust edx so that it is offset to the exact byte that mismatched. -;;; -;;; We already know at this point that the first three bytes of the -;;; strings match each other, and they can be safely passed over before -;;; starting the compare loop. So what this code does is skip over 0-3 -;;; bytes, as much as necessary in order to dword-align the edi -;;; pointer. (esi will still be misaligned three times out of four.) -;;; -;;; It should be confessed that this loop usually does not represent -;;; much of the total running time. Replacing it with a more -;;; straightforward "rep cmpsb" would not drastically degrade -;;; performance. - -LoopCmps: - mov eax, [esi + edx] - xor eax, [edi + edx] - jnz LeaveLoopCmps - mov eax, [esi + edx + 4] - xor eax, [edi + edx + 4] - jnz LeaveLoopCmps4 - add edx, 8 - jnz LoopCmps - jmp short LenMaximum -LeaveLoopCmps4: add edx, 4 -LeaveLoopCmps: test eax, 0000FFFFh - jnz LenLower - add edx, 2 - shr eax, 16 -LenLower: sub al, 1 - adc edx, 0 - -;;; Calculate the length of the match. If it is longer than MAX_MATCH, -;;; then automatically accept it as the best possible match and leave. - - lea eax, [edi + edx] - mov edi, [scan] - sub eax, edi - cmp eax, MAX_MATCH - jge LenMaximum - -;;; If the length of the match is not longer than the best match we -;;; have so far, then forget it and return to the lookup loop. - - mov edx, [deflatestate] - mov ebx, [bestlen] - cmp eax, ebx - jg LongerMatch - mov esi, [windowbestlen] - mov edi, [edx + dsPrev] - mov ebx, [scanend] - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; s->match_start = cur_match; -;;; best_len = len; -;;; if (len >= nice_match) break; -;;; scan_end = *(ushf*)(scan+best_len-1); - -LongerMatch: mov ebx, [nicematch] - mov [bestlen], eax - mov [edx + dsMatchStart], ecx - cmp eax, ebx - jge LeaveNow - mov esi, [window] - add esi, eax - mov [windowbestlen], esi - movzx ebx, word ptr [edi + eax - 1] - mov edi, [edx + dsPrev] - mov [scanend], ebx - mov edx, [chainlenwmask] - jmp LookupLoop - -;;; Accept the current string, with the maximum possible length. - -LenMaximum: mov edx, [deflatestate] - mov dword ptr [bestlen], MAX_MATCH - mov [edx + dsMatchStart], ecx - -;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; -;;; return s->lookahead; - -LeaveNow: - mov edx, [deflatestate] - mov ebx, [bestlen] - mov eax, [edx + dsLookahead] - cmp ebx, eax - jg LookaheadRet - mov eax, ebx -LookaheadRet: - -;;; Restore the stack and return from whence we came. - - add esp, LocalVarsSize - pop ebx - pop esi - pop edi - pop ebp - - ret -; please don't remove this string ! -; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! - db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah - - - IFDEF NOUNDERLINE - longest_match endp - ELSE - _longest_match endp - ENDIF - - IFDEF NOUNDERLINE - match_init proc near - ret - match_init endp - ELSE - _match_init proc near - ret - _match_init endp - ENDIF - - -_TEXT ends -end diff --git a/src/contrib/zlib/contrib/masmx86/readme.txt b/src/contrib/zlib/contrib/masmx86/readme.txt deleted file mode 100644 index 3f88886..0000000 --- a/src/contrib/zlib/contrib/masmx86/readme.txt +++ /dev/null @@ -1,27 +0,0 @@ - -Summary -------- -This directory contains ASM implementations of the functions -longest_match() and inflate_fast(). - - -Use instructions ----------------- -Assemble using MASM, and copy the object files into the zlib source -directory, then run the appropriate makefile, as suggested below. You can -donwload MASM from here: - - http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 - -You can also get objects files here: - - http://www.winimage.com/zLibDll/zlib124_masm_obj.zip - -Build instructions ------------------- -* With Microsoft C and MASM: -nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" - -* With Borland C and TASM: -make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj" - diff --git a/src/contrib/zlib/contrib/minizip/Makefile b/src/contrib/zlib/contrib/minizip/Makefile deleted file mode 100644 index 84eaad2..0000000 --- a/src/contrib/zlib/contrib/minizip/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -CC=cc -CFLAGS=-O -I../.. - -UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a -ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a - -.c.o: - $(CC) -c $(CFLAGS) $*.c - -all: miniunz minizip - -miniunz: $(UNZ_OBJS) - $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) - -minizip: $(ZIP_OBJS) - $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) - -test: miniunz minizip - ./minizip test readme.txt - ./miniunz -l test.zip - mv readme.txt readme.old - ./miniunz test.zip - -clean: - /bin/rm -f *.o *~ minizip miniunz diff --git a/src/contrib/zlib/contrib/minizip/Makefile.am b/src/contrib/zlib/contrib/minizip/Makefile.am deleted file mode 100644 index d343011..0000000 --- a/src/contrib/zlib/contrib/minizip/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -lib_LTLIBRARIES = libminizip.la - -if COND_DEMOS -bin_PROGRAMS = miniunzip minizip -endif - -zlib_top_srcdir = $(top_srcdir)/../.. -zlib_top_builddir = $(top_builddir)/../.. - -AM_CPPFLAGS = -I$(zlib_top_srcdir) -AM_LDFLAGS = -L$(zlib_top_builddir) - -if WIN32 -iowin32_src = iowin32.c -iowin32_h = iowin32.h -endif - -libminizip_la_SOURCES = \ - ioapi.c \ - mztools.c \ - unzip.c \ - zip.c \ - ${iowin32_src} - -libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz - -minizip_includedir = $(includedir)/minizip -minizip_include_HEADERS = \ - crypt.h \ - ioapi.h \ - mztools.h \ - unzip.h \ - zip.h \ - ${iowin32_h} - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = minizip.pc - -EXTRA_PROGRAMS = miniunzip minizip - -miniunzip_SOURCES = miniunz.c -miniunzip_LDADD = libminizip.la - -minizip_SOURCES = minizip.c -minizip_LDADD = libminizip.la -lz diff --git a/src/contrib/zlib/contrib/minizip/MiniZip64_Changes.txt b/src/contrib/zlib/contrib/minizip/MiniZip64_Changes.txt deleted file mode 100644 index 13a1bd9..0000000 --- a/src/contrib/zlib/contrib/minizip/MiniZip64_Changes.txt +++ /dev/null @@ -1,6 +0,0 @@ - -MiniZip 1.1 was derrived from MiniZip at version 1.01f - -Change in 1.0 (Okt 2009) - - **TODO - Add history** - diff --git a/src/contrib/zlib/contrib/minizip/MiniZip64_info.txt b/src/contrib/zlib/contrib/minizip/MiniZip64_info.txt deleted file mode 100644 index 57d7152..0000000 --- a/src/contrib/zlib/contrib/minizip/MiniZip64_info.txt +++ /dev/null @@ -1,74 +0,0 @@ -MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson - -Introduction ---------------------- -MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) - -When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. -All possible work was done for compatibility. - - -Background ---------------------- -When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 -support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) - -That was used as a starting point. And after that ZIP64 support was added to zip.c -some refactoring and code cleanup was also done. - - -Changed from MiniZip 1.0 to MiniZip 1.1 ---------------------------------------- -* Added ZIP64 support for unzip ( by Even Rouault ) -* Added ZIP64 support for zip ( by Mathias Svensson ) -* Reverted some changed that Even Rouault did. -* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. -* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) -* Added BZIP Compress method for zip -* Did some refactoring and code cleanup - - -Credits - - Gilles Vollant - Original MiniZip author - Even Rouault - ZIP64 unzip Support - Daniel Borca - BZip Compression method support in unzip - Mathias Svensson - ZIP64 zip support - Mathias Svensson - BZip Compression method support in zip - - Resources - - ZipLayout http://result42.com/projects/ZipFileLayout - Command line tool for Windows that shows the layout and information of the headers in a zip archive. - Used when debugging and validating the creation of zip files using MiniZip64 - - - ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT - Zip File specification - - -Notes. - * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. - -License ----------------------------------------------------------- - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - ----------------------------------------------------------- - diff --git a/src/contrib/zlib/contrib/minizip/configure.ac b/src/contrib/zlib/contrib/minizip/configure.ac deleted file mode 100644 index 5b11970..0000000 --- a/src/contrib/zlib/contrib/minizip/configure.ac +++ /dev/null @@ -1,32 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) -AC_CONFIG_SRCDIR([minizip.c]) -AM_INIT_AUTOMAKE([foreign]) -LT_INIT - -AC_MSG_CHECKING([whether to build example programs]) -AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) -AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) -if test "$enable_demos" = yes -then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -case "${host}" in - *-mingw* | mingw*) - WIN32="yes" - ;; - *) - ;; -esac -AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) - - -AC_SUBST([HAVE_UNISTD_H], [0]) -AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) -AC_CONFIG_FILES([Makefile minizip.pc]) -AC_OUTPUT diff --git a/src/contrib/zlib/contrib/minizip/crypt.h b/src/contrib/zlib/contrib/minizip/crypt.h deleted file mode 100644 index 1e9e820..0000000 --- a/src/contrib/zlib/contrib/minizip/crypt.h +++ /dev/null @@ -1,131 +0,0 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(const char* passwd, /* password string */ - unsigned char* buf, /* where to write header */ - int bufSize, - unsigned long* pkeys, - const z_crc_t* pcrc_32_tab, - unsigned long crcForCrypting) -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif diff --git a/src/contrib/zlib/contrib/minizip/ioapi.c b/src/contrib/zlib/contrib/minizip/ioapi.c deleted file mode 100644 index 7f5c191..0000000 --- a/src/contrib/zlib/contrib/minizip/ioapi.c +++ /dev/null @@ -1,247 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) - #define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(__APPLE__) || defined(IOAPI_NO_64) -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - -#include "ioapi.h" - -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ - if (pfilefunc->zfile_func64.zopen64_file != NULL) - return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); - else - { - return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); - } -} - -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); - else - { - uLong offsetTruncated = (uLong)offset; - if (offsetTruncated != offset) - return -1; - else - return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); - } -} - -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); - else - { - uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); - if ((tell_uLong) == MAXU32) - return (ZPOS64_T)-1; - else - return tell_uLong; - } -} - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ - p_filefunc64_32->zfile_func64.zopen64_file = NULL; - p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; - p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; - p_filefunc64_32->zfile_func64.ztell64_file = NULL; - p_filefunc64_32->zfile_func64.zseek64_file = NULL; - p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; - p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; - p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; -} - - - -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = FOPEN_FUNC((const char*)filename, mode_fopen); - return file; -} - - -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - - -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret; - ret = FTELLO_FUNC((FILE *)stream); - return ret; -} - -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - if (fseek((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - return ret; -} - -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - - if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - - return ret; -} - - -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = fopen64_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell64_file = ftell64_file_func; - pzlib_filefunc_def->zseek64_file = fseek64_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/src/contrib/zlib/contrib/minizip/ioapi.h b/src/contrib/zlib/contrib/minizip/ioapi.h deleted file mode 100644 index 8dcbdb0..0000000 --- a/src/contrib/zlib/contrib/minizip/ioapi.h +++ /dev/null @@ -1,208 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - - Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) - Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. - More if/def section may be needed to support other platforms - Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. - (but you should use iowin32.c for windows instead) - -*/ - -#ifndef _ZLIBIOAPI64_H -#define _ZLIBIOAPI64_H - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - - // Linux needs this to support file operation on files larger then 4+GB - // But might need better if/def to select just the platforms that needs them. - - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif - -#endif - -#include -#include -#include "zlib.h" - -#if defined(USE_FILE32API) -#define fopen64 fopen -#define ftello64 ftell -#define fseeko64 fseek -#else -#ifdef __FreeBSD__ -#define fopen64 fopen -#define ftello64 ftello -#define fseeko64 fseeko -#endif -#ifdef _MSC_VER - #define fopen64 fopen - #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) - #define ftello64 _ftelli64 - #define fseeko64 _fseeki64 - #else // old MSC - #define ftello64 ftell - #define fseeko64 fseek - #endif -#endif -#endif - -/* -#ifndef ZPOS64_T - #ifdef _WIN32 - #define ZPOS64_T fpos_t - #else - #include - #define ZPOS64_T uint64_t - #endif -#endif -*/ - -#ifdef HAVE_MINIZIP64_CONF_H -#include "mz64conf.h" -#endif - -/* a type choosen by DEFINE */ -#ifdef HAVE_64BIT_INT_CUSTOM -typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; -#else -#ifdef HAS_STDINT_H -#include "stdint.h" -typedef uint64_t ZPOS64_T; -#else - -/* Maximum unsigned 32-bit value used as placeholder for zip64 */ -#define MAXU32 0xffffffff - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef unsigned __int64 ZPOS64_T; -#else -typedef unsigned long long int ZPOS64_T; -#endif -#endif -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) - #define ZCALLBACK CALLBACK - #else - #define ZCALLBACK - #endif -#endif - - - - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); - - -/* here is the "old" 32 bits structure structure */ -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); - -typedef struct zlib_filefunc64_def_s -{ - open64_file_func zopen64_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell64_file_func ztell64_file; - seek64_file_func zseek64_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc64_def; - -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -/* now internal definition, only for zip.c and unzip.h */ -typedef struct zlib_filefunc64_32_def_s -{ - zlib_filefunc64_def zfile_func64; - open_file_func zopen32_file; - tell_file_func ztell32_file; - seek_file_func zseek32_file; -} zlib_filefunc64_32_def; - - -#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) -//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) -#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) - -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); - -#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) -#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) -#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/contrib/zlib/contrib/minizip/iowin32.c b/src/contrib/zlib/contrib/minizip/iowin32.c deleted file mode 100644 index 274f39e..0000000 --- a/src/contrib/zlib/contrib/minizip/iowin32.c +++ /dev/null @@ -1,462 +0,0 @@ -/* iowin32.c -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - -#include "zlib.h" -#include "ioapi.h" -#include "iowin32.h" - -#ifndef INVALID_HANDLE_VALUE -#define INVALID_HANDLE_VALUE (0xFFFFFFFF) -#endif - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - - -// see Include/shared/winapifamily.h in the Windows Kit -#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) -#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) -#define IOWIN32_USING_WINRT_API 1 -#endif -#endif - -voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); -uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); -long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); -int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); - -typedef struct -{ - HANDLE hf; - int error; -} WIN32FILE_IOWIN; - - -static void win32_translate_open_mode(int mode, - DWORD* lpdwDesiredAccess, - DWORD* lpdwCreationDisposition, - DWORD* lpdwShareMode, - DWORD* lpdwFlagsAndAttributes) -{ - *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; - - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - { - *lpdwDesiredAccess = GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - *lpdwShareMode = FILE_SHARE_READ; - } - else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - } - else if (mode & ZLIB_FILEFUNC_MODE_CREATE) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = CREATE_ALWAYS; - } -} - -static voidpf win32_build_iowin(HANDLE hFile) -{ - voidpf ret=NULL; - - if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - WIN32FILE_IOWIN w32fiow; - w32fiow.hf = hFile; - w32fiow.error = 0; - ret = malloc(sizeof(WIN32FILE_IOWIN)); - - if (ret==NULL) - CloseHandle(hFile); - else - *((WIN32FILE_IOWIN*)ret) = w32fiow; - } - return ret; -} - -voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API -#ifdef UNICODE - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#endif -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - -#ifdef IOWIN32_USING_WINRT_API -#ifdef UNICODE - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - { - WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; - MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); - hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); - } -#endif -#else - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); -#endif - - return win32_build_iowin(hFile); -} - - -uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!ReadFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - - -uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!WriteFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - -static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) -{ -#ifdef IOWIN32_USING_WINRT_API - return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); -#else - LONG lHigh = pos.HighPart; - DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); - BOOL fOk = TRUE; - if (dwNewPos == 0xFFFFFFFF) - if (GetLastError() != NO_ERROR) - fOk = FALSE; - if ((newPos != NULL) && (fOk)) - { - newPos->LowPart = dwNewPos; - newPos->HighPart = lHigh; - } - return fOk; -#endif -} - -long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) -{ - long ret=-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - LARGE_INTEGER pos; - pos.QuadPart = 0; - - if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=(long)pos.LowPart; - } - return ret; -} - -ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret= (ZPOS64_T)-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - if (hFile) - { - LARGE_INTEGER pos; - pos.QuadPart = 0; - - if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = (ZPOS64_T)-1; - } - else - ret=pos.QuadPart; - } - return ret; -} - - -long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - - long ret=-1; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile != NULL) - { - LARGE_INTEGER pos; - pos.QuadPart = offset; - if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - long ret=-1; - - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile) - { - LARGE_INTEGER pos; - pos.QuadPart = offset; - if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) -{ - int ret=-1; - - if (stream!=NULL) - { - HANDLE hFile; - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - CloseHandle(hFile); - ret=0; - } - free(stream); - } - return ret; -} - -int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) -{ - int ret=-1; - if (stream!=NULL) - { - ret = ((WIN32FILE_IOWIN*)stream) -> error; - } - return ret; -} - -void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen_file = win32_open_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell_file = win32_tell_file_func; - pzlib_filefunc_def->zseek_file = win32_seek_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/src/contrib/zlib/contrib/minizip/iowin32.h b/src/contrib/zlib/contrib/minizip/iowin32.h deleted file mode 100644 index 0ca0969..0000000 --- a/src/contrib/zlib/contrib/minizip/iowin32.h +++ /dev/null @@ -1,28 +0,0 @@ -/* iowin32.h -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); -void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); - -#ifdef __cplusplus -} -#endif diff --git a/src/contrib/zlib/contrib/minizip/make_vms.com b/src/contrib/zlib/contrib/minizip/make_vms.com deleted file mode 100644 index 9ac13a9..0000000 --- a/src/contrib/zlib/contrib/minizip/make_vms.com +++ /dev/null @@ -1,25 +0,0 @@ -$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig -$ open/write zdef vmsdefs.h -$ copy sys$input: zdef -$ deck -#define unix -#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from -#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator -#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord -#define Write_EndOfCentralDirectoryRecord Write_EoDRecord -$ eod -$ close zdef -$ copy vmsdefs.h,ioapi.h_orig ioapi.h -$ cc/include=[--]/prefix=all ioapi.c -$ cc/include=[--]/prefix=all miniunz.c -$ cc/include=[--]/prefix=all unzip.c -$ cc/include=[--]/prefix=all minizip.c -$ cc/include=[--]/prefix=all zip.c -$ link miniunz,unzip,ioapi,[--]libz.olb/lib -$ link minizip,zip,ioapi,[--]libz.olb/lib -$ mcr []minizip test minizip_info.txt -$ mcr []miniunz -l test.zip -$ rename minizip_info.txt; minizip_info.txt_old -$ mcr []miniunz test.zip -$ delete test.zip;* -$exit diff --git a/src/contrib/zlib/contrib/minizip/miniunz.c b/src/contrib/zlib/contrib/minizip/miniunz.c deleted file mode 100644 index 3d65401..0000000 --- a/src/contrib/zlib/contrib/minizip/miniunz.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - miniunz.c - Version 1.1, February 14h, 2010 - sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) -*/ - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#ifdef __APPLE__ -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# include -# include -#else -# include -# include -#endif - - -#include "unzip.h" - -#define CASESENSITIVITY (0) -#define WRITEBUFFERSIZE (8192) -#define MAXFILENAME (256) - -#ifdef _WIN32 -#define USEWIN32IOAPI -#include "iowin32.h" -#endif -/* - mini unzip, demo of unzip package - - usage : - Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] - - list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT - if it exists -*/ - - -/* change_file_date : change the date/time of a file - filename : the filename of the file where date/time must be modified - dosdate : the new date at the MSDos format (4 bytes) - tmu_date : the SAME new date at the tm_unz format */ -void change_file_date(filename,dosdate,tmu_date) - const char *filename; - uLong dosdate; - tm_unz tmu_date; -{ -#ifdef _WIN32 - HANDLE hFile; - FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; - - hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, - 0,NULL,OPEN_EXISTING,0,NULL); - GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); - DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); - LocalFileTimeToFileTime(&ftLocal,&ftm); - SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); - CloseHandle(hFile); -#else -#ifdef unix || __APPLE__ - struct utimbuf ut; - struct tm newdate; - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min=tmu_date.tm_min; - newdate.tm_hour=tmu_date.tm_hour; - newdate.tm_mday=tmu_date.tm_mday; - newdate.tm_mon=tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year=tmu_date.tm_year - 1900; - else - newdate.tm_year=tmu_date.tm_year ; - newdate.tm_isdst=-1; - - ut.actime=ut.modtime=mktime(&newdate); - utime(filename,&ut); -#endif -#endif -} - - -/* mymkdir and change_file_date are not 100 % portable - As I don't know well Unix, I wait feedback for the unix portion */ - -int mymkdir(dirname) - const char* dirname; -{ - int ret=0; -#ifdef _WIN32 - ret = _mkdir(dirname); -#elif unix - ret = mkdir (dirname,0775); -#elif __APPLE__ - ret = mkdir (dirname,0775); -#endif - return ret; -} - -int makedir (newdir) - char *newdir; -{ - char *buffer ; - char *p; - int len = (int)strlen(newdir); - - if (len <= 0) - return 0; - - buffer = (char*)malloc(len+1); - if (buffer==NULL) - { - printf("Error allocating memory\n"); - return UNZ_INTERNALERROR; - } - strcpy(buffer,newdir); - - if (buffer[len-1] == '/') { - buffer[len-1] = '\0'; - } - if (mymkdir(buffer) == 0) - { - free(buffer); - return 1; - } - - p = buffer+1; - while (1) - { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if ((mymkdir(buffer) == -1) && (errno == ENOENT)) - { - printf("couldn't create directory %s\n",buffer); - free(buffer); - return 0; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 1; -} - -void do_banner() -{ - printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); - printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); -} - -void do_help() -{ - printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ - " -e Extract without pathname (junk paths)\n" \ - " -x Extract with pathname\n" \ - " -v list files\n" \ - " -l list files\n" \ - " -d directory to extract into\n" \ - " -o overwrite files without prompting\n" \ - " -p extract crypted file using password\n\n"); -} - -void Display64BitsSize(ZPOS64_T n, int size_char) -{ - /* to avoid compatibility problem , we do here the conversion */ - char number[21]; - int offset=19; - int pos_string = 19; - number[20]=0; - for (;;) { - number[offset]=(char)((n%10)+'0'); - if (number[offset] != '0') - pos_string=offset; - n/=10; - if (offset==0) - break; - offset--; - } - { - int size_display_string = 19-pos_string; - while (size_char > size_display_string) - { - size_char--; - printf(" "); - } - } - - printf("%s",&number[pos_string]); -} - -int do_list(uf) - unzFile uf; -{ - uLong i; - unz_global_info64 gi; - int err; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); - printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); - for (i=0;i0) - ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); - - /* display a '*' if the file is crypted */ - if ((file_info.flag & 1) != 0) - charCrypt='*'; - - if (file_info.compression_method==0) - string_method="Stored"; - else - if (file_info.compression_method==Z_DEFLATED) - { - uInt iLevel=(uInt)((file_info.flag & 0x6)/2); - if (iLevel==0) - string_method="Defl:N"; - else if (iLevel==1) - string_method="Defl:X"; - else if ((iLevel==2) || (iLevel==3)) - string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ - } - else - if (file_info.compression_method==Z_BZIP2ED) - { - string_method="BZip2 "; - } - else - string_method="Unkn. "; - - Display64BitsSize(file_info.uncompressed_size,7); - printf(" %6s%c",string_method,charCrypt); - Display64BitsSize(file_info.compressed_size,7); - printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", - ratio, - (uLong)file_info.tmu_date.tm_mon + 1, - (uLong)file_info.tmu_date.tm_mday, - (uLong)file_info.tmu_date.tm_year % 100, - (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, - (uLong)file_info.crc,filename_inzip); - if ((i+1)='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - } - - if (rep == 'N') - skip = 1; - - if (rep == 'A') - *popt_overwrite=1; - } - - if ((skip==0) && (err==UNZ_OK)) - { - fout=FOPEN_FUNC(write_filename,"wb"); - /* some zipfile don't contain directory alone before file */ - if ((fout==NULL) && ((*popt_extract_without_path)==0) && - (filename_withoutpath!=(char*)filename_inzip)) - { - char c=*(filename_withoutpath-1); - *(filename_withoutpath-1)='\0'; - makedir(write_filename); - *(filename_withoutpath-1)=c; - fout=FOPEN_FUNC(write_filename,"wb"); - } - - if (fout==NULL) - { - printf("error opening %s\n",write_filename); - } - } - - if (fout!=NULL) - { - printf(" extracting: %s\n",write_filename); - - do - { - err = unzReadCurrentFile(uf,buf,size_buf); - if (err<0) - { - printf("error %d with zipfile in unzReadCurrentFile\n",err); - break; - } - if (err>0) - if (fwrite(buf,err,1,fout)!=1) - { - printf("error in writing extracted file\n"); - err=UNZ_ERRNO; - break; - } - } - while (err>0); - if (fout) - fclose(fout); - - if (err==0) - change_file_date(write_filename,file_info.dosDate, - file_info.tmu_date); - } - - if (err==UNZ_OK) - { - err = unzCloseCurrentFile (uf); - if (err!=UNZ_OK) - { - printf("error %d with zipfile in unzCloseCurrentFile\n",err); - } - } - else - unzCloseCurrentFile(uf); /* don't lose the error */ - } - - free(buf); - return err; -} - - -int do_extract(uf,opt_extract_without_path,opt_overwrite,password) - unzFile uf; - int opt_extract_without_path; - int opt_overwrite; - const char* password; -{ - uLong i; - unz_global_info64 gi; - int err; - FILE* fout=NULL; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - - for (i=0;i insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -miniunzip - uncompress and examine ZIP archives -.SH SYNOPSIS -.B miniunzip -.RI [ -exvlo ] -zipfile [ files_to_extract ] [-d tempdir] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the extraction of compressed file -archives in the ZIP format used by the MS-DOS utility PKZIP. It was -written as a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR unzip (1) -program. -.SH OPTIONS -A number of options are supported. With the exception of -.BI \-d\ tempdir -these must be supplied before any -other arguments and are: -.TP -.BI \-l\ ,\ \-\-v -List the files in the archive without extracting them. -.TP -.B \-o -Overwrite files without prompting for confirmation. -.TP -.B \-x -Extract files (default). -.PP -The -.I zipfile -argument is the name of the archive to process. The next argument can be used -to specify a single file to extract from the archive. - -Lastly, the following option can be specified at the end of the command-line: -.TP -.BI \-d\ tempdir -Extract the archive in the directory -.I tempdir -rather than the current directory. -.SH SEE ALSO -.BR minizip (1), -.BR zlib (3), -.BR unzip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . The -d tempdir option -was added by Dirk Eddelbuettel . diff --git a/src/contrib/zlib/contrib/minizip/minizip.1 b/src/contrib/zlib/contrib/minizip/minizip.1 deleted file mode 100644 index 1154484..0000000 --- a/src/contrib/zlib/contrib/minizip/minizip.1 +++ /dev/null @@ -1,46 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH minizip 1 "May 2, 2001" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) -.SH NAME -minizip - create ZIP archives -.SH SYNOPSIS -.B minizip -.RI [ -o ] -zipfile [ " files" ... ] -.SH DESCRIPTION -.B minizip -is a simple tool which allows the creation of compressed file archives -in the ZIP format used by the MS-DOS utility PKZIP. It was written as -a demonstration of the -.IR zlib (3) -library and therefore lack many of the features of the -.IR zip (1) -program. -.SH OPTIONS -The first argument supplied is the name of the ZIP archive to create or -.RI -o -in which case it is ignored and the second argument treated as the -name of the ZIP file. If the ZIP file already exists it will be -overwritten. -.PP -Subsequent arguments specify a list of files to place in the ZIP -archive. If none are specified then an empty archive will be created. -.SH SEE ALSO -.BR miniunzip (1), -.BR zlib (3), -.BR zip (1). -.SH AUTHOR -This program was written by Gilles Vollant. This manual page was -written by Mark Brown . - diff --git a/src/contrib/zlib/contrib/minizip/minizip.c b/src/contrib/zlib/contrib/minizip/minizip.c deleted file mode 100644 index 4288962..0000000 --- a/src/contrib/zlib/contrib/minizip/minizip.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - minizip.c - Version 1.1, February 14h, 2010 - sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) -*/ - - -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#ifdef __APPLE__ -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions -#define FOPEN_FUNC(filename, mode) fopen(filename, mode) -#define FTELLO_FUNC(stream) ftello(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) -#else -#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) -#define FTELLO_FUNC(stream) ftello64(stream) -#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) -#endif - - - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# include -# include -#else -# include -# include -# include -# include -#endif - -#include "zip.h" - -#ifdef _WIN32 - #define USEWIN32IOAPI - #include "iowin32.h" -#endif - - - -#define WRITEBUFFERSIZE (16384) -#define MAXFILENAME (256) - -#ifdef _WIN32 -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret = 0; - { - FILETIME ftLocal; - HANDLE hFind; - WIN32_FIND_DATAA ff32; - - hFind = FindFirstFileA(f,&ff32); - if (hFind != INVALID_HANDLE_VALUE) - { - FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); - FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); - FindClose(hFind); - ret = 1; - } - } - return ret; -} -#else -#ifdef unix || __APPLE__ -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret=0; - struct stat s; /* results of stat() */ - struct tm* filedate; - time_t tm_t=0; - - if (strcmp(f,"-")!=0) - { - char name[MAXFILENAME+1]; - int len = strlen(f); - if (len > MAXFILENAME) - len = MAXFILENAME; - - strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ - name[ MAXFILENAME ] = '\0'; - - if (name[len - 1] == '/') - name[len - 1] = '\0'; - /* not all systems allow stat'ing a file with / appended */ - if (stat(name,&s)==0) - { - tm_t = s.st_mtime; - ret = 1; - } - } - filedate = localtime(&tm_t); - - tmzip->tm_sec = filedate->tm_sec; - tmzip->tm_min = filedate->tm_min; - tmzip->tm_hour = filedate->tm_hour; - tmzip->tm_mday = filedate->tm_mday; - tmzip->tm_mon = filedate->tm_mon ; - tmzip->tm_year = filedate->tm_year; - - return ret; -} -#else -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - return 0; -} -#endif -#endif - - - - -int check_exist_file(filename) - const char* filename; -{ - FILE* ftestexist; - int ret = 1; - ftestexist = FOPEN_FUNC(filename,"rb"); - if (ftestexist==NULL) - ret = 0; - else - fclose(ftestexist); - return ret; -} - -void do_banner() -{ - printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); - printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); -} - -void do_help() -{ - printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ - " -o Overwrite existing file.zip\n" \ - " -a Append to existing file.zip\n" \ - " -0 Store only\n" \ - " -1 Compress faster\n" \ - " -9 Compress better\n\n" \ - " -j exclude path. store only the file name.\n\n"); -} - -/* calculate the CRC32 of a file, - because to encrypt a file, we need known the CRC32 of the file before */ -int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) -{ - unsigned long calculate_crc=0; - int err=ZIP_OK; - FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); - - unsigned long size_read = 0; - unsigned long total_read = 0; - if (fin==NULL) - { - err = ZIP_ERRNO; - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } - - if (size_read>0) - calculate_crc = crc32(calculate_crc,buf,size_read); - total_read += size_read; - - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - *result_crc=calculate_crc; - printf("file %s crc %lx\n", filenameinzip, calculate_crc); - return err; -} - -int isLargeFile(const char* filename) -{ - int largeFile = 0; - ZPOS64_T pos = 0; - FILE* pFile = FOPEN_FUNC(filename, "rb"); - - if(pFile != NULL) - { - int n = FSEEKO_FUNC(pFile, 0, SEEK_END); - pos = FTELLO_FUNC(pFile); - - printf("File : %s is %lld bytes\n", filename, pos); - - if(pos >= 0xffffffff) - largeFile = 1; - - fclose(pFile); - } - - return largeFile; -} - -int main(argc,argv) - int argc; - char *argv[]; -{ - int i; - int opt_overwrite=0; - int opt_compress_level=Z_DEFAULT_COMPRESSION; - int opt_exclude_path=0; - int zipfilenamearg = 0; - char filename_try[MAXFILENAME+16]; - int zipok; - int err=0; - int size_buf=0; - void* buf=NULL; - const char* password=NULL; - - - do_banner(); - if (argc==1) - { - do_help(); - return 0; - } - else - { - for (i=1;i='0') && (c<='9')) - opt_compress_level = c-'0'; - if ((c=='j') || (c=='J')) - opt_exclude_path = 1; - - if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - if (rep=='N') - zipok = 0; - if (rep=='A') - opt_overwrite = 2; - } - } - - if (zipok==1) - { - zipFile zf; - int errclose; -# ifdef USEWIN32IOAPI - zlib_filefunc64_def ffunc; - fill_win32_filefunc64A(&ffunc); - zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); -# else - zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); -# endif - - if (zf == NULL) - { - printf("error opening %s\n",filename_try); - err= ZIP_ERRNO; - } - else - printf("creating %s\n",filename_try); - - for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && - (strlen(argv[i]) == 2))) - { - FILE * fin; - int size_read; - const char* filenameinzip = argv[i]; - const char *savefilenameinzip; - zip_fileinfo zi; - unsigned long crcFile=0; - int zip64 = 0; - - zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = - zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; - zi.dosDate = 0; - zi.internal_fa = 0; - zi.external_fa = 0; - filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); - -/* - err = zipOpenNewFileInZip(zf,filenameinzip,&zi, - NULL,0,NULL,0,NULL / * comment * /, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level); -*/ - if ((password != NULL) && (err==ZIP_OK)) - err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); - - zip64 = isLargeFile(filenameinzip); - - /* The path name saved, should not include a leading slash. */ - /*if it did, windows/xp and dynazip couldn't read the zip file. */ - savefilenameinzip = filenameinzip; - while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) - { - savefilenameinzip++; - } - - /*should the zip file contain any path at all?*/ - if( opt_exclude_path ) - { - const char *tmpptr; - const char *lastslash = 0; - for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) - { - if( *tmpptr == '\\' || *tmpptr == '/') - { - lastslash = tmpptr; - } - } - if( lastslash != NULL ) - { - savefilenameinzip = lastslash+1; // base filename follows last slash. - } - } - - /**/ - err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, - NULL,0,NULL,0,NULL /* comment*/, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level,0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - password,crcFile, zip64); - - if (err != ZIP_OK) - printf("error in opening %s in zipfile\n",filenameinzip); - else - { - fin = FOPEN_FUNC(filenameinzip,"rb"); - if (fin==NULL) - { - err=ZIP_ERRNO; - printf("error in opening %s for reading\n",filenameinzip); - } - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } - - if (size_read>0) - { - err = zipWriteInFileInZip (zf,buf,size_read); - if (err<0) - { - printf("error in writing %s in the zipfile\n", - filenameinzip); - } - - } - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - if (err<0) - err=ZIP_ERRNO; - else - { - err = zipCloseFileInZip(zf); - if (err!=ZIP_OK) - printf("error in closing %s in the zipfile\n", - filenameinzip); - } - } - } - errclose = zipClose(zf,NULL); - if (errclose != ZIP_OK) - printf("error in closing %s\n",filename_try); - } - else - { - do_help(); - } - - free(buf); - return 0; -} diff --git a/src/contrib/zlib/contrib/minizip/minizip.pc.in b/src/contrib/zlib/contrib/minizip/minizip.pc.in deleted file mode 100644 index 69b5b7f..0000000 --- a/src/contrib/zlib/contrib/minizip/minizip.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@/minizip - -Name: minizip -Description: Minizip zip file manipulation library -Requires: -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lminizip -Libs.private: -lz -Cflags: -I${includedir} diff --git a/src/contrib/zlib/contrib/minizip/mztools.c b/src/contrib/zlib/contrib/minizip/mztools.c deleted file mode 100644 index 96891c2..0000000 --- a/src/contrib/zlib/contrib/minizip/mztools.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -/* Code */ -#include -#include -#include -#include "zlib.h" -#include "unzip.h" - -#define READ_8(adr) ((unsigned char)*(adr)) -#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) -#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) - -#define WRITE_8(buff, n) do { \ - *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ -} while(0) -#define WRITE_16(buff, n) do { \ - WRITE_8((unsigned char*)(buff), n); \ - WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ -} while(0) -#define WRITE_32(buff, n) do { \ - WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ - WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ -} while(0) - -extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) -const char* file; -const char* fileOut; -const char* fileOutTmp; -uLong* nRecovered; -uLong* bytesRecovered; -{ - int err = Z_OK; - FILE* fpZip = fopen(file, "rb"); - FILE* fpOut = fopen(fileOut, "wb"); - FILE* fpOutCD = fopen(fileOutTmp, "wb"); - if (fpZip != NULL && fpOut != NULL) { - int entries = 0; - uLong totalBytes = 0; - char header[30]; - char filename[1024]; - char extra[1024]; - int offset = 0; - int offsetCD = 0; - while ( fread(header, 1, 30, fpZip) == 30 ) { - int currentOffset = offset; - - /* File entry */ - if (READ_32(header) == 0x04034b50) { - unsigned int version = READ_16(header + 4); - unsigned int gpflag = READ_16(header + 6); - unsigned int method = READ_16(header + 8); - unsigned int filetime = READ_16(header + 10); - unsigned int filedate = READ_16(header + 12); - unsigned int crc = READ_32(header + 14); /* crc */ - unsigned int cpsize = READ_32(header + 18); /* compressed size */ - unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ - unsigned int fnsize = READ_16(header + 26); /* file name length */ - unsigned int extsize = READ_16(header + 28); /* extra field length */ - filename[0] = extra[0] = '\0'; - - /* Header */ - if (fwrite(header, 1, 30, fpOut) == 30) { - offset += 30; - } else { - err = Z_ERRNO; - break; - } - - /* Filename */ - if (fnsize > 0) { - if (fnsize < sizeof(filename)) { - if (fread(filename, 1, fnsize, fpZip) == fnsize) { - if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { - offset += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (extsize < sizeof(extra)) { - if (fread(extra, 1, extsize, fpZip) == extsize) { - if (fwrite(extra, 1, extsize, fpOut) == extsize) { - offset += extsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } - - /* Data */ - { - int dataSize = cpsize; - if (dataSize == 0) { - dataSize = uncpsize; - } - if (dataSize > 0) { - char* data = malloc(dataSize); - if (data != NULL) { - if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { - if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { - offset += dataSize; - totalBytes += dataSize; - } else { - err = Z_ERRNO; - } - } else { - err = Z_ERRNO; - } - free(data); - if (err != Z_OK) { - break; - } - } else { - err = Z_MEM_ERROR; - break; - } - } - } - - /* Central directory entry */ - { - char header[46]; - char* comment = ""; - int comsize = (int) strlen(comment); - WRITE_32(header, 0x02014b50); - WRITE_16(header + 4, version); - WRITE_16(header + 6, version); - WRITE_16(header + 8, gpflag); - WRITE_16(header + 10, method); - WRITE_16(header + 12, filetime); - WRITE_16(header + 14, filedate); - WRITE_32(header + 16, crc); - WRITE_32(header + 20, cpsize); - WRITE_32(header + 24, uncpsize); - WRITE_16(header + 28, fnsize); - WRITE_16(header + 30, extsize); - WRITE_16(header + 32, comsize); - WRITE_16(header + 34, 0); /* disk # */ - WRITE_16(header + 36, 0); /* int attrb */ - WRITE_32(header + 38, 0); /* ext attrb */ - WRITE_32(header + 42, currentOffset); - /* Header */ - if (fwrite(header, 1, 46, fpOutCD) == 46) { - offsetCD += 46; - - /* Filename */ - if (fnsize > 0) { - if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { - offsetCD += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { - offsetCD += extsize; - } else { - err = Z_ERRNO; - break; - } - } - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { - offsetCD += comsize; - } else { - err = Z_ERRNO; - break; - } - } - - - } else { - err = Z_ERRNO; - break; - } - } - - /* Success */ - entries++; - - } else { - break; - } - } - - /* Final central directory */ - { - int entriesZip = entries; - char header[22]; - char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; - int comsize = (int) strlen(comment); - if (entriesZip > 0xffff) { - entriesZip = 0xffff; - } - WRITE_32(header, 0x06054b50); - WRITE_16(header + 4, 0); /* disk # */ - WRITE_16(header + 6, 0); /* disk # */ - WRITE_16(header + 8, entriesZip); /* hack */ - WRITE_16(header + 10, entriesZip); /* hack */ - WRITE_32(header + 12, offsetCD); /* size of CD */ - WRITE_32(header + 16, offset); /* offset to CD */ - WRITE_16(header + 20, comsize); /* comment */ - - /* Header */ - if (fwrite(header, 1, 22, fpOutCD) == 22) { - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { - err = Z_ERRNO; - } - } - - } else { - err = Z_ERRNO; - } - } - - /* Final merge (file + central directory) */ - fclose(fpOutCD); - if (err == Z_OK) { - fpOutCD = fopen(fileOutTmp, "rb"); - if (fpOutCD != NULL) { - int nRead; - char buffer[8192]; - while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { - if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { - err = Z_ERRNO; - break; - } - } - fclose(fpOutCD); - } - } - - /* Close */ - fclose(fpZip); - fclose(fpOut); - - /* Wipe temporary file */ - (void)remove(fileOutTmp); - - /* Number of recovered entries */ - if (err == Z_OK) { - if (nRecovered != NULL) { - *nRecovered = entries; - } - if (bytesRecovered != NULL) { - *bytesRecovered = totalBytes; - } - } - } else { - err = Z_STREAM_ERROR; - } - return err; -} diff --git a/src/contrib/zlib/contrib/minizip/mztools.h b/src/contrib/zlib/contrib/minizip/mztools.h deleted file mode 100644 index a49a426..0000000 --- a/src/contrib/zlib/contrib/minizip/mztools.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -#ifndef _zip_tools_H -#define _zip_tools_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#include "unzip.h" - -/* Repair a ZIP file (missing central directory) - file: file to recover - fileOut: output file after recovery - fileOutTmp: temporary file name used for recovery -*/ -extern int ZEXPORT unzRepair(const char* file, - const char* fileOut, - const char* fileOutTmp, - uLong* nRecovered, - uLong* bytesRecovered); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/src/contrib/zlib/contrib/minizip/unzip.c b/src/contrib/zlib/contrib/minizip/unzip.c deleted file mode 100644 index bcfb941..0000000 --- a/src/contrib/zlib/contrib/minizip/unzip.c +++ /dev/null @@ -1,2125 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - - ------------------------------------------------------------------------------------ - Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of - compatibility with older software. The following is from the original crypt.c. - Code woven in by Terry Thorsen 1/2003. - - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - ------------------------------------------------------------------------------------ - - Changes in unzip.c - - 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos - 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* - 2007-2008 - Even Rouault - Remove old C style function prototypes - 2007-2008 - Even Rouault - Add unzip support for ZIP64 - - Copyright (C) 2007-2008 Even Rouault - - - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). - Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G - should only read the compressed/uncompressed size from the Zip64 format if - the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) - Patch created by Daniel Borca - - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - - Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson - -*/ - - -#include -#include -#include - -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - -#include "zlib.h" -#include "unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info64_internal_s -{ - ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ -} unz_file_info64_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ - ZPOS64_T total_out_64; - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ - ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip64_read_info_s; - - -/* unz64_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info64 gi; /* public global information */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - ZPOS64_T num_file; /* number of the current file in the zipfile*/ - ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ - ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ - ZPOS64_T central_pos; /* position of the beginning of the central dir*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info64 cur_file_info; /* public info about the current file in zip*/ - unz_file_info64_internal cur_file_info_internal; /* private info about it*/ - file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; - - int isZip64; - -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const z_crc_t* pcrc_32_tab; -# endif -} unz64_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been successfully opened for reading. -*/ - - -local int unz64local_getByte OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - - -/* - Locate the Central directory 64 of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream)); - -local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) - return 0; - - /* total number of disks */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - if (uL != 0x06064b50) - return 0; - - return relativeOffset; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -local unzFile unzOpenInternal (const void *path, - zlib_filefunc64_32_def* pzlib_filefunc64_32_def, - int is64bitOpenFunction) -{ - unz64_s us; - unz64_s *s; - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - us.z_filefunc.zseek32_file = NULL; - us.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); - else - us.z_filefunc = *pzlib_filefunc64_32_def; - us.is64bitOpenFunction = is64bitOpenFunction; - - - - us.filestream = ZOPEN64(us.z_filefunc, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); - if (central_pos) - { - uLong uS; - ZPOS64_T uL64; - - us.isZip64 = 1; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* size of zip64 end of central directory record */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version made by */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version needed to extract */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - us.gi.size_comment = 0; - } - else - { - central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - us.isZip64 = 0; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.gi.number_entry = uL; - - /* total number of entries in the central dir */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - number_entry_CD = uL; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.size_central_dir = uL; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.offset_central_dir = uL; - - /* zipfile comment length */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - } - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE64(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - /* to do : check if number_entry is not truncated */ - pglobal_info32->number_entry = (uLong)s->gi.number_entry; - pglobal_info32->size_comment = s->gi.size_comment; - return UNZ_OK; -} -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ - ZPOS64_T uDate; - uDate = (ZPOS64_T)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unz64local_GetCurrentFileInfoInternal (unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz64_s* s; - unz_file_info64 file_info; - unz_file_info64_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - uLong uL; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.compressed_size = uL; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.uncompressed_size = uL; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - // relative offset of local header - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info_internal.offset_curfile = uL; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - // Read extrafield - if ((err==UNZ_OK) && (extraField!=NULL)) - { - ZPOS64_T uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - - lSeek += file_info.size_file_extra - (uLong)uSizeRead; - } - else - lSeek += file_info.size_file_extra; - - - if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) - { - uLong acc = 0; - - // since lSeek now points to after the extra field we need to move back - lSeek -= file_info.size_file_extra; - - if (lSeek!=0) - { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - while(acc < file_info.size_file_extra) - { - uLong headerId; - uLong dataSize; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) - err=UNZ_ERRNO; - - /* ZIP64 extra fields */ - if (headerId == 0x0001) - { - uLong uL; - - if(file_info.uncompressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.compressed_size == MAXU32) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info_internal.offset_curfile == MAXU32) - { - /* Relative Header offset */ - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.disk_num_start == MAXU32) - { - /* Disk Start Number */ - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - } - - } - else - { - if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) - err=UNZ_ERRNO; - } - - acc += 2 + 2 + dataSize; - } - } - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - int err; - unz_file_info64 file_info64; - err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); - if ((err==UNZ_OK) && (pfile_info != NULL)) - { - pfile_info->version = file_info64.version; - pfile_info->version_needed = file_info64.version_needed; - pfile_info->flag = file_info64.flag; - pfile_info->compression_method = file_info64.compression_method; - pfile_info->dosDate = file_info64.dosDate; - pfile_info->crc = file_info64.crc; - - pfile_info->size_filename = file_info64.size_filename; - pfile_info->size_file_extra = file_info64.size_file_extra; - pfile_info->size_file_comment = file_info64.size_file_comment; - - pfile_info->disk_num_start = file_info64.disk_num_start; - pfile_info->internal_fa = file_info64.internal_fa; - pfile_info->external_fa = file_info64.external_fa; - - pfile_info->tmu_date = file_info64.tmu_date, - - - pfile_info->compressed_size = (uLong)file_info64.compressed_size; - pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; - - } - return err; -} -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ - unz64_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info64 cur_file_infoSaved; - unz_file_info64_internal cur_file_info_internalSaved; - ZPOS64_T num_fileSaved; - ZPOS64_T pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo64(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; // offset in file - ZPOS64_T num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ - unz64_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - int err = unzGetFilePos64(file,&file_pos64); - if (err==UNZ_OK) - { - file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; - file_pos->num_of_file = (uLong)file_pos64.num_of_file; - } - return err; -} - -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ - unz64_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - if (file_pos == NULL) - return UNZ_PARAMERROR; - - file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; - file_pos64.num_of_file = file_pos->num_of_file; - return unzGoToFilePos64(file,&file_pos64); -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ - int err=UNZ_OK; - uInt iSizeVar; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->total_out_64=0; - pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) - { -#ifdef HAVE_BZIP2 - pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; - pfile_in_zip_read_info->bstream.bzfree = (free_func)0; - pfile_in_zip_read_info->bstream.opaque = (voidpf)0; - pfile_in_zip_read_info->bstream.state = (voidpf)0; - - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } -#else - pfile_in_zip_read_info->raw=1; -#endif - } - else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = 0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - s->encrypted = 0; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - s=(unz64_s*)file; - if (file==NULL) - return 0; //UNZ_PARAMERROR; - pfile_in_zip_read_info=s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return 0; //UNZ_PARAMERROR; - return pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile; -} - -/** Addition for GDAL : END */ - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - - pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; - pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; - pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; - pfile_in_zip_read_info->bstream.total_in_hi32 = 0; - pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; - pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; - pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; - pfile_in_zip_read_info->bstream.total_out_hi32 = 0; - - uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; - bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; - - err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); - - uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); - pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; - pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; - pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; - pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; - pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; - pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; - - if (err==BZ_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=BZ_OK) - break; -#endif - } // end Z_BZIP2ED - else - { - ZPOS64_T uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - ZPOS64_T uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return (ZPOS64_T)-1; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return (ZPOS64_T)-1; - - return pfile_in_zip_read_info->total_out_64; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* -Read extra field from the current file (opened by unzOpenCurrentFile) -This is the local-header version of the extra field (sometimes, there is -more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - uInt read_now; - ZPOS64_T size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) - inflateEnd(&pfile_in_zip_read_info->stream); -#ifdef HAVE_BZIP2 - else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) - BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); -#endif - - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ - unz64_s* s; - uLong uReadThis ; - if (file==NULL) - return (int)UNZ_PARAMERROR; - s=(unz64_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ - unz64_s* s; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ - ZPOS64_T offset64; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - offset64 = unzGetOffset64(file); - return (uLong)offset64; -} - -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ - return unzSetOffset64(file,pos); -} diff --git a/src/contrib/zlib/contrib/minizip/unzip.h b/src/contrib/zlib/contrib/minizip/unzip.h deleted file mode 100644 index 2104e39..0000000 --- a/src/contrib/zlib/contrib/minizip/unzip.h +++ /dev/null @@ -1,437 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------------- - - Changes - - See header of unzip64.c - -*/ - -#ifndef _unz64_H -#define _unz64_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info64_s -{ - ZPOS64_T number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info64; - -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info64_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - ZPOS64_T compressed_size; /* compressed size 8 bytes */ - ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info64; - -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. - the "64" function take a const void* pointer, because the path is just the - value passed to the open64_file_func callback. - Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path - is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* - does not describe the reality -*/ - - -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unz64Open, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzCloseCurrentFile before call unzClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); - -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -typedef struct unz64_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ - ZPOS64_T num_of_file; /* # of file */ -} unz64_file_pos; - -extern int ZEXPORT unzGetFilePos64( - unzFile file, - unz64_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos64( - unzFile file, - const unz64_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, - unz_file_info64 *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); - -/** Addition for GDAL : END */ - - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); - -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz64_H */ diff --git a/src/contrib/zlib/contrib/minizip/zip.c b/src/contrib/zlib/contrib/minizip/zip.c deleted file mode 100644 index 44e88a9..0000000 --- a/src/contrib/zlib/contrib/minizip/zip.c +++ /dev/null @@ -1,2007 +0,0 @@ -/* zip.c -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - Oct-2009 - Mathias Svensson - Remove old C style function prototypes - Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives - Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. - Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. - Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - -*/ - - -#include -#include -#include -#include -#include "zlib.h" -#include "zip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ -#endif - -#ifndef Z_BUFSIZE -#define Z_BUFSIZE (64*1024) //(16384) -#endif - -#ifndef Z_MAXFILENAMEINZIP -#define Z_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -/* -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) -*/ - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - - -// NOT sure that this work on ALL platform -#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef DEF_MEM_LEVEL -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -#endif -const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - - -#define SIZEDATA_INDATABLOCK (4096-(4*4)) - -#define LOCALHEADERMAGIC (0x04034b50) -#define CENTRALHEADERMAGIC (0x02014b50) -#define ENDHEADERMAGIC (0x06054b50) -#define ZIP64ENDHEADERMAGIC (0x6064b50) -#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) - -#define FLAG_LOCALHEADER_OFFSET (0x06) -#define CRC_LOCALHEADER_OFFSET (0x0e) - -#define SIZECENTRALHEADER (0x2e) /* 46 */ - -typedef struct linkedlist_datablock_internal_s -{ - struct linkedlist_datablock_internal_s* next_datablock; - uLong avail_in_this_block; - uLong filled_in_this_block; - uLong unused; /* for future use and alignment */ - unsigned char data[SIZEDATA_INDATABLOCK]; -} linkedlist_datablock_internal; - -typedef struct linkedlist_data_s -{ - linkedlist_datablock_internal* first_block; - linkedlist_datablock_internal* last_block; -} linkedlist_data; - - -typedef struct -{ - z_stream stream; /* zLib stream structure for inflate */ -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - int stream_initialised; /* 1 is stream is initialised */ - uInt pos_in_buffered_data; /* last written byte in buffered_data */ - - ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ - char* central_header; /* central header data for the current file */ - uLong size_centralExtra; - uLong size_centralheader; /* size of the central header for cur file */ - uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ - uLong flag; /* flag of the file currently writing */ - - int method; /* compression method of file currenty wr.*/ - int raw; /* 1 for directly writing raw data */ - Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ - uLong dosDate; - uLong crc32; - int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ - ZPOS64_T pos_zip64extrainfo; - ZPOS64_T totalCompressedData; - ZPOS64_T totalUncompressedData; -#ifndef NOCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const z_crc_t* pcrc_32_tab; - int crypt_header_size; -#endif -} curfile64_info; - -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - linkedlist_data central_dir;/* datablock with central dir in construction*/ - int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ - - ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writing_offset; - ZPOS64_T number_entry; - -#ifndef NO_ADDFILEINEXISTINGZIP - char *globalcomment; -#endif - -} zip64_internal; - - -#ifndef NOCRYPT -#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED -#include "crypt.h" -#endif - -local linkedlist_datablock_internal* allocate_new_datablock() -{ - linkedlist_datablock_internal* ldi; - ldi = (linkedlist_datablock_internal*) - ALLOC(sizeof(linkedlist_datablock_internal)); - if (ldi!=NULL) - { - ldi->next_datablock = NULL ; - ldi->filled_in_this_block = 0 ; - ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; - } - return ldi; -} - -local void free_datablock(linkedlist_datablock_internal* ldi) -{ - while (ldi!=NULL) - { - linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); - ldi = ldinext; - } -} - -local void init_linkedlist(linkedlist_data* ll) -{ - ll->first_block = ll->last_block = NULL; -} - -local void free_linkedlist(linkedlist_data* ll) -{ - free_datablock(ll->first_block); - ll->first_block = ll->last_block = NULL; -} - - -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ - linkedlist_datablock_internal* ldi; - const unsigned char* from_copy; - - if (ll==NULL) - return ZIP_INTERNALERROR; - - if (ll->last_block == NULL) - { - ll->first_block = ll->last_block = allocate_new_datablock(); - if (ll->first_block == NULL) - return ZIP_INTERNALERROR; - } - - ldi = ll->last_block; - from_copy = (unsigned char*)buf; - - while (len>0) - { - uInt copy_this; - uInt i; - unsigned char* to_copy; - - if (ldi->avail_in_this_block==0) - { - ldi->next_datablock = allocate_new_datablock(); - if (ldi->next_datablock == NULL) - return ZIP_INTERNALERROR; - ldi = ldi->next_datablock ; - ll->last_block = ldi; - } - - if (ldi->avail_in_this_block < len) - copy_this = (uInt)ldi->avail_in_this_block; - else - copy_this = (uInt)len; - - to_copy = &(ldi->data[ldi->filled_in_this_block]); - - for (i=0;ifilled_in_this_block += copy_this; - ldi->avail_in_this_block -= copy_this; - from_copy += copy_this ; - len -= copy_this; - } - return ZIP_OK; -} - - - -/****************************************************************************/ - -#ifndef NO_ADDFILEINEXISTINGZIP -/* =========================================================================== - Inputs a long in LSB order to the given file - nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) -*/ - -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ - unsigned char buf[8]; - int n; - for (n = 0; n < nbByte; n++) - { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - if (x != 0) - { /* data overflow - hack for ZIP64 (X Roche) */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } - - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) - return ZIP_ERRNO; - else - return ZIP_OK; -} - -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ - unsigned char* buf=(unsigned char*)dest; - int n; - for (n = 0; n < nbByte; n++) { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - - if (x != 0) - { /* data overflow - hack for ZIP64 */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } -} - -/****************************************************************************/ - - -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ - uLong year = (uLong)ptm->tm_year; - if (year>=1980) - year-=1980; - else if (year>=80) - year-=80; - return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); -} - - -/****************************************************************************/ - -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return ZIP_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return ZIP_ERRNO; - else - return ZIP_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ - ZPOS64_T x; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<24; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<32; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<40; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<48; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<56; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - - return err; -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* -Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before -the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - { - // Signature "0x07064b50" Zip64 end of central directory locater - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - } - - if (uPosFound!=0) - break; - } - - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) - return 0; - - /* total number of disks */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto Zip64 end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' - return 0; - - return relativeOffset; -} - -int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ - int err=ZIP_OK; - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory */ - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry; - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - uLong VersionMadeBy; - uLong VersionNeeded; - uLong size_comment; - - int hasZIP64Record = 0; - - // check first if we find a ZIP64 record - central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); - if(central_pos > 0) - { - hasZIP64Record = 1; - } - else if(central_pos == 0) - { - central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); - } - -/* disable to allow appending to empty ZIP archive - if (central_pos==0) - err=ZIP_ERRNO; -*/ - - if(hasZIP64Record) - { - ZPOS64_T sizeEndOfCentralDirectory; - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* size of zip64 end of central directory record */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version made by */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version needed to extract */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - // TODO.. - // read the comment from the standard central header. - size_comment = 0; - } - else - { - // Read End of central Directory info - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central dir on this disk */ - number_entry = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry = uL; - - /* total number of entries in the central dir */ - number_entry_CD = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry_CD = uL; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - size_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - size_central_dir = uL; - - /* offset of start of central directory with respect to the starting disk number */ - offset_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - offset_central_dir = uL; - - - /* zipfile global comment length */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) - err=ZIP_ERRNO; - } - - if ((central_posz_filefunc, pziinit->filestream); - return ZIP_ERRNO; - } - - if (size_comment>0) - { - pziinit->globalcomment = (char*)ALLOC(size_comment+1); - if (pziinit->globalcomment) - { - size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); - pziinit->globalcomment[size_comment]=0; - } - } - - byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writing_offset = byte_before_the_zipfile; - - { - ZPOS64_T size_central_dir_to_read = size_central_dir; - size_t buf_size = SIZEDATA_INDATABLOCK; - void* buf_read = (void*)ALLOC(buf_size); - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - while ((size_central_dir_to_read>0) && (err==ZIP_OK)) - { - ZPOS64_T read_this = SIZEDATA_INDATABLOCK; - if (read_this > size_central_dir_to_read) - read_this = size_central_dir_to_read; - - if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) - err=ZIP_ERRNO; - - if (err==ZIP_OK) - err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); - - size_central_dir_to_read-=read_this; - } - TRYFREE(buf_read); - } - pziinit->begin_pos = byte_before_the_zipfile; - pziinit->number_entry = number_entry_CD; - - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - return err; -} - - -#endif /* !NO_ADDFILEINEXISTINGZIP*/ - - -/************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ - zip64_internal ziinit; - zip64_internal* zi; - int err=ZIP_OK; - - ziinit.z_filefunc.zseek32_file = NULL; - ziinit.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); - else - ziinit.z_filefunc = *pzlib_filefunc64_32_def; - - ziinit.filestream = ZOPEN64(ziinit.z_filefunc, - pathname, - (append == APPEND_STATUS_CREATE) ? - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); - - if (ziinit.filestream == NULL) - return NULL; - - if (append == APPEND_STATUS_CREATEAFTER) - ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); - - ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); - ziinit.in_opened_file_inzip = 0; - ziinit.ci.stream_initialised = 0; - ziinit.number_entry = 0; - ziinit.add_position_when_writing_offset = 0; - init_linkedlist(&(ziinit.central_dir)); - - - - zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); - if (zi==NULL) - { - ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); - return NULL; - } - - /* now we add file in a zipfile */ -# ifndef NO_ADDFILEINEXISTINGZIP - ziinit.globalcomment = NULL; - if (append == APPEND_STATUS_ADDINZIP) - { - // Read and Cache Central Directory Records - err = LoadCentralDirectoryRecord(&ziinit); - } - - if (globalcomment) - { - *globalcomment = ziinit.globalcomment; - } -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - - if (err != ZIP_OK) - { -# ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); - return NULL; - } - else - { - *zi = ziinit; - return (zipFile)zi; - } -} - -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ - if (pzlib_filefunc32_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ - if (pzlib_filefunc_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; - zlib_filefunc64_32_def_fill.ztell32_file = NULL; - zlib_filefunc64_32_def_fill.zseek32_file = NULL; - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - - - -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ - return zipOpen3((const void*)pathname,append,NULL,NULL); -} - -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ - return zipOpen3(pathname,append,NULL,NULL); -} - -int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ - /* write the local header */ - int err; - uInt size_filename = (uInt)strlen(filename); - uInt size_extrafield = size_extrafield_local; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); - - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); - - // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ - } - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); - - if(zi->ci.zip64) - { - size_extrafield += 20; - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); - - if ((err==ZIP_OK) && (size_filename > 0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) - err = ZIP_ERRNO; - } - - if ((err==ZIP_OK) && (size_extrafield_local > 0)) - { - if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) - err = ZIP_ERRNO; - } - - - if ((err==ZIP_OK) && (zi->ci.zip64)) - { - // write the Zip64 extended info - short HeaderID = 1; - short DataSize = 16; - ZPOS64_T CompressedSize = 0; - ZPOS64_T UncompressedSize = 0; - - // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) - zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); - } - - return err; -} - -/* - NOTE. - When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped - before calling this function it can be done with zipRemoveExtraInfoBlock - - It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize - unnecessary allocations. - */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase, int zip64) -{ - zip64_internal* zi; - uInt size_filename; - uInt size_comment; - uInt i; - int err = ZIP_OK; - -# ifdef NOCRYPT - (crcForCrypting); - if (password != NULL) - return ZIP_PARAMERROR; -# endif - - if (file == NULL) - return ZIP_PARAMERROR; - -#ifdef HAVE_BZIP2 - if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) - return ZIP_PARAMERROR; -#else - if ((method!=0) && (method!=Z_DEFLATED)) - return ZIP_PARAMERROR; -#endif - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - if (err != ZIP_OK) - return err; - } - - if (filename==NULL) - filename="-"; - - if (comment==NULL) - size_comment = 0; - else - size_comment = (uInt)strlen(comment); - - size_filename = (uInt)strlen(filename); - - if (zipfi == NULL) - zi->ci.dosDate = 0; - else - { - if (zipfi->dosDate != 0) - zi->ci.dosDate = zipfi->dosDate; - else - zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); - } - - zi->ci.flag = flagBase; - if ((level==8) || (level==9)) - zi->ci.flag |= 2; - if (level==2) - zi->ci.flag |= 4; - if (level==1) - zi->ci.flag |= 6; - if (password != NULL) - zi->ci.flag |= 1; - - zi->ci.crc32 = 0; - zi->ci.method = method; - zi->ci.encrypt = 0; - zi->ci.stream_initialised = 0; - zi->ci.pos_in_buffered_data = 0; - zi->ci.raw = raw; - zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); - - zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; - zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data - - zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); - - zi->ci.size_centralExtra = size_extrafield_global; - zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); - /* version info */ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); - zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); - zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); - zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); - zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ - zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); - zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); - zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); - else - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); - - if(zi->ci.pos_local_header >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); - - for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = - *(((const char*)extrafield_global)+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ - size_extrafield_global+i) = *(comment+i); - if (zi->ci.central_header == NULL) - return ZIP_INTERNALERROR; - - zi->ci.zip64 = zip64; - zi->ci.totalCompressedData = 0; - zi->ci.totalUncompressedData = 0; - zi->ci.pos_zip64extrainfo = 0; - - err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); - -#ifdef HAVE_BZIP2 - zi->ci.bstream.avail_in = (uInt)0; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - zi->ci.bstream.total_in_hi32 = 0; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_out_hi32 = 0; - zi->ci.bstream.total_out_lo32 = 0; -#endif - - zi->ci.stream.avail_in = (uInt)0; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - zi->ci.stream.total_in = 0; - zi->ci.stream.total_out = 0; - zi->ci.stream.data_type = Z_BINARY; - -#ifdef HAVE_BZIP2 - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) -#else - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) -#endif - { - if(zi->ci.method == Z_DEFLATED) - { - zi->ci.stream.zalloc = (alloc_func)0; - zi->ci.stream.zfree = (free_func)0; - zi->ci.stream.opaque = (voidpf)0; - - if (windowBits>0) - windowBits = -windowBits; - - err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); - - if (err==Z_OK) - zi->ci.stream_initialised = Z_DEFLATED; - } - else if(zi->ci.method == Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - // Init BZip stuff here - zi->ci.bstream.bzalloc = 0; - zi->ci.bstream.bzfree = 0; - zi->ci.bstream.opaque = (voidpf)0; - - err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); - if(err == BZ_OK) - zi->ci.stream_initialised = Z_BZIP2ED; -#endif - } - - } - -# ifndef NOCRYPT - zi->ci.crypt_header_size = 0; - if ((err==Z_OK) && (password != NULL)) - { - unsigned char bufHead[RAND_HEAD_LEN]; - unsigned int sizeHead; - zi->ci.encrypt = 1; - zi->ci.pcrc_32_tab = get_crc_table(); - /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ - - sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); - zi->ci.crypt_header_size = sizeHead; - - if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) - err = ZIP_ERRNO; - } -# endif - - if (err==Z_OK) - zi->in_opened_file_inzip = 1; - return err; -} - -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ - int err=ZIP_OK; - - if (zi->ci.encrypt != 0) - { -#ifndef NOCRYPT - uInt i; - int t; - for (i=0;ici.pos_in_buffered_data;i++) - zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); -#endif - } - - if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) - err = ZIP_ERRNO; - - zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED) - { - zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_in_hi32 = 0; - } - else -#endif - { - zi->ci.totalUncompressedData += zi->ci.stream.total_in; - zi->ci.stream.total_in = 0; - } - - - zi->ci.pos_in_buffered_data = 0; - - return err; -} - -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ - zip64_internal* zi; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - - zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) - { - zi->ci.bstream.next_in = (void*)buf; - zi->ci.bstream.avail_in = len; - err = BZ_RUN_OK; - - while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) - { - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - - - if(err != BZ_RUN_OK) - break; - - if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; -// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; - } - } - - if(err == BZ_RUN_OK) - err = ZIP_OK; - } - else -#endif - { - zi->ci.stream.next_in = (Bytef*)buf; - zi->ci.stream.avail_in = len; - - while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) - { - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - - - if(err != ZIP_OK) - break; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_NO_FLUSH); - if(uTotalOutBefore > zi->ci.stream.total_out) - { - int bBreak = 0; - bBreak++; - } - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - else - { - uInt copy_this,i; - if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) - copy_this = zi->ci.stream.avail_in; - else - copy_this = zi->ci.stream.avail_out; - - for (i = 0; i < copy_this; i++) - *(((char*)zi->ci.stream.next_out)+i) = - *(((const char*)zi->ci.stream.next_in)+i); - { - zi->ci.stream.avail_in -= copy_this; - zi->ci.stream.avail_out-= copy_this; - zi->ci.stream.next_in+= copy_this; - zi->ci.stream.next_out+= copy_this; - zi->ci.stream.total_in+= copy_this; - zi->ci.stream.total_out+= copy_this; - zi->ci.pos_in_buffered_data += copy_this; - } - } - }// while(...) - } - - return err; -} - -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ - return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); -} - -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ - zip64_internal* zi; - ZPOS64_T compressed_size; - uLong invalidValue = 0xffffffff; - short datasize = 0; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - zi->ci.stream.avail_in = 0; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - while (err==ZIP_OK) - { - uLong uTotalOutBefore; - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_FINISH); - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - } - else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { -#ifdef HAVE_BZIP2 - err = BZ_FINISH_OK; - while (err==BZ_FINISH_OK) - { - uLong uTotalOutBefore; - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.bstream.total_out_lo32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); - if(err == BZ_STREAM_END) - err = Z_STREAM_END; - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); - } - - if(err == BZ_FINISH_OK) - err = ZIP_OK; -#endif - } - - if (err==Z_STREAM_END) - err=ZIP_OK; /* this is normal */ - - if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) - { - if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) - err = ZIP_ERRNO; - } - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - int tmp_err = deflateEnd(&zi->ci.stream); - if (err == ZIP_OK) - err = tmp_err; - zi->ci.stream_initialised = 0; - } -#ifdef HAVE_BZIP2 - else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); - if (err==ZIP_OK) - err = tmperr; - zi->ci.stream_initialised = 0; - } -#endif - - if (!zi->ci.raw) - { - crc32 = (uLong)zi->ci.crc32; - uncompressed_size = zi->ci.totalUncompressedData; - } - compressed_size = zi->ci.totalCompressedData; - -# ifndef NOCRYPT - compressed_size += zi->ci.crypt_header_size; -# endif - - // update Current Item crc and sizes, - if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) - { - /*version Made by*/ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); - /*version needed*/ - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); - - } - - zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ - - - if(compressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ - - /// set internal file attributes field - if (zi->ci.stream.data_type == Z_ASCII) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); - - if(uncompressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ - - // Add ZIP64 extra info field for uncompressed size - if(uncompressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for compressed size - if(compressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for relative offset to local file header of current file - if(zi->ci.pos_local_header >= 0xffffffff) - datasize += 8; - - if(datasize > 0) - { - char* p = NULL; - - if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) - { - // we can not write more data to the buffer that we have room for. - return ZIP_BADZIPFILE; - } - - p = zi->ci.central_header + zi->ci.size_centralheader; - - // Add Extra Information Header for 'ZIP64 information' - zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID - p += 2; - zip64local_putValue_inmemory(p, datasize, 2); // DataSize - p += 2; - - if(uncompressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, uncompressed_size, 8); - p += 8; - } - - if(compressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, compressed_size, 8); - p += 8; - } - - if(zi->ci.pos_local_header >= 0xffffffff) - { - zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); - p += 8; - } - - // Update how much extra free space we got in the memory buffer - // and increase the centralheader size so the new ZIP64 fields are included - // ( 4 below is the size of HeaderID and DataSize field ) - zi->ci.size_centralExtraFree -= datasize + 4; - zi->ci.size_centralheader += datasize + 4; - - // Update the extra info size field - zi->ci.size_centralExtra += datasize + 4; - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); - } - - if (err==ZIP_OK) - err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); - - free(zi->ci.central_header); - - if (err==ZIP_OK) - { - // Update the LocalFileHeader with the new values. - - ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ - - if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) - { - if(zi->ci.pos_zip64extrainfo > 0) - { - // Update the size in the ZIP64 extended field. - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); - } - else - err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal - } - else - { - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); - } - - if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - } - - zi->number_entry ++; - zi->in_opened_file_inzip = 0; - - return err; -} - -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ - return zipCloseFileInZipRaw (file,0,0); -} - -int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ - int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); - - /*num disks*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - /*relative offset*/ - if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); - - /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); - - return err; -} - -int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - uLong Zip64DataSize = 44; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? - - if (err==ZIP_OK) /* version made by */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* version needed */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* total number of entries in the central dir */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); - } - return err; -} -int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - /*signature*/ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - { - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - } - - if (err==ZIP_OK) /* total number of entries in the central dir */ - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; - if(pos >= 0xffffffff) - { - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); - } - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); - } - - return err; -} - -int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ - int err = ZIP_OK; - uInt size_global_comment = 0; - - if(global_comment != NULL) - size_global_comment = (uInt)strlen(global_comment); - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); - - if (err == ZIP_OK && size_global_comment > 0) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) - err = ZIP_ERRNO; - } - return err; -} - -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ - zip64_internal* zi; - int err = 0; - uLong size_centraldir = 0; - ZPOS64_T centraldir_pos_inzip; - ZPOS64_T pos; - - if (file == NULL) - return ZIP_PARAMERROR; - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - } - -#ifndef NO_ADDFILEINEXISTINGZIP - if (global_comment==NULL) - global_comment = zi->globalcomment; -#endif - - centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (err==ZIP_OK) - { - linkedlist_datablock_internal* ldi = zi->central_dir.first_block; - while (ldi!=NULL) - { - if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) - err = ZIP_ERRNO; - } - - size_centraldir += ldi->filled_in_this_block; - ldi = ldi->next_datablock; - } - } - free_linkedlist(&(zi->central_dir)); - - pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; - if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) - { - ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); - Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); - } - - if (err==ZIP_OK) - err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - if(err == ZIP_OK) - err = Write_GlobalComment(zi, global_comment); - - if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) - if (err == ZIP_OK) - err = ZIP_ERRNO; - -#ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); -#endif - TRYFREE(zi); - - return err; -} - -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ - char* p = pData; - int size = 0; - char* pNewHeader; - char* pTmp; - short header; - short dataSize; - - int retVal = ZIP_OK; - - if(pData == NULL || *dataLen < 4) - return ZIP_PARAMERROR; - - pNewHeader = (char*)ALLOC(*dataLen); - pTmp = pNewHeader; - - while(p < (pData + *dataLen)) - { - header = *(short*)p; - dataSize = *(((short*)p)+1); - - if( header == sHeader ) // Header found. - { - p += dataSize + 4; // skip it. do not copy to temp buffer - } - else - { - // Extra Info block should not be removed, So copy it to the temp buffer. - memcpy(pTmp, p, dataSize + 4); - p += dataSize + 4; - size += dataSize + 4; - } - - } - - if(size < *dataLen) - { - // clean old extra info block. - memset(pData,0, *dataLen); - - // copy the new extra info block over the old - if(size > 0) - memcpy(pData, pNewHeader, size); - - // set the new extra info size - *dataLen = size; - - retVal = ZIP_OK; - } - else - retVal = ZIP_ERRNO; - - TRYFREE(pNewHeader); - - return retVal; -} diff --git a/src/contrib/zlib/contrib/minizip/zip.h b/src/contrib/zlib/contrib/minizip/zip.h deleted file mode 100644 index 8aaebb6..0000000 --- a/src/contrib/zlib/contrib/minizip/zip.h +++ /dev/null @@ -1,362 +0,0 @@ -/* zip.h -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------- - - Changes - - See header of zip.h - -*/ - -#ifndef _zip12_H -#define _zip12_H - -#ifdef __cplusplus -extern "C" { -#endif - -//#define HAVE_BZIP2 - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagzipFile__ { int unused; } zipFile__; -typedef zipFile__ *zipFile; -#else -typedef voidp zipFile; -#endif - -#define ZIP_OK (0) -#define ZIP_EOF (0) -#define ZIP_ERRNO (Z_ERRNO) -#define ZIP_PARAMERROR (-102) -#define ZIP_BADZIPFILE (-103) -#define ZIP_INTERNALERROR (-104) - -#ifndef DEF_MEM_LEVEL -# if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -# else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -# endif -#endif -/* default memLevel */ - -/* tm_zip contain date/time info */ -typedef struct tm_zip_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_zip; - -typedef struct -{ - tm_zip tmz_date; /* date in understandable format */ - uLong dosDate; /* if dos_date == 0, tmu_date is used */ -/* uLong flag; */ /* general purpose bit flag 2 bytes */ - - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ -} zip_fileinfo; - -typedef const char* zipcharpc; - - -#define APPEND_STATUS_CREATE (0) -#define APPEND_STATUS_CREATEAFTER (1) -#define APPEND_STATUS_ADDINZIP (2) - -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); -/* - Create a zipfile. - pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on - an Unix computer "zlib/zlib113.zip". - if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip - will be created at the end of the file. - (useful if the file contain a self extractor code) - if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will - add files in existing zip (be sure you don't add file that doesn't exist) - If the zipfile cannot be opened, the return value is NULL. - Else, the return value is a zipFile Handle, usable with other function - of this zip package. -*/ - -/* Note : there is no delete function into a zipfile. - If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte -*/ - -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); - -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); - -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); - -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); - -/* - Open a file in the ZIP for writing. - filename : the filename in zip (if NULL, '-' without quote will be used - *zipfi contain supplemental information - if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local - contains the extrafield data the the local header - if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global - contains the extrafield data the the local header - if comment != NULL, comment contain the comment string - method contain the compression method (0 for store, Z_DEFLATED for deflate) - level contain the level of compression (can be Z_DEFAULT_COMPRESSION) - zip64 is set to 1 if a zip64 extended information block should be added to the local file header. - this MUST be '1' if the uncompressed size is >= 0xffffffff. - -*/ - - -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); - - -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); -/* - Same than zipOpenNewFileInZip, except if raw=1, we write raw file - */ - -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); - -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); - -/* - Same than zipOpenNewFileInZip2, except - windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 - password : crypting password (NULL for no crypting) - crcForCrypting : crc of file to compress (needed for crypting) - */ - -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); - - -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); -/* - Same than zipOpenNewFileInZip4, except - versionMadeBy : value for Version made by field - flag : value for flag field (compression level info will be added) - */ - - -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); -/* - Write data in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); -/* - Close the current file in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); - -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); - -/* - Close the current file in the zipfile, for file opened with - parameter raw=1 in zipOpenNewFileInZip2 - uncompressed_size and crc32 are value for the uncompressed size -*/ - -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); -/* - Close the zipfile -*/ - - -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); -/* - zipRemoveExtraInfoBlock - Added by Mathias Svensson - - Remove extra information block from a extra information data for the local file header or central directory header - - It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. - - 0x0001 is the signature header for the ZIP64 extra information blocks - - usage. - Remove ZIP64 Extra information from a central director extra field data - zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); - - Remove ZIP64 Extra information from a Local File Header extra field data - zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _zip64_H */ diff --git a/src/contrib/zlib/contrib/pascal/example.pas b/src/contrib/zlib/contrib/pascal/example.pas deleted file mode 100644 index 5518b36..0000000 --- a/src/contrib/zlib/contrib/pascal/example.pas +++ /dev/null @@ -1,599 +0,0 @@ -(* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Pascal translation - * Copyright (C) 1998 by Jacques Nomssi Nzali. - * For conditions of distribution and use, see copyright notice in readme.txt - * - * Adaptation to the zlibpas interface - * Copyright (C) 2003 by Cosmin Truta. - * For conditions of distribution and use, see copyright notice in readme.txt - *) - -program example; - -{$DEFINE TEST_COMPRESS} -{DO NOT $DEFINE TEST_GZIO} -{$DEFINE TEST_DEFLATE} -{$DEFINE TEST_INFLATE} -{$DEFINE TEST_FLUSH} -{$DEFINE TEST_SYNC} -{$DEFINE TEST_DICT} - -uses SysUtils, zlibpas; - -const TESTFILE = 'foo.gz'; - -(* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - *) -const hello: PChar = 'hello, hello!'; - -const dictionary: PChar = 'hello'; - -var dictId: LongInt; (* Adler32 value of the dictionary *) - -procedure CHECK_ERR(err: Integer; msg: String); -begin - if err <> Z_OK then - begin - WriteLn(msg, ' error: ', err); - Halt(1); - end; -end; - -procedure EXIT_ERR(const msg: String); -begin - WriteLn('Error: ', msg); - Halt(1); -end; - -(* =========================================================================== - * Test compress and uncompress - *) -{$IFDEF TEST_COMPRESS} -procedure test_compress(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - len: LongInt; -begin - len := StrLen(hello)+1; - - err := compress(compr, comprLen, hello, len); - CHECK_ERR(err, 'compress'); - - StrCopy(PChar(uncompr), 'garbage'); - - err := uncompress(uncompr, uncomprLen, compr, comprLen); - CHECK_ERR(err, 'uncompress'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad uncompress') - else - WriteLn('uncompress(): ', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test read/write of .gz files - *) -{$IFDEF TEST_GZIO} -procedure test_gzio(const fname: PChar; (* compressed file name *) - uncompr: Pointer; - uncomprLen: LongInt); -var err: Integer; - len: Integer; - zfile: gzFile; - pos: LongInt; -begin - len := StrLen(hello)+1; - - zfile := gzopen(fname, 'wb'); - if zfile = NIL then - begin - WriteLn('gzopen error'); - Halt(1); - end; - gzputc(zfile, 'h'); - if gzputs(zfile, 'ello') <> 4 then - begin - WriteLn('gzputs err: ', gzerror(zfile, err)); - Halt(1); - end; - {$IFDEF GZ_FORMAT_STRING} - if gzprintf(zfile, ', %s!', 'hello') <> 8 then - begin - WriteLn('gzprintf err: ', gzerror(zfile, err)); - Halt(1); - end; - {$ELSE} - if gzputs(zfile, ', hello!') <> 8 then - begin - WriteLn('gzputs err: ', gzerror(zfile, err)); - Halt(1); - end; - {$ENDIF} - gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *) - gzclose(zfile); - - zfile := gzopen(fname, 'rb'); - if zfile = NIL then - begin - WriteLn('gzopen error'); - Halt(1); - end; - - StrCopy(PChar(uncompr), 'garbage'); - - if gzread(zfile, uncompr, uncomprLen) <> len then - begin - WriteLn('gzread err: ', gzerror(zfile, err)); - Halt(1); - end; - if StrComp(PChar(uncompr), hello) <> 0 then - begin - WriteLn('bad gzread: ', PChar(uncompr)); - Halt(1); - end - else - WriteLn('gzread(): ', PChar(uncompr)); - - pos := gzseek(zfile, -8, SEEK_CUR); - if (pos <> 6) or (gztell(zfile) <> pos) then - begin - WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile)); - Halt(1); - end; - - if gzgetc(zfile) <> ' ' then - begin - WriteLn('gzgetc error'); - Halt(1); - end; - - if gzungetc(' ', zfile) <> ' ' then - begin - WriteLn('gzungetc error'); - Halt(1); - end; - - gzgets(zfile, PChar(uncompr), uncomprLen); - uncomprLen := StrLen(PChar(uncompr)); - if uncomprLen <> 7 then (* " hello!" *) - begin - WriteLn('gzgets err after gzseek: ', gzerror(zfile, err)); - Halt(1); - end; - if StrComp(PChar(uncompr), hello + 6) <> 0 then - begin - WriteLn('bad gzgets after gzseek'); - Halt(1); - end - else - WriteLn('gzgets() after gzseek: ', PChar(uncompr)); - - gzclose(zfile); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with small buffers - *) -{$IFDEF TEST_DEFLATE} -procedure test_deflate(compr: Pointer; comprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; - len: LongInt; -begin - len := StrLen(hello)+1; - - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_in := hello; - c_stream.next_out := compr; - - while (c_stream.total_in <> len) and - (c_stream.total_out < comprLen) do - begin - c_stream.avail_out := 1; { force small buffers } - c_stream.avail_in := 1; - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - end; - - (* Finish the stream, still forcing small buffers: *) - while TRUE do - begin - c_stream.avail_out := 1; - err := deflate(c_stream, Z_FINISH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'deflate'); - end; - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with small buffers - *) -{$IFDEF TEST_INFLATE} -procedure test_inflate(compr: Pointer; comprLen : LongInt; - uncompr: Pointer; uncomprLen : LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := 0; - d_stream.next_out := uncompr; - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - while (d_stream.total_out < uncomprLen) and - (d_stream.total_in < comprLen) do - begin - d_stream.avail_out := 1; (* force small buffers *) - d_stream.avail_in := 1; - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'inflate'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad inflate') - else - WriteLn('inflate(): ', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with large buffers and dynamic change of compression level - *) -{$IFDEF TEST_DEFLATE} -procedure test_large_deflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; -begin - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_BEST_SPEED); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_out := compr; - c_stream.avail_out := Integer(comprLen); - - (* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - *) - c_stream.next_in := uncompr; - c_stream.avail_in := Integer(uncomprLen); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - if c_stream.avail_in <> 0 then - EXIT_ERR('deflate not greedy'); - - (* Feed in already compressed data and switch to no compression: *) - deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in := compr; - c_stream.avail_in := Integer(comprLen div 2); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - - (* Switch back to compressing mode: *) - deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in := uncompr; - c_stream.avail_in := Integer(uncomprLen); - err := deflate(c_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'deflate'); - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - EXIT_ERR('deflate should report Z_STREAM_END'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with large buffers - *) -{$IFDEF TEST_INFLATE} -procedure test_large_inflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := Integer(comprLen); - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - while TRUE do - begin - d_stream.next_out := uncompr; (* discard the output *) - d_stream.avail_out := Integer(uncomprLen); - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - CHECK_ERR(err, 'large inflate'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then - begin - WriteLn('bad large inflate: ', d_stream.total_out); - Halt(1); - end - else - WriteLn('large_inflate(): OK'); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with full flush - *) -{$IFDEF TEST_FLUSH} -procedure test_flush(compr: Pointer; var comprLen : LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; - len: Integer; -begin - len := StrLen(hello)+1; - - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - c_stream.next_in := hello; - c_stream.next_out := compr; - c_stream.avail_in := 3; - c_stream.avail_out := Integer(comprLen); - err := deflate(c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, 'deflate'); - - Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *) - c_stream.avail_in := len - 3; - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - CHECK_ERR(err, 'deflate'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); - - comprLen := c_stream.total_out; -end; -{$ENDIF} - -(* =========================================================================== - * Test inflateSync() - *) -{$IFDEF TEST_SYNC} -procedure test_sync(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen : LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := 2; (* just read the zlib header *) - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - d_stream.next_out := uncompr; - d_stream.avail_out := Integer(uncomprLen); - - inflate(d_stream, Z_NO_FLUSH); - CHECK_ERR(err, 'inflate'); - - d_stream.avail_in := Integer(comprLen-2); (* read all compressed data *) - err := inflateSync(d_stream); (* but skip the damaged part *) - CHECK_ERR(err, 'inflateSync'); - - err := inflate(d_stream, Z_FINISH); - if err <> Z_DATA_ERROR then - EXIT_ERR('inflate should report DATA_ERROR'); - (* Because of incorrect adler32 *) - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - WriteLn('after inflateSync(): hel', PChar(uncompr)); -end; -{$ENDIF} - -(* =========================================================================== - * Test deflate with preset dictionary - *) -{$IFDEF TEST_DICT} -procedure test_dict_deflate(compr: Pointer; comprLen: LongInt); -var c_stream: z_stream; (* compression stream *) - err: Integer; -begin - c_stream.zalloc := NIL; - c_stream.zfree := NIL; - c_stream.opaque := NIL; - - err := deflateInit(c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, 'deflateInit'); - - err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary)); - CHECK_ERR(err, 'deflateSetDictionary'); - - dictId := c_stream.adler; - c_stream.next_out := compr; - c_stream.avail_out := Integer(comprLen); - - c_stream.next_in := hello; - c_stream.avail_in := StrLen(hello)+1; - - err := deflate(c_stream, Z_FINISH); - if err <> Z_STREAM_END then - EXIT_ERR('deflate should report Z_STREAM_END'); - - err := deflateEnd(c_stream); - CHECK_ERR(err, 'deflateEnd'); -end; -{$ENDIF} - -(* =========================================================================== - * Test inflate with a preset dictionary - *) -{$IFDEF TEST_DICT} -procedure test_dict_inflate(compr: Pointer; comprLen: LongInt; - uncompr: Pointer; uncomprLen: LongInt); -var err: Integer; - d_stream: z_stream; (* decompression stream *) -begin - StrCopy(PChar(uncompr), 'garbage'); - - d_stream.zalloc := NIL; - d_stream.zfree := NIL; - d_stream.opaque := NIL; - - d_stream.next_in := compr; - d_stream.avail_in := Integer(comprLen); - - err := inflateInit(d_stream); - CHECK_ERR(err, 'inflateInit'); - - d_stream.next_out := uncompr; - d_stream.avail_out := Integer(uncomprLen); - - while TRUE do - begin - err := inflate(d_stream, Z_NO_FLUSH); - if err = Z_STREAM_END then - break; - if err = Z_NEED_DICT then - begin - if d_stream.adler <> dictId then - EXIT_ERR('unexpected dictionary'); - err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary)); - end; - CHECK_ERR(err, 'inflate with dict'); - end; - - err := inflateEnd(d_stream); - CHECK_ERR(err, 'inflateEnd'); - - if StrComp(PChar(uncompr), hello) <> 0 then - EXIT_ERR('bad inflate with dict') - else - WriteLn('inflate with dictionary: ', PChar(uncompr)); -end; -{$ENDIF} - -var compr, uncompr: Pointer; - comprLen, uncomprLen: LongInt; - -begin - if zlibVersion^ <> ZLIB_VERSION[1] then - EXIT_ERR('Incompatible zlib version'); - - WriteLn('zlib version: ', zlibVersion); - WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags])); - - comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *) - uncomprLen := comprLen; - GetMem(compr, comprLen); - GetMem(uncompr, uncomprLen); - if (compr = NIL) or (uncompr = NIL) then - EXIT_ERR('Out of memory'); - (* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - *) - FillChar(compr^, comprLen, 0); - FillChar(uncompr^, uncomprLen, 0); - - {$IFDEF TEST_COMPRESS} - WriteLn('** Testing compress'); - test_compress(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_GZIO} - WriteLn('** Testing gzio'); - if ParamCount >= 1 then - test_gzio(ParamStr(1), uncompr, uncomprLen) - else - test_gzio(TESTFILE, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_DEFLATE} - WriteLn('** Testing deflate with small buffers'); - test_deflate(compr, comprLen); - {$ENDIF} - {$IFDEF TEST_INFLATE} - WriteLn('** Testing inflate with small buffers'); - test_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_DEFLATE} - WriteLn('** Testing deflate with large buffers'); - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - {$IFDEF TEST_INFLATE} - WriteLn('** Testing inflate with large buffers'); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - {$IFDEF TEST_FLUSH} - WriteLn('** Testing deflate with full flush'); - test_flush(compr, comprLen); - {$ENDIF} - {$IFDEF TEST_SYNC} - WriteLn('** Testing inflateSync'); - test_sync(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - comprLen := uncomprLen; - - {$IFDEF TEST_DICT} - WriteLn('** Testing deflate and inflate with preset dictionary'); - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - {$ENDIF} - - FreeMem(compr, comprLen); - FreeMem(uncompr, uncomprLen); -end. diff --git a/src/contrib/zlib/contrib/pascal/readme.txt b/src/contrib/zlib/contrib/pascal/readme.txt deleted file mode 100644 index 60e87c8..0000000 --- a/src/contrib/zlib/contrib/pascal/readme.txt +++ /dev/null @@ -1,76 +0,0 @@ - -This directory contains a Pascal (Delphi, Kylix) interface to the -zlib data compression library. - - -Directory listing -================= - -zlibd32.mak makefile for Borland C++ -example.pas usage example of zlib -zlibpas.pas the Pascal interface to zlib -readme.txt this file - - -Compatibility notes -=================== - -- Although the name "zlib" would have been more normal for the - zlibpas unit, this name is already taken by Borland's ZLib unit. - This is somehow unfortunate, because that unit is not a genuine - interface to the full-fledged zlib functionality, but a suite of - class wrappers around zlib streams. Other essential features, - such as checksums, are missing. - It would have been more appropriate for that unit to have a name - like "ZStreams", or something similar. - -- The C and zlib-supplied types int, uInt, long, uLong, etc. are - translated directly into Pascal types of similar sizes (Integer, - LongInt, etc.), to avoid namespace pollution. In particular, - there is no conversion of unsigned int into a Pascal unsigned - integer. The Word type is non-portable and has the same size - (16 bits) both in a 16-bit and in a 32-bit environment, unlike - Integer. Even if there is a 32-bit Cardinal type, there is no - real need for unsigned int in zlib under a 32-bit environment. - -- Except for the callbacks, the zlib function interfaces are - assuming the calling convention normally used in Pascal - (__pascal for DOS and Windows16, __fastcall for Windows32). - Since the cdecl keyword is used, the old Turbo Pascal does - not work with this interface. - -- The gz* function interfaces are not translated, to avoid - interfacing problems with the C runtime library. Besides, - gzprintf(gzFile file, const char *format, ...) - cannot be translated into Pascal. - - -Legal issues -============ - -The zlibpas interface is: - Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler. - Copyright (C) 1998 by Bob Dellaca. - Copyright (C) 2003 by Cosmin Truta. - -The example program is: - Copyright (C) 1995-2003 by Jean-loup Gailly. - Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali. - Copyright (C) 2003 by Cosmin Truta. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - diff --git a/src/contrib/zlib/contrib/pascal/zlibd32.mak b/src/contrib/zlib/contrib/pascal/zlibd32.mak deleted file mode 100644 index 9bb00b7..0000000 --- a/src/contrib/zlib/contrib/pascal/zlibd32.mak +++ /dev/null @@ -1,99 +0,0 @@ -# Makefile for zlib -# For use with Delphi and C++ Builder under Win32 -# Updated for zlib 1.2.x by Cosmin Truta - -# ------------ Borland C++ ------------ - -# This project uses the Delphi (fastcall/register) calling convention: -LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl - -CC = bcc32 -LD = bcc32 -AR = tlib -# do not use "-pr" in CFLAGS -CFLAGS = -a -d -k- -O2 $(LOC) -LDFLAGS = - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del *.obj - -del *.exe - -del *.lib - -del *.tds - -del zlib.bak - -del foo.gz - diff --git a/src/contrib/zlib/contrib/pascal/zlibpas.pas b/src/contrib/zlib/contrib/pascal/zlibpas.pas deleted file mode 100644 index a0dff11..0000000 --- a/src/contrib/zlib/contrib/pascal/zlibpas.pas +++ /dev/null @@ -1,276 +0,0 @@ -(* zlibpas -- Pascal interface to the zlib data compression library - * - * Copyright (C) 2003 Cosmin Truta. - * Derived from original sources by Bob Dellaca. - * For conditions of distribution and use, see copyright notice in readme.txt - *) - -unit zlibpas; - -interface - -const - ZLIB_VERSION = '1.2.11'; - ZLIB_VERNUM = $12a0; - -type - alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; - cdecl; - free_func = procedure(opaque, address: Pointer); - cdecl; - - in_func = function(opaque: Pointer; var buf: PByte): Integer; - cdecl; - out_func = function(opaque: Pointer; buf: PByte; size: Integer): Integer; - cdecl; - - z_streamp = ^z_stream; - z_stream = packed record - next_in: PChar; (* next input byte *) - avail_in: Integer; (* number of bytes available at next_in *) - total_in: LongInt; (* total nb of input bytes read so far *) - - next_out: PChar; (* next output byte should be put there *) - avail_out: Integer; (* remaining free space at next_out *) - total_out: LongInt; (* total nb of bytes output so far *) - - msg: PChar; (* last error message, NULL if no error *) - state: Pointer; (* not visible by applications *) - - zalloc: alloc_func; (* used to allocate the internal state *) - zfree: free_func; (* used to free the internal state *) - opaque: Pointer; (* private data object passed to zalloc and zfree *) - - data_type: Integer; (* best guess about the data type: ascii or binary *) - adler: LongInt; (* adler32 value of the uncompressed data *) - reserved: LongInt; (* reserved for future use *) - end; - - gz_headerp = ^gz_header; - gz_header = packed record - text: Integer; (* true if compressed data believed to be text *) - time: LongInt; (* modification time *) - xflags: Integer; (* extra flags (not used when writing a gzip file) *) - os: Integer; (* operating system *) - extra: PChar; (* pointer to extra field or Z_NULL if none *) - extra_len: Integer; (* extra field length (valid if extra != Z_NULL) *) - extra_max: Integer; (* space at extra (only when reading header) *) - name: PChar; (* pointer to zero-terminated file name or Z_NULL *) - name_max: Integer; (* space at name (only when reading header) *) - comment: PChar; (* pointer to zero-terminated comment or Z_NULL *) - comm_max: Integer; (* space at comment (only when reading header) *) - hcrc: Integer; (* true if there was or will be a header crc *) - done: Integer; (* true when done reading gzip header *) - end; - -(* constants *) -const - Z_NO_FLUSH = 0; - Z_PARTIAL_FLUSH = 1; - Z_SYNC_FLUSH = 2; - Z_FULL_FLUSH = 3; - Z_FINISH = 4; - Z_BLOCK = 5; - Z_TREES = 6; - - Z_OK = 0; - Z_STREAM_END = 1; - Z_NEED_DICT = 2; - Z_ERRNO = -1; - Z_STREAM_ERROR = -2; - Z_DATA_ERROR = -3; - Z_MEM_ERROR = -4; - Z_BUF_ERROR = -5; - Z_VERSION_ERROR = -6; - - Z_NO_COMPRESSION = 0; - Z_BEST_SPEED = 1; - Z_BEST_COMPRESSION = 9; - Z_DEFAULT_COMPRESSION = -1; - - Z_FILTERED = 1; - Z_HUFFMAN_ONLY = 2; - Z_RLE = 3; - Z_FIXED = 4; - Z_DEFAULT_STRATEGY = 0; - - Z_BINARY = 0; - Z_TEXT = 1; - Z_ASCII = 1; - Z_UNKNOWN = 2; - - Z_DEFLATED = 8; - -(* basic functions *) -function zlibVersion: PChar; -function deflateInit(var strm: z_stream; level: Integer): Integer; -function deflate(var strm: z_stream; flush: Integer): Integer; -function deflateEnd(var strm: z_stream): Integer; -function inflateInit(var strm: z_stream): Integer; -function inflate(var strm: z_stream; flush: Integer): Integer; -function inflateEnd(var strm: z_stream): Integer; - -(* advanced functions *) -function deflateInit2(var strm: z_stream; level, method, windowBits, - memLevel, strategy: Integer): Integer; -function deflateSetDictionary(var strm: z_stream; const dictionary: PChar; - dictLength: Integer): Integer; -function deflateCopy(var dest, source: z_stream): Integer; -function deflateReset(var strm: z_stream): Integer; -function deflateParams(var strm: z_stream; level, strategy: Integer): Integer; -function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer; -function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt; -function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer; -function deflatePrime(var strm: z_stream; bits, value: Integer): Integer; -function deflateSetHeader(var strm: z_stream; head: gz_header): Integer; -function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; -function inflateSetDictionary(var strm: z_stream; const dictionary: PChar; - dictLength: Integer): Integer; -function inflateSync(var strm: z_stream): Integer; -function inflateCopy(var dest, source: z_stream): Integer; -function inflateReset(var strm: z_stream): Integer; -function inflateReset2(var strm: z_stream; windowBits: Integer): Integer; -function inflatePrime(var strm: z_stream; bits, value: Integer): Integer; -function inflateMark(var strm: z_stream): LongInt; -function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer; -function inflateBackInit(var strm: z_stream; - windowBits: Integer; window: PChar): Integer; -function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer; - out_fn: out_func; out_desc: Pointer): Integer; -function inflateBackEnd(var strm: z_stream): Integer; -function zlibCompileFlags: LongInt; - -(* utility functions *) -function compress(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt): Integer; -function compress2(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt; - level: Integer): Integer; -function compressBound(sourceLen: LongInt): LongInt; -function uncompress(dest: PChar; var destLen: LongInt; - const source: PChar; sourceLen: LongInt): Integer; - -(* checksum functions *) -function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt; -function adler32_combine(adler1, adler2, len2: LongInt): LongInt; -function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt; -function crc32_combine(crc1, crc2, len2: LongInt): LongInt; - -(* various hacks, don't look :) *) -function deflateInit_(var strm: z_stream; level: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateInit_(var strm: z_stream; const version: PChar; - stream_size: Integer): Integer; -function deflateInit2_(var strm: z_stream; - level, method, windowBits, memLevel, strategy: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateInit2_(var strm: z_stream; windowBits: Integer; - const version: PChar; stream_size: Integer): Integer; -function inflateBackInit_(var strm: z_stream; - windowBits: Integer; window: PChar; - const version: PChar; stream_size: Integer): Integer; - - -implementation - -{$L adler32.obj} -{$L compress.obj} -{$L crc32.obj} -{$L deflate.obj} -{$L infback.obj} -{$L inffast.obj} -{$L inflate.obj} -{$L inftrees.obj} -{$L trees.obj} -{$L uncompr.obj} -{$L zutil.obj} - -function adler32; external; -function adler32_combine; external; -function compress; external; -function compress2; external; -function compressBound; external; -function crc32; external; -function crc32_combine; external; -function deflate; external; -function deflateBound; external; -function deflateCopy; external; -function deflateEnd; external; -function deflateInit_; external; -function deflateInit2_; external; -function deflateParams; external; -function deflatePending; external; -function deflatePrime; external; -function deflateReset; external; -function deflateSetDictionary; external; -function deflateSetHeader; external; -function deflateTune; external; -function inflate; external; -function inflateBack; external; -function inflateBackEnd; external; -function inflateBackInit_; external; -function inflateCopy; external; -function inflateEnd; external; -function inflateGetHeader; external; -function inflateInit_; external; -function inflateInit2_; external; -function inflateMark; external; -function inflatePrime; external; -function inflateReset; external; -function inflateReset2; external; -function inflateSetDictionary; external; -function inflateSync; external; -function uncompress; external; -function zlibCompileFlags; external; -function zlibVersion; external; - -function deflateInit(var strm: z_stream; level: Integer): Integer; -begin - Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); -end; - -function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, - strategy: Integer): Integer; -begin - Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateInit(var strm: z_stream): Integer; -begin - Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; -begin - Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream)); -end; - -function inflateBackInit(var strm: z_stream; - windowBits: Integer; window: PChar): Integer; -begin - Result := inflateBackInit_(strm, windowBits, window, - ZLIB_VERSION, sizeof(z_stream)); -end; - -function _malloc(Size: Integer): Pointer; cdecl; -begin - GetMem(Result, Size); -end; - -procedure _free(Block: Pointer); cdecl; -begin - FreeMem(Block); -end; - -procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; -begin - FillChar(P^, count, B); -end; - -procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; -begin - Move(source^, dest^, count); -end; - -end. diff --git a/src/contrib/zlib/contrib/puff/Makefile b/src/contrib/zlib/contrib/puff/Makefile deleted file mode 100644 index 0e2594c..0000000 --- a/src/contrib/zlib/contrib/puff/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -CFLAGS=-O - -puff: puff.o pufftest.o - -puff.o: puff.h - -pufftest.o: puff.h - -test: puff - puff zeros.raw - -puft: puff.c puff.h pufftest.o - cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o - -# puff full coverage test (should say 100%) -cov: puft - @rm -f *.gcov *.gcda - @puft -w zeros.raw 2>&1 | cat > /dev/null - @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 - @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null - @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 - @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 - @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null - @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 - @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 - @puft -f zeros.raw 2>&1 | cat > /dev/null - @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 - @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 - @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 - @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 - @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 - @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 - @gcov -n puff.c - -clean: - rm -f puff puft *.o *.gc* diff --git a/src/contrib/zlib/contrib/puff/README b/src/contrib/zlib/contrib/puff/README deleted file mode 100644 index bbc4cb5..0000000 --- a/src/contrib/zlib/contrib/puff/README +++ /dev/null @@ -1,63 +0,0 @@ -Puff -- A Simple Inflate -3 Mar 2003 -Mark Adler -madler@alumni.caltech.edu - -What this is -- - -puff.c provides the routine puff() to decompress the deflate data format. It -does so more slowly than zlib, but the code is about one-fifth the size of the -inflate code in zlib, and written to be very easy to read. - -Why I wrote this -- - -puff.c was written to document the deflate format unambiguously, by virtue of -being working C code. It is meant to supplement RFC 1951, which formally -describes the deflate format. I have received many questions on details of the -deflate format, and I hope that reading this code will answer those questions. -puff.c is heavily commented with details of the deflate format, especially -those little nooks and cranies of the format that might not be obvious from a -specification. - -puff.c may also be useful in applications where code size or memory usage is a -very limited resource, and speed is not as important. - -How to use it -- - -Well, most likely you should just be reading puff.c and using zlib for actual -applications, but if you must ... - -Include puff.h in your code, which provides this prototype: - -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen); /* amount of input available */ - -Then you can call puff() to decompress a deflate stream that is in memory in -its entirety at source, to a sufficiently sized block of memory for the -decompressed data at dest. puff() is the only external symbol in puff.c The -only C library functions that puff.c needs are setjmp() and longjmp(), which -are used to simplify error checking in the code to improve readabilty. puff.c -does no memory allocation, and uses less than 2K bytes off of the stack. - -If destlen is not enough space for the uncompressed data, then inflate will -return an error without writing more than destlen bytes. Note that this means -that in order to decompress the deflate data successfully, you need to know -the size of the uncompressed data ahead of time. - -If needed, puff() can determine the size of the uncompressed data with no -output space. This is done by passing dest equal to (unsigned char *)0. Then -the initial value of *destlen is ignored and *destlen is set to the length of -the uncompressed data. So if the size of the uncompressed data is not known, -then two passes of puff() can be used--first to determine the size, and second -to do the actual inflation after allocating the appropriate memory. Not -pretty, but it works. (This is one of the reasons you should be using zlib.) - -The deflate format is self-terminating. If the deflate stream does not end -in *sourcelen bytes, puff() will return an error without reading at or past -endsource. - -On return, *sourcelen is updated to the amount of input data consumed, and -*destlen is updated to the size of the uncompressed data. See the comments -in puff.c for the possible return codes for puff(). diff --git a/src/contrib/zlib/contrib/puff/puff.c b/src/contrib/zlib/contrib/puff/puff.c deleted file mode 100644 index c6c90d7..0000000 --- a/src/contrib/zlib/contrib/puff/puff.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - * puff.c - * Copyright (C) 2002-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in puff.h - * version 2.3, 21 Jan 2013 - * - * puff.c is a simple inflate written to be an unambiguous way to specify the - * deflate format. It is not written for speed but rather simplicity. As a - * side benefit, this code might actually be useful when small code is more - * important than speed, such as bootstrap applications. For typical deflate - * data, zlib's inflate() is about four times as fast as puff(). zlib's - * inflate compiles to around 20K on my machine, whereas puff.c compiles to - * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() - * function here is used, then puff() is only twice as slow as zlib's - * inflate(). - * - * All dynamically allocated memory comes from the stack. The stack required - * is less than 2K bytes. This code is compatible with 16-bit int's and - * assumes that long's are at least 32 bits. puff.c uses the short data type, - * assumed to be 16 bits, for arrays in order to conserve memory. The code - * works whether integers are stored big endian or little endian. - * - * In the comments below are "Format notes" that describe the inflate process - * and document some of the less obvious aspects of the format. This source - * code is meant to supplement RFC 1951, which formally describes the deflate - * format: - * - * http://www.zlib.org/rfc-deflate.html - */ - -/* - * Change history: - * - * 1.0 10 Feb 2002 - First version - * 1.1 17 Feb 2002 - Clarifications of some comments and notes - * - Update puff() dest and source pointers on negative - * errors to facilitate debugging deflators - * - Remove longest from struct huffman -- not needed - * - Simplify offs[] index in construct() - * - Add input size and checking, using longjmp() to - * maintain easy readability - * - Use short data type for large arrays - * - Use pointers instead of long to specify source and - * destination sizes to avoid arbitrary 4 GB limits - * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), - * but leave simple version for readabilty - * - Make sure invalid distances detected if pointers - * are 16 bits - * - Fix fixed codes table error - * - Provide a scanning mode for determining size of - * uncompressed data - * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] - * - Add a puff.h file for the interface - * - Add braces in puff() for else do [Gailly] - * - Use indexes instead of pointers for readability - * 1.4 31 Mar 2002 - Simplify construct() code set check - * - Fix some comments - * - Add FIXLCODES #define - * 1.5 6 Apr 2002 - Minor comment fixes - * 1.6 7 Aug 2002 - Minor format changes - * 1.7 3 Mar 2003 - Added test code for distribution - * - Added zlib-like license - * 1.8 9 Jan 2004 - Added some comments on no distance codes case - * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] - * - Catch missing end-of-block symbol error - * 2.0 25 Jul 2008 - Add #define to permit distance too far back - * - Add option in TEST code for puff to write the data - * - Add option in TEST code to skip input bytes - * - Allow TEST code to read from piped stdin - * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers - * - Avoid unsigned comparisons for even happier compilers - * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] - * - Add const where appropriate [Oberhumer] - * - Split if's and ?'s for coverage testing - * - Break out test code to separate file - * - Move NIL to puff.h - * - Allow incomplete code only if single code length is 1 - * - Add full code coverage test to Makefile - * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks - */ - -#include /* for setjmp(), longjmp(), and jmp_buf */ -#include "puff.h" /* prototype for puff() */ - -#define local static /* for local function definitions */ - -/* - * Maximums for allocations and loops. It is not useful to change these -- - * they are fixed by the deflate format. - */ -#define MAXBITS 15 /* maximum bits in a code */ -#define MAXLCODES 286 /* maximum number of literal/length codes */ -#define MAXDCODES 30 /* maximum number of distance codes */ -#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ -#define FIXLCODES 288 /* number of fixed literal/length codes */ - -/* input and output state */ -struct state { - /* output state */ - unsigned char *out; /* output buffer */ - unsigned long outlen; /* available space at out */ - unsigned long outcnt; /* bytes written to out so far */ - - /* input state */ - const unsigned char *in; /* input buffer */ - unsigned long inlen; /* available input at in */ - unsigned long incnt; /* bytes read so far */ - int bitbuf; /* bit buffer */ - int bitcnt; /* number of bits in bit buffer */ - - /* input limit error return state for bits() and decode() */ - jmp_buf env; -}; - -/* - * Return need bits from the input stream. This always leaves less than - * eight bits in the buffer. bits() works properly for need == 0. - * - * Format notes: - * - * - Bits are stored in bytes from the least significant bit to the most - * significant bit. Therefore bits are dropped from the bottom of the bit - * buffer, using shift right, and new bytes are appended to the top of the - * bit buffer, using shift left. - */ -local int bits(struct state *s, int need) -{ - long val; /* bit accumulator (can use up to 20 bits) */ - - /* load at least need bits into val */ - val = s->bitbuf; - while (s->bitcnt < need) { - if (s->incnt == s->inlen) - longjmp(s->env, 1); /* out of input */ - val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ - s->bitcnt += 8; - } - - /* drop need bits and update buffer, always zero to seven bits left */ - s->bitbuf = (int)(val >> need); - s->bitcnt -= need; - - /* return need bits, zeroing the bits above that */ - return (int)(val & ((1L << need) - 1)); -} - -/* - * Process a stored block. - * - * Format notes: - * - * - After the two-bit stored block type (00), the stored block length and - * stored bytes are byte-aligned for fast copying. Therefore any leftover - * bits in the byte that has the last bit of the type, as many as seven, are - * discarded. The value of the discarded bits are not defined and should not - * be checked against any expectation. - * - * - The second inverted copy of the stored block length does not have to be - * checked, but it's probably a good idea to do so anyway. - * - * - A stored block can have zero length. This is sometimes used to byte-align - * subsets of the compressed data for random access or partial recovery. - */ -local int stored(struct state *s) -{ - unsigned len; /* length of stored block */ - - /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ - s->bitbuf = 0; - s->bitcnt = 0; - - /* get length and check against its one's complement */ - if (s->incnt + 4 > s->inlen) - return 2; /* not enough input */ - len = s->in[s->incnt++]; - len |= s->in[s->incnt++] << 8; - if (s->in[s->incnt++] != (~len & 0xff) || - s->in[s->incnt++] != ((~len >> 8) & 0xff)) - return -2; /* didn't match complement! */ - - /* copy len bytes from in to out */ - if (s->incnt + len > s->inlen) - return 2; /* not enough input */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) - return 1; /* not enough output space */ - while (len--) - s->out[s->outcnt++] = s->in[s->incnt++]; - } - else { /* just scanning */ - s->outcnt += len; - s->incnt += len; - } - - /* done with a valid stored block */ - return 0; -} - -/* - * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of - * each length, which for a canonical code are stepped through in order. - * symbol[] are the symbol values in canonical order, where the number of - * entries is the sum of the counts in count[]. The decoding process can be - * seen in the function decode() below. - */ -struct huffman { - short *count; /* number of symbols of each length */ - short *symbol; /* canonically ordered symbols */ -}; - -/* - * Decode a code from the stream s using huffman table h. Return the symbol or - * a negative value if there is an error. If all of the lengths are zero, i.e. - * an empty code, or if the code is incomplete and an invalid code is received, - * then -10 is returned after reading MAXBITS bits. - * - * Format notes: - * - * - The codes as stored in the compressed data are bit-reversed relative to - * a simple integer ordering of codes of the same lengths. Hence below the - * bits are pulled from the compressed data one at a time and used to - * build the code value reversed from what is in the stream in order to - * permit simple integer comparisons for decoding. A table-based decoding - * scheme (as used in zlib) does not need to do this reversal. - * - * - The first code for the shortest length is all zeros. Subsequent codes of - * the same length are simply integer increments of the previous code. When - * moving up a length, a zero bit is appended to the code. For a complete - * code, the last code of the longest length will be all ones. - * - * - Incomplete codes are handled by this decoder, since they are permitted - * in the deflate format. See the format notes for fixed() and dynamic(). - */ -#ifdef SLOW -local int decode(struct state *s, const struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - - code = first = index = 0; - for (len = 1; len <= MAXBITS; len++) { - code |= bits(s, 1); /* get next bit */ - count = h->count[len]; - if (code - count < first) /* if length len, return symbol */ - return h->symbol[index + (code - first)]; - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - } - return -10; /* ran out of codes */ -} - -/* - * A faster version of decode() for real applications of this code. It's not - * as readable, but it makes puff() twice as fast. And it only makes the code - * a few percent larger. - */ -#else /* !SLOW */ -local int decode(struct state *s, const struct huffman *h) -{ - int len; /* current number of bits in code */ - int code; /* len bits being decoded */ - int first; /* first code of length len */ - int count; /* number of codes of length len */ - int index; /* index of first code of length len in symbol table */ - int bitbuf; /* bits from stream */ - int left; /* bits left in next or left to process */ - short *next; /* next number of codes */ - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while (1) { - while (left--) { - code |= bitbuf & 1; - bitbuf >>= 1; - count = *next++; - if (code - count < first) { /* if length len, return symbol */ - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; /* else update for next length */ - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS+1) - len; - if (left == 0) - break; - if (s->incnt == s->inlen) - longjmp(s->env, 1); /* out of input */ - bitbuf = s->in[s->incnt++]; - if (left > 8) - left = 8; - } - return -10; /* ran out of codes */ -} -#endif /* SLOW */ - -/* - * Given the list of code lengths length[0..n-1] representing a canonical - * Huffman code for n symbols, construct the tables required to decode those - * codes. Those tables are the number of codes of each length, and the symbols - * sorted by length, retaining their original order within each length. The - * return value is zero for a complete code set, negative for an over- - * subscribed code set, and positive for an incomplete code set. The tables - * can be used if the return value is zero or positive, but they cannot be used - * if the return value is negative. If the return value is zero, it is not - * possible for decode() using that table to return an error--any stream of - * enough bits will resolve to a symbol. If the return value is positive, then - * it is possible for decode() using that table to return an error for received - * codes past the end of the incomplete lengths. - * - * Not used by decode(), but used for error checking, h->count[0] is the number - * of the n symbols not in the code. So n - h->count[0] is the number of - * codes. This is useful for checking for incomplete codes that have more than - * one symbol, which is an error in a dynamic block. - * - * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS - * This is assured by the construction of the length arrays in dynamic() and - * fixed() and is not verified by construct(). - * - * Format notes: - * - * - Permitted and expected examples of incomplete codes are one of the fixed - * codes and any code with a single symbol which in deflate is coded as one - * bit instead of zero bits. See the format notes for fixed() and dynamic(). - * - * - Within a given code length, the symbols are kept in ascending order for - * the code bits definition. - */ -local int construct(struct huffman *h, const short *length, int n) -{ - int symbol; /* current symbol when stepping through length[] */ - int len; /* current length when stepping through h->count[] */ - int left; /* number of possible codes left of current length */ - short offs[MAXBITS+1]; /* offsets in symbol table for each length */ - - /* count number of codes of each length */ - for (len = 0; len <= MAXBITS; len++) - h->count[len] = 0; - for (symbol = 0; symbol < n; symbol++) - (h->count[length[symbol]])++; /* assumes lengths are within bounds */ - if (h->count[0] == n) /* no codes! */ - return 0; /* complete, but decode() will fail */ - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; /* one possible code of zero length */ - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; /* one more bit, double codes left */ - left -= h->count[len]; /* deduct count from possible codes */ - if (left < 0) - return left; /* over-subscribed--return negative */ - } /* left > 0 means incomplete */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + h->count[len]; - - /* - * put symbols in table sorted by length, by symbol order within each - * length - */ - for (symbol = 0; symbol < n; symbol++) - if (length[symbol] != 0) - h->symbol[offs[length[symbol]]++] = symbol; - - /* return zero for complete set, positive for incomplete set */ - return left; -} - -/* - * Decode literal/length and distance codes until an end-of-block code. - * - * Format notes: - * - * - Compressed data that is after the block type if fixed or after the code - * description if dynamic is a combination of literals and length/distance - * pairs terminated by and end-of-block code. Literals are simply Huffman - * coded bytes. A length/distance pair is a coded length followed by a - * coded distance to represent a string that occurs earlier in the - * uncompressed data that occurs again at the current location. - * - * - Literals, lengths, and the end-of-block code are combined into a single - * code of up to 286 symbols. They are 256 literals (0..255), 29 length - * symbols (257..285), and the end-of-block symbol (256). - * - * - There are 256 possible lengths (3..258), and so 29 symbols are not enough - * to represent all of those. Lengths 3..10 and 258 are in fact represented - * by just a length symbol. Lengths 11..257 are represented as a symbol and - * some number of extra bits that are added as an integer to the base length - * of the length symbol. The number of extra bits is determined by the base - * length symbol. These are in the static arrays below, lens[] for the base - * lengths and lext[] for the corresponding number of extra bits. - * - * - The reason that 258 gets its own symbol is that the longest length is used - * often in highly redundant files. Note that 258 can also be coded as the - * base value 227 plus the maximum extra value of 31. While a good deflate - * should never do this, it is not an error, and should be decoded properly. - * - * - If a length is decoded, including its extra bits if any, then it is - * followed a distance code. There are up to 30 distance symbols. Again - * there are many more possible distances (1..32768), so extra bits are added - * to a base value represented by the symbol. The distances 1..4 get their - * own symbol, but the rest require extra bits. The base distances and - * corresponding number of extra bits are below in the static arrays dist[] - * and dext[]. - * - * - Literal bytes are simply written to the output. A length/distance pair is - * an instruction to copy previously uncompressed bytes to the output. The - * copy is from distance bytes back in the output stream, copying for length - * bytes. - * - * - Distances pointing before the beginning of the output data are not - * permitted. - * - * - Overlapped copies, where the length is greater than the distance, are - * allowed and common. For example, a distance of one and a length of 258 - * simply copies the last byte 258 times. A distance of four and a length of - * twelve copies the last four bytes three times. A simple forward copy - * ignoring whether the length is greater than the distance or not implements - * this correctly. You should not use memcpy() since its behavior is not - * defined for overlapped arrays. You should not use memmove() or bcopy() - * since though their behavior -is- defined for overlapping arrays, it is - * defined to do the wrong thing in this case. - */ -local int codes(struct state *s, - const struct huffman *lencode, - const struct huffman *distcode) -{ - int symbol; /* decoded symbol */ - int len; /* length for copy */ - unsigned dist; /* distance for copy */ - static const short lens[29] = { /* Size base for length codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; - static const short lext[29] = { /* Extra bits for length codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; - static const short dists[30] = { /* Offset base for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; - static const short dext[30] = { /* Extra bits for distance codes 0..29 */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - - /* decode literals and length/distance pairs */ - do { - symbol = decode(s, lencode); - if (symbol < 0) - return symbol; /* invalid symbol */ - if (symbol < 256) { /* literal: symbol is the byte */ - /* write out the literal */ - if (s->out != NIL) { - if (s->outcnt == s->outlen) - return 1; - s->out[s->outcnt] = symbol; - } - s->outcnt++; - } - else if (symbol > 256) { /* length */ - /* get and compute length */ - symbol -= 257; - if (symbol >= 29) - return -10; /* invalid fixed code */ - len = lens[symbol] + bits(s, lext[symbol]); - - /* get and check distance */ - symbol = decode(s, distcode); - if (symbol < 0) - return symbol; /* invalid symbol */ - dist = dists[symbol] + bits(s, dext[symbol]); -#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (dist > s->outcnt) - return -11; /* distance too far back */ -#endif - - /* copy length bytes from distance bytes back */ - if (s->out != NIL) { - if (s->outcnt + len > s->outlen) - return 1; - while (len--) { - s->out[s->outcnt] = -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - dist > s->outcnt ? - 0 : -#endif - s->out[s->outcnt - dist]; - s->outcnt++; - } - } - else - s->outcnt += len; - } - } while (symbol != 256); /* end of block symbol */ - - /* done with a valid fixed or dynamic block */ - return 0; -} - -/* - * Process a fixed codes block. - * - * Format notes: - * - * - This block type can be useful for compressing small amounts of data for - * which the size of the code descriptions in a dynamic block exceeds the - * benefit of custom codes for that block. For fixed codes, no bits are - * spent on code descriptions. Instead the code lengths for literal/length - * codes and distance codes are fixed. The specific lengths for each symbol - * can be seen in the "for" loops below. - * - * - The literal/length code is complete, but has two symbols that are invalid - * and should result in an error if received. This cannot be implemented - * simply as an incomplete code since those two symbols are in the "middle" - * of the code. They are eight bits long and the longest literal/length\ - * code is nine bits. Therefore the code must be constructed with those - * symbols, and the invalid symbols must be detected after decoding. - * - * - The fixed distance codes also have two invalid symbols that should result - * in an error if received. Since all of the distance codes are the same - * length, this can be implemented as an incomplete code. Then the invalid - * codes are detected while decoding. - */ -local int fixed(struct state *s) -{ - static int virgin = 1; - static short lencnt[MAXBITS+1], lensym[FIXLCODES]; - static short distcnt[MAXBITS+1], distsym[MAXDCODES]; - static struct huffman lencode, distcode; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - int symbol; - short lengths[FIXLCODES]; - - /* construct lencode and distcode */ - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - /* literal/length table */ - for (symbol = 0; symbol < 144; symbol++) - lengths[symbol] = 8; - for (; symbol < 256; symbol++) - lengths[symbol] = 9; - for (; symbol < 280; symbol++) - lengths[symbol] = 7; - for (; symbol < FIXLCODES; symbol++) - lengths[symbol] = 8; - construct(&lencode, lengths, FIXLCODES); - - /* distance table */ - for (symbol = 0; symbol < MAXDCODES; symbol++) - lengths[symbol] = 5; - construct(&distcode, lengths, MAXDCODES); - - /* do this just once */ - virgin = 0; - } - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - -/* - * Process a dynamic codes block. - * - * Format notes: - * - * - A dynamic block starts with a description of the literal/length and - * distance codes for that block. New dynamic blocks allow the compressor to - * rapidly adapt to changing data with new codes optimized for that data. - * - * - The codes used by the deflate format are "canonical", which means that - * the actual bits of the codes are generated in an unambiguous way simply - * from the number of bits in each code. Therefore the code descriptions - * are simply a list of code lengths for each symbol. - * - * - The code lengths are stored in order for the symbols, so lengths are - * provided for each of the literal/length symbols, and for each of the - * distance symbols. - * - * - If a symbol is not used in the block, this is represented by a zero as - * as the code length. This does not mean a zero-length code, but rather - * that no code should be created for this symbol. There is no way in the - * deflate format to represent a zero-length code. - * - * - The maximum number of bits in a code is 15, so the possible lengths for - * any code are 1..15. - * - * - The fact that a length of zero is not permitted for a code has an - * interesting consequence. Normally if only one symbol is used for a given - * code, then in fact that code could be represented with zero bits. However - * in deflate, that code has to be at least one bit. So for example, if - * only a single distance base symbol appears in a block, then it will be - * represented by a single code of length one, in particular one 0 bit. This - * is an incomplete code, since if a 1 bit is received, it has no meaning, - * and should result in an error. So incomplete distance codes of one symbol - * should be permitted, and the receipt of invalid codes should be handled. - * - * - It is also possible to have a single literal/length code, but that code - * must be the end-of-block code, since every dynamic block has one. This - * is not the most efficient way to create an empty block (an empty fixed - * block is fewer bits), but it is allowed by the format. So incomplete - * literal/length codes of one symbol should also be permitted. - * - * - If there are only literal codes and no lengths, then there are no distance - * codes. This is represented by one distance code with zero bits. - * - * - The list of up to 286 length/literal lengths and up to 30 distance lengths - * are themselves compressed using Huffman codes and run-length encoding. In - * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means - * that length, and the symbols 16, 17, and 18 are run-length instructions. - * Each of 16, 17, and 18 are follwed by extra bits to define the length of - * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 - * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols - * are common, hence the special coding for zero lengths. - * - * - The symbols for 0..18 are Huffman coded, and so that code must be - * described first. This is simply a sequence of up to 19 three-bit values - * representing no code (0) or the code length for that symbol (1..7). - * - * - A dynamic block starts with three fixed-size counts from which is computed - * the number of literal/length code lengths, the number of distance code - * lengths, and the number of code length code lengths (ok, you come up with - * a better name!) in the code descriptions. For the literal/length and - * distance codes, lengths after those provided are considered zero, i.e. no - * code. The code length code lengths are received in a permuted order (see - * the order[] array below) to make a short code length code length list more - * likely. As it turns out, very short and very long codes are less likely - * to be seen in a dynamic code description, hence what may appear initially - * to be a peculiar ordering. - * - * - Given the number of literal/length code lengths (nlen) and distance code - * lengths (ndist), then they are treated as one long list of nlen + ndist - * code lengths. Therefore run-length coding can and often does cross the - * boundary between the two sets of lengths. - * - * - So to summarize, the code description at the start of a dynamic block is - * three counts for the number of code lengths for the literal/length codes, - * the distance codes, and the code length codes. This is followed by the - * code length code lengths, three bits each. This is used to construct the - * code length code which is used to read the remainder of the lengths. Then - * the literal/length code lengths and distance lengths are read as a single - * set of lengths using the code length codes. Codes are constructed from - * the resulting two sets of lengths, and then finally you can start - * decoding actual compressed data in the block. - * - * - For reference, a "typical" size for the code description in a dynamic - * block is around 80 bytes. - */ -local int dynamic(struct state *s) -{ - int nlen, ndist, ncode; /* number of lengths in descriptor */ - int index; /* index of lengths[] */ - int err; /* construct() return value */ - short lengths[MAXCODES]; /* descriptor code lengths */ - short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ - short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ - struct huffman lencode, distcode; /* length and distance codes */ - static const short order[19] = /* permutation of code length codes */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* construct lencode and distcode */ - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - /* get number of lengths in each table, check lengths */ - nlen = bits(s, 5) + 257; - ndist = bits(s, 5) + 1; - ncode = bits(s, 4) + 4; - if (nlen > MAXLCODES || ndist > MAXDCODES) - return -3; /* bad counts */ - - /* read code length code lengths (really), missing lengths are zero */ - for (index = 0; index < ncode; index++) - lengths[order[index]] = bits(s, 3); - for (; index < 19; index++) - lengths[order[index]] = 0; - - /* build huffman table for code lengths codes (use lencode temporarily) */ - err = construct(&lencode, lengths, 19); - if (err != 0) /* require complete code set here */ - return -4; - - /* read length/literal and distance code length tables */ - index = 0; - while (index < nlen + ndist) { - int symbol; /* decoded value */ - int len; /* last length to repeat */ - - symbol = decode(s, &lencode); - if (symbol < 0) - return symbol; /* invalid symbol */ - if (symbol < 16) /* length in 0..15 */ - lengths[index++] = symbol; - else { /* repeat instruction */ - len = 0; /* assume repeating zeros */ - if (symbol == 16) { /* repeat last length 3..6 times */ - if (index == 0) - return -5; /* no last length! */ - len = lengths[index - 1]; /* last length */ - symbol = 3 + bits(s, 2); - } - else if (symbol == 17) /* repeat zero 3..10 times */ - symbol = 3 + bits(s, 3); - else /* == 18, repeat zero 11..138 times */ - symbol = 11 + bits(s, 7); - if (index + symbol > nlen + ndist) - return -6; /* too many lengths! */ - while (symbol--) /* repeat last or zero symbol times */ - lengths[index++] = len; - } - } - - /* check for end-of-block code -- there better be one! */ - if (lengths[256] == 0) - return -9; - - /* build huffman table for literal/length codes */ - err = construct(&lencode, lengths, nlen); - if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) - return -7; /* incomplete code ok only for single length 1 code */ - - /* build huffman table for distance codes */ - err = construct(&distcode, lengths + nlen, ndist); - if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) - return -8; /* incomplete code ok only for single length 1 code */ - - /* decode data until end-of-block code */ - return codes(s, &lencode, &distcode); -} - -/* - * Inflate source to dest. On return, destlen and sourcelen are updated to the - * size of the uncompressed data and the size of the deflate data respectively. - * On success, the return value of puff() is zero. If there is an error in the - * source data, i.e. it is not in the deflate format, then a negative value is - * returned. If there is not enough input available or there is not enough - * output space, then a positive error is returned. In that case, destlen and - * sourcelen are not updated to facilitate retrying from the beginning with the - * provision of more input data or more output space. In the case of invalid - * inflate data (a negative error), the dest and source pointers are updated to - * facilitate the debugging of deflators. - * - * puff() also has a mode to determine the size of the uncompressed output with - * no output written. For this dest must be (unsigned char *)0. In this case, - * the input value of *destlen is ignored, and on return *destlen is set to the - * size of the uncompressed output. - * - * The return codes are: - * - * 2: available inflate data did not terminate - * 1: output space exhausted before completing inflate - * 0: successful inflate - * -1: invalid block type (type == 3) - * -2: stored block length did not match one's complement - * -3: dynamic block code description: too many length or distance codes - * -4: dynamic block code description: code lengths codes incomplete - * -5: dynamic block code description: repeat lengths with no first length - * -6: dynamic block code description: repeat more than specified lengths - * -7: dynamic block code description: invalid literal/length code lengths - * -8: dynamic block code description: invalid distance code lengths - * -9: dynamic block code description: missing end-of-block code - * -10: invalid literal/length or distance code in fixed or dynamic block - * -11: distance is too far back in fixed or dynamic block - * - * Format notes: - * - * - Three bits are read for each block to determine the kind of block and - * whether or not it is the last block. Then the block is decoded and the - * process repeated if it was not the last block. - * - * - The leftover bits in the last byte of the deflate data after the last - * block (if it was a fixed or dynamic block) are undefined and have no - * expected values to check. - */ -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - const unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen) /* amount of input available */ -{ - struct state s; /* input/output state */ - int last, type; /* block information */ - int err; /* return value */ - - /* initialize output state */ - s.out = dest; - s.outlen = *destlen; /* ignored if dest is NIL */ - s.outcnt = 0; - - /* initialize input state */ - s.in = source; - s.inlen = *sourcelen; - s.incnt = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - /* return if bits() or decode() tries to read past available input */ - if (setjmp(s.env) != 0) /* if came back here via longjmp() */ - err = 2; /* then skip do-loop, return error */ - else { - /* process blocks until last block or error */ - do { - last = bits(&s, 1); /* one if last block */ - type = bits(&s, 2); /* block type 0..3 */ - err = type == 0 ? - stored(&s) : - (type == 1 ? - fixed(&s) : - (type == 2 ? - dynamic(&s) : - -1)); /* type == 3, invalid */ - if (err != 0) - break; /* return with error */ - } while (!last); - } - - /* update the lengths and return */ - if (err <= 0) { - *destlen = s.outcnt; - *sourcelen = s.incnt; - } - return err; -} diff --git a/src/contrib/zlib/contrib/puff/puff.h b/src/contrib/zlib/contrib/puff/puff.h deleted file mode 100644 index e23a245..0000000 --- a/src/contrib/zlib/contrib/puff/puff.h +++ /dev/null @@ -1,35 +0,0 @@ -/* puff.h - Copyright (C) 2002-2013 Mark Adler, all rights reserved - version 2.3, 21 Jan 2013 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - - -/* - * See puff.c for purpose and usage. - */ -#ifndef NIL -# define NIL ((unsigned char *)0) /* for no output option */ -#endif - -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - const unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen); /* amount of input available */ diff --git a/src/contrib/zlib/contrib/puff/pufftest.c b/src/contrib/zlib/contrib/puff/pufftest.c deleted file mode 100644 index 7764814..0000000 --- a/src/contrib/zlib/contrib/puff/pufftest.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * pufftest.c - * Copyright (C) 2002-2013 Mark Adler - * For conditions of distribution and use, see copyright notice in puff.h - * version 2.3, 21 Jan 2013 - */ - -/* Example of how to use puff(). - - Usage: puff [-w] [-f] [-nnn] file - ... | puff [-w] [-f] [-nnn] - - where file is the input file with deflate data, nnn is the number of bytes - of input to skip before inflating (e.g. to skip a zlib or gzip header), and - -w is used to write the decompressed data to stdout. -f is for coverage - testing, and causes pufftest to fail with not enough output space (-f does - a write like -w, so -w is not required). */ - -#include -#include -#include "puff.h" - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#define local static - -/* Return size times approximately the cube root of 2, keeping the result as 1, - 3, or 5 times a power of 2 -- the result is always > size, until the result - is the maximum value of an unsigned long, where it remains. This is useful - to keep reallocations less than ~33% over the actual data. */ -local size_t bythirds(size_t size) -{ - int n; - size_t m; - - m = size; - for (n = 0; m; n++) - m >>= 1; - if (n < 3) - return size + 1; - n -= 3; - m = size >> n; - m += m == 6 ? 2 : 1; - m <<= n; - return m > size ? m : (size_t)(-1); -} - -/* Read the input file *name, or stdin if name is NULL, into allocated memory. - Reallocate to larger buffers until the entire file is read in. Return a - pointer to the allocated data, or NULL if there was a memory allocation - failure. *len is the number of bytes of data read from the input file (even - if load() returns NULL). If the input file was empty or could not be opened - or read, *len is zero. */ -local void *load(const char *name, size_t *len) -{ - size_t size; - void *buf, *swap; - FILE *in; - - *len = 0; - buf = malloc(size = 4096); - if (buf == NULL) - return NULL; - in = name == NULL ? stdin : fopen(name, "rb"); - if (in != NULL) { - for (;;) { - *len += fread((char *)buf + *len, 1, size - *len, in); - if (*len < size) break; - size = bythirds(size); - if (size == *len || (swap = realloc(buf, size)) == NULL) { - free(buf); - buf = NULL; - break; - } - buf = swap; - } - fclose(in); - } - return buf; -} - -int main(int argc, char **argv) -{ - int ret, put = 0, fail = 0; - unsigned skip = 0; - char *arg, *name = NULL; - unsigned char *source = NULL, *dest; - size_t len = 0; - unsigned long sourcelen, destlen; - - /* process arguments */ - while (arg = *++argv, --argc) - if (arg[0] == '-') { - if (arg[1] == 'w' && arg[2] == 0) - put = 1; - else if (arg[1] == 'f' && arg[2] == 0) - fail = 1, put = 1; - else if (arg[1] >= '0' && arg[1] <= '9') - skip = (unsigned)atoi(arg + 1); - else { - fprintf(stderr, "invalid option %s\n", arg); - return 3; - } - } - else if (name != NULL) { - fprintf(stderr, "only one file name allowed\n"); - return 3; - } - else - name = arg; - source = load(name, &len); - if (source == NULL) { - fprintf(stderr, "memory allocation failure\n"); - return 4; - } - if (len == 0) { - fprintf(stderr, "could not read %s, or it was empty\n", - name == NULL ? "" : name); - free(source); - return 3; - } - if (skip >= len) { - fprintf(stderr, "skip request of %d leaves no input\n", skip); - free(source); - return 3; - } - - /* test inflate data with offset skip */ - len -= skip; - sourcelen = (unsigned long)len; - ret = puff(NIL, &destlen, source + skip, &sourcelen); - if (ret) - fprintf(stderr, "puff() failed with return code %d\n", ret); - else { - fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); - if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", - len - sourcelen); - } - - /* if requested, inflate again and write decompressd data to stdout */ - if (put && ret == 0) { - if (fail) - destlen >>= 1; - dest = malloc(destlen); - if (dest == NULL) { - fprintf(stderr, "memory allocation failure\n"); - free(source); - return 4; - } - puff(dest, &destlen, source + skip, &sourcelen); - SET_BINARY_MODE(stdout); - fwrite(dest, 1, destlen, stdout); - free(dest); - } - - /* clean up */ - free(source); - return ret; -} diff --git a/src/contrib/zlib/contrib/puff/zeros.raw b/src/contrib/zlib/contrib/puff/zeros.raw deleted file mode 100644 index 0a90e76b300205a44a0ecbf613e64aaaef2e51e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2517 zcmYdFkYHV$AkxzmXu#!mP=i#?5{3o^3jqcYc(h*%Opg+yAut*OqaiT#LSPd+y9&tF zP5<`ixi4UXdB8xJfs^6ee;AkH?VUytyFsD;HLIJ(gg5bUnNh}Q2#kinXb22!2pr%5 E0JRq+;s5{u diff --git a/src/contrib/zlib/contrib/testzlib/testzlib.c b/src/contrib/zlib/contrib/testzlib/testzlib.c deleted file mode 100644 index 8626c92..0000000 --- a/src/contrib/zlib/contrib/testzlib/testzlib.c +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include - -#include "zlib.h" - - -void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) -{ - R->HighPart = A.HighPart - B.HighPart; - if (A.LowPart >= B.LowPart) - R->LowPart = A.LowPart - B.LowPart; - else - { - R->LowPart = A.LowPart - B.LowPart; - R->HighPart --; - } -} - -#ifdef _M_X64 -// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc -unsigned __int64 __rdtsc(void); -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - // printf("rdtsc = %I64x\n",__rdtsc()); - pbeginTime64->QuadPart=__rdtsc(); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres; - unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); - LIres.QuadPart=res; - // printf("rdtsc = %I64x\n",__rdtsc()); - return LIres; -} -#else -#ifdef _M_IX86 -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ - DWORD dwEdx,dwEax; - _asm - { - rdtsc - mov dwEax,eax - mov dwEdx,edx - } - pbeginTime64->LowPart=dwEax; - pbeginTime64->HighPart=dwEdx; -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - myGetRDTSC32(pbeginTime64); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres,endTime64; - myGetRDTSC32(&endTime64); - - LIres.LowPart=LIres.HighPart=0; - MyDoMinus64(&LIres,endTime64,beginTime64); - return LIres; -} -#else -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER lr; - lr.QuadPart=0; - return lr; -} -#endif -#endif - -void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) -{ - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) - { - pbeginTime64->LowPart = GetTickCount(); - pbeginTime64->HighPart = 0; - } -} - -DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER endTime64,ticksPerSecond,ticks; - DWORDLONG ticksShifted,tickSecShifted; - DWORD dwLog=16+0; - DWORD dwRet; - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) - dwRet = (GetTickCount() - beginTime64.LowPart)*1; - else - { - MyDoMinus64(&ticks,endTime64,beginTime64); - QueryPerformanceFrequency(&ticksPerSecond); - - - { - ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); - tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); - - } - - dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); - dwRet *=1; - } - return dwRet; -} - -int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) -{ - FILE* stream; - unsigned char* ptr; - int retVal=1; - stream=fopen(filename, "rb"); - if (stream==NULL) - return 0; - - fseek(stream,0,SEEK_END); - - *plFileSize=ftell(stream); - fseek(stream,0,SEEK_SET); - ptr=malloc((*plFileSize)+1); - if (ptr==NULL) - retVal=0; - else - { - if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) - retVal=0; - } - fclose(stream); - *pFilePtr=ptr; - return retVal; -} - -int main(int argc, char *argv[]) -{ - int BlockSizeCompress=0x8000; - int BlockSizeUncompress=0x8000; - int cprLevel=Z_DEFAULT_COMPRESSION ; - long lFileSize; - unsigned char* FilePtr; - long lBufferSizeCpr; - long lBufferSizeUncpr; - long lCompressedSize=0; - unsigned char* CprPtr; - unsigned char* UncprPtr; - long lSizeCpr,lSizeUncpr; - DWORD dwGetTick,dwMsecQP; - LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; - - if (argc<=1) - { - printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); - return 0; - } - - if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) - { - printf("error reading %s\n",argv[1]); - return 1; - } - else printf("file %s read, %u bytes\n",argv[1],lFileSize); - - if (argc>=3) - BlockSizeCompress=atol(argv[2]); - - if (argc>=4) - BlockSizeUncompress=atol(argv[3]); - - if (argc>=5) - cprLevel=(int)atol(argv[4]); - - lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; - lBufferSizeUncpr = lBufferSizeCpr; - - CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lFileSize; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - deflateInit(&zcpr,cprLevel); - - zcpr.next_in = FilePtr; - zcpr.next_out = CprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); - zcpr.avail_out = BlockSizeCompress; - ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeCpr=zcpr.total_out; - deflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total compress size = %u, in %u step\n",lSizeCpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); - UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lSizeCpr; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - inflateInit(&zcpr); - - zcpr.next_in = CprPtr; - zcpr.next_out = UncprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); - zcpr.avail_out = BlockSizeUncompress; - ret=inflate(&zcpr,Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeUncpr=zcpr.total_out; - inflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - if (lSizeUncpr==lFileSize) - { - if (memcmp(FilePtr,UncprPtr,lFileSize)==0) - printf("compare ok\n"); - - } - - return 0; -} diff --git a/src/contrib/zlib/contrib/testzlib/testzlib.txt b/src/contrib/zlib/contrib/testzlib/testzlib.txt deleted file mode 100644 index e508bb2..0000000 --- a/src/contrib/zlib/contrib/testzlib/testzlib.txt +++ /dev/null @@ -1,10 +0,0 @@ -To build testzLib with Visual Studio 2005: - -copy to a directory file from : -- root of zLib tree -- contrib/testzlib -- contrib/masmx86 -- contrib/masmx64 -- contrib/vstudio/vc7 - -and open testzlib8.sln \ No newline at end of file diff --git a/src/contrib/zlib/contrib/untgz/Makefile b/src/contrib/zlib/contrib/untgz/Makefile deleted file mode 100644 index b54266f..0000000 --- a/src/contrib/zlib/contrib/untgz/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -CC=cc -CFLAGS=-g - -untgz: untgz.o ../../libz.a - $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz - -untgz.o: untgz.c ../../zlib.h - $(CC) $(CFLAGS) -c -I../.. untgz.c - -../../libz.a: - cd ../..; ./configure; make - -clean: - rm -f untgz untgz.o *~ diff --git a/src/contrib/zlib/contrib/untgz/Makefile.msc b/src/contrib/zlib/contrib/untgz/Makefile.msc deleted file mode 100644 index 77b8602..0000000 --- a/src/contrib/zlib/contrib/untgz/Makefile.msc +++ /dev/null @@ -1,17 +0,0 @@ -CC=cl -CFLAGS=-MD - -untgz.exe: untgz.obj ..\..\zlib.lib - $(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib - -untgz.obj: untgz.c ..\..\zlib.h - $(CC) $(CFLAGS) -c -I..\.. untgz.c - -..\..\zlib.lib: - cd ..\.. - $(MAKE) -f win32\makefile.msc - cd contrib\untgz - -clean: - -del untgz.obj - -del untgz.exe diff --git a/src/contrib/zlib/contrib/untgz/untgz.c b/src/contrib/zlib/contrib/untgz/untgz.c deleted file mode 100644 index 2c391e5..0000000 --- a/src/contrib/zlib/contrib/untgz/untgz.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * untgz.c -- Display contents and extract files from a gzip'd TAR file - * - * written by Pedro A. Aranda Gutierrez - * adaptation to Unix by Jean-loup Gailly - * various fixes by Cosmin Truta - */ - -#include -#include -#include -#include -#include - -#include "zlib.h" - -#ifdef unix -# include -#else -# include -# include -#endif - -#ifdef WIN32 -#include -# ifndef F_OK -# define F_OK 0 -# endif -# define mkdir(dirname,mode) _mkdir(dirname) -# ifdef _MSC_VER -# define access(path,mode) _access(path,mode) -# define chmod(path,mode) _chmod(path,mode) -# define strdup(str) _strdup(str) -# endif -#else -# include -#endif - - -/* values used in typeflag field */ - -#define REGTYPE '0' /* regular file */ -#define AREGTYPE '\0' /* regular file */ -#define LNKTYPE '1' /* link */ -#define SYMTYPE '2' /* reserved */ -#define CHRTYPE '3' /* character special */ -#define BLKTYPE '4' /* block special */ -#define DIRTYPE '5' /* directory */ -#define FIFOTYPE '6' /* FIFO special */ -#define CONTTYPE '7' /* reserved */ - -/* GNU tar extensions */ - -#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ -#define GNUTYPE_LONGLINK 'K' /* long link name */ -#define GNUTYPE_LONGNAME 'L' /* long file name */ -#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ -#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ -#define GNUTYPE_SPARSE 'S' /* sparse file */ -#define GNUTYPE_VOLHDR 'V' /* tape/volume header */ - - -/* tar header */ - -#define BLOCKSIZE 512 -#define SHORTNAMESIZE 100 - -struct tar_header -{ /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - char typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[155]; /* 345 */ - /* 500 */ -}; - -union tar_buffer -{ - char buffer[BLOCKSIZE]; - struct tar_header header; -}; - -struct attr_item -{ - struct attr_item *next; - char *fname; - int mode; - time_t time; -}; - -enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; - -char *TGZfname OF((const char *)); -void TGZnotfound OF((const char *)); - -int getoct OF((char *, int)); -char *strtime OF((time_t *)); -int setfiletime OF((char *, time_t)); -void push_attr OF((struct attr_item **, char *, int, time_t)); -void restore_attr OF((struct attr_item **)); - -int ExprMatch OF((char *, char *)); - -int makedir OF((char *)); -int matchname OF((int, int, char **, char *)); - -void error OF((const char *)); -int tar OF((gzFile, int, int, int, char **)); - -void help OF((int)); -int main OF((int, char **)); - -char *prog; - -const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; - -/* return the file name of the TGZ archive */ -/* or NULL if it does not exist */ - -char *TGZfname (const char *arcname) -{ - static char buffer[1024]; - int origlen,i; - - strcpy(buffer,arcname); - origlen = strlen(buffer); - - for (i=0; TGZsuffix[i]; i++) - { - strcpy(buffer+origlen,TGZsuffix[i]); - if (access(buffer,F_OK) == 0) - return buffer; - } - return NULL; -} - - -/* error message for the filename */ - -void TGZnotfound (const char *arcname) -{ - int i; - - fprintf(stderr,"%s: Couldn't find ",prog); - for (i=0;TGZsuffix[i];i++) - fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", - arcname, - TGZsuffix[i]); - exit(1); -} - - -/* convert octal digits to int */ -/* on error return -1 */ - -int getoct (char *p,int width) -{ - int result = 0; - char c; - - while (width--) - { - c = *p++; - if (c == 0) - break; - if (c == ' ') - continue; - if (c < '0' || c > '7') - return -1; - result = result * 8 + (c - '0'); - } - return result; -} - - -/* convert time_t to string */ -/* use the "YYYY/MM/DD hh:mm:ss" format */ - -char *strtime (time_t *t) -{ - struct tm *local; - static char result[32]; - - local = localtime(t); - sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", - local->tm_year+1900, local->tm_mon+1, local->tm_mday, - local->tm_hour, local->tm_min, local->tm_sec); - return result; -} - - -/* set file time */ - -int setfiletime (char *fname,time_t ftime) -{ -#ifdef WIN32 - static int isWinNT = -1; - SYSTEMTIME st; - FILETIME locft, modft; - struct tm *loctm; - HANDLE hFile; - int result; - - loctm = localtime(&ftime); - if (loctm == NULL) - return -1; - - st.wYear = (WORD)loctm->tm_year + 1900; - st.wMonth = (WORD)loctm->tm_mon + 1; - st.wDayOfWeek = (WORD)loctm->tm_wday; - st.wDay = (WORD)loctm->tm_mday; - st.wHour = (WORD)loctm->tm_hour; - st.wMinute = (WORD)loctm->tm_min; - st.wSecond = (WORD)loctm->tm_sec; - st.wMilliseconds = 0; - if (!SystemTimeToFileTime(&st, &locft) || - !LocalFileTimeToFileTime(&locft, &modft)) - return -1; - - if (isWinNT < 0) - isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; - hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, - (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), - NULL); - if (hFile == INVALID_HANDLE_VALUE) - return -1; - result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; - CloseHandle(hFile); - return result; -#else - struct utimbuf settime; - - settime.actime = settime.modtime = ftime; - return utime(fname,&settime); -#endif -} - - -/* push file attributes */ - -void push_attr(struct attr_item **list,char *fname,int mode,time_t time) -{ - struct attr_item *item; - - item = (struct attr_item *)malloc(sizeof(struct attr_item)); - if (item == NULL) - error("Out of memory"); - item->fname = strdup(fname); - item->mode = mode; - item->time = time; - item->next = *list; - *list = item; -} - - -/* restore file attributes */ - -void restore_attr(struct attr_item **list) -{ - struct attr_item *item, *prev; - - for (item = *list; item != NULL; ) - { - setfiletime(item->fname,item->time); - chmod(item->fname,item->mode); - prev = item; - item = item->next; - free(prev); - } - *list = NULL; -} - - -/* match regular expression */ - -#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) - -int ExprMatch (char *string,char *expr) -{ - while (1) - { - if (ISSPECIAL(*expr)) - { - if (*expr == '/') - { - if (*string != '\\' && *string != '/') - return 0; - string ++; expr++; - } - else if (*expr == '*') - { - if (*expr ++ == 0) - return 1; - while (*++string != *expr) - if (*string == 0) - return 0; - } - } - else - { - if (*string != *expr) - return 0; - if (*expr++ == 0) - return 1; - string++; - } - } -} - - -/* recursive mkdir */ -/* abort on ENOENT; ignore other errors like "directory already exists" */ -/* return 1 if OK */ -/* 0 on error */ - -int makedir (char *newdir) -{ - char *buffer = strdup(newdir); - char *p; - int len = strlen(buffer); - - if (len <= 0) { - free(buffer); - return 0; - } - if (buffer[len-1] == '/') { - buffer[len-1] = '\0'; - } - if (mkdir(buffer, 0755) == 0) - { - free(buffer); - return 1; - } - - p = buffer+1; - while (1) - { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) - { - fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer); - free(buffer); - return 0; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 1; -} - - -int matchname (int arg,int argc,char **argv,char *fname) -{ - if (arg == argc) /* no arguments given (untgz tgzarchive) */ - return 1; - - while (arg < argc) - if (ExprMatch(fname,argv[arg++])) - return 1; - - return 0; /* ignore this for the moment being */ -} - - -/* tar file list or extract */ - -int tar (gzFile in,int action,int arg,int argc,char **argv) -{ - union tar_buffer buffer; - int len; - int err; - int getheader = 1; - int remaining = 0; - FILE *outfile = NULL; - char fname[BLOCKSIZE]; - int tarmode; - time_t tartime; - struct attr_item *attributes = NULL; - - if (action == TGZ_LIST) - printf(" date time size file\n" - " ---------- -------- --------- -------------------------------------\n"); - while (1) - { - len = gzread(in, &buffer, BLOCKSIZE); - if (len < 0) - error(gzerror(in, &err)); - /* - * Always expect complete blocks to process - * the tar information. - */ - if (len != BLOCKSIZE) - { - action = TGZ_INVALID; /* force error exit */ - remaining = 0; /* force I/O cleanup */ - } - - /* - * If we have to get a tar header - */ - if (getheader >= 1) - { - /* - * if we met the end of the tar - * or the end-of-tar block, - * we are done - */ - if (len == 0 || buffer.header.name[0] == 0) - break; - - tarmode = getoct(buffer.header.mode,8); - tartime = (time_t)getoct(buffer.header.mtime,12); - if (tarmode == -1 || tartime == (time_t)-1) - { - buffer.header.name[0] = 0; - action = TGZ_INVALID; - } - - if (getheader == 1) - { - strncpy(fname,buffer.header.name,SHORTNAMESIZE); - if (fname[SHORTNAMESIZE-1] != 0) - fname[SHORTNAMESIZE] = 0; - } - else - { - /* - * The file name is longer than SHORTNAMESIZE - */ - if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) - error("bad long name"); - getheader = 1; - } - - /* - * Act according to the type flag - */ - switch (buffer.header.typeflag) - { - case DIRTYPE: - if (action == TGZ_LIST) - printf(" %s
%s\n",strtime(&tartime),fname); - if (action == TGZ_EXTRACT) - { - makedir(fname); - push_attr(&attributes,fname,tarmode,tartime); - } - break; - case REGTYPE: - case AREGTYPE: - remaining = getoct(buffer.header.size,12); - if (remaining == -1) - { - action = TGZ_INVALID; - break; - } - if (action == TGZ_LIST) - printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); - else if (action == TGZ_EXTRACT) - { - if (matchname(arg,argc,argv,fname)) - { - outfile = fopen(fname,"wb"); - if (outfile == NULL) { - /* try creating directory */ - char *p = strrchr(fname, '/'); - if (p != NULL) { - *p = '\0'; - makedir(fname); - *p = '/'; - outfile = fopen(fname,"wb"); - } - } - if (outfile != NULL) - printf("Extracting %s\n",fname); - else - fprintf(stderr, "%s: Couldn't create %s",prog,fname); - } - else - outfile = NULL; - } - getheader = 0; - break; - case GNUTYPE_LONGLINK: - case GNUTYPE_LONGNAME: - remaining = getoct(buffer.header.size,12); - if (remaining < 0 || remaining >= BLOCKSIZE) - { - action = TGZ_INVALID; - break; - } - len = gzread(in, fname, BLOCKSIZE); - if (len < 0) - error(gzerror(in, &err)); - if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) - { - action = TGZ_INVALID; - break; - } - getheader = 2; - break; - default: - if (action == TGZ_LIST) - printf(" %s <---> %s\n",strtime(&tartime),fname); - break; - } - } - else - { - unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; - - if (outfile != NULL) - { - if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) - { - fprintf(stderr, - "%s: Error writing %s -- skipping\n",prog,fname); - fclose(outfile); - outfile = NULL; - remove(fname); - } - } - remaining -= bytes; - } - - if (remaining == 0) - { - getheader = 1; - if (outfile != NULL) - { - fclose(outfile); - outfile = NULL; - if (action != TGZ_INVALID) - push_attr(&attributes,fname,tarmode,tartime); - } - } - - /* - * Abandon if errors are found - */ - if (action == TGZ_INVALID) - { - error("broken archive"); - break; - } - } - - /* - * Restore file modes and time stamps - */ - restore_attr(&attributes); - - if (gzclose(in) != Z_OK) - error("failed gzclose"); - - return 0; -} - - -/* ============================================================ */ - -void help(int exitval) -{ - printf("untgz version 0.2.1\n" - " using zlib version %s\n\n", - zlibVersion()); - printf("Usage: untgz file.tgz extract all files\n" - " untgz file.tgz fname ... extract selected files\n" - " untgz -l file.tgz list archive contents\n" - " untgz -h display this help\n"); - exit(exitval); -} - -void error(const char *msg) -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - - -/* ============================================================ */ - -#if defined(WIN32) && defined(__GNUC__) -int _CRT_glob = 0; /* disable argument globbing in MinGW */ -#endif - -int main(int argc,char **argv) -{ - int action = TGZ_EXTRACT; - int arg = 1; - char *TGZfile; - gzFile *f; - - prog = strrchr(argv[0],'\\'); - if (prog == NULL) - { - prog = strrchr(argv[0],'/'); - if (prog == NULL) - { - prog = strrchr(argv[0],':'); - if (prog == NULL) - prog = argv[0]; - else - prog++; - } - else - prog++; - } - else - prog++; - - if (argc == 1) - help(0); - - if (strcmp(argv[arg],"-l") == 0) - { - action = TGZ_LIST; - if (argc == ++arg) - help(0); - } - else if (strcmp(argv[arg],"-h") == 0) - { - help(0); - } - - if ((TGZfile = TGZfname(argv[arg])) == NULL) - TGZnotfound(argv[arg]); - - ++arg; - if ((action == TGZ_LIST) && (arg != argc)) - help(1); - -/* - * Process the TGZ file - */ - switch(action) - { - case TGZ_LIST: - case TGZ_EXTRACT: - f = gzopen(TGZfile,"rb"); - if (f == NULL) - { - fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile); - return 1; - } - exit(tar(f, action, arg, argc, argv)); - break; - - default: - error("Unknown option"); - exit(1); - } - - return 0; -} diff --git a/src/contrib/zlib/contrib/vstudio/readme.txt b/src/contrib/zlib/contrib/vstudio/readme.txt deleted file mode 100644 index 48cccc0..0000000 --- a/src/contrib/zlib/contrib/vstudio/readme.txt +++ /dev/null @@ -1,78 +0,0 @@ -Building instructions for the DLL versions of Zlib 1.2.11 -======================================================== - -This directory contains projects that build zlib and minizip using -Microsoft Visual C++ 9.0/10.0. - -You don't need to build these projects yourself. You can download the -binaries from: - http://www.winimage.com/zLibDll - -More information can be found at this site. - - - - - -Build instructions for Visual Studio 2008 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Compile assembly code (with Visual Studio Command Prompt) by running: - bld_ml64.bat (in contrib\masmx64) - bld_ml32.bat (in contrib\masmx86) -- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008 -- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32" - -Build instructions for Visual Studio 2010 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010 - -Build instructions for Visual Studio 2012 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012 - -Build instructions for Visual Studio 2013 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013 - -Build instructions for Visual Studio 2015 (32 bits or 64 bits) --------------------------------------------------------------- -- Decompress current zlib, including all contrib/* files -- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015 - - -Important ---------- -- To use zlibwapi.dll in your application, you must define the - macro ZLIB_WINAPI when compiling your application's source files. - - -Additional notes ----------------- -- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built - by Gilles Vollant from the zlib 1.1.x sources, and distributed at - http://www.winimage.com/zLibDll - It uses the WINAPI calling convention for the exported functions, and - includes the minizip functionality. If your application needs that - particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll. - -- The new DLL was renamed because there exist several incompatible - versions of zlib.dll on the Internet. - -- There is also an official DLL build of zlib, named zlib1.dll. This one - is exporting the functions using the CDECL convention. See the file - win32\DLL_FAQ.txt found in this zlib distribution. - -- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol - has a slightly different effect. To avoid compatibility problems, do - not define it here. - - -Gilles Vollant -info@winimage.com - -Visual Studio 2013 and 2015 Projects from Sean Hunt -seandhunt_7@yahoo.com diff --git a/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj deleted file mode 100644 index 1b36242..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj +++ /dev/null @@ -1,310 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694382A} - Win32Proj - - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - true - false - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - false - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - true - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - true - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - false - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebug - false - - - $(IntDir) - Level3 - EditAndContinue - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters deleted file mode 100644 index 0bd1221..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {048af943-022b-4db6-beeb-a54c34774ee2} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {c1d600d2-888f-4aea-b73e-8b0dd9befa0c} - h;hpp;hxx;hm;inl;inc - - - {0844199a-966b-4f19-81db-1e0125e141b9} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj deleted file mode 100644 index ccd3651..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj +++ /dev/null @@ -1,307 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} - Win32Proj - - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - true - false - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - false - x64\$(Configuration)\ - x64\$(Configuration)\ - true - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - true - false - x64\$(Configuration)\ - x64\$(Configuration)\ - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebug - false - - - $(IntDir) - Level3 - EditAndContinue - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters deleted file mode 100644 index 7076d76..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {c0419b40-bf50-40da-b153-ff74215b79de} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {bb87b070-735b-478e-92ce-7383abb2f36c} - h;hpp;hxx;hm;inl;inc - - - {f46ab6a6-548f-43cb-ae96-681abb5bd5db} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj deleted file mode 100644 index 476b8ea..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj +++ /dev/null @@ -1,420 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} - testzlib - Win32Proj - - - - Application - MultiByte - true - - - Application - MultiByte - true - - - Application - MultiByte - - - Application - MultiByte - true - - - Application - MultiByte - true - - - Application - MultiByte - - - Application - true - - - Application - true - - - Application - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - true - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - true - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebug - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - EditAndContinue - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDebugDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - %(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters deleted file mode 100644 index 3276491..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters +++ /dev/null @@ -1,58 +0,0 @@ - - - - - {c1f6a2e3-5da5-4955-8653-310d3efe05a9} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {c2aaffdc-2c95-4d6f-8466-4bec5890af2c} - h;hpp;hxx;hm;inl;inc - - - {c274fe07-05f2-461c-964b-f6341e4e7eb5} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj deleted file mode 100644 index 8e38876..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj +++ /dev/null @@ -1,310 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694366A} - Win32Proj - - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - true - false - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - false - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - true - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - true - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - false - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebug - false - - - $(IntDir) - Level3 - EditAndContinue - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters deleted file mode 100644 index ab87f09..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {fa61a89f-93fc-4c89-b29e-36224b7592f4} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {d4b85da0-2ba2-4934-b57f-e2584e3848ee} - h;hpp;hxx;hm;inl;inc - - - {e573e075-00bd-4a7d-bd67-a8cc9bfc5aca} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlib.rc b/src/contrib/zlib/contrib/vstudio/vc10/zlib.rc deleted file mode 100644 index c4e4b01..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj deleted file mode 100644 index 45389a3..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj +++ /dev/null @@ -1,473 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} - - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - - - MultiThreadedDebug - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - Itanium - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters deleted file mode 100644 index 0c8b250..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters +++ /dev/null @@ -1,77 +0,0 @@ - - - - - {174213f6-7f66-4ae8-a3a8-a1e0a1e6ffdd} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - - - Source Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.def b/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.def deleted file mode 100644 index f876c3b..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.sln b/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.sln deleted file mode 100644 index 649f40c..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.sln +++ /dev/null @@ -1,135 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj b/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj deleted file mode 100644 index 7d7c49a..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj +++ /dev/null @@ -1,657 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {8FD826F8-3739-44E6-8CC8-997122E53B8D} - - - - DynamicLibrary - false - true - - - DynamicLibrary - false - true - - - DynamicLibrary - false - - - DynamicLibrary - false - true - - - DynamicLibrary - false - true - - - DynamicLibrary - false - - - DynamicLibrary - false - true - - - DynamicLibrary - false - true - - - DynamicLibrary - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - true - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - true - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - true - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - zlibwapid - zlibwapi - zlibwapi - zlibwapid - zlibwapi - zlibwapi - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - - - MultiThreadedDebug - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - EditAndContinue - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - true - .\zlibvc.def - true - true - Windows - false - - - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - true - false - .\zlibvc.def - true - Windows - false - - - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - true - false - .\zlibvc.def - true - Windows - false - - - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - true - .\zlibvc.def - true - true - Windows - MachineX64 - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - true - false - .\zlibvc.def - true - Windows - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - true - false - .\zlibvc.def - true - Windows - MachineX64 - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters b/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters deleted file mode 100644 index 2278682..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters +++ /dev/null @@ -1,118 +0,0 @@ - - - - - {07934a85-8b61-443d-a0ee-b2eedb74f3cd} - cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 - - - {1d99675b-433d-4a21-9e50-ed4ab8b19762} - h;hpp;hxx;hm;inl;fi;fd - - - {431c0958-fa71-44d0-9084-2d19d100c0cc} - ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj deleted file mode 100644 index 99be63d..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj +++ /dev/null @@ -1,314 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694382A} - Win32Proj - - - - Application - MultiByte - v110 - - - Application - Unicode - v110 - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - v110 - - - Application - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - true - false - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - false - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - true - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - true - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - false - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj deleted file mode 100644 index d6e98f4..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj +++ /dev/null @@ -1,311 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} - Win32Proj - - - - Application - MultiByte - v110 - - - Application - Unicode - v110 - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - v110 - - - Application - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - true - false - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - false - x64\$(Configuration)\ - x64\$(Configuration)\ - true - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - true - false - x64\$(Configuration)\ - x64\$(Configuration)\ - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj deleted file mode 100644 index 0115dd1..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj +++ /dev/null @@ -1,426 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} - testzlib - Win32Proj - - - - Application - MultiByte - true - v110 - - - Application - MultiByte - true - v110 - - - Application - Unicode - v110 - - - Application - MultiByte - true - - - Application - MultiByte - true - - - Application - MultiByte - - - Application - true - v110 - - - Application - true - v110 - - - Application - v110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - true - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - true - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDebugDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - %(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj deleted file mode 100644 index 9d36336..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj +++ /dev/null @@ -1,314 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694366A} - Win32Proj - - - - Application - MultiByte - v110 - - - Application - Unicode - v110 - - - Application - MultiByte - - - Application - MultiByte - - - Application - MultiByte - v110 - - - Application - MultiByte - v110 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - true - false - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - false - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - true - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - true - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - false - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/zlib.rc b/src/contrib/zlib/contrib/vstudio/vc11/zlib.rc deleted file mode 100644 index c4e4b01..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj deleted file mode 100644 index 64b4d86..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj +++ /dev/null @@ -1,464 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} - - - - StaticLibrary - false - v110 - - - StaticLibrary - false - v110 - - - StaticLibrary - false - v110 - Unicode - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - - - StaticLibrary - false - v110 - - - StaticLibrary - false - v110 - - - StaticLibrary - false - v110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.def b/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.def deleted file mode 100644 index f876c3b..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.sln b/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.sln deleted file mode 100644 index b7e3812..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.sln +++ /dev/null @@ -1,117 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj b/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj deleted file mode 100644 index c4cffcc..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj +++ /dev/null @@ -1,688 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {8FD826F8-3739-44E6-8CC8-997122E53B8D} - - - - DynamicLibrary - false - true - v110 - - - DynamicLibrary - false - true - v110 - - - DynamicLibrary - false - v110 - Unicode - - - DynamicLibrary - false - true - - - DynamicLibrary - false - true - - - DynamicLibrary - false - - - DynamicLibrary - false - true - v110 - - - DynamicLibrary - false - true - v110 - - - DynamicLibrary - false - v110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - true - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - true - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - true - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\contrib\masmx64 -bld_ml64.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj deleted file mode 100644 index d88ac7f..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694382A} - Win32Proj - - - - Application - MultiByte - v120 - - - Application - Unicode - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - true - false - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - false - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - true - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - true - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - false - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj deleted file mode 100644 index f1f239c..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj +++ /dev/null @@ -1,313 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} - Win32Proj - - - - Application - MultiByte - v120 - - - Application - Unicode - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - true - false - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - false - x64\$(Configuration)\ - x64\$(Configuration)\ - true - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - true - false - x64\$(Configuration)\ - x64\$(Configuration)\ - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj deleted file mode 100644 index 64b2cbe..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj +++ /dev/null @@ -1,430 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} - testzlib - Win32Proj - - - - Application - MultiByte - true - v120 - - - Application - MultiByte - true - v120 - - - Application - Unicode - v120 - - - Application - MultiByte - true - v120 - - - Application - MultiByte - true - v120 - - - Application - MultiByte - v120 - - - Application - true - v120 - - - Application - true - v120 - - - Application - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - true - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - true - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - false - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDebugDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - %(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj deleted file mode 100644 index c66573a..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694366A} - Win32Proj - - - - Application - MultiByte - v120 - - - Application - Unicode - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - Application - MultiByte - v120 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - true - false - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - false - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - true - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - true - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - false - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/zlib.rc b/src/contrib/zlib/contrib/vstudio/vc12/zlib.rc deleted file mode 100644 index c4e4b01..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj deleted file mode 100644 index 3fdee7c..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj +++ /dev/null @@ -1,467 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} - - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - Unicode - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - StaticLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.def b/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.def deleted file mode 100644 index f876c3b..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.sln b/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.sln deleted file mode 100644 index dcda229..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.sln +++ /dev/null @@ -1,119 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj b/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj deleted file mode 100644 index ab2b6c3..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj +++ /dev/null @@ -1,692 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {8FD826F8-3739-44E6-8CC8-997122E53B8D} - - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - v120 - Unicode - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - v120 - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - true - v120 - - - DynamicLibrary - false - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - true - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - true - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - true - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - false - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\contrib\masmx64 -bld_ml64.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj deleted file mode 100644 index 9b5c075..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694382A} - Win32Proj - - - - Application - MultiByte - v140 - - - Application - Unicode - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - true - false - x86\MiniUnzip$(Configuration)\ - x86\MiniUnzip$(Configuration)\Tmp\ - false - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - true - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - true - false - x64\MiniUnzip$(Configuration)\ - x64\MiniUnzip$(Configuration)\Tmp\ - false - false - ia64\MiniUnzip$(Configuration)\ - ia64\MiniUnzip$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - $(OutDir)miniunz.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)miniunz.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj deleted file mode 100644 index 968a410..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj +++ /dev/null @@ -1,313 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} - Win32Proj - - - - Application - MultiByte - v140 - - - Application - Unicode - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - true - false - x86\MiniZip$(Configuration)\ - x86\MiniZip$(Configuration)\Tmp\ - false - x64\$(Configuration)\ - x64\$(Configuration)\ - true - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - true - false - x64\$(Configuration)\ - x64\$(Configuration)\ - false - ia64\$(Configuration)\ - ia64\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - $(OutDir)minizip.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)minizip.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj deleted file mode 100644 index 2c37125..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj +++ /dev/null @@ -1,430 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} - testzlib - Win32Proj - - - - Application - MultiByte - true - v140 - - - Application - MultiByte - true - v140 - - - Application - Unicode - v140 - - - Application - MultiByte - true - v140 - - - Application - MultiByte - true - v140 - - - Application - MultiByte - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - true - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x86\TestZlib$(Configuration)\ - x86\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - true - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - x64\TestZlib$(Configuration)\ - x64\TestZlib$(Configuration)\Tmp\ - false - ia64\TestZlib$(Configuration)\ - ia64\TestZlib$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)testzlib.exe - true - Console - true - true - false - - - MachineX86 - false - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDebugDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - Disabled - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - AssemblyAndSourceCode - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - %(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - ..\..\..;%(AdditionalIncludeDirectories) - ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - Default - MultiThreadedDLL - false - $(IntDir) - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - $(OutDir)testzlib.exe - true - Console - true - true - MachineIA64 - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj deleted file mode 100644 index d87474d..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {C52F9E7B-498A-42BE-8DB4-85A15694366A} - Win32Proj - - - - Application - MultiByte - v140 - - - Application - Unicode - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - Application - MultiByte - v140 - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - true - false - x86\TestZlibDll$(Configuration)\ - x86\TestZlibDll$(Configuration)\Tmp\ - false - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - true - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - true - false - x64\TestZlibDll$(Configuration)\ - x64\TestZlibDll$(Configuration)\Tmp\ - false - false - ia64\TestZlibDll$(Configuration)\ - ia64\TestZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - false - - - MachineX86 - - - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - Default - MultiThreaded - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineX64 - - - - - Itanium - - - Disabled - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDebugDLL - false - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - $(OutDir)testzlib.pdb - Console - MachineIA64 - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineX64 - - - - - Itanium - - - MaxSpeed - OnlyExplicitInline - true - ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) - true - Default - MultiThreadedDLL - false - true - - - $(IntDir) - Level3 - ProgramDatabase - - - ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) - $(OutDir)testzlibdll.exe - true - Console - true - true - MachineIA64 - - - - - - - - {8fd826f8-3739-44e6-8cc8-997122e53b8d} - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/zlib.rc b/src/contrib/zlib/contrib/vstudio/vc14/zlib.rc deleted file mode 100644 index c4e4b01..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj deleted file mode 100644 index 3e4b986..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj +++ /dev/null @@ -1,467 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} - - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - Unicode - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - StaticLibrary - false - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x86\ZlibStat$(Configuration)\ - x86\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - x64\ZlibStat$(Configuration)\ - x64\ZlibStat$(Configuration)\Tmp\ - ia64\ZlibStat$(Configuration)\ - ia64\ZlibStat$(Configuration)\Tmp\ - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - OldStyle - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - X64 - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - Itanium - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibstat.pch - $(IntDir) - $(IntDir) - $(OutDir) - Level3 - true - - - 0x040c - - - /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) - $(OutDir)zlibstat.lib - true - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.def b/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.def deleted file mode 100644 index f876c3b..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.sln b/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.sln deleted file mode 100644 index 6f4a107..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.sln +++ /dev/null @@ -1,119 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj b/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj deleted file mode 100644 index f8f673c..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj +++ /dev/null @@ -1,692 +0,0 @@ - - - - - Debug - Itanium - - - Debug - Win32 - - - Debug - x64 - - - ReleaseWithoutAsm - Itanium - - - ReleaseWithoutAsm - Win32 - - - ReleaseWithoutAsm - x64 - - - Release - Itanium - - - Release - Win32 - - - Release - x64 - - - - {8FD826F8-3739-44E6-8CC8-997122E53B8D} - - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - v140 - Unicode - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - v140 - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - true - v140 - - - DynamicLibrary - false - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - true - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x86\ZlibDll$(Configuration)\ - x86\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - true - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - true - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - x64\ZlibDll$(Configuration)\ - x64\ZlibDll$(Configuration)\Tmp\ - false - false - ia64\ZlibDll$(Configuration)\ - ia64\ZlibDll$(Configuration)\Tmp\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - zlibwapi - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) - true - - - MultiThreaded - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - /MACHINE:I386 %(AdditionalOptions) - ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - false - - - $(OutDir)zlibwapi.lib - false - - - cd ..\..\masmx86 -bld_ml32.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\contrib\masmx64 -bld_ml64.bat - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - Disabled - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - - - MultiThreadedDebugDLL - false - $(IntDir)zlibvc.pch - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - ProgramDatabase - - - _DEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - .\zlibvc.def - true - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineX64 - - - cd ..\..\masmx64 -bld_ml64.bat - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Itanium - $(OutDir)zlibvc.tlb - - - OnlyExplicitInline - ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - $(IntDir)zlibvc.pch - All - $(IntDir) - $(IntDir) - $(OutDir) - - - Level3 - true - - - NDEBUG;%(PreprocessorDefinitions) - 0x040c - - - $(OutDir)zlibwapi.dll - true - false - .\zlibvc.def - $(OutDir)zlibwapi.pdb - true - $(OutDir)zlibwapi.map - Windows - $(OutDir)zlibwapi.lib - MachineIA64 - - - - - - - - - - - - - - true - true - true - true - true - true - - - - - - - - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - %(AdditionalIncludeDirectories) - ZLIB_INTERNAL;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj deleted file mode 100644 index 038a9e5..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj +++ /dev/null @@ -1,565 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/vstudio/vc9/minizip.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/minizip.vcproj deleted file mode 100644 index ad40239..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/minizip.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj deleted file mode 100644 index c9f19d2..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj +++ /dev/null @@ -1,852 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/vstudio/vc9/testzlibdll.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/testzlibdll.vcproj deleted file mode 100644 index d7530fd..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/testzlibdll.vcproj +++ /dev/null @@ -1,565 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/vstudio/vc9/zlib.rc b/src/contrib/zlib/contrib/vstudio/vc9/zlib.rc deleted file mode 100644 index c4e4b01..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/zlib.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#define IDR_VERSION1 1 -IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1, 2, 11, 0 - PRODUCTVERSION 1, 2, 11, 0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS 0 - FILEOS VOS_DOS_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - - BEGIN - VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.11\0" - VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlibwapi.dll\0" - VALUE "ProductName", "ZLib.DLL\0" - VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj deleted file mode 100644 index d4ffb46..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj +++ /dev/null @@ -1,835 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.def b/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.def deleted file mode 100644 index f876c3b..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.def +++ /dev/null @@ -1,153 +0,0 @@ -LIBRARY -; zlib data compression and ZIP file I/O library - -VERSION 1.2 - -EXPORTS - adler32 @1 - compress @2 - crc32 @3 - deflate @4 - deflateCopy @5 - deflateEnd @6 - deflateInit2_ @7 - deflateInit_ @8 - deflateParams @9 - deflateReset @10 - deflateSetDictionary @11 - gzclose @12 - gzdopen @13 - gzerror @14 - gzflush @15 - gzopen @16 - gzread @17 - gzwrite @18 - inflate @19 - inflateEnd @20 - inflateInit2_ @21 - inflateInit_ @22 - inflateReset @23 - inflateSetDictionary @24 - inflateSync @25 - uncompress @26 - zlibVersion @27 - gzprintf @28 - gzputc @29 - gzgetc @30 - gzseek @31 - gzrewind @32 - gztell @33 - gzeof @34 - gzsetparams @35 - zError @36 - inflateSyncPoint @37 - get_crc_table @38 - compress2 @39 - gzputs @40 - gzgets @41 - inflateCopy @42 - inflateBackInit_ @43 - inflateBack @44 - inflateBackEnd @45 - compressBound @46 - deflateBound @47 - gzclearerr @48 - gzungetc @49 - zlibCompileFlags @50 - deflatePrime @51 - deflatePending @52 - - unzOpen @61 - unzClose @62 - unzGetGlobalInfo @63 - unzGetCurrentFileInfo @64 - unzGoToFirstFile @65 - unzGoToNextFile @66 - unzOpenCurrentFile @67 - unzReadCurrentFile @68 - unzOpenCurrentFile3 @69 - unztell @70 - unzeof @71 - unzCloseCurrentFile @72 - unzGetGlobalComment @73 - unzStringFileNameCompare @74 - unzLocateFile @75 - unzGetLocalExtrafield @76 - unzOpen2 @77 - unzOpenCurrentFile2 @78 - unzOpenCurrentFilePassword @79 - - zipOpen @80 - zipOpenNewFileInZip @81 - zipWriteInFileInZip @82 - zipCloseFileInZip @83 - zipClose @84 - zipOpenNewFileInZip2 @86 - zipCloseFileInZipRaw @87 - zipOpen2 @88 - zipOpenNewFileInZip3 @89 - - unzGetFilePos @100 - unzGoToFilePos @101 - - fill_win32_filefunc @110 - -; zlibwapi v1.2.4 added: - fill_win32_filefunc64 @111 - fill_win32_filefunc64A @112 - fill_win32_filefunc64W @113 - - unzOpen64 @120 - unzOpen2_64 @121 - unzGetGlobalInfo64 @122 - unzGetCurrentFileInfo64 @124 - unzGetCurrentFileZStreamPos64 @125 - unztell64 @126 - unzGetFilePos64 @127 - unzGoToFilePos64 @128 - - zipOpen64 @130 - zipOpen2_64 @131 - zipOpenNewFileInZip64 @132 - zipOpenNewFileInZip2_64 @133 - zipOpenNewFileInZip3_64 @134 - zipOpenNewFileInZip4_64 @135 - zipCloseFileInZipRaw64 @136 - -; zlib1 v1.2.4 added: - adler32_combine @140 - crc32_combine @142 - deflateSetHeader @144 - deflateTune @145 - gzbuffer @146 - gzclose_r @147 - gzclose_w @148 - gzdirect @149 - gzoffset @150 - inflateGetHeader @156 - inflateMark @157 - inflatePrime @158 - inflateReset2 @159 - inflateUndermine @160 - -; zlib1 v1.2.6 added: - gzgetc_ @161 - inflateResetKeep @163 - deflateResetKeep @164 - -; zlib1 v1.2.7 added: - gzopen_w @165 - -; zlib1 v1.2.8 added: - inflateGetDictionary @166 - gzvprintf @167 - -; zlib1 v1.2.9 added: - inflateCodesUsed @168 - inflateValidate @169 - uncompress2 @170 - gzfread @171 - gzfwrite @172 - deflateGetDictionary @173 - adler32_z @174 - crc32_z @175 diff --git a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.sln b/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.sln deleted file mode 100644 index 75c64c3..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.sln +++ /dev/null @@ -1,144 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" - ProjectSection(ProjectDependencies) = postProject - {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" - ProjectSection(ProjectDependencies) = postProject - {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" - ProjectSection(ProjectDependencies) = postProject - {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Itanium = Debug|Itanium - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Itanium = Release|Itanium - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium - ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 - ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 - {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 - {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj b/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj deleted file mode 100644 index 95bb241..0000000 --- a/src/contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj +++ /dev/null @@ -1,1156 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/crc32.c b/src/contrib/zlib/crc32.c deleted file mode 100644 index 9580440..0000000 --- a/src/contrib/zlib/crc32.c +++ /dev/null @@ -1,442 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - - DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. - */ - -#ifdef MAKECRCH -# include -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -/* Definitions for doing the crc four data bytes at a time. */ -#if !defined(NOBYFOUR) && defined(Z_U4) -# define BYFOUR -#endif -#ifdef BYFOUR - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, z_size_t)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, z_size_t)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); - - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local z_crc_t FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - z_crc_t c; - int n, k; - z_crc_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (z_crc_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (z_crc_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const z_crc_t FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table(out, table) - FILE *out; - const z_crc_t FAR *table; -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const z_crc_t FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - z_crc_t endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - uInt len; -{ - return crc32_z(crc, buf, len); -} - -#ifdef BYFOUR - -/* - This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit - integer pointer type. This violates the strict aliasing rule, where a - compiler can assume, for optimization purposes, that two pointers to - fundamentally different types won't ever point to the same memory. This can - manifest as a problem only if one of the pointers is written to. This code - only reads from those pointers. So long as this code remains isolated in - this compilation unit, there won't be a problem. For this reason, this code - should not be copied and pasted into a compilation unit in which other code - writes to the buffer that is passed to these routines. - */ - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = (z_crc_t)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ - register z_crc_t c; - register const z_crc_t FAR *buf4; - - c = ZSWAP32((z_crc_t)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(ZSWAP32(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -local uLong crc32_combine_(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case (also disallow negative lengths) */ - if (len2 <= 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} - -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ - return crc32_combine_(crc1, crc2, len2); -} diff --git a/src/contrib/zlib/crc32.h b/src/contrib/zlib/crc32.h deleted file mode 100644 index 9e0c778..0000000 --- a/src/contrib/zlib/crc32.h +++ /dev/null @@ -1,441 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const z_crc_t FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; diff --git a/src/contrib/zlib/deflate.c b/src/contrib/zlib/deflate.c deleted file mode 100644 index 1ec7614..0000000 --- a/src/contrib/zlib/deflate.c +++ /dev/null @@ -1,2163 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local int deflateStateCheck OF((z_streamp strm)); -local void slide_hash OF((deflate_state *s)); -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV -# pragma message("Assembler code may have bugs -- use at your own risk") - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef ZLIB_DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to UPDATE_HASH are made with consecutive input - * characters, so that a running hash key can be computed from the previous - * key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to INSERT_STRING are made with consecutive input - * characters and the first MIN_MATCH bytes of str are valid (except for - * the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* =========================================================================== - * Slide the hash table when sliding the window down (could be avoided with 32 - * bit values at the expense of memory usage). We slide even when level == 0 to - * keep the hash table consistent if we switch back to level > 0 later. - */ -local void slide_hash(s) - deflate_state *s; -{ - unsigned n, m; - Posf *p; - uInt wsize = s->w_size; - - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m - wsize : NIL); - } while (--n); - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m - wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif -} - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - s->status = INIT_STATE; /* to pass state test in deflateReset() */ - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = (uInt)windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = (uInt)memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= - * Check for a valid deflate stream state. Return 0 if ok, 1 if not. - */ -local int deflateStateCheck (strm) - z_streamp strm; -{ - deflate_state *s; - if (strm == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) - return 1; - s = strm->state; - if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && -#ifdef GZIP - s->status != GZIP_STATE && -#endif - s->status != EXTRA_STATE && - s->status != NAME_STATE && - s->status != COMMENT_STATE && - s->status != HCRC_STATE && - s->status != BUSY_STATE && - s->status != FINISH_STATE)) - return 1; - return 0; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt str, n; - int wrap; - unsigned avail; - z_const unsigned char *next; - - if (deflateStateCheck(strm) || dictionary == Z_NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = adler32(strm->adler, dictionary, dictLength); - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const Bytef *)dictionary; - fill_window(s); - while (s->lookahead >= MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); - do { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - } while (--n); - s->strstart = str; - s->lookahead = MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (long)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - strm->next_in = next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) - z_streamp strm; - Bytef *dictionary; - uInt *dictLength; -{ - deflate_state *s; - uInt len; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - len = s->strstart + s->lookahead; - if (len > s->w_size) - len = s->w_size; - if (dictionary != Z_NULL && len) - zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); - if (dictLength != Z_NULL) - *dictLength = len; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateResetKeep (strm) - z_streamp strm; -{ - deflate_state *s; - - if (deflateStateCheck(strm)) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = -#ifdef GZIP - s->wrap == 2 ? GZIP_STATE : -#endif - s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - int ret; - - ret = deflateResetKeep(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ - if (deflateStateCheck(strm) || strm->state->wrap != 2) - return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePending (strm, pending, bits) - unsigned *pending; - int *bits; - z_streamp strm; -{ - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - if (pending != Z_NULL) - *pending = strm->state->pending; - if (bits != Z_NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - deflate_state *s; - int put; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = Buf_size - s->bi_valid; - if (put > bits) - put = bits; - s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); - s->bi_valid += put; - _tr_flush_bits(s); - value >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if ((strategy != s->strategy || func != configuration_table[level].func) && - s->high_water) { - /* Flush the last buffer: */ - int err = deflate(strm, Z_BLOCK); - if (err == Z_STREAM_ERROR) - return err; - if (strm->avail_out == 0) - return Z_BUF_ERROR; - } - if (s->level != level) { - if (s->level == 0 && s->matches != 0) { - if (s->matches == 1) - slide_hash(s); - else - CLEAR_HASH(s); - s->matches = 0; - } - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ - deflate_state *s; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = (uInt)good_length; - s->max_lazy_match = (uInt)max_lazy; - s->nice_match = nice_length; - s->max_chain_length = (uInt)max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. - */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ - deflate_state *s; - uLong complen, wraplen; - - /* conservative upper bound for compressed data */ - complen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (deflateStateCheck(strm)) - return complen + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; -#ifdef GZIP - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ - Bytef *str; - if (s->gzhead->extra != Z_NULL) - wraplen += 2 + s->gzhead->extra_len; - str = s->gzhead->name; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - str = s->gzhead->comment; - if (str != Z_NULL) - do { - wraplen++; - } while (*str++); - if (s->gzhead->hcrc) - wraplen += 2; - } - break; -#endif - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return conservative bound */ - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return complen + wraplen; - - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + - (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output, except for - * some deflate_stored() output, goes through this function so some - * applications may wish to modify it to avoid allocating a large - * strm->next_out buffer and copying into it. (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len; - deflate_state *s = strm->state; - - _tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) { - s->pending_out = s->pending_buf; - } -} - -/* =========================================================================== - * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. - */ -#define HCRC_UPDATE(beg) \ - do { \ - if (s->gzhead->hcrc && s->pending > (beg)) \ - strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ - s->pending - (beg)); \ - } while (0) - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->avail_in != 0 && strm->next_in == Z_NULL) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - old_flush = s->last_flush; - s->last_flush = flush; - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Write the header */ - if (s->status == INIT_STATE) { - /* zlib header */ - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#ifdef GZIP - if (s->status == GZIP_STATE) { - /* gzip header */ - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; - while (s->pending + left > s->pending_buf_size) { - uInt copy = s->pending_buf_size - s->pending; - zmemcpy(s->pending_buf + s->pending, - s->gzhead->extra + s->gzindex, copy); - s->pending = s->pending_buf_size; - HCRC_UPDATE(beg); - s->gzindex += copy; - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - left -= copy; - } - zmemcpy(s->pending_buf + s->pending, - s->gzhead->extra + s->gzindex, left); - s->pending += left; - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - int val; - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - ulg beg = s->pending; /* start of bytes to update crc */ - int val; - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - } - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) { - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - } - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#endif - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = s->level == 0 ? deflate_stored(s, flush) : - s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0L; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (deflateStateCheck(strm)) return Z_STREAM_ERROR; - - status = strm->state->status; - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (deflateStateCheck(source) || dest == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local unsigned read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = (int)s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} -#endif /* ASMV */ - -#else /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for FASTEST only - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#endif /* FASTEST */ - -#ifdef ZLIB_DEBUG - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* ZLIB_DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - unsigned n; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - slide_hash(s); - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } - - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (last)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* Maximum stored block length in deflate format (not including header). */ -#define MAX_STORED 65535 - -/* Minimum of a and b. */ -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * - * In case deflateParams() is used to later switch to a non-zero compression - * level, s->matches (otherwise unused when storing) keeps track of the number - * of hash table slides to perform. If s->matches is 1, then one hash table - * slide will be done when switching. If s->matches is 2, the maximum value - * allowed here, then the hash table will be cleared, since two or more slides - * is the same as a clear. - * - * deflate_stored() is written to minimize the number of times an input byte is - * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Smallest worthy block size when not flushing or finishing. By default - * this is 32K. This can be as small as 507 bytes for memLevel == 1. For - * large input and output buffers, the stored block size will be larger. - */ - unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - - /* Copy as many min_block or larger stored blocks directly to next_out as - * possible. If flushing, copy the remaining available input to next_out as - * stored blocks, if there is enough space. - */ - unsigned len, left, have, last = 0; - unsigned used = s->strm->avail_in; - do { - /* Set len to the maximum size block that we can copy directly with the - * available input data and output space. Set left to how much of that - * would be copied from what's left in the window. - */ - len = MAX_STORED; /* maximum deflate stored block length */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - if (s->strm->avail_out < have) /* need room for header */ - break; - /* maximum stored block length that will fit in avail_out: */ - have = s->strm->avail_out - have; - left = s->strstart - s->block_start; /* bytes left in window */ - if (len > (ulg)left + s->strm->avail_in) - len = left + s->strm->avail_in; /* limit len to the input */ - if (len > have) - len = have; /* limit len to the output */ - - /* If the stored block would be less than min_block in length, or if - * unable to copy all of the available input when flushing, then try - * copying to the window and the pending buffer instead. Also don't - * write an empty block when flushing -- deflate() does that. - */ - if (len < min_block && ((len == 0 && flush != Z_FINISH) || - flush == Z_NO_FLUSH || - len != left + s->strm->avail_in)) - break; - - /* Make a dummy stored block in pending to get the header bytes, - * including any pending bits. This also updates the debugging counts. - */ - last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; - _tr_stored_block(s, (char *)0, 0L, last); - - /* Replace the lengths in the dummy stored block with len. */ - s->pending_buf[s->pending - 4] = len; - s->pending_buf[s->pending - 3] = len >> 8; - s->pending_buf[s->pending - 2] = ~len; - s->pending_buf[s->pending - 1] = ~len >> 8; - - /* Write the stored block header bytes. */ - flush_pending(s->strm); - -#ifdef ZLIB_DEBUG - /* Update debugging counts for the data about to be copied. */ - s->compressed_len += len << 3; - s->bits_sent += len << 3; -#endif - - /* Copy uncompressed bytes from the window to next_out. */ - if (left) { - if (left > len) - left = len; - zmemcpy(s->strm->next_out, s->window + s->block_start, left); - s->strm->next_out += left; - s->strm->avail_out -= left; - s->strm->total_out += left; - s->block_start += left; - len -= left; - } - - /* Copy uncompressed bytes directly from next_in to next_out, updating - * the check value. - */ - if (len) { - read_buf(s->strm, s->strm->next_out, len); - s->strm->next_out += len; - s->strm->avail_out -= len; - s->strm->total_out += len; - } - } while (last == 0); - - /* Update the sliding window with the last s->w_size bytes of the copied - * data, or append all of the copied data to the existing window if less - * than s->w_size bytes were copied. Also update the number of bytes to - * insert in the hash tables, in the event that deflateParams() switches to - * a non-zero compression level. - */ - used -= s->strm->avail_in; /* number of input bytes directly copied */ - if (used) { - /* If any input was used, then no unused input remains in the window, - * therefore s->block_start == s->strstart. - */ - if (used >= s->w_size) { /* supplant the previous history */ - s->matches = 2; /* clear hash */ - zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); - s->strstart = s->w_size; - } - else { - if (s->window_size - s->strstart <= used) { - /* Slide the window down. */ - s->strstart -= s->w_size; - zmemcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - } - zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); - s->strstart += used; - } - s->block_start = s->strstart; - s->insert += MIN(used, s->w_size - s->insert); - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* If the last block was written to next_out, then done. */ - if (last) - return finish_done; - - /* If flushing and all input has been consumed, then done. */ - if (flush != Z_NO_FLUSH && flush != Z_FINISH && - s->strm->avail_in == 0 && (long)s->strstart == s->block_start) - return block_done; - - /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart - 1; - if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { - /* Slide the window down. */ - s->block_start -= s->w_size; - s->strstart -= s->w_size; - zmemcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - have += s->w_size; /* more space now */ - } - if (have > s->strm->avail_in) - have = s->strm->avail_in; - if (have) { - read_buf(s->strm, s->window + s->strstart, have); - s->strstart += have; - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* There was not enough avail_out to write a complete worthy or flushed - * stored block to next_out. Write a stored block to pending instead, if we - * have enough input for a worthy block, or if flushing and there is enough - * room for the remaining input as a stored block in the pending buffer. - */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - /* maximum stored block length that will fit in pending: */ - have = MIN(s->pending_buf_size - have, MAX_STORED); - min_block = MIN(have, s->w_size); - left = s->strstart - s->block_start; - if (left >= min_block || - ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && - s->strm->avail_in == 0 && left <= have)) { - len = MIN(left, have); - last = flush == Z_FINISH && s->strm->avail_in == 0 && - len == left ? 1 : 0; - _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); - s->block_start += len; - flush_pending(s->strm); - } - - /* We've done all we can with the available input and output. */ - return last ? finish_started : need_more; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = NIL; - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s->match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} -#endif /* FASTEST */ - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - uInt prev; /* byte at distance one to match */ - Bytef *scan, *strend; /* scan goes up to strend for length of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s->match_length = 0; - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - s->match_length = MAX_MATCH - (uInt)(strend - scan); - if (s->match_length > s->lookahead) - s->match_length = s->lookahead; - } - Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, s->match_length); - - _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - s->strstart += s->match_length; - s->match_length = 0; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -local block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s->match_length = 0; - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->last_lit) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/src/contrib/zlib/deflate.h b/src/contrib/zlib/deflate.h deleted file mode 100644 index 23ecdd3..0000000 --- a/src/contrib/zlib/deflate.h +++ /dev/null @@ -1,349 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define Buf_size 16 -/* size of bit buffer in bi_buf */ - -#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ -#ifdef GZIP -# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ -#endif -#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ -#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ -#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ -#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ -#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ -#define FINISH_STATE 666 /* stream complete */ -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - const static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - ulg pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - ulg gzindex; /* where in extra, name, or comment */ - Byte method; /* can only be DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - uInt insert; /* bytes at end of window left to insert */ - -#ifdef ZLIB_DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - ulg high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef ZLIB_DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch ZLIB_INTERNAL _length_code[]; - extern uch ZLIB_INTERNAL _dist_code[]; -#else - extern const uch ZLIB_INTERNAL _length_code[]; - extern const uch ZLIB_INTERNAL _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (uch)(length); \ - ush dist = (ush)(distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/src/contrib/zlib/doc/algorithm.txt b/src/contrib/zlib/doc/algorithm.txt deleted file mode 100644 index c97f495..0000000 --- a/src/contrib/zlib/doc/algorithm.txt +++ /dev/null @@ -1,209 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by gzip (also zip and zlib) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for -a longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the process of lazy evaluation begins again. Otherwise, -the original match is kept, and the next match search is attempted only N -steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -2.1 Introduction - -The key question is how to represent a Huffman code (or any prefix code) so -that you can decode fast. The most important characteristic is that shorter -codes are much more common than longer codes, so pay attention to decoding the -short codes fast, and let the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and then -to set that variable for the maximum speed. - -For inflate, which has 286 possible codes for the literal/length tree, the size -of the first table is nine bits. Also the distance trees have 30 possible -values, and the size of the first table is six bits. Note that for each of -those cases, the table ended up one bit longer than the ``average'' code -length, i.e. the code length of an approximately flat code which would be a -little more than eight bits for 286 symbols and a little less than five bits -for 30 symbols. - - -2.2 More details on the inflate table lookup - -Ok, you want to know what this cleverly obfuscated inflate tree actually -looks like. You are correct that it's not a Huffman tree. It is simply a -lookup table for the first, let's say, nine bits of a Huffman symbol. The -symbol could be as short as one bit or as long as 15 bits. If a particular -symbol is shorter than nine bits, then that symbol's translation is duplicated -in all those entries that start with that symbol's bits. For example, if the -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a -symbol is nine bits long, it appears in the table once. - -If the symbol is longer than nine bits, then that entry in the table points -to another similar table for the remaining bits. Again, there are duplicated -entries as needed. The idea is that most of the time the symbol will be short -and there will only be one table look up. (That's whole idea behind data -compression in the first place.) For the less frequent long symbols, there -will be two lookups. If you had a compression method with really long -symbols, you could have as many levels of lookups as is efficient. For -inflate, two is enough. - -So a table entry either points to another table (in which case nine bits in -the above example are gobbled), or it contains the translation for the symbol -and the number of bits to gobble. Then you start again with the next -ungobbled bit. - -You may wonder: why not just have one lookup table for how ever many bits the -longest symbol is? The reason is that if you do that, you end up spending -more time filling in duplicate symbol entries than you do actually decoding. -At least for deflate's output that generates new trees every several 10's of -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code -would take too long if you're only decoding several thousand symbols. At the -other extreme, you could make a new table for every bit in the code. In fact, -that's essentially a Huffman tree. But then you spend too much time -traversing the tree while decoding, even for short symbols. - -So the number of bits for the first lookup table is a trade of the time to -fill out the table vs. the time spent looking at the second level and above of -the table. - -Here is an example, scaled down: - -The code being decoded, with 10 symbols, from 1 to 6 bits long: - -A: 0 -B: 10 -C: 1100 -D: 11010 -E: 11011 -F: 11100 -G: 11101 -H: 11110 -I: 111110 -J: 111111 - -Let's make the first table three bits long (eight entries): - -000: A,1 -001: A,1 -010: A,1 -011: A,1 -100: B,2 -101: B,2 -110: -> table X (gobble 3 bits) -111: -> table Y (gobble 3 bits) - -Each entry is what the bits decode as and how many bits that is, i.e. how -many bits to gobble. Or the entry points to another table, with the number of -bits to gobble implicit in the size of the table. - -Table X is two bits long since the longest code starting with 110 is five bits -long: - -00: C,1 -01: C,1 -10: D,2 -11: E,2 - -Table Y is three bits long since the longest code starting with 111 is six -bits long: - -000: F,2 -001: F,2 -010: G,2 -011: G,2 -100: H,2 -101: H,2 -110: I,3 -111: J,3 - -So what we have here are three tables with a total of 20 entries that had to -be constructed. That's compared to 64 entries for a single table. Or -compared to 16 entries for a Huffman tree (six two entry tables and one four -entry table). Assuming that the code ideally represents the probability of -the symbols, it takes on the average 1.25 lookups per symbol. That's compared -to one lookup for the single table, or 1.66 lookups per symbol for the -Huffman tree. - -There, I think that gives you a picture of what's going on. For inflate, the -meaning of a particular symbol is often more than just a letter. It can be a -byte (a "literal"), or it can be either a length or a distance which -indicates a base value and a number of bits to fetch after the code that is -added to the base value. Or it might be the special end-of-block code. The -data structures created in inftrees.c try to encode all that information -compactly in the tables. - - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -http://tools.ietf.org/html/rfc1951 diff --git a/src/contrib/zlib/doc/rfc1950.txt b/src/contrib/zlib/doc/rfc1950.txt deleted file mode 100644 index ce6428a..0000000 --- a/src/contrib/zlib/doc/rfc1950.txt +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1950 Aladdin Enterprises -Category: Informational J-L. Gailly - Info-ZIP - May 1996 - - - ZLIB Compressed Data Format Specification version 3.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format. The - data can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a priori - bounded amount of intermediate storage. The format presently uses - the DEFLATE compression method but can be easily extended to use - other compression methods. It can be implemented readily in a manner - not covered by patents. This specification also defines the ADLER-32 - checksum (an extension and improvement of the Fletcher checksum), - used for detection of data corruption, and provides an algorithm for - computing it. - - - - -Deutsch & Gailly Informational [Page 1] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 3 - 2.1. Overall conventions ....................................... 3 - 2.2. Data format ............................................... 4 - 2.3. Compliance ................................................ 7 - 3. References ..................................................... 7 - 4. Source code .................................................... 8 - 5. Security Considerations ........................................ 8 - 6. Acknowledgements ............................................... 8 - 7. Authors' Addresses ............................................. 8 - 8. Appendix: Rationale ............................................ 9 - 9. Appendix: Sample code ..........................................10 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence can - be used in data communications or similar structures such as - Unix filters; - - * Can use a number of different compression methods; - - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely. - - The data format defined by this specification does not attempt to - allow random access to compressed data. - - - - - - - -Deutsch & Gailly Informational [Page 2] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into zlib format and/or decompress data from zlib - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compressed data format that can be - used for in-memory compression of a sequence of arbitrary bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below, for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - Version 3.1 was the first public release of this specification. - In version 3.2, some terminology was changed and the Adler-32 - sample code was rewritten for clarity. In version 3.3, the - support for a preset dictionary was introduced, and the - specification was converted to RFC style. - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - - - -Deutsch & Gailly Informational [Page 3] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the MOST-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00000010|00001000| - +--------+--------+ - ^ ^ - | | - | + less significant byte = 8 - + more significant byte = 2 x 256 - - 2.2. Data format - - A zlib stream has the following structure: - - 0 1 - +---+---+ - |CMF|FLG| (more-->) - +---+---+ - - - - - - - - -Deutsch & Gailly Informational [Page 4] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - (if FLG.FDICT set) - - 0 1 2 3 - +---+---+---+---+ - | DICTID | (more-->) - +---+---+---+---+ - - +=====================+---+---+---+---+ - |...compressed data...| ADLER32 | - +=====================+---+---+---+---+ - - Any data which may appear after ADLER32 are not part of the zlib - stream. - - CMF (Compression Method and flags) - This byte is divided into a 4-bit compression method and a 4- - bit information field depending on the compression method. - - bits 0 to 3 CM Compression method - bits 4 to 7 CINFO Compression info - - CM (Compression method) - This identifies the compression method used in the file. CM = 8 - denotes the "deflate" compression method with a window size up - to 32K. This is the method used by gzip and PNG (see - references [1] and [2] in Chapter 3, below, for the reference - documents). CM = 15 is reserved. It might be used in a future - version of this specification to indicate the presence of an - extra field before the compressed data. - - CINFO (Compression info) - For CM = 8, CINFO is the base-2 logarithm of the LZ77 window - size, minus eight (CINFO=7 indicates a 32K window size). Values - of CINFO above 7 are not allowed in this version of the - specification. CINFO is not defined in this specification for - CM not equal to 8. - - FLG (FLaGs) - This flag byte is divided as follows: - - bits 0 to 4 FCHECK (check bits for CMF and FLG) - bit 5 FDICT (preset dictionary) - bits 6 to 7 FLEVEL (compression level) - - The FCHECK value must be such that CMF and FLG, when viewed as - a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), - is a multiple of 31. - - - - -Deutsch & Gailly Informational [Page 5] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - FDICT (Preset dictionary) - If FDICT is set, a DICT dictionary identifier is present - immediately after the FLG byte. The dictionary is a sequence of - bytes which are initially fed to the compressor without - producing any compressed output. DICT is the Adler-32 checksum - of this sequence of bytes (see the definition of ADLER32 - below). The decompressor can use this identifier to determine - which dictionary has been used by the compressor. - - FLEVEL (Compression level) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - 0 - compressor used fastest algorithm - 1 - compressor used fast algorithm - 2 - compressor used default algorithm - 3 - compressor used maximum compression, slowest algorithm - - The information in FLEVEL is not needed for decompression; it - is there to indicate if recompression might be worthwhile. - - compressed data - For compression method 8, the compressed data is stored in the - deflate compressed data format as described in the document - "DEFLATE Compressed Data Format Specification" by L. Peter - Deutsch. (See reference [3] in Chapter 3, below) - - Other compressed data formats are not specified in this version - of the zlib specification. - - ADLER32 (Adler-32 checksum) - This contains a checksum value of the uncompressed data - (excluding any dictionary data) computed according to Adler-32 - algorithm. This algorithm is a 32-bit extension and improvement - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - standard. See references [4] and [5] in Chapter 3, below) - - Adler-32 is composed of two sums accumulated per byte: s1 is - the sum of all bytes, s2 is the sum of all s1 values. Both sums - are done modulo 65521. s1 is initialized to 1, s2 to zero. The - Adler-32 checksum is stored as s2*65536 + s1 in most- - significant-byte first (network) order. - - - - - - - - -Deutsch & Gailly Informational [Page 6] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 2.3. Compliance - - A compliant compressor must produce streams with correct CMF, FLG - and ADLER32, but need not support preset dictionaries. When the - zlib data format is used as part of another standard data format, - the compressor may use only preset dictionaries that are specified - by this other data format. If this other format does not use the - preset dictionary feature, the compressor must not set the FDICT - flag. - - A compliant decompressor must check CMF, FLG, and ADLER32, and - provide an error indication if any of these have incorrect values. - A compliant decompressor must give an error indication if CM is - not one of the values defined in this specification (only the - value 8 is permitted in this version), since another value could - indicate the presence of new features that would cause subsequent - data to be interpreted incorrectly. A compliant decompressor must - give an error indication if FDICT is set and DICTID is not the - identifier of a known preset dictionary. A decompressor may - ignore FLEVEL and still be compliant. When the zlib data format - is being used as a part of another standard format, a compliant - decompressor must support all the preset dictionaries specified by - the other format. When the other format does not use the preset - dictionary feature, a compliant decompressor must reject any - stream in which the FDICT flag is set. - -3. References - - [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", - available in ftp://ftp.uu.net/graphics/png/documents/ - - [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Fletcher, J. G., "An Arithmetic Checksum for Serial - Transmissions," IEEE Transactions on Communications, Vol. COM-30, - No. 1, January 1982, pp. 247-252. - - [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," - November, 1993, pp. 144, 145. (Available from - gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. - - - - - - - -Deutsch & Gailly Informational [Page 7] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -4. Source code - - Source code for a C language implementation of a "zlib" compliant - library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -5. Security Considerations - - A decoder that fails to check the ADLER32 checksum value may be - subject to undetected data corruption. - -6. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly and Mark Adler designed the zlib format and wrote - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -7. Authors' Addresses - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - - Jean-Loup Gailly - - EMail: - - Questions about the technical content of this specification can be - sent by email to - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - -Deutsch & Gailly Informational [Page 8] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -8. Appendix: Rationale - - 8.1. Preset dictionaries - - A preset dictionary is specially useful to compress short input - sequences. The compressor can take advantage of the dictionary - context to encode the input in a more compact manner. The - decompressor can be initialized with the appropriate context by - virtually decompressing a compressed version of the dictionary - without producing any output. However for certain compression - algorithms such as the deflate algorithm this operation can be - achieved without actually performing any decompression. - - The compressor and the decompressor must use exactly the same - dictionary. The dictionary may be fixed or may be chosen among a - certain number of predefined dictionaries, according to the kind - of input data. The decompressor can determine which dictionary has - been chosen by the compressor by checking the dictionary - identifier. This document does not specify the contents of - predefined dictionaries, since the optimal dictionaries are - application specific. Standard data formats using this feature of - the zlib specification must precisely define the allowed - dictionaries. - - 8.2. The Adler-32 algorithm - - The Adler-32 algorithm is much faster than the CRC32 algorithm yet - still provides an extremely low probability of undetected errors. - - The modulo on unsigned long accumulators can be delayed for 5552 - bytes, so the modulo operation time is negligible. If the bytes - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - and order sensitive, unlike the first sum, which is just a - checksum. That 65521 is prime is important to avoid a possible - large class of two-byte errors that leave the check unchanged. - (The Fletcher checksum uses 255, which is not prime and which also - makes the Fletcher check insensitive to single byte changes 0 <-> - 255.) - - The sum s1 is initialized to 1 instead of zero to make the length - of the sequence part of s2, so that the length does not have to be - checked separately. (Any sequence of zeroes has a Fletcher - checksum of zero.) - - - - - - - - -Deutsch & Gailly Informational [Page 9] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -9. Appendix: Sample code - - The following C code computes the Adler-32 checksum of a data buffer. - It is written for clarity, not for speed. The sample code is in the - ANSI C programming language. Non C users may find it easier to read - with these hints: - - & Bitwise AND operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero bit(s) - at the left. - << Bitwise left shift operator. Left shift inserts zero - bit(s) at the right. - ++ "n++" increments the variable n. - % modulo operator: a % b is the remainder of a divided by b. - - #define BASE 65521 /* largest prime smaller than 65536 */ - - /* - Update a running Adler-32 checksum with the bytes buf[0..len-1] - and return the updated checksum. The Adler-32 checksum should be - initialized to 1. - - Usage example: - - unsigned long adler = 1L; - - while (read_buffer(buffer, length) != EOF) { - adler = update_adler32(adler, buffer, length); - } - if (adler != original_adler) error(); - */ - unsigned long update_adler32(unsigned long adler, - unsigned char *buf, int len) - { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int n; - - for (n = 0; n < len; n++) { - s1 = (s1 + buf[n]) % BASE; - s2 = (s2 + s1) % BASE; - } - return (s2 << 16) + s1; - } - - /* Return the adler32 of the bytes buf[0..len-1] */ - - - - -Deutsch & Gailly Informational [Page 10] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - unsigned long adler32(unsigned char *buf, int len) - { - return update_adler32(1L, buf, len); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch & Gailly Informational [Page 11] - diff --git a/src/contrib/zlib/doc/rfc1951.txt b/src/contrib/zlib/doc/rfc1951.txt deleted file mode 100644 index 403c8c7..0000000 --- a/src/contrib/zlib/doc/rfc1951.txt +++ /dev/null @@ -1,955 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1951 Aladdin Enterprises -Category: Informational May 1996 - - - DEFLATE Compressed Data Format Specification version 1.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that - compresses data using a combination of the LZ77 algorithm and Huffman - coding, with efficiency comparable to the best currently available - general-purpose compression methods. The data can be produced or - consumed, even for an arbitrarily long sequentially presented input - data stream, using only an a priori bounded amount of intermediate - storage. The format can be implemented readily in a manner not - covered by patents. - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 4 - 2. Compressed representation overview ............................. 4 - 3. Detailed specification ......................................... 5 - 3.1. Overall conventions ....................................... 5 - 3.1.1. Packing into bytes .................................. 5 - 3.2. Compressed block format ................................... 6 - 3.2.1. Synopsis of prefix and Huffman coding ............... 6 - 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 - 3.2.3. Details of block format ............................. 9 - 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 - 3.2.5. Compressed blocks (length and distance codes) ...... 11 - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 - 3.3. Compliance ............................................... 14 - 4. Compression algorithm details ................................. 14 - 5. References .................................................... 16 - 6. Security Considerations ....................................... 16 - 7. Source code ................................................... 16 - 8. Acknowledgements .............................................. 16 - 9. Author's Address .............................................. 17 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence - can be used in data communications or similar structures - such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - - - -Deutsch Informational [Page 2] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - The data format defined by this specification does not attempt to: - - * Allow random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well - as the best currently available specialized algorithms. - - A simple counting argument shows that no lossless compression - algorithm can compress every possible input data set. For the - format defined here, the worst case expansion is 5 bytes per 32K- - byte block, i.e., a size increase of 0.015% for large data sets. - English text usually compresses by a factor of 2.5 to 3; - executable files usually compress somewhat less; graphical data - such as raster images may compress much more. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into "deflate" format and/or decompress data from - "deflate" format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. Familiarity with the technique of Huffman coding - is helpful but not required. - - 1.3. Scope - - The specification specifies a method for representing a sequence - of bytes as a (usually shorter) sequence of bits, and a method for - packing the latter bit sequence into bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - Byte: 8 bits stored or transmitted as a unit (same as an octet). - For this specification, a byte is exactly 8 bits, even on machines - - - -Deutsch Informational [Page 3] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - which store a character on a number of bits different from eight. - See below, for the numbering of bits within a byte. - - String: a sequence of arbitrary bytes. - - 1.6. Changes from previous versions - - There have been no technical changes to the deflate format since - version 1.1 of this specification. In version 1.2, some - terminology was changed. Version 1.3 is a conversion of the - specification to RFC style. - -2. Compressed representation overview - - A compressed data set consists of a series of blocks, corresponding - to successive blocks of input data. The block sizes are arbitrary, - except that non-compressible blocks are limited to 65,535 bytes. - - Each block is compressed using a combination of the LZ77 algorithm - and Huffman coding. The Huffman trees for each block are independent - of those for previous or subsequent blocks; the LZ77 algorithm may - use a reference to a duplicated string occurring in a previous block, - up to 32K input bytes before. - - Each block consists of two parts: a pair of Huffman code trees that - describe the representation of the compressed data part, and a - compressed data part. (The Huffman trees themselves are compressed - using Huffman encoding.) The compressed data consists of a series of - elements of two types: literal bytes (of strings that have not been - detected as duplicated within the previous 32K input bytes), and - pointers to duplicated strings, where a pointer is represented as a - pair . The representation used in the - "deflate" format limits distances to 32K bytes and lengths to 258 - bytes, but does not limit the size of a block, except for - uncompressible blocks, which are limited as noted above. - - Each type of value (literals, distances, and lengths) in the - compressed data is represented using a Huffman code, using one code - tree for literals and lengths and a separate code tree for distances. - The code trees for each block appear in a compact form just before - the compressed data for that block. - - - - - - - - - - -Deutsch Informational [Page 4] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -3. Detailed specification - - 3.1. Overall conventions In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - 3.1.1. Packing into bytes - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, - since the final data format described here is byte- rather than - - - -Deutsch Informational [Page 5] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - bit-oriented. However, we describe the compressed block format - in below, as a sequence of data elements of various bit - lengths, not a sequence of bytes. We must therefore specify - how to pack these data elements into bytes to form the final - compressed byte sequence: - - * Data elements are packed into bytes in order of - increasing bit number within the byte, i.e., starting - with the least-significant bit of the byte. - * Data elements other than Huffman codes are packed - starting with the least-significant bit of the data - element. - * Huffman codes are packed starting with the most- - significant bit of the code. - - In other words, if one were to print out the compressed data as - a sequence of bytes, starting with the first byte at the - *right* margin and proceeding to the *left*, with the most- - significant bit of each byte on the left as usual, one would be - able to parse the result from right to left, with fixed-width - elements in the correct MSB-to-LSB order and Huffman codes in - bit-reversed order (i.e., with the first bit of the code in the - relative LSB position). - - 3.2. Compressed block format - - 3.2.1. Synopsis of prefix and Huffman coding - - Prefix coding represents symbols from an a priori known - alphabet by bit sequences (codes), one code for each symbol, in - a manner such that different symbols may be represented by bit - sequences of different lengths, but a parser can always parse - an encoded string unambiguously symbol-by-symbol. - - We define a prefix code in terms of a binary tree in which the - two edges descending from each non-leaf node are labeled 0 and - 1 and in which the leaf nodes correspond one-for-one with (are - labeled with) the symbols of the alphabet; then the code for a - symbol is the sequence of 0's and 1's on the edges leading from - the root to the leaf labeled with that symbol. For example: - - - - - - - - - - - -Deutsch Informational [Page 6] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - /\ Symbol Code - 0 1 ------ ---- - / \ A 00 - /\ B B 1 - 0 1 C 011 - / \ D 010 - A /\ - 0 1 - / \ - D C - - A parser can decode the next symbol from an encoded input - stream by walking down the tree from the root, at each step - choosing the edge corresponding to the next input bit. - - Given an alphabet with known symbol frequencies, the Huffman - algorithm allows the construction of an optimal prefix code - (one which represents strings with those symbol frequencies - using the fewest bits of any possible prefix codes for that - alphabet). Such a code is called a Huffman code. (See - reference [1] in Chapter 5, references for additional - information on Huffman codes.) - - Note that in the "deflate" format, the Huffman codes for the - various alphabets must not exceed certain maximum code lengths. - This constraint complicates the algorithm for computing code - lengths from symbol frequencies. Again, see Chapter 5, - references for details. - - 3.2.2. Use of Huffman coding in the "deflate" format - - The Huffman codes used for each alphabet in the "deflate" - format have two additional rules: - - * All codes of a given bit length have lexicographically - consecutive values, in the same order as the symbols - they represent; - - * Shorter codes lexicographically precede longer codes. - - - - - - - - - - - - -Deutsch Informational [Page 7] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - We could recode the example above to follow this rule as - follows, assuming that the order of the alphabet is ABCD: - - Symbol Code - ------ ---- - A 10 - B 0 - C 110 - D 111 - - I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are - lexicographically consecutive. - - Given this rule, we can define the Huffman code for an alphabet - just by giving the bit lengths of the codes for each symbol of - the alphabet in order; this is sufficient to determine the - actual codes. In our example, the code is completely defined - by the sequence of bit lengths (2, 1, 3, 3). The following - algorithm generates the codes as integers, intended to be read - from most- to least-significant bit. The code lengths are - initially in tree[I].Len; the codes are produced in - tree[I].Code. - - 1) Count the number of codes for each code length. Let - bl_count[N] be the number of codes of length N, N >= 1. - - 2) Find the numerical value of the smallest code for each - code length: - - code = 0; - bl_count[0] = 0; - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = code; - } - - 3) Assign numerical values to all codes, using consecutive - values for all codes of the same length with the base - values determined at step 2. Codes that are never used - (which have a bit length of zero) must not be assigned a - value. - - for (n = 0; n <= max_code; n++) { - len = tree[n].Len; - if (len != 0) { - tree[n].Code = next_code[len]; - next_code[len]++; - } - - - -Deutsch Informational [Page 8] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - } - - Example: - - Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, - 3, 2, 4, 4). After step 1, we have: - - N bl_count[N] - - ----------- - 2 1 - 3 5 - 4 2 - - Step 2 computes the following next_code values: - - N next_code[N] - - ------------ - 1 0 - 2 0 - 3 2 - 4 14 - - Step 3 produces the following code values: - - Symbol Length Code - ------ ------ ---- - A 3 010 - B 3 011 - C 3 100 - D 3 101 - E 3 110 - F 2 00 - G 4 1110 - H 4 1111 - - 3.2.3. Details of block format - - Each block of compressed data begins with 3 header bits - containing the following data: - - first bit BFINAL - next 2 bits BTYPE - - Note that the header bits do not necessarily begin on a byte - boundary, since a block does not necessarily occupy an integral - number of bytes. - - - - - -Deutsch Informational [Page 9] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - BFINAL is set if and only if this is the last block of the data - set. - - BTYPE specifies how the data are compressed, as follows: - - 00 - no compression - 01 - compressed with fixed Huffman codes - 10 - compressed with dynamic Huffman codes - 11 - reserved (error) - - The only difference between the two compressed cases is how the - Huffman codes for the literal/length and distance alphabets are - defined. - - In all cases, the decoding algorithm for the actual data is as - follows: - - do - read block header from input stream. - if stored with no compression - skip any remaining bits in current partially - processed byte - read LEN and NLEN (see next section) - copy LEN bytes of data to output - otherwise - if compressed with dynamic Huffman codes - read representation of code trees (see - subsection below) - loop (until end of block code recognized) - decode literal/length value from input stream - if value < 256 - copy value (literal byte) to output stream - otherwise - if value = end of block (256) - break from loop - otherwise (value = 257..285) - decode distance from input stream - - move backwards distance bytes in the output - stream, and copy length bytes from this - position to the output stream. - end loop - while not last block - - Note that a duplicated string reference may refer to a string - in a previous block; i.e., the backward distance may cross one - or more block boundaries. However a distance cannot refer past - the beginning of the output stream. (An application using a - - - -Deutsch Informational [Page 10] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - preset dictionary might discard part of the output stream; a - distance can refer to that part of the output stream anyway) - Note also that the referenced string may overlap the current - position; for example, if the last 2 bytes decoded have values - X and Y, a string reference with - adds X,Y,X,Y,X to the output stream. - - We now specify each compression method in turn. - - 3.2.4. Non-compressed blocks (BTYPE=00) - - Any bits of input up to the next byte boundary are ignored. - The rest of the block consists of the following information: - - 0 1 2 3 4... - +---+---+---+---+================================+ - | LEN | NLEN |... LEN bytes of literal data...| - +---+---+---+---+================================+ - - LEN is the number of data bytes in the block. NLEN is the - one's complement of LEN. - - 3.2.5. Compressed blocks (length and distance codes) - - As noted above, encoded data blocks in the "deflate" format - consist of sequences of symbols drawn from three conceptually - distinct alphabets: either literal bytes, from the alphabet of - byte values (0..255), or pairs, - where the length is drawn from (3..258) and the distance is - drawn from (1..32,768). In fact, the literal and length - alphabets are merged into a single alphabet (0..285), where - values 0..255 represent literal bytes, the value 256 indicates - end-of-block, and values 257..285 represent length codes - (possibly in conjunction with extra bits following the symbol - code) as follows: - - - - - - - - - - - - - - - - -Deutsch Informational [Page 11] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - Extra Extra Extra - Code Bits Length(s) Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- - 257 0 3 267 1 15,16 277 4 67-82 - 258 0 4 268 1 17,18 278 4 83-98 - 259 0 5 269 2 19-22 279 4 99-114 - 260 0 6 270 2 23-26 280 4 115-130 - 261 0 7 271 2 27-30 281 5 131-162 - 262 0 8 272 2 31-34 282 5 163-194 - 263 0 9 273 3 35-42 283 5 195-226 - 264 0 10 274 3 43-50 284 5 227-257 - 265 1 11,12 275 3 51-58 285 0 258 - 266 1 13,14 276 3 59-66 - - The extra bits should be interpreted as a machine integer - stored with the most-significant bit first, e.g., bits 1110 - represent the value 14. - - Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- - 0 0 1 10 4 33-48 20 9 1025-1536 - 1 0 2 11 4 49-64 21 9 1537-2048 - 2 0 3 12 5 65-96 22 10 2049-3072 - 3 0 4 13 5 97-128 23 10 3073-4096 - 4 1 5,6 14 6 129-192 24 11 4097-6144 - 5 1 7,8 15 6 193-256 25 11 6145-8192 - 6 2 9-12 16 7 257-384 26 12 8193-12288 - 7 2 13-16 17 7 385-512 27 12 12289-16384 - 8 3 17-24 18 8 513-768 28 13 16385-24576 - 9 3 25-32 19 8 769-1024 29 13 24577-32768 - - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) - - The Huffman codes for the two alphabets are fixed, and are not - represented explicitly in the data. The Huffman code lengths - for the literal/length alphabet are: - - Lit Value Bits Codes - --------- ---- ----- - 0 - 143 8 00110000 through - 10111111 - 144 - 255 9 110010000 through - 111111111 - 256 - 279 7 0000000 through - 0010111 - 280 - 287 8 11000000 through - 11000111 - - - -Deutsch Informational [Page 12] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - The code lengths are sufficient to generate the actual codes, - as described above; we show the codes in the table for added - clarity. Literal/length values 286-287 will never actually - occur in the compressed data, but participate in the code - construction. - - Distance codes 0-31 are represented by (fixed-length) 5-bit - codes, with possible additional bits as shown in the table - shown in Paragraph 3.2.5, above. Note that distance codes 30- - 31 will never actually occur in the compressed data. - - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) - - The Huffman codes for the two alphabets appear in the block - immediately after the header bits and before the actual - compressed data, first the literal/length code and then the - distance code. Each code is defined by a sequence of code - lengths, as discussed in Paragraph 3.2.2, above. For even - greater compactness, the code length sequences themselves are - compressed using a Huffman code. The alphabet for code lengths - is as follows: - - 0 - 15: Represent code lengths of 0 - 15 - 16: Copy the previous code length 3 - 6 times. - The next 2 bits indicate repeat length - (0 = 3, ... , 3 = 6) - Example: Codes 8, 16 (+2 bits 11), - 16 (+2 bits 10) will expand to - 12 code lengths of 8 (1 + 6 + 5) - 17: Repeat a code length of 0 for 3 - 10 times. - (3 bits of length) - 18: Repeat a code length of 0 for 11 - 138 times - (7 bits of length) - - A code length of 0 indicates that the corresponding symbol in - the literal/length or distance alphabet will not occur in the - block, and should not participate in the Huffman code - construction algorithm given earlier. If only one distance - code is used, it is encoded using one bit, not zero bits; in - this case there is a single code length of one, with one unused - code. One distance code of zero bits means that there are no - distance codes used at all (the data is all literals). - - We can now define the format of the block: - - 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) - 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) - 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) - - - -Deutsch Informational [Page 13] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - (HCLEN + 4) x 3 bits: code lengths for the code length - alphabet given just above, in the order: 16, 17, 18, - 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - - These code lengths are interpreted as 3-bit integers - (0-7); as above, a code length of 0 means the - corresponding symbol (literal/length or distance code - length) is not used. - - HLIT + 257 code lengths for the literal/length alphabet, - encoded using the code length Huffman code - - HDIST + 1 code lengths for the distance alphabet, - encoded using the code length Huffman code - - The actual compressed data of the block, - encoded using the literal/length and distance Huffman - codes - - The literal/length symbol 256 (end of data), - encoded using the literal/length Huffman code - - The code length repeat codes can cross from HLIT + 257 to the - HDIST + 1 code lengths. In other words, all code lengths form - a single sequence of HLIT + HDIST + 258 values. - - 3.3. Compliance - - A compressor may limit further the ranges of values specified in - the previous section and still be compliant; for example, it may - limit the range of backward pointers to some value smaller than - 32K. Similarly, a compressor may limit the size of blocks so that - a compressible block fits in memory. - - A compliant decompressor must accept the full range of possible - values defined in the previous section, and must accept blocks of - arbitrary size. - -4. Compression algorithm details - - While it is the intent of this document to define the "deflate" - compressed data format without reference to any particular - compression algorithm, the format is related to the compressed - formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); - since many variations of LZ77 are patented, it is strongly - recommended that the implementor of a compressor follow the general - algorithm presented here, which is known not to be patented per se. - The material in this section is not part of the definition of the - - - -Deutsch Informational [Page 14] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - specification per se, and a compressor need not follow it in order to - be compliant. - - The compressor terminates a block when it determines that starting a - new block with fresh trees would be useful, or when the block size - fills up the compressor's block buffer. - - The compressor uses a chained hash table to find duplicated strings, - using a hash function that operates on 3-byte sequences. At any - given point during compression, let XYZ be the next 3 input bytes to - be examined (not necessarily all different, of course). First, the - compressor examines the hash chain for XYZ. If the chain is empty, - the compressor simply writes out X as a literal byte and advances one - byte in the input. If the hash chain is not empty, indicating that - the sequence XYZ (or, if we are unlucky, some other 3 bytes with the - same hash function value) has occurred recently, the compressor - compares all strings on the XYZ hash chain with the actual input data - sequence starting at the current point, and selects the longest - match. - - The compressor searches the hash chains starting with the most recent - strings, to favor small distances and thus take advantage of the - Huffman encoding. The hash chains are singly linked. There are no - deletions from the hash chains; the algorithm simply discards matches - that are too old. To avoid a worst-case situation, very long hash - chains are arbitrarily truncated at a certain length, determined by a - run-time parameter. - - To improve overall compression, the compressor optionally defers the - selection of matches ("lazy matching"): after a match of length N has - been found, the compressor searches for a longer match starting at - the next input byte. If it finds a longer match, it truncates the - previous match to a length of one (thus producing a single literal - byte) and then emits the longer match. Otherwise, it emits the - original match, and, as described above, advances N bytes before - continuing. - - Run-time parameters also control this "lazy match" procedure. If - compression ratio is most important, the compressor attempts a - complete second search regardless of the length of the first match. - In the normal case, if the current match is "long enough", the - compressor reduces the search for a longer match, thus speeding up - the process. If speed is most important, the compressor inserts new - strings in the hash table only when no match was found, or when the - match is not "too long". This degrades the compression ratio but - saves time since there are both fewer insertions and fewer searches. - - - - - -Deutsch Informational [Page 15] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -5. References - - [1] Huffman, D. A., "A Method for the Construction of Minimum - Redundancy Codes", Proceedings of the Institute of Radio - Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. - - [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data - Compression", IEEE Transactions on Information Theory, Vol. 23, - No. 3, pp. 337-343. - - [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, - available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ - - [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix - encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. - - [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," - Comm. ACM, 33,4, April 1990, pp. 449-459. - -6. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data. See - reference [3], for example. - -7. Source code - - Source code for a C language implementation of a "deflate" compliant - compressor and decompressor is available within the zlib package at - ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -8. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Phil Katz designed the deflate format. Jean-Loup Gailly and Mark - Adler wrote the related software described in this specification. - Glenn Randers-Pehrson converted this document to RFC and HTML format. - - - -Deutsch Informational [Page 16] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -9. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch Informational [Page 17] - diff --git a/src/contrib/zlib/doc/rfc1952.txt b/src/contrib/zlib/doc/rfc1952.txt deleted file mode 100644 index a8e51b4..0000000 --- a/src/contrib/zlib/doc/rfc1952.txt +++ /dev/null @@ -1,675 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1952 Aladdin Enterprises -Category: Informational May 1996 - - - GZIP file format specification version 4.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that is - compatible with the widely used GZIP utility. The format includes a - cyclic redundancy check value for detecting data corruption. The - format presently uses the DEFLATE method of compression but can be - easily extended to use other compression methods. The format can be - implemented readily in a manner not covered by patents. - - - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1952 GZIP File Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................. 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 4 - 2.1. Overall conventions ....................................... 4 - 2.2. File format ............................................... 5 - 2.3. Member format ............................................. 5 - 2.3.1. Member header and trailer ........................... 6 - 2.3.1.1. Extra field ................................... 8 - 2.3.1.2. Compliance .................................... 9 - 3. References .................................................. 9 - 4. Security Considerations .................................... 10 - 5. Acknowledgements ........................................... 10 - 6. Author's Address ........................................... 10 - 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 - 8. Appendix: Sample CRC Code .................................. 11 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can compress or decompress a data stream (as opposed to a - randomly accessible file) to produce another data stream, - using only an a priori bounded amount of intermediate - storage, and hence can be used in data communications or - similar structures such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - - - -Deutsch Informational [Page 2] - -RFC 1952 GZIP File Format Specification May 1996 - - - The data format defined by this specification does not attempt to: - - * Provide random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well as - the best currently available specialized algorithms. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into gzip format and/or decompress data from gzip - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compression method and a file format - (the latter assuming only that a file can store a sequence of - arbitrary bytes). It does not specify any particular interface to - a file system or anything about character sets or encodings - (except for file names and comments, which are optional). - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any file that conforms to all the - specifications presented here; a compliant compressor must produce - files that conform to all the specifications presented here. The - material in the appendices is not part of the specification per se - and is not relevant to compliance. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - There have been no technical changes to the gzip format since - version 4.1 of this specification. In version 4.2, some - terminology was changed, and the sample CRC code was rewritten for - clarity and to eliminate the requirement for the caller to do pre- - and post-conditioning. Version 4.3 is a conversion of the - specification to RFC style. - - - -Deutsch Informational [Page 3] - -RFC 1952 GZIP File Format Specification May 1996 - - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, since - the data format described here is byte- rather than bit-oriented. - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - - -Deutsch Informational [Page 4] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.2. File format - - A gzip file consists of a series of "members" (compressed data - sets). The format of each member is specified in the following - section. The members simply appear one after another in the file, - with no additional information before, between, or after them. - - 2.3. Member format - - Each member has the following structure: - - +---+---+---+---+---+---+---+---+---+---+ - |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) - +---+---+---+---+---+---+---+---+---+---+ - - (if FLG.FEXTRA set) - - +---+---+=================================+ - | XLEN |...XLEN bytes of "extra field"...| (more-->) - +---+---+=================================+ - - (if FLG.FNAME set) - - +=========================================+ - |...original file name, zero-terminated...| (more-->) - +=========================================+ - - (if FLG.FCOMMENT set) - - +===================================+ - |...file comment, zero-terminated...| (more-->) - +===================================+ - - (if FLG.FHCRC set) - - +---+---+ - | CRC16 | - +---+---+ - - +=======================+ - |...compressed blocks...| (more-->) - +=======================+ - - 0 1 2 3 4 5 6 7 - +---+---+---+---+---+---+---+---+ - | CRC32 | ISIZE | - +---+---+---+---+---+---+---+---+ - - - - -Deutsch Informational [Page 5] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.3.1. Member header and trailer - - ID1 (IDentification 1) - ID2 (IDentification 2) - These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 - (0x8b, \213), to identify the file as being in gzip format. - - CM (Compression Method) - This identifies the compression method used in the file. CM - = 0-7 are reserved. CM = 8 denotes the "deflate" - compression method, which is the one customarily used by - gzip and which is documented elsewhere. - - FLG (FLaGs) - This flag byte is divided into individual bits as follows: - - bit 0 FTEXT - bit 1 FHCRC - bit 2 FEXTRA - bit 3 FNAME - bit 4 FCOMMENT - bit 5 reserved - bit 6 reserved - bit 7 reserved - - If FTEXT is set, the file is probably ASCII text. This is - an optional indication, which the compressor may set by - checking a small amount of the input data to see whether any - non-ASCII characters are present. In case of doubt, FTEXT - is cleared, indicating binary data. For systems which have - different file formats for ascii text and binary data, the - decompressor can use FTEXT to choose the appropriate format. - We deliberately do not specify the algorithm used to set - this bit, since a compressor always has the option of - leaving it cleared and a decompressor always has the option - of ignoring it and letting some other program handle issues - of data conversion. - - If FHCRC is set, a CRC16 for the gzip header is present, - immediately before the compressed data. The CRC16 consists - of the two least significant bytes of the CRC32 for all - bytes of the gzip header up to and not including the CRC16. - [The FHCRC bit was never set by versions of gzip up to - 1.2.4, even though it was documented with a different - meaning in gzip 1.2.4.] - - If FEXTRA is set, optional extra fields are present, as - described in a following section. - - - -Deutsch Informational [Page 6] - -RFC 1952 GZIP File Format Specification May 1996 - - - If FNAME is set, an original file name is present, - terminated by a zero byte. The name must consist of ISO - 8859-1 (LATIN-1) characters; on operating systems using - EBCDIC or any other character set for file names, the name - must be translated to the ISO LATIN-1 character set. This - is the original name of the file being compressed, with any - directory components removed, and, if the file being - compressed is on a file system with case insensitive names, - forced to lower case. There is no original file name if the - data was compressed from a source other than a named file; - for example, if the source was stdin on a Unix system, there - is no file name. - - If FCOMMENT is set, a zero-terminated file comment is - present. This comment is not interpreted; it is only - intended for human consumption. The comment must consist of - ISO 8859-1 (LATIN-1) characters. Line breaks should be - denoted by a single line feed character (10 decimal). - - Reserved FLG bits must be zero. - - MTIME (Modification TIME) - This gives the most recent modification time of the original - file being compressed. The time is in Unix format, i.e., - seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this - may cause problems for MS-DOS and other systems that use - local rather than Universal time.) If the compressed data - did not come from a file, MTIME is set to the time at which - compression started. MTIME = 0 means no time stamp is - available. - - XFL (eXtra FLags) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - XFL = 2 - compressor used maximum compression, - slowest algorithm - XFL = 4 - compressor used fastest algorithm - - OS (Operating System) - This identifies the type of file system on which compression - took place. This may be useful in determining end-of-line - convention for text files. The currently defined values are - as follows: - - - - - - -Deutsch Informational [Page 7] - -RFC 1952 GZIP File Format Specification May 1996 - - - 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) - 1 - Amiga - 2 - VMS (or OpenVMS) - 3 - Unix - 4 - VM/CMS - 5 - Atari TOS - 6 - HPFS filesystem (OS/2, NT) - 7 - Macintosh - 8 - Z-System - 9 - CP/M - 10 - TOPS-20 - 11 - NTFS filesystem (NT) - 12 - QDOS - 13 - Acorn RISCOS - 255 - unknown - - XLEN (eXtra LENgth) - If FLG.FEXTRA is set, this gives the length of the optional - extra field. See below for details. - - CRC32 (CRC-32) - This contains a Cyclic Redundancy Check value of the - uncompressed data computed according to CRC-32 algorithm - used in the ISO 3309 standard and in section 8.1.1.6.2 of - ITU-T recommendation V.42. (See http://www.iso.ch for - ordering ISO documents. See gopher://info.itu.ch for an - online version of ITU-T V.42.) - - ISIZE (Input SIZE) - This contains the size of the original (uncompressed) input - data modulo 2^32. - - 2.3.1.1. Extra field - - If the FLG.FEXTRA bit is set, an "extra field" is present in - the header, with total length XLEN bytes. It consists of a - series of subfields, each of the form: - - +---+---+---+---+==================================+ - |SI1|SI2| LEN |... LEN bytes of subfield data ...| - +---+---+---+---+==================================+ - - SI1 and SI2 provide a subfield ID, typically two ASCII letters - with some mnemonic value. Jean-Loup Gailly - is maintaining a registry of subfield - IDs; please send him any subfield ID you wish to use. Subfield - IDs with SI2 = 0 are reserved for future use. The following - IDs are currently defined: - - - -Deutsch Informational [Page 8] - -RFC 1952 GZIP File Format Specification May 1996 - - - SI1 SI2 Data - ---------- ---------- ---- - 0x41 ('A') 0x70 ('P') Apollo file type information - - LEN gives the length of the subfield data, excluding the 4 - initial bytes. - - 2.3.1.2. Compliance - - A compliant compressor must produce files with correct ID1, - ID2, CM, CRC32, and ISIZE, but may set all the other fields in - the fixed-length part of the header to default values (255 for - OS, 0 for all others). The compressor must set all reserved - bits to zero. - - A compliant decompressor must check ID1, ID2, and CM, and - provide an error indication if any of these have incorrect - values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC - at least so it can skip over the optional fields if they are - present. It need not examine any other part of the header or - trailer; in particular, a decompressor may ignore FTEXT and OS - and always produce binary output, and still be compliant. A - compliant decompressor must give an error indication if any - reserved bit is non-zero, since such a bit could indicate the - presence of a new field that would cause subsequent data to be - interpreted incorrectly. - -3. References - - [1] "Information Processing - 8-bit single-byte coded graphic - character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). - The ISO 8859-1 (Latin-1) character set is a superset of 7-bit - ASCII. Files defining this character set are available as - iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ - - [2] ISO 3309 - - [3] ITU-T recommendation V.42 - - [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in - ftp://prep.ai.mit.edu/pub/gnu/ - - [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table - Look-Up", Communications of the ACM, 31(8), pp.1008-1013. - - - - -Deutsch Informational [Page 9] - -RFC 1952 GZIP File Format Specification May 1996 - - - [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, - pp.118-133. - - [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, - describing the CRC concept. - -4. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data, such as by - setting and checking the CRC-32 check value. - -5. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -6. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - -Deutsch Informational [Page 10] - -RFC 1952 GZIP File Format Specification May 1996 - - -7. Appendix: Jean-Loup Gailly's gzip utility - - The most widely used implementation of gzip compression, and the - original documentation on which this specification is based, were - created by Jean-Loup Gailly . Since this - implementation is a de facto standard, we mention some more of its - features here. Again, the material in this section is not part of - the specification per se, and implementations need not follow it to - be compliant. - - When compressing or decompressing a file, gzip preserves the - protection, ownership, and modification time attributes on the local - file system, since there is no provision for representing protection - attributes in the gzip file format itself. Since the file format - includes a modification time, the gzip decompressor provides a - command line switch that assigns the modification time from the file, - rather than the local modification time of the compressed input, to - the decompressed output. - -8. Appendix: Sample CRC Code - - The following sample code represents a practical implementation of - the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 - for a formal specification.) - - The sample code is in the ANSI C programming language. Non C users - may find it easier to read with these hints: - - & Bitwise AND operator. - ^ Bitwise exclusive-OR operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero - bit(s) at the left. - ! Logical NOT operator. - ++ "n++" increments the variable n. - 0xNNN 0x introduces a hexadecimal (base 16) constant. - Suffix L indicates a long value (at least 32 bits). - - /* Table of CRCs of all 8-bit messages. */ - unsigned long crc_table[256]; - - /* Flag: has the table been computed? Initially false. */ - int crc_table_computed = 0; - - /* Make the table for a fast CRC. */ - void make_crc_table(void) - { - unsigned long c; - - - -Deutsch Informational [Page 11] - -RFC 1952 GZIP File Format Specification May 1996 - - - int n, k; - for (n = 0; n < 256; n++) { - c = (unsigned long) n; - for (k = 0; k < 8; k++) { - if (c & 1) { - c = 0xedb88320L ^ (c >> 1); - } else { - c = c >> 1; - } - } - crc_table[n] = c; - } - crc_table_computed = 1; - } - - /* - Update a running crc with the bytes buf[0..len-1] and return - the updated crc. The crc should be initialized to zero. Pre- and - post-conditioning (one's complement) is performed within this - function so it shouldn't be done by the caller. Usage example: - - unsigned long crc = 0L; - - while (read_buffer(buffer, length) != EOF) { - crc = update_crc(crc, buffer, length); - } - if (crc != original_crc) error(); - */ - unsigned long update_crc(unsigned long crc, - unsigned char *buf, int len) - { - unsigned long c = crc ^ 0xffffffffL; - int n; - - if (!crc_table_computed) - make_crc_table(); - for (n = 0; n < len; n++) { - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c ^ 0xffffffffL; - } - - /* Return the CRC of the bytes buf[0..len-1]. */ - unsigned long crc(unsigned char *buf, int len) - { - return update_crc(0L, buf, len); - } - - - - -Deutsch Informational [Page 12] - diff --git a/src/contrib/zlib/doc/txtvsbin.txt b/src/contrib/zlib/doc/txtvsbin.txt deleted file mode 100644 index 3d0f063..0000000 --- a/src/contrib/zlib/doc/txtvsbin.txt +++ /dev/null @@ -1,107 +0,0 @@ -A Fast Method for Identifying Plain Text Files -============================================== - - -Introduction ------------- - -Given a file coming from an unknown source, it is sometimes desirable -to find out whether the format of that file is plain text. Although -this may appear like a simple task, a fully accurate detection of the -file type requires heavy-duty semantic analysis on the file contents. -It is, however, possible to obtain satisfactory results by employing -various heuristics. - -Previous versions of PKZip and other zip-compatible compression tools -were using a crude detection scheme: if more than 80% (4/5) of the bytes -found in a certain buffer are within the range [7..127], the file is -labeled as plain text, otherwise it is labeled as binary. A prominent -limitation of this scheme is the restriction to Latin-based alphabets. -Other alphabets, like Greek, Cyrillic or Asian, make extensive use of -the bytes within the range [128..255], and texts using these alphabets -are most often misidentified by this scheme; in other words, the rate -of false negatives is sometimes too high, which means that the recall -is low. Another weakness of this scheme is a reduced precision, due to -the false positives that may occur when binary files containing large -amounts of textual characters are misidentified as plain text. - -In this article we propose a new, simple detection scheme that features -a much increased precision and a near-100% recall. This scheme is -designed to work on ASCII, Unicode and other ASCII-derived alphabets, -and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) -and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings -(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. - - -The Algorithm -------------- - -The algorithm works by dividing the set of bytecodes [0..255] into three -categories: -- The white list of textual bytecodes: - 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. -- The gray list of tolerated bytecodes: - 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). -- The black list of undesired, non-textual bytecodes: - 0 (NUL) to 6, 14 to 31. - -If a file contains at least one byte that belongs to the white list and -no byte that belongs to the black list, then the file is categorized as -plain text; otherwise, it is categorized as binary. (The boundary case, -when the file is empty, automatically falls into the latter category.) - - -Rationale ---------- - -The idea behind this algorithm relies on two observations. - -The first observation is that, although the full range of 7-bit codes -[0..127] is properly specified by the ASCII standard, most control -characters in the range [0..31] are not used in practice. The only -widely-used, almost universally-portable control codes are 9 (TAB), -10 (LF) and 13 (CR). There are a few more control codes that are -recognized on a reduced range of platforms and text viewers/editors: -7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these -codes are rarely (if ever) used alone, without being accompanied by -some printable text. Even the newer, portable text formats such as -XML avoid using control characters outside the list mentioned here. - -The second observation is that most of the binary files tend to contain -control characters, especially 0 (NUL). Even though the older text -detection schemes observe the presence of non-ASCII codes from the range -[128..255], the precision rarely has to suffer if this upper range is -labeled as textual, because the files that are genuinely binary tend to -contain both control characters and codes from the upper range. On the -other hand, the upper range needs to be labeled as textual, because it -is used by virtually all ASCII extensions. In particular, this range is -used for encoding non-Latin scripts. - -Since there is no counting involved, other than simply observing the -presence or the absence of some byte values, the algorithm produces -consistent results, regardless what alphabet encoding is being used. -(If counting were involved, it could be possible to obtain different -results on a text encoded, say, using ISO-8859-16 versus UTF-8.) - -There is an extra category of plain text files that are "polluted" with -one or more black-listed codes, either by mistake or by peculiar design -considerations. In such cases, a scheme that tolerates a small fraction -of black-listed codes would provide an increased recall (i.e. more true -positives). This, however, incurs a reduced precision overall, since -false positives are more likely to appear in binary files that contain -large chunks of textual data. Furthermore, "polluted" plain text should -be regarded as binary by general-purpose text detection schemes, because -general-purpose text processing algorithms might not be applicable. -Under this premise, it is safe to say that our detection method provides -a near-100% recall. - -Experiments have been run on many files coming from various platforms -and applications. We tried plain text files, system logs, source code, -formatted office documents, compiled object code, etc. The results -confirm the optimistic assumptions about the capabilities of this -algorithm. - - --- -Cosmin Truta -Last updated: 2006-May-28 diff --git a/src/contrib/zlib/examples/README.examples b/src/contrib/zlib/examples/README.examples deleted file mode 100644 index 56a3171..0000000 --- a/src/contrib/zlib/examples/README.examples +++ /dev/null @@ -1,49 +0,0 @@ -This directory contains examples of the use of zlib and other relevant -programs and documentation. - -enough.c - calculation and justification of ENOUGH parameter in inftrees.h - - calculates the maximum table space used in inflate tree - construction over all possible Huffman codes - -fitblk.c - compress just enough input to nearly fill a requested output size - - zlib isn't designed to do this, but fitblk does it anyway - -gun.c - uncompress a gzip file - - illustrates the use of inflateBack() for high speed file-to-file - decompression using call-back functions - - is approximately twice as fast as gzip -d - - also provides Unix uncompress functionality, again twice as fast - -gzappend.c - append to a gzip file - - illustrates the use of the Z_BLOCK flush parameter for inflate() - - illustrates the use of deflatePrime() to start at any bit - -gzjoin.c - join gzip files without recalculating the crc or recompressing - - illustrates the use of the Z_BLOCK flush parameter for inflate() - - illustrates the use of crc32_combine() - -gzlog.c -gzlog.h - efficiently and robustly maintain a message log file in gzip format - - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), - and deflateSetDictionary() - - illustrates use of a gzip header extra field - -zlib_how.html - painfully comprehensive description of zpipe.c (see below) - - describes in excruciating detail the use of deflate() and inflate() - -zpipe.c - reads and writes zlib streams from stdin to stdout - - illustrates the proper use of deflate() and inflate() - - deeply commented in zlib_how.html (see above) - -zran.c - index a zlib or gzip stream and randomly access it - - illustrates the use of Z_BLOCK, inflatePrime(), and - inflateSetDictionary() to provide random access diff --git a/src/contrib/zlib/examples/enough.c b/src/contrib/zlib/examples/enough.c deleted file mode 100644 index b991144..0000000 --- a/src/contrib/zlib/examples/enough.c +++ /dev/null @@ -1,572 +0,0 @@ -/* enough.c -- determine the maximum size of inflate's Huffman code tables over - * all possible valid and complete Huffman codes, subject to a length limit. - * Copyright (C) 2007, 2008, 2012 Mark Adler - * Version 1.4 18 August 2012 Mark Adler - */ - -/* Version history: - 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) - 1.1 4 Jan 2007 Use faster incremental table usage computation - Prune examine() search on previously visited states - 1.2 5 Jan 2007 Comments clean up - As inflate does, decrease root for short codes - Refuse cases where inflate would increase root - 1.3 17 Feb 2008 Add argument for initial root table size - Fix bug for initial root table size == max - 1 - Use a macro to compute the history index - 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) - Clean up comparisons of different types - Clean up code indentation - */ - -/* - Examine all possible Huffman codes for a given number of symbols and a - maximum code length in bits to determine the maximum table size for zilb's - inflate. Only complete Huffman codes are counted. - - Two codes are considered distinct if the vectors of the number of codes per - length are not identical. So permutations of the symbol assignments result - in the same code for the counting, as do permutations of the assignments of - the bit values to the codes (i.e. only canonical codes are counted). - - We build a code from shorter to longer lengths, determining how many symbols - are coded at each length. At each step, we have how many symbols remain to - be coded, what the last code length used was, and how many bit patterns of - that length remain unused. Then we add one to the code length and double the - number of unused patterns to graduate to the next code length. We then - assign all portions of the remaining symbols to that code length that - preserve the properties of a correct and eventually complete code. Those - properties are: we cannot use more bit patterns than are available; and when - all the symbols are used, there are exactly zero possible bit patterns - remaining. - - The inflate Huffman decoding algorithm uses two-level lookup tables for - speed. There is a single first-level table to decode codes up to root bits - in length (root == 9 in the current inflate implementation). The table - has 1 << root entries and is indexed by the next root bits of input. Codes - shorter than root bits have replicated table entries, so that the correct - entry is pointed to regardless of the bits that follow the short code. If - the code is longer than root bits, then the table entry points to a second- - level table. The size of that table is determined by the longest code with - that root-bit prefix. If that longest code has length len, then the table - has size 1 << (len - root), to index the remaining bits in that set of - codes. Each subsequent root-bit prefix then has its own sub-table. The - total number of table entries required by the code is calculated - incrementally as the number of codes at each bit length is populated. When - all of the codes are shorter than root bits, then root is reduced to the - longest code length, resulting in a single, smaller, one-level table. - - The inflate algorithm also provides for small values of root (relative to - the log2 of the number of symbols), where the shortest code has more bits - than root. In that case, root is increased to the length of the shortest - code. This program, by design, does not handle that case, so it is verified - that the number of symbols is less than 2^(root + 1). - - In order to speed up the examination (by about ten orders of magnitude for - the default arguments), the intermediate states in the build-up of a code - are remembered and previously visited branches are pruned. The memory - required for this will increase rapidly with the total number of symbols and - the maximum code length in bits. However this is a very small price to pay - for the vast speedup. - - First, all of the possible Huffman codes are counted, and reachable - intermediate states are noted by a non-zero count in a saved-results array. - Second, the intermediate states that lead to (root + 1) bit or longer codes - are used to look at all sub-codes from those junctures for their inflate - memory usage. (The amount of memory used is not affected by the number of - codes of root bits or less in length.) Third, the visited states in the - construction of those sub-codes and the associated calculation of the table - size is recalled in order to avoid recalculating from the same juncture. - Beginning the code examination at (root + 1) bit codes, which is enabled by - identifying the reachable nodes, accounts for about six of the orders of - magnitude of improvement for the default arguments. About another four - orders of magnitude come from not revisiting previous states. Out of - approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes - need to be examined to cover all of the possible table memory usage cases - for the default arguments of 286 symbols limited to 15-bit codes. - - Note that an unsigned long long type is used for counting. It is quite easy - to exceed the capacity of an eight-byte integer with a large number of - symbols and a large maximum code length, so multiple-precision arithmetic - would need to replace the unsigned long long arithmetic in that case. This - program will abort if an overflow occurs. The big_t type identifies where - the counting takes place. - - An unsigned long long type is also used for calculating the number of - possible codes remaining at the maximum length. This limits the maximum - code length to the number of bits in a long long minus the number of bits - needed to represent the symbols in a flat code. The code_t type identifies - where the bit pattern counting takes place. - */ - -#include -#include -#include -#include - -#define local static - -/* special data types */ -typedef unsigned long long big_t; /* type for code counting */ -typedef unsigned long long code_t; /* type for bit pattern counting */ -struct tab { /* type for been here check */ - size_t len; /* length of bit vector in char's */ - char *vec; /* allocated bit vector */ -}; - -/* The array for saving results, num[], is indexed with this triplet: - - syms: number of symbols remaining to code - left: number of available bit patterns at length len - len: number of bits in the codes currently being assigned - - Those indices are constrained thusly when saving results: - - syms: 3..totsym (totsym == total symbols to code) - left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) - len: 1..max - 1 (max == maximum code length in bits) - - syms == 2 is not saved since that immediately leads to a single code. left - must be even, since it represents the number of available bit patterns at - the current length, which is double the number at the previous length. - left ends at syms-1 since left == syms immediately results in a single code. - (left > sym is not allowed since that would result in an incomplete code.) - len is less than max, since the code completes immediately when len == max. - - The offset into the array is calculated for the three indices with the - first one (syms) being outermost, and the last one (len) being innermost. - We build the array with length max-1 lists for the len index, with syms-3 - of those for each symbol. There are totsym-2 of those, with each one - varying in length as a function of sym. See the calculation of index in - count() for the index, and the calculation of size in main() for the size - of the array. - - For the deflate example of 286 symbols limited to 15-bit codes, the array - has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than - half of the space allocated for saved results is actually used -- not all - possible triplets are reached in the generation of valid Huffman codes. - */ - -/* The array for tracking visited states, done[], is itself indexed identically - to the num[] array as described above for the (syms, left, len) triplet. - Each element in the array is further indexed by the (mem, rem) doublet, - where mem is the amount of inflate table space used so far, and rem is the - remaining unused entries in the current inflate sub-table. Each indexed - element is simply one bit indicating whether the state has been visited or - not. Since the ranges for mem and rem are not known a priori, each bit - vector is of a variable size, and grows as needed to accommodate the visited - states. mem and rem are used to calculate a single index in a triangular - array. Since the range of mem is expected in the default case to be about - ten times larger than the range of rem, the array is skewed to reduce the - memory usage, with eight times the range for mem than for rem. See the - calculations for offset and bit in beenhere() for the details. - - For the deflate example of 286 symbols limited to 15-bit codes, the bit - vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] - array itself. - */ - -/* Globals to avoid propagating constants or constant pointers recursively */ -local int max; /* maximum allowed bit length for the codes */ -local int root; /* size of base code table in bits */ -local int large; /* largest code table so far */ -local size_t size; /* number of elements in num and done */ -local int *code; /* number of symbols assigned to each bit length */ -local big_t *num; /* saved results array for code counting */ -local struct tab *done; /* states already evaluated array */ - -/* Index function for num[] and done[] */ -#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) - -/* Free allocated space. Uses globals code, num, and done. */ -local void cleanup(void) -{ - size_t n; - - if (done != NULL) { - for (n = 0; n < size; n++) - if (done[n].len) - free(done[n].vec); - free(done); - } - if (num != NULL) - free(num); - if (code != NULL) - free(code); -} - -/* Return the number of possible Huffman codes using bit patterns of lengths - len through max inclusive, coding syms symbols, with left bit patterns of - length len unused -- return -1 if there is an overflow in the counting. - Keep a record of previous results in num to prevent repeating the same - calculation. Uses the globals max and num. */ -local big_t count(int syms, int len, int left) -{ - big_t sum; /* number of possible codes from this juncture */ - big_t got; /* value returned from count() */ - int least; /* least number of syms to use at this juncture */ - int most; /* most number of syms to use at this juncture */ - int use; /* number of bit patterns to use in next call */ - size_t index; /* index of this case in *num */ - - /* see if only one possible code */ - if (syms == left) - return 1; - - /* note and verify the expected state */ - assert(syms > left && left > 0 && len < max); - - /* see if we've done this one already */ - index = INDEX(syms, left, len); - got = num[index]; - if (got) - return got; /* we have -- return the saved result */ - - /* we need to use at least this many bit patterns so that the code won't be - incomplete at the next length (more bit patterns than symbols) */ - least = (left << 1) - syms; - if (least < 0) - least = 0; - - /* we can use at most this many bit patterns, lest there not be enough - available for the remaining symbols at the maximum length (if there were - no limit to the code length, this would become: most = left - 1) */ - most = (((code_t)left << (max - len)) - syms) / - (((code_t)1 << (max - len)) - 1); - - /* count all possible codes from this juncture and add them up */ - sum = 0; - for (use = least; use <= most; use++) { - got = count(syms - use, len + 1, (left - use) << 1); - sum += got; - if (got == (big_t)0 - 1 || sum < got) /* overflow */ - return (big_t)0 - 1; - } - - /* verify that all recursive calls are productive */ - assert(sum != 0); - - /* save the result and return it */ - num[index] = sum; - return sum; -} - -/* Return true if we've been here before, set to true if not. Set a bit in a - bit vector to indicate visiting this state. Each (syms,len,left) state - has a variable size bit vector indexed by (mem,rem). The bit vector is - lengthened if needed to allow setting the (mem,rem) bit. */ -local int beenhere(int syms, int len, int left, int mem, int rem) -{ - size_t index; /* index for this state's bit vector */ - size_t offset; /* offset in this state's bit vector */ - int bit; /* mask for this state's bit */ - size_t length; /* length of the bit vector in bytes */ - char *vector; /* new or enlarged bit vector */ - - /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ - index = INDEX(syms, left, len); - mem -= 1 << root; - offset = (mem >> 3) + rem; - offset = ((offset * (offset + 1)) >> 1) + rem; - bit = 1 << (mem & 7); - - /* see if we've been here */ - length = done[index].len; - if (offset < length && (done[index].vec[offset] & bit) != 0) - return 1; /* done this! */ - - /* we haven't been here before -- set the bit to show we have now */ - - /* see if we need to lengthen the vector in order to set the bit */ - if (length <= offset) { - /* if we have one already, enlarge it, zero out the appended space */ - if (length) { - do { - length <<= 1; - } while (length <= offset); - vector = realloc(done[index].vec, length); - if (vector != NULL) - memset(vector + done[index].len, 0, length - done[index].len); - } - - /* otherwise we need to make a new vector and zero it out */ - else { - length = 1 << (len - root); - while (length <= offset) - length <<= 1; - vector = calloc(length, sizeof(char)); - } - - /* in either case, bail if we can't get the memory */ - if (vector == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - exit(1); - } - - /* install the new vector */ - done[index].len = length; - done[index].vec = vector; - } - - /* set the bit */ - done[index].vec[offset] |= bit; - return 0; -} - -/* Examine all possible codes from the given node (syms, len, left). Compute - the amount of memory required to build inflate's decoding tables, where the - number of code structures used so far is mem, and the number remaining in - the current sub-table is rem. Uses the globals max, code, root, large, and - done. */ -local void examine(int syms, int len, int left, int mem, int rem) -{ - int least; /* least number of syms to use at this juncture */ - int most; /* most number of syms to use at this juncture */ - int use; /* number of bit patterns to use in next call */ - - /* see if we have a complete code */ - if (syms == left) { - /* set the last code entry */ - code[len] = left; - - /* complete computation of memory used by this code */ - while (rem < left) { - left -= rem; - rem = 1 << (len - root); - mem += rem; - } - assert(rem == left); - - /* if this is a new maximum, show the entries used and the sub-code */ - if (mem > large) { - large = mem; - printf("max %d: ", mem); - for (use = root + 1; use <= max; use++) - if (code[use]) - printf("%d[%d] ", code[use], use); - putchar('\n'); - fflush(stdout); - } - - /* remove entries as we drop back down in the recursion */ - code[len] = 0; - return; - } - - /* prune the tree if we can */ - if (beenhere(syms, len, left, mem, rem)) - return; - - /* we need to use at least this many bit patterns so that the code won't be - incomplete at the next length (more bit patterns than symbols) */ - least = (left << 1) - syms; - if (least < 0) - least = 0; - - /* we can use at most this many bit patterns, lest there not be enough - available for the remaining symbols at the maximum length (if there were - no limit to the code length, this would become: most = left - 1) */ - most = (((code_t)left << (max - len)) - syms) / - (((code_t)1 << (max - len)) - 1); - - /* occupy least table spaces, creating new sub-tables as needed */ - use = least; - while (rem < use) { - use -= rem; - rem = 1 << (len - root); - mem += rem; - } - rem -= use; - - /* examine codes from here, updating table space as we go */ - for (use = least; use <= most; use++) { - code[len] = use; - examine(syms - use, len + 1, (left - use) << 1, - mem + (rem ? 1 << (len - root) : 0), rem << 1); - if (rem == 0) { - rem = 1 << (len - root); - mem += rem; - } - rem--; - } - - /* remove entries as we drop back down in the recursion */ - code[len] = 0; -} - -/* Look at all sub-codes starting with root + 1 bits. Look at only the valid - intermediate code states (syms, left, len). For each completed code, - calculate the amount of memory required by inflate to build the decoding - tables. Find the maximum amount of memory required and show the code that - requires that maximum. Uses the globals max, root, and num. */ -local void enough(int syms) -{ - int n; /* number of remaing symbols for this node */ - int left; /* number of unused bit patterns at this length */ - size_t index; /* index of this case in *num */ - - /* clear code */ - for (n = 0; n <= max; n++) - code[n] = 0; - - /* look at all (root + 1) bit and longer codes */ - large = 1 << root; /* base table */ - if (root < max) /* otherwise, there's only a base table */ - for (n = 3; n <= syms; n++) - for (left = 2; left < n; left += 2) - { - /* look at all reachable (root + 1) bit nodes, and the - resulting codes (complete at root + 2 or more) */ - index = INDEX(n, left, root + 1); - if (root + 1 < max && num[index]) /* reachable node */ - examine(n, root + 1, left, 1 << root, 0); - - /* also look at root bit codes with completions at root + 1 - bits (not saved in num, since complete), just in case */ - if (num[index - 1] && n <= left << 1) - examine((n - left) << 1, root + 1, (n - left) << 1, - 1 << root, 0); - } - - /* done */ - printf("done: maximum of %d table entries\n", large); -} - -/* - Examine and show the total number of possible Huffman codes for a given - maximum number of symbols, initial root table size, and maximum code length - in bits -- those are the command arguments in that order. The default - values are 286, 9, and 15 respectively, for the deflate literal/length code. - The possible codes are counted for each number of coded symbols from two to - the maximum. The counts for each of those and the total number of codes are - shown. The maximum number of inflate table entires is then calculated - across all possible codes. Each new maximum number of table entries and the - associated sub-code (starting at root + 1 == 10 bits) is shown. - - To count and examine Huffman codes that are not length-limited, provide a - maximum length equal to the number of symbols minus one. - - For the deflate literal/length code, use "enough". For the deflate distance - code, use "enough 30 6". - - This uses the %llu printf format to print big_t numbers, which assumes that - big_t is an unsigned long long. If the big_t type is changed (for example - to a multiple precision type), the method of printing will also need to be - updated. - */ -int main(int argc, char **argv) -{ - int syms; /* total number of symbols to code */ - int n; /* number of symbols to code for this run */ - big_t got; /* return value of count() */ - big_t sum; /* accumulated number of codes over n */ - code_t word; /* for counting bits in code_t */ - - /* set up globals for cleanup() */ - code = NULL; - num = NULL; - done = NULL; - - /* get arguments -- default to the deflate literal/length code */ - syms = 286; - root = 9; - max = 15; - if (argc > 1) { - syms = atoi(argv[1]); - if (argc > 2) { - root = atoi(argv[2]); - if (argc > 3) - max = atoi(argv[3]); - } - } - if (argc > 4 || syms < 2 || root < 1 || max < 1) { - fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", - stderr); - return 1; - } - - /* if not restricting the code length, the longest is syms - 1 */ - if (max > syms - 1) - max = syms - 1; - - /* determine the number of bits in a code_t */ - for (n = 0, word = 1; word; n++, word <<= 1) - ; - - /* make sure that the calculation of most will not overflow */ - if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { - fputs("abort: code length too long for internal types\n", stderr); - return 1; - } - - /* reject impossible code requests */ - if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { - fprintf(stderr, "%d symbols cannot be coded in %d bits\n", - syms, max); - return 1; - } - - /* allocate code vector */ - code = calloc(max + 1, sizeof(int)); - if (code == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - return 1; - } - - /* determine size of saved results array, checking for overflows, - allocate and clear the array (set all to zero with calloc()) */ - if (syms == 2) /* iff max == 1 */ - num = NULL; /* won't be saving any results */ - else { - size = syms >> 1; - if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || - (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || - (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || - (num = calloc(size, sizeof(big_t))) == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - return 1; - } - } - - /* count possible codes for all numbers of symbols, add up counts */ - sum = 0; - for (n = 2; n <= syms; n++) { - got = count(n, 1, 2); - sum += got; - if (got == (big_t)0 - 1 || sum < got) { /* overflow */ - fputs("abort: can't count that high!\n", stderr); - cleanup(); - return 1; - } - printf("%llu %d-codes\n", got, n); - } - printf("%llu total codes for 2 to %d symbols", sum, syms); - if (max < syms - 1) - printf(" (%d-bit length limit)\n", max); - else - puts(" (no length limit)"); - - /* allocate and clear done array for beenhere() */ - if (syms == 2) - done = NULL; - else if (size > ((size_t)0 - 1) / sizeof(struct tab) || - (done = calloc(size, sizeof(struct tab))) == NULL) { - fputs("abort: unable to allocate enough memory\n", stderr); - cleanup(); - return 1; - } - - /* find and show maximum inflate table usage */ - if (root > max) /* reduce root to max length */ - root = max; - if ((code_t)syms < ((code_t)1 << (root + 1))) - enough(syms); - else - puts("cannot handle minimum code lengths > root"); - - /* done */ - cleanup(); - return 0; -} diff --git a/src/contrib/zlib/examples/fitblk.c b/src/contrib/zlib/examples/fitblk.c deleted file mode 100644 index c61de5c..0000000 --- a/src/contrib/zlib/examples/fitblk.c +++ /dev/null @@ -1,233 +0,0 @@ -/* fitblk.c: example of fitting compressed output to a specified size - Not copyrighted -- provided to the public domain - Version 1.1 25 November 2004 Mark Adler */ - -/* Version history: - 1.0 24 Nov 2004 First version - 1.1 25 Nov 2004 Change deflateInit2() to deflateInit() - Use fixed-size, stack-allocated raw buffers - Simplify code moving compression to subroutines - Use assert() for internal errors - Add detailed description of approach - */ - -/* Approach to just fitting a requested compressed size: - - fitblk performs three compression passes on a portion of the input - data in order to determine how much of that input will compress to - nearly the requested output block size. The first pass generates - enough deflate blocks to produce output to fill the requested - output size plus a specfied excess amount (see the EXCESS define - below). The last deflate block may go quite a bit past that, but - is discarded. The second pass decompresses and recompresses just - the compressed data that fit in the requested plus excess sized - buffer. The deflate process is terminated after that amount of - input, which is less than the amount consumed on the first pass. - The last deflate block of the result will be of a comparable size - to the final product, so that the header for that deflate block and - the compression ratio for that block will be about the same as in - the final product. The third compression pass decompresses the - result of the second step, but only the compressed data up to the - requested size minus an amount to allow the compressed stream to - complete (see the MARGIN define below). That will result in a - final compressed stream whose length is less than or equal to the - requested size. Assuming sufficient input and a requested size - greater than a few hundred bytes, the shortfall will typically be - less than ten bytes. - - If the input is short enough that the first compression completes - before filling the requested output size, then that compressed - stream is return with no recompression. - - EXCESS is chosen to be just greater than the shortfall seen in a - two pass approach similar to the above. That shortfall is due to - the last deflate block compressing more efficiently with a smaller - header on the second pass. EXCESS is set to be large enough so - that there is enough uncompressed data for the second pass to fill - out the requested size, and small enough so that the final deflate - block of the second pass will be close in size to the final deflate - block of the third and final pass. MARGIN is chosen to be just - large enough to assure that the final compression has enough room - to complete in all cases. - */ - -#include -#include -#include -#include "zlib.h" - -#define local static - -/* print nastygram and leave */ -local void quit(char *why) -{ - fprintf(stderr, "fitblk abort: %s\n", why); - exit(1); -} - -#define RAWLEN 4096 /* intermediate uncompressed buffer size */ - -/* compress from file to def until provided buffer is full or end of - input reached; return last deflate() return value, or Z_ERRNO if - there was read error on the file */ -local int partcompress(FILE *in, z_streamp def) -{ - int ret, flush; - unsigned char raw[RAWLEN]; - - flush = Z_NO_FLUSH; - do { - def->avail_in = fread(raw, 1, RAWLEN, in); - if (ferror(in)) - return Z_ERRNO; - def->next_in = raw; - if (feof(in)) - flush = Z_FINISH; - ret = deflate(def, flush); - assert(ret != Z_STREAM_ERROR); - } while (def->avail_out != 0 && flush == Z_NO_FLUSH); - return ret; -} - -/* recompress from inf's input to def's output; the input for inf and - the output for def are set in those structures before calling; - return last deflate() return value, or Z_MEM_ERROR if inflate() - was not able to allocate enough memory when it needed to */ -local int recompress(z_streamp inf, z_streamp def) -{ - int ret, flush; - unsigned char raw[RAWLEN]; - - flush = Z_NO_FLUSH; - do { - /* decompress */ - inf->avail_out = RAWLEN; - inf->next_out = raw; - ret = inflate(inf, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && - ret != Z_NEED_DICT); - if (ret == Z_MEM_ERROR) - return ret; - - /* compress what was decompresed until done or no room */ - def->avail_in = RAWLEN - inf->avail_out; - def->next_in = raw; - if (inf->avail_out != 0) - flush = Z_FINISH; - ret = deflate(def, flush); - assert(ret != Z_STREAM_ERROR); - } while (ret != Z_STREAM_END && def->avail_out != 0); - return ret; -} - -#define EXCESS 256 /* empirically determined stream overage */ -#define MARGIN 8 /* amount to back off for completion */ - -/* compress from stdin to fixed-size block on stdout */ -int main(int argc, char **argv) -{ - int ret; /* return code */ - unsigned size; /* requested fixed output block size */ - unsigned have; /* bytes written by deflate() call */ - unsigned char *blk; /* intermediate and final stream */ - unsigned char *tmp; /* close to desired size stream */ - z_stream def, inf; /* zlib deflate and inflate states */ - - /* get requested output size */ - if (argc != 2) - quit("need one argument: size of output block"); - ret = strtol(argv[1], argv + 1, 10); - if (argv[1][0] != 0) - quit("argument must be a number"); - if (ret < 8) /* 8 is minimum zlib stream size */ - quit("need positive size of 8 or greater"); - size = (unsigned)ret; - - /* allocate memory for buffers and compression engine */ - blk = malloc(size + EXCESS); - def.zalloc = Z_NULL; - def.zfree = Z_NULL; - def.opaque = Z_NULL; - ret = deflateInit(&def, Z_DEFAULT_COMPRESSION); - if (ret != Z_OK || blk == NULL) - quit("out of memory"); - - /* compress from stdin until output full, or no more input */ - def.avail_out = size + EXCESS; - def.next_out = blk; - ret = partcompress(stdin, &def); - if (ret == Z_ERRNO) - quit("error reading input"); - - /* if it all fit, then size was undersubscribed -- done! */ - if (ret == Z_STREAM_END && def.avail_out >= EXCESS) { - /* write block to stdout */ - have = size + EXCESS - def.avail_out; - if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) - quit("error writing output"); - - /* clean up and print results to stderr */ - ret = deflateEnd(&def); - assert(ret != Z_STREAM_ERROR); - free(blk); - fprintf(stderr, - "%u bytes unused out of %u requested (all input)\n", - size - have, size); - return 0; - } - - /* it didn't all fit -- set up for recompression */ - inf.zalloc = Z_NULL; - inf.zfree = Z_NULL; - inf.opaque = Z_NULL; - inf.avail_in = 0; - inf.next_in = Z_NULL; - ret = inflateInit(&inf); - tmp = malloc(size + EXCESS); - if (ret != Z_OK || tmp == NULL) - quit("out of memory"); - ret = deflateReset(&def); - assert(ret != Z_STREAM_ERROR); - - /* do first recompression close to the right amount */ - inf.avail_in = size + EXCESS; - inf.next_in = blk; - def.avail_out = size + EXCESS; - def.next_out = tmp; - ret = recompress(&inf, &def); - if (ret == Z_MEM_ERROR) - quit("out of memory"); - - /* set up for next reocmpression */ - ret = inflateReset(&inf); - assert(ret != Z_STREAM_ERROR); - ret = deflateReset(&def); - assert(ret != Z_STREAM_ERROR); - - /* do second and final recompression (third compression) */ - inf.avail_in = size - MARGIN; /* assure stream will complete */ - inf.next_in = tmp; - def.avail_out = size; - def.next_out = blk; - ret = recompress(&inf, &def); - if (ret == Z_MEM_ERROR) - quit("out of memory"); - assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */ - - /* done -- write block to stdout */ - have = size - def.avail_out; - if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) - quit("error writing output"); - - /* clean up and print results to stderr */ - free(tmp); - ret = inflateEnd(&inf); - assert(ret != Z_STREAM_ERROR); - ret = deflateEnd(&def); - assert(ret != Z_STREAM_ERROR); - free(blk); - fprintf(stderr, - "%u bytes unused out of %u requested (%lu input)\n", - size - have, size, def.total_in); - return 0; -} diff --git a/src/contrib/zlib/examples/gun.c b/src/contrib/zlib/examples/gun.c deleted file mode 100644 index be44fa5..0000000 --- a/src/contrib/zlib/examples/gun.c +++ /dev/null @@ -1,702 +0,0 @@ -/* gun.c -- simple gunzip to give an example of the use of inflateBack() - * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.7 12 August 2012 Mark Adler */ - -/* Version history: - 1.0 16 Feb 2003 First version for testing of inflateBack() - 1.1 21 Feb 2005 Decompress concatenated gzip streams - Remove use of "this" variable (C++ keyword) - Fix return value for in() - Improve allocation failure checking - Add typecasting for void * structures - Add -h option for command version and usage - Add a bunch of comments - 1.2 20 Mar 2005 Add Unix compress (LZW) decompression - Copy file attributes from input file to output file - 1.3 12 Jun 2005 Add casts for error messages [Oberhumer] - 1.4 8 Dec 2006 LZW decompression speed improvements - 1.5 9 Feb 2008 Avoid warning in latest version of gcc - 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings - 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 - */ - -/* - gun [ -t ] [ name ... ] - - decompresses the data in the named gzip files. If no arguments are given, - gun will decompress from stdin to stdout. The names must end in .gz, -gz, - .z, -z, _z, or .Z. The uncompressed data will be written to a file name - with the suffix stripped. On success, the original file is deleted. On - failure, the output file is deleted. For most failures, the command will - continue to process the remaining names on the command line. A memory - allocation failure will abort the command. If -t is specified, then the - listed files or stdin will be tested as gzip files for integrity (without - checking for a proper suffix), no output will be written, and no files - will be deleted. - - Like gzip, gun allows concatenated gzip streams and will decompress them, - writing all of the uncompressed data to the output. Unlike gzip, gun allows - an empty file on input, and will produce no error writing an empty output - file. - - gun will also decompress files made by Unix compress, which uses LZW - compression. These files are automatically detected by virtue of their - magic header bytes. Since the end of Unix compress stream is marked by the - end-of-file, they cannot be concantenated. If a Unix compress stream is - encountered in an input file, it is the last stream in that file. - - Like gunzip and uncompress, the file attributes of the original compressed - file are maintained in the final uncompressed file, to the extent that the - user permissions allow it. - - On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version - 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the - LZW decompression provided by gun is about twice as fast as the standard - Unix uncompress command. - */ - -/* external functions and related types and constants */ -#include /* fprintf() */ -#include /* malloc(), free() */ -#include /* strerror(), strcmp(), strlen(), memcpy() */ -#include /* errno */ -#include /* open() */ -#include /* read(), write(), close(), chown(), unlink() */ -#include -#include /* stat(), chmod() */ -#include /* utime() */ -#include "zlib.h" /* inflateBackInit(), inflateBack(), */ - /* inflateBackEnd(), crc32() */ - -/* function declaration */ -#define local static - -/* buffer constants */ -#define SIZE 32768U /* input and output buffer sizes */ -#define PIECE 16384 /* limits i/o chunks for 16-bit int case */ - -/* structure for infback() to pass to input function in() -- it maintains the - input file and a buffer of size SIZE */ -struct ind { - int infile; - unsigned char *inbuf; -}; - -/* Load input buffer, assumed to be empty, and return bytes loaded and a - pointer to them. read() is called until the buffer is full, or until it - returns end-of-file or error. Return 0 on error. */ -local unsigned in(void *in_desc, z_const unsigned char **buf) -{ - int ret; - unsigned len; - unsigned char *next; - struct ind *me = (struct ind *)in_desc; - - next = me->inbuf; - *buf = next; - len = 0; - do { - ret = PIECE; - if ((unsigned)ret > SIZE - len) - ret = (int)(SIZE - len); - ret = (int)read(me->infile, next, ret); - if (ret == -1) { - len = 0; - break; - } - next += ret; - len += ret; - } while (ret != 0 && len < SIZE); - return len; -} - -/* structure for infback() to pass to output function out() -- it maintains the - output file, a running CRC-32 check on the output and the total number of - bytes output, both for checking against the gzip trailer. (The length in - the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and - the output is greater than 4 GB.) */ -struct outd { - int outfile; - int check; /* true if checking crc and total */ - unsigned long crc; - unsigned long total; -}; - -/* Write output buffer and update the CRC-32 and total bytes written. write() - is called until all of the output is written or an error is encountered. - On success out() returns 0. For a write failure, out() returns 1. If the - output file descriptor is -1, then nothing is written. - */ -local int out(void *out_desc, unsigned char *buf, unsigned len) -{ - int ret; - struct outd *me = (struct outd *)out_desc; - - if (me->check) { - me->crc = crc32(me->crc, buf, len); - me->total += len; - } - if (me->outfile != -1) - do { - ret = PIECE; - if ((unsigned)ret > len) - ret = (int)len; - ret = (int)write(me->outfile, buf, ret); - if (ret == -1) - return 1; - buf += ret; - len -= ret; - } while (len != 0); - return 0; -} - -/* next input byte macro for use inside lunpipe() and gunpipe() */ -#define NEXT() (have ? 0 : (have = in(indp, &next)), \ - last = have ? (have--, (int)(*next++)) : -1) - -/* memory for gunpipe() and lunpipe() -- - the first 256 entries of prefix[] and suffix[] are never used, could - have offset the index, but it's faster to waste the memory */ -unsigned char inbuf[SIZE]; /* input buffer */ -unsigned char outbuf[SIZE]; /* output buffer */ -unsigned short prefix[65536]; /* index to LZW prefix string */ -unsigned char suffix[65536]; /* one-character LZW suffix */ -unsigned char match[65280 + 2]; /* buffer for reversed match or gzip - 32K sliding window */ - -/* throw out what's left in the current bits byte buffer (this is a vestigial - aspect of the compressed data format derived from an implementation that - made use of a special VAX machine instruction!) */ -#define FLUSHCODE() \ - do { \ - left = 0; \ - rem = 0; \ - if (chunk > have) { \ - chunk -= have; \ - have = 0; \ - if (NEXT() == -1) \ - break; \ - chunk--; \ - if (chunk > have) { \ - chunk = have = 0; \ - break; \ - } \ - } \ - have -= chunk; \ - next += chunk; \ - chunk = 0; \ - } while (0) - -/* Decompress a compress (LZW) file from indp to outfile. The compress magic - header (two bytes) has already been read and verified. There are have bytes - of buffered input at next. strm is used for passing error information back - to gunpipe(). - - lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of - file, read error, or write error (a write error indicated by strm->next_in - not equal to Z_NULL), or Z_DATA_ERROR for invalid input. - */ -local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, - int outfile, z_stream *strm) -{ - int last; /* last byte read by NEXT(), or -1 if EOF */ - unsigned chunk; /* bytes left in current chunk */ - int left; /* bits left in rem */ - unsigned rem; /* unused bits from input */ - int bits; /* current bits per code */ - unsigned code; /* code, table traversal index */ - unsigned mask; /* mask for current bits codes */ - int max; /* maximum bits per code for this stream */ - unsigned flags; /* compress flags, then block compress flag */ - unsigned end; /* last valid entry in prefix/suffix tables */ - unsigned temp; /* current code */ - unsigned prev; /* previous code */ - unsigned final; /* last character written for previous code */ - unsigned stack; /* next position for reversed string */ - unsigned outcnt; /* bytes in output buffer */ - struct outd outd; /* output structure */ - unsigned char *p; - - /* set up output */ - outd.outfile = outfile; - outd.check = 0; - - /* process remainder of compress header -- a flags byte */ - flags = NEXT(); - if (last == -1) - return Z_BUF_ERROR; - if (flags & 0x60) { - strm->msg = (char *)"unknown lzw flags set"; - return Z_DATA_ERROR; - } - max = flags & 0x1f; - if (max < 9 || max > 16) { - strm->msg = (char *)"lzw bits out of range"; - return Z_DATA_ERROR; - } - if (max == 9) /* 9 doesn't really mean 9 */ - max = 10; - flags &= 0x80; /* true if block compress */ - - /* clear table */ - bits = 9; - mask = 0x1ff; - end = flags ? 256 : 255; - - /* set up: get first 9-bit code, which is the first decompressed byte, but - don't create a table entry until the next code */ - if (NEXT() == -1) /* no compressed data is ok */ - return Z_OK; - final = prev = (unsigned)last; /* low 8 bits of code */ - if (NEXT() == -1) /* missing a bit */ - return Z_BUF_ERROR; - if (last & 1) { /* code must be < 256 */ - strm->msg = (char *)"invalid lzw code"; - return Z_DATA_ERROR; - } - rem = (unsigned)last >> 1; /* remaining 7 bits */ - left = 7; - chunk = bits - 2; /* 7 bytes left in this chunk */ - outbuf[0] = (unsigned char)final; /* write first decompressed byte */ - outcnt = 1; - - /* decode codes */ - stack = 0; - for (;;) { - /* if the table will be full after this, increment the code size */ - if (end >= mask && bits < max) { - FLUSHCODE(); - bits++; - mask <<= 1; - mask++; - } - - /* get a code of length bits */ - if (chunk == 0) /* decrement chunk modulo bits */ - chunk = bits; - code = rem; /* low bits of code */ - if (NEXT() == -1) { /* EOF is end of compressed data */ - /* write remaining buffered output */ - if (outcnt && out(&outd, outbuf, outcnt)) { - strm->next_in = outbuf; /* signal write error */ - return Z_BUF_ERROR; - } - return Z_OK; - } - code += (unsigned)last << left; /* middle (or high) bits of code */ - left += 8; - chunk--; - if (bits > left) { /* need more bits */ - if (NEXT() == -1) /* can't end in middle of code */ - return Z_BUF_ERROR; - code += (unsigned)last << left; /* high bits of code */ - left += 8; - chunk--; - } - code &= mask; /* mask to current code length */ - left -= bits; /* number of unused bits */ - rem = (unsigned)last >> (8 - left); /* unused bits from last byte */ - - /* process clear code (256) */ - if (code == 256 && flags) { - FLUSHCODE(); - bits = 9; /* initialize bits and mask */ - mask = 0x1ff; - end = 255; /* empty table */ - continue; /* get next code */ - } - - /* special code to reuse last match */ - temp = code; /* save the current code */ - if (code > end) { - /* Be picky on the allowed code here, and make sure that the code - we drop through (prev) will be a valid index so that random - input does not cause an exception. The code != end + 1 check is - empirically derived, and not checked in the original uncompress - code. If this ever causes a problem, that check could be safely - removed. Leaving this check in greatly improves gun's ability - to detect random or corrupted input after a compress header. - In any case, the prev > end check must be retained. */ - if (code != end + 1 || prev > end) { - strm->msg = (char *)"invalid lzw code"; - return Z_DATA_ERROR; - } - match[stack++] = (unsigned char)final; - code = prev; - } - - /* walk through linked list to generate output in reverse order */ - p = match + stack; - while (code >= 256) { - *p++ = suffix[code]; - code = prefix[code]; - } - stack = p - match; - match[stack++] = (unsigned char)code; - final = code; - - /* link new table entry */ - if (end < mask) { - end++; - prefix[end] = (unsigned short)prev; - suffix[end] = (unsigned char)final; - } - - /* set previous code for next iteration */ - prev = temp; - - /* write output in forward order */ - while (stack > SIZE - outcnt) { - while (outcnt < SIZE) - outbuf[outcnt++] = match[--stack]; - if (out(&outd, outbuf, outcnt)) { - strm->next_in = outbuf; /* signal write error */ - return Z_BUF_ERROR; - } - outcnt = 0; - } - p = match + stack; - do { - outbuf[outcnt++] = *--p; - } while (p > match); - stack = 0; - - /* loop for next code with final and prev as the last match, rem and - left provide the first 0..7 bits of the next code, end is the last - valid table entry */ - } -} - -/* Decompress a gzip file from infile to outfile. strm is assumed to have been - successfully initialized with inflateBackInit(). The input file may consist - of a series of gzip streams, in which case all of them will be decompressed - to the output file. If outfile is -1, then the gzip stream(s) integrity is - checked and nothing is written. - - The return value is a zlib error code: Z_MEM_ERROR if out of memory, - Z_DATA_ERROR if the header or the compressed data is invalid, or if the - trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends - prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip - stream) follows a valid gzip stream. - */ -local int gunpipe(z_stream *strm, int infile, int outfile) -{ - int ret, first, last; - unsigned have, flags, len; - z_const unsigned char *next = NULL; - struct ind ind, *indp; - struct outd outd; - - /* setup input buffer */ - ind.infile = infile; - ind.inbuf = inbuf; - indp = &ind; - - /* decompress concatenated gzip streams */ - have = 0; /* no input data read in yet */ - first = 1; /* looking for first gzip header */ - strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ - for (;;) { - /* look for the two magic header bytes for a gzip stream */ - if (NEXT() == -1) { - ret = Z_OK; - break; /* empty gzip stream is ok */ - } - if (last != 31 || (NEXT() != 139 && last != 157)) { - strm->msg = (char *)"incorrect header check"; - ret = first ? Z_DATA_ERROR : Z_ERRNO; - break; /* not a gzip or compress header */ - } - first = 0; /* next non-header is junk */ - - /* process a compress (LZW) file -- can't be concatenated after this */ - if (last == 157) { - ret = lunpipe(have, next, indp, outfile, strm); - break; - } - - /* process remainder of gzip header */ - ret = Z_BUF_ERROR; - if (NEXT() != 8) { /* only deflate method allowed */ - if (last == -1) break; - strm->msg = (char *)"unknown compression method"; - ret = Z_DATA_ERROR; - break; - } - flags = NEXT(); /* header flags */ - NEXT(); /* discard mod time, xflgs, os */ - NEXT(); - NEXT(); - NEXT(); - NEXT(); - NEXT(); - if (last == -1) break; - if (flags & 0xe0) { - strm->msg = (char *)"unknown header flags set"; - ret = Z_DATA_ERROR; - break; - } - if (flags & 4) { /* extra field */ - len = NEXT(); - len += (unsigned)(NEXT()) << 8; - if (last == -1) break; - while (len > have) { - len -= have; - have = 0; - if (NEXT() == -1) break; - len--; - } - if (last == -1) break; - have -= len; - next += len; - } - if (flags & 8) /* file name */ - while (NEXT() != 0 && last != -1) - ; - if (flags & 16) /* comment */ - while (NEXT() != 0 && last != -1) - ; - if (flags & 2) { /* header crc */ - NEXT(); - NEXT(); - } - if (last == -1) break; - - /* set up output */ - outd.outfile = outfile; - outd.check = 1; - outd.crc = crc32(0L, Z_NULL, 0); - outd.total = 0; - - /* decompress data to output */ - strm->next_in = next; - strm->avail_in = have; - ret = inflateBack(strm, in, indp, out, &outd); - if (ret != Z_STREAM_END) break; - next = strm->next_in; - have = strm->avail_in; - strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ - - /* check trailer */ - ret = Z_BUF_ERROR; - if (NEXT() != (int)(outd.crc & 0xff) || - NEXT() != (int)((outd.crc >> 8) & 0xff) || - NEXT() != (int)((outd.crc >> 16) & 0xff) || - NEXT() != (int)((outd.crc >> 24) & 0xff)) { - /* crc error */ - if (last != -1) { - strm->msg = (char *)"incorrect data check"; - ret = Z_DATA_ERROR; - } - break; - } - if (NEXT() != (int)(outd.total & 0xff) || - NEXT() != (int)((outd.total >> 8) & 0xff) || - NEXT() != (int)((outd.total >> 16) & 0xff) || - NEXT() != (int)((outd.total >> 24) & 0xff)) { - /* length error */ - if (last != -1) { - strm->msg = (char *)"incorrect length check"; - ret = Z_DATA_ERROR; - } - break; - } - - /* go back and look for another gzip stream */ - } - - /* clean up and return */ - return ret; -} - -/* Copy file attributes, from -> to, as best we can. This is best effort, so - no errors are reported. The mode bits, including suid, sgid, and the sticky - bit are copied (if allowed), the owner's user id and group id are copied - (again if allowed), and the access and modify times are copied. */ -local void copymeta(char *from, char *to) -{ - struct stat was; - struct utimbuf when; - - /* get all of from's Unix meta data, return if not a regular file */ - if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG) - return; - - /* set to's mode bits, ignore errors */ - (void)chmod(to, was.st_mode & 07777); - - /* copy owner's user and group, ignore errors */ - (void)chown(to, was.st_uid, was.st_gid); - - /* copy access and modify times, ignore errors */ - when.actime = was.st_atime; - when.modtime = was.st_mtime; - (void)utime(to, &when); -} - -/* Decompress the file inname to the file outnname, of if test is true, just - decompress without writing and check the gzip trailer for integrity. If - inname is NULL or an empty string, read from stdin. If outname is NULL or - an empty string, write to stdout. strm is a pre-initialized inflateBack - structure. When appropriate, copy the file attributes from inname to - outname. - - gunzip() returns 1 if there is an out-of-memory error or an unexpected - return code from gunpipe(). Otherwise it returns 0. - */ -local int gunzip(z_stream *strm, char *inname, char *outname, int test) -{ - int ret; - int infile, outfile; - - /* open files */ - if (inname == NULL || *inname == 0) { - inname = "-"; - infile = 0; /* stdin */ - } - else { - infile = open(inname, O_RDONLY, 0); - if (infile == -1) { - fprintf(stderr, "gun cannot open %s\n", inname); - return 0; - } - } - if (test) - outfile = -1; - else if (outname == NULL || *outname == 0) { - outname = "-"; - outfile = 1; /* stdout */ - } - else { - outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (outfile == -1) { - close(infile); - fprintf(stderr, "gun cannot create %s\n", outname); - return 0; - } - } - errno = 0; - - /* decompress */ - ret = gunpipe(strm, infile, outfile); - if (outfile > 2) close(outfile); - if (infile > 2) close(infile); - - /* interpret result */ - switch (ret) { - case Z_OK: - case Z_ERRNO: - if (infile > 2 && outfile > 2) { - copymeta(inname, outname); /* copy attributes */ - unlink(inname); - } - if (ret == Z_ERRNO) - fprintf(stderr, "gun warning: trailing garbage ignored in %s\n", - inname); - break; - case Z_DATA_ERROR: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg); - break; - case Z_MEM_ERROR: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun out of memory error--aborting\n"); - return 1; - case Z_BUF_ERROR: - if (outfile > 2) unlink(outname); - if (strm->next_in != Z_NULL) { - fprintf(stderr, "gun write error on %s: %s\n", - outname, strerror(errno)); - } - else if (errno) { - fprintf(stderr, "gun read error on %s: %s\n", - inname, strerror(errno)); - } - else { - fprintf(stderr, "gun unexpected end of file on %s\n", - inname); - } - break; - default: - if (outfile > 2) unlink(outname); - fprintf(stderr, "gun internal error--aborting\n"); - return 1; - } - return 0; -} - -/* Process the gun command line arguments. See the command syntax near the - beginning of this source file. */ -int main(int argc, char **argv) -{ - int ret, len, test; - char *outname; - unsigned char *window; - z_stream strm; - - /* initialize inflateBack state for repeated use */ - window = match; /* reuse LZW match buffer */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - ret = inflateBackInit(&strm, 15, window); - if (ret != Z_OK) { - fprintf(stderr, "gun out of memory error--aborting\n"); - return 1; - } - - /* decompress each file to the same name with the suffix removed */ - argc--; - argv++; - test = 0; - if (argc && strcmp(*argv, "-h") == 0) { - fprintf(stderr, "gun 1.6 (17 Jan 2010)\n"); - fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n"); - fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n"); - return 0; - } - if (argc && strcmp(*argv, "-t") == 0) { - test = 1; - argc--; - argv++; - } - if (argc) - do { - if (test) - outname = NULL; - else { - len = (int)strlen(*argv); - if (strcmp(*argv + len - 3, ".gz") == 0 || - strcmp(*argv + len - 3, "-gz") == 0) - len -= 3; - else if (strcmp(*argv + len - 2, ".z") == 0 || - strcmp(*argv + len - 2, "-z") == 0 || - strcmp(*argv + len - 2, "_z") == 0 || - strcmp(*argv + len - 2, ".Z") == 0) - len -= 2; - else { - fprintf(stderr, "gun error: no gz type on %s--skipping\n", - *argv); - continue; - } - outname = malloc(len + 1); - if (outname == NULL) { - fprintf(stderr, "gun out of memory error--aborting\n"); - ret = 1; - break; - } - memcpy(outname, *argv, len); - outname[len] = 0; - } - ret = gunzip(&strm, *argv, outname, test); - if (outname != NULL) free(outname); - if (ret) break; - } while (argv++, --argc); - else - ret = gunzip(&strm, NULL, NULL, test); - - /* clean up */ - inflateBackEnd(&strm); - return ret; -} diff --git a/src/contrib/zlib/examples/gzappend.c b/src/contrib/zlib/examples/gzappend.c deleted file mode 100644 index 662dec3..0000000 --- a/src/contrib/zlib/examples/gzappend.c +++ /dev/null @@ -1,504 +0,0 @@ -/* gzappend -- command to append to a gzip file - - Copyright (C) 2003, 2012 Mark Adler, all rights reserved - version 1.2, 11 Oct 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* - * Change history: - * - * 1.0 19 Oct 2003 - First version - * 1.1 4 Nov 2003 - Expand and clarify some comments and notes - * - Add version and copyright to help - * - Send help to stdout instead of stderr - * - Add some preemptive typecasts - * - Add L to constants in lseek() calls - * - Remove some debugging information in error messages - * - Use new data_type definition for zlib 1.2.1 - * - Simplfy and unify file operations - * - Finish off gzip file in gztack() - * - Use deflatePrime() instead of adding empty blocks - * - Keep gzip file clean on appended file read errors - * - Use in-place rotate instead of auxiliary buffer - * (Why you ask? Because it was fun to write!) - * 1.2 11 Oct 2012 - Fix for proper z_const usage - * - Check for input buffer malloc failure - */ - -/* - gzappend takes a gzip file and appends to it, compressing files from the - command line or data from stdin. The gzip file is written to directly, to - avoid copying that file, in case it's large. Note that this results in the - unfriendly behavior that if gzappend fails, the gzip file is corrupted. - - This program was written to illustrate the use of the new Z_BLOCK option of - zlib 1.2.x's inflate() function. This option returns from inflate() at each - block boundary to facilitate locating and modifying the last block bit at - the start of the final deflate block. Also whether using Z_BLOCK or not, - another required feature of zlib 1.2.x is that inflate() now provides the - number of unusued bits in the last input byte used. gzappend will not work - with versions of zlib earlier than 1.2.1. - - gzappend first decompresses the gzip file internally, discarding all but - the last 32K of uncompressed data, and noting the location of the last block - bit and the number of unused bits in the last byte of the compressed data. - The gzip trailer containing the CRC-32 and length of the uncompressed data - is verified. This trailer will be later overwritten. - - Then the last block bit is cleared by seeking back in the file and rewriting - the byte that contains it. Seeking forward, the last byte of the compressed - data is saved along with the number of unused bits to initialize deflate. - - A deflate process is initialized, using the last 32K of the uncompressed - data from the gzip file to initialize the dictionary. If the total - uncompressed data was less than 32K, then all of it is used to initialize - the dictionary. The deflate output bit buffer is also initialized with the - last bits from the original deflate stream. From here on, the data to - append is simply compressed using deflate, and written to the gzip file. - When that is complete, the new CRC-32 and uncompressed length are written - as the trailer of the gzip file. - */ - -#include -#include -#include -#include -#include -#include "zlib.h" - -#define local static -#define LGCHUNK 14 -#define CHUNK (1U << LGCHUNK) -#define DSIZE 32768U - -/* print an error message and terminate with extreme prejudice */ -local void bye(char *msg1, char *msg2) -{ - fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); - exit(1); -} - -/* return the greatest common divisor of a and b using Euclid's algorithm, - modified to be fast when one argument much greater than the other, and - coded to avoid unnecessary swapping */ -local unsigned gcd(unsigned a, unsigned b) -{ - unsigned c; - - while (a && b) - if (a > b) { - c = b; - while (a - c >= c) - c <<= 1; - a -= c; - } - else { - c = a; - while (b - c >= c) - c <<= 1; - b -= c; - } - return a + b; -} - -/* rotate list[0..len-1] left by rot positions, in place */ -local void rotate(unsigned char *list, unsigned len, unsigned rot) -{ - unsigned char tmp; - unsigned cycles; - unsigned char *start, *last, *to, *from; - - /* normalize rot and handle degenerate cases */ - if (len < 2) return; - if (rot >= len) rot %= len; - if (rot == 0) return; - - /* pointer to last entry in list */ - last = list + (len - 1); - - /* do simple left shift by one */ - if (rot == 1) { - tmp = *list; - memcpy(list, list + 1, len - 1); - *last = tmp; - return; - } - - /* do simple right shift by one */ - if (rot == len - 1) { - tmp = *last; - memmove(list + 1, list, len - 1); - *list = tmp; - return; - } - - /* otherwise do rotate as a set of cycles in place */ - cycles = gcd(len, rot); /* number of cycles */ - do { - start = from = list + cycles; /* start index is arbitrary */ - tmp = *from; /* save entry to be overwritten */ - for (;;) { - to = from; /* next step in cycle */ - from += rot; /* go right rot positions */ - if (from > last) from -= len; /* (pointer better not wrap) */ - if (from == start) break; /* all but one shifted */ - *to = *from; /* shift left */ - } - *to = tmp; /* complete the circle */ - } while (--cycles); -} - -/* structure for gzip file read operations */ -typedef struct { - int fd; /* file descriptor */ - int size; /* 1 << size is bytes in buf */ - unsigned left; /* bytes available at next */ - unsigned char *buf; /* buffer */ - z_const unsigned char *next; /* next byte in buffer */ - char *name; /* file name for error messages */ -} file; - -/* reload buffer */ -local int readin(file *in) -{ - int len; - - len = read(in->fd, in->buf, 1 << in->size); - if (len == -1) bye("error reading ", in->name); - in->left = (unsigned)len; - in->next = in->buf; - return len; -} - -/* read from file in, exit if end-of-file */ -local int readmore(file *in) -{ - if (readin(in) == 0) bye("unexpected end of ", in->name); - return 0; -} - -#define read1(in) (in->left == 0 ? readmore(in) : 0, \ - in->left--, *(in->next)++) - -/* skip over n bytes of in */ -local void skip(file *in, unsigned n) -{ - unsigned bypass; - - if (n > in->left) { - n -= in->left; - bypass = n & ~((1U << in->size) - 1); - if (bypass) { - if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) - bye("seeking ", in->name); - n -= bypass; - } - readmore(in); - if (n > in->left) - bye("unexpected end of ", in->name); - } - in->left -= n; - in->next += n; -} - -/* read a four-byte unsigned integer, little-endian, from in */ -unsigned long read4(file *in) -{ - unsigned long val; - - val = read1(in); - val += (unsigned)read1(in) << 8; - val += (unsigned long)read1(in) << 16; - val += (unsigned long)read1(in) << 24; - return val; -} - -/* skip over gzip header */ -local void gzheader(file *in) -{ - int flags; - unsigned n; - - if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); - if (read1(in) != 8) bye("unknown compression method in", in->name); - flags = read1(in); - if (flags & 0xe0) bye("unknown header flags set in", in->name); - skip(in, 6); - if (flags & 4) { - n = read1(in); - n += (unsigned)(read1(in)) << 8; - skip(in, n); - } - if (flags & 8) while (read1(in) != 0) ; - if (flags & 16) while (read1(in) != 0) ; - if (flags & 2) skip(in, 2); -} - -/* decompress gzip file "name", return strm with a deflate stream ready to - continue compression of the data in the gzip file, and return a file - descriptor pointing to where to write the compressed data -- the deflate - stream is initialized to compress using level "level" */ -local int gzscan(char *name, z_stream *strm, int level) -{ - int ret, lastbit, left, full; - unsigned have; - unsigned long crc, tot; - unsigned char *window; - off_t lastoff, end; - file gz; - - /* open gzip file */ - gz.name = name; - gz.fd = open(name, O_RDWR, 0); - if (gz.fd == -1) bye("cannot open ", name); - gz.buf = malloc(CHUNK); - if (gz.buf == NULL) bye("out of memory", ""); - gz.size = LGCHUNK; - gz.left = 0; - - /* skip gzip header */ - gzheader(&gz); - - /* prepare to decompress */ - window = malloc(DSIZE); - if (window == NULL) bye("out of memory", ""); - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = inflateInit2(strm, -15); - if (ret != Z_OK) bye("out of memory", " or library mismatch"); - - /* decompress the deflate stream, saving append information */ - lastbit = 0; - lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; - left = 0; - strm->avail_in = gz.left; - strm->next_in = gz.next; - crc = crc32(0L, Z_NULL, 0); - have = full = 0; - do { - /* if needed, get more input */ - if (strm->avail_in == 0) { - readmore(&gz); - strm->avail_in = gz.left; - strm->next_in = gz.next; - } - - /* set up output to next available section of sliding window */ - strm->avail_out = DSIZE - have; - strm->next_out = window + have; - - /* inflate and check for errors */ - ret = inflate(strm, Z_BLOCK); - if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); - if (ret == Z_MEM_ERROR) bye("out of memory", ""); - if (ret == Z_DATA_ERROR) - bye("invalid compressed data--format violated in", name); - - /* update crc and sliding window pointer */ - crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); - if (strm->avail_out) - have = DSIZE - strm->avail_out; - else { - have = 0; - full = 1; - } - - /* process end of block */ - if (strm->data_type & 128) { - if (strm->data_type & 64) - left = strm->data_type & 0x1f; - else { - lastbit = strm->data_type & 0x1f; - lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; - } - } - } while (ret != Z_STREAM_END); - inflateEnd(strm); - gz.left = strm->avail_in; - gz.next = strm->next_in; - - /* save the location of the end of the compressed data */ - end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; - - /* check gzip trailer and save total for deflate */ - if (crc != read4(&gz)) - bye("invalid compressed data--crc mismatch in ", name); - tot = strm->total_out; - if ((tot & 0xffffffffUL) != read4(&gz)) - bye("invalid compressed data--length mismatch in", name); - - /* if not at end of file, warn */ - if (gz.left || readin(&gz)) - fprintf(stderr, - "gzappend warning: junk at end of gzip file overwritten\n"); - - /* clear last block bit */ - lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); - if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); - *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); - lseek(gz.fd, -1L, SEEK_CUR); - if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); - - /* if window wrapped, build dictionary from window by rotating */ - if (full) { - rotate(window, DSIZE, have); - have = DSIZE; - } - - /* set up deflate stream with window, crc, total_in, and leftover bits */ - ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) bye("out of memory", ""); - deflateSetDictionary(strm, window, have); - strm->adler = crc; - strm->total_in = tot; - if (left) { - lseek(gz.fd, --end, SEEK_SET); - if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); - deflatePrime(strm, 8 - left, *gz.buf); - } - lseek(gz.fd, end, SEEK_SET); - - /* clean up and return */ - free(window); - free(gz.buf); - return gz.fd; -} - -/* append file "name" to gzip file gd using deflate stream strm -- if last - is true, then finish off the deflate stream at the end */ -local void gztack(char *name, int gd, z_stream *strm, int last) -{ - int fd, len, ret; - unsigned left; - unsigned char *in, *out; - - /* open file to compress and append */ - fd = 0; - if (name != NULL) { - fd = open(name, O_RDONLY, 0); - if (fd == -1) - fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", - name); - } - - /* allocate buffers */ - in = malloc(CHUNK); - out = malloc(CHUNK); - if (in == NULL || out == NULL) bye("out of memory", ""); - - /* compress input file and append to gzip file */ - do { - /* get more input */ - len = read(fd, in, CHUNK); - if (len == -1) { - fprintf(stderr, - "gzappend warning: error reading %s, skipping rest ...\n", - name); - len = 0; - } - strm->avail_in = (unsigned)len; - strm->next_in = in; - if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); - - /* compress and write all available output */ - do { - strm->avail_out = CHUNK; - strm->next_out = out; - ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); - left = CHUNK - strm->avail_out; - while (left) { - len = write(gd, out + CHUNK - strm->avail_out - left, left); - if (len == -1) bye("writing gzip file", ""); - left -= (unsigned)len; - } - } while (strm->avail_out == 0 && ret != Z_STREAM_END); - } while (len != 0); - - /* write trailer after last entry */ - if (last) { - deflateEnd(strm); - out[0] = (unsigned char)(strm->adler); - out[1] = (unsigned char)(strm->adler >> 8); - out[2] = (unsigned char)(strm->adler >> 16); - out[3] = (unsigned char)(strm->adler >> 24); - out[4] = (unsigned char)(strm->total_in); - out[5] = (unsigned char)(strm->total_in >> 8); - out[6] = (unsigned char)(strm->total_in >> 16); - out[7] = (unsigned char)(strm->total_in >> 24); - len = 8; - do { - ret = write(gd, out + 8 - len, len); - if (ret == -1) bye("writing gzip file", ""); - len -= ret; - } while (len); - close(gd); - } - - /* clean up and return */ - free(out); - free(in); - if (fd > 0) close(fd); -} - -/* process the compression level option if present, scan the gzip file, and - append the specified files, or append the data from stdin if no other file - names are provided on the command line -- the gzip file must be writable - and seekable */ -int main(int argc, char **argv) -{ - int gd, level; - z_stream strm; - - /* ignore command name */ - argc--; argv++; - - /* provide usage if no arguments */ - if (*argv == NULL) { - printf( - "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" - ); - printf( - "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); - return 0; - } - - /* set compression level */ - level = Z_DEFAULT_COMPRESSION; - if (argv[0][0] == '-') { - if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) - bye("invalid compression level", ""); - level = argv[0][1] - '0'; - if (*++argv == NULL) bye("no gzip file name after options", ""); - } - - /* prepare to append to gzip file */ - gd = gzscan(*argv++, &strm, level); - - /* append files on command line, or from stdin if none */ - if (*argv == NULL) - gztack(NULL, gd, &strm, 1); - else - do { - gztack(*argv, gd, &strm, argv[1] == NULL); - } while (*++argv != NULL); - return 0; -} diff --git a/src/contrib/zlib/examples/gzjoin.c b/src/contrib/zlib/examples/gzjoin.c deleted file mode 100644 index 89e8098..0000000 --- a/src/contrib/zlib/examples/gzjoin.c +++ /dev/null @@ -1,449 +0,0 @@ -/* gzjoin -- command to join gzip files into one gzip file - - Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved - version 1.2, 14 Aug 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* - * Change history: - * - * 1.0 11 Dec 2004 - First version - * 1.1 12 Jun 2005 - Changed ssize_t to long for portability - * 1.2 14 Aug 2012 - Clean up for z_const usage - */ - -/* - gzjoin takes one or more gzip files on the command line and writes out a - single gzip file that will uncompress to the concatenation of the - uncompressed data from the individual gzip files. gzjoin does this without - having to recompress any of the data and without having to calculate a new - crc32 for the concatenated uncompressed data. gzjoin does however have to - decompress all of the input data in order to find the bits in the compressed - data that need to be modified to concatenate the streams. - - gzjoin does not do an integrity check on the input gzip files other than - checking the gzip header and decompressing the compressed data. They are - otherwise assumed to be complete and correct. - - Each joint between gzip files removes at least 18 bytes of previous trailer - and subsequent header, and inserts an average of about three bytes to the - compressed data in order to connect the streams. The output gzip file - has a minimal ten-byte gzip header with no file name or modification time. - - This program was written to illustrate the use of the Z_BLOCK option of - inflate() and the crc32_combine() function. gzjoin will not compile with - versions of zlib earlier than 1.2.3. - */ - -#include /* fputs(), fprintf(), fwrite(), putc() */ -#include /* exit(), malloc(), free() */ -#include /* open() */ -#include /* close(), read(), lseek() */ -#include "zlib.h" - /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */ - -#define local static - -/* exit with an error (return a value to allow use in an expression) */ -local int bail(char *why1, char *why2) -{ - fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2); - exit(1); - return 0; -} - -/* -- simple buffered file input with access to the buffer -- */ - -#define CHUNK 32768 /* must be a power of two and fit in unsigned */ - -/* bin buffered input file type */ -typedef struct { - char *name; /* name of file for error messages */ - int fd; /* file descriptor */ - unsigned left; /* bytes remaining at next */ - unsigned char *next; /* next byte to read */ - unsigned char *buf; /* allocated buffer of length CHUNK */ -} bin; - -/* close a buffered file and free allocated memory */ -local void bclose(bin *in) -{ - if (in != NULL) { - if (in->fd != -1) - close(in->fd); - if (in->buf != NULL) - free(in->buf); - free(in); - } -} - -/* open a buffered file for input, return a pointer to type bin, or NULL on - failure */ -local bin *bopen(char *name) -{ - bin *in; - - in = malloc(sizeof(bin)); - if (in == NULL) - return NULL; - in->buf = malloc(CHUNK); - in->fd = open(name, O_RDONLY, 0); - if (in->buf == NULL || in->fd == -1) { - bclose(in); - return NULL; - } - in->left = 0; - in->next = in->buf; - in->name = name; - return in; -} - -/* load buffer from file, return -1 on read error, 0 or 1 on success, with - 1 indicating that end-of-file was reached */ -local int bload(bin *in) -{ - long len; - - if (in == NULL) - return -1; - if (in->left != 0) - return 0; - in->next = in->buf; - do { - len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left); - if (len < 0) - return -1; - in->left += (unsigned)len; - } while (len != 0 && in->left < CHUNK); - return len == 0 ? 1 : 0; -} - -/* get a byte from the file, bail if end of file */ -#define bget(in) (in->left ? 0 : bload(in), \ - in->left ? (in->left--, *(in->next)++) : \ - bail("unexpected end of file on ", in->name)) - -/* get a four-byte little-endian unsigned integer from file */ -local unsigned long bget4(bin *in) -{ - unsigned long val; - - val = bget(in); - val += (unsigned long)(bget(in)) << 8; - val += (unsigned long)(bget(in)) << 16; - val += (unsigned long)(bget(in)) << 24; - return val; -} - -/* skip bytes in file */ -local void bskip(bin *in, unsigned skip) -{ - /* check pointer */ - if (in == NULL) - return; - - /* easy case -- skip bytes in buffer */ - if (skip <= in->left) { - in->left -= skip; - in->next += skip; - return; - } - - /* skip what's in buffer, discard buffer contents */ - skip -= in->left; - in->left = 0; - - /* seek past multiples of CHUNK bytes */ - if (skip > CHUNK) { - unsigned left; - - left = skip & (CHUNK - 1); - if (left == 0) { - /* exact number of chunks: seek all the way minus one byte to check - for end-of-file with a read */ - lseek(in->fd, skip - 1, SEEK_CUR); - if (read(in->fd, in->buf, 1) != 1) - bail("unexpected end of file on ", in->name); - return; - } - - /* skip the integral chunks, update skip with remainder */ - lseek(in->fd, skip - left, SEEK_CUR); - skip = left; - } - - /* read more input and skip remainder */ - bload(in); - if (skip > in->left) - bail("unexpected end of file on ", in->name); - in->left -= skip; - in->next += skip; -} - -/* -- end of buffered input functions -- */ - -/* skip the gzip header from file in */ -local void gzhead(bin *in) -{ - int flags; - - /* verify gzip magic header and compression method */ - if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8) - bail(in->name, " is not a valid gzip file"); - - /* get and verify flags */ - flags = bget(in); - if ((flags & 0xe0) != 0) - bail("unknown reserved bits set in ", in->name); - - /* skip modification time, extra flags, and os */ - bskip(in, 6); - - /* skip extra field if present */ - if (flags & 4) { - unsigned len; - - len = bget(in); - len += (unsigned)(bget(in)) << 8; - bskip(in, len); - } - - /* skip file name if present */ - if (flags & 8) - while (bget(in) != 0) - ; - - /* skip comment if present */ - if (flags & 16) - while (bget(in) != 0) - ; - - /* skip header crc if present */ - if (flags & 2) - bskip(in, 2); -} - -/* write a four-byte little-endian unsigned integer to out */ -local void put4(unsigned long val, FILE *out) -{ - putc(val & 0xff, out); - putc((val >> 8) & 0xff, out); - putc((val >> 16) & 0xff, out); - putc((val >> 24) & 0xff, out); -} - -/* Load up zlib stream from buffered input, bail if end of file */ -local void zpull(z_streamp strm, bin *in) -{ - if (in->left == 0) - bload(in); - if (in->left == 0) - bail("unexpected end of file on ", in->name); - strm->avail_in = in->left; - strm->next_in = in->next; -} - -/* Write header for gzip file to out and initialize trailer. */ -local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out) -{ - fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out); - *crc = crc32(0L, Z_NULL, 0); - *tot = 0; -} - -/* Copy the compressed data from name, zeroing the last block bit of the last - block if clr is true, and adding empty blocks as needed to get to a byte - boundary. If clr is false, then the last block becomes the last block of - the output, and the gzip trailer is written. crc and tot maintains the - crc and length (modulo 2^32) of the output for the trailer. The resulting - gzip file is written to out. gzinit() must be called before the first call - of gzcopy() to write the gzip header and to initialize crc and tot. */ -local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, - FILE *out) -{ - int ret; /* return value from zlib functions */ - int pos; /* where the "last block" bit is in byte */ - int last; /* true if processing the last block */ - bin *in; /* buffered input file */ - unsigned char *start; /* start of compressed data in buffer */ - unsigned char *junk; /* buffer for uncompressed data -- discarded */ - z_off_t len; /* length of uncompressed data (support > 4 GB) */ - z_stream strm; /* zlib inflate stream */ - - /* open gzip file and skip header */ - in = bopen(name); - if (in == NULL) - bail("could not open ", name); - gzhead(in); - - /* allocate buffer for uncompressed data and initialize raw inflate - stream */ - junk = malloc(CHUNK); - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -15); - if (junk == NULL || ret != Z_OK) - bail("out of memory", ""); - - /* inflate and copy compressed data, clear last-block bit if requested */ - len = 0; - zpull(&strm, in); - start = in->next; - last = start[0] & 1; - if (last && clr) - start[0] &= ~1; - strm.avail_out = 0; - for (;;) { - /* if input used and output done, write used input and get more */ - if (strm.avail_in == 0 && strm.avail_out != 0) { - fwrite(start, 1, strm.next_in - start, out); - start = in->buf; - in->left = 0; - zpull(&strm, in); - } - - /* decompress -- return early when end-of-block reached */ - strm.avail_out = CHUNK; - strm.next_out = junk; - ret = inflate(&strm, Z_BLOCK); - switch (ret) { - case Z_MEM_ERROR: - bail("out of memory", ""); - case Z_DATA_ERROR: - bail("invalid compressed data in ", in->name); - } - - /* update length of uncompressed data */ - len += CHUNK - strm.avail_out; - - /* check for block boundary (only get this when block copied out) */ - if (strm.data_type & 128) { - /* if that was the last block, then done */ - if (last) - break; - - /* number of unused bits in last byte */ - pos = strm.data_type & 7; - - /* find the next last-block bit */ - if (pos != 0) { - /* next last-block bit is in last used byte */ - pos = 0x100 >> pos; - last = strm.next_in[-1] & pos; - if (last && clr) - in->buf[strm.next_in - in->buf - 1] &= ~pos; - } - else { - /* next last-block bit is in next unused byte */ - if (strm.avail_in == 0) { - /* don't have that byte yet -- get it */ - fwrite(start, 1, strm.next_in - start, out); - start = in->buf; - in->left = 0; - zpull(&strm, in); - } - last = strm.next_in[0] & 1; - if (last && clr) - in->buf[strm.next_in - in->buf] &= ~1; - } - } - } - - /* update buffer with unused input */ - in->left = strm.avail_in; - in->next = in->buf + (strm.next_in - in->buf); - - /* copy used input, write empty blocks to get to byte boundary */ - pos = strm.data_type & 7; - fwrite(start, 1, in->next - start - 1, out); - last = in->next[-1]; - if (pos == 0 || !clr) - /* already at byte boundary, or last file: write last byte */ - putc(last, out); - else { - /* append empty blocks to last byte */ - last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */ - if (pos & 1) { - /* odd -- append an empty stored block */ - putc(last, out); - if (pos == 1) - putc(0, out); /* two more bits in block header */ - fwrite("\0\0\xff\xff", 1, 4, out); - } - else { - /* even -- append 1, 2, or 3 empty fixed blocks */ - switch (pos) { - case 6: - putc(last | 8, out); - last = 0; - case 4: - putc(last | 0x20, out); - last = 0; - case 2: - putc(last | 0x80, out); - putc(0, out); - } - } - } - - /* update crc and tot */ - *crc = crc32_combine(*crc, bget4(in), len); - *tot += (unsigned long)len; - - /* clean up */ - inflateEnd(&strm); - free(junk); - bclose(in); - - /* write trailer if this is the last gzip file */ - if (!clr) { - put4(*crc, out); - put4(*tot, out); - } -} - -/* join the gzip files on the command line, write result to stdout */ -int main(int argc, char **argv) -{ - unsigned long crc, tot; /* running crc and total uncompressed length */ - - /* skip command name */ - argc--; - argv++; - - /* show usage if no arguments */ - if (argc == 0) { - fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n", - stderr); - return 0; - } - - /* join gzip files on command line and write to stdout */ - gzinit(&crc, &tot, stdout); - while (argc--) - gzcopy(*argv++, argc, &crc, &tot, stdout); - - /* done */ - return 0; -} diff --git a/src/contrib/zlib/examples/gzlog.c b/src/contrib/zlib/examples/gzlog.c deleted file mode 100644 index b8c2927..0000000 --- a/src/contrib/zlib/examples/gzlog.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * gzlog.c - * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved - * For conditions of distribution and use, see copyright notice in gzlog.h - * version 2.2, 14 Aug 2012 - */ - -/* - gzlog provides a mechanism for frequently appending short strings to a gzip - file that is efficient both in execution time and compression ratio. The - strategy is to write the short strings in an uncompressed form to the end of - the gzip file, only compressing when the amount of uncompressed data has - reached a given threshold. - - gzlog also provides protection against interruptions in the process due to - system crashes. The status of the operation is recorded in an extra field - in the gzip file, and is only updated once the gzip file is brought to a - valid state. The last data to be appended or compressed is saved in an - auxiliary file, so that if the operation is interrupted, it can be completed - the next time an append operation is attempted. - - gzlog maintains another auxiliary file with the last 32K of data from the - compressed portion, which is preloaded for the compression of the subsequent - data. This minimizes the impact to the compression ratio of appending. - */ - -/* - Operations Concept: - - Files (log name "foo"): - foo.gz -- gzip file with the complete log - foo.add -- last message to append or last data to compress - foo.dict -- dictionary of the last 32K of data for next compression - foo.temp -- temporary dictionary file for compression after this one - foo.lock -- lock file for reading and writing the other files - foo.repairs -- log file for log file recovery operations (not compressed) - - gzip file structure: - - fixed-length (no file name) header with extra field (see below) - - compressed data ending initially with empty stored block - - uncompressed data filling out originally empty stored block and - subsequent stored blocks as needed (16K max each) - - gzip trailer - - no junk at end (no other gzip streams) - - When appending data, the information in the first three items above plus the - foo.add file are sufficient to recover an interrupted append operation. The - extra field has the necessary information to restore the start of the last - stored block and determine where to append the data in the foo.add file, as - well as the crc and length of the gzip data before the append operation. - - The foo.add file is created before the gzip file is marked for append, and - deleted after the gzip file is marked as complete. So if the append - operation is interrupted, the data to add will still be there. If due to - some external force, the foo.add file gets deleted between when the append - operation was interrupted and when recovery is attempted, the gzip file will - still be restored, but without the appended data. - - When compressing data, the information in the first two items above plus the - foo.add file are sufficient to recover an interrupted compress operation. - The extra field has the necessary information to find the end of the - compressed data, and contains both the crc and length of just the compressed - data and of the complete set of data including the contents of the foo.add - file. - - Again, the foo.add file is maintained during the compress operation in case - of an interruption. If in the unlikely event the foo.add file with the data - to be compressed is missing due to some external force, a gzip file with - just the previous compressed data will be reconstructed. In this case, all - of the data that was to be compressed is lost (approximately one megabyte). - This will not occur if all that happened was an interruption of the compress - operation. - - The third state that is marked is the replacement of the old dictionary with - the new dictionary after a compress operation. Once compression is - complete, the gzip file is marked as being in the replace state. This - completes the gzip file, so an interrupt after being so marked does not - result in recompression. Then the dictionary file is replaced, and the gzip - file is marked as completed. This state prevents the possibility of - restarting compression with the wrong dictionary file. - - All three operations are wrapped by a lock/unlock procedure. In order to - gain exclusive access to the log files, first a foo.lock file must be - exclusively created. When all operations are complete, the lock is - released by deleting the foo.lock file. If when attempting to create the - lock file, it already exists and the modify time of the lock file is more - than five minutes old (set by the PATIENCE define below), then the old - lock file is considered stale and deleted, and the exclusive creation of - the lock file is retried. To assure that there are no false assessments - of the staleness of the lock file, the operations periodically touch the - lock file to update the modified date. - - Following is the definition of the extra field with all of the information - required to enable the above append and compress operations and their - recovery if interrupted. Multi-byte values are stored little endian - (consistent with the gzip format). File pointers are eight bytes long. - The crc's and lengths for the gzip trailer are four bytes long. (Note that - the length at the end of a gzip file is used for error checking only, and - for large files is actually the length modulo 2^32.) The stored block - length is two bytes long. The gzip extra field two-byte identification is - "ap" for append. It is assumed that writing the extra field to the file is - an "atomic" operation. That is, either all of the extra field is written - to the file, or none of it is, if the operation is interrupted right at the - point of updating the extra field. This is a reasonable assumption, since - the extra field is within the first 52 bytes of the file, which is smaller - than any expected block size for a mass storage device (usually 512 bytes or - larger). - - Extra field (35 bytes): - - Pointer to first stored block length -- this points to the two-byte length - of the first stored block, which is followed by the two-byte, one's - complement of that length. The stored block length is preceded by the - three-bit header of the stored block, which is the actual start of the - stored block in the deflate format. See the bit offset field below. - - Pointer to the last stored block length. This is the same as above, but - for the last stored block of the uncompressed data in the gzip file. - Initially this is the same as the first stored block length pointer. - When the stored block gets to 16K (see the MAX_STORE define), then a new - stored block as added, at which point the last stored block length pointer - is different from the first stored block length pointer. When they are - different, the first bit of the last stored block header is eight bits, or - one byte back from the block length. - - Compressed data crc and length. This is the crc and length of the data - that is in the compressed portion of the deflate stream. These are used - only in the event that the foo.add file containing the data to compress is - lost after a compress operation is interrupted. - - Total data crc and length. This is the crc and length of all of the data - stored in the gzip file, compressed and uncompressed. It is used to - reconstruct the gzip trailer when compressing, as well as when recovering - interrupted operations. - - Final stored block length. This is used to quickly find where to append, - and allows the restoration of the original final stored block state when - an append operation is interrupted. - - First stored block start as the number of bits back from the final stored - block first length byte. This value is in the range of 3..10, and is - stored as the low three bits of the final byte of the extra field after - subtracting three (0..7). This allows the last-block bit of the stored - block header to be updated when a new stored block is added, for the case - when the first stored block and the last stored block are the same. (When - they are different, the numbers of bits back is known to be eight.) This - also allows for new compressed data to be appended to the old compressed - data in the compress operation, overwriting the previous first stored - block, or for the compressed data to be terminated and a valid gzip file - reconstructed on the off chance that a compression operation was - interrupted and the data to compress in the foo.add file was deleted. - - The operation in process. This is the next two bits in the last byte (the - bits under the mask 0x18). The are interpreted as 0: nothing in process, - 1: append in process, 2: compress in process, 3: replace in process. - - The top three bits of the last byte in the extra field are reserved and - are currently set to zero. - - Main procedure: - - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of - the system open() call. If the modify time of an existing lock file is - more than PATIENCE seconds old, then the lock file is deleted and the - exclusive create is retried. - - Load the extra field from the foo.gz file, and see if an operation was in - progress but not completed. If so, apply the recovery procedure below. - - Perform the append procedure with the provided data. - - If the uncompressed data in the foo.gz file is 1MB or more, apply the - compress procedure. - - Delete the foo.lock file. - - Append procedure: - - Put what to append in the foo.add file so that the operation can be - restarted if this procedure is interrupted. - - Mark the foo.gz extra field with the append operation in progress. - + Restore the original last-block bit and stored block length of the last - stored block from the information in the extra field, in case a previous - append operation was interrupted. - - Append the provided data to the last stored block, creating new stored - blocks as needed and updating the stored blocks last-block bits and - lengths. - - Update the crc and length with the new data, and write the gzip trailer. - - Write over the extra field (with a single write operation) with the new - pointers, lengths, and crc's, and mark the gzip file as not in process. - Though there is still a foo.add file, it will be ignored since nothing - is in process. If a foo.add file is leftover from a previously - completed operation, it is truncated when writing new data to it. - - Delete the foo.add file. - - Compress and replace procedures: - - Read all of the uncompressed data in the stored blocks in foo.gz and write - it to foo.add. Also write foo.temp with the last 32K of that data to - provide a dictionary for the next invocation of this procedure. - - Rewrite the extra field marking foo.gz with a compression in process. - * If there is no data provided to compress (due to a missing foo.add file - when recovering), reconstruct and truncate the foo.gz file to contain - only the previous compressed data and proceed to the step after the next - one. Otherwise ... - - Compress the data with the dictionary in foo.dict, and write to the - foo.gz file starting at the bit immediately following the last previously - compressed block. If there is no foo.dict, proceed anyway with the - compression at slightly reduced efficiency. (For the foo.dict file to be - missing requires some external failure beyond simply the interruption of - a compress operation.) During this process, the foo.lock file is - periodically touched to assure that that file is not considered stale by - another process before we're done. The deflation is terminated with a - non-last empty static block (10 bits long), that is then located and - written over by a last-bit-set empty stored block. - - Append the crc and length of the data in the gzip file (previously - calculated during the append operations). - - Write over the extra field with the updated stored block offsets, bits - back, crc's, and lengths, and mark foo.gz as in process for a replacement - of the dictionary. - @ Delete the foo.add file. - - Replace foo.dict with foo.temp. - - Write over the extra field, marking foo.gz as complete. - - Recovery procedure: - - If not a replace recovery, read in the foo.add file, and provide that data - to the appropriate recovery below. If there is no foo.add file, provide - a zero data length to the recovery. In that case, the append recovery - restores the foo.gz to the previous compressed + uncompressed data state. - For the the compress recovery, a missing foo.add file results in foo.gz - being restored to the previous compressed-only data state. - - Append recovery: - - Pick up append at + step above - - Compress recovery: - - Pick up compress at * step above - - Replace recovery: - - Pick up compress at @ step above - - Log the repair with a date stamp in foo.repairs - */ - -#include -#include /* rename, fopen, fprintf, fclose */ -#include /* malloc, free */ -#include /* strlen, strrchr, strcpy, strncpy, strcmp */ -#include /* open */ -#include /* lseek, read, write, close, unlink, sleep, */ - /* ftruncate, fsync */ -#include /* errno */ -#include /* time, ctime */ -#include /* stat */ -#include /* utimes */ -#include "zlib.h" /* crc32 */ - -#include "gzlog.h" /* header for external access */ - -#define local static -typedef unsigned int uint; -typedef unsigned long ulong; - -/* Macro for debugging to deterministically force recovery operations */ -#ifdef GZLOG_DEBUG - #include /* longjmp */ - jmp_buf gzlog_jump; /* where to go back to */ - int gzlog_bail = 0; /* which point to bail at (1..8) */ - int gzlog_count = -1; /* number of times through to wait */ -# define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ - longjmp(gzlog_jump, gzlog_bail); } while (0) -#else -# define BAIL(n) -#endif - -/* how old the lock file can be in seconds before considering it stale */ -#define PATIENCE 300 - -/* maximum stored block size in Kbytes -- must be in 1..63 */ -#define MAX_STORE 16 - -/* number of stored Kbytes to trigger compression (must be >= 32 to allow - dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to - discard the stored block headers contribution of five bytes each) */ -#define TRIGGER 1024 - -/* size of a deflate dictionary (this cannot be changed) */ -#define DICT 32768U - -/* values for the operation (2 bits) */ -#define NO_OP 0 -#define APPEND_OP 1 -#define COMPRESS_OP 2 -#define REPLACE_OP 3 - -/* macros to extract little-endian integers from an unsigned byte buffer */ -#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) -#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) -#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) - -/* macros to store integers into a byte buffer in little-endian order */ -#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) -#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) -#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) - -/* internal structure for log information */ -#define LOGID "\106\035\172" /* should be three non-zero characters */ -struct log { - char id[4]; /* contains LOGID to detect inadvertent overwrites */ - int fd; /* file descriptor for .gz file, opened read/write */ - char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ - char *end; /* end of path, for appending suffices such as ".gz" */ - off_t first; /* offset of first stored block first length byte */ - int back; /* location of first block id in bits back from first */ - uint stored; /* bytes currently in last stored block */ - off_t last; /* offset of last stored block first length byte */ - ulong ccrc; /* crc of compressed data */ - ulong clen; /* length (modulo 2^32) of compressed data */ - ulong tcrc; /* crc of total data */ - ulong tlen; /* length (modulo 2^32) of total data */ - time_t lock; /* last modify time of our lock file */ -}; - -/* gzip header for gzlog */ -local unsigned char log_gzhead[] = { - 0x1f, 0x8b, /* magic gzip id */ - 8, /* compression method is deflate */ - 4, /* there is an extra field (no file name) */ - 0, 0, 0, 0, /* no modification time provided */ - 0, 0xff, /* no extra flags, no OS specified */ - 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ - /* 35 is EXTRA, 39 is EXTRA + 4 */ -}; - -#define HEAD sizeof(log_gzhead) /* should be 16 */ - -/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ -local unsigned char log_gzext[] = { - 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ - 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ - 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ - 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ - 0, 0, /* final stored block data length */ - 5 /* op is NO_OP, last bit 8 bits back */ -}; - -#define EXTRA sizeof(log_gzext) /* should be 35 */ - -/* initial gzip data and trailer */ -local unsigned char log_gzbody[] = { - 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ - 0, 0, 0, 0, /* crc */ - 0, 0, 0, 0 /* uncompressed length */ -}; - -#define BODY sizeof(log_gzbody) - -/* Exclusively create foo.lock in order to negotiate exclusive access to the - foo.* files. If the modify time of an existing lock file is greater than - PATIENCE seconds in the past, then consider the lock file to have been - abandoned, delete it, and try the exclusive create again. Save the lock - file modify time for verification of ownership. Return 0 on success, or -1 - on failure, usually due to an access restriction or invalid path. Note that - if stat() or unlink() fails, it may be due to another process noticing the - abandoned lock file a smidge sooner and deleting it, so those are not - flagged as an error. */ -local int log_lock(struct log *log) -{ - int fd; - struct stat st; - - strcpy(log->end, ".lock"); - while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { - if (errno != EEXIST) - return -1; - if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { - unlink(log->path); - continue; - } - sleep(2); /* relinquish the CPU for two seconds while waiting */ - } - close(fd); - if (stat(log->path, &st) == 0) - log->lock = st.st_mtime; - return 0; -} - -/* Update the modify time of the lock file to now, in order to prevent another - task from thinking that the lock is stale. Save the lock file modify time - for verification of ownership. */ -local void log_touch(struct log *log) -{ - struct stat st; - - strcpy(log->end, ".lock"); - utimes(log->path, NULL); - if (stat(log->path, &st) == 0) - log->lock = st.st_mtime; -} - -/* Check the log file modify time against what is expected. Return true if - this is not our lock. If it is our lock, touch it to keep it. */ -local int log_check(struct log *log) -{ - struct stat st; - - strcpy(log->end, ".lock"); - if (stat(log->path, &st) || st.st_mtime != log->lock) - return 1; - log_touch(log); - return 0; -} - -/* Unlock a previously acquired lock, but only if it's ours. */ -local void log_unlock(struct log *log) -{ - if (log_check(log)) - return; - strcpy(log->end, ".lock"); - unlink(log->path); - log->lock = 0; -} - -/* Check the gzip header and read in the extra field, filling in the values in - the log structure. Return op on success or -1 if the gzip header was not as - expected. op is the current operation in progress last written to the extra - field. This assumes that the gzip file has already been opened, with the - file descriptor log->fd. */ -local int log_head(struct log *log) -{ - int op; - unsigned char buf[HEAD + EXTRA]; - - if (lseek(log->fd, 0, SEEK_SET) < 0 || - read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || - memcmp(buf, log_gzhead, HEAD)) { - return -1; - } - log->first = PULL8(buf + HEAD); - log->last = PULL8(buf + HEAD + 8); - log->ccrc = PULL4(buf + HEAD + 16); - log->clen = PULL4(buf + HEAD + 20); - log->tcrc = PULL4(buf + HEAD + 24); - log->tlen = PULL4(buf + HEAD + 28); - log->stored = PULL2(buf + HEAD + 32); - log->back = 3 + (buf[HEAD + 34] & 7); - op = (buf[HEAD + 34] >> 3) & 3; - return op; -} - -/* Write over the extra field contents, marking the operation as op. Use fsync - to assure that the device is written to, and in the requested order. This - operation, and only this operation, is assumed to be atomic in order to - assure that the log is recoverable in the event of an interruption at any - point in the process. Return -1 if the write to foo.gz failed. */ -local int log_mark(struct log *log, int op) -{ - int ret; - unsigned char ext[EXTRA]; - - PUT8(ext, log->first); - PUT8(ext + 8, log->last); - PUT4(ext + 16, log->ccrc); - PUT4(ext + 20, log->clen); - PUT4(ext + 24, log->tcrc); - PUT4(ext + 28, log->tlen); - PUT2(ext + 32, log->stored); - ext[34] = log->back - 3 + (op << 3); - fsync(log->fd); - ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || - write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; - fsync(log->fd); - return ret; -} - -/* Rewrite the last block header bits and subsequent zero bits to get to a byte - boundary, setting the last block bit if last is true, and then write the - remainder of the stored block header (length and one's complement). Leave - the file pointer after the end of the last stored block data. Return -1 if - there is a read or write failure on the foo.gz file */ -local int log_last(struct log *log, int last) -{ - int back, len, mask; - unsigned char buf[6]; - - /* determine the locations of the bytes and bits to modify */ - back = log->last == log->first ? log->back : 8; - len = back > 8 ? 2 : 1; /* bytes back from log->last */ - mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ - - /* get the byte to modify (one or two back) into buf[0] -- don't need to - read the byte if the last-bit is eight bits back, since in that case - the entire byte will be modified */ - buf[0] = 0; - if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || - read(log->fd, buf, 1) != 1)) - return -1; - - /* change the last-bit of the last stored block as requested -- note - that all bits above the last-bit are set to zero, per the type bits - of a stored block being 00 and per the convention that the bits to - bring the stream to a byte boundary are also zeros */ - buf[1] = 0; - buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); - - /* write the modified stored block header and lengths, move the file - pointer to after the last stored block data */ - PUT2(buf + 2, log->stored); - PUT2(buf + 4, log->stored ^ 0xffff); - return lseek(log->fd, log->last - len, SEEK_SET) < 0 || - write(log->fd, buf + 2 - len, len + 4) != len + 4 || - lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; -} - -/* Append len bytes from data to the locked and open log file. len may be zero - if recovering and no .add file was found. In that case, the previous state - of the foo.gz file is restored. The data is appended uncompressed in - deflate stored blocks. Return -1 if there was an error reading or writing - the foo.gz file. */ -local int log_append(struct log *log, unsigned char *data, size_t len) -{ - uint put; - off_t end; - unsigned char buf[8]; - - /* set the last block last-bit and length, in case recovering an - interrupted append, then position the file pointer to append to the - block */ - if (log_last(log, 1)) - return -1; - - /* append, adding stored blocks and updating the offset of the last stored - block as needed, and update the total crc and length */ - while (len) { - /* append as much as we can to the last block */ - put = (MAX_STORE << 10) - log->stored; - if (put > len) - put = (uint)len; - if (put) { - if (write(log->fd, data, put) != put) - return -1; - BAIL(1); - log->tcrc = crc32(log->tcrc, data, put); - log->tlen += put; - log->stored += put; - data += put; - len -= put; - } - - /* if we need to, add a new empty stored block */ - if (len) { - /* mark current block as not last */ - if (log_last(log, 0)) - return -1; - - /* point to new, empty stored block */ - log->last += 4 + log->stored + 1; - log->stored = 0; - } - - /* mark last block as last, update its length */ - if (log_last(log, 1)) - return -1; - BAIL(2); - } - - /* write the new crc and length trailer, and truncate just in case (could - be recovering from partial append with a missing foo.add file) */ - PUT4(buf, log->tcrc); - PUT4(buf + 4, log->tlen); - if (write(log->fd, buf, 8) != 8 || - (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) - return -1; - - /* write the extra field, marking the log file as done, delete .add file */ - if (log_mark(log, NO_OP)) - return -1; - strcpy(log->end, ".add"); - unlink(log->path); /* ignore error, since may not exist */ - return 0; -} - -/* Replace the foo.dict file with the foo.temp file. Also delete the foo.add - file, since the compress operation may have been interrupted before that was - done. Returns 1 if memory could not be allocated, or -1 if reading or - writing foo.gz fails, or if the rename fails for some reason other than - foo.temp not existing. foo.temp not existing is a permitted error, since - the replace operation may have been interrupted after the rename is done, - but before foo.gz is marked as complete. */ -local int log_replace(struct log *log) -{ - int ret; - char *dest; - - /* delete foo.add file */ - strcpy(log->end, ".add"); - unlink(log->path); /* ignore error, since may not exist */ - BAIL(3); - - /* rename foo.name to foo.dict, replacing foo.dict if it exists */ - strcpy(log->end, ".dict"); - dest = malloc(strlen(log->path) + 1); - if (dest == NULL) - return -2; - strcpy(dest, log->path); - strcpy(log->end, ".temp"); - ret = rename(log->path, dest); - free(dest); - if (ret && errno != ENOENT) - return -1; - BAIL(4); - - /* mark the foo.gz file as done */ - return log_mark(log, NO_OP); -} - -/* Compress the len bytes at data and append the compressed data to the - foo.gz deflate data immediately after the previous compressed data. This - overwrites the previous uncompressed data, which was stored in foo.add - and is the data provided in data[0..len-1]. If this operation is - interrupted, it picks up at the start of this routine, with the foo.add - file read in again. If there is no data to compress (len == 0), then we - simply terminate the foo.gz file after the previously compressed data, - appending a final empty stored block and the gzip trailer. Return -1 if - reading or writing the log.gz file failed, or -2 if there was a memory - allocation failure. */ -local int log_compress(struct log *log, unsigned char *data, size_t len) -{ - int fd; - uint got, max; - ssize_t dict; - off_t end; - z_stream strm; - unsigned char buf[DICT]; - - /* compress and append compressed data */ - if (len) { - /* set up for deflate, allocating memory */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, - Z_DEFAULT_STRATEGY) != Z_OK) - return -2; - - /* read in dictionary (last 32K of data that was compressed) */ - strcpy(log->end, ".dict"); - fd = open(log->path, O_RDONLY, 0); - if (fd >= 0) { - dict = read(fd, buf, DICT); - close(fd); - if (dict < 0) { - deflateEnd(&strm); - return -1; - } - if (dict) - deflateSetDictionary(&strm, buf, (uint)dict); - } - log_touch(log); - - /* prime deflate with last bits of previous block, position write - pointer to write those bits and overwrite what follows */ - if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), - SEEK_SET) < 0 || - read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { - deflateEnd(&strm); - return -1; - } - deflatePrime(&strm, (8 - log->back) & 7, *buf); - - /* compress, finishing with a partial non-last empty static block */ - strm.next_in = data; - max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ - do { - strm.avail_in = len > max ? max : (uint)len; - len -= strm.avail_in; - do { - strm.avail_out = DICT; - strm.next_out = buf; - deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); - got = DICT - strm.avail_out; - if (got && write(log->fd, buf, got) != got) { - deflateEnd(&strm); - return -1; - } - log_touch(log); - } while (strm.avail_out == 0); - } while (len); - deflateEnd(&strm); - BAIL(5); - - /* find start of empty static block -- scanning backwards the first one - bit is the second bit of the block, if the last byte is zero, then - we know the byte before that has a one in the top bit, since an - empty static block is ten bits long */ - if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || - read(log->fd, buf, 1) != 1) - return -1; - log->first++; - if (*buf) { - log->back = 1; - while ((*buf & ((uint)1 << (8 - log->back++))) == 0) - ; /* guaranteed to terminate, since *buf != 0 */ - } - else - log->back = 10; - - /* update compressed crc and length */ - log->ccrc = log->tcrc; - log->clen = log->tlen; - } - else { - /* no data to compress -- fix up existing gzip stream */ - log->tcrc = log->ccrc; - log->tlen = log->clen; - } - - /* complete and truncate gzip stream */ - log->last = log->first; - log->stored = 0; - PUT4(buf, log->tcrc); - PUT4(buf + 4, log->tlen); - if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || - (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) - return -1; - BAIL(6); - - /* mark as being in the replace operation */ - if (log_mark(log, REPLACE_OP)) - return -1; - - /* execute the replace operation and mark the file as done */ - return log_replace(log); -} - -/* log a repair record to the .repairs file */ -local void log_log(struct log *log, int op, char *record) -{ - time_t now; - FILE *rec; - - now = time(NULL); - strcpy(log->end, ".repairs"); - rec = fopen(log->path, "a"); - if (rec == NULL) - return; - fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? - "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); - fclose(rec); - return; -} - -/* Recover the interrupted operation op. First read foo.add for recovering an - append or compress operation. Return -1 if there was an error reading or - writing foo.gz or reading an existing foo.add, or -2 if there was a memory - allocation failure. */ -local int log_recover(struct log *log, int op) -{ - int fd, ret = 0; - unsigned char *data = NULL; - size_t len = 0; - struct stat st; - - /* log recovery */ - log_log(log, op, "start"); - - /* load foo.add file if expected and present */ - if (op == APPEND_OP || op == COMPRESS_OP) { - strcpy(log->end, ".add"); - if (stat(log->path, &st) == 0 && st.st_size) { - len = (size_t)(st.st_size); - if ((off_t)len != st.st_size || - (data = malloc(st.st_size)) == NULL) { - log_log(log, op, "allocation failure"); - return -2; - } - if ((fd = open(log->path, O_RDONLY, 0)) < 0) { - log_log(log, op, ".add file read failure"); - return -1; - } - ret = (size_t)read(fd, data, len) != len; - close(fd); - if (ret) { - log_log(log, op, ".add file read failure"); - return -1; - } - log_log(log, op, "loaded .add file"); - } - else - log_log(log, op, "missing .add file!"); - } - - /* recover the interrupted operation */ - switch (op) { - case APPEND_OP: - ret = log_append(log, data, len); - break; - case COMPRESS_OP: - ret = log_compress(log, data, len); - break; - case REPLACE_OP: - ret = log_replace(log); - } - - /* log status */ - log_log(log, op, ret ? "failure" : "complete"); - - /* clean up */ - if (data != NULL) - free(data); - return ret; -} - -/* Close the foo.gz file (if open) and release the lock. */ -local void log_close(struct log *log) -{ - if (log->fd >= 0) - close(log->fd); - log->fd = -1; - log_unlock(log); -} - -/* Open foo.gz, verify the header, and load the extra field contents, after - first creating the foo.lock file to gain exclusive access to the foo.* - files. If foo.gz does not exist or is empty, then write the initial header, - extra, and body content of an empty foo.gz log file. If there is an error - creating the lock file due to access restrictions, or an error reading or - writing the foo.gz file, or if the foo.gz file is not a proper log file for - this object (e.g. not a gzip file or does not contain the expected extra - field), then return true. If there is an error, the lock is released. - Otherwise, the lock is left in place. */ -local int log_open(struct log *log) -{ - int op; - - /* release open file resource if left over -- can occur if lock lost - between gzlog_open() and gzlog_write() */ - if (log->fd >= 0) - close(log->fd); - log->fd = -1; - - /* negotiate exclusive access */ - if (log_lock(log) < 0) - return -1; - - /* open the log file, foo.gz */ - strcpy(log->end, ".gz"); - log->fd = open(log->path, O_RDWR | O_CREAT, 0644); - if (log->fd < 0) { - log_close(log); - return -1; - } - - /* if new, initialize foo.gz with an empty log, delete old dictionary */ - if (lseek(log->fd, 0, SEEK_END) == 0) { - if (write(log->fd, log_gzhead, HEAD) != HEAD || - write(log->fd, log_gzext, EXTRA) != EXTRA || - write(log->fd, log_gzbody, BODY) != BODY) { - log_close(log); - return -1; - } - strcpy(log->end, ".dict"); - unlink(log->path); - } - - /* verify log file and load extra field information */ - if ((op = log_head(log)) < 0) { - log_close(log); - return -1; - } - - /* check for interrupted process and if so, recover */ - if (op != NO_OP && log_recover(log, op)) { - log_close(log); - return -1; - } - - /* touch the lock file to prevent another process from grabbing it */ - log_touch(log); - return 0; -} - -/* See gzlog.h for the description of the external methods below */ -gzlog *gzlog_open(char *path) -{ - size_t n; - struct log *log; - - /* check arguments */ - if (path == NULL || *path == 0) - return NULL; - - /* allocate and initialize log structure */ - log = malloc(sizeof(struct log)); - if (log == NULL) - return NULL; - strcpy(log->id, LOGID); - log->fd = -1; - - /* save path and end of path for name construction */ - n = strlen(path); - log->path = malloc(n + 9); /* allow for ".repairs" */ - if (log->path == NULL) { - free(log); - return NULL; - } - strcpy(log->path, path); - log->end = log->path + n; - - /* gain exclusive access and verify log file -- may perform a - recovery operation if needed */ - if (log_open(log)) { - free(log->path); - free(log); - return NULL; - } - - /* return pointer to log structure */ - return log; -} - -/* gzlog_compress() return values: - 0: all good - -1: file i/o error (usually access issue) - -2: memory allocation failure - -3: invalid log pointer argument */ -int gzlog_compress(gzlog *logd) -{ - int fd, ret; - uint block; - size_t len, next; - unsigned char *data, buf[5]; - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - - /* see if we lost the lock -- if so get it again and reload the extra - field information (it probably changed), recover last operation if - necessary */ - if (log_check(log) && log_open(log)) - return -1; - - /* create space for uncompressed data */ - len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + - log->stored; - if ((data = malloc(len)) == NULL) - return -2; - - /* do statement here is just a cheap trick for error handling */ - do { - /* read in the uncompressed data */ - if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) - break; - next = 0; - while (next < len) { - if (read(log->fd, buf, 5) != 5) - break; - block = PULL2(buf + 1); - if (next + block > len || - read(log->fd, (char *)data + next, block) != block) - break; - next += block; - } - if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) - break; - log_touch(log); - - /* write the uncompressed data to the .add file */ - strcpy(log->end, ".add"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - break; - ret = (size_t)write(fd, data, len) != len; - if (ret | close(fd)) - break; - log_touch(log); - - /* write the dictionary for the next compress to the .temp file */ - strcpy(log->end, ".temp"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - break; - next = DICT > len ? len : DICT; - ret = (size_t)write(fd, (char *)data + len - next, next) != next; - if (ret | close(fd)) - break; - log_touch(log); - - /* roll back to compressed data, mark the compress in progress */ - log->last = log->first; - log->stored = 0; - if (log_mark(log, COMPRESS_OP)) - break; - BAIL(7); - - /* compress and append the data (clears mark) */ - ret = log_compress(log, data, len); - free(data); - return ret; - } while (0); - - /* broke out of do above on i/o error */ - free(data); - return -1; -} - -/* gzlog_write() return values: - 0: all good - -1: file i/o error (usually access issue) - -2: memory allocation failure - -3: invalid log pointer argument */ -int gzlog_write(gzlog *logd, void *data, size_t len) -{ - int fd, ret; - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - if (data == NULL || len <= 0) - return 0; - - /* see if we lost the lock -- if so get it again and reload the extra - field information (it probably changed), recover last operation if - necessary */ - if (log_check(log) && log_open(log)) - return -1; - - /* create and write .add file */ - strcpy(log->end, ".add"); - fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd < 0) - return -1; - ret = (size_t)write(fd, data, len) != len; - if (ret | close(fd)) - return -1; - log_touch(log); - - /* mark log file with append in progress */ - if (log_mark(log, APPEND_OP)) - return -1; - BAIL(8); - - /* append data (clears mark) */ - if (log_append(log, data, len)) - return -1; - - /* check to see if it's time to compress -- if not, then done */ - if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) - return 0; - - /* time to compress */ - return gzlog_compress(log); -} - -/* gzlog_close() return values: - 0: ok - -3: invalid log pointer argument */ -int gzlog_close(gzlog *logd) -{ - struct log *log = logd; - - /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID)) - return -3; - - /* close the log file and release the lock */ - log_close(log); - - /* free structure and return */ - if (log->path != NULL) - free(log->path); - strcpy(log->id, "bad"); - free(log); - return 0; -} diff --git a/src/contrib/zlib/examples/gzlog.h b/src/contrib/zlib/examples/gzlog.h deleted file mode 100644 index 86f0cec..0000000 --- a/src/contrib/zlib/examples/gzlog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* gzlog.h - Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved - version 2.2, 14 Aug 2012 - - This software is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Mark Adler madler@alumni.caltech.edu - */ - -/* Version History: - 1.0 26 Nov 2004 First version - 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations - Interface changed slightly in that now path is a prefix - Compression now occurs as needed during gzlog_write() - gzlog_write() now always leaves the log file as valid gzip - 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() - 2.2 14 Aug 2012 Clean up signed comparisons - */ - -/* - The gzlog object allows writing short messages to a gzipped log file, - opening the log file locked for small bursts, and then closing it. The log - object works by appending stored (uncompressed) data to the gzip file until - 1 MB has been accumulated. At that time, the stored data is compressed, and - replaces the uncompressed data in the file. The log file is truncated to - its new size at that time. After each write operation, the log file is a - valid gzip file that can decompressed to recover what was written. - - The gzlog operations can be interupted at any point due to an application or - system crash, and the log file will be recovered the next time the log is - opened with gzlog_open(). - */ - -#ifndef GZLOG_H -#define GZLOG_H - -/* gzlog object type */ -typedef void gzlog; - -/* Open a gzlog object, creating the log file if it does not exist. Return - NULL on error. Note that gzlog_open() could take a while to complete if it - has to wait to verify that a lock is stale (possibly for five minutes), or - if there is significant contention with other instantiations of this object - when locking the resource. path is the prefix of the file names created by - this object. If path is "foo", then the log file will be "foo.gz", and - other auxiliary files will be created and destroyed during the process: - "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) - dictionary, "foo.add" for data being added or compressed, "foo.lock" for the - lock file, and "foo.repairs" to log recovery operations performed due to - interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() - will recover a previously interrupted operation, if any. */ -gzlog *gzlog_open(char *path); - -/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o - error on any of the gzlog files (this should not happen if gzlog_open() - succeeded, unless the device has run out of space or leftover auxiliary - files have permissions or ownership that prevent their use), -2 if there is - a memory allocation failure, or -3 if the log argument is invalid (e.g. if - it was not created by gzlog_open()). This function will write data to the - file uncompressed, until 1 MB has been accumulated, at which time that data - will be compressed. The log file will be a valid gzip file upon successful - return. */ -int gzlog_write(gzlog *log, void *data, size_t len); - -/* Force compression of any uncompressed data in the log. This should be used - sparingly, if at all. The main application would be when a log file will - not be appended to again. If this is used to compress frequently while - appending, it will both significantly increase the execution time and - reduce the compression ratio. The return codes are the same as for - gzlog_write(). */ -int gzlog_compress(gzlog *log); - -/* Close a gzlog object. Return zero on success, -3 if the log argument is - invalid. The log object is freed, and so cannot be referenced again. */ -int gzlog_close(gzlog *log); - -#endif diff --git a/src/contrib/zlib/examples/zlib_how.html b/src/contrib/zlib/examples/zlib_how.html deleted file mode 100644 index 444ff1c..0000000 --- a/src/contrib/zlib/examples/zlib_how.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - -zlib Usage Example - - - -

zlib Usage Example

-We often get questions about how the deflate() and inflate() functions should be used. -Users wonder when they should provide more input, when they should use more output, -what to do with a Z_BUF_ERROR, how to make sure the process terminates properly, and -so on. So for those who have read zlib.h (a few times), and -would like further edification, below is an annotated example in C of simple routines to compress and decompress -from an input file to an output file using deflate() and inflate() respectively. The -annotations are interspersed between lines of the code. So please read between the lines. -We hope this helps explain some of the intricacies of zlib. -

-Without further adieu, here is the program zpipe.c: -


-/* zpipe.c: example of proper use of zlib's inflate() and deflate()
-   Not copyrighted -- provided to the public domain
-   Version 1.4  11 December 2005  Mark Adler */
-
-/* Version history:
-   1.0  30 Oct 2004  First version
-   1.1   8 Nov 2004  Add void casting for unused return values
-                     Use switch statement for inflate() return values
-   1.2   9 Nov 2004  Add assertions to document zlib guarantees
-   1.3   6 Apr 2005  Remove incorrect assertion in inf()
-   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
-                     Avoid some compiler warnings for input and output buffers
- */
-
-We now include the header files for the required definitions. From -stdio.h we use fopen(), fread(), fwrite(), -feof(), ferror(), and fclose() for file i/o, and -fputs() for error messages. From string.h we use -strcmp() for command line argument processing. -From assert.h we use the assert() macro. -From zlib.h -we use the basic compression functions deflateInit(), -deflate(), and deflateEnd(), and the basic decompression -functions inflateInit(), inflate(), and -inflateEnd(). -

-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "zlib.h"
-
-This is an ugly hack required to avoid corruption of the input and output data on -Windows/MS-DOS systems. Without this, those systems would assume that the input and output -files are text, and try to convert the end-of-line characters from one standard to -another. That would corrupt binary data, and in particular would render the compressed data unusable. -This sets the input and output to binary which suppresses the end-of-line conversions. -SET_BINARY_MODE() will be used later on stdin and stdout, at the beginning of main(). -

-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-#  include <fcntl.h>
-#  include <io.h>
-#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-#  define SET_BINARY_MODE(file)
-#endif
-
-CHUNK is simply the buffer size for feeding data to and pulling data -from the zlib routines. Larger buffer sizes would be more efficient, -especially for inflate(). If the memory is available, buffers sizes -on the order of 128K or 256K bytes should be used. -

-#define CHUNK 16384
-
-The def() routine compresses data from an input file to an output file. The output data -will be in the zlib format, which is different from the gzip or zip -formats. The zlib format has a very small header of only two bytes to identify it as -a zlib stream and to provide decoding information, and a four-byte trailer with a fast -check value to verify the integrity of the uncompressed data after decoding. -

-/* Compress from file source to file dest until EOF on source.
-   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_STREAM_ERROR if an invalid compression
-   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
-   version of the library linked do not match, or Z_ERRNO if there is
-   an error reading or writing the files. */
-int def(FILE *source, FILE *dest, int level)
-{
-
-Here are the local variables for def(). ret will be used for zlib -return codes. flush will keep track of the current flushing state for deflate(), -which is either no flushing, or flush to completion after the end of the input file is reached. -have is the amount of data returned from deflate(). The strm structure -is used to pass information to and from the zlib routines, and to maintain the -deflate() state. in and out are the input and output buffers for -deflate(). -

-    int ret, flush;
-    unsigned have;
-    z_stream strm;
-    unsigned char in[CHUNK];
-    unsigned char out[CHUNK];
-
-The first thing we do is to initialize the zlib state for compression using -deflateInit(). This must be done before the first use of deflate(). -The zalloc, zfree, and opaque fields in the strm -structure must be initialized before calling deflateInit(). Here they are -set to the zlib constant Z_NULL to request that zlib use -the default memory allocation routines. An application may also choose to provide -custom memory allocation routines here. deflateInit() will allocate on the -order of 256K bytes for the internal state. -(See zlib Technical Details.) -

-deflateInit() is called with a pointer to the structure to be initialized and -the compression level, which is an integer in the range of -1 to 9. Lower compression -levels result in faster execution, but less compression. Higher levels result in -greater compression, but slower execution. The zlib constant Z_DEFAULT_COMPRESSION, -equal to -1, -provides a good compromise between compression and speed and is equivalent to level 6. -Level 0 actually does no compression at all, and in fact expands the data slightly to produce -the zlib format (it is not a byte-for-byte copy of the input). -More advanced applications of zlib -may use deflateInit2() here instead. Such an application may want to reduce how -much memory will be used, at some price in compression. Or it may need to request a -gzip header and trailer instead of a zlib header and trailer, or raw -encoding with no header or trailer at all. -

-We must check the return value of deflateInit() against the zlib constant -Z_OK to make sure that it was able to -allocate memory for the internal state, and that the provided arguments were valid. -deflateInit() will also check that the version of zlib that the zlib.h -file came from matches the version of zlib actually linked with the program. This -is especially important for environments in which zlib is a shared library. -

-Note that an application can initialize multiple, independent zlib streams, which can -operate in parallel. The state information maintained in the structure allows the zlib -routines to be reentrant. -


-    /* allocate deflate state */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    ret = deflateInit(&strm, level);
-    if (ret != Z_OK)
-        return ret;
-
-With the pleasantries out of the way, now we can get down to business. The outer do-loop -reads all of the input file and exits at the bottom of the loop once end-of-file is reached. -This loop contains the only call of deflate(). So we must make sure that all of the -input data has been processed and that all of the output data has been generated and consumed -before we fall out of the loop at the bottom. -

-    /* compress until end of file */
-    do {
-
-We start off by reading data from the input file. The number of bytes read is put directly -into avail_in, and a pointer to those bytes is put into next_in. We also -check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the -zlib constant Z_FINISH, which is later passed to deflate() to -indicate that this is the last chunk of input data to compress. We need to use feof() -to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The -reason is that if the input file length is an exact multiple of CHUNK, we will miss -the fact that we got to the end-of-file, and not know to tell deflate() to finish -up the compressed stream. If we are not yet at the end of the input, then the zlib -constant Z_NO_FLUSH will be passed to deflate to indicate that we are still -in the middle of the uncompressed data. -

-If there is an error in reading from the input file, the process is aborted with -deflateEnd() being called to free the allocated zlib state before returning -the error. We wouldn't want a memory leak, now would we? deflateEnd() can be called -at any time after the state has been initialized. Once that's done, deflateInit() (or -deflateInit2()) would have to be called to start a new compression process. There is -no point here in checking the deflateEnd() return code. The deallocation can't fail. -


-        strm.avail_in = fread(in, 1, CHUNK, source);
-        if (ferror(source)) {
-            (void)deflateEnd(&strm);
-            return Z_ERRNO;
-        }
-        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
-        strm.next_in = in;
-
-The inner do-loop passes our chunk of input data to deflate(), and then -keeps calling deflate() until it is done producing output. Once there is no more -new output, deflate() is guaranteed to have consumed all of the input, i.e., -avail_in will be zero. -

-        /* run deflate() on input until output buffer not full, finish
-           compression if all of source has been read in */
-        do {
-
-Output space is provided to deflate() by setting avail_out to the number -of available output bytes and next_out to a pointer to that space. -

-            strm.avail_out = CHUNK;
-            strm.next_out = out;
-
-Now we call the compression engine itself, deflate(). It takes as many of the -avail_in bytes at next_in as it can process, and writes as many as -avail_out bytes to next_out. Those counters and pointers are then -updated past the input data consumed and the output data written. It is the amount of -output space available that may limit how much input is consumed. -Hence the inner loop to make sure that -all of the input is consumed by providing more output space each time. Since avail_in -and next_in are updated by deflate(), we don't have to mess with those -between deflate() calls until it's all used up. -

-The parameters to deflate() are a pointer to the strm structure containing -the input and output information and the internal compression engine state, and a parameter -indicating whether and how to flush data to the output. Normally deflate will consume -several K bytes of input data before producing any output (except for the header), in order -to accumulate statistics on the data for optimum compression. It will then put out a burst of -compressed data, and proceed to consume more input before the next burst. Eventually, -deflate() -must be told to terminate the stream, complete the compression with provided input data, and -write out the trailer check value. deflate() will continue to compress normally as long -as the flush parameter is Z_NO_FLUSH. Once the Z_FINISH parameter is provided, -deflate() will begin to complete the compressed output stream. However depending on how -much output space is provided, deflate() may have to be called several times until it -has provided the complete compressed stream, even after it has consumed all of the input. The flush -parameter must continue to be Z_FINISH for those subsequent calls. -

-There are other values of the flush parameter that are used in more advanced applications. You can -force deflate() to produce a burst of output that encodes all of the input data provided -so far, even if it wouldn't have otherwise, for example to control data latency on a link with -compressed data. You can also ask that deflate() do that as well as erase any history up to -that point so that what follows can be decompressed independently, for example for random access -applications. Both requests will degrade compression by an amount depending on how often such -requests are made. -

-deflate() has a return value that can indicate errors, yet we do not check it here. Why -not? Well, it turns out that deflate() can do no wrong here. Let's go through -deflate()'s return values and dispense with them one by one. The possible values are -Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR. Z_OK -is, well, ok. Z_STREAM_END is also ok and will be returned for the last call of -deflate(). This is already guaranteed by calling deflate() with Z_FINISH -until it has no more output. Z_STREAM_ERROR is only possible if the stream is not -initialized properly, but we did initialize it properly. There is no harm in checking for -Z_STREAM_ERROR here, for example to check for the possibility that some -other part of the application inadvertently clobbered the memory containing the zlib state. -Z_BUF_ERROR will be explained further below, but -suffice it to say that this is simply an indication that deflate() could not consume -more input or produce more output. deflate() can be called again with more output space -or more available input, which it will be in this code. -


-            ret = deflate(&strm, flush);    /* no bad return value */
-            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-
-Now we compute how much output deflate() provided on the last call, which is the -difference between how much space was provided before the call, and how much output space -is still available after the call. Then that data, if any, is written to the output file. -We can then reuse the output buffer for the next call of deflate(). Again if there -is a file i/o error, we call deflateEnd() before returning to avoid a memory leak. -

-            have = CHUNK - strm.avail_out;
-            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
-                (void)deflateEnd(&strm);
-                return Z_ERRNO;
-            }
-
-The inner do-loop is repeated until the last deflate() call fails to fill the -provided output buffer. Then we know that deflate() has done as much as it can with -the provided input, and that all of that input has been consumed. We can then fall out of this -loop and reuse the input buffer. -

-The way we tell that deflate() has no more output is by seeing that it did not fill -the output buffer, leaving avail_out greater than zero. However suppose that -deflate() has no more output, but just so happened to exactly fill the output buffer! -avail_out is zero, and we can't tell that deflate() has done all it can. -As far as we know, deflate() -has more output for us. So we call it again. But now deflate() produces no output -at all, and avail_out remains unchanged as CHUNK. That deflate() call -wasn't able to do anything, either consume input or produce output, and so it returns -Z_BUF_ERROR. (See, I told you I'd cover this later.) However this is not a problem at -all. Now we finally have the desired indication that deflate() is really done, -and so we drop out of the inner loop to provide more input to deflate(). -

-With flush set to Z_FINISH, this final set of deflate() calls will -complete the output stream. Once that is done, subsequent calls of deflate() would return -Z_STREAM_ERROR if the flush parameter is not Z_FINISH, and do no more processing -until the state is reinitialized. -

-Some applications of zlib have two loops that call deflate() -instead of the single inner loop we have here. The first loop would call -without flushing and feed all of the data to deflate(). The second loop would call -deflate() with no more -data and the Z_FINISH parameter to complete the process. As you can see from this -example, that can be avoided by simply keeping track of the current flush state. -


-        } while (strm.avail_out == 0);
-        assert(strm.avail_in == 0);     /* all input will be used */
-
-Now we check to see if we have already processed all of the input file. That information was -saved in the flush variable, so we see if that was set to Z_FINISH. If so, -then we're done and we fall out of the outer loop. We're guaranteed to get Z_STREAM_END -from the last deflate() call, since we ran it until the last chunk of input was -consumed and all of the output was generated. -

-        /* done when last data in file processed */
-    } while (flush != Z_FINISH);
-    assert(ret == Z_STREAM_END);        /* stream will be complete */
-
-The process is complete, but we still need to deallocate the state to avoid a memory leak -(or rather more like a memory hemorrhage if you didn't do this). Then -finally we can return with a happy return value. -

-    /* clean up and return */
-    (void)deflateEnd(&strm);
-    return Z_OK;
-}
-
-Now we do the same thing for decompression in the inf() routine. inf() -decompresses what is hopefully a valid zlib stream from the input file and writes the -uncompressed data to the output file. Much of the discussion above for def() -applies to inf() as well, so the discussion here will focus on the differences between -the two. -

-/* Decompress from file source to file dest until stream ends or EOF.
-   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
-   allocated for processing, Z_DATA_ERROR if the deflate data is
-   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
-   the version of the library linked do not match, or Z_ERRNO if there
-   is an error reading or writing the files. */
-int inf(FILE *source, FILE *dest)
-{
-
-The local variables have the same functionality as they do for def(). The -only difference is that there is no flush variable, since inflate() -can tell from the zlib stream itself when the stream is complete. -

-    int ret;
-    unsigned have;
-    z_stream strm;
-    unsigned char in[CHUNK];
-    unsigned char out[CHUNK];
-
-The initialization of the state is the same, except that there is no compression level, -of course, and two more elements of the structure are initialized. avail_in -and next_in must be initialized before calling inflateInit(). This -is because the application has the option to provide the start of the zlib stream in -order for inflateInit() to have access to information about the compression -method to aid in memory allocation. In the current implementation of zlib -(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of -inflate() anyway. However those fields must be initialized since later versions -of zlib that provide more compression methods may take advantage of this interface. -In any case, no decompression is performed by inflateInit(), so the -avail_out and next_out fields do not need to be initialized before calling. -

-Here avail_in is set to zero and next_in is set to Z_NULL to -indicate that no input data is being provided. -


-    /* allocate inflate state */
-    strm.zalloc = Z_NULL;
-    strm.zfree = Z_NULL;
-    strm.opaque = Z_NULL;
-    strm.avail_in = 0;
-    strm.next_in = Z_NULL;
-    ret = inflateInit(&strm);
-    if (ret != Z_OK)
-        return ret;
-
-The outer do-loop decompresses input until inflate() indicates -that it has reached the end of the compressed data and has produced all of the uncompressed -output. This is in contrast to def() which processes all of the input file. -If end-of-file is reached before the compressed data self-terminates, then the compressed -data is incomplete and an error is returned. -

-    /* decompress until deflate stream ends or end of file */
-    do {
-
-We read input data and set the strm structure accordingly. If we've reached the -end of the input file, then we leave the outer loop and report an error, since the -compressed data is incomplete. Note that we may read more data than is eventually consumed -by inflate(), if the input file continues past the zlib stream. -For applications where zlib streams are embedded in other data, this routine would -need to be modified to return the unused data, or at least indicate how much of the input -data was not used, so the application would know where to pick up after the zlib stream. -

-        strm.avail_in = fread(in, 1, CHUNK, source);
-        if (ferror(source)) {
-            (void)inflateEnd(&strm);
-            return Z_ERRNO;
-        }
-        if (strm.avail_in == 0)
-            break;
-        strm.next_in = in;
-
-The inner do-loop has the same function it did in def(), which is to -keep calling inflate() until has generated all of the output it can with the -provided input. -

-        /* run inflate() on input until output buffer not full */
-        do {
-
-Just like in def(), the same output space is provided for each call of inflate(). -

-            strm.avail_out = CHUNK;
-            strm.next_out = out;
-
-Now we run the decompression engine itself. There is no need to adjust the flush parameter, since -the zlib format is self-terminating. The main difference here is that there are -return values that we need to pay attention to. Z_DATA_ERROR -indicates that inflate() detected an error in the zlib compressed data format, -which means that either the data is not a zlib stream to begin with, or that the data was -corrupted somewhere along the way since it was compressed. The other error to be processed is -Z_MEM_ERROR, which can occur since memory allocation is deferred until inflate() -needs it, unlike deflate(), whose memory is allocated at the start by deflateInit(). -

-Advanced applications may use -deflateSetDictionary() to prime deflate() with a set of likely data to improve the -first 32K or so of compression. This is noted in the zlib header, so inflate() -requests that that dictionary be provided before it can start to decompress. Without the dictionary, -correct decompression is not possible. For this routine, we have no idea what the dictionary is, -so the Z_NEED_DICT indication is converted to a Z_DATA_ERROR. -

-inflate() can also return Z_STREAM_ERROR, which should not be possible here, -but could be checked for as noted above for def(). Z_BUF_ERROR does not need to be -checked for here, for the same reasons noted for def(). Z_STREAM_END will be -checked for later. -


-            ret = inflate(&strm, Z_NO_FLUSH);
-            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
-            switch (ret) {
-            case Z_NEED_DICT:
-                ret = Z_DATA_ERROR;     /* and fall through */
-            case Z_DATA_ERROR:
-            case Z_MEM_ERROR:
-                (void)inflateEnd(&strm);
-                return ret;
-            }
-
-The output of inflate() is handled identically to that of deflate(). -

-            have = CHUNK - strm.avail_out;
-            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
-                (void)inflateEnd(&strm);
-                return Z_ERRNO;
-            }
-
-The inner do-loop ends when inflate() has no more output as indicated -by not filling the output buffer, just as for deflate(). In this case, we cannot -assert that strm.avail_in will be zero, since the deflate stream may end before the file -does. -

-        } while (strm.avail_out == 0);
-
-The outer do-loop ends when inflate() reports that it has reached the -end of the input zlib stream, has completed the decompression and integrity -check, and has provided all of the output. This is indicated by the inflate() -return value Z_STREAM_END. The inner loop is guaranteed to leave ret -equal to Z_STREAM_END if the last chunk of the input file read contained the end -of the zlib stream. So if the return value is not Z_STREAM_END, the -loop continues to read more input. -

-        /* done when inflate() says it's done */
-    } while (ret != Z_STREAM_END);
-
-At this point, decompression successfully completed, or we broke out of the loop due to no -more data being available from the input file. If the last inflate() return value -is not Z_STREAM_END, then the zlib stream was incomplete and a data error -is returned. Otherwise, we return with a happy return value. Of course, inflateEnd() -is called first to avoid a memory leak. -

-    /* clean up and return */
-    (void)inflateEnd(&strm);
-    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
-}
-
-That ends the routines that directly use zlib. The following routines make this -a command-line program by running data through the above routines from stdin to -stdout, and handling any errors reported by def() or inf(). -

-zerr() is used to interpret the possible error codes from def() -and inf(), as detailed in their comments above, and print out an error message. -Note that these are only a subset of the possible return values from deflate() -and inflate(). -


-/* report a zlib or i/o error */
-void zerr(int ret)
-{
-    fputs("zpipe: ", stderr);
-    switch (ret) {
-    case Z_ERRNO:
-        if (ferror(stdin))
-            fputs("error reading stdin\n", stderr);
-        if (ferror(stdout))
-            fputs("error writing stdout\n", stderr);
-        break;
-    case Z_STREAM_ERROR:
-        fputs("invalid compression level\n", stderr);
-        break;
-    case Z_DATA_ERROR:
-        fputs("invalid or incomplete deflate data\n", stderr);
-        break;
-    case Z_MEM_ERROR:
-        fputs("out of memory\n", stderr);
-        break;
-    case Z_VERSION_ERROR:
-        fputs("zlib version mismatch!\n", stderr);
-    }
-}
-
-Here is the main() routine used to test def() and inf(). The -zpipe command is simply a compression pipe from stdin to stdout, if -no arguments are given, or it is a decompression pipe if zpipe -d is used. If any other -arguments are provided, no compression or decompression is performed. Instead a usage -message is displayed. Examples are zpipe < foo.txt > foo.txt.z to compress, and -zpipe -d < foo.txt.z > foo.txt to decompress. -

-/* compress or decompress from stdin to stdout */
-int main(int argc, char **argv)
-{
-    int ret;
-
-    /* avoid end-of-line conversions */
-    SET_BINARY_MODE(stdin);
-    SET_BINARY_MODE(stdout);
-
-    /* do compression if no arguments */
-    if (argc == 1) {
-        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
-        if (ret != Z_OK)
-            zerr(ret);
-        return ret;
-    }
-
-    /* do decompression if -d specified */
-    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
-        ret = inf(stdin, stdout);
-        if (ret != Z_OK)
-            zerr(ret);
-        return ret;
-    }
-
-    /* otherwise, report usage */
-    else {
-        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
-        return 1;
-    }
-}
-
-
-Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
- - diff --git a/src/contrib/zlib/examples/zpipe.c b/src/contrib/zlib/examples/zpipe.c deleted file mode 100644 index 83535d1..0000000 --- a/src/contrib/zlib/examples/zpipe.c +++ /dev/null @@ -1,205 +0,0 @@ -/* zpipe.c: example of proper use of zlib's inflate() and deflate() - Not copyrighted -- provided to the public domain - Version 1.4 11 December 2005 Mark Adler */ - -/* Version history: - 1.0 30 Oct 2004 First version - 1.1 8 Nov 2004 Add void casting for unused return values - Use switch statement for inflate() return values - 1.2 9 Nov 2004 Add assertions to document zlib guarantees - 1.3 6 Apr 2005 Remove incorrect assertion in inf() - 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions - Avoid some compiler warnings for input and output buffers - */ - -#include -#include -#include -#include "zlib.h" - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#define CHUNK 16384 - -/* Compress from file source to file dest until EOF on source. - def() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_STREAM_ERROR if an invalid compression - level is supplied, Z_VERSION_ERROR if the version of zlib.h and the - version of the library linked do not match, or Z_ERRNO if there is - an error reading or writing the files. */ -int def(FILE *source, FILE *dest, int level) -{ - int ret, flush; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate deflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - ret = deflateInit(&strm, level); - if (ret != Z_OK) - return ret; - - /* compress until end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; - strm.next_in = in; - - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)deflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - assert(strm.avail_in == 0); /* all input will be used */ - - /* done when last data in file processed */ - } while (flush != Z_FINISH); - assert(ret == Z_STREAM_END); /* stream will be complete */ - - /* clean up and return */ - (void)deflateEnd(&strm); - return Z_OK; -} - -/* Decompress from file source to file dest until stream ends or EOF. - inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be - allocated for processing, Z_DATA_ERROR if the deflate data is - invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and - the version of the library linked do not match, or Z_ERRNO if there - is an error reading or writing the files. */ -int inf(FILE *source, FILE *dest) -{ - int ret; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; - - /* decompress until deflate stream ends or end of file */ - do { - strm.avail_in = fread(in, 1, CHUNK, source); - if (ferror(source)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - if (strm.avail_in == 0) - break; - strm.next_in = in; - - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - have = CHUNK - strm.avail_out; - if (fwrite(out, 1, have, dest) != have || ferror(dest)) { - (void)inflateEnd(&strm); - return Z_ERRNO; - } - } while (strm.avail_out == 0); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END); - - /* clean up and return */ - (void)inflateEnd(&strm); - return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; -} - -/* report a zlib or i/o error */ -void zerr(int ret) -{ - fputs("zpipe: ", stderr); - switch (ret) { - case Z_ERRNO: - if (ferror(stdin)) - fputs("error reading stdin\n", stderr); - if (ferror(stdout)) - fputs("error writing stdout\n", stderr); - break; - case Z_STREAM_ERROR: - fputs("invalid compression level\n", stderr); - break; - case Z_DATA_ERROR: - fputs("invalid or incomplete deflate data\n", stderr); - break; - case Z_MEM_ERROR: - fputs("out of memory\n", stderr); - break; - case Z_VERSION_ERROR: - fputs("zlib version mismatch!\n", stderr); - } -} - -/* compress or decompress from stdin to stdout */ -int main(int argc, char **argv) -{ - int ret; - - /* avoid end-of-line conversions */ - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - - /* do compression if no arguments */ - if (argc == 1) { - ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); - if (ret != Z_OK) - zerr(ret); - return ret; - } - - /* do decompression if -d specified */ - else if (argc == 2 && strcmp(argv[1], "-d") == 0) { - ret = inf(stdin, stdout); - if (ret != Z_OK) - zerr(ret); - return ret; - } - - /* otherwise, report usage */ - else { - fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); - return 1; - } -} diff --git a/src/contrib/zlib/examples/zran.c b/src/contrib/zlib/examples/zran.c deleted file mode 100644 index 4fec659..0000000 --- a/src/contrib/zlib/examples/zran.c +++ /dev/null @@ -1,409 +0,0 @@ -/* zran.c -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005, 2012 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.1 29 Sep 2012 Mark Adler */ - -/* Version History: - 1.0 29 May 2005 First version - 1.1 29 Sep 2012 Fix memory reallocation error - */ - -/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() - for random access of a compressed file. A file containing a zlib or gzip - stream is provided on the command line. The compressed stream is decoded in - its entirety, and an index built with access points about every SPAN bytes - in the uncompressed output. The compressed file is left open, and can then - be read randomly, having to decompress on the average SPAN/2 uncompressed - bytes before getting to the desired block of data. - - An access point can be created at the start of any deflate block, by saving - the starting file offset and bit of that block, and the 32K bytes of - uncompressed data that precede that block. Also the uncompressed offset of - that block is saved to provide a referece for locating a desired starting - point in the uncompressed stream. build_index() works by decompressing the - input zlib or gzip stream a block at a time, and at the end of each block - deciding if enough uncompressed data has gone by to justify the creation of - a new access point. If so, that point is saved in a data structure that - grows as needed to accommodate the points. - - To use the index, an offset in the uncompressed data is provided, for which - the latest access point at or preceding that offset is located in the index. - The input file is positioned to the specified location in the index, and if - necessary the first few bits of the compressed data is read from the file. - inflate is initialized with those bits and the 32K of uncompressed data, and - the decompression then proceeds until the desired offset in the file is - reached. Then the decompression continues to read the desired uncompressed - data from the file. - - Another approach would be to generate the index on demand. In that case, - requests for random access reads from the compressed data would try to use - the index, but if a read far enough past the end of the index is required, - then further index entries would be generated and added. - - There is some fair bit of overhead to starting inflation for the random - access, mainly copying the 32K byte dictionary. So if small pieces of the - file are being accessed, it would make sense to implement a cache to hold - some lookahead and avoid many calls to extract() for small lengths. - - Another way to build an index would be to use inflateCopy(). That would - not be constrained to have access points at block boundaries, but requires - more memory per access point, and also cannot be saved to file due to the - use of pointers in the state. The approach here allows for storage of the - index in a file. - */ - -#include -#include -#include -#include "zlib.h" - -#define local static - -#define SPAN 1048576L /* desired distance between access points */ -#define WINSIZE 32768U /* sliding window size */ -#define CHUNK 16384 /* file input buffer size */ - -/* access point entry */ -struct point { - off_t out; /* corresponding offset in uncompressed data */ - off_t in; /* offset in input file of first full byte */ - int bits; /* number of bits (1-7) from byte at in - 1, or 0 */ - unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ -}; - -/* access point list */ -struct access { - int have; /* number of list entries filled in */ - int size; /* number of list entries allocated */ - struct point *list; /* allocated list */ -}; - -/* Deallocate an index built by build_index() */ -local void free_index(struct access *index) -{ - if (index != NULL) { - free(index->list); - free(index); - } -} - -/* Add an entry to the access point list. If out of memory, deallocate the - existing list and return NULL. */ -local struct access *addpoint(struct access *index, int bits, - off_t in, off_t out, unsigned left, unsigned char *window) -{ - struct point *next; - - /* if list is empty, create it (start with eight points) */ - if (index == NULL) { - index = malloc(sizeof(struct access)); - if (index == NULL) return NULL; - index->list = malloc(sizeof(struct point) << 3); - if (index->list == NULL) { - free(index); - return NULL; - } - index->size = 8; - index->have = 0; - } - - /* if list is full, make it bigger */ - else if (index->have == index->size) { - index->size <<= 1; - next = realloc(index->list, sizeof(struct point) * index->size); - if (next == NULL) { - free_index(index); - return NULL; - } - index->list = next; - } - - /* fill in entry and increment how many we have */ - next = index->list + index->have; - next->bits = bits; - next->in = in; - next->out = out; - if (left) - memcpy(next->window, window + WINSIZE - left, left); - if (left < WINSIZE) - memcpy(next->window + left, window, WINSIZE - left); - index->have++; - - /* return list, possibly reallocated */ - return index; -} - -/* Make one entire pass through the compressed stream and build an index, with - access points about every span bytes of uncompressed output -- span is - chosen to balance the speed of random access against the memory requirements - of the list, about 32K bytes per access point. Note that data after the end - of the first zlib or gzip stream in the file is ignored. build_index() - returns the number of access points on success (>= 1), Z_MEM_ERROR for out - of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a - file read error. On success, *built points to the resulting index. */ -local int build_index(FILE *in, off_t span, struct access **built) -{ - int ret; - off_t totin, totout; /* our own total counters to avoid 4GB limit */ - off_t last; /* totout value of last access point */ - struct access *index; /* access points being generated */ - z_stream strm; - unsigned char input[CHUNK]; - unsigned char window[WINSIZE]; - - /* initialize inflate */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ - if (ret != Z_OK) - return ret; - - /* inflate the input, maintain a sliding window, and build an index -- this - also validates the integrity of the compressed data using the check - information at the end of the gzip or zlib stream */ - totin = totout = last = 0; - index = NULL; /* will be allocated by first addpoint() */ - strm.avail_out = 0; - do { - /* get some compressed data from input file */ - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto build_index_error; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto build_index_error; - } - strm.next_in = input; - - /* process all of that, or until end of stream */ - do { - /* reset sliding window if necessary */ - if (strm.avail_out == 0) { - strm.avail_out = WINSIZE; - strm.next_out = window; - } - - /* inflate until out of input, output, or at end of block -- - update the total input and output counters */ - totin += strm.avail_in; - totout += strm.avail_out; - ret = inflate(&strm, Z_BLOCK); /* return at end of block */ - totin -= strm.avail_in; - totout -= strm.avail_out; - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto build_index_error; - if (ret == Z_STREAM_END) - break; - - /* if at end of block, consider adding an index entry (note that if - data_type indicates an end-of-block, then all of the - uncompressed data from that block has been delivered, and none - of the compressed data after that block has been consumed, - except for up to seven bits) -- the totout == 0 provides an - entry point after the zlib or gzip header, and assures that the - index always has at least one access point; we avoid creating an - access point after the last block by checking bit 6 of data_type - */ - if ((strm.data_type & 128) && !(strm.data_type & 64) && - (totout == 0 || totout - last > span)) { - index = addpoint(index, strm.data_type & 7, totin, - totout, strm.avail_out, window); - if (index == NULL) { - ret = Z_MEM_ERROR; - goto build_index_error; - } - last = totout; - } - } while (strm.avail_in != 0); - } while (ret != Z_STREAM_END); - - /* clean up and return index (release unused entries in list) */ - (void)inflateEnd(&strm); - index->list = realloc(index->list, sizeof(struct point) * index->have); - index->size = index->have; - *built = index; - return index->size; - - /* return error */ - build_index_error: - (void)inflateEnd(&strm); - if (index != NULL) - free_index(index); - return ret; -} - -/* Use the index to read len bytes from offset into buf, return bytes read or - negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past - the end of the uncompressed data, then extract() will return a value less - than len, indicating how much as actually read into buf. This function - should not return a data error unless the file was modified since the index - was generated. extract() may also return Z_ERRNO if there is an error on - reading or seeking the input file. */ -local int extract(FILE *in, struct access *index, off_t offset, - unsigned char *buf, int len) -{ - int ret, skip; - z_stream strm; - struct point *here; - unsigned char input[CHUNK]; - unsigned char discard[WINSIZE]; - - /* proceed only if something reasonable to do */ - if (len < 0) - return 0; - - /* find where in stream to start */ - here = index->list; - ret = index->have; - while (--ret && here[1].out <= offset) - here++; - - /* initialize file and inflate state to start there */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -15); /* raw inflate */ - if (ret != Z_OK) - return ret; - ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); - if (ret == -1) - goto extract_ret; - if (here->bits) { - ret = getc(in); - if (ret == -1) { - ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; - goto extract_ret; - } - (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); - } - (void)inflateSetDictionary(&strm, here->window, WINSIZE); - - /* skip uncompressed bytes until offset reached, then satisfy request */ - offset -= here->out; - strm.avail_in = 0; - skip = 1; /* while skipping to offset */ - do { - /* define where to put uncompressed data, and how much */ - if (offset == 0 && skip) { /* at offset now */ - strm.avail_out = len; - strm.next_out = buf; - skip = 0; /* only do this once */ - } - if (offset > WINSIZE) { /* skip WINSIZE bytes */ - strm.avail_out = WINSIZE; - strm.next_out = discard; - offset -= WINSIZE; - } - else if (offset != 0) { /* last skip */ - strm.avail_out = (unsigned)offset; - strm.next_out = discard; - offset = 0; - } - - /* uncompress until avail_out filled, or end of stream */ - do { - if (strm.avail_in == 0) { - strm.avail_in = fread(input, 1, CHUNK, in); - if (ferror(in)) { - ret = Z_ERRNO; - goto extract_ret; - } - if (strm.avail_in == 0) { - ret = Z_DATA_ERROR; - goto extract_ret; - } - strm.next_in = input; - } - ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ - if (ret == Z_NEED_DICT) - ret = Z_DATA_ERROR; - if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) - goto extract_ret; - if (ret == Z_STREAM_END) - break; - } while (strm.avail_out != 0); - - /* if reach end of stream, then don't keep trying to get more */ - if (ret == Z_STREAM_END) - break; - - /* do until offset reached and requested data read, or stream ends */ - } while (skip); - - /* compute number of uncompressed bytes read after offset */ - ret = skip ? 0 : len - strm.avail_out; - - /* clean up and return bytes read or error */ - extract_ret: - (void)inflateEnd(&strm); - return ret; -} - -/* Demonstrate the use of build_index() and extract() by processing the file - provided on the command line, and the extracting 16K from about 2/3rds of - the way through the uncompressed output, and writing that to stdout. */ -int main(int argc, char **argv) -{ - int len; - off_t offset; - FILE *in; - struct access *index = NULL; - unsigned char buf[CHUNK]; - - /* open input file */ - if (argc != 2) { - fprintf(stderr, "usage: zran file.gz\n"); - return 1; - } - in = fopen(argv[1], "rb"); - if (in == NULL) { - fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); - return 1; - } - - /* build index */ - len = build_index(in, SPAN, &index); - if (len < 0) { - fclose(in); - switch (len) { - case Z_MEM_ERROR: - fprintf(stderr, "zran: out of memory\n"); - break; - case Z_DATA_ERROR: - fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); - break; - case Z_ERRNO: - fprintf(stderr, "zran: read error on %s\n", argv[1]); - break; - default: - fprintf(stderr, "zran: error %d while building index\n", len); - } - return 1; - } - fprintf(stderr, "zran: built index with %d access points\n", len); - - /* use index by reading some bytes from an arbitrary offset */ - offset = (index->list[index->have - 1].out << 1) / 3; - len = extract(in, index, offset, buf, CHUNK); - if (len < 0) - fprintf(stderr, "zran: extraction failed: %s error\n", - len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); - else { - fwrite(buf, 1, len, stdout); - fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); - } - - /* clean up and exit */ - free_index(index); - fclose(in); - return 0; -} diff --git a/src/contrib/zlib/gzclose.c b/src/contrib/zlib/gzclose.c deleted file mode 100644 index caeb99a..0000000 --- a/src/contrib/zlib/gzclose.c +++ /dev/null @@ -1,25 +0,0 @@ -/* gzclose.c -- zlib gzclose() function - * Copyright (C) 2004, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* gzclose() is in a separate file so that it is linked in only if it is used. - That way the other gzclose functions can be used instead to avoid linking in - unneeded compression or decompression routines. */ -int ZEXPORT gzclose(file) - gzFile file; -{ -#ifndef NO_GZCOMPRESS - gz_statep state; - - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); -#else - return gzclose_r(file); -#endif -} diff --git a/src/contrib/zlib/gzguts.h b/src/contrib/zlib/gzguts.h deleted file mode 100644 index 990a4d2..0000000 --- a/src/contrib/zlib/gzguts.h +++ /dev/null @@ -1,218 +0,0 @@ -/* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef _LARGEFILE64_SOURCE -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE 1 -# endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif -#endif - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include -#include "zlib.h" -#ifdef STDC -# include -# include -# include -#endif - -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE -#endif -#include - -#ifdef _WIN32 -# include -#endif - -#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) -# include -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) -# define WIDECHAR -#endif - -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif - -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS -/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 -/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -# ifdef VMS -# define NO_vsnprintf -# endif -# ifdef __OS400__ -# define NO_vsnprintf -# endif -# ifdef __MVS__ -# define NO_vsnprintf -# endif -#endif - -/* unlike snprintf (which is required in C99), _snprintf does not guarantee - null termination of the result -- however this is only used in gzlib.c where - the result is assured to fit in the space provided */ -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#ifndef local -# define local static -#endif -/* since "static" is used to mean two completely different things in C, we - define "local" for the non-static meaning of "static", for readability - (compile with -Dlocal if your debugger can't find static symbols) */ - -/* gz* functions always use library allocation functions */ -#ifndef STDC - extern voidp malloc OF((uInt size)); - extern void free OF((voidpf ptr)); -#endif - -/* get errno and strerror definition */ -#if defined UNDER_CE -# include -# define zstrerror() gz_strwinerror((DWORD)GetLastError()) -#else -# ifndef NO_STRERROR -# include -# define zstrerror() strerror(errno) -# else -# define zstrerror() "stdio error (consult errno)" -# endif -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); -#endif - -/* default memLevel */ -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -/* default i/o buffer size -- double this for output when reading (this and - twice this must be able to fit in an unsigned type) */ -#define GZBUFSIZE 8192 - -/* gzip modes, also provide a little integrity check on the passed structure */ -#define GZ_NONE 0 -#define GZ_READ 7247 -#define GZ_WRITE 31153 -#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ - -/* values for gz_state how */ -#define LOOK 0 /* look for a gzip header */ -#define COPY 1 /* copy input directly */ -#define GZIP 2 /* decompress a gzip stream */ - -/* internal gzip file state data structure */ -typedef struct { - /* exposed contents for gzgetc() macro */ - struct gzFile_s x; /* "x" for exposed */ - /* x.have: number of bytes available at x.next */ - /* x.next: next output data to deliver or write */ - /* x.pos: current position in uncompressed data */ - /* used for both reading and writing */ - int mode; /* see gzip modes above */ - int fd; /* file descriptor */ - char *path; /* path or fd for error messages */ - unsigned size; /* buffer size, zero if not allocated yet */ - unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer (double-sized when writing) */ - unsigned char *out; /* output buffer (double-sized when reading) */ - int direct; /* 0 if processing gzip, 1 if transparent */ - /* just for reading */ - int how; /* 0: get header, 1: copy, 2: decompress */ - z_off64_t start; /* where the gzip data started, for rewinding */ - int eof; /* true if end of input file reached */ - int past; /* true if read requested past end */ - /* just for writing */ - int level; /* compression level */ - int strategy; /* compression strategy */ - /* seek request */ - z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ - /* error information */ - int err; /* error code */ - char *msg; /* error message */ - /* zlib inflate or deflate stream */ - z_stream strm; /* stream structure in-place (not a pointer) */ -} gz_state; -typedef gz_state FAR *gz_statep; - -/* shared functions */ -void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); -#if defined UNDER_CE -char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); -#endif - -/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t - value -- needed when comparing unsigned to z_off64_t, which is signed - (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned ZLIB_INTERNAL gz_intmax OF((void)); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif diff --git a/src/contrib/zlib/gzlib.c b/src/contrib/zlib/gzlib.c deleted file mode 100644 index 4105e6a..0000000 --- a/src/contrib/zlib/gzlib.c +++ /dev/null @@ -1,637 +0,0 @@ -/* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) -# define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define LSEEK lseek64 -#else -# define LSEEK lseek -#endif -#endif - -/* Local functions */ -local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const void *, int, const char *)); - -#if defined UNDER_CE - -/* Map the Windows error number in ERROR to a locale-dependent error message - string and return a pointer to it. Typically, the values for ERROR come - from GetLastError. - - The string pointed to shall not be modified by the application, but may be - overwritten by a subsequent call to gz_strwinerror - - The gz_strwinerror function does not change the current setting of - GetLastError. */ -char ZLIB_INTERNAL *gz_strwinerror (error) - DWORD error; -{ - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -#endif /* UNDER_CE */ - -/* Reset gzip file state */ -local void gz_reset(state) - gz_statep state; -{ - state->x.have = 0; /* no output data available */ - if (state->mode == GZ_READ) { /* for reading ... */ - state->eof = 0; /* not at end of file */ - state->past = 0; /* have not read past end yet */ - state->how = LOOK; /* look for gzip header */ - } - state->seek = 0; /* no seek request pending */ - gz_error(state, Z_OK, NULL); /* clear error */ - state->x.pos = 0; /* no uncompressed data yet */ - state->strm.avail_in = 0; /* no input data yet */ -} - -/* Open a gzip file either by name or file descriptor. */ -local gzFile gz_open(path, fd, mode) - const void *path; - int fd; - const char *mode; -{ - gz_statep state; - z_size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif -#ifdef O_EXCL - int exclusive = 0; -#endif - - /* check input */ - if (path == NULL) - return NULL; - - /* allocate gzFile structure to return */ - state = (gz_statep)malloc(sizeof(gz_state)); - if (state == NULL) - return NULL; - state->size = 0; /* no buffers allocated yet */ - state->want = GZBUFSIZE; /* requested buffer size */ - state->msg = NULL; /* no error message yet */ - - /* interpret mode */ - state->mode = GZ_NONE; - state->level = Z_DEFAULT_COMPRESSION; - state->strategy = Z_DEFAULT_STRATEGY; - state->direct = 0; - while (*mode) { - if (*mode >= '0' && *mode <= '9') - state->level = *mode - '0'; - else - switch (*mode) { - case 'r': - state->mode = GZ_READ; - break; -#ifndef NO_GZCOMPRESS - case 'w': - state->mode = GZ_WRITE; - break; - case 'a': - state->mode = GZ_APPEND; - break; -#endif - case '+': /* can't read and write at the same time */ - free(state); - return NULL; - case 'b': /* ignore -- will request binary anyway */ - break; -#ifdef O_CLOEXEC - case 'e': - cloexec = 1; - break; -#endif -#ifdef O_EXCL - case 'x': - exclusive = 1; - break; -#endif - case 'f': - state->strategy = Z_FILTERED; - break; - case 'h': - state->strategy = Z_HUFFMAN_ONLY; - break; - case 'R': - state->strategy = Z_RLE; - break; - case 'F': - state->strategy = Z_FIXED; - break; - case 'T': - state->direct = 1; - break; - default: /* could consider as an error, but just ignore */ - ; - } - mode++; - } - - /* must provide an "r", "w", or "a" */ - if (state->mode == GZ_NONE) { - free(state); - return NULL; - } - - /* can't force transparent read */ - if (state->mode == GZ_READ) { - if (state->direct) { - free(state); - return NULL; - } - state->direct = 1; /* for empty file */ - } - - /* save the path name for error messages */ -#ifdef WIDECHAR - if (fd == -2) { - len = wcstombs(NULL, path, 0); - if (len == (z_size_t)-1) - len = 0; - } - else -#endif - len = strlen((const char *)path); - state->path = (char *)malloc(len + 1); - if (state->path == NULL) { - free(state); - return NULL; - } -#ifdef WIDECHAR - if (fd == -2) - if (len) - wcstombs(state->path, path, len + 1); - else - *(state->path) = 0; - else -#endif -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(state->path, len + 1, "%s", (const char *)path); -#else - strcpy(state->path, path); -#endif - - /* compute the flags for open() */ - oflag = -#ifdef O_LARGEFILE - O_LARGEFILE | -#endif -#ifdef O_BINARY - O_BINARY | -#endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | -#ifdef O_EXCL - (exclusive ? O_EXCL : 0) | -#endif - (state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))); - - /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( -#ifdef WIDECHAR - fd == -2 ? _wopen(path, oflag, 0666) : -#endif - open((const char *)path, oflag, 0666)); - if (state->fd == -1) { - free(state->path); - free(state); - return NULL; - } - if (state->mode == GZ_APPEND) { - LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ - state->mode = GZ_WRITE; /* simplify later checks */ - } - - /* save the current position for rewinding (only if reading) */ - if (state->mode == GZ_READ) { - state->start = LSEEK(state->fd, 0, SEEK_CUR); - if (state->start == -1) state->start = 0; - } - - /* initialize stream */ - gz_reset(state); - - /* return stream */ - return (gzFile)state; -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen(path, mode) - const char *path; - const char *mode; -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzopen64(path, mode) - const char *path; - const char *mode; -{ - return gz_open(path, -1, mode); -} - -/* -- see zlib.h -- */ -gzFile ZEXPORT gzdopen(fd, mode) - int fd; - const char *mode; -{ - char *path; /* identifier for error messages */ - gzFile gz; - - if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) - return NULL; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); -#else - sprintf(path, "", fd); /* for debugging */ -#endif - gz = gz_open(path, fd, mode); - free(path); - return gz; -} - -/* -- see zlib.h -- */ -#ifdef WIDECHAR -gzFile ZEXPORT gzopen_w(path, mode) - const wchar_t *path; - const char *mode; -{ - return gz_open(path, -2, mode); -} -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzbuffer(file, size) - gzFile file; - unsigned size; -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* make sure we haven't already allocated memory */ - if (state->size != 0) - return -1; - - /* check and set requested size */ - if ((size << 1) < size) - return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ - state->want = size; - return 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzrewind(file) - gzFile file; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* back up and start over */ - if (LSEEK(state->fd, state->start, SEEK_SET) == -1) - return -1; - gz_reset(state); - return 0; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzseek64(file, offset, whence) - gzFile file; - z_off64_t offset; - int whence; -{ - unsigned n; - z_off64_t ret; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* check that there's no error */ - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* can only seek from start or relative to current position */ - if (whence != SEEK_SET && whence != SEEK_CUR) - return -1; - - /* normalize offset to a SEEK_CUR specification */ - if (whence == SEEK_SET) - offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; - - /* if within raw area while reading, just go there */ - if (state->mode == GZ_READ && state->how == COPY && - state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); - if (ret == -1) - return -1; - state->x.have = 0; - state->eof = 0; - state->past = 0; - state->seek = 0; - gz_error(state, Z_OK, NULL); - state->strm.avail_in = 0; - state->x.pos += offset; - return state->x.pos; - } - - /* calculate skip amount, rewinding if needed for back seek when reading */ - if (offset < 0) { - if (state->mode != GZ_READ) /* writing -- can't go backwards */ - return -1; - offset += state->x.pos; - if (offset < 0) /* before start of file! */ - return -1; - if (gzrewind(file) == -1) /* rewind, then skip to offset */ - return -1; - } - - /* if reading, skip what's in output buffer (one less gzgetc() check) */ - if (state->mode == GZ_READ) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? - (unsigned)offset : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - offset -= n; - } - - /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->x.pos + offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzseek(file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ - z_off64_t ret; - - ret = gzseek64(file, (z_off64_t)offset, whence); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gztell64(file) - gzFile file; -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gztell(file) - gzFile file; -{ - z_off64_t ret; - - ret = gztell64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -z_off64_t ZEXPORT gzoffset64(file) - gzFile file; -{ - z_off64_t offset; - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* compute and return effective offset in file */ - offset = LSEEK(state->fd, 0, SEEK_CUR); - if (offset == -1) - return -1; - if (state->mode == GZ_READ) /* reading */ - offset -= state->strm.avail_in; /* don't count buffered input */ - return offset; -} - -/* -- see zlib.h -- */ -z_off_t ZEXPORT gzoffset(file) - gzFile file; -{ - z_off64_t ret; - - ret = gzoffset64(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzeof(file) - gzFile file; -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return 0; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return 0; - - /* return end-of-file state */ - return state->mode == GZ_READ ? state->past : 0; -} - -/* -- see zlib.h -- */ -const char * ZEXPORT gzerror(file, errnum) - gzFile file; - int *errnum; -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return NULL; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return NULL; - - /* return error information */ - if (errnum != NULL) - *errnum = state->err; - return state->err == Z_MEM_ERROR ? "out of memory" : - (state->msg == NULL ? "" : state->msg); -} - -/* -- see zlib.h -- */ -void ZEXPORT gzclearerr(file) - gzFile file; -{ - gz_statep state; - - /* get internal structure and check integrity */ - if (file == NULL) - return; - state = (gz_statep)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return; - - /* clear error and end-of-file */ - if (state->mode == GZ_READ) { - state->eof = 0; - state->past = 0; - } - gz_error(state, Z_OK, NULL); -} - -/* Create an error message in allocated memory and set state->err and - state->msg accordingly. Free any previous error message already there. Do - not try to free or allocate space if the error is Z_MEM_ERROR (out of - memory). Simply save the error message as a static string. If there is an - allocation failure constructing the error message, then convert the error to - out of memory. */ -void ZLIB_INTERNAL gz_error(state, err, msg) - gz_statep state; - int err; - const char *msg; -{ - /* free previously allocated message and clear */ - if (state->msg != NULL) { - if (state->err != Z_MEM_ERROR) - free(state->msg); - state->msg = NULL; - } - - /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) - state->x.have = 0; - - /* set error code, and if no message, then done */ - state->err = err; - if (msg == NULL) - return; - - /* for an out of memory error, return literal string when requested */ - if (err == Z_MEM_ERROR) - return; - - /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == - NULL) { - state->err = Z_MEM_ERROR; - return; - } -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); -#else - strcpy(state->msg, state->path); - strcat(state->msg, ": "); - strcat(state->msg, msg); -#endif -} - -#ifndef INT_MAX -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned ZLIB_INTERNAL gz_intmax() -{ - unsigned p, q; - - p = 1; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -} -#endif diff --git a/src/contrib/zlib/gzread.c b/src/contrib/zlib/gzread.c deleted file mode 100644 index 956b91e..0000000 --- a/src/contrib/zlib/gzread.c +++ /dev/null @@ -1,654 +0,0 @@ -/* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Local functions */ -local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); -local int gz_avail OF((gz_statep)); -local int gz_look OF((gz_statep)); -local int gz_decomp OF((gz_statep)); -local int gz_fetch OF((gz_statep)); -local int gz_skip OF((gz_statep, z_off64_t)); -local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); - -/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from - state->fd, and update state->eof, state->err, and state->msg as appropriate. - This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -local int gz_load(state, buf, len, have) - gz_statep state; - unsigned char *buf; - unsigned len; - unsigned *have; -{ - int ret; - unsigned get, max = ((unsigned)-1 >> 2) + 1; - - *have = 0; - do { - get = len - *have; - if (get > max) - get = max; - ret = read(state->fd, buf + *have, get); - if (ret <= 0) - break; - *have += (unsigned)ret; - } while (*have < len); - if (ret < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (ret == 0) - state->eof = 1; - return 0; -} - -/* Load up input buffer and set eof flag if last data loaded -- return -1 on - error, 0 otherwise. Note that the eof flag is set when the end of the input - file is reached, even though there may be unused data in the buffer. Once - that data has been used, no more attempts will be made to read the file. - If strm->avail_in != 0, then the current data is moved to the beginning of - the input buffer, and then the remainder of the buffer is loaded with the - available data from the input file. */ -local int gz_avail(state) - gz_statep state; -{ - unsigned got; - z_streamp strm = &(state->strm); - - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - if (state->eof == 0) { - if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in; - unsigned const char *q = strm->next_in; - unsigned n = strm->avail_in; - do { - *p++ = *q++; - } while (--n); - } - if (gz_load(state, state->in + strm->avail_in, - state->size - strm->avail_in, &got) == -1) - return -1; - strm->avail_in += got; - strm->next_in = state->in; - } - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. - If this is the first time in, allocate required memory. state->how will be - left unchanged if there is no more input data available, will be set to COPY - if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression. If direct copying, then leftover input - data from the input buffer will be copied to the output buffer. In that - case, all further file reads will be directly to either the output buffer or - a user buffer. If decompressing, the inflate state will be initialized. - gz_look() will return 0 on success or -1 on failure. */ -local int gz_look(state) - gz_statep state; -{ - z_streamp strm = &(state->strm); - - /* allocate read buffers and inflate memory */ - if (state->size == 0) { - /* allocate buffers */ - state->in = (unsigned char *)malloc(state->want); - state->out = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL || state->out == NULL) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - state->size = state->want; - - /* allocate inflate memory */ - state->strm.zalloc = Z_NULL; - state->strm.zfree = Z_NULL; - state->strm.opaque = Z_NULL; - state->strm.avail_in = 0; - state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ - free(state->out); - free(state->in); - state->size = 0; - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* get at least the magic bytes in the input buffer */ - if (strm->avail_in < 2) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; - } - - /* look for gzip magic bytes -- if there, do gzip decoding (note: there is - a logical dilemma here when considering the case of a partially written - gzip file, to wit, if a single 31 byte is written, then we cannot tell - whether this is a single-byte file, or just a partially written gzip - file -- for here we assume that if a gzip file is being written, then - the header will be written in a single operation, so that reading a - single byte is sufficient indication that it is not a gzip file) */ - if (strm->avail_in > 1 && - strm->next_in[0] == 31 && strm->next_in[1] == 139) { - inflateReset(strm); - state->how = GZIP; - state->direct = 0; - return 0; - } - - /* no gzip header -- if we were decoding gzip before, then this is trailing - garbage. Ignore the trailing garbage and finish. */ - if (state->direct == 0) { - strm->avail_in = 0; - state->eof = 1; - state->x.have = 0; - return 0; - } - - /* doing raw i/o, copy any leftover input to output -- this assumes that - the output buffer is larger than the input buffer, which also assures - space for gzungetc() */ - state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } - state->how = COPY; - state->direct = 1; - return 0; -} - -/* Decompress from input to the provided next_out and avail_out in the state. - On return, state->x.have and state->x.next point to the just decompressed - data. If the gzip stream completes, state->how is reset to LOOK to look for - the next gzip stream or raw data, once state->x.have is depleted. Returns 0 - on success, -1 on failure. */ -local int gz_decomp(state) - gz_statep state; -{ - int ret = Z_OK; - unsigned had; - z_streamp strm = &(state->strm); - - /* fill output buffer up to end of deflate stream */ - had = strm->avail_out; - do { - /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) { - gz_error(state, Z_BUF_ERROR, "unexpected end of file"); - break; - } - - /* decompress and handle errors */ - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { - gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); - return -1; - } - if (ret == Z_MEM_ERROR) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ - gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; - } - } while (strm->avail_out && ret != Z_STREAM_END); - - /* update available output */ - state->x.have = had - strm->avail_out; - state->x.next = strm->next_out - state->x.have; - - /* if the gzip stream completed successfully, look for another */ - if (ret == Z_STREAM_END) - state->how = LOOK; - - /* good decompression */ - return 0; -} - -/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. - Data is either copied from the input file or decompressed from the input - file depending on state->how. If state->how is LOOK, then a gzip header is - looked for to determine whether to copy or decompress. Returns -1 on error, - otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the - end of the input file has been reached and all data has been processed. */ -local int gz_fetch(state) - gz_statep state; -{ - z_streamp strm = &(state->strm); - - do { - switch(state->how) { - case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ - if (gz_look(state) == -1) - return -1; - if (state->how == LOOK) - return 0; - break; - case COPY: /* -> COPY */ - if (gz_load(state, state->out, state->size << 1, &(state->x.have)) - == -1) - return -1; - state->x.next = state->out; - return 0; - case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } - } while (state->x.have == 0 && (!state->eof || strm->avail_in)); - return 0; -} - -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -local int gz_skip(state, len) - gz_statep state; - z_off64_t len; -{ - unsigned n; - - /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) - /* skip over whatever is in output buffer */ - if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - len -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) - break; - - /* need more data to skip -- load up output buffer */ - else { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - } - return 0; -} - -/* Read len bytes into buf from file, or less than len up to the end of the - input. Return the number of bytes read. If zero is returned, either the - end of file was reached, or there was an error. state->err must be - consulted in that case to determine which. */ -local z_size_t gz_read(state, buf, len) - gz_statep state; - voidp buf; - z_size_t len; -{ - z_size_t got; - unsigned n; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return 0; - } - - /* get len bytes to buf, or less than len if at the end */ - got = 0; - do { - /* set n to the maximum amount of len that fits in an unsigned int */ - n = -1; - if (n > len) - n = len; - - /* first just try copying data from the output buffer */ - if (state->x.have) { - if (state->x.have < n) - n = state->x.have; - memcpy(buf, state->x.next, n); - state->x.next += n; - state->x.have -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) { - state->past = 1; /* tried to read past end */ - break; - } - - /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || n < (state->size << 1)) { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return 0; - continue; /* no progress yet -- go back to copy above */ - /* the copy above assures that we will leave with space in the - output buffer, allowing at least one gzungetc() to succeed */ - } - - /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, n, &n) == -1) - return 0; - } - - /* large len -- decompress directly into user buffer */ - else { /* state->how == GZIP */ - state->strm.avail_out = n; - state->strm.next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return 0; - n = state->x.have; - state->x.have = 0; - } - - /* update progress */ - len -= n; - buf = (char *)buf + n; - got += n; - state->x.pos += n; - } while (len); - - /* return number of bytes read into user buffer */ - return got; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); - return -1; - } - - /* read len or fewer bytes to buf */ - len = gz_read(state, buf, len); - - /* check for an error */ - if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* return the number of bytes read (this is assured to fit in an int) */ - return (int)len; -} - -/* -- see zlib.h -- */ -z_size_t ZEXPORT gzfread(buf, size, nitems, file) - voidp buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ - z_size_t len; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return 0; - - /* compute bytes to read -- error on overflow */ - len = nitems * size; - if (size && len / size != nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - - /* read len or fewer bytes to buf, return the number of full items read */ - return len ? gz_read(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -#else -# undef gzgetc -#endif -int ZEXPORT gzgetc(file) - gzFile file; -{ - int ret; - unsigned char buf[1]; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* try output buffer (no need to check for skip request) */ - if (state->x.have) { - state->x.have--; - state->x.pos++; - return *(state->x.next)++; - } - - /* nothing there -- try gz_read() */ - ret = gz_read(state, buf, 1); - return ret < 1 ? -1 : buf[0]; -} - -int ZEXPORT gzgetc_(file) -gzFile file; -{ - return gzgetc(file); -} - -/* -- see zlib.h -- */ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* can't push EOF */ - if (c < 0) - return -1; - - /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->x.have == 0) { - state->x.have = 1; - state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; - } - - /* if no room, give up (must have already done a gzungetc()) */ - if (state->x.have == (state->size << 1)) { - gz_error(state, Z_DATA_ERROR, "out of room to push characters"); - return -1; - } - - /* slide output data if needed and insert byte before existing data */ - if (state->x.next == state->out) { - unsigned char *src = state->out + state->x.have; - unsigned char *dest = state->out + (state->size << 1); - while (src > state->out) - *--dest = *--src; - state->x.next = dest; - } - state->x.have++; - state->x.next--; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; -} - -/* -- see zlib.h -- */ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ - unsigned left, n; - char *str; - unsigned char *eol; - gz_statep state; - - /* check parameters and get internal structure */ - if (file == NULL || buf == NULL || len < 1) - return NULL; - state = (gz_statep)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return NULL; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } - - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ - str = buf; - left = (unsigned)len - 1; - if (left) do { - /* assure that something is in the output buffer */ - if (state->x.have == 0 && gz_fetch(state) == -1) - return NULL; /* error */ - if (state->x.have == 0) { /* end of file */ - state->past = 1; /* read past end */ - break; /* return what we have */ - } - - /* look for end-of-line in current output buffer */ - n = state->x.have > left ? left : state->x.have; - eol = (unsigned char *)memchr(state->x.next, '\n', n); - if (eol != NULL) - n = (unsigned)(eol - state->x.next) + 1; - - /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->x.next, n); - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - left -= n; - buf += n; - } while (left && eol == NULL); - - /* return terminated string, or if nothing, end of file */ - if (buf == str) - return NULL; - buf[0] = 0; - return str; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzdirect(file) - gzFile file; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* if the state is not known, but we can find out, then do so (this is - mainly for right after a gzopen() or gzdopen()) */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_r(file) - gzFile file; -{ - int ret, err; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're reading */ - if (state->mode != GZ_READ) - return Z_STREAM_ERROR; - - /* free memory and close file */ - if (state->size) { - inflateEnd(&(state->strm)); - free(state->out); - free(state->in); - } - err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; - gz_error(state, Z_OK, NULL); - free(state->path); - ret = close(state->fd); - free(state); - return ret ? Z_ERRNO : err; -} diff --git a/src/contrib/zlib/gzwrite.c b/src/contrib/zlib/gzwrite.c deleted file mode 100644 index c7b5651..0000000 --- a/src/contrib/zlib/gzwrite.c +++ /dev/null @@ -1,665 +0,0 @@ -/* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "gzguts.h" - -/* Local functions */ -local int gz_init OF((gz_statep)); -local int gz_comp OF((gz_statep, int)); -local int gz_zero OF((gz_statep, z_off64_t)); -local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); - -/* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on a memory allocation failure, or 0 on - success. */ -local int gz_init(state) - gz_statep state; -{ - int ret; - z_streamp strm = &(state->strm); - - /* allocate input buffer (double size for gzprintf) */ - state->in = (unsigned char *)malloc(state->want << 1); - if (state->in == NULL) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* only need output buffer and deflate state if compressing */ - if (!state->direct) { - /* allocate output buffer */ - state->out = (unsigned char *)malloc(state->want); - if (state->out == NULL) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); - if (ret != Z_OK) { - free(state->out); - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - strm->next_in = NULL; - } - - /* mark state as initialized */ - state->size = state->want; - - /* initialize write buffer if compressing */ - if (!state->direct) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = strm->next_out; - } - return 0; -} - -/* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file or if gz_init() - fails to allocate memory, otherwise 0. flush is assumed to be a valid - deflate() flush value. If flush is Z_FINISH, then the deflate() state is - reset to start a new gzip stream. If gz->direct is true, then simply write - to the output file without compressing, and ignore flush. */ -local int gz_comp(state, flush) - gz_statep state; - int flush; -{ - int ret, writ; - unsigned have, put, max = ((unsigned)-1 >> 2) + 1; - z_streamp strm = &(state->strm); - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return -1; - - /* write directly if requested */ - if (state->direct) { - while (strm->avail_in) { - put = strm->avail_in > max ? max : strm->avail_in; - writ = write(state->fd, strm->next_in, put); - if (writ < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - strm->avail_in -= (unsigned)writ; - strm->next_in += writ; - } - return 0; - } - - /* run deflate() on provided input until it produces no more output */ - ret = Z_OK; - do { - /* write out current buffer contents if full, or if flushing, but if - doing Z_FINISH then don't write until we get to Z_STREAM_END */ - if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && - (flush != Z_FINISH || ret == Z_STREAM_END))) { - while (strm->next_out > state->x.next) { - put = strm->next_out - state->x.next > (int)max ? max : - (unsigned)(strm->next_out - state->x.next); - writ = write(state->fd, state->x.next, put); - if (writ < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - state->x.next += writ; - } - if (strm->avail_out == 0) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = state->out; - } - } - - /* compress */ - have = strm->avail_out; - ret = deflate(strm, flush); - if (ret == Z_STREAM_ERROR) { - gz_error(state, Z_STREAM_ERROR, - "internal error: deflate stream corrupt"); - return -1; - } - have -= strm->avail_out; - } while (have); - - /* if that completed a deflate stream, allow another to start */ - if (flush == Z_FINISH) - deflateReset(strm); - - /* all done, no errors */ - return 0; -} - -/* Compress len zeros to output. Return -1 on a write error or memory - allocation failure by gz_comp(), or 0 on success. */ -local int gz_zero(state, len) - gz_statep state; - z_off64_t len; -{ - int first; - unsigned n; - z_streamp strm = &(state->strm); - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - - /* compress len zeros (len guaranteed > 0) */ - first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? - (unsigned)len : state->size; - if (first) { - memset(state->in, 0, n); - first = 0; - } - strm->avail_in = n; - strm->next_in = state->in; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - len -= n; - } - return 0; -} - -/* Write len bytes from buf to file. Return the number of bytes written. If - the returned value is less than len, then there was an error. */ -local z_size_t gz_write(state, buf, len) - gz_statep state; - voidpc buf; - z_size_t len; -{ - z_size_t put = len; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* for small len, copy to input buffer, otherwise compress directly */ - if (len < state->size) { - /* copy to input buffer, compress when full */ - do { - unsigned have, copy; - - if (state->strm.avail_in == 0) - state->strm.next_in = state->in; - have = (unsigned)((state->strm.next_in + state->strm.avail_in) - - state->in); - copy = state->size - have; - if (copy > len) - copy = len; - memcpy(state->in + have, buf, copy); - state->strm.avail_in += copy; - state->x.pos += copy; - buf = (const char *)buf + copy; - len -= copy; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); - } - else { - /* consume whatever's left in the input buffer */ - if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* directly compress user buffer to file */ - state->strm.next_in = (z_const Bytef *)buf; - do { - unsigned n = (unsigned)-1; - if (n > len) - n = len; - state->strm.avail_in = n; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - len -= n; - } while (len); - } - - /* input was all buffered or compressed */ - return put; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } - - /* write len bytes from buf (the return value will fit in an int) */ - return (int)gz_write(state, buf, len); -} - -/* -- see zlib.h -- */ -z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) - voidpc buf; - z_size_t size; - z_size_t nitems; - gzFile file; -{ - z_size_t len; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* compute bytes to read -- error on overflow */ - len = nitems * size; - if (size && len / size != nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - - /* write len bytes to buf, return the number of full items written */ - return len ? gz_write(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ - unsigned have; - unsigned char buf[1]; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* try writing to input buffer for speed (state->size == 0 if buffer not - initialized) */ - if (state->size) { - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - if (have < state->size) { - state->in[have] = (unsigned char)c; - strm->avail_in++; - state->x.pos++; - return c & 0xff; - } - } - - /* no room in buffer or not initialized, use gz_write() */ - buf[0] = (unsigned char)c; - if (gz_write(state, buf, 1) != 1) - return -1; - return c & 0xff; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzputs(file, str) - gzFile file; - const char *str; -{ - int ret; - z_size_t len; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* write string */ - len = strlen(str); - ret = gz_write(state, str, len); - return ret == 0 && len != 0 ? -1 : ret; -} - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -#include - -/* -- see zlib.h -- */ -int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) -{ - int len; - unsigned left; - char *next; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return state->err; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* do the printf() into the input buffer, put length in len -- the input - buffer is double-sized just for this function, so there is guaranteed to - be state->size bytes available after the current contents */ - if (strm->avail_in == 0) - strm->next_in = state->in; - next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); - next[state->size - 1] = 0; -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf(next, format, va); - for (len = 0; len < state->size; len++) - if (next[len] == 0) break; -# else - len = vsprintf(next, format, va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf(next, state->size, format, va); - len = strlen(next); -# else - len = vsnprintf(next, state->size, format, va); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) - return 0; - - /* update buffer and position, compress first half if past that */ - strm->avail_in += (unsigned)len; - state->x.pos += len; - if (strm->avail_in >= state->size) { - left = strm->avail_in - state->size; - strm->avail_in = state->size; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return state->err; - memcpy(state->in, state->in + state->size, left); - strm->next_in = state->in; - strm->avail_in = left; - } - return len; -} - -int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) -{ - va_list va; - int ret; - - va_start(va, format); - ret = gzvprintf(file, format, va); - va_end(va); - return ret; -} - -#else /* !STDC && !Z_HAVE_STDARG_H */ - -/* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - unsigned len, left; - char *next; - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that can really pass pointer in ints */ - if (sizeof(int) != sizeof(void *)) - return Z_STREAM_ERROR; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return state->error; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->error; - } - - /* do the printf() into the input buffer, put length in len -- the input - buffer is double-sized just for this function, so there is guaranteed to - be state->size bytes available after the current contents */ - if (strm->avail_in == 0) - strm->next_in = state->in; - next = (char *)(strm->next_in + strm->avail_in); - next[state->size - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, - a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < size; len++) - if (next[len] == 0) - break; -# else - len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, - a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, - a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(next); -# else - len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#endif - - /* check that printf() results fit in buffer */ - if (len == 0 || len >= state->size || next[state->size - 1] != 0) - return 0; - - /* update buffer and position, compress first half if past that */ - strm->avail_in += len; - state->x.pos += len; - if (strm->avail_in >= state->size) { - left = strm->avail_in - state->size; - strm->avail_in = state->size; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return state->err; - memcpy(state->in, state->in + state->size, left); - strm->next_in = state->in; - strm->avail_in = left; - } - return (int)len; -} - -#endif - -/* -- see zlib.h -- */ -int ZEXPORT gzflush(file, flush) - gzFile file; - int flush; -{ - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* check flush parameter */ - if (flush < 0 || flush > Z_FINISH) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* compress remaining data with requested flush */ - (void)gz_comp(state, flush); - return state->err; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzsetparams(file, level, strategy) - gzFile file; - int level; - int strategy; -{ - gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* if no change is requested, then do nothing */ - if (level == state->level && strategy == state->strategy) - return Z_OK; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* change compression parameters for subsequent input */ - if (state->size) { - /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) - return state->err; - deflateParams(strm, level, strategy); - } - state->level = level; - state->strategy = strategy; - return Z_OK; -} - -/* -- see zlib.h -- */ -int ZEXPORT gzclose_w(file) - gzFile file; -{ - int ret = Z_OK; - gz_statep state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_statep)file; - - /* check that we're writing */ - if (state->mode != GZ_WRITE) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } - - /* flush, free memory, and close file */ - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; - if (state->size) { - if (!state->direct) { - (void)deflateEnd(&(state->strm)); - free(state->out); - } - free(state->in); - } - gz_error(state, Z_OK, NULL); - free(state->path); - if (close(state->fd) == -1) - ret = Z_ERRNO; - free(state); - return ret; -} diff --git a/src/contrib/zlib/infback.c b/src/contrib/zlib/infback.c deleted file mode 100644 index 59679ec..0000000 --- a/src/contrib/zlib/infback.c +++ /dev/null @@ -1,640 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = (uInt)windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = (unsigned)here.val; - - /* process literal */ - if (here.op == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(here.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/src/contrib/zlib/inffast.c b/src/contrib/zlib/inffast.c deleted file mode 100644 index 0dbd1db..0000000 --- a/src/contrib/zlib/inffast.c +++ /dev/null @@ -1,323 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef ASMINF -# pragma message("Assembler code may have bugs -- use at your own risk") -#else - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void ZLIB_INTERNAL inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *in; /* local strm->next_in */ - z_const unsigned char FAR *last; /* have enough input while in < last */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in; - last = in + (strm->avail_in - 5); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = lcode[hold & lmask]; - dolen: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - *out++ = (unsigned char)(here.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - here = dcode[hold & dmask]; - dodist: - op = (unsigned)(here.bits); - hold >>= op; - bits -= op; - op = (unsigned)(here.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(*in++) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - strm->msg = - (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = window; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - *out++ = *from++; - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - *out++ = *from++; - *out++ = *from++; - *out++ = *from++; - len -= 3; - } while (len > 2); - if (len) { - *out++ = *from++; - if (len > 1) - *out++ = *from++; - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in; - strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and wnext == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/src/contrib/zlib/inffast.h b/src/contrib/zlib/inffast.h deleted file mode 100644 index e5c1aa4..0000000 --- a/src/contrib/zlib/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/src/contrib/zlib/inffixed.h b/src/contrib/zlib/inffixed.h deleted file mode 100644 index d628327..0000000 --- a/src/contrib/zlib/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. - It is part of the implementation of this library and is - subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/src/contrib/zlib/inflate.c b/src/contrib/zlib/inflate.c deleted file mode 100644 index ac333e8..0000000 --- a/src/contrib/zlib/inflate.c +++ /dev/null @@ -1,1561 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common wnext == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local int inflateStateCheck OF((z_streamp strm)); -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -local int inflateStateCheck(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) - return 1; - state = (struct inflate_state FAR *)strm->state; - if (state == Z_NULL || state->strm != strm || - state->mode < HEAD || state->mode > SYNC) - return 1; - return 0; -} - -int ZEXPORT inflateResetKeep(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - if (state->wrap) /* to support ill-conceived Java test suite */ - strm->adler = state->wrap & 1; - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - state->sane = 1; - state->back = -1; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; - return inflateResetKeep(strm); -} - -int ZEXPORT inflateReset2(strm, windowBits) -z_streamp strm; -int windowBits; -{ - int wrap; - struct inflate_state FAR *state; - - /* get the state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 5; -#ifdef GUNZIP - if (windowBits < 48) - windowBits &= 15; -#endif - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) - return Z_STREAM_ERROR; - if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { - ZFREE(strm, state->window); - state->window = Z_NULL; - } - - /* update state and reset the rest of it */ - state->wrap = wrap; - state->wbits = (unsigned)windowBits; - return inflateReset(strm); -} - -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ - int ret; - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; -#endif - } - if (strm->zfree == (free_func)0) -#ifdef Z_SOLO - return Z_STREAM_ERROR; -#else - strm->zfree = zcfree; -#endif - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->strm = strm; - state->window = Z_NULL; - state->mode = HEAD; /* to pass state test in inflateReset2() */ - ret = inflateReset2(strm, windowBits); - if (ret != Z_OK) { - ZFREE(strm, state); - strm->state = Z_NULL; - } - return ret; -} - -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits < 0) { - state->hold = 0; - state->bits = 0; - return Z_OK; - } - if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += (unsigned)value << state->bits; - state->bits += (uInt)bits; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, - state.lencode[low].bits, state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(strm, end, copy) -z_streamp strm; -const Bytef *end; -unsigned copy; -{ - struct inflate_state FAR *state; - unsigned dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->wnext = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - zmemcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->wnext; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } - else { - state->wnext += dist; - if (state->wnext == state->wsize) state->wnext = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ - struct inflate_state FAR *state; - z_const unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (inflateStateCheck(strm) || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - if (state->wbits == 0) - state->wbits = 15; - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (state->wbits == 0) - state->wbits = len; - if (len > 15 || len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = (Bytef)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = (Bytef)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if ((state->wrap & 4) && hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN_; /* decode codes */ - if (flush == Z_TREES) { - DROPBITS(2); - goto inf_leave; - } - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY_; - if (flush == Z_TREES) goto inf_leave; - case COPY_: - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } - else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (const code FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN_; - if (flush == Z_TREES) goto inf_leave; - case LEN_: - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - if (state->mode == TYPE) - state->back = -1; - break; - } - state->back = 0; - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - state->length = (unsigned)here.val; - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - state->mode = LIT; - break; - } - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->back = -1; - state->mode = TYPE; - break; - } - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(here.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->was = state->length; - state->mode = DIST; - case DIST: - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if ((unsigned)(here.bits) <= bits) break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + here.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)here.val; - state->extra = (unsigned)(here.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - if (copy > state->length) copy = state->length; - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; -#endif - } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->wnext - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if ((state->wrap & 4) && out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if ((state->wrap & 4) && ( -#ifdef GUNZIP - state->flags ? hold : -#endif - ZSWAP32(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if ((state->wrap & 4) && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = (int)state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0) + - (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) -z_streamp strm; -Bytef *dictionary; -uInt *dictLength; -{ - struct inflate_state FAR *state; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* copy dictionary */ - if (state->whave && dictionary != Z_NULL) { - zmemcpy(dictionary, state->window + state->wnext, - state->whave - state->wnext); - zmemcpy(dictionary + state->whave - state->wnext, - state->window, state->wnext); - } - if (dictLength != Z_NULL) - *dictLength = state->whave; - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ - struct inflate_state FAR *state; - unsigned long dictid; - int ret; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary identifier */ - if (state->mode == DICT) { - dictid = adler32(0L, Z_NULL, 0); - dictid = adler32(dictid, dictionary, dictLength); - if (dictid != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; - return Z_MEM_ERROR; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ - struct inflate_state FAR *state; - - /* check state */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -const unsigned char FAR *buf; -unsigned len; -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (inflateStateCheck(source) || dest == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); - zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); - copy->strm = dest; - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} - -int ZEXPORT inflateUndermine(strm, subvert) -z_streamp strm; -int subvert; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - state->sane = !subvert; - return Z_OK; -#else - (void)subvert; - state->sane = 1; - return Z_DATA_ERROR; -#endif -} - -int ZEXPORT inflateValidate(strm, check) -z_streamp strm; -int check; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (check) - state->wrap |= 4; - else - state->wrap &= ~4; - return Z_OK; -} - -long ZEXPORT inflateMark(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (inflateStateCheck(strm)) - return -(1L << 16); - state = (struct inflate_state FAR *)strm->state; - return (long)(((unsigned long)((long)state->back)) << 16) + - (state->mode == COPY ? state->length : - (state->mode == MATCH ? state->was - state->length : 0)); -} - -unsigned long ZEXPORT inflateCodesUsed(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (inflateStateCheck(strm)) return (unsigned long)-1; - state = (struct inflate_state FAR *)strm->state; - return (unsigned long)(state->next - state->codes); -} diff --git a/src/contrib/zlib/inflate.h b/src/contrib/zlib/inflate.h deleted file mode 100644 index a46cce6..0000000 --- a/src/contrib/zlib/inflate.h +++ /dev/null @@ -1,125 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD = 16180, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY_, /* i/o: same as COPY below, but only first time in */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN_, /* i: same as LEN below, but only first time in */ - LEN, /* i: waiting for length/lit/eob code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to BAD or MEM on error -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) or (raw) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> - HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - (raw) -> TYPEDO - Read deflate blocks: - TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK - STORED -> COPY_ -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN_ - LEN_ -> LEN - Read deflate codes in fixed or dynamic block: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* State maintained between inflate() calls -- approximately 7K bytes, not - including the allocated sliding window, which is up to 32K bytes. */ -struct inflate_state { - z_streamp strm; /* pointer back to this zlib stream */ - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip, - bit 2 true to validate check value */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ - int sane; /* if false, allow invalid distance too far */ - int back; /* bits back of last unprocessed length/lit */ - unsigned was; /* initial length of match */ -}; diff --git a/src/contrib/zlib/inftrees.c b/src/contrib/zlib/inftrees.c deleted file mode 100644 index 2ea08fc..0000000 --- a/src/contrib/zlib/inftrees.c +++ /dev/null @@ -1,304 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - unsigned match; /* use base and extra for symbol >= match */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (unsigned short)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - match = 20; - break; - case LENS: - base = lbase; - extra = lext; - match = 257; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - match = 0; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if (work[sym] + 1U < match) { - here.op = (unsigned char)0; - here.val = work[sym]; - } - else if (work[sym] >= match) { - here.op = (unsigned char)(extra[work[sym] - match]); - here.val = base[work[sym] - match]; - } - else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - next[huff] = here; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/src/contrib/zlib/inftrees.h b/src/contrib/zlib/inftrees.h deleted file mode 100644 index baa53a0..0000000 --- a/src/contrib/zlib/inftrees.h +++ /dev/null @@ -1,62 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in inflate.c and infback.c. If the root table size is - changed, then these maximum sizes would be need to be recalculated and - updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 592 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/contrib/zlib/make_vms.com b/src/contrib/zlib/make_vms.com deleted file mode 100644 index 65e9d0c..0000000 --- a/src/contrib/zlib/make_vms.com +++ /dev/null @@ -1,867 +0,0 @@ -$! make libz under VMS written by -$! Martin P.J. Zinser -$! -$! In case of problems with the install you might contact me at -$! zinser@zinser.no-ip.info(preferred) or -$! martin.zinser@eurexchange.com (work) -$! -$! Make procedure history for Zlib -$! -$!------------------------------------------------------------------------------ -$! Version history -$! 0.01 20060120 First version to receive a number -$! 0.02 20061008 Adapt to new Makefile.in -$! 0.03 20091224 Add support for large file check -$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite -$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in -$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples -$! subdir path, update module search in makefile.in -$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned -$! shared image creation -$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared -$! image -$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). -$! "" -> automatic, preference: MMK, MMS, built-in. -$! -$ on error then goto err_exit -$! -$ true = 1 -$ false = 0 -$ tmpnam = "temp_" + f$getjpi("","pid") -$ tt = tmpnam + ".txt" -$ tc = tmpnam + ".c" -$ th = tmpnam + ".h" -$ define/nolog tconfig 'th' -$ its_decc = false -$ its_vaxc = false -$ its_gnuc = false -$ s_case = False -$! -$! Setup variables holding "config" information -$! -$ Make = "''p1'" -$ name = "Zlib" -$ version = "?.?.?" -$ v_string = "ZLIB_VERSION" -$ v_file = "zlib.h" -$ ccopt = "/include = []" -$ lopts = "" -$ dnsrl = "" -$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" -$ conf_check_string = "" -$ linkonly = false -$ optfile = name + ".opt" -$ mapfile = name + ".map" -$ libdefs = "" -$ vax = f$getsyi("HW_MODEL").lt.1024 -$ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 -$ ia64 = f$getsyi("HW_MODEL").ge.4096 -$! -$! 2012-03-05 SMS. -$! Why is this needed? And if it is needed, why not simply ".not. vax"? -$! -$!!! if axp .or. ia64 then set proc/parse=extended -$! -$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") -$ mydef = F$parse(whoami,,,"DEVICE") -$ mydir = f$parse(whoami,,,"DIRECTORY") - "][" -$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") -$! -$! Check for MMK/MMS -$! -$ if (Make .eqs. "") -$ then -$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" -$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" -$ else -$ Make = f$edit( Make, "trim") -$ endif -$! -$ gosub find_version -$! -$ open/write topt tmp.opt -$ open/write optf 'optfile' -$! -$ gosub check_opts -$! -$! Look for the compiler used -$! -$ gosub check_compiler -$ close topt -$ close optf -$! -$ if its_decc -$ then -$ ccopt = "/prefix=all" + ccopt -$ if f$trnlnm("SYS") .eqs. "" -$ then -$ if axp -$ then -$ define sys sys$library: -$ else -$ ccopt = "/decc" + ccopt -$ define sys decc$library_include: -$ endif -$ endif -$! -$! 2012-03-05 SMS. -$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? -$! -$ if axp .or. ia64 -$ then -$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" -$ s_case = true -$ endif -$ endif -$ if its_vaxc .or. its_gnuc -$ then -$ if f$trnlnm("SYS").eqs."" then define sys sys$library: -$ endif -$! -$! Build a fake configure input header -$! -$ open/write conf_hin config.hin -$ write conf_hin "#undef _LARGEFILE64_SOURCE" -$ close conf_hin -$! -$! -$ i = 0 -$FIND_ACONF: -$ fname = f$element(i,"#",aconf_in_file) -$ if fname .eqs. "#" then goto AMISS_ERR -$ if f$search(fname) .eqs. "" -$ then -$ i = i + 1 -$ goto find_aconf -$ endif -$ open/read/err=aconf_err aconf_in 'fname' -$ open/write aconf zconf.h -$ACONF_LOOP: -$ read/end_of_file=aconf_exit aconf_in line -$ work = f$edit(line, "compress,trim") -$ if f$extract(0,6,work) .nes. "#undef" -$ then -$ if f$extract(0,12,work) .nes. "#cmakedefine" -$ then -$ write aconf line -$ endif -$ else -$ cdef = f$element(1," ",work) -$ gosub check_config -$ endif -$ goto aconf_loop -$ACONF_EXIT: -$ write aconf "" -$ write aconf "/* VMS specifics added by make_vms.com: */" -$ write aconf "#define VMS 1" -$ write aconf "#include " -$ write aconf "#include " -$ write aconf "#ifdef _LARGEFILE" -$ write aconf "# define off64_t __off64_t" -$ write aconf "# define fopen64 fopen" -$ write aconf "# define fseeko64 fseeko" -$ write aconf "# define lseek64 lseek" -$ write aconf "# define ftello64 ftell" -$ write aconf "#endif" -$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" -$ write aconf "# define HAVE_VSNPRINTF" -$ write aconf "#endif" -$ close aconf_in -$ close aconf -$ if f$search("''th'") .nes. "" then delete 'th';* -$! Build the thing plain or with mms -$! -$ write sys$output "Compiling Zlib sources ..." -$ if make.eqs."" -$ then -$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* -$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* -$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - - adler32.c zlib.h zconf.h -$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - - compress.c zlib.h zconf.h -$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - - crc32.c zlib.h zconf.h -$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - - deflate.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" - - gzclose.c zutil.h zlib.h zconf.h -$ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" - - gzlib.c zutil.h zlib.h zconf.h -$ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" - - gzread.c zutil.h zlib.h zconf.h -$ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" - - gzwrite.c zutil.h zlib.h zconf.h -$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - - infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - - inffast.c zutil.h zlib.h zconf.h inffast.h -$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - - inflate.c zutil.h zlib.h zconf.h infblock.h -$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - - inftrees.c zutil.h zlib.h zconf.h inftrees.h -$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - - trees.c deflate.h zutil.h zlib.h zconf.h -$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - - uncompr.c zlib.h zconf.h -$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - - zutil.c zutil.h zlib.h zconf.h -$ write sys$output "Building Zlib ..." -$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ -$ write sys$output "Building example..." -$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - - [.test]example.c zlib.h zconf.h -$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb -$ write sys$output "Building minigzip..." -$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - - [.test]minigzip.c zlib.h zconf.h -$ call make minigzip.exe - - "LINK minigzip,libz.olb/lib" - - minigzip.obj libz.olb -$ else -$ gosub crea_mms -$ write sys$output "Make ''name' ''version' with ''Make' " -$ 'make' -$ endif -$! -$! Create shareable image -$! -$ gosub crea_olist -$ write sys$output "Creating libzshr.exe" -$ call map_2_shopt 'mapfile' 'optfile' -$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt -$ write sys$output "Zlib build completed" -$ delete/nolog tmp.opt;* -$ exit -$AMISS_ERR: -$ write sys$output "No source for config.hin found." -$ write sys$output "Tried any of ''aconf_in_file'" -$ goto err_exit -$CC_ERR: -$ write sys$output "C compiler required to build ''name'" -$ goto err_exit -$ERR_EXIT: -$ set message/facil/ident/sever/text -$ close/nolog optf -$ close/nolog topt -$ close/nolog aconf_in -$ close/nolog aconf -$ close/nolog out -$ close/nolog min -$ close/nolog mod -$ close/nolog h_in -$ write sys$output "Exiting..." -$ exit 2 -$! -$! -$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES -$ V = 'F$Verify(0) -$! P1 = What we are trying to make -$! P2 = Command to make it -$! P3 - P8 What it depends on -$ -$ If F$Search(P1) .Eqs. "" Then Goto Makeit -$ Time = F$CvTime(F$File(P1,"RDT")) -$arg=3 -$Loop: -$ Argument = P'arg -$ If Argument .Eqs. "" Then Goto Exit -$ El=0 -$Loop2: -$ File = F$Element(El," ",Argument) -$ If File .Eqs. " " Then Goto Endl -$ AFile = "" -$Loop3: -$ OFile = AFile -$ AFile = F$Search(File) -$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl -$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit -$ Goto Loop3 -$NextEL: -$ El = El + 1 -$ Goto Loop2 -$EndL: -$ arg=arg+1 -$ If arg .Le. 8 Then Goto Loop -$ Goto Exit -$ -$Makeit: -$ VV=F$VERIFY(0) -$ write sys$output P2 -$ 'P2 -$ VV='F$Verify(VV) -$Exit: -$ If V Then Set Verify -$ENDSUBROUTINE -$!------------------------------------------------------------------------------ -$! -$! Check command line options and set symbols accordingly -$! -$!------------------------------------------------------------------------------ -$! Version history -$! 0.01 20041206 First version to receive a number -$! 0.02 20060126 Add new "HELP" target -$ CHECK_OPTS: -$ i = 1 -$ OPT_LOOP: -$ if i .lt. 9 -$ then -$ cparm = f$edit(p'i',"upcase") -$! -$! Check if parameter actually contains something -$! -$ if f$edit(cparm,"trim") .nes. "" -$ then -$ if cparm .eqs. "DEBUG" -$ then -$ ccopt = ccopt + "/noopt/deb" -$ lopts = lopts + "/deb" -$ endif -$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ ccopt = ccopt + f$extract(start,len,cparm) -$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - - then s_case = true -$ endif -$ if cparm .eqs. "LINK" then linkonly = true -$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ lopts = lopts + f$extract(start,len,cparm) -$ endif -$ if f$locate("CC=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ cc_com = f$extract(start,len,cparm) - if (cc_com .nes. "DECC") .and. - - (cc_com .nes. "VAXC") .and. - - (cc_com .nes. "GNUC") -$ then -$ write sys$output "Unsupported compiler choice ''cc_com' ignored" -$ write sys$output "Use DECC, VAXC, or GNUC instead" -$ else -$ if cc_com .eqs. "DECC" then its_decc = true -$ if cc_com .eqs. "VAXC" then its_vaxc = true -$ if cc_com .eqs. "GNUC" then its_gnuc = true -$ endif -$ endif -$ if f$locate("MAKE=",cparm) .lt. f$length(cparm) -$ then -$ start = f$locate("=",cparm) + 1 -$ len = f$length(cparm) - start -$ mmks = f$extract(start,len,cparm) -$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") -$ then -$ make = mmks -$ else -$ write sys$output "Unsupported make choice ''mmks' ignored" -$ write sys$output "Use MMK or MMS instead" -$ endif -$ endif -$ if cparm .eqs. "HELP" then gosub bhelp -$ endif -$ i = i + 1 -$ goto opt_loop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Look for the compiler used -$! -$! Version history -$! 0.01 20040223 First version to receive a number -$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists -$! 0.03 20060202 Extend handling of GNU C -$! 0.04 20090402 Compaq -> hp -$CHECK_COMPILER: -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then -$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") -$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") -$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") -$ endif -$! -$! Exit if no compiler available -$! -$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) -$ then goto CC_ERR -$ else -$ if its_decc -$ then -$ write sys$output "CC compiler check ... hp C" -$ if f$trnlnm("decc$no_rooted_search_lists") .nes. "" -$ then -$ dnrsl = f$trnlnm("decc$no_rooted_search_lists") -$ endif -$ define/nolog decc$no_rooted_search_lists 1 -$ else -$ if its_vaxc then write sys$output "CC compiler check ... VAX C" -$ if its_gnuc -$ then -$ write sys$output "CC compiler check ... GNU C" -$ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib" -$ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib" -$ cc = "gcc" -$ endif -$ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share" -$ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share" -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! If MMS/MMK are available dump out the descrip.mms if required -$! -$CREA_MMS: -$ write sys$output "Creating descrip.mms..." -$ create descrip.mms -$ open/append out descrip.mms -$ copy sys$input: out -$ deck -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser -# - -OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ - gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, \ - inftrees.obj, inffast.obj - -$ eod -$ write out "CFLAGS=", ccopt -$ write out "LOPTS=", lopts -$ write out "all : example.exe minigzip.exe libz.olb" -$ copy sys$input: out -$ deck - @ write sys$output " Example applications available" - -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link $(LOPTS) example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link $(LOPTS) minigzip,libz.olb/lib - -clean : - delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* - - -# Other dependencies. -adler32.obj : adler32.c zutil.h zlib.h zconf.h -compress.obj : compress.c zlib.h zconf.h -crc32.obj : crc32.c zutil.h zlib.h zconf.h -deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h -example.obj : [.test]example.c zlib.h zconf.h -gzclose.obj : gzclose.c zutil.h zlib.h zconf.h -gzlib.obj : gzlib.c zutil.h zlib.h zconf.h -gzread.obj : gzread.c zutil.h zlib.h zconf.h -gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h -inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h -inflate.obj : inflate.c zutil.h zlib.h zconf.h -inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h -minigzip.obj : [.test]minigzip.c zlib.h zconf.h -trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h -uncompr.obj : uncompr.c zlib.h zconf.h -zutil.obj : zutil.c zutil.h zlib.h zconf.h -infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h -$ eod -$ close out -$ return -$!------------------------------------------------------------------------------ -$! -$! Read list of core library sources from makefile.in and create options -$! needed to build shareable image -$! -$CREA_OLIST: -$ open/read min makefile.in -$ open/write mod modules.opt -$ src_check_list = "OBJZ =#OBJG =" -$MRLOOP: -$ read/end=mrdone min rec -$ i = 0 -$SRC_CHECK_LOOP: -$ src_check = f$element(i, "#", src_check_list) -$ i = i+1 -$ if src_check .eqs. "#" then goto mrloop -$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop -$ rec = rec - src_check -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop -$MRSLOOP: -$ read/end=mrdone min rec -$ gosub extra_filnam -$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop -$MRDONE: -$ close min -$ close mod -$ return -$!------------------------------------------------------------------------------ -$! -$! Take record extracted in crea_olist and split it into single filenames -$! -$EXTRA_FILNAM: -$ myrec = f$edit(rec - "\", "trim,compress") -$ i = 0 -$FELOOP: -$ srcfil = f$element(i," ", myrec) -$ if (srcfil .nes. " ") -$ then -$ write mod f$parse(srcfil,,,"NAME"), ".obj" -$ i = i + 1 -$ goto feloop -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Find current Zlib version number -$! -$FIND_VERSION: -$ open/read h_in 'v_file' -$hloop: -$ read/end=hdone h_in rec -$ rec = f$edit(rec,"TRIM") -$ if (f$extract(0,1,rec) .nes. "#") then goto hloop -$ rec = f$edit(rec - "#", "TRIM") -$ if f$element(0," ",rec) .nes. "define" then goto hloop -$ if f$element(1," ",rec) .eqs. v_string -$ then -$ version = 'f$element(2," ",rec)' -$ goto hdone -$ endif -$ goto hloop -$hdone: -$ close h_in -$ return -$!------------------------------------------------------------------------------ -$! -$CHECK_CONFIG: -$! -$ in_ldef = f$locate(cdef,libdefs) -$ if (in_ldef .lt. f$length(libdefs)) -$ then -$ write aconf "#define ''cdef' 1" -$ libdefs = f$extract(0,in_ldef,libdefs) + - - f$extract(in_ldef + f$length(cdef) + 1, - - f$length(libdefs) - in_ldef - f$length(cdef) - 1, - - libdefs) -$ else -$ if (f$type('cdef') .eqs. "INTEGER") -$ then -$ write aconf "#define ''cdef' ", 'cdef' -$ else -$ if (f$type('cdef') .eqs. "STRING") -$ then -$ write aconf "#define ''cdef' ", """", '''cdef'', """" -$ else -$ gosub check_cc_def -$ endif -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Check if this is a define relating to the properties of the C/C++ -$! compiler -$! -$ CHECK_CC_DEF: -$ if (cdef .eqs. "_LARGEFILE64_SOURCE") -$ then -$ copy sys$input: 'tc' -$ deck -#include "tconfig" -#define _LARGEFILE -#include - -int main(){ -FILE *fp; - fp = fopen("temp.txt","r"); - fseeko(fp,1,SEEK_SET); - fclose(fp); -} - -$ eod -$ test_inv = false -$ comm_h = false -$ gosub cc_prop_check -$ return -$ endif -$ write aconf "/* ", line, " */" -$ return -$!------------------------------------------------------------------------------ -$! -$! Check for properties of C/C++ compiler -$! -$! Version history -$! 0.01 20031020 First version to receive a number -$! 0.02 20031022 Added logic for defines with value -$! 0.03 20040309 Make sure local config file gets not deleted -$! 0.04 20041230 Also write include for configure run -$! 0.05 20050103 Add processing of "comment defines" -$CC_PROP_CHECK: -$ cc_prop = true -$ is_need = false -$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true) -$ if f$search(th) .eqs. "" then create 'th' -$ set message/nofac/noident/nosever/notext -$ on error then continue -$ cc 'tmpnam' -$ if .not. ($status) then cc_prop = false -$ on error then continue -$! The headers might lie about the capabilities of the RTL -$ link 'tmpnam',tmp.opt/opt -$ if .not. ($status) then cc_prop = false -$ set message/fac/ident/sever/text -$ on error then goto err_exit -$ delete/nolog 'tmpnam'.*;*/exclude='th' -$ if (cc_prop .and. .not. is_need) .or. - - (.not. cc_prop .and. is_need) -$ then -$ write sys$output "Checking for ''cdef'... yes" -$ if f$type('cdef_val'_yes) .nes. "" -$ then -$ if f$type('cdef_val'_yes) .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes) -$ if f$type('cdef_val'_yes) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes) -$ else -$ call write_config f$fao("#define !AS 1",cdef) -$ endif -$ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. - - (cdef .eqs. "_LARGEFILE64_SOURCE") then - - call write_config f$string("#define _LARGEFILE 1") -$ else -$ write sys$output "Checking for ''cdef'... no" -$ if (comm_h) -$ then - call write_config f$fao("/* !AS */",line) -$ else -$ if f$type('cdef_val'_no) .nes. "" -$ then -$ if f$type('cdef_val'_no) .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no) -$ if f$type('cdef_val'_no) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no) -$ else -$ call write_config f$fao("#undef !AS",cdef) -$ endif -$ endif -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Check for properties of C/C++ compiler with multiple result values -$! -$! Version history -$! 0.01 20040127 First version -$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05 -$CC_MPROP_CHECK: -$ cc_prop = true -$ i = 1 -$ idel = 1 -$ MT_LOOP: -$ if f$type(result_'i') .eqs. "STRING" -$ then -$ set message/nofac/noident/nosever/notext -$ on error then continue -$ cc 'tmpnam'_'i' -$ if .not. ($status) then cc_prop = false -$ on error then continue -$! The headers might lie about the capabilities of the RTL -$ link 'tmpnam'_'i',tmp.opt/opt -$ if .not. ($status) then cc_prop = false -$ set message/fac/ident/sever/text -$ on error then goto err_exit -$ delete/nolog 'tmpnam'_'i'.*;* -$ if (cc_prop) -$ then -$ write sys$output "Checking for ''cdef'... ", mdef_'i' -$ if f$type(mdef_'i') .eqs. "INTEGER" - - then call write_config f$fao("#define !AS !UL",cdef,mdef_'i') -$ if f$type('cdef_val'_yes) .eqs. "STRING" - - then call write_config f$fao("#define !AS !AS",cdef,mdef_'i') -$ goto msym_clean -$ else -$ i = i + 1 -$ goto mt_loop -$ endif -$ endif -$ write sys$output "Checking for ''cdef'... no" -$ call write_config f$fao("#undef !AS",cdef) -$ MSYM_CLEAN: -$ if (idel .le. msym_max) -$ then -$ delete/sym mdef_'idel' -$ idel = idel + 1 -$ goto msym_clean -$ endif -$ return -$!------------------------------------------------------------------------------ -$! -$! Write configuration to both permanent and temporary config file -$! -$! Version history -$! 0.01 20031029 First version to receive a number -$! -$WRITE_CONFIG: SUBROUTINE -$ write aconf 'p1' -$ open/append confh 'th' -$ write confh 'p1' -$ close confh -$ENDSUBROUTINE -$!------------------------------------------------------------------------------ -$! -$! Analyze the project map file and create the symbol vector for a shareable -$! image from it -$! -$! Version history -$! 0.01 20120128 First version -$! 0.02 20120226 Add pre-load logic -$! -$ MAP_2_SHOPT: Subroutine -$! -$ SAY := "WRITE_ SYS$OUTPUT" -$! -$ IF F$SEARCH("''P1'") .EQS. "" -$ THEN -$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" -$ goto exit_m2s -$ ENDIF -$ IF "''P2'" .EQS. "" -$ THEN -$ SAY "MAP_2_SHOPT: Error, no output file provided" -$ goto exit_m2s -$ ENDIF -$! -$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" -$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" -$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" -$ module4 = "inflateSync#uncompress#zlibVersion#compress" -$ open/read map 'p1 -$ if axp .or. ia64 -$ then -$ open/write aopt a.opt -$ open/write bopt b.opt -$ write aopt " CASE_SENSITIVE=YES" -$ write bopt "SYMBOL_VECTOR= (-" -$ mod_sym_num = 1 -$ MOD_SYM_LOOP: -$ if f$type(module'mod_sym_num') .nes. "" -$ then -$ mod_in = 0 -$ MOD_SYM_IN: -$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') -$ if shared_proc .nes. "#" -$ then -$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- - f$edit(shared_proc,"upcase"),shared_proc) -$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) -$ mod_in = mod_in + 1 -$ goto mod_sym_in -$ endif -$ mod_sym_num = mod_sym_num + 1 -$ goto mod_sym_loop -$ endif -$MAP_LOOP: -$ read/end=map_end map line -$ if (f$locate("{",line).lt. f$length(line)) .or. - - (f$locate("global:", line) .lt. f$length(line)) -$ then -$ proc = true -$ goto map_loop -$ endif -$ if f$locate("}",line).lt. f$length(line) then proc = false -$ if f$locate("local:", line) .lt. f$length(line) then proc = false -$ if proc -$ then -$ shared_proc = f$edit(line,"collapse") -$ chop_semi = f$locate(";", shared_proc) -$ if chop_semi .lt. f$length(shared_proc) then - - shared_proc = f$extract(0, chop_semi, shared_proc) -$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- - f$edit(shared_proc,"upcase"),shared_proc) -$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) -$ endif -$ goto map_loop -$MAP_END: -$ close/nolog aopt -$ close/nolog bopt -$ open/append libopt 'p2' -$ open/read aopt a.opt -$ open/read bopt b.opt -$ALOOP: -$ read/end=aloop_end aopt line -$ write libopt line -$ goto aloop -$ALOOP_END: -$ close/nolog aopt -$ sv = "" -$BLOOP: -$ read/end=bloop_end bopt svn -$ if (svn.nes."") -$ then -$ if (sv.nes."") then write libopt sv -$ sv = svn -$ endif -$ goto bloop -$BLOOP_END: -$ write libopt f$extract(0,f$length(sv)-2,sv), "-" -$ write libopt ")" -$ close/nolog bopt -$ delete/nolog/noconf a.opt;*,b.opt;* -$ else -$ if vax -$ then -$ open/append libopt 'p2' -$ mod_sym_num = 1 -$ VMOD_SYM_LOOP: -$ if f$type(module'mod_sym_num') .nes. "" -$ then -$ mod_in = 0 -$ VMOD_SYM_IN: -$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') -$ if shared_proc .nes. "#" -$ then -$ write libopt f$fao("UNIVERSAL=!AS",- - f$edit(shared_proc,"upcase")) -$ mod_in = mod_in + 1 -$ goto vmod_sym_in -$ endif -$ mod_sym_num = mod_sym_num + 1 -$ goto vmod_sym_loop -$ endif -$VMAP_LOOP: -$ read/end=vmap_end map line -$ if (f$locate("{",line).lt. f$length(line)) .or. - - (f$locate("global:", line) .lt. f$length(line)) -$ then -$ proc = true -$ goto vmap_loop -$ endif -$ if f$locate("}",line).lt. f$length(line) then proc = false -$ if f$locate("local:", line) .lt. f$length(line) then proc = false -$ if proc -$ then -$ shared_proc = f$edit(line,"collapse") -$ chop_semi = f$locate(";", shared_proc) -$ if chop_semi .lt. f$length(shared_proc) then - - shared_proc = f$extract(0, chop_semi, shared_proc) -$ write libopt f$fao("UNIVERSAL=!AS",- - f$edit(shared_proc,"upcase")) -$ endif -$ goto vmap_loop -$VMAP_END: -$ else -$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" -$ write sys$output "No options file created" -$ endif -$ endif -$ EXIT_M2S: -$ close/nolog map -$ close/nolog libopt -$ endsubroutine diff --git a/src/contrib/zlib/msdos/Makefile.bor b/src/contrib/zlib/msdos/Makefile.bor deleted file mode 100644 index 3d12a2c..0000000 --- a/src/contrib/zlib/msdos/Makefile.bor +++ /dev/null @@ -1,115 +0,0 @@ -# Makefile for zlib -# Borland C++ -# Last updated: 15-Mar-2003 - -# To use, do "make -fmakefile.bor" -# To compile in small model, set below: MODEL=s - -# WARNING: the small model is supported but only for small values of -# MAX_WBITS and MAX_MEM_LEVEL. For example: -# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to the LOC macro below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------ Turbo C++, Borland C++ ------------ - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added -# to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. -CPU_TYP = 0 - -# memory model: one of s, m, c, l (small, medium, compact, large) -MODEL=l - -# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version -CC=bcc -LD=bcc -AR=tlib - -# compiler flags -# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 -CFLAGS=-O2 -Z -m$(MODEL) $(LOC) - -LDFLAGS=-m$(MODEL) -f- - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del zlib_*.bak - -del foo.gz diff --git a/src/contrib/zlib/msdos/Makefile.dj2 b/src/contrib/zlib/msdos/Makefile.dj2 deleted file mode 100644 index 59d2037..0000000 --- a/src/contrib/zlib/msdos/Makefile.dj2 +++ /dev/null @@ -1,104 +0,0 @@ -# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.dj2; make test -fmakefile.dj2 -# -# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: -# -# make install -fmakefile.dj2 -# -# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as -# in the sample below if the pattern of the DJGPP distribution is to -# be followed. Remember that, while 'es around <=> are ignored in -# makefiles, they are *not* in batch files or in djgpp.env. -# - - - - - -# [make] -# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include -# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib -# BUTT=-m486 -# - - - - - -# Alternately, these variables may be defined below, overriding the values -# in djgpp.env, as -# INCLUDE_PATH=c:\usr\include -# LIBRARY_PATH=c:\usr\lib - -CC=gcc - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lz -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=libz.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -OBJA = -# to use the asm code: make OBJA=match.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -check: test -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -libz.a: $(OBJS) $(OBJA) - $(AR) $@ $(OBJS) $(OBJA) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - -# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . - -.PHONY : uninstall clean - -install: $(INCL) $(LIBS) - -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) - -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) - $(INSTALL) zlib.h $(INCLUDE_PATH) - $(INSTALL) zconf.h $(INCLUDE_PATH) - $(INSTALL) libz.a $(LIBRARY_PATH) - -uninstall: - $(RM) $(INCLUDE_PATH)\zlib.h - $(RM) $(INCLUDE_PATH)\zconf.h - $(RM) $(LIBRARY_PATH)\libz.a - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) libz.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/src/contrib/zlib/msdos/Makefile.emx b/src/contrib/zlib/msdos/Makefile.emx deleted file mode 100644 index e30f67b..0000000 --- a/src/contrib/zlib/msdos/Makefile.emx +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.emx; make test -fmakefile.emx -# - -CC=gcc - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lzlib -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=zlib.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ - uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -zlib.a: $(OBJS) - $(AR) $@ $(OBJS) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - - -.PHONY : clean - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) zlib.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/src/contrib/zlib/msdos/Makefile.msc b/src/contrib/zlib/msdos/Makefile.msc deleted file mode 100644 index ae83786..0000000 --- a/src/contrib/zlib/msdos/Makefile.msc +++ /dev/null @@ -1,112 +0,0 @@ -# Makefile for zlib -# Microsoft C 5.1 or later -# Last updated: 19-Mar-2003 - -# To use, do "make makefile.msc" -# To compile in small model, set below: MODEL=S - -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to the LOC macro below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------- Microsoft C 5.1 and later ------------- - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added -# to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. -CPU_TYP = 0 - -# Memory model: one of S, M, C, L (small, medium, compact, large) -MODEL=L - -CC=cl -CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) -#-Ox generates bad code with MSC 5.1 -LIB_CFLAGS=-Zl $(CFLAGS) - -LD=link -LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode -# "/farcall/packcode" are only useful for `large code' memory models -# but should be a "no-op" for small code models. - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(LIB_CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - $(CC) -c $(CFLAGS) $*.c - -minigzip.obj: test/minigzip.c zlib.h zconf.h - $(CC) -c $(CFLAGS) $*.c - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - if exist $(ZLIB_LIB) del $(ZLIB_LIB) - lib $(ZLIB_LIB) $(OBJ1); - lib $(ZLIB_LIB) $(OBJ2); - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del *.map - -del zlib_*.bak - -del foo.gz diff --git a/src/contrib/zlib/msdos/Makefile.tc b/src/contrib/zlib/msdos/Makefile.tc deleted file mode 100644 index 5aec82a..0000000 --- a/src/contrib/zlib/msdos/Makefile.tc +++ /dev/null @@ -1,100 +0,0 @@ -# Makefile for zlib -# Turbo C 2.01, Turbo C++ 1.01 -# Last updated: 15-Mar-2003 - -# To use, do "make -fmakefile.tc" -# To compile in small model, set below: MODEL=s - -# WARNING: the small model is supported but only for small values of -# MAX_WBITS and MAX_MEM_LEVEL. For example: -# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -# If you wish to reduce the memory requirements (default 256K for big -# objects plus a few K), you can add to CFLAGS below: -# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 -# See zconf.h for details about the memory requirements. - -# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------ -MODEL=l -CC=tcc -LD=tcc -AR=tlib -# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 -CFLAGS=-O2 -G -Z -m$(MODEL) -LDFLAGS=-m$(MODEL) -f- - - -# variables -ZLIB_LIB = zlib_$(MODEL).lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $*.c - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -clean: - -del *.obj - -del *.lib - -del *.exe - -del zlib_*.bak - -del foo.gz diff --git a/src/contrib/zlib/nintendods/Makefile b/src/contrib/zlib/nintendods/Makefile deleted file mode 100644 index 21337d0..0000000 --- a/src/contrib/zlib/nintendods/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/ds_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(shell basename $(CURDIR)) -BUILD := build -SOURCES := ../../ -DATA := data -INCLUDES := include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork - -CFLAGS := -Wall -O2\ - -march=armv5te -mtune=arm946e-s \ - -fomit-frame-pointer -ffast-math \ - $(ARCH) - -CFLAGS += $(INCLUDE) -DARM9 -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions - -ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s -LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(LIBNDS) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/lib/libz.a - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - @[ -d $@ ] || mkdir -p include - @cp ../../*.h include - -lib: - @[ -d $@ ] || mkdir -p $@ - -$(BUILD): lib - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) lib - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT) : $(OFILES) - -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/src/contrib/zlib/nintendods/README b/src/contrib/zlib/nintendods/README deleted file mode 100644 index ba7a37d..0000000 --- a/src/contrib/zlib/nintendods/README +++ /dev/null @@ -1,5 +0,0 @@ -This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. - -Eduardo Costa -January 3, 2009 - diff --git a/src/contrib/zlib/old/Makefile.emx b/src/contrib/zlib/old/Makefile.emx deleted file mode 100644 index 612b037..0000000 --- a/src/contrib/zlib/old/Makefile.emx +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. -# Copyright (C) 1995-1998 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type: -# -# make -fmakefile.emx; make test -fmakefile.emx -# - -CC=gcc -Zwin32 - -#CFLAGS=-MMD -O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DZLIB_DEBUG -CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ - -Wstrict-prototypes -Wmissing-prototypes - -# If cp.exe is available, replace "copy /Y" with "cp -fp" . -CP=copy /Y -# If gnu install.exe is available, replace $(CP) with ginstall. -INSTALL=$(CP) -# The default value of RM is "rm -f." If "rm.exe" is found, comment out: -RM=del -LDLIBS=-L. -lzlib -LD=$(CC) -s -o -LDSHARED=$(CC) - -INCL=zlib.h zconf.h -LIBS=zlib.a - -AR=ar rcs - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ - gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o - -TEST_OBJS = example.o minigzip.o - -all: example.exe minigzip.exe - -test: all - ./example - echo hello world | .\minigzip | .\minigzip -d - -%.o : %.c - $(CC) $(CFLAGS) -c $< -o $@ - -zlib.a: $(OBJS) - $(AR) $@ $(OBJS) - -%.exe : %.o $(LIBS) - $(LD) $@ $< $(LDLIBS) - - -.PHONY : clean - -clean: - $(RM) *.d - $(RM) *.o - $(RM) *.exe - $(RM) zlib.a - $(RM) foo.gz - -DEPS := $(wildcard *.d) -ifneq ($(DEPS),) -include $(DEPS) -endif diff --git a/src/contrib/zlib/old/Makefile.riscos b/src/contrib/zlib/old/Makefile.riscos deleted file mode 100644 index 57e29d3..0000000 --- a/src/contrib/zlib/old/Makefile.riscos +++ /dev/null @@ -1,151 +0,0 @@ -# Project: zlib_1_03 -# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 -# test works out-of-the-box, installs `somewhere' on demand - -# Toolflags: -CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah -C++flags = -c -depend !Depend -IC: -throwback -Linkflags = -aif -c++ -o $@ -ObjAsmflags = -throwback -NoCache -depend !Depend -CMHGflags = -LibFileflags = -c -l -o $@ -Squeezeflags = -o $@ - -# change the line below to where _you_ want the library installed. -libdest = lib:zlib - -# Final targets: -@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ - @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ - @.o.uncompr @.o.zutil - LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ - @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ - @.o.trees @.o.uncompr @.o.zutil -test: @.minigzip @.example @.lib - @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV - @echo running tests: hang on. - @/@.minigzip -f -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -f -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -h -1 libc - @/@.minigzip -d libc-gz - @/@.minigzip -9 libc - @/@.minigzip -d libc-gz - @/@.minigzip -1 libc - @/@.minigzip -d libc-gz - @diff @.lib @.libc - @echo that should have reported '@.lib and @.libc identical' if you have diff. - @/@.example @.fred @.fred - @echo that will have given lots of hello!'s. - -@.minigzip: @.o.minigzip @.lib C:o.Stubs - Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs -@.example: @.o.example @.lib C:o.Stubs - Link $(Linkflags) @.o.example @.lib C:o.Stubs - -install: @.lib - cdir $(libdest) - cdir $(libdest).h - @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV - @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV - @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV - @echo okay, installed zlib in $(libdest) - -clean:; remove @.minigzip - remove @.example - remove @.libc - -wipe @.o.* F~r~cV - remove @.fred - -# User-editable dependencies: -.c.o: - cc $(ccflags) -o $@ $< - -# Static dependencies: - -# Dynamic dependencies: -o.example: c.example -o.example: h.zlib -o.example: h.zconf -o.minigzip: c.minigzip -o.minigzip: h.zlib -o.minigzip: h.zconf -o.adler32: c.adler32 -o.adler32: h.zlib -o.adler32: h.zconf -o.compress: c.compress -o.compress: h.zlib -o.compress: h.zconf -o.crc32: c.crc32 -o.crc32: h.zlib -o.crc32: h.zconf -o.deflate: c.deflate -o.deflate: h.deflate -o.deflate: h.zutil -o.deflate: h.zlib -o.deflate: h.zconf -o.gzio: c.gzio -o.gzio: h.zutil -o.gzio: h.zlib -o.gzio: h.zconf -o.infblock: c.infblock -o.infblock: h.zutil -o.infblock: h.zlib -o.infblock: h.zconf -o.infblock: h.infblock -o.infblock: h.inftrees -o.infblock: h.infcodes -o.infblock: h.infutil -o.infcodes: c.infcodes -o.infcodes: h.zutil -o.infcodes: h.zlib -o.infcodes: h.zconf -o.infcodes: h.inftrees -o.infcodes: h.infblock -o.infcodes: h.infcodes -o.infcodes: h.infutil -o.infcodes: h.inffast -o.inffast: c.inffast -o.inffast: h.zutil -o.inffast: h.zlib -o.inffast: h.zconf -o.inffast: h.inftrees -o.inffast: h.infblock -o.inffast: h.infcodes -o.inffast: h.infutil -o.inffast: h.inffast -o.inflate: c.inflate -o.inflate: h.zutil -o.inflate: h.zlib -o.inflate: h.zconf -o.inflate: h.infblock -o.inftrees: c.inftrees -o.inftrees: h.zutil -o.inftrees: h.zlib -o.inftrees: h.zconf -o.inftrees: h.inftrees -o.inftrees: h.inffixed -o.infutil: c.infutil -o.infutil: h.zutil -o.infutil: h.zlib -o.infutil: h.zconf -o.infutil: h.infblock -o.infutil: h.inftrees -o.infutil: h.infcodes -o.infutil: h.infutil -o.trees: c.trees -o.trees: h.deflate -o.trees: h.zutil -o.trees: h.zlib -o.trees: h.zconf -o.trees: h.trees -o.uncompr: c.uncompr -o.uncompr: h.zlib -o.uncompr: h.zconf -o.zutil: c.zutil -o.zutil: h.zutil -o.zutil: h.zlib -o.zutil: h.zconf diff --git a/src/contrib/zlib/old/README b/src/contrib/zlib/old/README deleted file mode 100644 index 800bf07..0000000 --- a/src/contrib/zlib/old/README +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains files that have not been updated for zlib 1.2.x - -(Volunteers are encouraged to help clean this up. Thanks.) diff --git a/src/contrib/zlib/old/descrip.mms b/src/contrib/zlib/old/descrip.mms deleted file mode 100644 index 7066da5..0000000 --- a/src/contrib/zlib/old/descrip.mms +++ /dev/null @@ -1,48 +0,0 @@ -# descrip.mms: MMS description file for building zlib on VMS -# written by Martin P.J. Zinser - -cc_defs = -c_deb = - -.ifdef __DECC__ -pref = /prefix=all -.endif - -OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ - deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ - inftrees.obj, infcodes.obj, infutil.obj, inffast.obj - -CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) - -all : example.exe minigzip.exe - @ write sys$output " Example applications available" -libz.olb : libz.olb($(OBJS)) - @ write sys$output " libz available" - -example.exe : example.obj libz.olb - link example,libz.olb/lib - -minigzip.exe : minigzip.obj libz.olb - link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib - -clean : - delete *.obj;*,libz.olb;* - - -# Other dependencies. -adler32.obj : zutil.h zlib.h zconf.h -compress.obj : zlib.h zconf.h -crc32.obj : zutil.h zlib.h zconf.h -deflate.obj : deflate.h zutil.h zlib.h zconf.h -example.obj : zlib.h zconf.h -gzio.obj : zutil.h zlib.h zconf.h -infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h -inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h -inflate.obj : zutil.h zlib.h zconf.h infblock.h -inftrees.obj : zutil.h zlib.h zconf.h inftrees.h -infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h -minigzip.obj : zlib.h zconf.h -trees.obj : deflate.h zutil.h zlib.h zconf.h -uncompr.obj : zlib.h zconf.h -zutil.obj : zutil.h zlib.h zconf.h diff --git a/src/contrib/zlib/old/os2/Makefile.os2 b/src/contrib/zlib/old/os2/Makefile.os2 deleted file mode 100644 index bb426c0..0000000 --- a/src/contrib/zlib/old/os2/Makefile.os2 +++ /dev/null @@ -1,136 +0,0 @@ -# Makefile for zlib under OS/2 using GCC (PGCC) -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# cp Makefile.os2 .. -# cd .. -# make -f Makefile.os2 test - -# This makefile will build a static library z.lib, a shared library -# z.dll and a import library zdll.lib. You can use either z.lib or -# zdll.lib by specifying either -lz or -lzdll on gcc's command line - -CC=gcc -Zomf -s - -CFLAGS=-O6 -Wall -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DZLIB_DEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -#################### BUG WARNING: ##################### -## infcodes.c hits a bug in pgcc-1.0, so you have to use either -## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) -## This bug is reportedly fixed in pgcc >1.0, but this was not tested -CFLAGS+=-fno-force-mem - -LDFLAGS=-s -L. -lzdll -Zcrtdll -LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll - -VER=1.1.0 -ZLIB=z.lib -SHAREDLIB=z.dll -SHAREDLIBIMP=zdll.lib -LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) - -AR=emxomfar cr -IMPLIB=emximp -RANLIB=echo -TAR=tar -SHELL=bash - -prefix=/usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ - zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o - -TEST_OBJS = example.o minigzip.o - -DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ - algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ - nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ - contrib/asm386/*.asm contrib/asm386/*.c \ - contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ - contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ - contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 - -all: example.exe minigzip.exe - -test: all - @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - echo hello world | ./minigzip | ./minigzip -d || \ - echo ' *** minigzip test FAILED ***' ; \ - if ./example; then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; \ - fi - -$(ZLIB): $(OBJS) - $(AR) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -$(SHAREDLIB): $(OBJS) os2/z.def - $(LDSHARED) -o $@ $^ - -$(SHAREDLIBIMP): os2/z.def - $(IMPLIB) -o $@ $^ - -example.exe: example.o $(LIBS) - $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) - -minigzip.exe: minigzip.o $(LIBS) - $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) - -clean: - rm -f *.o *~ example minigzip libz.a libz.so* foo.gz - -distclean: clean - -zip: - mv Makefile Makefile~; cp -p Makefile.in Makefile - rm -f test.c ztest*.c - v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ - zip -ul9 zlib$$v $(DISTFILES) - mv Makefile~ Makefile - -dist: - mv Makefile Makefile~; cp -p Makefile.in Makefile - rm -f test.c ztest*.c - d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ - rm -f $$d.tar.gz; \ - if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ - files=""; \ - for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ - cd ..; \ - GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ - if test ! -d $$d; then rm -f $$d; fi - mv Makefile~ Makefile - -tags: - etags *.[ch] - -depend: - makedepend -- $(CFLAGS) -- *.[ch] - -# DO NOT DELETE THIS LINE -- make depend depends on it. - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -example.o: zlib.h zconf.h -gzio.o: zutil.h zlib.h zconf.h -infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h -infcodes.o: zutil.h zlib.h zconf.h -infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h -inffast.o: infblock.h infcodes.h infutil.h inffast.h -inflate.o: zutil.h zlib.h zconf.h infblock.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h -minigzip.o: zlib.h zconf.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/src/contrib/zlib/old/os2/zlib.def b/src/contrib/zlib/old/os2/zlib.def deleted file mode 100644 index 4c753f1..0000000 --- a/src/contrib/zlib/old/os2/zlib.def +++ /dev/null @@ -1,51 +0,0 @@ -; -; Slightly modified version of ../nt/zlib.dnt :-) -; - -LIBRARY Z -DESCRIPTION "Zlib compression library for OS/2" -CODE PRELOAD MOVEABLE DISCARDABLE -DATA PRELOAD MOVEABLE MULTIPLE - -EXPORTS - adler32 - compress - crc32 - deflate - deflateCopy - deflateEnd - deflateInit2_ - deflateInit_ - deflateParams - deflateReset - deflateSetDictionary - gzclose - gzdopen - gzerror - gzflush - gzopen - gzread - gzwrite - inflate - inflateEnd - inflateInit2_ - inflateInit_ - inflateReset - inflateSetDictionary - inflateSync - uncompress - zlibVersion - gzprintf - gzputc - gzgetc - gzseek - gzrewind - gztell - gzeof - gzsetparams - zError - inflateSyncPoint - get_crc_table - compress2 - gzputs - gzgets diff --git a/src/contrib/zlib/old/visual-basic.txt b/src/contrib/zlib/old/visual-basic.txt deleted file mode 100644 index 57efe58..0000000 --- a/src/contrib/zlib/old/visual-basic.txt +++ /dev/null @@ -1,160 +0,0 @@ -See below some functions declarations for Visual Basic. - -Frequently Asked Question: - -Q: Each time I use the compress function I get the -5 error (not enough - room in the output buffer). - -A: Make sure that the length of the compressed buffer is passed by - reference ("as any"), not by value ("as long"). Also check that - before the call of compress this length is equal to the total size of - the compressed buffer and not zero. - - -From: "Jon Caruana" -Subject: Re: How to port zlib declares to vb? -Date: Mon, 28 Oct 1996 18:33:03 -0600 - -Got the answer! (I haven't had time to check this but it's what I got, and -looks correct): - -He has the following routines working: - compress - uncompress - gzopen - gzwrite - gzread - gzclose - -Declares follow: (Quoted from Carlos Rios , in Vb4 form) - -#If Win16 Then 'Use Win16 calls. -Declare Function compress Lib "ZLIB.DLL" (ByVal compr As - String, comprLen As Any, ByVal buf As String, ByVal buflen - As Long) As Integer -Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr - As String, uncomprLen As Any, ByVal compr As String, ByVal - lcompr As Long) As Integer -Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As - String, ByVal mode As String) As Long -Declare Function gzread Lib "ZLIB.DLL" (ByVal file As - Long, ByVal uncompr As String, ByVal uncomprLen As Integer) - As Integer -Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As - Long, ByVal uncompr As String, ByVal uncomprLen As Integer) - As Integer -Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As - Long) As Integer -#Else -Declare Function compress Lib "ZLIB32.DLL" - (ByVal compr As String, comprLen As Any, ByVal buf As - String, ByVal buflen As Long) As Integer -Declare Function uncompress Lib "ZLIB32.DLL" - (ByVal uncompr As String, uncomprLen As Any, ByVal compr As - String, ByVal lcompr As Long) As Long -Declare Function gzopen Lib "ZLIB32.DLL" - (ByVal file As String, ByVal mode As String) As Long -Declare Function gzread Lib "ZLIB32.DLL" - (ByVal file As Long, ByVal uncompr As String, ByVal - uncomprLen As Long) As Long -Declare Function gzwrite Lib "ZLIB32.DLL" - (ByVal file As Long, ByVal uncompr As String, ByVal - uncomprLen As Long) As Long -Declare Function gzclose Lib "ZLIB32.DLL" - (ByVal file As Long) As Long -#End If - --Jon Caruana -jon-net@usa.net -Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member - - -Here is another example from Michael that he -says conforms to the VB guidelines, and that solves the problem of not -knowing the uncompressed size by storing it at the end of the file: - -'Calling the functions: -'bracket meaning: [optional] {Range of possible values} -'Call subCompressFile( [, , [level of compression {1..9}]]) -'Call subUncompressFile() - -Option Explicit -Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller' -Private Const SUCCESS As Long = 0 -Private Const strFilExt As String = ".cpr" -Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef -dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long, -ByVal level As Integer) As Long -Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef -dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long) -As Long - -Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal -strargCprFilPth As String, Optional ByVal intLvl As Integer = 9) - Dim strCprPth As String - Dim lngOriSiz As Long - Dim lngCprSiz As Long - Dim bytaryOri() As Byte - Dim bytaryCpr() As Byte - lngOriSiz = FileLen(strargOriFilPth) - ReDim bytaryOri(lngOriSiz - 1) - Open strargOriFilPth For Binary Access Read As #1 - Get #1, , bytaryOri() - Close #1 - strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth) -'Select file path and name - strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) = -strFilExt, "", strFilExt) 'Add file extension if not exists - lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit -more space then original file size - ReDim bytaryCpr(lngCprSiz - 1) - If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) = -SUCCESS Then - lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100 - ReDim Preserve bytaryCpr(lngCprSiz - 1) - Open strCprPth For Binary Access Write As #1 - Put #1, , bytaryCpr() - Put #1, , lngOriSiz 'Add the the original size value to the end -(last 4 bytes) - Close #1 - Else - MsgBox "Compression error" - End If - Erase bytaryCpr - Erase bytaryOri -End Sub - -Public Sub subUncompressFile(ByVal strargFilPth As String) - Dim bytaryCpr() As Byte - Dim bytaryOri() As Byte - Dim lngOriSiz As Long - Dim lngCprSiz As Long - Dim strOriPth As String - lngCprSiz = FileLen(strargFilPth) - ReDim bytaryCpr(lngCprSiz - 1) - Open strargFilPth For Binary Access Read As #1 - Get #1, , bytaryCpr() - Close #1 - 'Read the original file size value: - lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _ - + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _ - + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _ - + bytaryCpr(lngCprSiz - 4) - ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value - ReDim bytaryOri(lngOriSiz - 1) - If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS -Then - strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt)) - Open strOriPth For Binary Access Write As #1 - Put #1, , bytaryOri() - Close #1 - Else - MsgBox "Uncompression error" - End If - Erase bytaryCpr - Erase bytaryOri -End Sub -Public Property Get lngPercentSmaller() As Long - lngPercentSmaller = lngpvtPcnSml -End Property diff --git a/src/contrib/zlib/os400/README400 b/src/contrib/zlib/os400/README400 deleted file mode 100644 index 4f98334..0000000 --- a/src/contrib/zlib/os400/README400 +++ /dev/null @@ -1,48 +0,0 @@ - ZLIB version 1.2.11 for OS/400 installation instructions - -1) Download and unpack the zlib tarball to some IFS directory. - (i.e.: /path/to/the/zlib/ifs/source/directory) - - If the installed IFS command suppors gzip format, this is straightforward, -else you have to unpack first to some directory on a system supporting it, -then move the whole directory to the IFS via the network (via SMB or FTP). - -2) Edit the configuration parameters in the compilation script. - - EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh') - -Tune the parameters according to your needs if not matching the defaults. -Save the file and exit after edition. - -3) Enter qshell, then work in the zlib OS/400 specific directory. - - QSH - cd /path/to/the/zlib/ifs/source/directory/os400 - -4) Compile and install - - sh make.sh - -The script will: -- create the libraries, objects and IFS directories for the zlib environment, -- compile all modules, -- create a service program, -- create a static and a dynamic binding directory, -- install header files for C/C++ and for ILE/RPG, both for compilation in - DB2 and IFS environments. - -That's all. - - -Notes: For OS/400 ILE RPG programmers, a /copy member defining the ZLIB - API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). - In the ILE environment, the same definitions are available from - file zlib.inc located in the same IFS include directory as the - C/C++ header files. - Please read comments in this member for more information. - - Remember that most foreign textual data are ASCII coded: this - implementation does not handle conversion from/to ASCII, so - text data code conversions must be done explicitely. - - Mainly for the reason above, always open zipped files in binary mode. diff --git a/src/contrib/zlib/os400/bndsrc b/src/contrib/zlib/os400/bndsrc deleted file mode 100644 index 5e6e0a2..0000000 --- a/src/contrib/zlib/os400/bndsrc +++ /dev/null @@ -1,119 +0,0 @@ -STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.1.3 entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32") - EXPORT SYMBOL("compress") - EXPORT SYMBOL("compress2") - EXPORT SYMBOL("crc32") - EXPORT SYMBOL("get_crc_table") - EXPORT SYMBOL("deflate") - EXPORT SYMBOL("deflateEnd") - EXPORT SYMBOL("deflateSetDictionary") - EXPORT SYMBOL("deflateCopy") - EXPORT SYMBOL("deflateReset") - EXPORT SYMBOL("deflateParams") - EXPORT SYMBOL("deflatePrime") - EXPORT SYMBOL("deflateInit_") - EXPORT SYMBOL("deflateInit2_") - EXPORT SYMBOL("gzopen") - EXPORT SYMBOL("gzdopen") - EXPORT SYMBOL("gzsetparams") - EXPORT SYMBOL("gzread") - EXPORT SYMBOL("gzwrite") - EXPORT SYMBOL("gzprintf") - EXPORT SYMBOL("gzputs") - EXPORT SYMBOL("gzgets") - EXPORT SYMBOL("gzputc") - EXPORT SYMBOL("gzgetc") - EXPORT SYMBOL("gzflush") - EXPORT SYMBOL("gzseek") - EXPORT SYMBOL("gzrewind") - EXPORT SYMBOL("gztell") - EXPORT SYMBOL("gzeof") - EXPORT SYMBOL("gzclose") - EXPORT SYMBOL("gzerror") - EXPORT SYMBOL("inflate") - EXPORT SYMBOL("inflateEnd") - EXPORT SYMBOL("inflateSetDictionary") - EXPORT SYMBOL("inflateSync") - EXPORT SYMBOL("inflateReset") - EXPORT SYMBOL("inflateInit_") - EXPORT SYMBOL("inflateInit2_") - EXPORT SYMBOL("inflateSyncPoint") - EXPORT SYMBOL("uncompress") - EXPORT SYMBOL("zlibVersion") - EXPORT SYMBOL("zError") - EXPORT SYMBOL("z_errmsg") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.1 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("compressBound") - EXPORT SYMBOL("deflateBound") - EXPORT SYMBOL("deflatePending") - EXPORT SYMBOL("gzungetc") - EXPORT SYMBOL("gzclearerr") - EXPORT SYMBOL("inflateBack") - EXPORT SYMBOL("inflateBackEnd") - EXPORT SYMBOL("inflateBackInit_") - EXPORT SYMBOL("inflateCopy") - EXPORT SYMBOL("zlibCompileFlags") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.4 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32_combine") - EXPORT SYMBOL("adler32_combine64") - EXPORT SYMBOL("crc32_combine") - EXPORT SYMBOL("crc32_combine64") - EXPORT SYMBOL("deflateSetHeader") - EXPORT SYMBOL("deflateTune") - EXPORT SYMBOL("gzbuffer") - EXPORT SYMBOL("gzclose_r") - EXPORT SYMBOL("gzclose_w") - EXPORT SYMBOL("gzdirect") - EXPORT SYMBOL("gzoffset") - EXPORT SYMBOL("gzoffset64") - EXPORT SYMBOL("gzopen64") - EXPORT SYMBOL("gzseek64") - EXPORT SYMBOL("gztell64") - EXPORT SYMBOL("inflateGetHeader") - EXPORT SYMBOL("inflateMark") - EXPORT SYMBOL("inflatePrime") - EXPORT SYMBOL("inflateReset2") - EXPORT SYMBOL("inflateUndermine") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.6 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("deflateResetKeep") - EXPORT SYMBOL("gzgetc_") - EXPORT SYMBOL("inflateResetKeep") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.8 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("gzvprintf") - EXPORT SYMBOL("inflateGetDictionary") - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/* Version 1.2.9 additional entry points. */ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - EXPORT SYMBOL("adler32_z") - EXPORT SYMBOL("crc32_z") - EXPORT SYMBOL("deflateGetDictionary") - EXPORT SYMBOL("gzfread") - EXPORT SYMBOL("gzfwrite") - EXPORT SYMBOL("inflateCodesUsed") - EXPORT SYMBOL("inflateValidate") - EXPORT SYMBOL("uncompress2") - -ENDPGMEXP diff --git a/src/contrib/zlib/os400/make.sh b/src/contrib/zlib/os400/make.sh deleted file mode 100644 index 19eec11..0000000 --- a/src/contrib/zlib/os400/make.sh +++ /dev/null @@ -1,366 +0,0 @@ -#!/bin/sh -# -# ZLIB compilation script for the OS/400. -# -# -# This is a shell script since make is not a standard component of OS/400. - - -################################################################################ -# -# Tunable configuration parameters. -# -################################################################################ - -TARGETLIB='ZLIB' # Target OS/400 program library -STATBNDDIR='ZLIB_A' # Static binding directory. -DYNBNDDIR='ZLIB' # Dynamic binding directory. -SRVPGM="ZLIB" # Service program. -IFSDIR='/zlib' # IFS support base directory. -TGTCCSID='500' # Target CCSID of objects -DEBUG='*NONE' # Debug level -OPTIMIZE='40' # Optimisation level -OUTPUT='*NONE' # Compilation output option. -TGTRLS='V6R1M0' # Target OS release - -export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM IFSDIR -export TGTCCSID DEBUG OPTIMIZE OUTPUT TGTRLS - - -################################################################################ -# -# OS/400 specific definitions. -# -################################################################################ - -LIBIFSNAME="/QSYS.LIB/${TARGETLIB}.LIB" - - -################################################################################ -# -# Procedures. -# -################################################################################ - -# action_needed dest [src] -# -# dest is an object to build -# if specified, src is an object on which dest depends. -# -# exit 0 (succeeds) if some action has to be taken, else 1. - -action_needed() - -{ - [ ! -e "${1}" ] && return 0 - [ "${2}" ] || return 1 - [ "${1}" -ot "${2}" ] && return 0 - return 1 -} - - -# make_module module_name source_name [additional_definitions] -# -# Compile source name into module if needed. -# As side effect, append the module name to variable MODULES. -# Set LINK to "YES" if the module has been compiled. - -make_module() - -{ - MODULES="${MODULES} ${1}" - MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" - CSRC="`basename \"${2}\"`" - - if action_needed "${MODIFSNAME}" "${2}" - then : - elif [ ! "`sed -e \"//,/<\\\\/source>/!d\" \ - -e '/ tmphdrfile - - # Need to translate to target CCSID. - - CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DEST}')" - CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" - system "${CMD}" - # touch -r "${HFILE}" "${DEST}" - rm -f tmphdrfile - fi - - IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" - - if action_needed "${IFSFILE}" "${DEST}" - then rm -f "${IFSFILE}" - ln -s "${DEST}" "${IFSFILE}" - fi -done - - -# Install the ILE/RPG header file. - - -HFILE="${SCRIPTDIR}/zlib.inc" -DEST="${SRCPF}/ZLIB.INC.MBR" - -if action_needed "${DEST}" "${HFILE}" -then CMD="CPY OBJ('${HFILE}') TOOBJ('${DEST}')" - CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" - system "${CMD}" - # touch -r "${HFILE}" "${DEST}" -fi - -IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" - -if action_needed "${IFSFILE}" "${DEST}" -then rm -f "${IFSFILE}" - ln -s "${DEST}" "${IFSFILE}" -fi - - -# Create and compile the identification source file. - -echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c -echo '#pragma comment(user, __DATE__)' >> os400.c -echo '#pragma comment(user, __TIME__)' >> os400.c -echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c -make_module OS400 os400.c -LINK= # No need to rebuild service program yet. -MODULES= - - -# Get source list. - -CSOURCES=`sed -e '/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Library - - Medium - - 2.0 - - - - zlib - zlib - alain.bonnefoy@icbt.com - Public - public - www.gzip.org/zlib - - - Jean-Loup Gailly,Mark Adler - www.gzip.org/zlib - - zlib@gzip.org - - - A massively spiffy yet delicately unobtrusive compression library. - zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system. - http://www.gzip.org/zlib - - - - - 1.2.11 - Medium - Stable - - - - - - - No License - - - - Software Development/Libraries and Extensions/C Libraries - zlib,compression - qnx6 - qnx6 - None - Developer - - - - - - - - - - - - - - Install - Post - No - Ignore - - No - Optional - - - - - - - - - - - - - InstallOver - zlib - - - - - - - - - - - - - InstallOver - zlib-dev - - - - - - - - - diff --git a/src/contrib/zlib/test/example.c b/src/contrib/zlib/test/example.c deleted file mode 100644 index 3090dba..0000000 --- a/src/contrib/zlib/test/example.c +++ /dev/null @@ -1,602 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "../zlib.h" -#include - -#ifdef STDC -# include -# include -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static z_const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -static const char dictionary[] = "hello"; -static uLong dictId; /* Adler32 value of the dictionary */ - -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - - -#ifdef Z_SOLO - -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ - (void)q; - return calloc(n, m); -} - -void myfree(void *q, void *p) -{ - (void)q; - free(p); -} - -static alloc_func zalloc = myalloc; -static free_func zfree = myfree; - -#else /* !Z_SOLO */ - -static alloc_func zalloc = (alloc_func)0; -static free_func zfree = (free_func)0; - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *fname, - Byte *uncompr, uLong uncomprLen)); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = (uLong)strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(fname, uncompr, uncomprLen) - const char *fname; /* compressed file name */ - Byte *uncompr; - uLong uncomprLen; -{ -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - int len = (int)strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - strcpy((char*)uncompr, "garbage"); - - if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - if (gzungetc(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - - gzclose(file); -#endif -} - -#endif /* Z_SOLO */ - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uLong len = (uLong)strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - uInt len = (uInt)strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - err = inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, (int)sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - (int)sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - -#ifdef Z_SOLO - (void)argc; - (void)argv; -#else - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); -#endif - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/src/contrib/zlib/test/infcover.c b/src/contrib/zlib/test/infcover.c deleted file mode 100644 index e45b6cb..0000000 --- a/src/contrib/zlib/test/infcover.c +++ /dev/null @@ -1,671 +0,0 @@ -/* infcover.c -- test zlib's inflate routines with full code coverage - * Copyright (C) 2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* to use, do: ./configure --cover && make cover */ - -#include -#include -#include -#include -#include "../zlib.h" - -/* get definition of internal structure so we can mess with it (see pull()), - and so we can call inflate_trees() (see cover5()) */ -#define ZLIB_INTERNAL -#include "inftrees.h" -#include "inflate.h" - -#define local static - -/* -- memory tracking routines -- */ - -/* - These memory tracking routines are provided to zlib and track all of zlib's - allocations and deallocations, check for LIFO operations, keep a current - and high water mark of total bytes requested, optionally set a limit on the - total memory that can be allocated, and when done check for memory leaks. - - They are used as follows: - - z_stream strm; - mem_setup(&strm) initializes the memory tracking and sets the - zalloc, zfree, and opaque members of strm to use - memory tracking for all zlib operations on strm - mem_limit(&strm, limit) sets a limit on the total bytes requested -- a - request that exceeds this limit will result in an - allocation failure (returns NULL) -- setting the - limit to zero means no limit, which is the default - after mem_setup() - mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used - mem_high(&strm, "msg") prints to stderr "msg" and the high water mark - mem_done(&strm, "msg") ends memory tracking, releases all allocations - for the tracking as well as leaked zlib blocks, if - any. If there was anything unusual, such as leaked - blocks, non-FIFO frees, or frees of addresses not - allocated, then "msg" and information about the - problem is printed to stderr. If everything is - normal, nothing is printed. mem_done resets the - strm members to Z_NULL to use the default memory - allocation routines on the next zlib initialization - using strm. - */ - -/* these items are strung together in a linked list, one for each allocation */ -struct mem_item { - void *ptr; /* pointer to allocated memory */ - size_t size; /* requested size of allocation */ - struct mem_item *next; /* pointer to next item in list, or NULL */ -}; - -/* this structure is at the root of the linked list, and tracks statistics */ -struct mem_zone { - struct mem_item *first; /* pointer to first item in list, or NULL */ - size_t total, highwater; /* total allocations, and largest total */ - size_t limit; /* memory allocation limit, or 0 if no limit */ - int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ -}; - -/* memory allocation routine to pass to zlib */ -local void *mem_alloc(void *mem, unsigned count, unsigned size) -{ - void *ptr; - struct mem_item *item; - struct mem_zone *zone = mem; - size_t len = count * (size_t)size; - - /* induced allocation failure */ - if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) - return NULL; - - /* perform allocation using the standard library, fill memory with a - non-zero value to make sure that the code isn't depending on zeros */ - ptr = malloc(len); - if (ptr == NULL) - return NULL; - memset(ptr, 0xa5, len); - - /* create a new item for the list */ - item = malloc(sizeof(struct mem_item)); - if (item == NULL) { - free(ptr); - return NULL; - } - item->ptr = ptr; - item->size = len; - - /* insert item at the beginning of the list */ - item->next = zone->first; - zone->first = item; - - /* update the statistics */ - zone->total += item->size; - if (zone->total > zone->highwater) - zone->highwater = zone->total; - - /* return the allocated memory */ - return ptr; -} - -/* memory free routine to pass to zlib */ -local void mem_free(void *mem, void *ptr) -{ - struct mem_item *item, *next; - struct mem_zone *zone = mem; - - /* if no zone, just do a free */ - if (zone == NULL) { - free(ptr); - return; - } - - /* point next to the item that matches ptr, or NULL if not found -- remove - the item from the linked list if found */ - next = zone->first; - if (next) { - if (next->ptr == ptr) - zone->first = next->next; /* first one is it, remove from list */ - else { - do { /* search the linked list */ - item = next; - next = item->next; - } while (next != NULL && next->ptr != ptr); - if (next) { /* if found, remove from linked list */ - item->next = next->next; - zone->notlifo++; /* not a LIFO free */ - } - - } - } - - /* if found, update the statistics and free the item */ - if (next) { - zone->total -= next->size; - free(next); - } - - /* if not found, update the rogue count */ - else - zone->rogue++; - - /* in any case, do the requested free with the standard library function */ - free(ptr); -} - -/* set up a controlled memory allocation space for monitoring, set the stream - parameters to the controlled routines, with opaque pointing to the space */ -local void mem_setup(z_stream *strm) -{ - struct mem_zone *zone; - - zone = malloc(sizeof(struct mem_zone)); - assert(zone != NULL); - zone->first = NULL; - zone->total = 0; - zone->highwater = 0; - zone->limit = 0; - zone->notlifo = 0; - zone->rogue = 0; - strm->opaque = zone; - strm->zalloc = mem_alloc; - strm->zfree = mem_free; -} - -/* set a limit on the total memory allocation, or 0 to remove the limit */ -local void mem_limit(z_stream *strm, size_t limit) -{ - struct mem_zone *zone = strm->opaque; - - zone->limit = limit; -} - -/* show the current total requested allocations in bytes */ -local void mem_used(z_stream *strm, char *prefix) -{ - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); -} - -/* show the high water allocation in bytes */ -local void mem_high(z_stream *strm, char *prefix) -{ - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); -} - -/* release the memory allocation zone -- if there are any surprises, notify */ -local void mem_done(z_stream *strm, char *prefix) -{ - int count = 0; - struct mem_item *item, *next; - struct mem_zone *zone = strm->opaque; - - /* show high water mark */ - mem_high(strm, prefix); - - /* free leftover allocations and item structures, if any */ - item = zone->first; - while (item != NULL) { - free(item->ptr); - next = item->next; - free(item); - item = next; - count++; - } - - /* issue alerts about anything unexpected */ - if (count || zone->total) - fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", - prefix, zone->total, count); - if (zone->notlifo) - fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); - if (zone->rogue) - fprintf(stderr, "** %s: %d frees not recognized\n", - prefix, zone->rogue); - - /* free the zone and delete from the stream */ - free(zone); - strm->opaque = Z_NULL; - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; -} - -/* -- inflate test routines -- */ - -/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This - decodes liberally, in that hex digits can be adjacent, in which case two in - a row writes a byte. Or they can be delimited by any non-hex character, - where the delimiters are ignored except when a single hex digit is followed - by a delimiter, where that single digit writes a byte. The returned data is - allocated and must eventually be freed. NULL is returned if out of memory. - If the length is not needed, then len can be NULL. */ -local unsigned char *h2b(const char *hex, unsigned *len) -{ - unsigned char *in, *re; - unsigned next, val; - - in = malloc((strlen(hex) + 1) >> 1); - if (in == NULL) - return NULL; - next = 0; - val = 1; - do { - if (*hex >= '0' && *hex <= '9') - val = (val << 4) + *hex - '0'; - else if (*hex >= 'A' && *hex <= 'F') - val = (val << 4) + *hex - 'A' + 10; - else if (*hex >= 'a' && *hex <= 'f') - val = (val << 4) + *hex - 'a' + 10; - else if (val != 1 && val < 32) /* one digit followed by delimiter */ - val += 240; /* make it look like two digits */ - if (val > 255) { /* have two digits */ - in[next++] = val & 0xff; /* save the decoded byte */ - val = 1; /* start over */ - } - } while (*hex++); /* go through the loop with the terminating null */ - if (len != NULL) - *len = next; - re = realloc(in, next); - return re == NULL ? in : re; -} - -/* generic inflate() run, where hex is the hexadecimal input data, what is the - text to include in an error message, step is how much input data to feed - inflate() on each call, or zero to feed it all, win is the window bits - parameter to inflateInit2(), len is the size of the output buffer, and err - is the error code expected from the first inflate() call (the second - inflate() call is expected to return Z_STREAM_END). If win is 47, then - header information is collected with inflateGetHeader(). If a zlib stream - is looking for a dictionary, then an empty dictionary is provided. - inflate() is run until all of the input data is consumed. */ -local void inf(char *hex, char *what, unsigned step, int win, unsigned len, - int err) -{ - int ret; - unsigned have; - unsigned char *in, *out; - z_stream strm, copy; - gz_header head; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, win); - if (ret != Z_OK) { - mem_done(&strm, what); - return; - } - out = malloc(len); assert(out != NULL); - if (win == 47) { - head.extra = out; - head.extra_max = len; - head.name = out; - head.name_max = len; - head.comment = out; - head.comm_max = len; - ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); - } - in = h2b(hex, &have); assert(in != NULL); - if (step == 0 || step > have) - step = have; - strm.avail_in = step; - have -= step; - strm.next_in = in; - do { - strm.avail_out = len; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); - if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) - break; - if (ret == Z_NEED_DICT) { - ret = inflateSetDictionary(&strm, in, 1); - assert(ret == Z_DATA_ERROR); - mem_limit(&strm, 1); - ret = inflateSetDictionary(&strm, out, 0); - assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ((struct inflate_state *)strm.state)->mode = DICT; - ret = inflateSetDictionary(&strm, out, 0); - assert(ret == Z_OK); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); - } - ret = inflateCopy(©, &strm); assert(ret == Z_OK); - ret = inflateEnd(©); assert(ret == Z_OK); - err = 9; /* don't care next time around */ - have += strm.avail_in; - strm.avail_in = step > have ? have : step; - have -= strm.avail_in; - } while (strm.avail_in); - free(in); - free(out); - ret = inflateReset2(&strm, -8); assert(ret == Z_OK); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, what); -} - -/* cover all of the lines in inflate.c up to inflate() */ -local void cover_support(void) -{ - int ret; - z_stream strm; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); assert(ret == Z_OK); - mem_used(&strm, "inflate init"); - ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); - ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); - ret = inflateSetDictionary(&strm, Z_NULL, 0); - assert(ret == Z_STREAM_ERROR); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "prime"); - - inf("63 0", "force window allocation", 0, -15, 1, Z_OK); - inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); - inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); - inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); - inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); - assert(ret == Z_VERSION_ERROR); - mem_done(&strm, "wrong version"); - - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); assert(ret == Z_OK); - ret = inflateEnd(&strm); assert(ret == Z_OK); - fputs("inflate built-in memory routines\n", stderr); -} - -/* cover all inflate() header and trailer cases and code after inflate() */ -local void cover_wrap(void) -{ - int ret; - z_stream strm, copy; - unsigned char dict[257]; - - ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); - ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); - ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflate bad parameters\n", stderr); - - inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); - inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); - inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); - inf("8 99", "set window size from header", 0, 0, 0, Z_OK); - inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); - inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); - inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, - Z_DATA_ERROR); - inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", - 0, 47, 0, Z_STREAM_END); - inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); - inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); - inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, -8); - strm.avail_in = 2; - strm.next_in = (void *)"\x63"; - strm.avail_out = 1; - strm.next_out = (void *)&ret; - mem_limit(&strm, 1); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - memset(dict, 0, 257); - ret = inflateSetDictionary(&strm, dict, 257); - assert(ret == Z_OK); - mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); - ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x80"; - ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); - ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); - strm.avail_in = 4; - strm.next_in = (void *)"\0\0\xff\xff"; - ret = inflateSync(&strm); assert(ret == Z_OK); - (void)inflateSyncPoint(&strm); - ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); - (void)inflateMark(&strm); - ret = inflateEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "miscellaneous, force memory errors"); -} - -/* input and output functions for inflateBack() */ -local unsigned pull(void *desc, unsigned char **buf) -{ - static unsigned int next = 0; - static unsigned char dat[] = {0x63, 0, 2, 0}; - struct inflate_state *state; - - if (desc == Z_NULL) { - next = 0; - return 0; /* no input (already provided at next_in) */ - } - state = (void *)((z_stream *)desc)->state; - if (state != Z_NULL) - state->mode = SYNC; /* force an otherwise impossible situation */ - return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; -} - -local int push(void *desc, unsigned char *buf, unsigned len) -{ - buf += len; - return desc != Z_NULL; /* force error if desc not null */ -} - -/* cover inflateBack() up to common deflate data cases and after those */ -local void cover_back(void) -{ - int ret; - z_stream strm; - unsigned char win[32768]; - - ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); - assert(ret == Z_VERSION_ERROR); - ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); - ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); - assert(ret == Z_STREAM_ERROR); - ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflateBack bad parameters\n", stderr); - - mem_setup(&strm); - ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x03"; - ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); - assert(ret == Z_STREAM_END); - /* force output error */ - strm.avail_in = 3; - strm.next_in = (void *)"\x63\x00"; - ret = inflateBack(&strm, pull, Z_NULL, push, &strm); - assert(ret == Z_BUF_ERROR); - /* force mode error by mucking with state */ - ret = inflateBack(&strm, pull, &strm, push, Z_NULL); - assert(ret == Z_STREAM_ERROR); - ret = inflateBackEnd(&strm); assert(ret == Z_OK); - mem_done(&strm, "inflateBack bad state"); - - ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); - ret = inflateBackEnd(&strm); assert(ret == Z_OK); - fputs("inflateBack built-in memory routines\n", stderr); -} - -/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ -local int try(char *hex, char *id, int err) -{ - int ret; - unsigned len, size; - unsigned char *in, *out, *win; - char *prefix; - z_stream strm; - - /* convert to hex */ - in = h2b(hex, &len); - assert(in != NULL); - - /* allocate work areas */ - size = len << 3; - out = malloc(size); - assert(out != NULL); - win = malloc(32768); - assert(win != NULL); - prefix = malloc(strlen(id) + 6); - assert(prefix != NULL); - - /* first with inflate */ - strcpy(prefix, id); - strcat(prefix, "-late"); - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit2(&strm, err < 0 ? 47 : -15); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - do { - strm.avail_out = size; - strm.next_out = out; - ret = inflate(&strm, Z_TREES); - assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); - if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) - break; - } while (strm.avail_in || strm.avail_out == 0); - if (err) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - inflateEnd(&strm); - mem_done(&strm, prefix); - - /* then with inflateBack */ - if (err >= 0) { - strcpy(prefix, id); - strcat(prefix, "-back"); - mem_setup(&strm); - ret = inflateBackInit(&strm, 15, win); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); - assert(ret != Z_STREAM_ERROR); - if (err) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - inflateBackEnd(&strm); - mem_done(&strm, prefix); - } - - /* clean up */ - free(prefix); - free(win); - free(out); - free(in); - return ret; -} - -/* cover deflate data cases in both inflate() and inflateBack() */ -local void cover_inflate(void) -{ - try("0 0 0 0 0", "invalid stored block lengths", 1); - try("3 0", "fixed", 0); - try("6", "invalid block type", 1); - try("1 1 0 fe ff 0", "stored", 0); - try("fc 0 0", "too many length or distance symbols", 1); - try("4 0 fe ff", "invalid code lengths set", 1); - try("4 0 24 49 0", "invalid bit length repeat", 1); - try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); - try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); - try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", - "invalid literal/lengths set", 1); - try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); - try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); - try("2 7e ff ff", "invalid distance code", 1); - try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); - - /* also trailer mismatch just in inflate() */ - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", - "incorrect length check", -1); - try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); - try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", - "long code", 0); - try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); - try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", - "long distance and extra", 0); - try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); - inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, - Z_STREAM_END); - inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); -} - -/* cover remaining lines in inftrees.c */ -local void cover_trees(void) -{ - int ret; - unsigned bits; - unsigned short lens[16], work[16]; - code *next, table[ENOUGH_DISTS]; - - /* we need to call inflate_table() directly in order to manifest not- - enough errors, since zlib insures that enough is always enough */ - for (bits = 0; bits < 15; bits++) - lens[bits] = (unsigned short)(bits + 1); - lens[15] = 15; - next = table; - bits = 15; - ret = inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - next = table; - bits = 1; - ret = inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - fputs("inflate_table not enough errors\n", stderr); -} - -/* cover remaining inffast.c decoding and window copying */ -local void cover_fast(void) -{ - inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" - " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); - inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" - " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, - Z_DATA_ERROR); - inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, - Z_DATA_ERROR); - inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, - Z_DATA_ERROR); - inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", - "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); - inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); - inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", - "contiguous and wrap around window", 6, -8, 259, Z_OK); - inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, - Z_STREAM_END); -} - -int main(void) -{ - fprintf(stderr, "%s\n", zlibVersion()); - cover_support(); - cover_wrap(); - cover_back(); - cover_inflate(); - cover_trees(); - cover_fast(); - return 0; -} diff --git a/src/contrib/zlib/test/minigzip.c b/src/contrib/zlib/test/minigzip.c deleted file mode 100644 index 93de87b..0000000 --- a/src/contrib/zlib/test/minigzip.c +++ /dev/null @@ -1,651 +0,0 @@ -/* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * minigzip is a minimal implementation of the gzip utility. This is - * only an example of using zlib and isn't meant to replace the - * full-featured gzip. No attempt is made to deal with file systems - * limiting names to 14 or 8+3 characters, etc... Error checking is - * very limited. So use minigzip only for testing; use gzip for the - * real thing. On MSDOS, use only on file names without extension - * or in pipe mode. - */ - -/* @(#) $Id$ */ - -#include "../zlib.h" -#include - -#ifdef STDC -# include -# include -#endif - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) -# include -# include -# ifdef UNDER_CE -# include -# endif -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#ifdef VMS -# define unlink delete -# define GZ_SUFFIX "-gz" -#endif -#ifdef RISCOS -# define unlink remove -# define GZ_SUFFIX "-gz" -# define fileno(file) file->__file -#endif -#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fileno */ -#endif - -#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) -#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ - extern int unlink OF((const char *)); -#endif -#endif - -#if defined(UNDER_CE) -# include -# define perror(s) pwinerror(s) - -/* Map the Windows error number in ERROR to a locale-dependent error - message string and return a pointer to it. Typically, the values - for ERROR come from GetLastError. - - The string pointed to shall not be modified by the application, - but may be overwritten by a subsequent call to strwinerror - - The strwinerror function does not change the current setting - of GetLastError. */ - -static char *strwinerror (error) - DWORD error; -{ - static char buf[1024]; - - wchar_t *msgbuf; - DWORD lasterr = GetLastError(); - DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, - error, - 0, /* Default language */ - (LPVOID)&msgbuf, - 0, - NULL); - if (chars != 0) { - /* If there is an \r\n appended, zap it. */ - if (chars >= 2 - && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { - chars -= 2; - msgbuf[chars] = 0; - } - - if (chars > sizeof (buf) - 1) { - chars = sizeof (buf) - 1; - msgbuf[chars] = 0; - } - - wcstombs(buf, msgbuf, chars + 1); - LocalFree(msgbuf); - } - else { - sprintf(buf, "unknown win32 error (%ld)", error); - } - - SetLastError(lasterr); - return buf; -} - -static void pwinerror (s) - const char *s; -{ - if (s && *s) - fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); - else - fprintf(stderr, "%s\n", strwinerror(GetLastError ())); -} - -#endif /* UNDER_CE */ - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#define BUFLEN 16384 -#define MAX_NAME_LEN 1024 - -#ifdef MAXSEG_64K -# define local static - /* Needed for systems with limitation on stack size. */ -#else -# define local -#endif - -#ifdef Z_SOLO -/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ - -#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) -# include /* for unlink() */ -#endif - -void *myalloc OF((void *, unsigned, unsigned)); -void myfree OF((void *, void *)); - -void *myalloc(q, n, m) - void *q; - unsigned n, m; -{ - (void)q; - return calloc(n, m); -} - -void myfree(q, p) - void *q, *p; -{ - (void)q; - free(p); -} - -typedef struct gzFile_s { - FILE *file; - int write; - int err; - char *msg; - z_stream strm; -} *gzFile; - -gzFile gzopen OF((const char *, const char *)); -gzFile gzdopen OF((int, const char *)); -gzFile gz_open OF((const char *, int, const char *)); - -gzFile gzopen(path, mode) -const char *path; -const char *mode; -{ - return gz_open(path, -1, mode); -} - -gzFile gzdopen(fd, mode) -int fd; -const char *mode; -{ - return gz_open(NULL, fd, mode); -} - -gzFile gz_open(path, fd, mode) - const char *path; - int fd; - const char *mode; -{ - gzFile gz; - int ret; - - gz = malloc(sizeof(struct gzFile_s)); - if (gz == NULL) - return NULL; - gz->write = strchr(mode, 'w') != NULL; - gz->strm.zalloc = myalloc; - gz->strm.zfree = myfree; - gz->strm.opaque = Z_NULL; - if (gz->write) - ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); - else { - gz->strm.next_in = 0; - gz->strm.avail_in = Z_NULL; - ret = inflateInit2(&(gz->strm), 15 + 16); - } - if (ret != Z_OK) { - free(gz); - return NULL; - } - gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : - fopen(path, gz->write ? "wb" : "rb"); - if (gz->file == NULL) { - gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); - free(gz); - return NULL; - } - gz->err = 0; - gz->msg = ""; - return gz; -} - -int gzwrite OF((gzFile, const void *, unsigned)); - -int gzwrite(gz, buf, len) - gzFile gz; - const void *buf; - unsigned len; -{ - z_stream *strm; - unsigned char out[BUFLEN]; - - if (gz == NULL || !gz->write) - return 0; - strm = &(gz->strm); - strm->next_in = (void *)buf; - strm->avail_in = len; - do { - strm->next_out = out; - strm->avail_out = BUFLEN; - (void)deflate(strm, Z_NO_FLUSH); - fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); - } while (strm->avail_out == 0); - return len; -} - -int gzread OF((gzFile, void *, unsigned)); - -int gzread(gz, buf, len) - gzFile gz; - void *buf; - unsigned len; -{ - int ret; - unsigned got; - unsigned char in[1]; - z_stream *strm; - - if (gz == NULL || gz->write) - return 0; - if (gz->err) - return 0; - strm = &(gz->strm); - strm->next_out = (void *)buf; - strm->avail_out = len; - do { - got = fread(in, 1, 1, gz->file); - if (got == 0) - break; - strm->next_in = in; - strm->avail_in = 1; - ret = inflate(strm, Z_NO_FLUSH); - if (ret == Z_DATA_ERROR) { - gz->err = Z_DATA_ERROR; - gz->msg = strm->msg; - return 0; - } - if (ret == Z_STREAM_END) - inflateReset(strm); - } while (strm->avail_out); - return len - strm->avail_out; -} - -int gzclose OF((gzFile)); - -int gzclose(gz) - gzFile gz; -{ - z_stream *strm; - unsigned char out[BUFLEN]; - - if (gz == NULL) - return Z_STREAM_ERROR; - strm = &(gz->strm); - if (gz->write) { - strm->next_in = Z_NULL; - strm->avail_in = 0; - do { - strm->next_out = out; - strm->avail_out = BUFLEN; - (void)deflate(strm, Z_FINISH); - fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); - } while (strm->avail_out == 0); - deflateEnd(strm); - } - else - inflateEnd(strm); - fclose(gz->file); - free(gz); - return Z_OK; -} - -const char *gzerror OF((gzFile, int *)); - -const char *gzerror(gz, err) - gzFile gz; - int *err; -{ - *err = gz->err; - return gz->msg; -} - -#endif - -static char *prog; - -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -#ifdef USE_MMAP -int gz_compress_mmap OF((FILE *in, gzFile out)); -#endif -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file, char *mode)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Display error message and exit - */ -void error(msg) - const char *msg; -{ - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(in, out) - FILE *in; - gzFile out; -{ - local char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); - } - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(in, out) - FILE *in; - gzFile out; -{ - int len; - int err; - int ifd = fileno(in); - caddr_t buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (caddr_t)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = gzwrite(out, (char *)buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(gzerror(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (gzclose(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(in, out) - gzFile in; - FILE *out; -{ - local char buf[BUFLEN]; - int len; - int err; - - for (;;) { - len = gzread(in, buf, sizeof(buf)); - if (len < 0) error (gzerror(in, &err)); - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - error("failed fwrite"); - } - } - if (fclose(out)) error("failed fclose"); - - if (gzclose(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(file, mode) - char *file; - char *mode; -{ - local char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); -#else - strcpy(outfile, file); - strcat(outfile, GZ_SUFFIX); -#endif - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = gzopen(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(file) - char *file; -{ - local char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - unsigned len = strlen(file); - - if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(buf, sizeof(buf), "%s", file); -#else - strcpy(buf, file); -#endif - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); -#else - strcat(infile, GZ_SUFFIX); -#endif - } - in = gzopen(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - unlink(infile); -} - - -/* =========================================================================== - * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] - * -c : write to standard output - * -d : decompress - * -f : compress with Z_FILTERED - * -h : compress with Z_HUFFMAN_ONLY - * -r : compress with Z_RLE - * -1 to -9 : compression level - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - int copyout = 0; - int uncompr = 0; - gzFile file; - char *bname, outmode[20]; - -#if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(outmode, sizeof(outmode), "%s", "wb6 "); -#else - strcpy(outmode, "wb6 "); -#endif - - prog = argv[0]; - bname = strrchr(argv[0], '/'); - if (bname) - bname++; - else - bname = argv[0]; - argc--, argv++; - - if (!strcmp(bname, "gunzip")) - uncompr = 1; - else if (!strcmp(bname, "zcat")) - copyout = uncompr = 1; - - while (argc > 0) { - if (strcmp(*argv, "-c") == 0) - copyout = 1; - else if (strcmp(*argv, "-d") == 0) - uncompr = 1; - else if (strcmp(*argv, "-f") == 0) - outmode[3] = 'f'; - else if (strcmp(*argv, "-h") == 0) - outmode[3] = 'h'; - else if (strcmp(*argv, "-r") == 0) - outmode[3] = 'R'; - else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && - (*argv)[2] == 0) - outmode[2] = (*argv)[1]; - else - break; - argc--, argv++; - } - if (outmode[3] == ' ') - outmode[3] = 0; - if (argc == 0) { - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (uncompr) { - file = gzdopen(fileno(stdin), "rb"); - if (file == NULL) error("can't gzdopen stdin"); - gz_uncompress(file, stdout); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - gz_compress(stdin, file); - } - } else { - if (copyout) { - SET_BINARY_MODE(stdout); - } - do { - if (uncompr) { - if (copyout) { - file = gzopen(*argv, "rb"); - if (file == NULL) - fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); - else - gz_uncompress(file, stdout); - } else { - file_uncompress(*argv); - } - } else { - if (copyout) { - FILE * in = fopen(*argv, "rb"); - - if (in == NULL) { - perror(*argv); - } else { - file = gzdopen(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - - gz_compress(in, file); - } - - } else { - file_compress(*argv, outmode); - } - } - } while (argv++, --argc); - } - return 0; -} diff --git a/src/contrib/zlib/treebuild.xml b/src/contrib/zlib/treebuild.xml deleted file mode 100644 index fd75525..0000000 --- a/src/contrib/zlib/treebuild.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - zip compression library - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/contrib/zlib/trees.c b/src/contrib/zlib/trees.c deleted file mode 100644 index 50cf4b4..0000000 --- a/src/contrib/zlib/trees.c +++ /dev/null @@ -1,1203 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2017 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef ZLIB_DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local const static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local const static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local const static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef ZLIB_DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* !ZLIB_DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef ZLIB_DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (ush)value << s->bi_valid; - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= (ush)value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !ZLIB_DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = (int)value;\ - s->bi_buf |= (ush)val << s->bi_valid;\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (ush)(value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* ZLIB_DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef ZLIB_DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, - "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (unsigned)(bits + xbits); - if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); - } - if (overflow == 0) return; - - Tracev((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - unsigned code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = (ush)code; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ - bi_windup(s); /* align on byte boundary */ - put_short(s, (ush)stored_len); - put_short(s, (ush)~stored_len); - zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); - s->pending += stored_len; -#ifdef ZLIB_DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; - s->bits_sent += 2*16; - s->bits_sent += stored_len<<3; -#endif -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void ZLIB_INTERNAL _tr_flush_bits(s) - deflate_state *s; -{ - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void ZLIB_INTERNAL _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef ZLIB_DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and write out the encoded block. - */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (const ct_data *)static_ltree, - (const ct_data *)static_dtree); -#ifdef ZLIB_DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+last, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (const ct_data *)s->dyn_ltree, - (const ct_data *)s->dyn_dtree); -#ifdef ZLIB_DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); -#ifdef ZLIB_DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ZLIB_INTERNAL _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - const ct_data *ltree; /* literal tree */ - const ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= (unsigned)base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(s) - deflate_state *s; -{ - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} diff --git a/src/contrib/zlib/trees.h b/src/contrib/zlib/trees.h deleted file mode 100644 index d35639d..0000000 --- a/src/contrib/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/src/contrib/zlib/uncompr.c b/src/contrib/zlib/uncompr.c deleted file mode 100644 index f03a1a8..0000000 --- a/src/contrib/zlib/uncompr.c +++ /dev/null @@ -1,93 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. *sourceLen is - the byte length of the source buffer. Upon entry, *destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, - *destLen is the size of the decompressed data and *sourceLen is the number - of source bytes consumed. Upon return, source + *sourceLen points to the - first unused input byte. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, or - Z_DATA_ERROR if the input data was corrupted, including if the input data is - an incomplete zlib stream. -*/ -int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong *sourceLen; -{ - z_stream stream; - int err; - const uInt max = (uInt)-1; - uLong len, left; - Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ - - len = *sourceLen; - if (*destLen) { - left = *destLen; - *destLen = 0; - } - else { - left = 1; - dest = buf; - } - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = 0; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - stream.next_out = dest; - stream.avail_out = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (uLong)max ? max : (uInt)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = len > (uLong)max ? max : (uInt)len; - len -= stream.avail_in; - } - err = inflate(&stream, Z_NO_FLUSH); - } while (err == Z_OK); - - *sourceLen -= len + stream.avail_in; - if (dest != buf) - *destLen = stream.total_out; - else if (stream.total_out && err == Z_BUF_ERROR) - left = 1; - - inflateEnd(&stream); - return err == Z_STREAM_END ? Z_OK : - err == Z_NEED_DICT ? Z_DATA_ERROR : - err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : - err; -} - -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return uncompress2(dest, destLen, source, &sourceLen); -} diff --git a/src/contrib/zlib/watcom/watcom_f.mak b/src/contrib/zlib/watcom/watcom_f.mak deleted file mode 100644 index 37f4d74..0000000 --- a/src/contrib/zlib/watcom/watcom_f.mak +++ /dev/null @@ -1,43 +0,0 @@ -# Makefile for zlib -# OpenWatcom flat model -# Last updated: 28-Dec-2005 - -# To use, do "wmake -f watcom_f.mak" - -C_SOURCE = adler32.c compress.c crc32.c deflate.c & - gzclose.c gzlib.c gzread.c gzwrite.c & - infback.c inffast.c inflate.c inftrees.c & - trees.c uncompr.c zutil.c - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj & - gzclose.obj gzlib.obj gzread.obj gzwrite.obj & - infback.obj inffast.obj inflate.obj inftrees.obj & - trees.obj uncompr.obj zutil.obj - -CC = wcc386 -LINKER = wcl386 -CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx -ZLIB_LIB = zlib_f.lib - -.C.OBJ: - $(CC) $(CFLAGS) $[@ - -all: $(ZLIB_LIB) example.exe minigzip.exe - -$(ZLIB_LIB): $(OBJS) - wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj - wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj - wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj - wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj - wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj - -example.exe: $(ZLIB_LIB) example.obj - $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB) - -minigzip.exe: $(ZLIB_LIB) minigzip.obj - $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) - -clean: .SYMBOLIC - del *.obj - del $(ZLIB_LIB) - @echo Cleaning done diff --git a/src/contrib/zlib/watcom/watcom_l.mak b/src/contrib/zlib/watcom/watcom_l.mak deleted file mode 100644 index 193eed7..0000000 --- a/src/contrib/zlib/watcom/watcom_l.mak +++ /dev/null @@ -1,43 +0,0 @@ -# Makefile for zlib -# OpenWatcom large model -# Last updated: 28-Dec-2005 - -# To use, do "wmake -f watcom_l.mak" - -C_SOURCE = adler32.c compress.c crc32.c deflate.c & - gzclose.c gzlib.c gzread.c gzwrite.c & - infback.c inffast.c inflate.c inftrees.c & - trees.c uncompr.c zutil.c - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj & - gzclose.obj gzlib.obj gzread.obj gzwrite.obj & - infback.obj inffast.obj inflate.obj inftrees.obj & - trees.obj uncompr.obj zutil.obj - -CC = wcc -LINKER = wcl -CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx -ZLIB_LIB = zlib_l.lib - -.C.OBJ: - $(CC) $(CFLAGS) $[@ - -all: $(ZLIB_LIB) example.exe minigzip.exe - -$(ZLIB_LIB): $(OBJS) - wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj - wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj - wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj - wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj - wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj - -example.exe: $(ZLIB_LIB) example.obj - $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB) - -minigzip.exe: $(ZLIB_LIB) minigzip.obj - $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) - -clean: .SYMBOLIC - del *.obj - del $(ZLIB_LIB) - @echo Cleaning done diff --git a/src/contrib/zlib/win32/DLL_FAQ.txt b/src/contrib/zlib/win32/DLL_FAQ.txt deleted file mode 100644 index 12c0090..0000000 --- a/src/contrib/zlib/win32/DLL_FAQ.txt +++ /dev/null @@ -1,397 +0,0 @@ - - Frequently Asked Questions about ZLIB1.DLL - - -This document describes the design, the rationale, and the usage -of the official DLL build of zlib, named ZLIB1.DLL. If you have -general questions about zlib, you should see the file "FAQ" found -in the zlib distribution, or at the following location: - http://www.gzip.org/zlib/zlib_faq.html - - - 1. What is ZLIB1.DLL, and how can I get it? - - - ZLIB1.DLL is the official build of zlib as a DLL. - (Please remark the character '1' in the name.) - - Pointers to a precompiled ZLIB1.DLL can be found in the zlib - web site at: - http://www.zlib.net/ - - Applications that link to ZLIB1.DLL can rely on the following - specification: - - * The exported symbols are exclusively defined in the source - files "zlib.h" and "zlib.def", found in an official zlib - source distribution. - * The symbols are exported by name, not by ordinal. - * The exported names are undecorated. - * The calling convention of functions is "C" (CDECL). - * The ZLIB1.DLL binary is linked to MSVCRT.DLL. - - The archive in which ZLIB1.DLL is bundled contains compiled - test programs that must run with a valid build of ZLIB1.DLL. - It is recommended to download the prebuilt DLL from the zlib - web site, instead of building it yourself, to avoid potential - incompatibilities that could be introduced by your compiler - and build settings. If you do build the DLL yourself, please - make sure that it complies with all the above requirements, - and it runs with the precompiled test programs, bundled with - the original ZLIB1.DLL distribution. - - If, for any reason, you need to build an incompatible DLL, - please use a different file name. - - - 2. Why did you change the name of the DLL to ZLIB1.DLL? - What happened to the old ZLIB.DLL? - - - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required - compilation settings that were incompatible to those used by - a static build. The DLL settings were supposed to be enabled - by defining the macro ZLIB_DLL, before including "zlib.h". - Incorrect handling of this macro was silently accepted at - build time, resulting in two major problems: - - * ZLIB_DLL was missing from the old makefile. When building - the DLL, not all people added it to the build options. In - consequence, incompatible incarnations of ZLIB.DLL started - to circulate around the net. - - * When switching from using the static library to using the - DLL, applications had to define the ZLIB_DLL macro and - to recompile all the sources that contained calls to zlib - functions. Failure to do so resulted in creating binaries - that were unable to run with the official ZLIB.DLL build. - - The only possible solution that we could foresee was to make - a binary-incompatible change in the DLL interface, in order to - remove the dependency on the ZLIB_DLL macro, and to release - the new DLL under a different name. - - We chose the name ZLIB1.DLL, where '1' indicates the major - zlib version number. We hope that we will not have to break - the binary compatibility again, at least not as long as the - zlib-1.x series will last. - - There is still a ZLIB_DLL macro, that can trigger a more - efficient build and use of the DLL, but compatibility no - longer dependents on it. - - - 3. Can I build ZLIB.DLL from the new zlib sources, and replace - an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - - - In principle, you can do it by assigning calling convention - keywords to the macros ZEXPORT and ZEXPORTVA. In practice, - it depends on what you mean by "an old ZLIB.DLL", because the - old DLL exists in several mutually-incompatible versions. - You have to find out first what kind of calling convention is - being used in your particular ZLIB.DLL build, and to use the - same one in the new build. If you don't know what this is all - about, you might be better off if you would just leave the old - DLL intact. - - - 4. Can I compile my application using the new zlib interface, and - link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or - earlier? - - - The official answer is "no"; the real answer depends again on - what kind of ZLIB.DLL you have. Even if you are lucky, this - course of action is unreliable. - - If you rebuild your application and you intend to use a newer - version of zlib (post- 1.1.4), it is strongly recommended to - link it to the new ZLIB1.DLL. - - - 5. Why are the zlib symbols exported by name, and not by ordinal? - - - Although exporting symbols by ordinal is a little faster, it - is risky. Any single glitch in the maintenance or use of the - DEF file that contains the ordinals can result in incompatible - builds and frustrating crashes. Simply put, the benefits of - exporting symbols by ordinal do not justify the risks. - - Technically, it should be possible to maintain ordinals in - the DEF file, and still export the symbols by name. Ordinals - exist in every DLL, and even if the dynamic linking performed - at the DLL startup is searching for names, ordinals serve as - hints, for a faster name lookup. However, if the DEF file - contains ordinals, the Microsoft linker automatically builds - an implib that will cause the executables linked to it to use - those ordinals, and not the names. It is interesting to - notice that the GNU linker for Win32 does not suffer from this - problem. - - It is possible to avoid the DEF file if the exported symbols - are accompanied by a "__declspec(dllexport)" attribute in the - source files. You can do this in zlib by predefining the - ZLIB_DLL macro. - - - 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling - convention. Why not use the STDCALL convention? - STDCALL is the standard convention in Win32, and I need it in - my Visual Basic project! - - (For readability, we use CDECL to refer to the convention - triggered by the "__cdecl" keyword, STDCALL to refer to - the convention triggered by "__stdcall", and FASTCALL to - refer to the convention triggered by "__fastcall".) - - - Most of the native Windows API functions (without varargs) use - indeed the WINAPI convention (which translates to STDCALL in - Win32), but the standard C functions use CDECL. If a user - application is intrinsically tied to the Windows API (e.g. - it calls native Windows API functions such as CreateFile()), - sometimes it makes sense to decorate its own functions with - WINAPI. But if ANSI C or POSIX portability is a goal (e.g. - it calls standard C functions such as fopen()), it is not a - sound decision to request the inclusion of , or to - use non-ANSI constructs, for the sole purpose to make the user - functions STDCALL-able. - - The functionality offered by zlib is not in the category of - "Windows functionality", but is more like "C functionality". - - Technically, STDCALL is not bad; in fact, it is slightly - faster than CDECL, and it works with variable-argument - functions, just like CDECL. It is unfortunate that, in spite - of using STDCALL in the Windows API, it is not the default - convention used by the C compilers that run under Windows. - The roots of the problem reside deep inside the unsafety of - the K&R-style function prototypes, where the argument types - are not specified; but that is another story for another day. - - The remaining fact is that CDECL is the default convention. - Even if an explicit convention is hard-coded into the function - prototypes inside C headers, problems may appear. The - necessity to expose the convention in users' callbacks is one - of these problems. - - The calling convention issues are also important when using - zlib in other programming languages. Some of them, like Ada - (GNAT) and Fortran (GNU G77), have C bindings implemented - initially on Unix, and relying on the C calling convention. - On the other hand, the pre- .NET versions of Microsoft Visual - Basic require STDCALL, while Borland Delphi prefers, although - it does not require, FASTCALL. - - In fairness to all possible uses of zlib outside the C - programming language, we choose the default "C" convention. - Anyone interested in different bindings or conventions is - encouraged to maintain specialized projects. The "contrib/" - directory from the zlib distribution already holds a couple - of foreign bindings, such as Ada, C++, and Delphi. - - - 7. I need a DLL for my Visual Basic project. What can I do? - - - Define the ZLIB_WINAPI macro before including "zlib.h", when - building both the DLL and the user application (except that - you don't need to define anything when using the DLL in Visual - Basic). The ZLIB_WINAPI macro will switch on the WINAPI - (STDCALL) convention. The name of this DLL must be different - than the official ZLIB1.DLL. - - Gilles Vollant has contributed a build named ZLIBWAPI.DLL, - with the ZLIB_WINAPI macro turned on, and with the minizip - functionality built in. For more information, please read - the notes inside "contrib/vstudio/readme.txt", found in the - zlib distribution. - - - 8. I need to use zlib in my Microsoft .NET project. What can I - do? - - - Henrik Ravn has contributed a .NET wrapper around zlib. Look - into contrib/dotzlib/, inside the zlib distribution. - - - 9. If my application uses ZLIB1.DLL, should I link it to - MSVCRT.DLL? Why? - - - It is not required, but it is recommended to link your - application to MSVCRT.DLL, if it uses ZLIB1.DLL. - - The executables (.EXE, .DLL, etc.) that are involved in the - same process and are using the C run-time library (i.e. they - are calling standard C functions), must link to the same - library. There are several libraries in the Win32 system: - CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. - Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that - depend on it should also be linked to MSVCRT.DLL. - - -10. Why are you saying that ZLIB1.DLL and my application should - be linked to the same C run-time (CRT) library? I linked my - application and my DLLs to different C libraries (e.g. my - application to a static library, and my DLLs to MSVCRT.DLL), - and everything works fine. - - - If a user library invokes only pure Win32 API (accessible via - and the related headers), its DLL build will work - in any context. But if this library invokes standard C API, - things get more complicated. - - There is a single Win32 library in a Win32 system. Every - function in this library resides in a single DLL module, that - is safe to call from anywhere. On the other hand, there are - multiple versions of the C library, and each of them has its - own separate internal state. Standalone executables and user - DLLs that call standard C functions must link to a C run-time - (CRT) library, be it static or shared (DLL). Intermixing - occurs when an executable (not necessarily standalone) and a - DLL are linked to different CRTs, and both are running in the - same process. - - Intermixing multiple CRTs is possible, as long as their - internal states are kept intact. The Microsoft Knowledge Base - articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 - "HOWTO: Link with the Correct C Run-Time (CRT) Library" - mention the potential problems raised by intermixing. - - If intermixing works for you, it's because your application - and DLLs are avoiding the corruption of each of the CRTs' - internal states, maybe by careful design, or maybe by fortune. - - Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such - as those provided by Borland, raises similar problems. - - -11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - - - MSVCRT.DLL exists on every Windows 95 with a new service pack - installed, or with Microsoft Internet Explorer 4 or later, and - on all other Windows 4.x or later (Windows 98, Windows NT 4, - or later). It is freely distributable; if not present in the - system, it can be downloaded from Microsoft or from other - software provider for free. - - The fact that MSVCRT.DLL does not exist on a virgin Windows 95 - is not so problematic. Windows 95 is scarcely found nowadays, - Microsoft ended its support a long time ago, and many recent - applications from various vendors, including Microsoft, do not - even run on it. Furthermore, no serious user should run - Windows 95 without a proper update installed. - - -12. Why are you not linking ZLIB1.DLL to - <> ? - - - We considered and abandoned the following alternatives: - - * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or - LIBCMT.LIB) is not a good option. People are using the DLL - mainly to save disk space. If you are linking your program - to a static C library, you may as well consider linking zlib - in statically, too. - - * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because - CRTDLL.DLL is present on every Win32 installation. - Unfortunately, it has a series of problems: it does not - work properly with Microsoft's C++ libraries, it does not - provide support for 64-bit file offsets, (and so on...), - and Microsoft discontinued its support a long time ago. - - * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied - with the Microsoft .NET platform, and Visual C++ 7.0/7.1, - raises problems related to the status of ZLIB1.DLL as a - system component. According to the Microsoft Knowledge Base - article KB326922 "INFO: Redistribution of the Shared C - Runtime Component in Visual C++ .NET", MSVCR70.DLL and - MSVCR71.DLL are not supposed to function as system DLLs, - because they may clash with MSVCRT.DLL. Instead, the - application's installer is supposed to put these DLLs - (if needed) in the application's private directory. - If ZLIB1.DLL depends on a non-system runtime, it cannot - function as a redistributable system component. - - * Linking ZLIB1.DLL to non-Microsoft runtimes, such as - Borland's, or Cygwin's, raises problems related to the - reliable presence of these runtimes on Win32 systems. - It's easier to let the DLL build of zlib up to the people - who distribute these runtimes, and who may proceed as - explained in the answer to Question 14. - - -13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, - how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 - (Visual Studio .NET) or newer? - - - Due to the problems explained in the Microsoft Knowledge Base - article KB326922 (see the previous answer), the C runtime that - comes with the VC7 environment is no longer considered a - system component. That is, it should not be assumed that this - runtime exists, or may be installed in a system directory. - Since ZLIB1.DLL is supposed to be a system component, it may - not depend on a non-system component. - - In order to link ZLIB1.DLL and your application to MSVCRT.DLL - in VC7, you need the library of Visual C++ 6.0 or older. If - you don't have this library at hand, it's probably best not to - use ZLIB1.DLL. - - We are hoping that, in the future, Microsoft will provide a - way to build applications linked to a proper system runtime, - from the Visual C++ environment. Until then, you have a - couple of alternatives, such as linking zlib in statically. - If your application requires dynamic linking, you may proceed - as explained in the answer to Question 14. - - -14. I need to link my own DLL build to a CRT different than - MSVCRT.DLL. What can I do? - - - Feel free to rebuild the DLL from the zlib sources, and link - it the way you want. You should, however, clearly state that - your build is unofficial. You should give it a different file - name, and/or install it in a private directory that can be - accessed by your application only, and is not visible to the - others (i.e. it's neither in the PATH, nor in the SYSTEM or - SYSTEM32 directories). Otherwise, your build may clash with - applications that link to the official build. - - For example, in Cygwin, zlib is linked to the Cygwin runtime - CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. - - -15. May I include additional pieces of code that I find useful, - link them in ZLIB1.DLL, and export them? - - - No. A legitimate build of ZLIB1.DLL must not include code - that does not originate from the official zlib source code. - But you can make your own private DLL build, under a different - file name, as suggested in the previous answer. - - For example, zlib is a part of the VCL library, distributed - with Borland Delphi and C++ Builder. The DLL build of VCL - is a redistributable file, named VCLxx.DLL. - - -16. May I remove some functionality out of ZLIB1.DLL, by enabling - macros like NO_GZCOMPRESS or NO_GZIP at compile time? - - - No. A legitimate build of ZLIB1.DLL must provide the complete - zlib functionality, as implemented in the official zlib source - code. But you can make your own private DLL build, under a - different file name, as suggested in the previous answer. - - -17. I made my own ZLIB1.DLL build. Can I test it for compliance? - - - We prefer that you download the official DLL from the zlib - web site. If you need something peculiar from this DLL, you - can send your suggestion to the zlib mailing list. - - However, in case you do rebuild the DLL yourself, you can run - it with the test programs found in the DLL distribution. - Running these test programs is not a guarantee of compliance, - but a failure can imply a detected problem. - -** - -This document is written and maintained by -Cosmin Truta diff --git a/src/contrib/zlib/win32/Makefile.bor b/src/contrib/zlib/win32/Makefile.bor deleted file mode 100644 index d152bbb..0000000 --- a/src/contrib/zlib/win32/Makefile.bor +++ /dev/null @@ -1,110 +0,0 @@ -# Makefile for zlib -# Borland C++ for Win32 -# -# Usage: -# make -f win32/Makefile.bor -# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj - -# ------------ Borland C++ ------------ - -# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) -# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or -# added to the declaration of LOC here: -LOC = $(LOCAL_ZLIB) - -CC = bcc32 -AS = bcc32 -LD = bcc32 -AR = tlib -CFLAGS = -a -d -k- -O2 $(LOC) -ASFLAGS = $(LOC) -LDFLAGS = $(LOC) - - -# variables -ZLIB_LIB = zlib.lib - -OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj -OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj -#OBJA = -OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj -OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj -#OBJPA= - - -# targets -all: $(ZLIB_LIB) example.exe minigzip.exe - -.c.obj: - $(CC) -c $(CFLAGS) $< - -.asm.obj: - $(AS) -c $(ASFLAGS) $< - -adler32.obj: adler32.c zlib.h zconf.h - -compress.obj: compress.c zlib.h zconf.h - -crc32.obj: crc32.c zlib.h zconf.h crc32.h - -deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h - -gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h - -gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h - -gzread.obj: gzread.c zlib.h zconf.h gzguts.h - -gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h - -infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h - -inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ - inffast.h inffixed.h - -inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h - -trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h - -uncompr.obj: uncompr.c zlib.h zconf.h - -zutil.obj: zutil.c zutil.h zlib.h zconf.h - -example.obj: test/example.c zlib.h zconf.h - -minigzip.obj: test/minigzip.c zlib.h zconf.h - - -# For the sake of the old Borland make, -# the command line is cut to fit in the MS-DOS 128 byte limit: -$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA) - -del $(ZLIB_LIB) - $(AR) $(ZLIB_LIB) $(OBJP1) - $(AR) $(ZLIB_LIB) $(OBJP2) - $(AR) $(ZLIB_LIB) $(OBJPA) - - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -example.exe: example.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) - -minigzip.exe: minigzip.obj $(ZLIB_LIB) - $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) - - -# cleanup -clean: - -del $(ZLIB_LIB) - -del *.obj - -del *.exe - -del *.tds - -del zlib.bak - -del foo.gz diff --git a/src/contrib/zlib/win32/Makefile.gcc b/src/contrib/zlib/win32/Makefile.gcc deleted file mode 100644 index 305be50..0000000 --- a/src/contrib/zlib/win32/Makefile.gcc +++ /dev/null @@ -1,182 +0,0 @@ -# Makefile for zlib, derived from Makefile.dj2. -# Modified for mingw32 by C. Spieler, 6/16/98. -# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003. -# Last updated: Mar 2012. -# Tested under Cygwin and MinGW. - -# Copyright (C) 1995-2003 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile, or to compile and test, type from the top level zlib directory: -# -# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc -# -# To use the asm code, type: -# cp contrib/asm?86/match.S ./match.S -# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc -# -# To install libz.a, zconf.h and zlib.h in the system directories, type: -# -# make install -fwin32/Makefile.gcc -# -# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set. -# -# To install the shared lib, append SHARED_MODE=1 to the make command : -# -# make install -fwin32/Makefile.gcc SHARED_MODE=1 - -# Note: -# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN), -# the DLL name should be changed from "zlib1.dll". - -STATICLIB = libz.a -SHAREDLIB = zlib1.dll -IMPLIB = libz.dll.a - -# -# Set to 1 if shared object needs to be installed -# -SHARED_MODE=0 - -#LOC = -DASMV -#LOC = -DZLIB_DEBUG -g - -PREFIX = -CC = $(PREFIX)gcc -CFLAGS = $(LOC) -O3 -Wall - -AS = $(CC) -ASFLAGS = $(LOC) -Wall - -LD = $(CC) -LDFLAGS = $(LOC) - -AR = $(PREFIX)ar -ARFLAGS = rcs - -RC = $(PREFIX)windres -RCFLAGS = --define GCC_WINDRES - -STRIP = $(PREFIX)strip - -CP = cp -fp -# If GNU install is available, replace $(CP) with install. -INSTALL = $(CP) -RM = rm -f - -prefix ?= /usr/local -exec_prefix = $(prefix) - -OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ - gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o -OBJA = - -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe - -test: example.exe minigzip.exe - ./example - echo hello world | ./minigzip | ./minigzip -d - -testdll: example_d.exe minigzip_d.exe - ./example_d - echo hello world | ./minigzip_d | ./minigzip_d -d - -.c.o: - $(CC) $(CFLAGS) -c -o $@ $< - -.S.o: - $(AS) $(ASFLAGS) -c -o $@ $< - -$(STATICLIB): $(OBJS) $(OBJA) - $(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o - $(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \ - -o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o - $(STRIP) $@ - -example.exe: example.o $(STATICLIB) - $(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB) - $(STRIP) $@ - -minigzip.exe: minigzip.o $(STATICLIB) - $(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB) - $(STRIP) $@ - -example_d.exe: example.o $(IMPLIB) - $(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB) - $(STRIP) $@ - -minigzip_d.exe: minigzip.o $(IMPLIB) - $(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB) - $(STRIP) $@ - -example.o: test/example.c zlib.h zconf.h - $(CC) $(CFLAGS) -I. -c -o $@ test/example.c - -minigzip.o: test/minigzip.c zlib.h zconf.h - $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c - -zlibrc.o: win32/zlib1.rc - $(RC) $(RCFLAGS) -o $@ win32/zlib1.rc - -.PHONY: install uninstall clean - -install: zlib.h zconf.h $(STATICLIB) $(IMPLIB) - @if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \ - echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \ - exit 1; \ - fi - -@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)' - -@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig - -if [ "$(SHARED_MODE)" = "1" ]; then \ - mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \ - $(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \ - $(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \ - fi - -$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)' - -$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)' - -$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)' - sed \ - -e 's|@prefix@|${prefix}|g' \ - -e 's|@exec_prefix@|${exec_prefix}|g' \ - -e 's|@libdir@|$(LIBRARY_PATH)|g' \ - -e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \ - -e 's|@includedir@|$(INCLUDE_PATH)|g' \ - -e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \ - zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc - -uninstall: - -if [ "$(SHARED_MODE)" = "1" ]; then \ - $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \ - $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \ - fi - -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h - -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h - -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB) - -clean: - -$(RM) $(STATICLIB) - -$(RM) $(SHAREDLIB) - -$(RM) $(IMPLIB) - -$(RM) *.o - -$(RM) *.exe - -$(RM) foo.gz - -adler32.o: zlib.h zconf.h -compress.o: zlib.h zconf.h -crc32.o: crc32.h zlib.h zconf.h -deflate.o: deflate.h zutil.h zlib.h zconf.h -gzclose.o: zlib.h zconf.h gzguts.h -gzlib.o: zlib.h zconf.h gzguts.h -gzread.o: zlib.h zconf.h gzguts.h -gzwrite.o: zlib.h zconf.h gzguts.h -inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h -inftrees.o: zutil.h zlib.h zconf.h inftrees.h -trees.o: deflate.h zutil.h zlib.h zconf.h trees.h -uncompr.o: zlib.h zconf.h -zutil.o: zutil.h zlib.h zconf.h diff --git a/src/contrib/zlib/win32/Makefile.msc b/src/contrib/zlib/win32/Makefile.msc deleted file mode 100644 index 6831882..0000000 --- a/src/contrib/zlib/win32/Makefile.msc +++ /dev/null @@ -1,163 +0,0 @@ -# Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler -# -# Usage: -# nmake -f win32/Makefile.msc (standard build) -# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build) -# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \ -# OBJA="inffas32.obj match686.obj" (use ASM code, x86) -# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \ -# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64) - -# The toplevel directory of the source tree. -# -TOP = . - -# optional build flags -LOC = - -# variables -STATICLIB = zlib.lib -SHAREDLIB = zlib1.dll -IMPLIB = zdll.lib - -CC = cl -AS = ml -LD = link -AR = lib -RC = rc -CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) -WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -ASFLAGS = -coff -Zi $(LOC) -LDFLAGS = -nologo -debug -incremental:no -opt:ref -ARFLAGS = -nologo -RCFLAGS = /dWIN32 /r - -OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \ - gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj -OBJA = - - -# targets -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ - example.exe minigzip.exe example_d.exe minigzip_d.exe - -$(STATICLIB): $(OBJS) $(OBJA) - $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res - $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;2 - -example.exe: example.obj $(STATICLIB) - $(LD) $(LDFLAGS) example.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip.exe: minigzip.obj $(STATICLIB) - $(LD) $(LDFLAGS) minigzip.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -example_d.exe: example.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip_d.exe: minigzip.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -{$(TOP)}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/test}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/contrib/masmx64}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/contrib/masmx64}.asm.obj: - $(AS) -c $(ASFLAGS) $< - -{$(TOP)/contrib/masmx86}.asm.obj: - $(AS) -c $(ASFLAGS) $< - -adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h - -compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h - -crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h - -deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h - -gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h - -infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h $(TOP)/inffixed.h - -inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h - -inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ - $(TOP)/inffast.h $(TOP)/inffixed.h - -inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h - -trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h - -uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h - -zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h - -gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm - -inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm - -inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \ - $(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h - -inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm - -match686.obj: $(TOP)/contrib\masmx86\match686.asm - -example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h - -minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h - -zlib1.res: $(TOP)/win32/zlib1.rc - $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -testdll: example_d.exe minigzip_d.exe - example_d - echo hello world | minigzip_d | minigzip_d -d - - -# cleanup -clean: - -del $(STATICLIB) - -del $(SHAREDLIB) - -del $(IMPLIB) - -del *.obj - -del *.res - -del *.exp - -del *.exe - -del *.pdb - -del *.manifest - -del foo.gz diff --git a/src/contrib/zlib/win32/README-WIN32.txt b/src/contrib/zlib/win32/README-WIN32.txt deleted file mode 100644 index df7ab7f..0000000 --- a/src/contrib/zlib/win32/README-WIN32.txt +++ /dev/null @@ -1,103 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled -examples are distributed in this package, example and minigzip. The example_d -and minigzip_d flavors validate that the zlib1.dll file is working correctly. - -Questions about zlib should be sent to . The zlib home page -is http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html -before asking for help. - - -Manifest: - -The package zlib-1.2.11-win32-x86.zip will contain the following files: - - README-WIN32.txt This document - ChangeLog Changes since previous zlib packages - DLL_FAQ.txt Frequently asked questions about zlib1.dll - zlib.3.pdf Documentation of this library in Adobe Acrobat format - - example.exe A statically-bound example (using zlib.lib, not the dll) - example.pdb Symbolic information for debugging example.exe - - example_d.exe A zlib1.dll bound example (using zdll.lib) - example_d.pdb Symbolic information for debugging example_d.exe - - minigzip.exe A statically-bound test program (using zlib.lib, not the dll) - minigzip.pdb Symbolic information for debugging minigzip.exe - - minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) - minigzip_d.pdb Symbolic information for debugging minigzip_d.exe - - zlib.h Install these files into the compilers' INCLUDE path to - zconf.h compile programs which use zlib.lib or zdll.lib - - zdll.lib Install these files into the compilers' LIB path if linking - zdll.exp a compiled program to the zlib1.dll binary - - zlib.lib Install these files into the compilers' LIB path to link zlib - zlib.pdb into compiled programs, without zlib1.dll runtime dependency - (zlib.pdb provides debugging info to the compile time linker) - - zlib1.dll Install this binary shared library into the system PATH, or - the program's runtime directory (where the .exe resides) - zlib1.pdb Install in the same directory as zlib1.dll, in order to debug - an application crash using WinDbg or similar tools. - -All .pdb files above are entirely optional, but are very useful to a developer -attempting to diagnose program misbehavior or a crash. Many additional -important files for developers can be found in the zlib127.zip source package -available from http://zlib.net/ - review that package's README file for details. - - -Acknowledgments: - -The deflate format used by zlib was defined by Phil Katz. The deflate and -zlib specifications were written by L. Peter Deutsch. Thanks to all the -people who reported problems and suggested various improvements in zlib; they -are too numerous to cite here. - - -Copyright notice: - - (C) 1995-2017 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/src/contrib/zlib/win32/VisualC.txt b/src/contrib/zlib/win32/VisualC.txt deleted file mode 100644 index 1005b21..0000000 --- a/src/contrib/zlib/win32/VisualC.txt +++ /dev/null @@ -1,3 +0,0 @@ - -To build zlib using the Microsoft Visual C++ environment, -use the appropriate project from the contrib/vstudio/ directory. diff --git a/src/contrib/zlib/win32/zlib.def b/src/contrib/zlib/win32/zlib.def deleted file mode 100644 index a2188b0..0000000 --- a/src/contrib/zlib/win32/zlib.def +++ /dev/null @@ -1,94 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 - gzopen - gzdopen - gzbuffer - gzsetparams - gzread - gzfread - gzwrite - gzfwrite - gzprintf - gzvprintf - gzputs - gzgets - gzputc - gzgetc - gzungetc - gzflush - gzseek - gzrewind - gztell - gzoffset - gzeof - gzdirect - gzclose - gzclose_r - gzclose_w - gzerror - gzclearerr -; large file functions - gzopen64 - gzseek64 - gztell64 - gzoffset64 - adler32_combine64 - crc32_combine64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - gzgetc_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep - gzopen_w diff --git a/src/contrib/zlib/win32/zlib1.rc b/src/contrib/zlib/win32/zlib1.rc deleted file mode 100644 index 234e641..0000000 --- a/src/contrib/zlib/win32/zlib1.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "../zlib.h" - -#ifdef GCC_WINDRES -VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif - FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - BEGIN - VALUE "FileDescription", "zlib data compression library\0" - VALUE "FileVersion", ZLIB_VERSION "\0" - VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" - VALUE "OriginalFilename", "zlib1.dll\0" - VALUE "ProductName", "zlib\0" - VALUE "ProductVersion", ZLIB_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/src/contrib/zlib/zconf.h.cmakein b/src/contrib/zlib/zconf.h.cmakein deleted file mode 100644 index a7f24cc..0000000 --- a/src/contrib/zlib/zconf.h.cmakein +++ /dev/null @@ -1,536 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H -#cmakedefine Z_PREFIX -#cmakedefine Z_HAVE_UNISTD_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols and init macros */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define adler32_z z_adler32_z -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define crc32_z z_crc32_z -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateGetDictionary z_deflateGetDictionary -# define deflateInit z_deflateInit -# define deflateInit2 z_deflateInit2 -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzfread z_gzfread -# define gzfwrite z_gzfwrite -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzvprintf z_gzvprintf -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit z_inflateBackInit -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCodesUsed z_inflateCodesUsed -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetDictionary z_inflateGetDictionary -# define inflateGetHeader z_inflateGetHeader -# define inflateInit z_inflateInit -# define inflateInit2 z_inflateInit2 -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateResetKeep z_inflateResetKeep -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateValidate z_inflateValidate -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# define uncompress2 z_uncompress2 -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -#ifdef Z_SOLO - typedef unsigned long z_size_t; -#else -# define z_longlong long long -# if defined(NO_SIZE_T) - typedef unsigned NO_SIZE_T z_size_t; -# elif defined(STDC) -# include - typedef size_t z_size_t; -# else - typedef unsigned long z_size_t; -# endif -# undef z_longlong -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/src/contrib/zlib/zconf.h.in b/src/contrib/zlib/zconf.h.in deleted file mode 100644 index 5e1d68a..0000000 --- a/src/contrib/zlib/zconf.h.in +++ /dev/null @@ -1,534 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols and init macros */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define adler32_z z_adler32_z -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define crc32_z z_crc32_z -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateGetDictionary z_deflateGetDictionary -# define deflateInit z_deflateInit -# define deflateInit2 z_deflateInit2 -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzfread z_gzfread -# define gzfwrite z_gzfwrite -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzvprintf z_gzvprintf -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit z_inflateBackInit -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCodesUsed z_inflateCodesUsed -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetDictionary z_inflateGetDictionary -# define inflateGetHeader z_inflateGetHeader -# define inflateInit z_inflateInit -# define inflateInit2 z_inflateInit2 -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateResetKeep z_inflateResetKeep -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateValidate z_inflateValidate -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# define uncompress2 z_uncompress2 -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -#ifdef Z_SOLO - typedef unsigned long z_size_t; -#else -# define z_longlong long long -# if defined(NO_SIZE_T) - typedef unsigned NO_SIZE_T z_size_t; -# elif defined(STDC) -# include - typedef size_t z_size_t; -# else - typedef unsigned long z_size_t; -# endif -# undef z_longlong -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/src/contrib/zlib/zconf.h.included b/src/contrib/zlib/zconf.h.included deleted file mode 100644 index 9987a77..0000000 --- a/src/contrib/zlib/zconf.h.included +++ /dev/null @@ -1,511 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_bits z__tr_flush_bits -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# ifdef _WIN32 -# define gzopen_w z_gzopen_w -# endif -# define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# endif -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) -# include -# if (UINT_MAX == 0xffffffffUL) -# define Z_U4 unsigned -# elif (ULONG_MAX == 0xffffffffUL) -# define Z_U4 unsigned long -# elif (USHRT_MAX == 0xffffffffUL) -# define Z_U4 unsigned short -# endif -#endif - -#ifdef Z_U4 - typedef Z_U4 z_crc_t; -#else - typedef unsigned long z_crc_t; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -# include /* for va_list */ -# endif -#endif - -#ifdef _WIN32 -# ifndef Z_SOLO -# include /* for wchar_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) -# define Z_HAVE_UNISTD_H -#endif -#ifndef Z_SOLO -# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/src/contrib/zlib/zlib.3 b/src/contrib/zlib/zlib.3 deleted file mode 100644 index bda4eb0..0000000 --- a/src/contrib/zlib/zlib.3 +++ /dev/null @@ -1,149 +0,0 @@ -.TH ZLIB 3 "15 Jan 2017" -.SH NAME -zlib \- compression/decompression library -.SH SYNOPSIS -[see -.I zlib.h -for full description] -.SH DESCRIPTION -The -.I zlib -library is a general purpose data compression library. -The code is thread safe, assuming that the standard library functions -used are thread safe, such as memory allocation routines. -It provides in-memory compression and decompression functions, -including integrity checks of the uncompressed data. -This version of the library supports only one compression method (deflation) -but other algorithms may be added later -with the same stream interface. -.LP -Compression can be done in a single step if the buffers are large enough -or can be done by repeated calls of the compression function. -In the latter case, -the application must provide more input and/or consume the output -(providing more output space) before each call. -.LP -The library also supports reading and writing files in -.IR gzip (1) -(.gz) format -with an interface similar to that of stdio. -.LP -The library does not install any signal handler. -The decoder checks the consistency of the compressed data, -so the library should never crash even in the case of corrupted input. -.LP -All functions of the compression library are documented in the file -.IR zlib.h . -The distribution source includes examples of use of the library -in the files -.I test/example.c -and -.IR test/minigzip.c, -as well as other examples in the -.IR examples/ -directory. -.LP -Changes to this version are documented in the file -.I ChangeLog -that accompanies the source. -.LP -.I zlib -is built in to many languages and operating systems, including but not limited to -Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. -.LP -An experimental package to read and write files in the .zip format, -written on top of -.I zlib -by Gilles Vollant (info@winimage.com), -is available at: -.IP -http://www.winimage.com/zLibDll/minizip.html -and also in the -.I contrib/minizip -directory of the main -.I zlib -source distribution. -.SH "SEE ALSO" -The -.I zlib -web site can be found at: -.IP -http://zlib.net/ -.LP -The data format used by the -.I zlib -library is described by RFC -(Request for Comments) 1950 to 1952 in the files: -.IP -http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) -.br -http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) -.br -http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) -.LP -Mark Nelson wrote an article about -.I zlib -for the Jan. 1997 issue of Dr. Dobb's Journal; -a copy of the article is available at: -.IP -http://marknelson.us/1997/01/01/zlib-engine/ -.SH "REPORTING PROBLEMS" -Before reporting a problem, -please check the -.I zlib -web site to verify that you have the latest version of -.IR zlib ; -otherwise, -obtain the latest version and see if the problem still exists. -Please read the -.I zlib -FAQ at: -.IP -http://zlib.net/zlib_faq.html -.LP -before asking for help. -Send questions and/or comments to zlib@gzip.org, -or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). -.SH AUTHORS AND LICENSE -Version 1.2.11 -.LP -Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler -.LP -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. -.LP -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: -.LP -.nr step 1 1 -.IP \n[step]. 3 -The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -.IP \n+[step]. -Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -.IP \n+[step]. -This notice may not be removed or altered from any source distribution. -.LP -Jean-loup Gailly Mark Adler -.br -jloup@gzip.org madler@alumni.caltech.edu -.LP -The deflate format used by -.I zlib -was defined by Phil Katz. -The deflate and -.I zlib -specifications were written by L. Peter Deutsch. -Thanks to all the people who reported problems and suggested various -improvements in -.IR zlib ; -who are too numerous to cite here. -.LP -UNIX manual page by R. P. C. Rodgers, -U.S. National Library of Medicine (rodgers@nlm.nih.gov). -.\" end of man page diff --git a/src/contrib/zlib/zlib.3.pdf b/src/contrib/zlib/zlib.3.pdf deleted file mode 100644 index 6fa519c5bdf5df33b2f17549e1df142c619c916c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19318 zcmch<1z40#*8og65|UC&NwX~79a56gDJJenky_R zjF^%z2*5%4XDY8<8S0-Zf~{xeY#q($F=t7g1UIzEeY+0|_eAV?>=24$8RuCFhh9H| zi$0hvRN^^Km5ho<`99aKxmXj4#n5;-O6BBx_BCoZwCAR7Aubu+owD1I`CxRICp|A9 z&ryM3kt5Yyp;HOV{L7)Hy}`1ohXD0W;rv?W5m*1IR)qs%YE17mvG@5}^4od0&Y`0# zK0?!KBmswNdzU(z@06vk&5OzUnsp<+O&B*)D__Zzw`51-@X7*|wgP%nZ(8Q!*Vjk3 zs8lbG)9IMIv9?D(EVs6|c{rOad)r`K&n4#TKbk8Hs9_#-uGy5a-C=%Czc}n;*dmlB zqY&52sHI4wVCG@ATFUVo+Q^lg(kr)W56Ds&>dwe)A({6uN77uV z@IzeT@C!AuRfb4+n!R}~ytMTvWDEn|^9fhP=~Qcu;*l@+?m6fYkLxccn(BW+^az3z z6nw{?R8r^~RFtdM$to-vz|zv-fnoRtd6cS&!MM^zwxi0Y1{le;gGNRf2GYFHXVt=e zMmOTN$;S|qf4@Lb$6}VO{)uxXVXVjS#8mgIP1y>OLmnwClBB%dNHhJtS@PY+pk&q0 zQHIW`&gRj&hX-S2*tBGPkjQ z!9c)wU-10R^1jRRYK7ffb%xfhWVE;l^$|ff16dRAQGnd?<#biPPp^&=yr_83KuS@| zl?>AfvvD{il&>wJ<(v7?kV0ql(0?V&q2o?AWI+0QP$YMV0+fBGu`+vJ&zYp4@ zbkaFEEglgT^O1&O={Kj#N&{tI_}N&JyM?~5cpqK$1Kbo~ZveN%j)eFyT#ojviv`IqM&LuA!`;m-) zsZ+tc@H=`A$8|zEX585$*48PfFhaA zwpSmk!C^ZPAn1nouywXgep4a5x{6Cs^m_9F8%6oe>_m?m8+l`b;6eg|xj%*ADuZ3B zui=55!@z@?V(U;9C&utOn^%$yG+?<8oJht}FDmr#GsL(OUI}vBg_HAgGrH$$i{Lx=+|kqg7z+!h+p?j?bU&T zT$0qMMt;GV6vGv2_4gID4^Pcbc-iH04^d_?IPdcv7$-cqSoEEKDV2eTV?a*dCp7-v zx779i*BFk2SZRBPP>v6(uHP|lW|X5m0GS`fli?JuglKZ_F}jCJh=!VIsqgH;86lzK z_wqf&%j>F#!_a+zpy!mT6rN4ngbh#B?4w`Dv4ygJ9!9I;I`qNuEWLShczx8n-LBJK zaWODM`ABRHKe`yt!3tBeQd7ra5w|zEgUictA;B(hNpozVA zNy1ILehoK%HEc#>4W^kw%wZ58M6O&^>> zbA2_s%Kh4&6Rns5oP= zXO4gzjO9+AP#iO{I2*yHM>=l{6*H`xbfzr9+bK(m$rw>5aBL+nvf`?~*IcE-3XLRX z9K3vuf>ZxgQ8fTrex#@_j(XQM9m8TPES2^x<+e{9`D(PkVn!5Kw8f~_&+ zN5F-liuS5{7=$R6Hr1*`TCJ@%gqReRE%brQ`}?}AJr*t&VvHj_6R44i^8nm0&zgj{ zx3v%oaq1sIHjG2Kr5)wu^U6mjEJK`xGRBI>)$@Vi(cV6$_|bV1td|_e9^!8+;kj4T zCEC*JSRX3dmZ-Tu$akp&YI<9nAOdM6oJ(B}(#z_9P%os(Kk)Mq~jaCcdsawRf(9@uc@hs$hk!PJ|WH z^NM4e?PvKcR2kEbXtf#_bFL^)-tWTKD+iHu`x4J06#2dL<|^pt$Izxx^QGcF%@*~| zd1>LMT;hZ&DvQoS*F=q%YHPk(ub&Qo^|`0oX^cy3=riYe^b7m6sEQYoQBCBLHkgSN zx$sHtE=BjHhfFwjVNPi|1&XkhJ1Sm`>2Pj^JYnAp2|i?>Z+Jf=@1 zgan9MFIE}z4v-R{$5DG6Dok?%50~tA&xZOdNuw3&o|UFP`QSTYZaBm$!;%tPSpPas zy^o+bfKyxi>vBxk`%1Ywvr>WkGSew-aHwV1pJ5rh2$lq5P?bma_ejkRgWug3pc&HI zOVq%5C|C4M)DU>R0=qDp^L<%dCaPI8M#Q`Q>Sk?ib=A1Q#=|I3jJwTZthb@m>T6Sl z3vBl#I44c)UejZ)A;rQW?(6y)!1((p7LIkI%`D=UUWqBO)idmi{10Hs6lMF#`$E%i z%6j0^bd$S~NJR;hZ62D~Nq(v?ddc7k*pPUbX|`{ARL6jzL4jFgyzUFx>ijZVSkQxV z&72-)Xb?xJ$#eL9Bj^G&_7!0}d+ZJbjN9F4I%gbu%m!g)io(;jgV0cSrY=< zd03`j@{^qUaO41lppFk>{@{1D1Qd&9g-5Go@L}Cn#V?FQn9fL1zx9|9 zR|W^2X#MQy8wJB5A?tLH&F|cg z)7kHNMTTQ}a5_@p;e0I%#sz{mu-E*vd|^?1CoBuKA|!ltg`QaHHo4I{_`n}$Arj&j z4Vyc&7*R=GSp`p9%#&Zr=_nbnZA!mDSq&ai2?)%nNvSxDolEQD=Uok`A=&X*U|Y&wc_)@gb?5GbhE zI}m7mNOvlR@oApr`6rkr`1eh)l)(*(5{2sTch=~FUa376%3s{e{frW}awf`s{}DqA zd;HDQphea1i1qiZvs5R0iyKQj_%C|pA~=t|of>(P)j|E*%EEesQfH6n4N4T#(TVAE zA)Y)h>OADMhX$xl*097TP)T1kBlG5Y6g4^3MksVs4u8G>A*Xo4-Ep2Uu{|AxOrX)* ztb&RcT*3UFD5!Q7318 zv_@EeN2!mv6ong7O4=ax^*(Mn&|;X0*C<220h^Rkj_cJW`22L58Fn)=hD!9#^H)+hA5@^&^&LRe zM0Lb3YV#&@&3p&J2xK1tI^S}ecX4p=j=$l^Da)p>Z)Ou>J02kP7?zs7UwD9$x3f4B zYBvyPql#x>s82a&b7JC$w1!*uRr`E+qe0thah%&Gpw-o*1ht;fmO&LQm99FHP*b@R z5h0%v4rR*k34`eKx}@Cd1ZP@ z{Hr3Z>hhS{*{i|=mzkoKY_uS*PcGi`+zJkZ!E6OfTjgPc^htvDN?)Y%1VwFJKWI2< z(S@>-F=6%lYYYUHPHER4_5^i3Y#SUh*`C?t%X!cf+9TFKI1+JhHkq$!^Cle?t~W~^YH69o04nM4 z!Y_)V99lQddY#c6Hh{lxFbE`fSCb*X+5B#PZgt-&KY@=#c0`>w!)M&OFh^nj98!*t%3o?Y-+BL9toN#%4O8WCmgpd4wB)9YiGP4|vOl%-HJ(d{R_A-USsPb|Cg!$^JM zA}xgBGAhimUXr=gnLkMtxrn2Bl%Q#OwoOtf@n)P4Wvfh1u}#e?eV*)s2*^|<$8xbh-Pi1trEpy8juxC8ZkOkh(wU}xi> zFih<}7&LRJ(s@~y)XG4R?v+yVcx;Vr!|8d)?(w`_#8?eyIwcZjNRmT!+GZ_Z_!hI_ zLg}}jQN%p0NrMRQH`#Rx808e+sq?-pb4u!iZyY?@(q}qkPGF17RcR3TT=%BVkRHl( zn`W<0I)xt~WfTwV<&VJSRhM{n)HxS z*`%E|5Pp-0&0Hqvwx1PknzAC!8OE04{4L|qV{^^9h+oMcY}(@?r)VZ8LA$b%gP|;% zit04tRm)c!9>4}v42_iiwz_OvttC1XvN;8FW&#pKbks5+GND2x^uAn55f3t-S54oN zJH+AwP?Jao4x%kK1aH1kP?4UGws>CKJ4U7`I?O8}9E*zgs8EG54>K|$2e#8Tpl#By z4|n)g&-V6FyFguIYOq^Gr-VQuePMi5a{h%EBlFhQoageZ5(f#DkauU zqF?RkEIR=s`LJ!pSI4vy8>5U0-C1-65w!c{GMeR{NyRP=NNwf7_yo_909yn>^9mi| zxdKa)=QVio!=umjG$Le}^e9zearD#kq?1w}tHPr`4-mTViktU#hI)NJ#XN)}7w0J>WxF^hmjMq1PYdC2PByT+cn({6JM&?x}WVSQyMHj?pZwWD~pLX_u!gQ z97MOm?~UEPwis^8*lh$w?+0NX?45pBjvMn}q{m39*8BF{Or_MB<1B|TtS4G4l57BL znvUtC|7Gg2%$;CS;)=57vKB`Cogr@!%c*m-qr)dsf+ ze$AUqwDpA|`oxYKHpJYKT?x&e;C@PuIy=X@md2j_*Q4mGMTD7k8%*MoIftkCS)vV* zrjYw9@76vkjdhD?ocNQ})H}ci3#hG@%}zyY3IVDFFIL13-c=Ch>J1r>VFtKff4FBv zj3vd3?ABN~v_^$b?(6(SUksPuhBKP1eaCTIjNzE7&zyF$7k0G*;BnH}kShoF3b9j4 zNqE;!u<1(`jRyb16mul#0ZiX^6OYc^3uJ|^3y9EIE&*-w#{e_O3oE+(aMoE9?}jLA zoc1P}dJ`qL_ycLbsR?*rPt7c!kdYD07u`lIqO2p2T{U<bmK5M!Edh=D+rjx)O+Hi@ zmgwIs2TBGA5s!<}f2t_%&%6>xI{UmY9>@8S5mleI;R;@-jF{SNJto3|OQAi}L?%4T zldS98`_uZUcbnaYmFF}kitJj z-x-W{K>-x^_+`!8=4@~L+rPsr%-LK0!zZ}g>~Ea{5FZcsFQPoF^D!vPFbHZ}(X z6~U&K#^Uzw09`g{GdGAGz{AI`j|Nn=hd?9J05)hZC$Jp^z;Ww6K&!#d_AX8)U}tC` zTiMCpL=6nl1wupJ0H8Y99Rh`ua)-#M-GPE`$Af}M+e5)Yw*hcfG-zxaC;`2OVsr-l zQT5Ad`Q^z#asU59Am48UvfobsZv@_XQFnDeDZFLEk0?HLzEBnd?s(`70LojMIs*c93VVE;Rlesk>Z zc=QLq(SS z0=`ouNwBktlcfX1-U$G@^!$~`nUIwmfLUW2kqZ_{8sm~ornFF{=dGtxNfBneg79YZu{PS*lrn&@|B3td zmzRU%M?WrZv>&}VZfl@Wf6nLj3W|e`?bZhEpyx=IcIMD&+lkpZTmEsa=JFJBYx%dD z1J#s2l=2qz?_$tV6PMM}`b`Yt_BN*fkO2q^srtXmfS2#T5Wy`K(D#4AxLd~m{^91n zRc{`s@NR2=F@+lhx?|m4PpD9T_Ja1fE#0=>w)_|sTJ!&bakt9!cfM(8t4PU8{mHk# zv+Qos`QJGP;^Fv@EW6c-TMfAV+>(Dg;oI`;5A5cH}%*V-j2XVW(fPTv6cKADTptAmh zP$=eK<=gf@%1}JF6TVY-=|u&`t@7S|3U}UmS$#P=(Y^qhjr07_<)Ws z_Rv#gOLGed8i`xW^b4|U|)yKxR;Qx6M7Ki!^ zx-8HwgM}UHXz+4Djgb?ie|v^)?hIXe(STykCbvEVv=+ME8#_D#-;(y@@^-M>wp&m% zpe%IrvosO2Gq-`d8fZW@2-sEw0AlAs11efNJ42VSyM_BssexKQ(Qt9_L9s$td8qF} z50n5Z0F8l9fhIr`ds|y$AQ)&4v;bNHZGg5wJD@$#0q6kbjJ+w)3Fr)TwlQ|L06IGu zn}C53pgYi$;cmvzLwGRMdhXV;KY4X`{ZlqSj_H3trH2yx`(g?u+O+pCFk|Q)i;R8)mO*`V0_&f-*ot86}^-*`RezB9a|y6~WoFm3FE(*#lP)M7CW+%TV!ola|ts#Z>b zNcPd!0bAIB_%+j56~=MHYj3z@7DKy}{=tQ5>zPOzSwki&x*aj?Jn`Cu zYuT6~EP9hXw8TPYXI67kA~6X6e8z7JvPl@%##kmYLB^R zHn1Tk8q6NUc<4O~4kRtuhg`8~M7(mNh-yrem<4qOfkE(}BlM&$W3L9!%?QlIIRt7( zibezMkjeI~qb9T`2G`LWqX!ZzHbCh+a!;f7BzaKmfb7Mec0FuuEut~FQF>w`#q_Q1^&s`Y}Zy#Tl4H?axvMQSFU1M zn79`aI6lCcpb9_^qA43%D46J0M2yry)zb1=X_RPbku~@%eXb| z(yhV=59_}QueU)veeya^Jqkx8rY!18$o<{Rv$Avf<$MfW={<}HSNI|0%2g>D56yjG zSD&54HFXmHWnzX*&Oy*<+~RY+o0ML7$ST$A?L*0j+TS8H5i}v}Tx#A^3nXW~O#&)Q zwwplh)f#h0aTJaKHIS5$9GMgpa*VAC~Grgj2B z5;-$g)N@oAd#g#Z&ywr!5NV?Wnx5K@pCWxq(N5CV8tF{pcrZ|jn;!Hn{;O3)XAB2$ z+C;yDKkM0<=KHbC=~)ew(jnFiZoC#IzH&Q86QKkl0bNo>Dl#lGF{z$&nws#>x}o2~ z5@{|&7@o2dlYIu_+R9K?red$XXC5*3CEMqVs((H6)~vh%S+?-0`*4X8sE6bAv!E4j z0fV+|qS}Lyn}v@_2R9ETyJ&(H_WP6M&hlw{QQ{`mCO5{hl%uDurTa-N(7vU)y>1p~ zPT0dp|GYA)+KHoG$F%ROHK#$_}4s{v* z^7Och+TSjIvdc1(205Uf?rjvpNqQdPx$u~8`oMy8N;S9z&VAqOo9lVae@ypfmk%+rE8d>M)->Hz6Oy8 z;Rg(1V#Jbm?G_el9uB(T-sw^Ls4(-qPs^61civvyuD;d7 zo=i5eNM0Asl5C_}vLN^N>;8VMlEp;??Qk?RN56KI3xV#^wBWC1g|;J3@lKPJX$uP^ zK~;p_Pk7Q0Ly|s?TJ_|=(XijqN8pJVJX&$lC$v9#v@rV6w6-uA!lTS;Tn^-~RhnbA zboXpn9o*s@H5J$;O@I7yCF`QHEj9X#(R5<=L}{gA`t4aBEU6}114sL{QdQ=v2v$?8 zaT;%@b@GZZzmitg8|^Ef^d1!k`H7@&xQZ6|i?c~lhFv%B3|=mDdKQ|T9ldoXPzyAi z9adl7d+B&Zy>K}u?>d5E=|%3M+wdvTSjJh^Sv6QURVmYYA$Iv5^^v`yY8V#0=|Ir) zVS)PN^jEnIGuzoISksnVp`*Q;y#&F2Oc#BgU-Oo(iWl(HjSsW+n~UGcqfWy{l4NdF zvr)v!?BOOn9Z1j-8sV-@YHtersN>y8nYQ80BeD5`Ik8EisTiQq{FOP;a#v}mM?bFq zm0YH!SvJ3tW)fv4htJkvyDtamylYL+`BQ(mP+~xF zs2e2-lmf~C9|2{d4wWMCF;EGp3{(ZG0o8#|fZ9KNroVVgcL9Unyrti6<^Owc3Bk%SeZ0K8M9EcxW(@0AAiaSF-9DcEhTDbo< zWfykvSH>z32P6V6$6t{AE!lOF}z4?lY)NH`Jp zI4$(p}Qxur$Jt7szqy`#`>mNJR1r3p;*u2 zqdv!2S(2ob2Cb9V?CdQ3nOxx%UoXFoc&MSGp`=&J*WH}w=)O$KOpMK)tf4@(od3vD zP)jQREQ!Izx{Z~Amd=o{G@kXs5Rr0&pwWFlE?;FF^wwm3O|wEyL8nzZbc~skB$!fZ zBlybz@>eSOV;N~qLc}alPOK4`P7Bzz7=hfd4GSFp$dE=hJ1n>5-nX>#`D2?|Z&{K- z+D&@`jSVf*%cIUMqz|UgAU5zkV=B@2sHBJKgx^maE@4f+d0Svz*v`wLf{*)G?7 zl1A@U_ub0LqZb~8YD)GNmlsD=WqH?dL`Bj;*sC8cPhL(Ff23!@#3_=#Hy*I~_QN}y z=h5JE~SnMLgRgSpfNfdvp9sN(}ZXOR#==$SZAE_EOUe`QXGt(wR4W!ZEfCnb=aB39CetocX_bn$^&Qirr`>HWZ?ZJ-Tq7 z8CT#{$k05|nVmyaMA?W0?6-WB2MSwsQpyHQml>?FKLgmz?DIt4e$A&-IF1K;G%Sh{L<5O{`{6enJH^Tr9Kzp^m z;euXejS5TITbK|AyBCl6Fv1~^R;4?PcvM6dM0KP=suSs7R>VRaJ}g>q`p>6 zub9jTFP_y_4Mu4yMk~o-9mxsK8nOpoCze=rh@b<=nT+uV$OC}%xIWqBm^zG8J61K; zj$2cii%O?2Aa+q@DU_St(nv&4<|yZ>;#6>6Ykfi1YI7#beVj{sE^WIWz%5tAPCzYF z{dD;f&-eRjc{j%+kaMe+zr-#sf1JSV>E^w4p9H)1SC+3EmVb=zV(#V6Qm ztaMP{{PoJ+#}1nk*=ZehO#cK^p6 z>|bMBKcWH9Xv^4zzK~f{4*HvFPoS2&+SVNDF1T{QwFO1 zv4v>>HGx_{9cZk;7y=C!JasZQu?9nIz-G{^ALYCF$z2@5#@_B{G{F=aPcXZSr&zi| zOE!1G1q%-c3$PtD#$W}szKb*5MOmQH20KeTFf`;~5B-LQ9d6G}?(pB0eqjF@i*Woc zV)G*~0k*X?vA-SH8SDzh{ntPR#KH*-4OqC@16_bFcBWt_XA^rTFwhm~2905O06l@8 zU?=;(Y|eL~@!vM*-@-os{pQTc#r1nABU%exD_VQe$FTVvKxW}ZTkRG>lc7!x0VKwu zWhgM@Q7obhlgc2itIB)TqIrx5adN91x zUh%!D&Du@ht2MNBrsiPF=U~fVJV6C3qQG)JW@`A`R7>Na>_lR#g<>SUS6HBFq{GZ% zyh|_!do1Ps+!B9pES)g;s}3vYqXWf3iv5Tq+(<7=U(rQ))+x~z>FXjD1L+3Gj# zD=ENo=H-6&Eef~rG<=k`M(@3Jlh-rTbuP0q9;ta%wIWag8CT*1amC!0;%s#qu#%KY zcag=Ae?)eOT6F?7SH=S|Zw1Ay^deqHKc|AVV$q@Cmtu%26;qOoDGy|Wl@F$9h62&@ z1&ar#WYmecBG3w3icqXLd)0)B0~0`8DaYCB2@Hu+UscQ!__$tuQasIOrstbZ{vaJE7|*FJJ*8C=#xM0E?_`HgsP9Y4d~Qp>Jv)VwHd!=UI_6>PTEU?8i205UrnkT^KywAXfCK%php~5x zH3!~5Q%PrZg!|A*tTBxkOIt2w0y_iCrq#Dr{02?QpAm_J`Pp+=`$-ZG(LPiMe6y8O z42QBW@|X!$M#X(=u>|Cn)U`>+=Pxe(Ls}zQ_e%J^*YYl@nj-k)to0usIei|DHL1fw z%92O?kWVhpNB$j*z2?YO+Utg(g+{p~1+kdE=|x6sQ_eO`&@0nXj%nt#o`xK&qWCb1 zGT=EJpTGQsK=I)s2qgDVbbN98wp`}j+Ypfyw`Rnw<@(G3Hq(U4+%k2}L)KL{laRT=yZWAR=(yyj{ z3aNN8cA-_Eu7`;dpWrJWHz%LKbxMA@+$0ZMm8oJ{PkN{SGXEv6@N6;y-xR((N-)EI zhyQ-vTPf|(L}X{Tl6t8V)uNFc6OO?#S_TQi1(r>hWQU|NG~_uB&@}ok4i>zCACf)F zHxy5!eANSjFsiM>ppzH8jqwyrm4P{It6RG!jucBwPs`H0HcZ%%PfA~8;*i2v_K-Z# zv6(4GxPAr7K`+Ic{$SJ>M#y!k{1^kLlEXCfJy2*e0>19G`Sl7Bx^age92$Uv#2+q{ z=`%=U5zG?CV z_~vq;f%fYqex#99k?!PVCGSqzfuigK3Z@PcOdko2s`2f}W_6tz1-;3U9OwP29Q}tO z5oTRY4V@oM)Z$b)GTHh;g=$$1a`P=0S8J_b=|>n@eU^h#iv`X$n3DFt*=%hkwjk?9 zDDD<^0^+)F%3bVVntNL}81A$(UA!$5Dw-&{T%ErdHDUT56S!r@WTrQ4C6ghD@Exgd1@3i!?5I^Qx+^TNQ7-ph^pc9G zfoWG!7Q!&VW^i4QDCj-lVD{sX%sHMHS*kTcHMK`{j)~Cw8LGe$gt8Y#0~UfbY!@=E zm?X|rrFQQ$cX>4EAG}eTdDc{c@_Fa&TgF7cOeb7<48IJ`Nfw>zWQ~Wf=u%d>%O7tB z?4Gt}EeHD{*{1h|_3<*W5V)`?FR{WbRTVpYH!$X~4s%>6c@Yb*cE^eX_ck?YT=YEZcRAcbGbL0dzMS@d>qQ|HuduVi8zXU~$ zh$jL8+GmCHv%Igp=+_;+Z0#A#mSNjH7~s&I44Z+DL`1sR!_H^X+n2yrCX>0s?HS2T zyHGL~_RqUk#=Q&E+s-}aEb|_ss3HyvD-W12q?qMoHJOLCD|7@h?7=)A_&thB-dwOp}U)(U;c9)6!WR5%l zF`@M}J&(QJ$8_4yVOWYns$O3urMB*E*6eTQ;|pAfOkd*6-?-0Fi2{!q;(HpABdvQy zi~Ju*G+exRWh^NzM|4j3+T1u3#=lCoYX(l{DSDV`x)w?Yn3uFPm5^CWj7n=w@*}=A z{gp)>(K3dQWTVas)p&W3Ji;;Sbf7?b3;$Z$LYcI+G6a`06~-rb*#z9t&!?uA;1CAy z)uKD*imq|-9j8nuZ`{%95;X5Gk{TUE-)C86Km{{8v3(hbaY|R)D{=bR9cC~>0A1{| z^+blS5TC#tQ2O-C;ANMpkDz8-&a+c;2sYV5)7D$~X4iwS$DDY(!nXoQ2cGtm&_*lb$_ z6eUcrXS145(s;65n(^Ekd-F4suunhBr*j$XkmD_7DOup$UufP(f#y|eU|z=)ylRb$ zm3EQv6F+0**EMkYHq6sJnk^uR@nA71l>UfTwpYrUdJe66sb+zAdAXWniT3$w8PYcO zxF4i^ecz#FP*qqN0x*tR->9^ENUNdny3YyACdymTRY{nnv`nsSurTzUE6 zox>n(>z*7HPh_3PHSiYWyWzGPRy}sGYq~m0A%L|mUts4fH zd>oUd=lkFT46X(7rOb_M#(QOYB^rB7%x|SEpEV%wp)?Cl`I;?nxFeF@0Is%Z=wz(x za&W{1;lk*2d+XI7zEH0~m*Qv`UdVn8X9i5Gwx9N|tDNy4T)Qva&sq3fBUgi*`Prdd zvAfx$;Ak92tH`iaffgtG&YN#!Cu26t&KePcT^LT7R9`Mzd-rF?gZ6YBXm*IoKfLc6 z`mn7oZBSnxmrs+`YFR*1OQm@ELSum`>VGhfmY|0fJ?x`ZzfqQI->%t+7F(jZxm zT6CrS>_kM|HHAqvj;jDh61a{?Ys<5^ zG`ChBEQ}DXu-Wf(5y1Z5(scYv)qF@SZroy#U}l96k{%KQ3~Rd9HD~FNi@rG^(wYXB zU)OYty?J@_O1;;pcrIUZ#4J-V1fVzA0{$%ME^D(v(-+d)$eRq(QqK@qY_OCv33yaD zbzJY%4PUtO3RL5|_f9!a6YojR+m<)e!At%3zB?iM5+Mt{3Tzc$8X`7IuFYzDg7kQ! z-$0)cew0GtdxuX|csh_&OHl1Y@K(6~FdKnuTzrVw<&A5_KsDi&WiKCb=1K9==|t|)XQ3P?^)dTI3=Wx?*5Y`@8e8ww6^p=g$>heiJfqOMj%PZlInZ!eh*ZBzHz!;k! zgZZmPJ^bPm6AH;uj5%uZD^DZ#@k5kFZhviwZ5E4W#Ck=7{skk8!Z)d3lz&LDOU7Wky+JyFj zDwFo*aWB`Syqe8+d_T!2^*x8MUu^4+>O zwCWOzQFMD=UnBTIPV00T0kJwFyhxwNZ}K0Nrt07XxEtmYZlycmJyw8_ zAH*G@_lWN`5(1mjU@#X2Osn+ufKb16d#%7RHHB3x0-4~maU57?f6a1YvmY|lgSj8j zM%R3LRmrpnY-yYNJ}Xc7Ae`Gk*PXAJvG{nsGGP1>UR)|}Y}(~cSsm;%ylZO-Ab&t zXgQv?2MjeTIqdBFbOlnHQ=9G|ss!Bh)+sM$t98p<(5efK(t&I;HIiDrI(b0n>=f}t zdj{?BGF6Tq;mCcoK(!GS4N*b(t$aaOo;kz8sm+O6?N>SJy=@mY;d7J(geULj8R^}T zCOhwc^a-PRO>D3fi^1gh{W0OTSE1*J&BKJ^v@g@Ek%W2 z2`(TGPVPUBYy?Hzp~*DRKpNmF*xb@ii0-htoep4WDnzHrrO2k}AOW_peB|i_R`YzU zZsKWe!e>e+B8(;|Vhnw93C!Yd?7(7n_Xilx0BBl}5S4_gf;81_2X}sVTL)Wc5-h;o z*2d16-(86A4ul_CzO4q*0q(j$tcB>b6qNxGdwUyeOK7SsD<3O}1;oJ&Fmr;YF}c}0 zSpz_<+;mWsPNru3s?bE`9|)mWLUa}ohyyc+up?_>@H@$vBi+1P>5Lmp@k z7H1DTh_O41oijCbygNcHwf+FJb7sAxi4~f71hmuwf>_yrzXtks{AX!z2e=*B_^G`M zM2ODC#nP0Y&6L}Omy^>NN+vfu3kYP!&cX(LvGB5S@_^aQ*i4N%O@0mM@Ee(b84ub3 z9gqXc2WW{Onu%@dVghy&qLWcp0LWO_J41e?$pWD4;G+Znoc{k6RZ!XdI~Sk={mBMF zXdiw>XcnrOha@zQT$r5=#KXb{6%Cg<8y`Q2jh~&9g^ib=jZF~vx1LbpLqR2=e}Dr0 zLzMpl^tYbBf!aH%Lsdf9+{xa|4B!flnBGbP1Z4&*`;QUtz<%};1m4Q%H}3pj^UK&l zQSpD~n62%tO5gV5m$Wx=v4y6{$x8meQJDX08Jn8?L9m01lg*uVn3@2=HsD*@oS|X{ zK`Ayh;Wx8)vNeY4wy}c)G?mX70%bH1s*`lWg3v~YB{ak?d}n)NHjp0$8_Qc;;>NmPjK=HUHD9WUq~^nutodH+5Jh@F%DAGGlB{DTKj z1^ZpT5GP}3?yM8^Z><18HA_!0R5t+7M~Cd85BxxrVpIV@Svxa(z+I{cG&w~QperaT zF3!y-CM7N<#v#Sa&IK(adler to the Adler-32 checksum of all input read - so far (that is, total_in bytes). If a gzip stream is being generated, then - strm->adler will be the CRC-32 checksum of the input read so far. (See - deflateInit2 below.) - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is - considered binary. This field is only for information purposes and does not - affect the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL or the state was inadvertently written over - by the application), or Z_BUF_ERROR if no progress is possible (for example - avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and - deflate() can be called again with more input and more output space to - continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. In the current version of inflate, the provided input is not - read or consumed. The allocation of a sliding window will be deferred to - the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to Z_NULL, inflateInit updates - them to use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression. - Actual decompression will be done by inflate(). So next_in, and avail_in, - next_out, and avail_out are unused and unchanged. The current - implementation of inflateInit() does not process any header information -- - that is deferred until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), then next_in and avail_in are updated - accordingly, and processing will resume at this point for the next call of - inflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. If the - caller of inflate() does not provide both available input and available - output space, it is possible that there will be no progress made. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - To assist in this, on return inflate() always sets strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed Adler-32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained unless inflateGetHeader() is used. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - produced so far. The CRC-32 is checked against the gzip trailer, as is the - uncompressed length, modulo 2^32. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value, in which case strm->msg points to a string with a more specific - error), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL, or the state was inadvertently written over - by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR - if no progress was possible or if there was not enough room in the output - buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is to be attempted. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state - was inconsistent. -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - For the current implementation of deflate(), a windowBits value of 8 (a - window size of 256 bytes) is not supported. As a result, a request for 8 - will result in 9 (a 512-byte window). In that case, providing 8 to - inflateInit2() will result in an error when the zlib header with 9 is - checked against the initialization of inflate(). The remedy is to not use 8 - with deflateInit2() with this initialization, or at least in that case use 9 - with inflateInit2(). - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute a check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to the appropriate value, - if the operating system was determined at compile time. If a gzip stream is - being written, strm->adler is a CRC-32 instead of an Adler-32. - - For raw deflate or gzip encoding, a request for a 256-byte window is - rejected as invalid, since only the zlib header provides a means of - transmitting the window size to the decompressor. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the Adler-32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler-32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - Adler-32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by deflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If deflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - deflateGetDictionary() may return a length less than the window size, even - when more than the window size in input has been provided. It may return up - to 258 bytes less in that case, due to how zlib's implementation of deflate - manages the sliding window and lookahead for matches, where matches can be - up to 258 bytes long. If the application needs the last window-size bytes of - input, then that would need to be saved by the application outside of zlib. - - deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, but - does not free and reallocate the internal compression state. The stream - will leave the compression level and any other attributes that may have been - set unchanged. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2(). This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression approach (which is a function of the level) or the - strategy is changed, and if any input has been consumed in a previous - deflate() call, then the input available so far is compressed with the old - level and strategy using deflate(strm, Z_BLOCK). There are three approaches - for the compression levels 0, 1..3, and 4..9 respectively. The new level - and strategy will take effect at the next call of deflate(). - - If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does - not have enough output space to complete, then the parameter change will not - take effect. In this case, deflateParams() can be called again with the - same parameters and more output space to try again. - - In order to assure a change in the parameters on the first try, the - deflate stream should be flushed using deflate() with Z_BLOCK or other flush - request until strm.avail_out is not zero, before calling deflateParams(). - Then no more input data should be provided before the deflateParams() call. - If this is done, the old level and strategy will be applied to the data - compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). - - deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream - state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if - there was not enough output space to complete the compression of the - available input data before a change in the strategy or approach. Note that - in the case of a Z_BUF_ERROR, the parameters are not changed. A return - value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be - retried with more output space. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are Z_NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an Adler-32 or a CRC-32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see - below), inflate() will not automatically decode concatenated gzip streams. - inflate() will return Z_STREAM_END at the end of the gzip stream. The state - would need to be reset to continue decoding a subsequent gzip stream. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler-32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler-32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. If the window size is changed, then the - memory allocated for the window is freed, and the window will be reallocated - by inflate() if needed. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above, or -65536 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the default - behavior of inflate(), which expects a zlib header and trailer around the - deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero -- buf is ignored in that - case -- and inflateBack() will return a buffer error. inflateBack() will - call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. - out() should return zero on success, or non-zero on failure. If out() - returns non-zero, inflateBack() will return with an error. Neither in() nor - out() are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: ZLIB_DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - -#ifndef Z_SOLO - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. compress() is equivalent to compress2() with a level - parameter of Z_DEFAULT_COMPRESSION. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed data. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - -ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong *sourceLen)); -/* - Same as uncompress, except that sourceLen is a pointer, where the - length of the source is *sourceLen. On return, *sourceLen is the number of - source bytes consumed. -*/ - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Three times that size in buffer space is allocated. A larger buffer - size of, for example, 64K or 128K bytes will noticeably increase the speed - of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. Previously provided - data is flushed before the parameter change. - - gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not - opened for writing, Z_ERRNO if there is an error writing the flushed data, - or Z_MEM_ERROR if there is a memory allocation error. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. If len is too large to fit in an int, - then nothing is read, -1 is returned, and the error state is set to - Z_STREAM_ERROR. -*/ - -ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, - gzFile file)); -/* - Read up to nitems items of size size from file to buf, otherwise operating - as gzread() does. This duplicates the interface of stdio's fread(), with - size_t request and return types. If the library defines size_t, then - z_size_t is identical to size_t. If not, then z_size_t is an unsigned - integer type that can contain a pointer. - - gzfread() returns the number of full items read of size size, or zero if - the end of the file was reached and a full item could not be read, or if - there was an error. gzerror() must be consulted if zero is returned in - order to determine if there was an error. If the multiplication of size and - nitems overflows, i.e. the product does not fit in a z_size_t, then nothing - is read, zero is returned, and the error state is set to Z_STREAM_ERROR. - - In the event that the end of file is reached and only a partial item is - available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevetheless read into buf - and the end-of-file flag is set. The length of the partial item read is not - provided, but could be inferred from the result of gztell(). This behavior - is the same as the behavior of fread() implementations in common libraries, - but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, - z_size_t nitems, gzFile file)); -/* - gzfwrite() writes nitems items of size size from buf to file, duplicating - the interface of stdio's fwrite(), with size_t request and return types. If - the library defines size_t, then z_size_t is identical to size_t. If not, - then z_size_t is an unsigned integer type that can contain a pointer. - - gzfwrite() returns the number of full items written of size size, or zero - if there was an error. If the multiplication of size and nitems overflows, - i.e. the product does not fit in a z_size_t, then nothing is written, zero - is returned, and the error state is set to Z_STREAM_ERROR. -*/ - -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or a negative zlib error code in case - of error. The number of uncompressed bytes written is limited to 8191, or - one less than the buffer size given to gzbuffer(). The caller should assure - that this limit is not exceeded. If it is exceeded, then gzprintf() will - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. - This can be determined using zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatenated gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - -#endif /* !Z_SOLO */ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); -/* - Same as adler32(), but with a size_t length. -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); -/* - Same as crc32(), but with a size_t length. -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#ifdef Z_PREFIX_SET -# define z_deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -# define z_inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -# define z_inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) -#else -# define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -# define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -# define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -# define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) -#endif - -#ifndef Z_SOLO - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ -#ifdef Z_PREFIX_SET -# undef z_gzgetc -# define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) -#else -# define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) -#endif - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) -# ifdef Z_PREFIX_SET -# define z_gzopen z_gzopen64 -# define z_gzseek z_gzseek64 -# define z_gztell z_gztell64 -# define z_gzoffset z_gzoffset64 -# define z_adler32_combine z_adler32_combine64 -# define z_crc32_combine z_crc32_combine64 -# else -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# endif -# ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -#else /* Z_SOLO */ - - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - -#endif /* !Z_SOLO */ - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); -# endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/src/contrib/zlib/zlib.map b/src/contrib/zlib/zlib.map deleted file mode 100644 index 82ce98c..0000000 --- a/src/contrib/zlib/zlib.map +++ /dev/null @@ -1,94 +0,0 @@ -ZLIB_1.2.0 { - global: - compressBound; - deflateBound; - inflateBack; - inflateBackEnd; - inflateBackInit_; - inflateCopy; - local: - deflate_copyright; - inflate_copyright; - inflate_fast; - inflate_table; - zcalloc; - zcfree; - z_errmsg; - gz_error; - gz_intmax; - _*; -}; - -ZLIB_1.2.0.2 { - gzclearerr; - gzungetc; - zlibCompileFlags; -} ZLIB_1.2.0; - -ZLIB_1.2.0.8 { - deflatePrime; -} ZLIB_1.2.0.2; - -ZLIB_1.2.2 { - adler32_combine; - crc32_combine; - deflateSetHeader; - inflateGetHeader; -} ZLIB_1.2.0.8; - -ZLIB_1.2.2.3 { - deflateTune; - gzdirect; -} ZLIB_1.2.2; - -ZLIB_1.2.2.4 { - inflatePrime; -} ZLIB_1.2.2.3; - -ZLIB_1.2.3.3 { - adler32_combine64; - crc32_combine64; - gzopen64; - gzseek64; - gztell64; - inflateUndermine; -} ZLIB_1.2.2.4; - -ZLIB_1.2.3.4 { - inflateReset2; - inflateMark; -} ZLIB_1.2.3.3; - -ZLIB_1.2.3.5 { - gzbuffer; - gzoffset; - gzoffset64; - gzclose_r; - gzclose_w; -} ZLIB_1.2.3.4; - -ZLIB_1.2.5.1 { - deflatePending; -} ZLIB_1.2.3.5; - -ZLIB_1.2.5.2 { - deflateResetKeep; - gzgetc_; - inflateResetKeep; -} ZLIB_1.2.5.1; - -ZLIB_1.2.7.1 { - inflateGetDictionary; - gzvprintf; -} ZLIB_1.2.5.2; - -ZLIB_1.2.9 { - inflateCodesUsed; - inflateValidate; - uncompress2; - gzfread; - gzfwrite; - deflateGetDictionary; - adler32_z; - crc32_z; -} ZLIB_1.2.7.1; diff --git a/src/contrib/zlib/zlib.pc.cmakein b/src/contrib/zlib/zlib.pc.cmakein deleted file mode 100644 index a5e6429..0000000 --- a/src/contrib/zlib/zlib.pc.cmakein +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@INSTALL_LIB_DIR@ -sharedlibdir=@INSTALL_LIB_DIR@ -includedir=@INSTALL_INC_DIR@ - -Name: zlib -Description: zlib compression library -Version: @VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz -Cflags: -I${includedir} diff --git a/src/contrib/zlib/zlib.pc.in b/src/contrib/zlib/zlib.pc.in deleted file mode 100644 index 7e5acf9..0000000 --- a/src/contrib/zlib/zlib.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -sharedlibdir=@sharedlibdir@ -includedir=@includedir@ - -Name: zlib -Description: zlib compression library -Version: @VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz -Cflags: -I${includedir} diff --git a/src/contrib/zlib/zlib2ansi b/src/contrib/zlib/zlib2ansi deleted file mode 100644 index 15e3e16..0000000 --- a/src/contrib/zlib/zlib2ansi +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/perl - -# Transform K&R C function definitions into ANSI equivalent. -# -# Author: Paul Marquess -# Version: 1.0 -# Date: 3 October 2006 - -# TODO -# -# Asumes no function pointer parameters. unless they are typedefed. -# Assumes no literal strings that look like function definitions -# Assumes functions start at the beginning of a line - -use strict; -use warnings; - -local $/; -$_ = <>; - -my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments - -my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; -my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; -my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; - - -while (s/^ - ( # Start $1 - ( # Start $2 - .*? # Minimal eat content - ( ^ \w [\w\s\*]+ ) # $3 -- function name - \s* # optional whitespace - ) # $2 - Matched up to before parameter list - - \( \s* # Literal "(" + optional whitespace - ( [^\)]+ ) # $4 - one or more anythings except ")" - \s* \) # optional whitespace surrounding a Literal ")" - - ( (?: $dList )+ ) # $5 - - $sp ^ { # literal "{" at start of line - ) # Remember to $1 - //xsom - ) -{ - my $all = $1 ; - my $prefix = $2; - my $param_list = $4 ; - my $params = $5; - - StripComments($params); - StripComments($param_list); - $param_list =~ s/^\s+//; - $param_list =~ s/\s+$//; - - my $i = 0 ; - my %pList = map { $_ => $i++ } - split /\s*,\s*/, $param_list; - my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; - - my @params = split /\s*;\s*/, $params; - my @outParams = (); - foreach my $p (@params) - { - if ($p =~ /,/) - { - my @bits = split /\s*,\s*/, $p; - my $first = shift @bits; - $first =~ s/^\s*//; - push @outParams, $first; - $first =~ /^(\w+\s*)/; - my $type = $1 ; - push @outParams, map { $type . $_ } @bits; - } - else - { - $p =~ s/^\s+//; - push @outParams, $p; - } - } - - - my %tmp = map { /$pMatch/; $_ => $pList{$1} } - @outParams ; - - @outParams = map { " $_" } - sort { $tmp{$a} <=> $tmp{$b} } - @outParams ; - - print $prefix ; - print "(\n" . join(",\n", @outParams) . ")\n"; - print "{" ; - -} - -# Output any trailing code. -print ; -exit 0; - - -sub StripComments -{ - - no warnings; - - # Strip C & C++ coments - # From the perlfaq - $_[0] =~ - - s{ - /\* ## Start of /* ... */ comment - [^*]*\*+ ## Non-* followed by 1-or-more *'s - ( - [^/*][^*]*\*+ - )* ## 0-or-more things which don't start with / - ## but do end with '*' - / ## End of /* ... */ comment - - | ## OR C++ Comment - // ## Start of C++ comment // - [^\n]* ## followed by 0-or-more non end of line characters - - | ## OR various things which aren't comments: - - ( - " ## Start of " ... " string - ( - \\. ## Escaped char - | ## OR - [^"\\] ## Non "\ - )* - " ## End of " ... " string - - | ## OR - - ' ## Start of ' ... ' string - ( - \\. ## Escaped char - | ## OR - [^'\\] ## Non '\ - )* - ' ## End of ' ... ' string - - | ## OR - - . ## Anything other char - [^/"'\\]* ## Chars which doesn't start a comment, string or escape - ) - }{$2}gxs; - -} diff --git a/src/contrib/zlib/zutil.c b/src/contrib/zlib/zutil.c deleted file mode 100644 index a76c6b0..0000000 --- a/src/contrib/zlib/zutil.c +++ /dev/null @@ -1,325 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2017 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" -#ifndef Z_SOLO -# include "gzguts.h" -#endif - -z_const char * const z_errmsg[10] = { - (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ - (z_const char *)"stream end", /* Z_STREAM_END 1 */ - (z_const char *)"", /* Z_OK 0 */ - (z_const char *)"file error", /* Z_ERRNO (-1) */ - (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ - (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ - (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ - (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ - (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ - (z_const char *)"" -}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch ((int)(sizeof(uInt))) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch ((int)(sizeof(uLong))) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch ((int)(sizeof(voidpf))) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch ((int)(sizeof(z_off_t))) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef ZLIB_DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef ZLIB_DEBUG -#include -# ifndef verbose -# define verbose 0 -# endif -int ZLIB_INTERNAL z_verbose = verbose; - -void ZLIB_INTERNAL z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#ifndef HAVE_MEMCPY - -void ZLIB_INTERNAL zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int ZLIB_INTERNAL zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void ZLIB_INTERNAL zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifndef Z_SOLO - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf; - ulg bsize = (ulg)items*size; - - (void)opaque; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - int n; - - (void)opaque; - - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) -{ - (void)opaque; - return _halloc((long)items, size); -} - -void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) -{ - (void)opaque; - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - (void)opaque; - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void ZLIB_INTERNAL zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - (void)opaque; - free(ptr); -} - -#endif /* MY_ZCALLOC */ - -#endif /* !Z_SOLO */ diff --git a/src/contrib/zlib/zutil.h b/src/contrib/zlib/zutil.h deleted file mode 100644 index b079ea6..0000000 --- a/src/contrib/zlib/zutil.h +++ /dev/null @@ -1,271 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#ifdef HAVE_HIDDEN -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include "zlib.h" - -#if defined(STDC) && !defined(Z_SOLO) -# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) -# include -# endif -# include -# include -#endif - -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#endif - -#ifndef local -# define local static -#endif -/* since "static" is used to mean two completely different things in C, we - define "local" for the non-static meaning of "static", for readability - (compile with -Dlocal if your debugger can't find static symbols) */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# ifndef Z_SOLO -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif -# else /* MSC or DJGPP */ -# include -# endif -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 1 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 2 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#ifdef __370__ -# if __TARGET_LIB__ < 0x20000000 -# define OS_CODE 4 -# elif __TARGET_LIB__ < 0x40000000 -# define OS_CODE 11 -# else -# define OS_CODE 8 -# endif -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 5 -#endif - -#ifdef OS2 -# define OS_CODE 6 -# if defined(M_I86) && !defined(Z_SOLO) -# include -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 7 -# ifndef Z_SOLO -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -# endif -#endif - -#ifdef __acorn -# define OS_CODE 13 -#endif - -#if defined(WIN32) && !defined(__CYGWIN__) -# define OS_CODE 10 -#endif - -#ifdef _BEOS_ -# define OS_CODE 16 -#endif - -#ifdef __TOS_OS400__ -# define OS_CODE 18 -#endif - -#ifdef __APPLE__ -# define OS_CODE 19 -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - -#if defined(__BORLANDC__) && !defined(MSDOS) - #pragma warn -8004 - #pragma warn -8008 - #pragma warn -8066 -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && \ - (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 3 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(pyr) || defined(Z_SOLO) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef ZLIB_DEBUG -# include - extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -#ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); -#endif - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -/* Reverse the bytes in a 32-bit value */ -#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -#endif /* ZUTIL_H */ diff --git a/src/crypto/RIPEMD160.c b/src/crypto/RIPEMD160.c deleted file mode 100644 index 0f83230..0000000 --- a/src/crypto/RIPEMD160.c +++ /dev/null @@ -1,287 +0,0 @@ -/********************************************************************\ -* -* FILE: rmd160.c -* -* CONTENTS: A sample C-implementation of the RIPEMD-160 -* hash-function. -* TARGET: any computer with an ANSI C compiler -* -* AUTHOR: Antoon Bosselaers, ESAT-COSIC -* DATE: 1 March 1996 -* VERSION: 1.0 -* -* Copyright (c) 1996 Katholieke Universiteit Leuven -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, -* publish, distribute, sublicense, and/or sell copies of the Software, -* and to permit persons to whom the Software is furnished to do so, -* subject to the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -\********************************************************************/ - -/* header files */ -#include -#include -#include -#include "RIPEMD160.h" - -/********************************************************************/ - -void MDinit(dword *MDbuf) -{ - MDbuf[0] = 0x67452301UL; - MDbuf[1] = 0xefcdab89UL; - MDbuf[2] = 0x98badcfeUL; - MDbuf[3] = 0x10325476UL; - MDbuf[4] = 0xc3d2e1f0UL; - - return; -} - -/********************************************************************/ - -void compress(dword *MDbuf, dword *X) -{ - dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], - dd = MDbuf[3], ee = MDbuf[4]; - dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], - ddd = MDbuf[3], eee = MDbuf[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[0], 11); - FF(ee, aa, bb, cc, dd, X[1], 14); - FF(dd, ee, aa, bb, cc, X[2], 15); - FF(cc, dd, ee, aa, bb, X[3], 12); - FF(bb, cc, dd, ee, aa, X[4], 5); - FF(aa, bb, cc, dd, ee, X[5], 8); - FF(ee, aa, bb, cc, dd, X[6], 7); - FF(dd, ee, aa, bb, cc, X[7], 9); - FF(cc, dd, ee, aa, bb, X[8], 11); - FF(bb, cc, dd, ee, aa, X[9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[7], 7); - GG(dd, ee, aa, bb, cc, X[4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[0], 12); - GG(ee, aa, bb, cc, dd, X[9], 15); - GG(dd, ee, aa, bb, cc, X[5], 9); - GG(cc, dd, ee, aa, bb, X[2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[4], 7); - HH(ee, aa, bb, cc, dd, X[9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[8], 13); - HH(bb, cc, dd, ee, aa, X[1], 15); - HH(aa, bb, cc, dd, ee, X[2], 14); - HH(ee, aa, bb, cc, dd, X[7], 8); - HH(dd, ee, aa, bb, cc, X[0], 13); - HH(cc, dd, ee, aa, bb, X[6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[1], 11); - II(bb, cc, dd, ee, aa, X[9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[0], 14); - II(cc, dd, ee, aa, bb, X[8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[3], 14); - II(cc, dd, ee, aa, bb, X[7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[5], 6); - II(dd, ee, aa, bb, cc, X[6], 5); - II(cc, dd, ee, aa, bb, X[2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[4], 9); - JJ(aa, bb, cc, dd, ee, X[0], 15); - JJ(ee, aa, bb, cc, dd, X[5], 5); - JJ(dd, ee, aa, bb, cc, X[9], 11); - JJ(cc, dd, ee, aa, bb, X[7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[1], 12); - JJ(bb, cc, dd, ee, aa, X[3], 13); - JJ(aa, bb, cc, dd, ee, X[8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[3], 15); - III(bbb, ccc, ddd, eee, aaa, X[7], 7); - III(aaa, bbb, ccc, ddd, eee, X[0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[4], 6); - III(bbb, ccc, ddd, eee, aaa, X[9], 15); - III(aaa, bbb, ccc, ddd, eee, X[1], 13); - III(eee, aaa, bbb, ccc, ddd, X[2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12], 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15], 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10], 12); - FFF(ddd, eee, aaa, bbb, ccc, X[4], 9); - FFF(ccc, ddd, eee, aaa, bbb, X[1], 12); - FFF(bbb, ccc, ddd, eee, aaa, X[5], 5); - FFF(aaa, bbb, ccc, ddd, eee, X[8], 14); - FFF(eee, aaa, bbb, ccc, ddd, X[7], 6); - FFF(ddd, eee, aaa, bbb, ccc, X[6], 8); - FFF(ccc, ddd, eee, aaa, bbb, X[2], 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13], 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14], 5); - FFF(eee, aaa, bbb, ccc, ddd, X[0], 15); - FFF(ddd, eee, aaa, bbb, ccc, X[3], 13); - FFF(ccc, ddd, eee, aaa, bbb, X[9], 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11], 11); - - /* combine results */ - ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ - MDbuf[1] = MDbuf[2] + dd + eee; - MDbuf[2] = MDbuf[3] + ee + aaa; - MDbuf[3] = MDbuf[4] + aa + bbb; - MDbuf[4] = MDbuf[0] + bb + ccc; - MDbuf[0] = ddd; - - return; -} - -/********************************************************************/ - -void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen) -{ - unsigned int i; /* counter */ - dword X[16]; /* message words */ - - memset(X, 0, 16 * sizeof(dword)); - - /* put bytes from strptr into X */ - for (i = 0; i<(lswlen & 63); i++) { - /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ - X[i >> 2] ^= (dword)*strptr++ << (8 * (i & 3)); - } - - /* append the bit m_n == 1 */ - X[(lswlen >> 2) & 15] ^= (dword)1 << (8 * (lswlen & 3) + 7); - - if ((lswlen & 63) > 55) { - /* length goes to next block */ - compress(MDbuf, X); - memset(X, 0, 16 * sizeof(dword)); - } - - /* append length in bits*/ - X[14] = lswlen << 3; - X[15] = (lswlen >> 29) | (mswlen << 3); - compress(MDbuf, X); - - return; -} - -/************************ end of file rmd160.c **********************/ diff --git a/src/crypto/RIPEMD160.h b/src/crypto/RIPEMD160.h deleted file mode 100644 index f0ea97e..0000000 --- a/src/crypto/RIPEMD160.h +++ /dev/null @@ -1,150 +0,0 @@ -/********************************************************************\ -* -* FILE: rmd160.h -* -* CONTENTS: Header file for a sample C-implementation of the -* RIPEMD-160 hash-function. -* TARGET: any computer with an ANSI C compiler -* -* AUTHOR: Antoon Bosselaers, ESAT-COSIC -* DATE: 1 March 1996 -* VERSION: 1.0 -* -* Copyright (c) 1996 Katholieke Universiteit Leuven -* -* Permission is hereby granted, free of charge, to any person -* obtaining a copy of this software and associated documentation -* files (the "Software"), to deal in the Software without restriction, -* including without limitation the rights to use, copy, modify, merge, -* publish, distribute, sublicense, and/or sell copies of the Software, -* and to permit persons to whom the Software is furnished to do so, -* subject to the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* -\********************************************************************/ - -#ifndef RMD160H /* make sure this file is read only once */ -#define RMD160H - -/********************************************************************/ -#include -/* typedef 8 and 32 bit types, resp. */ -/* adapt these, if necessary, -for your operating system and compiler */ -typedef unsigned char byte; -typedef uint32_t dword; - -/* if this line causes a compiler error, -adapt the defintion of dword above */ -typedef int the_correct_size_was_chosen[sizeof(dword) == 4 ? 1 : -1]; - -/********************************************************************/ - -/* macro definitions */ - -/* collect four bytes into one word: */ -#define BYTES_TO_DWORD(strptr) \ - (((dword) *((strptr)+3) << 24) | \ - ((dword) *((strptr)+2) << 16) | \ - ((dword) *((strptr)+1) << 8) | \ - ((dword) *(strptr))) - -/* ROL(x, n) cyclically rotates x over n bits to the left */ -/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ -#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* the five basic functions F(), G() and H() */ -#define F(x, y, z) ((x) ^ (y) ^ (z)) -#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define H(x, y, z) (((x) | ~(y)) ^ (z)) -#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define J(x, y, z) ((x) ^ ((y) | ~(z))) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) {\ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define GG(a, b, c, d, e, x, s) {\ - (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define HH(a, b, c, d, e, x, s) {\ - (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define II(a, b, c, d, e, x, s) {\ - (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define JJ(a, b, c, d, e, x, s) {\ - (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define FFF(a, b, c, d, e, x, s) {\ - (a) += F((b), (c), (d)) + (x);\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define GGG(a, b, c, d, e, x, s) {\ - (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define HHH(a, b, c, d, e, x, s) {\ - (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define III(a, b, c, d, e, x, s) {\ - (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } -#define JJJ(a, b, c, d, e, x, s) {\ - (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ - (a) = ROL((a), (s)) + (e);\ - (c) = ROL((c), 10);\ - } - -/********************************************************************/ - -/* function prototypes */ - -void MDinit(dword *MDbuf); -/* -* initializes MDbuffer to "magic constants" -*/ - -void compress(dword *MDbuf, dword *X); -/* -* the compression function. -* transforms MDbuf using message bytes X[0] through X[15] -*/ - -void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen); -/* -* puts bytes from strptr into X and pad out; appends length -* and finally, compresses the last block(s) -* note: length in bits == 8 * (lswlen + 2^32 mswlen). -* note: there are (lswlen mod 64) bytes left in strptr. -*/ - -#endif /* RMD160H */ - -/*********************** end of file rmd160.h ***********************/ diff --git a/src/crypto/RIPEMD160_helper.cpp b/src/crypto/RIPEMD160_helper.cpp deleted file mode 100644 index 1386540..0000000 --- a/src/crypto/RIPEMD160_helper.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2020 The Zano developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "RIPEMD160_helper.h" -#include "auto_val_init.h" -extern "C" { -#include "RIPEMD160.h" -} - -#define RMDsize 160 - -namespace crypto { - - void RIPEMD160_hash(const void *data, size_t length_size_t, hash160 &h) - { - - dword MDbuf[RMDsize / 32] = {0}; /* contains (A, B, C, D(, E)) */ - byte* hashcode = (byte*)&h; /* hashcode[RMDsize / 8]; /* for final hash-value */ - dword X[16] = {0}; /* current 16-word chunk */ - unsigned int i = 0; /* counter */ - dword length = static_cast(length_size_t); /* length in bytes of message */ - dword nbytes = 0; /* # of bytes not yet processed */ - byte* message = (byte*)data; - - /* initialize */ - MDinit(MDbuf); - //length = (dword)strlen((char *)message); - - /* process message in 16-word chunks */ - for (nbytes = length; nbytes > 63; nbytes -= 64) { - for (i = 0; i < 16; i++) { - X[i] = BYTES_TO_DWORD(message); - message += 4; - } - compress(MDbuf, X); - }/* length mod 64 bytes left */ - - /* finish: */ - MDfinish(MDbuf, message, length, 0); - - for (i = 0; i < RMDsize / 8; i += 4) { - hashcode[i] = (byte)MDbuf[i >> 2]; /* implicit cast to byte */ - hashcode[i + 1] = (byte)(MDbuf[i >> 2] >> 8); /* extracts the 8 least */ - hashcode[i + 2] = (byte)(MDbuf[i >> 2] >> 16); /* significant bits. */ - hashcode[i + 3] = (byte)(MDbuf[i >> 2] >> 24); - } - } - - hash160 RIPEMD160_hash(const void *data, size_t length) - { - hash160 h = AUTO_VAL_INIT(h); - RIPEMD160_hash(data, length, h); - return h; - } - - hash RIPEMD160_hash_256(const void *data, size_t length) - { - hash160 h = RIPEMD160_hash(data, length); - hash h256 = AUTO_VAL_INIT(h256); - memcpy(&h256, &h, sizeof(h)); - return h256; - } - -} diff --git a/src/crypto/RIPEMD160_helper.h b/src/crypto/RIPEMD160_helper.h deleted file mode 100644 index 2257e2b..0000000 --- a/src/crypto/RIPEMD160_helper.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2020 The Zano developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "hash.h" - - -namespace crypto { - -#pragma pack(push, 1) - POD_CLASS hash160{ - char data[20]; - }; -#pragma pack(pop) - - void RIPEMD160_hash(const void *data, size_t length, hash160 &h); - hash160 RIPEMD160_hash(const void *data, size_t length); - hash RIPEMD160_hash_256(const void *data, size_t length); - -} - -POD_MAKE_HASHABLE(crypto, hash160) - - - diff --git a/src/crypto/bitcoin/byteswap.h b/src/crypto/bitcoin/byteswap.h deleted file mode 100644 index 27ef1a1..0000000 --- a/src/crypto/bitcoin/byteswap.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2014-2019 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_COMPAT_BYTESWAP_H -#define BITCOIN_COMPAT_BYTESWAP_H - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include - -#if defined(HAVE_BYTESWAP_H) -#include -#endif - -#if defined(MAC_OSX) - -#include -#define bswap_16(x) OSSwapInt16(x) -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) - -#else -// Non-MacOS / non-Darwin - -#if HAVE_DECL_BSWAP_16 == 0 -inline uint16_t bswap_16(uint16_t x) -{ - return (x >> 8) | (x << 8); -} -#endif // HAVE_DECL_BSWAP16 == 0 - -#if HAVE_DECL_BSWAP_32 == 0 -inline uint32_t bswap_32(uint32_t x) -{ - return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) | - ((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24)); -} -#endif // HAVE_DECL_BSWAP32 == 0 - -#if HAVE_DECL_BSWAP_64 == 0 -inline uint64_t bswap_64(uint64_t x) -{ - return (((x & 0xff00000000000000ull) >> 56) - | ((x & 0x00ff000000000000ull) >> 40) - | ((x & 0x0000ff0000000000ull) >> 24) - | ((x & 0x000000ff00000000ull) >> 8) - | ((x & 0x00000000ff000000ull) << 8) - | ((x & 0x0000000000ff0000ull) << 24) - | ((x & 0x000000000000ff00ull) << 40) - | ((x & 0x00000000000000ffull) << 56)); -} -#endif // HAVE_DECL_BSWAP64 == 0 - -#endif // defined(MAC_OSX) - -#endif // BITCOIN_COMPAT_BYTESWAP_H diff --git a/src/crypto/bitcoin/common.h b/src/crypto/bitcoin/common.h deleted file mode 100644 index afaf0e1..0000000 --- a/src/crypto/bitcoin/common.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2014-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_CRYPTO_COMMON_H -#define BITCOIN_CRYPTO_COMMON_H - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include -#include - -#include "endian.h" - -uint16_t static inline ReadLE16(const unsigned char* ptr) -{ - uint16_t x; - memcpy((char*)&x, ptr, 2); - return le16toh(x); -} - -uint32_t static inline ReadLE32(const unsigned char* ptr) -{ - uint32_t x; - memcpy((char*)&x, ptr, 4); - return le32toh(x); -} - -uint64_t static inline ReadLE64(const unsigned char* ptr) -{ - uint64_t x; - memcpy((char*)&x, ptr, 8); - return le64toh(x); -} - -void static inline WriteLE16(unsigned char* ptr, uint16_t x) -{ - uint16_t v = htole16(x); - memcpy(ptr, (char*)&v, 2); -} - -void static inline WriteLE32(unsigned char* ptr, uint32_t x) -{ - uint32_t v = htole32(x); - memcpy(ptr, (char*)&v, 4); -} - -void static inline WriteLE64(unsigned char* ptr, uint64_t x) -{ - uint64_t v = htole64(x); - memcpy(ptr, (char*)&v, 8); -} - -uint16_t static inline ReadBE16(const unsigned char* ptr) -{ - uint16_t x; - memcpy((char*)&x, ptr, 2); - return be16toh(x); -} - -uint32_t static inline ReadBE32(const unsigned char* ptr) -{ - uint32_t x; - memcpy((char*)&x, ptr, 4); - return be32toh(x); -} - -uint64_t static inline ReadBE64(const unsigned char* ptr) -{ - uint64_t x; - memcpy((char*)&x, ptr, 8); - return be64toh(x); -} - -void static inline WriteBE32(unsigned char* ptr, uint32_t x) -{ - uint32_t v = htobe32(x); - memcpy(ptr, (char*)&v, 4); -} - -void static inline WriteBE64(unsigned char* ptr, uint64_t x) -{ - uint64_t v = htobe64(x); - memcpy(ptr, (char*)&v, 8); -} - -/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ -uint64_t static inline CountBits(uint64_t x) -{ -#if HAVE_BUILTIN_CLZL - if (sizeof(unsigned long) >= sizeof(uint64_t)) { - return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; - } -#endif -#if HAVE_BUILTIN_CLZLL - if (sizeof(unsigned long long) >= sizeof(uint64_t)) { - return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; - } -#endif - int ret = 0; - while (x) { - x >>= 1; - ++ret; - } - return ret; -} - -#endif // BITCOIN_CRYPTO_COMMON_H \ No newline at end of file diff --git a/src/crypto/bitcoin/cpuid.h b/src/crypto/bitcoin/cpuid.h deleted file mode 100644 index 0877ad4..0000000 --- a/src/crypto/bitcoin/cpuid.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2017-2019 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_COMPAT_CPUID_H -#define BITCOIN_COMPAT_CPUID_H - -#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) -#define HAVE_GETCPUID - -#include - -// We can't use cpuid.h's __get_cpuid as it does not support subleafs. -void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) -{ -#ifdef __GNUC__ - __cpuid_count(leaf, subleaf, a, b, c, d); -#else - __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); -#endif -} - -#endif // defined(__x86_64__) || defined(__amd64__) || defined(__i386__) -#endif // BITCOIN_COMPAT_CPUID_H diff --git a/src/crypto/bitcoin/endian.h b/src/crypto/bitcoin/endian.h deleted file mode 100644 index 354c637..0000000 --- a/src/crypto/bitcoin/endian.h +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2014-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_COMPAT_ENDIAN_H -#define BITCOIN_COMPAT_ENDIAN_H - -#if defined(HAVE_CONFIG_H) -#include -#endif - -#include "byteswap.h" - -#include - -#if defined(HAVE_ENDIAN_H) -#include -#elif defined(HAVE_SYS_ENDIAN_H) -#include -#endif - -#ifndef HAVE_CONFIG_H -// While not technically a supported configuration, defaulting to defining these -// DECLs when we were compiled without autotools makes it easier for other build -// systems to build things like libbitcoinconsensus for strange targets. -#ifdef htobe16 -#define HAVE_DECL_HTOBE16 1 -#endif -#ifdef htole16 -#define HAVE_DECL_HTOLE16 1 -#endif -#ifdef be16toh -#define HAVE_DECL_BE16TOH 1 -#endif -#ifdef le16toh -#define HAVE_DECL_LE16TOH 1 -#endif - -#ifdef htobe32 -#define HAVE_DECL_HTOBE32 1 -#endif -#ifdef htole32 -#define HAVE_DECL_HTOLE32 1 -#endif -#ifdef be32toh -#define HAVE_DECL_BE32TOH 1 -#endif -#ifdef le32toh -#define HAVE_DECL_LE32TOH 1 -#endif - -#ifdef htobe64 -#define HAVE_DECL_HTOBE64 1 -#endif -#ifdef htole64 -#define HAVE_DECL_HTOLE64 1 -#endif -#ifdef be64toh -#define HAVE_DECL_BE64TOH 1 -#endif -#ifdef le64toh -#define HAVE_DECL_LE64TOH 1 -#endif - -#endif // HAVE_CONFIG_H - -#if defined(WORDS_BIGENDIAN) - -#if HAVE_DECL_HTOBE16 == 0 -inline uint16_t htobe16(uint16_t host_16bits) -{ - return host_16bits; -} -#endif // HAVE_DECL_HTOBE16 - -#if HAVE_DECL_HTOLE16 == 0 -inline uint16_t htole16(uint16_t host_16bits) -{ - return bswap_16(host_16bits); -} -#endif // HAVE_DECL_HTOLE16 - -#if HAVE_DECL_BE16TOH == 0 -inline uint16_t be16toh(uint16_t big_endian_16bits) -{ - return big_endian_16bits; -} -#endif // HAVE_DECL_BE16TOH - -#if HAVE_DECL_LE16TOH == 0 -inline uint16_t le16toh(uint16_t little_endian_16bits) -{ - return bswap_16(little_endian_16bits); -} -#endif // HAVE_DECL_LE16TOH - -#if HAVE_DECL_HTOBE32 == 0 -inline uint32_t htobe32(uint32_t host_32bits) -{ - return host_32bits; -} -#endif // HAVE_DECL_HTOBE32 - -#if HAVE_DECL_HTOLE32 == 0 -inline uint32_t htole32(uint32_t host_32bits) -{ - return bswap_32(host_32bits); -} -#endif // HAVE_DECL_HTOLE32 - -#if HAVE_DECL_BE32TOH == 0 -inline uint32_t be32toh(uint32_t big_endian_32bits) -{ - return big_endian_32bits; -} -#endif // HAVE_DECL_BE32TOH - -#if HAVE_DECL_LE32TOH == 0 -inline uint32_t le32toh(uint32_t little_endian_32bits) -{ - return bswap_32(little_endian_32bits); -} -#endif // HAVE_DECL_LE32TOH - -#if HAVE_DECL_HTOBE64 == 0 -inline uint64_t htobe64(uint64_t host_64bits) -{ - return host_64bits; -} -#endif // HAVE_DECL_HTOBE64 - -#if HAVE_DECL_HTOLE64 == 0 -inline uint64_t htole64(uint64_t host_64bits) -{ - return bswap_64(host_64bits); -} -#endif // HAVE_DECL_HTOLE64 - -#if HAVE_DECL_BE64TOH == 0 -inline uint64_t be64toh(uint64_t big_endian_64bits) -{ - return big_endian_64bits; -} -#endif // HAVE_DECL_BE64TOH - -#if HAVE_DECL_LE64TOH == 0 -inline uint64_t le64toh(uint64_t little_endian_64bits) -{ - return bswap_64(little_endian_64bits); -} -#endif // HAVE_DECL_LE64TOH - -#else // WORDS_BIGENDIAN - -#if HAVE_DECL_HTOBE16 == 0 -inline uint16_t htobe16(uint16_t host_16bits) -{ - return bswap_16(host_16bits); -} -#endif // HAVE_DECL_HTOBE16 - -#if HAVE_DECL_HTOLE16 == 0 -inline uint16_t htole16(uint16_t host_16bits) -{ - return host_16bits; -} -#endif // HAVE_DECL_HTOLE16 - -#if HAVE_DECL_BE16TOH == 0 -inline uint16_t be16toh(uint16_t big_endian_16bits) -{ - return bswap_16(big_endian_16bits); -} -#endif // HAVE_DECL_BE16TOH - -#if HAVE_DECL_LE16TOH == 0 -inline uint16_t le16toh(uint16_t little_endian_16bits) -{ - return little_endian_16bits; -} -#endif // HAVE_DECL_LE16TOH - -#if HAVE_DECL_HTOBE32 == 0 -inline uint32_t htobe32(uint32_t host_32bits) -{ - return bswap_32(host_32bits); -} -#endif // HAVE_DECL_HTOBE32 - -#if HAVE_DECL_HTOLE32 == 0 -inline uint32_t htole32(uint32_t host_32bits) -{ - return host_32bits; -} -#endif // HAVE_DECL_HTOLE32 - -#if HAVE_DECL_BE32TOH == 0 -inline uint32_t be32toh(uint32_t big_endian_32bits) -{ - return bswap_32(big_endian_32bits); -} -#endif // HAVE_DECL_BE32TOH - -#if HAVE_DECL_LE32TOH == 0 -inline uint32_t le32toh(uint32_t little_endian_32bits) -{ - return little_endian_32bits; -} -#endif // HAVE_DECL_LE32TOH - -#if HAVE_DECL_HTOBE64 == 0 -inline uint64_t htobe64(uint64_t host_64bits) -{ - return bswap_64(host_64bits); -} -#endif // HAVE_DECL_HTOBE64 - -#if HAVE_DECL_HTOLE64 == 0 -inline uint64_t htole64(uint64_t host_64bits) -{ - return host_64bits; -} -#endif // HAVE_DECL_HTOLE64 - -#if HAVE_DECL_BE64TOH == 0 -inline uint64_t be64toh(uint64_t big_endian_64bits) -{ - return bswap_64(big_endian_64bits); -} -#endif // HAVE_DECL_BE64TOH - -#if HAVE_DECL_LE64TOH == 0 -inline uint64_t le64toh(uint64_t little_endian_64bits) -{ - return little_endian_64bits; -} -#endif // HAVE_DECL_LE64TOH - -#endif // WORDS_BIGENDIAN - -#endif // BITCOIN_COMPAT_ENDIAN_H diff --git a/src/crypto/bitcoin/sha256.cpp b/src/crypto/bitcoin/sha256.cpp deleted file mode 100644 index 5626695..0000000 --- a/src/crypto/bitcoin/sha256.cpp +++ /dev/null @@ -1,719 +0,0 @@ -// Copyright (c) 2014-2019 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "sha256.h" -#include "common.h" - -#include -#include - -//#include - -#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) -#if defined(USE_ASM) -namespace sha256_sse4 -{ - void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); -} -#endif -#endif - -namespace sha256d64_sse41 -{ - void Transform_4way(unsigned char* out, const unsigned char* in); -} - -namespace sha256d64_avx2 -{ - void Transform_8way(unsigned char* out, const unsigned char* in); -} - -namespace sha256d64_shani -{ - void Transform_2way(unsigned char* out, const unsigned char* in); -} - -namespace sha256_shani -{ - void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); -} - -// Internal implementation code. -namespace -{ - /// Internal SHA-256 implementation. - namespace sha256 - { - uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } - uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } - uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } - uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } - uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } - uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } - - /** One round of SHA-256. */ - void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k) - { - uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k; - uint32_t t2 = Sigma0(a) + Maj(a, b, c); - d += t1; - h = t1 + t2; - } - - /** Initialize SHA-256 state. */ - void inline Initialize(uint32_t* s) - { - s[0] = 0x6a09e667ul; - s[1] = 0xbb67ae85ul; - s[2] = 0x3c6ef372ul; - s[3] = 0xa54ff53aul; - s[4] = 0x510e527ful; - s[5] = 0x9b05688cul; - s[6] = 0x1f83d9abul; - s[7] = 0x5be0cd19ul; - } - - /** Perform a number of SHA-256 transformations, processing 64-byte chunks. */ - void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) - { - while (blocks--) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98 + (w0 = ReadBE32(chunk + 0))); - Round(h, a, b, c, d, e, f, g, 0x71374491 + (w1 = ReadBE32(chunk + 4))); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf + (w2 = ReadBE32(chunk + 8))); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5 + (w3 = ReadBE32(chunk + 12))); - Round(e, f, g, h, a, b, c, d, 0x3956c25b + (w4 = ReadBE32(chunk + 16))); - Round(d, e, f, g, h, a, b, c, 0x59f111f1 + (w5 = ReadBE32(chunk + 20))); - Round(c, d, e, f, g, h, a, b, 0x923f82a4 + (w6 = ReadBE32(chunk + 24))); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5 + (w7 = ReadBE32(chunk + 28))); - Round(a, b, c, d, e, f, g, h, 0xd807aa98 + (w8 = ReadBE32(chunk + 32))); - Round(h, a, b, c, d, e, f, g, 0x12835b01 + (w9 = ReadBE32(chunk + 36))); - Round(g, h, a, b, c, d, e, f, 0x243185be + (w10 = ReadBE32(chunk + 40))); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3 + (w11 = ReadBE32(chunk + 44))); - Round(e, f, g, h, a, b, c, d, 0x72be5d74 + (w12 = ReadBE32(chunk + 48))); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe + (w13 = ReadBE32(chunk + 52))); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7 + (w14 = ReadBE32(chunk + 56))); - Round(b, c, d, e, f, g, h, a, 0xc19bf174 + (w15 = ReadBE32(chunk + 60))); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1 + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0xefbe4786 + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6 + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x76f988da + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0x983e5152 + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0xa831c66d + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0xb00327c8 + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7 + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3 + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xd5a79147 + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0x06ca6351 + (w14 += sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0x14292967 + (w15 += sigma1(w13) + w8 + sigma0(w0))); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85 + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138 + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x53380d13 + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x650a7354 + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x766a0abb + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x92722c85 + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1 + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0xa81a664b + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70 + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3 + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0xd192e819 + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xd6990624 + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xf40e3585 + (w14 += sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0x106aa070 + (w15 += sigma1(w13) + w8 + sigma0(w0))); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116 + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x1e376c08 + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x2748774c + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5 + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3 + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3 + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0x748f82ee + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0x78a5636f + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0x84c87814 + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0x8cc70208 + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0x90befffa + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7 + (w14 + sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0xc67178f2 + (w15 + sigma1(w13) + w8 + sigma0(w0))); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; - chunk += 64; - } - } - - void TransformD64(unsigned char* out, const unsigned char* in) - { - // Transform 1 - uint32_t a = 0x6a09e667ul; - uint32_t b = 0xbb67ae85ul; - uint32_t c = 0x3c6ef372ul; - uint32_t d = 0xa54ff53aul; - uint32_t e = 0x510e527ful; - uint32_t f = 0x9b05688cul; - uint32_t g = 0x1f83d9abul; - uint32_t h = 0x5be0cd19ul; - - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + (w0 = ReadBE32(in + 0))); - Round(h, a, b, c, d, e, f, g, 0x71374491ul + (w1 = ReadBE32(in + 4))); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + (w2 = ReadBE32(in + 8))); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + (w3 = ReadBE32(in + 12))); - Round(e, f, g, h, a, b, c, d, 0x3956c25bul + (w4 = ReadBE32(in + 16))); - Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + (w5 = ReadBE32(in + 20))); - Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + (w6 = ReadBE32(in + 24))); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + (w7 = ReadBE32(in + 28))); - Round(a, b, c, d, e, f, g, h, 0xd807aa98ul + (w8 = ReadBE32(in + 32))); - Round(h, a, b, c, d, e, f, g, 0x12835b01ul + (w9 = ReadBE32(in + 36))); - Round(g, h, a, b, c, d, e, f, 0x243185beul + (w10 = ReadBE32(in + 40))); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul + (w11 = ReadBE32(in + 44))); - Round(e, f, g, h, a, b, c, d, 0x72be5d74ul + (w12 = ReadBE32(in + 48))); - Round(d, e, f, g, h, a, b, c, 0x80deb1feul + (w13 = ReadBE32(in + 52))); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul + (w14 = ReadBE32(in + 56))); - Round(b, c, d, e, f, g, h, a, 0xc19bf174ul + (w15 = ReadBE32(in + 60))); - Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); - Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); - Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0))); - - a += 0x6a09e667ul; - b += 0xbb67ae85ul; - c += 0x3c6ef372ul; - d += 0xa54ff53aul; - e += 0x510e527ful; - f += 0x9b05688cul; - g += 0x1f83d9abul; - h += 0x5be0cd19ul; - - uint32_t t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; - - // Transform 2 - Round(a, b, c, d, e, f, g, h, 0xc28a2f98ul); - Round(h, a, b, c, d, e, f, g, 0x71374491ul); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul); - Round(e, f, g, h, a, b, c, d, 0x3956c25bul); - Round(d, e, f, g, h, a, b, c, 0x59f111f1ul); - Round(c, d, e, f, g, h, a, b, 0x923f82a4ul); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul); - Round(a, b, c, d, e, f, g, h, 0xd807aa98ul); - Round(h, a, b, c, d, e, f, g, 0x12835b01ul); - Round(g, h, a, b, c, d, e, f, 0x243185beul); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul); - Round(e, f, g, h, a, b, c, d, 0x72be5d74ul); - Round(d, e, f, g, h, a, b, c, 0x80deb1feul); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul); - Round(b, c, d, e, f, g, h, a, 0xc19bf374ul); - Round(a, b, c, d, e, f, g, h, 0x649b69c1ul); - Round(h, a, b, c, d, e, f, g, 0xf0fe4786ul); - Round(g, h, a, b, c, d, e, f, 0x0fe1edc6ul); - Round(f, g, h, a, b, c, d, e, 0x240cf254ul); - Round(e, f, g, h, a, b, c, d, 0x4fe9346ful); - Round(d, e, f, g, h, a, b, c, 0x6cc984beul); - Round(c, d, e, f, g, h, a, b, 0x61b9411eul); - Round(b, c, d, e, f, g, h, a, 0x16f988faul); - Round(a, b, c, d, e, f, g, h, 0xf2c65152ul); - Round(h, a, b, c, d, e, f, g, 0xa88e5a6dul); - Round(g, h, a, b, c, d, e, f, 0xb019fc65ul); - Round(f, g, h, a, b, c, d, e, 0xb9d99ec7ul); - Round(e, f, g, h, a, b, c, d, 0x9a1231c3ul); - Round(d, e, f, g, h, a, b, c, 0xe70eeaa0ul); - Round(c, d, e, f, g, h, a, b, 0xfdb1232bul); - Round(b, c, d, e, f, g, h, a, 0xc7353eb0ul); - Round(a, b, c, d, e, f, g, h, 0x3069bad5ul); - Round(h, a, b, c, d, e, f, g, 0xcb976d5ful); - Round(g, h, a, b, c, d, e, f, 0x5a0f118ful); - Round(f, g, h, a, b, c, d, e, 0xdc1eeefdul); - Round(e, f, g, h, a, b, c, d, 0x0a35b689ul); - Round(d, e, f, g, h, a, b, c, 0xde0b7a04ul); - Round(c, d, e, f, g, h, a, b, 0x58f4ca9dul); - Round(b, c, d, e, f, g, h, a, 0xe15d5b16ul); - Round(a, b, c, d, e, f, g, h, 0x007f3e86ul); - Round(h, a, b, c, d, e, f, g, 0x37088980ul); - Round(g, h, a, b, c, d, e, f, 0xa507ea32ul); - Round(f, g, h, a, b, c, d, e, 0x6fab9537ul); - Round(e, f, g, h, a, b, c, d, 0x17406110ul); - Round(d, e, f, g, h, a, b, c, 0x0d8cd6f1ul); - Round(c, d, e, f, g, h, a, b, 0xcdaa3b6dul); - Round(b, c, d, e, f, g, h, a, 0xc0bbbe37ul); - Round(a, b, c, d, e, f, g, h, 0x83613bdaul); - Round(h, a, b, c, d, e, f, g, 0xdb48a363ul); - Round(g, h, a, b, c, d, e, f, 0x0b02e931ul); - Round(f, g, h, a, b, c, d, e, 0x6fd15ca7ul); - Round(e, f, g, h, a, b, c, d, 0x521afacaul); - Round(d, e, f, g, h, a, b, c, 0x31338431ul); - Round(c, d, e, f, g, h, a, b, 0x6ed41a95ul); - Round(b, c, d, e, f, g, h, a, 0x6d437890ul); - Round(a, b, c, d, e, f, g, h, 0xc39c91f2ul); - Round(h, a, b, c, d, e, f, g, 0x9eccabbdul); - Round(g, h, a, b, c, d, e, f, 0xb5c9a0e6ul); - Round(f, g, h, a, b, c, d, e, 0x532fb63cul); - Round(e, f, g, h, a, b, c, d, 0xd2c741c6ul); - Round(d, e, f, g, h, a, b, c, 0x07237ea3ul); - Round(c, d, e, f, g, h, a, b, 0xa4954b68ul); - Round(b, c, d, e, f, g, h, a, 0x4c191d76ul); - - w0 = t0 + a; - w1 = t1 + b; - w2 = t2 + c; - w3 = t3 + d; - w4 = t4 + e; - w5 = t5 + f; - w6 = t6 + g; - w7 = t7 + h; - - // Transform 3 - a = 0x6a09e667ul; - b = 0xbb67ae85ul; - c = 0x3c6ef372ul; - d = 0xa54ff53aul; - e = 0x510e527ful; - f = 0x9b05688cul; - g = 0x1f83d9abul; - h = 0x5be0cd19ul; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + w0); - Round(h, a, b, c, d, e, f, g, 0x71374491ul + w1); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + w2); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + w3); - Round(e, f, g, h, a, b, c, d, 0x3956c25bul + w4); - Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + w5); - Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + w6); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + w7); - Round(a, b, c, d, e, f, g, h, 0x5807aa98ul); - Round(h, a, b, c, d, e, f, g, 0x12835b01ul); - Round(g, h, a, b, c, d, e, f, 0x243185beul); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul); - Round(e, f, g, h, a, b, c, d, 0x72be5d74ul); - Round(d, e, f, g, h, a, b, c, 0x80deb1feul); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul); - Round(b, c, d, e, f, g, h, a, 0xc19bf274ul); - Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += 0xa00000ul + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + 0x100ul + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + 0x11002000ul)); - Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 = 0x80000000ul + sigma1(w6) + w1)); - Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 = sigma1(w7) + w2)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 = sigma1(w8) + w3)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 = sigma1(w9) + w4)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 = sigma1(w10) + w5)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 = sigma1(w11) + w6)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 = sigma1(w12) + w7 + 0x400022ul)); - Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 = 0x100ul + sigma1(w13) + w8 + sigma0(w0))); - Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); - Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); - Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); - Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3))); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6))); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7))); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); - Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9))); - Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10))); - Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); - Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); - Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13))); - Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14))); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15))); - Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0))); - - // Output - WriteBE32(out + 0, a + 0x6a09e667ul); - WriteBE32(out + 4, b + 0xbb67ae85ul); - WriteBE32(out + 8, c + 0x3c6ef372ul); - WriteBE32(out + 12, d + 0xa54ff53aul); - WriteBE32(out + 16, e + 0x510e527ful); - WriteBE32(out + 20, f + 0x9b05688cul); - WriteBE32(out + 24, g + 0x1f83d9abul); - WriteBE32(out + 28, h + 0x5be0cd19ul); - } - - } // namespace sha256 - - typedef void(*TransformType)(uint32_t*, const unsigned char*, size_t); - typedef void(*TransformD64Type)(unsigned char*, const unsigned char*); - - template - void TransformD64Wrapper(unsigned char* out, const unsigned char* in) - { - uint32_t s[8]; - static const unsigned char padding1[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 - }; - unsigned char buffer2[64] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 - }; - sha256::Initialize(s); - tr(s, in, 1); - tr(s, padding1, 1); - WriteBE32(buffer2 + 0, s[0]); - WriteBE32(buffer2 + 4, s[1]); - WriteBE32(buffer2 + 8, s[2]); - WriteBE32(buffer2 + 12, s[3]); - WriteBE32(buffer2 + 16, s[4]); - WriteBE32(buffer2 + 20, s[5]); - WriteBE32(buffer2 + 24, s[6]); - WriteBE32(buffer2 + 28, s[7]); - sha256::Initialize(s); - tr(s, buffer2, 1); - WriteBE32(out + 0, s[0]); - WriteBE32(out + 4, s[1]); - WriteBE32(out + 8, s[2]); - WriteBE32(out + 12, s[3]); - WriteBE32(out + 16, s[4]); - WriteBE32(out + 20, s[5]); - WriteBE32(out + 24, s[6]); - WriteBE32(out + 28, s[7]); - } - - TransformType Transform = sha256::Transform; - TransformD64Type TransformD64 = sha256::TransformD64; - TransformD64Type TransformD64_2way = nullptr; - TransformD64Type TransformD64_4way = nullptr; - TransformD64Type TransformD64_8way = nullptr; - - bool SelfTest() { - // Input state (equal to the initial SHA256 state) - static const uint32_t init[8] = { - 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul - }; - // Some random input data to test with - static const unsigned char data[641] = "-" // Intentionally not aligned - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " - "eiusmod tempor incididunt ut labore et dolore magna aliqua. Et m" - "olestie ac feugiat sed lectus vestibulum mattis ullamcorper. Mor" - "bi blandit cursus risus at ultrices mi tempus imperdiet nulla. N" - "unc congue nisi vita suscipit tellus mauris. Imperdiet proin fer" - "mentum leo vel orci. Massa tempor nec feugiat nisl pretium fusce" - " id velit. Telus in metus vulputate eu scelerisque felis. Mi tem" - "pus imperdiet nulla malesuada pellentesque. Tristique magna sit."; - // Expected output state for hashing the i*64 first input bytes above (excluding SHA256 padding). - static const uint32_t result[9][8] = { - { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, - { 0x91f8ec6bul, 0x4da10fe3ul, 0x1c9c292cul, 0x45e18185ul, 0x435cc111ul, 0x3ca26f09ul, 0xeb954caeul, 0x402a7069ul }, - { 0xcabea5acul, 0x374fb97cul, 0x182ad996ul, 0x7bd69cbful, 0x450ff900ul, 0xc1d2be8aul, 0x6a41d505ul, 0xe6212dc3ul }, - { 0xbcff09d6ul, 0x3e76f36eul, 0x3ecb2501ul, 0x78866e97ul, 0xe1c1e2fdul, 0x32f4eafful, 0x8aa6c4e5ul, 0xdfc024bcul }, - { 0xa08c5d94ul, 0x0a862f93ul, 0x6b7f2f40ul, 0x8f9fae76ul, 0x6d40439ful, 0x79dcee0cul, 0x3e39ff3aul, 0xdc3bdbb1ul }, - { 0x216a0895ul, 0x9f1a3662ul, 0xe99946f9ul, 0x87ba4364ul, 0x0fb5db2cul, 0x12bed3d3ul, 0x6689c0c7ul, 0x292f1b04ul }, - { 0xca3067f8ul, 0xbc8c2656ul, 0x37cb7e0dul, 0x9b6b8b0ful, 0x46dc380bul, 0xf1287f57ul, 0xc42e4b23ul, 0x3fefe94dul }, - { 0x3e4c4039ul, 0xbb6fca8cul, 0x6f27d2f7ul, 0x301e44a4ul, 0x8352ba14ul, 0x5769ce37ul, 0x48a1155ful, 0xc0e1c4c6ul }, - { 0xfe2fa9ddul, 0x69d0862bul, 0x1ae0db23ul, 0x471f9244ul, 0xf55c0145ul, 0xc30f9c3bul, 0x40a84ea0ul, 0x5b8a266cul }, - }; - // Expected output for each of the individual 8 64-byte messages under full double SHA256 (including padding). - static const unsigned char result_d64[256] = { - 0x09, 0x3a, 0xc4, 0xd0, 0x0f, 0xf7, 0x57, 0xe1, 0x72, 0x85, 0x79, 0x42, 0xfe, 0xe7, 0xe0, 0xa0, - 0xfc, 0x52, 0xd7, 0xdb, 0x07, 0x63, 0x45, 0xfb, 0x53, 0x14, 0x7d, 0x17, 0x22, 0x86, 0xf0, 0x52, - 0x48, 0xb6, 0x11, 0x9e, 0x6e, 0x48, 0x81, 0x6d, 0xcc, 0x57, 0x1f, 0xb2, 0x97, 0xa8, 0xd5, 0x25, - 0x9b, 0x82, 0xaa, 0x89, 0xe2, 0xfd, 0x2d, 0x56, 0xe8, 0x28, 0x83, 0x0b, 0xe2, 0xfa, 0x53, 0xb7, - 0xd6, 0x6b, 0x07, 0x85, 0x83, 0xb0, 0x10, 0xa2, 0xf5, 0x51, 0x3c, 0xf9, 0x60, 0x03, 0xab, 0x45, - 0x6c, 0x15, 0x6e, 0xef, 0xb5, 0xac, 0x3e, 0x6c, 0xdf, 0xb4, 0x92, 0x22, 0x2d, 0xce, 0xbf, 0x3e, - 0xe9, 0xe5, 0xf6, 0x29, 0x0e, 0x01, 0x4f, 0xd2, 0xd4, 0x45, 0x65, 0xb3, 0xbb, 0xf2, 0x4c, 0x16, - 0x37, 0x50, 0x3c, 0x6e, 0x49, 0x8c, 0x5a, 0x89, 0x2b, 0x1b, 0xab, 0xc4, 0x37, 0xd1, 0x46, 0xe9, - 0x3d, 0x0e, 0x85, 0xa2, 0x50, 0x73, 0xa1, 0x5e, 0x54, 0x37, 0xd7, 0x94, 0x17, 0x56, 0xc2, 0xd8, - 0xe5, 0x9f, 0xed, 0x4e, 0xae, 0x15, 0x42, 0x06, 0x0d, 0x74, 0x74, 0x5e, 0x24, 0x30, 0xce, 0xd1, - 0x9e, 0x50, 0xa3, 0x9a, 0xb8, 0xf0, 0x4a, 0x57, 0x69, 0x78, 0x67, 0x12, 0x84, 0x58, 0xbe, 0xc7, - 0x36, 0xaa, 0xee, 0x7c, 0x64, 0xa3, 0x76, 0xec, 0xff, 0x55, 0x41, 0x00, 0x2a, 0x44, 0x68, 0x4d, - 0xb6, 0x53, 0x9e, 0x1c, 0x95, 0xb7, 0xca, 0xdc, 0x7f, 0x7d, 0x74, 0x27, 0x5c, 0x8e, 0xa6, 0x84, - 0xb5, 0xac, 0x87, 0xa9, 0xf3, 0xff, 0x75, 0xf2, 0x34, 0xcd, 0x1a, 0x3b, 0x82, 0x2c, 0x2b, 0x4e, - 0x6a, 0x46, 0x30, 0xa6, 0x89, 0x86, 0x23, 0xac, 0xf8, 0xa5, 0x15, 0xe9, 0x0a, 0xaa, 0x1e, 0x9a, - 0xd7, 0x93, 0x6b, 0x28, 0xe4, 0x3b, 0xfd, 0x59, 0xc6, 0xed, 0x7c, 0x5f, 0xa5, 0x41, 0xcb, 0x51 - }; - - - // Test Transform() for 0 through 8 transformations. - for (size_t i = 0; i <= 8; ++i) { - uint32_t state[8]; - std::copy(init, init + 8, state); - Transform(state, data + 1, i); - if (!std::equal(state, state + 8, result[i])) return false; - } - - // Test TransformD64 - unsigned char out[32]; - TransformD64(out, data + 1); - if (!std::equal(out, out + 32, result_d64)) return false; - - // Test TransformD64_2way, if available. - if (TransformD64_2way) { - unsigned char out[64]; - TransformD64_2way(out, data + 1); - if (!std::equal(out, out + 64, result_d64)) return false; - } - - // Test TransformD64_4way, if available. - if (TransformD64_4way) { - unsigned char out[128]; - TransformD64_4way(out, data + 1); - if (!std::equal(out, out + 128, result_d64)) return false; - } - - // Test TransformD64_8way, if available. - if (TransformD64_8way) { - unsigned char out[256]; - TransformD64_8way(out, data + 1); - if (!std::equal(out, out + 256, result_d64)) return false; - } - - return true; - } - -#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) - /** Check whether the OS has enabled AVX registers. */ - bool AVXEnabled() - { - uint32_t a, d; - __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0)); - return (a & 6) == 6; - } -#endif -} // namespace - - -std::string SHA256AutoDetect() -{ - std::string ret = "standard"; -#if defined(USE_ASM) && defined(HAVE_GETCPUID) - bool have_sse4 = false; - bool have_xsave = false; - bool have_avx = false; - bool have_avx2 = false; - bool have_shani = false; - bool enabled_avx = false; - - (void)AVXEnabled; - (void)have_sse4; - (void)have_avx; - (void)have_xsave; - (void)have_avx2; - (void)have_shani; - (void)enabled_avx; - - uint32_t eax, ebx, ecx, edx; - GetCPUID(1, 0, eax, ebx, ecx, edx); - have_sse4 = (ecx >> 19) & 1; - have_xsave = (ecx >> 27) & 1; - have_avx = (ecx >> 28) & 1; - if (have_xsave && have_avx) { - enabled_avx = AVXEnabled(); - } - if (have_sse4) { - GetCPUID(7, 0, eax, ebx, ecx, edx); - have_avx2 = (ebx >> 5) & 1; - have_shani = (ebx >> 29) & 1; - } - -#if defined(ENABLE_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) - if (have_shani) { - Transform = sha256_shani::Transform; - TransformD64 = TransformD64Wrapper; - TransformD64_2way = sha256d64_shani::Transform_2way; - ret = "shani(1way,2way)"; - have_sse4 = false; // Disable SSE4/AVX2; - have_avx2 = false; - } -#endif - - if (have_sse4) { -#if defined(__x86_64__) || defined(__amd64__) - Transform = sha256_sse4::Transform; - TransformD64 = TransformD64Wrapper; - ret = "sse4(1way)"; -#endif -#if defined(ENABLE_SSE41) && !defined(BUILD_BITCOIN_INTERNAL) - TransformD64_4way = sha256d64_sse41::Transform_4way; - ret += ",sse41(4way)"; -#endif - } - -#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL) - if (have_avx2 && have_avx && enabled_avx) { - TransformD64_8way = sha256d64_avx2::Transform_8way; - ret += ",avx2(8way)"; - } -#endif -#endif - - assert(SelfTest()); - return ret; -} - -////// SHA-256 - -CSHA256::CSHA256() : bytes(0) -{ - sha256::Initialize(s); -} - -CSHA256& CSHA256::Write(const unsigned char* data, size_t len) -{ - const unsigned char* end = data + len; - size_t bufsize = bytes % 64; - if (bufsize && bufsize + len >= 64) { - // Fill the buffer, and process it. - memcpy(buf + bufsize, data, 64 - bufsize); - bytes += 64 - bufsize; - data += 64 - bufsize; - Transform(s, buf, 1); - bufsize = 0; - } - if (end - data >= 64) { - size_t blocks = (end - data) / 64; - Transform(s, data, blocks); - data += 64 * blocks; - bytes += 64 * blocks; - } - if (end > data) { - // Fill the buffer with what remains. - memcpy(buf + bufsize, data, end - data); - bytes += end - data; - } - return *this; -} - -void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) -{ - static const unsigned char pad[64] = { 0x80 }; - unsigned char sizedesc[8]; - WriteBE64(sizedesc, bytes << 3); - Write(pad, 1 + ((119 - (bytes % 64)) % 64)); - Write(sizedesc, 8); - WriteBE32(hash, s[0]); - WriteBE32(hash + 4, s[1]); - WriteBE32(hash + 8, s[2]); - WriteBE32(hash + 12, s[3]); - WriteBE32(hash + 16, s[4]); - WriteBE32(hash + 20, s[5]); - WriteBE32(hash + 24, s[6]); - WriteBE32(hash + 28, s[7]); -} - -CSHA256& CSHA256::Reset() -{ - bytes = 0; - sha256::Initialize(s); - return *this; -} - -void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks) -{ - if (TransformD64_8way) { - while (blocks >= 8) { - TransformD64_8way(out, in); - out += 256; - in += 512; - blocks -= 8; - } - } - if (TransformD64_4way) { - while (blocks >= 4) { - TransformD64_4way(out, in); - out += 128; - in += 256; - blocks -= 4; - } - } - if (TransformD64_2way) { - while (blocks >= 2) { - TransformD64_2way(out, in); - out += 64; - in += 128; - blocks -= 2; - } - } - while (blocks) { - TransformD64(out, in); - out += 32; - in += 64; - --blocks; - } -} \ No newline at end of file diff --git a/src/crypto/bitcoin/sha256.h b/src/crypto/bitcoin/sha256.h deleted file mode 100644 index 80d3625..0000000 --- a/src/crypto/bitcoin/sha256.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2014-2018 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_CRYPTO_SHA256_H -#define BITCOIN_CRYPTO_SHA256_H - -#include -#include -#include - -/** A hasher class for SHA-256. */ -class CSHA256 -{ -private: - uint32_t s[8]; - unsigned char buf[64]; - uint64_t bytes; - -public: - static const size_t OUTPUT_SIZE = 32; - - CSHA256(); - CSHA256& Write(const unsigned char* data, size_t len); - void Finalize(unsigned char hash[OUTPUT_SIZE]); - CSHA256& Reset(); -}; - -/** Autodetect the best available SHA256 implementation. -* Returns the name of the implementation. -*/ -std::string SHA256AutoDetect(); - -/** Compute multiple double-SHA256's of 64-byte blobs. -* output: pointer to a blocks*32 byte output buffer -* input: pointer to a blocks*64 byte input buffer -* blocks: the number of hashes to compute. -*/ -void SHA256D64(unsigned char* output, const unsigned char* input, size_t blocks); - -#endif // BITCOIN_CRYPTO_SHA256_H \ No newline at end of file diff --git a/src/crypto/bitcoin/sha256_helper.h b/src/crypto/bitcoin/sha256_helper.h deleted file mode 100644 index f376913..0000000 --- a/src/crypto/bitcoin/sha256_helper.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2020 The Zano developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "crypto/hash.h" -#include "sha256.h" - - -namespace crypto { - - inline void sha256_hash(const void *data, std::size_t length, hash &h) - { - CSHA256 sh; - sh.Write((const unsigned char*)data, length); - sh.Finalize((unsigned char* )&h); - } - - inline hash sha256_hash(const void *data, std::size_t length) - { - hash h; - sha256_hash(data, length, h); - return h; - } - -} diff --git a/src/crypto/blake2-impl.h b/src/crypto/blake2-impl.h deleted file mode 100644 index c1df82e..0000000 --- a/src/crypto/blake2-impl.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ -#ifndef BLAKE2_IMPL_H -#define BLAKE2_IMPL_H - -#include -#include - -#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) - #if defined(_MSC_VER) - #define BLAKE2_INLINE __inline - #elif defined(__GNUC__) - #define BLAKE2_INLINE __inline__ - #else - #define BLAKE2_INLINE - #endif -#else - #define BLAKE2_INLINE inline -#endif - -static BLAKE2_INLINE uint32_t load32( const void *src ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; -#else - const uint8_t *p = ( const uint8_t * )src; - return (( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8) | - (( uint32_t )( p[2] ) << 16) | - (( uint32_t )( p[3] ) << 24) ; -#endif -} - -static BLAKE2_INLINE uint64_t load64( const void *src ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; -#else - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) | - (( uint64_t )( p[6] ) << 48) | - (( uint64_t )( p[7] ) << 56) ; -#endif -} - -static BLAKE2_INLINE uint16_t load16( const void *src ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - uint16_t w; - memcpy(&w, src, sizeof w); - return w; -#else - const uint8_t *p = ( const uint8_t * )src; - return ( uint16_t )((( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8)); -#endif -} - -static BLAKE2_INLINE void store16( void *dst, uint16_t w ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); -#else - uint8_t *p = ( uint8_t * )dst; - *p++ = ( uint8_t )w; w >>= 8; - *p++ = ( uint8_t )w; -#endif -} - -static BLAKE2_INLINE void store32( void *dst, uint32_t w ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); -#else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); -#endif -} - -static BLAKE2_INLINE void store64( void *dst, uint64_t w ) -{ -#if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); -#else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); - p[6] = (uint8_t)(w >> 48); - p[7] = (uint8_t)(w >> 56); -#endif -} - -static BLAKE2_INLINE uint64_t load48( const void *src ) -{ - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) ; -} - -static BLAKE2_INLINE void store48( void *dst, uint64_t w ) -{ - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); -} - -static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 32 - c ) ); -} - -static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 64 - c ) ); -} - -/* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) -{ - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); -} - -#endif diff --git a/src/crypto/blake2.h b/src/crypto/blake2.h deleted file mode 100644 index 4949c65..0000000 --- a/src/crypto/blake2.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ -#ifndef BLAKE2_H -#define BLAKE2_H - -#include -#include - -#if defined(_MSC_VER) -#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) -#else -#define BLAKE2_PACKED(x) x __attribute__((packed)) -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - - enum blake2s_constant - { - BLAKE2S_BLOCKBYTES = 64, - BLAKE2S_OUTBYTES = 32, - BLAKE2S_KEYBYTES = 32, - BLAKE2S_SALTBYTES = 8, - BLAKE2S_PERSONALBYTES = 8 - }; - - enum blake2b_constant - { - BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, - BLAKE2B_PERSONALBYTES = 16 - }; - - typedef struct blake2s_state__ - { - uint32_t h[8]; - uint32_t t[2]; - uint32_t f[2]; - uint8_t buf[BLAKE2S_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; - } blake2s_state; - - typedef struct blake2b_state__ - { - uint64_t h[8]; - uint64_t t[2]; - uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; - } blake2b_state; - - typedef struct blake2sp_state__ - { - blake2s_state S[8][1]; - blake2s_state R[1]; - uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; - size_t buflen; - size_t outlen; - } blake2sp_state; - - typedef struct blake2bp_state__ - { - blake2b_state S[4][1]; - blake2b_state R[1]; - uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - } blake2bp_state; - - - BLAKE2_PACKED(struct blake2s_param__ - { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint16_t xof_length; /* 14 */ - uint8_t node_depth; /* 15 */ - uint8_t inner_length; /* 16 */ - /* uint8_t reserved[0]; */ - uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ - uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ - }); - - typedef struct blake2s_param__ blake2s_param; - - BLAKE2_PACKED(struct blake2b_param__ - { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ - }); - - typedef struct blake2b_param__ blake2b_param; - - typedef struct blake2xs_state__ - { - blake2s_state S[1]; - blake2s_param P[1]; - } blake2xs_state; - - typedef struct blake2xb_state__ - { - blake2b_state S[1]; - blake2b_param P[1]; - } blake2xb_state; - - - /* Padded structs result in a compile-time error */ - - enum { - BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), - BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) - }; -// static_assert(sizeof(blake2s_param) == BLAKE2S_OUTBYTES, "Wrong size of blake2s_param"); -// static_assert(sizeof(blake2b_param) == BLAKE2B_OUTBYTES, "Wrong size of blake2b_param"); - - - /* Streaming API */ - int blake2s_init( blake2s_state *S, size_t outlen ); - int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); - int blake2s_update( blake2s_state *S, const void *in, size_t inlen ); - int blake2s_final( blake2s_state *S, void *out, size_t outlen ); - - int blake2b_init( blake2b_state *S, size_t outlen ); - int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); - int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); - int blake2b_final( blake2b_state *S, void *out, size_t outlen ); - - int blake2sp_init( blake2sp_state *S, size_t outlen ); - int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen ); - int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ); - - int blake2bp_init( blake2bp_state *S, size_t outlen ); - int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen ); - int blake2bp_final( blake2bp_state *S, void *out, size_t outlen ); - - /* Variable output length API */ - int blake2xs_init( blake2xs_state *S, const size_t outlen ); - int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ); - int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ); - int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); - - int blake2xb_init( blake2xb_state *S, const size_t outlen ); - int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen ); - int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ); - int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); - - /* Simple API */ - int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - /* This is simply an alias for blake2b */ - int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/src/crypto/blake2b-ref.c b/src/crypto/blake2b-ref.c deleted file mode 100644 index cd38b1b..0000000 --- a/src/crypto/blake2b-ref.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ - -#include -#include -#include - -#include "blake2.h" -#include "blake2-impl.h" - -static const uint64_t blake2b_IV[8] = -{ - 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, - 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, - 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL -}; - -static const uint8_t blake2b_sigma[12][16] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } -}; - - -static void blake2b_set_lastnode( blake2b_state *S ) -{ - S->f[1] = (uint64_t)-1; -} - -/* Some helper functions, not necessarily useful */ -static int blake2b_is_lastblock( const blake2b_state *S ) -{ - return S->f[0] != 0; -} - -static void blake2b_set_lastblock( blake2b_state *S ) -{ - if( S->last_node ) blake2b_set_lastnode( S ); - - S->f[0] = (uint64_t)-1; -} - -static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) -{ - S->t[0] += inc; - S->t[1] += ( S->t[0] < inc ); -} - -static void blake2b_init0( blake2b_state *S ) -{ - size_t i; - memset( S, 0, sizeof( blake2b_state ) ); - - for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; -} - -/* init xors IV with input parameter block */ -int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) -{ - const uint8_t *p = ( const uint8_t * )( P ); - size_t i; - - blake2b_init0( S ); - - /* IV XOR ParamBlock */ - for( i = 0; i < 8; ++i ) - S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); - - S->outlen = P->digest_length; - return 0; -} - - - -int blake2b_init( blake2b_state *S, size_t outlen ) -{ - blake2b_param P[1]; - - if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; - - P->digest_length = (uint8_t)outlen; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32( &P->leaf_length, 0 ); - store32( &P->node_offset, 0 ); - store32( &P->xof_length, 0 ); - P->node_depth = 0; - P->inner_length = 0; - memset( P->reserved, 0, sizeof( P->reserved ) ); - memset( P->salt, 0, sizeof( P->salt ) ); - memset( P->personal, 0, sizeof( P->personal ) ); - return blake2b_init_param( S, P ); -} - - -int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) -{ - blake2b_param P[1]; - - if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; - - if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; - - P->digest_length = (uint8_t)outlen; - P->key_length = (uint8_t)keylen; - P->fanout = 1; - P->depth = 1; - store32( &P->leaf_length, 0 ); - store32( &P->node_offset, 0 ); - store32( &P->xof_length, 0 ); - P->node_depth = 0; - P->inner_length = 0; - memset( P->reserved, 0, sizeof( P->reserved ) ); - memset( P->salt, 0, sizeof( P->salt ) ); - memset( P->personal, 0, sizeof( P->personal ) ); - - if( blake2b_init_param( S, P ) < 0 ) return -1; - - { - uint8_t block[BLAKE2B_BLOCKBYTES]; - memset( block, 0, BLAKE2B_BLOCKBYTES ); - memcpy( block, key, keylen ); - blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); - secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ - } - return 0; -} - -#define G(r,i,a,b,c,d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2*i+0]]; \ - d = rotr64(d ^ a, 32); \ - c = c + d; \ - b = rotr64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2*i+1]]; \ - d = rotr64(d ^ a, 16); \ - c = c + d; \ - b = rotr64(b ^ c, 63); \ - } while(0) - -#define ROUND(r) \ - do { \ - G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ - G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ - G(r,2,v[ 2],v[ 6],v[10],v[14]); \ - G(r,3,v[ 3],v[ 7],v[11],v[15]); \ - G(r,4,v[ 0],v[ 5],v[10],v[15]); \ - G(r,5,v[ 1],v[ 6],v[11],v[12]); \ - G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ - G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ - } while(0) - -static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) -{ - uint64_t m[16]; - uint64_t v[16]; - size_t i; - - for( i = 0; i < 16; ++i ) { - m[i] = load64( block + i * sizeof( m[i] ) ); - } - - for( i = 0; i < 8; ++i ) { - v[i] = S->h[i]; - } - - v[ 8] = blake2b_IV[0]; - v[ 9] = blake2b_IV[1]; - v[10] = blake2b_IV[2]; - v[11] = blake2b_IV[3]; - v[12] = blake2b_IV[4] ^ S->t[0]; - v[13] = blake2b_IV[5] ^ S->t[1]; - v[14] = blake2b_IV[6] ^ S->f[0]; - v[15] = blake2b_IV[7] ^ S->f[1]; - - ROUND( 0 ); - ROUND( 1 ); - ROUND( 2 ); - ROUND( 3 ); - ROUND( 4 ); - ROUND( 5 ); - ROUND( 6 ); - ROUND( 7 ); - ROUND( 8 ); - ROUND( 9 ); - ROUND( 10 ); - ROUND( 11 ); - - for( i = 0; i < 8; ++i ) { - S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; - } -} - -#undef G -#undef ROUND - -int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) -{ - const unsigned char * in = (const unsigned char *)pin; - if( inlen > 0 ) - { - size_t left = S->buflen; - size_t fill = BLAKE2B_BLOCKBYTES - left; - if( inlen > fill ) - { - S->buflen = 0; - memcpy( S->buf + left, in, fill ); /* Fill buffer */ - blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); - blake2b_compress( S, S->buf ); /* Compress */ - in += fill; inlen -= fill; - while(inlen > BLAKE2B_BLOCKBYTES) { - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress( S, in ); - in += BLAKE2B_BLOCKBYTES; - inlen -= BLAKE2B_BLOCKBYTES; - } - } - memcpy( S->buf + S->buflen, in, inlen ); - S->buflen += inlen; - } - return 0; -} - -int blake2b_final( blake2b_state *S, void *out, size_t outlen ) -{ - uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; - size_t i; - - if( out == NULL || outlen < S->outlen ) - return -1; - - if( blake2b_is_lastblock( S ) ) - return -1; - - blake2b_increment_counter( S, S->buflen ); - blake2b_set_lastblock( S ); - memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ - blake2b_compress( S, S->buf ); - - for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ - store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); - - memcpy( out, buffer, S->outlen ); - secure_zero_memory(buffer, sizeof(buffer)); - return 0; -} - -/* inlen, at least, should be uint64_t. Others can be size_t. */ -int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) -{ - blake2b_state S[1]; - - /* Verify parameters */ - if ( NULL == in && inlen > 0 ) return -1; - - if ( NULL == out ) return -1; - - if( NULL == key && keylen > 0 ) return -1; - - if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; - - if( keylen > BLAKE2B_KEYBYTES ) return -1; - - if( keylen > 0 ) - { - if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; - } - else - { - if( blake2b_init( S, outlen ) < 0 ) return -1; - } - - blake2b_update( S, ( const uint8_t * )in, inlen ); - blake2b_final( S, out, outlen ); - return 0; -} - -int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { - return blake2b(out, outlen, in, inlen, key, keylen); -} - -#if defined(SUPERCOP) -int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) -{ - return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 ); -} -#endif - -#if defined(BLAKE2B_SELFTEST) -#include -#include "blake2-kat.h" -int main( void ) -{ - uint8_t key[BLAKE2B_KEYBYTES]; - uint8_t buf[BLAKE2_KAT_LENGTH]; - size_t i, step; - - for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) - key[i] = ( uint8_t )i; - - for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) - buf[i] = ( uint8_t )i; - - /* Test simple API */ - for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) - { - uint8_t hash[BLAKE2B_OUTBYTES]; - blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES ); - - if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) - { - goto fail; - } - } - - /* Test streaming API */ - for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { - for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { - uint8_t hash[BLAKE2B_OUTBYTES]; - blake2b_state S; - uint8_t * p = buf; - size_t mlen = i; - int err = 0; - - if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) { - goto fail; - } - - while (mlen >= step) { - if ( (err = blake2b_update(&S, p, step)) < 0 ) { - goto fail; - } - mlen -= step; - p += step; - } - if ( (err = blake2b_update(&S, p, mlen)) < 0) { - goto fail; - } - if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { - goto fail; - } - - if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { - goto fail; - } - } - } - - puts( "ok" ); - return 0; -fail: - puts("error"); - return -1; -} -#endif diff --git a/src/crypto/chacha8.c b/src/crypto/chacha8.c deleted file mode 100644 index df135af..0000000 --- a/src/crypto/chacha8.c +++ /dev/null @@ -1,170 +0,0 @@ -/* -chacha-merged.c version 20080118 -D. J. Bernstein -Public domain. -*/ - -#include -#include -#include - -#include "chacha8.h" -#include "common/int-util.h" -#include "warnings.h" - -/* - * The following macros are used to obtain exact-width results. - */ -#define U8V(v) ((uint8_t)(v) & UINT8_C(0xFF)) -#define U32V(v) ((uint32_t)(v) & UINT32_C(0xFFFFFFFF)) - -/* - * The following macros load words from an array of bytes with - * different types of endianness, and vice versa. - */ -#define U8TO32_LITTLE(p) SWAP32LE(((uint32_t*)(p))[0]) -#define U32TO8_LITTLE(p, v) (((uint32_t*)(p))[0] = SWAP32LE(v)) - -#define ROTATE(v,c) (rol32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -#define QUARTERROUND(a,b,c,d) \ - a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ - a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ - c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); - -static const char sigma[] = "expand 32-byte k"; - -DISABLE_GCC_AND_CLANG_WARNING(strict-aliasing) - -void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) { - uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; - char* ctarget = 0; - char tmp[64]; - int i; - - if (!length) return; - - j0 = U8TO32_LITTLE(sigma + 0); - j1 = U8TO32_LITTLE(sigma + 4); - j2 = U8TO32_LITTLE(sigma + 8); - j3 = U8TO32_LITTLE(sigma + 12); - j4 = U8TO32_LITTLE(key + 0); - j5 = U8TO32_LITTLE(key + 4); - j6 = U8TO32_LITTLE(key + 8); - j7 = U8TO32_LITTLE(key + 12); - j8 = U8TO32_LITTLE(key + 16); - j9 = U8TO32_LITTLE(key + 20); - j10 = U8TO32_LITTLE(key + 24); - j11 = U8TO32_LITTLE(key + 28); - j12 = 0; - j13 = 0; - j14 = U8TO32_LITTLE(iv + 0); - j15 = U8TO32_LITTLE(iv + 4); - - for (;;) { - if (length < 64) { - memcpy(tmp, data, length); - data = tmp; - ctarget = cipher; - cipher = tmp; - } - x0 = j0; - x1 = j1; - x2 = j2; - x3 = j3; - x4 = j4; - x5 = j5; - x6 = j6; - x7 = j7; - x8 = j8; - x9 = j9; - x10 = j10; - x11 = j11; - x12 = j12; - x13 = j13; - x14 = j14; - x15 = j15; - for (i = 8;i > 0;i -= 2) { - QUARTERROUND( x0, x4, x8,x12) - QUARTERROUND( x1, x5, x9,x13) - QUARTERROUND( x2, x6,x10,x14) - QUARTERROUND( x3, x7,x11,x15) - QUARTERROUND( x0, x5,x10,x15) - QUARTERROUND( x1, x6,x11,x12) - QUARTERROUND( x2, x7, x8,x13) - QUARTERROUND( x3, x4, x9,x14) - } - x0 = PLUS( x0, j0); - x1 = PLUS( x1, j1); - x2 = PLUS( x2, j2); - x3 = PLUS( x3, j3); - x4 = PLUS( x4, j4); - x5 = PLUS( x5, j5); - x6 = PLUS( x6, j6); - x7 = PLUS( x7, j7); - x8 = PLUS( x8, j8); - x9 = PLUS( x9, j9); - x10 = PLUS(x10,j10); - x11 = PLUS(x11,j11); - x12 = PLUS(x12,j12); - x13 = PLUS(x13,j13); - x14 = PLUS(x14,j14); - x15 = PLUS(x15,j15); - - x0 = XOR( x0,U8TO32_LITTLE((uint8_t*)data + 0)); - x1 = XOR( x1,U8TO32_LITTLE((uint8_t*)data + 4)); - x2 = XOR( x2,U8TO32_LITTLE((uint8_t*)data + 8)); - x3 = XOR( x3,U8TO32_LITTLE((uint8_t*)data + 12)); - x4 = XOR( x4,U8TO32_LITTLE((uint8_t*)data + 16)); - x5 = XOR( x5,U8TO32_LITTLE((uint8_t*)data + 20)); - x6 = XOR( x6,U8TO32_LITTLE((uint8_t*)data + 24)); - x7 = XOR( x7,U8TO32_LITTLE((uint8_t*)data + 28)); - x8 = XOR( x8,U8TO32_LITTLE((uint8_t*)data + 32)); - x9 = XOR( x9,U8TO32_LITTLE((uint8_t*)data + 36)); - x10 = XOR(x10,U8TO32_LITTLE((uint8_t*)data + 40)); - x11 = XOR(x11,U8TO32_LITTLE((uint8_t*)data + 44)); - x12 = XOR(x12,U8TO32_LITTLE((uint8_t*)data + 48)); - x13 = XOR(x13,U8TO32_LITTLE((uint8_t*)data + 52)); - x14 = XOR(x14,U8TO32_LITTLE((uint8_t*)data + 56)); - x15 = XOR(x15,U8TO32_LITTLE((uint8_t*)data + 60)); - - j12 = PLUSONE(j12); - if (!j12) - { - j13 = PLUSONE(j13); - /* stopping at 2^70 bytes per iv is user's responsibility */ - } - - U32TO8_LITTLE(cipher + 0,x0); - U32TO8_LITTLE(cipher + 4,x1); - U32TO8_LITTLE(cipher + 8,x2); - U32TO8_LITTLE(cipher + 12,x3); - U32TO8_LITTLE(cipher + 16,x4); - U32TO8_LITTLE(cipher + 20,x5); - U32TO8_LITTLE(cipher + 24,x6); - U32TO8_LITTLE(cipher + 28,x7); - U32TO8_LITTLE(cipher + 32,x8); - U32TO8_LITTLE(cipher + 36,x9); - U32TO8_LITTLE(cipher + 40,x10); - U32TO8_LITTLE(cipher + 44,x11); - U32TO8_LITTLE(cipher + 48,x12); - U32TO8_LITTLE(cipher + 52,x13); - U32TO8_LITTLE(cipher + 56,x14); - U32TO8_LITTLE(cipher + 60,x15); - - if (length <= 64) { - if (length < 64) { - memcpy(ctarget, cipher, length); - } - return; - } - length -= 64; - cipher += 64; - data = (uint8_t*)data + 64; - } -} diff --git a/src/crypto/chacha8.h b/src/crypto/chacha8.h deleted file mode 100644 index cebc6ab..0000000 --- a/src/crypto/chacha8.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -#define CHACHA8_KEY_SIZE 32 -#define CHACHA8_IV_SIZE 8 - -#if defined(__cplusplus) -#include - -#include "hash.h" - -namespace crypto { - extern "C" { -#endif - void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher); -#if defined(__cplusplus) - } - -#pragma pack(push, 1) - struct chacha8_key { - uint8_t data[CHACHA8_KEY_SIZE]; - - ~chacha8_key() - { - memset(data, 0, sizeof(data)); - } - }; - - // MS VC 2012 doesn't interpret `class chacha8_iv` as POD in spite of [9.0.10], so it is a struct - struct chacha8_iv { - uint8_t data[CHACHA8_IV_SIZE]; - }; -#pragma pack(pop) - - static_assert(sizeof(chacha8_key) == CHACHA8_KEY_SIZE && sizeof(chacha8_iv) == CHACHA8_IV_SIZE, "Invalid structure size"); - - inline void chacha8(const void* data, std::size_t length, const chacha8_key& key, const chacha8_iv& iv, char* cipher) { - chacha8(data, length, reinterpret_cast(&key), reinterpret_cast(&iv), cipher); - } - - inline void generate_chacha8_key(const void* pass, size_t sz, chacha8_key& key) { - static_assert(sizeof(chacha8_key) <= sizeof(hash), "Size of hash must be at least that of chacha8_key"); - char pwd_hash[HASH_SIZE]; - //TODO: change wallet encryption algo - crypto::cn_fast_hash(pass, sz, pwd_hash); - memcpy(&key.data, pwd_hash, sizeof(key.data)); - memset(pwd_hash, 0, sizeof(pwd_hash)); - } - - inline void generate_chacha8_key(std::string password, chacha8_key& key) - { - generate_chacha8_key(password.data(), password.size(), key); - } - - - inline bool chacha_crypt(const void* src_buff, size_t sz, void* target_buff, const void* key_buff, size_t key_buff_size) - { - crypto::chacha8_key key; - crypto::chacha8_iv iv; - memset(&iv, 0, sizeof(iv)); - crypto::generate_chacha8_key(key_buff, key_buff_size, key); - crypto::chacha8(src_buff, sz, key, iv, (char*)target_buff); - return true; - } - - inline bool chacha_crypt(std::string& buff, const std::string& pass) - { - - std::string decrypted_buff; - decrypted_buff.resize(buff.size()); - chacha_crypt(buff.data(), buff.size(), (void*)decrypted_buff.data(), pass.data(), pass.size()); - buff = decrypted_buff; - return true; - } - - template - inline bool chacha_crypt(pod_to_encrypt& crypt, const pod_pass& pass) - { - std::string buff; - buff.resize(sizeof(pod_to_encrypt)); - chacha_crypt(&crypt, sizeof(crypt), (void*)buff.data(), &pass, sizeof(pass)); - memcpy(&crypt, buff.data(), sizeof(crypt)); - return true; - } - - template - inline bool chacha_crypt(std::string& buff, const pod_pass& pass) - { - std::string buff_target; - buff_target.resize(buff.size()); - chacha_crypt(buff.data(), buff.size(), (void*)buff_target.data(), &pass, sizeof(pass)); - buff = buff_target; - return true; - } - - template - inline std::string chacha_crypt(const std::string& input, const pod_pass& pass) - { - std::string result; - result.resize(input.size()); - if (chacha_crypt(input.data(), input.size(), (void*)result.data(), &pass, sizeof pass)) - return result; - return ""; - } - -} - -#endif diff --git a/src/crypto/chacha8_stream.c b/src/crypto/chacha8_stream.c deleted file mode 100644 index 94d9d81..0000000 --- a/src/crypto/chacha8_stream.c +++ /dev/null @@ -1,115 +0,0 @@ -/* -chacha-ref.c version 20080118 -D. J. Bernstein -Public domain. -*/ - -#include "ecrypt-sync.h" - -#define ROTATE(v,c) (ROTL32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -#define QUARTERROUND(a,b,c,d) \ - x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ - x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ - x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ - x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); - -static void salsa20_wordtobyte(u8 output[64], const u32 input[16]) -{ - u32 x[16]; - int i; - - for (i = 0; i < 16; ++i) x[i] = input[i]; - for (i = 8; i > 0; i -= 2) { - QUARTERROUND(0, 4, 8, 12) - QUARTERROUND(1, 5, 9, 13) - QUARTERROUND(2, 6, 10, 14) - QUARTERROUND(3, 7, 11, 15) - QUARTERROUND(0, 5, 10, 15) - QUARTERROUND(1, 6, 11, 12) - QUARTERROUND(2, 7, 8, 13) - QUARTERROUND(3, 4, 9, 14) - } - for (i = 0; i < 16; ++i) x[i] = PLUS(x[i], input[i]); - for (i = 0; i < 16; ++i) U32TO8_LITTLE(output + 4 * i, x[i]); -} - -void ECRYPT_init(void) -{ - return; -} - -static const char sigma[16] = "expand 32-byte k"; -static const char tau[16] = "expand 16-byte k"; - -void ECRYPT_keysetup(ECRYPT_ctx *x, const u8 *k, u32 kbits, u32 ivbits) -{ - const char *constants; - - x->input[4] = U8TO32_LITTLE(k + 0); - x->input[5] = U8TO32_LITTLE(k + 4); - x->input[6] = U8TO32_LITTLE(k + 8); - x->input[7] = U8TO32_LITTLE(k + 12); - if (kbits == 256) { /* recommended */ - k += 16; - constants = sigma; - } - else { /* kbits == 128 */ - constants = tau; - } - x->input[8] = U8TO32_LITTLE(k + 0); - x->input[9] = U8TO32_LITTLE(k + 4); - x->input[10] = U8TO32_LITTLE(k + 8); - x->input[11] = U8TO32_LITTLE(k + 12); - x->input[0] = U8TO32_LITTLE(constants + 0); - x->input[1] = U8TO32_LITTLE(constants + 4); - x->input[2] = U8TO32_LITTLE(constants + 8); - x->input[3] = U8TO32_LITTLE(constants + 12); -} - -void ECRYPT_ivsetup(ECRYPT_ctx *x, const u8 *iv) -{ - x->input[12] = 0; - x->input[13] = 0; - x->input[14] = U8TO32_LITTLE(iv + 0); - x->input[15] = U8TO32_LITTLE(iv + 4); -} - -void ECRYPT_encrypt_bytes(ECRYPT_ctx *x, const u8 *m, u8 *c, u32 bytes) -{ - u8 output[64]; - int i; - - if (!bytes) return; - for (;;) { - salsa20_wordtobyte(output, x->input); - x->input[12] = PLUSONE(x->input[12]); - if (!x->input[12]) { - x->input[13] = PLUSONE(x->input[13]); - /* stopping at 2^70 bytes per nonce is user's responsibility */ - } - if (bytes <= 64) { - for (i = 0; i < bytes; ++i) c[i] = m[i] ^ output[i]; - return; - } - for (i = 0; i < 64; ++i) c[i] = m[i] ^ output[i]; - bytes -= 64; - c += 64; - m += 64; - } -} - -void ECRYPT_decrypt_bytes(ECRYPT_ctx *x, const u8 *c, u8 *m, u32 bytes) -{ - ECRYPT_encrypt_bytes(x, c, m, bytes); -} - -void ECRYPT_keystream_bytes(ECRYPT_ctx *x, u8 *stream, u32 bytes) -{ - u32 i; - for (i = 0; i < bytes; ++i) stream[i] = 0; - ECRYPT_encrypt_bytes(x, stream, stream, bytes); -} \ No newline at end of file diff --git a/src/crypto/chacha8_stream.h b/src/crypto/chacha8_stream.h deleted file mode 100644 index a2d0b07..0000000 --- a/src/crypto/chacha8_stream.h +++ /dev/null @@ -1,289 +0,0 @@ -/* ecrypt-sync.h */ - -/* -* Header file for synchronous stream ciphers without authentication -* mechanism. -* -* *** Please only edit parts marked with "[edit]". *** -*/ - -#ifndef ECRYPT_SYNC -#define ECRYPT_SYNC - -#if defined(__cplusplus) -extern "C" { -#endif - - -#include "ecrypt-portable.h" - - /* ------------------------------------------------------------------------- */ - - /* Cipher parameters */ - - /* - * The name of your cipher. - */ -#define ECRYPT_NAME "ChaCha8" -#define ECRYPT_PROFILE "_____" - - /* - * Specify which key and IV sizes are supported by your cipher. A user - * should be able to enumerate the supported sizes by running the - * following code: - * - * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i) - * { - * keysize = ECRYPT_KEYSIZE(i); - * - * ... - * } - * - * All sizes are in bits. - */ - -#define ECRYPT_MAXKEYSIZE 256 /* [edit] */ -#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */ - -#define ECRYPT_MAXIVSIZE 64 /* [edit] */ -#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */ - - /* ------------------------------------------------------------------------- */ - - /* Data structures */ - - /* - * ECRYPT_ctx is the structure containing the representation of the - * internal state of your cipher. - */ - - typedef struct - { - u32 input[16]; /* could be compressed */ - /* - * [edit] - * - * Put here all state variable needed during the encryption process. - */ - } ECRYPT_ctx; - - /* ------------------------------------------------------------------------- */ - - /* Mandatory functions */ - - /* - * Key and message independent initialization. This function will be - * called once when the program starts (e.g., to build expanded S-box - * tables). - */ - void ECRYPT_init(); - - /* - * Key setup. It is the user's responsibility to select the values of - * keysize and ivsize from the set of supported values specified - * above. - */ - void ECRYPT_keysetup( - ECRYPT_ctx* ctx, - const u8* key, - u32 keysize, /* Key size in bits. */ - u32 ivsize); /* IV size in bits. */ - - /* - * IV setup. After having called ECRYPT_keysetup(), the user is - * allowed to call ECRYPT_ivsetup() different times in order to - * encrypt/decrypt different messages with the same key but different - * IV's. - */ - void ECRYPT_ivsetup( - ECRYPT_ctx* ctx, - const u8* iv); - - /* - * Encryption/decryption of arbitrary length messages. - * - * For efficiency reasons, the API provides two types of - * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function - * (declared here) encrypts byte strings of arbitrary length, while - * the ECRYPT_encrypt_blocks() function (defined later) only accepts - * lengths which are multiples of ECRYPT_BLOCKLENGTH. - * - * The user is allowed to make multiple calls to - * ECRYPT_encrypt_blocks() to incrementally encrypt a long message, - * but he is NOT allowed to make additional encryption calls once he - * has called ECRYPT_encrypt_bytes() (unless he starts a new message - * of course). For example, this sequence of calls is acceptable: - * - * ECRYPT_keysetup(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_bytes(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_blocks(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_bytes(); - * - * The following sequence is not: - * - * ECRYPT_keysetup(); - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_bytes(); - * ECRYPT_encrypt_blocks(); - */ - - void ECRYPT_encrypt_bytes( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 msglen); /* Message length in bytes. */ - - void ECRYPT_decrypt_bytes( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 msglen); /* Message length in bytes. */ - - /* ------------------------------------------------------------------------- */ - - /* Optional features */ - - /* - * For testing purposes it can sometimes be useful to have a function - * which immediately generates keystream without having to provide it - * with a zero plaintext. If your cipher cannot provide this function - * (e.g., because it is not strictly a synchronous cipher), please - * reset the ECRYPT_GENERATES_KEYSTREAM flag. - */ - -#define ECRYPT_GENERATES_KEYSTREAM -#ifdef ECRYPT_GENERATES_KEYSTREAM - - void ECRYPT_keystream_bytes( - ECRYPT_ctx* ctx, - u8* keystream, - u32 length); /* Length of keystream in bytes. */ - -#endif - -/* ------------------------------------------------------------------------- */ - -/* Optional optimizations */ - -/* -* By default, the functions in this section are implemented using -* calls to functions declared above. However, you might want to -* implement them differently for performance reasons. -*/ - -/* -* All-in-one encryption/decryption of (short) packets. -* -* The default definitions of these functions can be found in -* "ecrypt-sync.c". If you want to implement them differently, please -* undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag. -*/ -#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */ - - void ECRYPT_encrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* plaintext, - u8* ciphertext, - u32 msglen); - - void ECRYPT_decrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* ciphertext, - u8* plaintext, - u32 msglen); - - /* - * Encryption/decryption of blocks. - * - * By default, these functions are defined as macros. If you want to - * provide a different implementation, please undef the - * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions - * declared below. - */ - -#define ECRYPT_BLOCKLENGTH 64 /* [edit] */ - -#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */ -#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS - -#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ - ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ - ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#ifdef ECRYPT_GENERATES_KEYSTREAM - -#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \ - ECRYPT_keystream_bytes(ctx, keystream, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#endif - -#else - - void ECRYPT_encrypt_blocks( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 blocks); /* Message length in blocks. */ - - void ECRYPT_decrypt_blocks( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 blocks); /* Message length in blocks. */ - -#ifdef ECRYPT_GENERATES_KEYSTREAM - - void ECRYPT_keystream_blocks( - ECRYPT_ctx* ctx, - const u8* keystream, - u32 blocks); /* Keystream length in blocks. */ - -#endif - -#endif - -/* -* If your cipher can be implemented in different ways, you can use -* the ECRYPT_VARIANT parameter to allow the user to choose between -* them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please -* only use this possibility if you really think it could make a -* significant difference and keep the number of variants -* (ECRYPT_MAXVARIANT) as small as possible (definitely not more than -* 10). Note also that all variants should have exactly the same -* external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.). -*/ -#define ECRYPT_MAXVARIANT 1 /* [edit] */ - -#ifndef ECRYPT_VARIANT -#define ECRYPT_VARIANT 1 -#endif - -#if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT) -#error this variant does not exist -#endif - -/* ------------------------------------------------------------------------- */ - -#if defined(__cplusplus) -//extern "C" { -} -#endif - -#endif \ No newline at end of file diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c deleted file mode 100644 index 48bfe21..0000000 --- a/src/crypto/crypto-ops-data.c +++ /dev/null @@ -1,846 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include - -#include "crypto-ops.h" - -/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */ -/* d = -121665 / 121666 */ -const fe fe_d = {-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116}; /* d */ -const fe fe_sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482}; /* sqrt(-1) */ -const fe fe_d2 = {-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199}; /* 2 * d */ - -/* base[i][j] = (j+1)*256^i*B */ -const ge_precomp ge_base[32][8] = { - { - {{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, - {{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, - {-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, - {26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}}, - {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, - {{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, - {23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, - {7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}}, - {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, - {{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, - {-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, - {-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}}, - {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, - {{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, - {-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, - {27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}} - }, { - {{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, - {27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, - {17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}}, - {{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, - {29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, - {5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}}, - {{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, - {12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, - {25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}}, - {{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, - {-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, - {-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}}, - {{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, - {13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, - {21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}}, - {{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, - {-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, - {-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}}, - {{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, - {-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, - {-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}}, - {{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, - {33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, - {1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}} - }, { - {{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, - {4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, - {-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}}, - {{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, - {-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, - {-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}}, - {{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, - {20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, - {9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}}, - {{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, - {19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, - {8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}}, - {{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, - {11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, - {-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}}, - {{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, - {-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, - {1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}}, - {{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, - {-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, - {-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}}, - {{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, - {11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, - {-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}} - }, { - {{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, - {-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, - {-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}}, - {{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, - {14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, - {-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}}, - {{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, - {12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, - {-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}}, - {{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, - {14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, - {236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}}, - {{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, - {5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, - {20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}}, - {{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, - {-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, - {-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}}, - {{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, - {-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, - {23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}}, - {{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, - {-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, - {27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}} - }, { - {{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, - {-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, - {24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}}, - {{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, - {8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, - {-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}}, - {{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, - {10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, - {10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}}, - {{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, - {-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, - {28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}}, - {{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, - {-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, - {-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}}, - {{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, - {-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, - {29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}}, - {{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, - {-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, - {-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}}, - {{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, - {23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, - {-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}} - }, { - {{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, - {-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, - {14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}}, - {{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, - {-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, - {-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}}, - {{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, - {19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, - {-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}}, - {{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, - {-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, - {-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}}, - {{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, - {-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, - {-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}}, - {{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, - {-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, - {-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}}, - {{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, - {-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, - {-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}}, - {{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, - {-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, - {29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}} - }, { - {{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, - {20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, - {-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}}, - {{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, - {22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, - {16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}}, - {{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, - {24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, - {-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}}, - {{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, - {-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, - {-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}}, - {{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, - {-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, - {-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}}, - {{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, - {-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, - {-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}}, - {{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, - {10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, - {-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}}, - {{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, - {6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, - {28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}} - }, { - {{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, - {26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, - {-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}}, - {{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, - {-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, - {-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}}, - {{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, - {-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, - {-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}}, - {{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, - {-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, - {4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}}, - {{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, - {-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, - {-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}}, - {{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, - {-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, - {-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}}, - {{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, - {26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, - {19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}}, - {{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, - {19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, - {19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}} - }, { - {{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, - {32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, - {22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}}, - {{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, - {-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, - {1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}}, - {{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, - {-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, - {-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}}, - {{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, - {14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, - {5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}}, - {{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, - {-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, - {20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}}, - {{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, - {-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, - {-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}}, - {{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, - {23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, - {15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}}, - {{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, - {-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, - {-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}} - }, { - {{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, - {-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, - {3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}}, - {{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, - {-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, - {-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}}, - {{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, - {-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, - {-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}}, - {{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, - {29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, - {-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}}, - {{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, - {31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, - {-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}}, - {{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, - {-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, - {-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}}, - {{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, - {9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, - {-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}}, - {{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, - {27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, - {19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}} - }, { - {{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, - {2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, - {-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}}, - {{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, - {915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, - {32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}}, - {{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, - {-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, - {21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}}, - {{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, - {31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, - {19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}}, - {{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, - {32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, - {2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}}, - {{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, - {-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, - {-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}}, - {{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, - {-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, - {-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}}, - {{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, - {20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, - {32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}} - }, { - {{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, - {-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, - {5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}}, - {{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, - {-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, - {-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}}, - {{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, - {-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, - {580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}}, - {{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, - {13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, - {2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}}, - {{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, - {-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, - {4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}}, - {{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, - {27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, - {6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}}, - {{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, - {16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, - {22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}}, - {{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, - {-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, - {-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}} - }, { - {{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, - {3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, - {10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}}, - {{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, - {24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, - {13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}}, - {{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, - {29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, - {-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}}, - {{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, - {20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, - {-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}}, - {{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, - {12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, - {13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}}, - {{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, - {-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, - {17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}}, - {{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, - {-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, - {-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}}, - {{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, - {-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, - {-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}} - }, { - {{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, - {18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, - {-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}}, - {{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, - {10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, - {-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}}, - {{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, - {29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, - {10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}}, - {{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, - {-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, - {-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}}, - {{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, - {-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, - {3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}}, - {{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, - {-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, - {-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}}, - {{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, - {-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, - {-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}}, - {{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, - {-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, - {-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}} - }, { - {{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, - {-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, - {22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}}, - {{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, - {15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, - {15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}}, - {{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, - {11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, - {14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}}, - {{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, - {-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, - {29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}}, - {{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, - {-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, - {10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}}, - {{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, - {-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, - {10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}}, - {{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, - {14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, - {30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}}, - {{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, - {-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, - {-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}} - }, { - {{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, - {10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, - {17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}}, - {{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, - {26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, - {-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}}, - {{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, - {9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, - {-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}}, - {{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, - {32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, - {14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}}, - {{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, - {-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, - {-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}}, - {{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, - {27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, - {10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}}, - {{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, - {-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, - {-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}}, - {{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, - {20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, - {27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}} - }, { - {{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, - {-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, - {-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}}, - {{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, - {1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, - {-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}}, - {{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, - {31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, - {29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}}, - {{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, - {6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, - {-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}}, - {{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, - {-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, - {-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}}, - {{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, - {-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, - {-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}}, - {{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, - {-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, - {-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}}, - {{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, - {11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, - {-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}} - }, { - {{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, - {-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, - {-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}}, - {{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, - {-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, - {-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}}, - {{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, - {8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, - {-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}}, - {{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, - {27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, - {21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}}, - {{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, - {26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, - {-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}}, - {{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, - {-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, - {-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}}, - {{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, - {-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, - {21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}}, - {{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, - {29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, - {-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}} - }, { - {{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, - {2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, - {-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}}, - {{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, - {-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, - {-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}}, - {{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, - {18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, - {2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}}, - {{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, - {-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, - {7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}}, - {{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, - {10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, - {696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}}, - {{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, - {17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, - {26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}}, - {{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, - {-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, - {-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}}, - {{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, - {-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, - {-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}} - }, { - {{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, - {-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, - {-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}}, - {{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, - {-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, - {20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}}, - {{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, - {-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, - {-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}}, - {{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, - {6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, - {30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}}, - {{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, - {17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, - {-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}}, - {{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, - {-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, - {18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}}, - {{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, - {33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, - {-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}}, - {{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, - {-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, - {18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}} - }, { - {{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, - {5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, - {-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}}, - {{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, - {8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, - {17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}}, - {{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, - {-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, - {-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}}, - {{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, - {8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, - {15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}}, - {{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, - {-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, - {31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}}, - {{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, - {842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, - {-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}}, - {{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, - {-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, - {-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}}, - {{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, - {-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, - {12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}} - }, { - {{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, - {10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, - {-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}}, - {{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, - {21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, - {-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}}, - {{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, - {-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, - {-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}}, - {{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, - {30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, - {9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}}, - {{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, - {-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, - {-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}}, - {{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, - {-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, - {-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}}, - {{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, - {-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, - {22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}}, - {{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, - {-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, - {-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}} - }, { - {{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, - {-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, - {6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}}, - {{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, - {22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, - {-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}}, - {{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, - {9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, - {7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}}, - {{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, - {-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, - {-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}}, - {{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, - {-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, - {-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}}, - {{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, - {31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, - {4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}}, - {{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, - {-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, - {26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}}, - {{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, - {16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, - {28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}} - }, { - {{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, - {-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, - {-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}}, - {{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, - {18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, - {19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}}, - {{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, - {14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, - {19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}}, - {{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, - {-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, - {-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}}, - {{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, - {18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, - {-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}}, - {{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, - {-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, - {-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}}, - {{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, - {-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, - {-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}}, - {{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, - {24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, - {-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}} - }, { - {{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, - {5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, - {-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}}, - {{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, - {10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, - {27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}}, - {{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, - {4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, - {-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}}, - {{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, - {-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, - {-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}}, - {{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, - {13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, - {28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}}, - {{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, - {24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, - {17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}}, - {{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, - {-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, - {28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}}, - {{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, - {10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, - {-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}} - }, { - {{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, - {15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, - {-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}}, - {{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, - {21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, - {-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}}, - {{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, - {-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, - {-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}}, - {{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, - {-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, - {-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}}, - {{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, - {-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, - {15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}}, - {{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, - {4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, - {-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}}, - {{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, - {-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, - {2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}}, - {{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, - {18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, - {-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}} - }, { - {{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, - {-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, - {21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}}, - {{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, - {-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, - {-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}}, - {{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, - {-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, - {4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}}, - {{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, - {19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, - {24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}}, - {{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, - {510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, - {18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}}, - {{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, - {9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, - {12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}}, - {{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, - {11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, - {20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}}, - {{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, - {-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, - {24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}} - }, { - {{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, - {-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, - {-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}}, - {{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, - {22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, - {-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}}, - {{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, - {26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, - {-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}}, - {{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, - {15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, - {8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}}, - {{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, - {-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, - {21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}}, - {{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, - {-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, - {-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}}, - {{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, - {4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, - {366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}}, - {{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, - {18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, - {476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}} - }, { - {{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, - {-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, - {24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}}, - {{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, - {-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, - {-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}}, - {{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, - {-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, - {-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}}, - {{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, - {-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, - {-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}}, - {{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, - {25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, - {-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}}, - {{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, - {-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, - {-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}}, - {{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, - {17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, - {-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}}, - {{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, - {13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, - {-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}} - }, { - {{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, - {31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, - {-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}}, - {{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, - {-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, - {31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}}, - {{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, - {-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, - {33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}}, - {{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, - {-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, - {22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}}, - {{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, - {23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, - {-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}}, - {{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, - {3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, - {-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}}, - {{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, - {21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, - {18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}}, - {{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, - {9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, - {-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}} - }, { - {{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, - {-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, - {-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}}, - {{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, - {-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, - {18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}}, - {{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, - {-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, - {-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}}, - {{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, - {25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, - {31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}}, - {{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, - {-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, - {-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}}, - {{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, - {2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, - {33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}}, - {{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, - {23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, - {1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}}, - {{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, - {13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, - {-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}} - }, { - {{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, - {-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, - {29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}}, - {{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, - {-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, - {-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}}, - {{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, - {-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, - {16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}}, - {{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, - {-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, - {31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}}, - {{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, - {15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, - {-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}}, - {{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, - {11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, - {-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}}, - {{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, - {-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, - {-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}}, - {{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, - {29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, - {-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}} - } -}; - -const ge_precomp ge_Bi[8] = { - {{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, {{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, - {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, - {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}}, {{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, - {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, - {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}}, {{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, - {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, - {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}}, {{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, - {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, - {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}} -}; - -/* A = 2 * (1 - d) / (1 + d) = 486662 */ -const fe fe_ma2 = {-12721188, -3529, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A^2 */ -const fe fe_ma = {-486662, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A */ -const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -321052, 14850977, -10296299, -16929438, -407568}; /* sqrt(-2 * A * (A + 2)) */ -const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */ -const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */ -const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */ diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c deleted file mode 100644 index caf20a0..0000000 --- a/src/crypto/crypto-ops.c +++ /dev/null @@ -1,4312 +0,0 @@ -// Copyright (c) 2018-2021 Zano Project -// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com) -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// This file contains pieces of code from libsodium project. -// libsodium is licensed under the ISC License: -/* - * ISC License - * - * Copyright (c) 2013-2020 - * Frank Denis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include "warnings.h" -#include "crypto-ops.h" -#include "hash-ops.h" // for cn_fast_hash - -DISABLE_VS_WARNINGS(4146 4244) - -/* Predeclarations */ - -void fe_mul(fe, const fe, const fe); -void fe_sq(fe, const fe); -void fe_tobytes(unsigned char *, const fe); -static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *); -static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *); -static void ge_p2_0(ge_p2 *); -static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *); -void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *); -static void fe_divpowm1(fe, const fe, const fe); - -/* Common functions */ - -static uint64_t load_3(const unsigned char *in) { - uint64_t result; - result = (uint64_t) in[0]; - result |= ((uint64_t) in[1]) << 8; - result |= ((uint64_t) in[2]) << 16; - return result; -} - -static uint64_t load_4(const unsigned char *in) -{ - uint64_t result; - result = (uint64_t) in[0]; - result |= ((uint64_t) in[1]) << 8; - result |= ((uint64_t) in[2]) << 16; - result |= ((uint64_t) in[3]) << 24; - return result; -} - -/* From fe_0.c */ - -/* -h = 0 -*/ - -void fe_0(fe h) { - h[0] = 0; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* From fe_1.c */ - -/* -h = 1 -*/ - -static void fe_1(fe h) { - h[0] = 1; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* From fe_add.c */ - -/* -h = f + g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static void fe_add(fe h, const fe f, const fe g) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t g0 = g[0]; - int32_t g1 = g[1]; - int32_t g2 = g[2]; - int32_t g3 = g[3]; - int32_t g4 = g[4]; - int32_t g5 = g[5]; - int32_t g6 = g[6]; - int32_t g7 = g[7]; - int32_t g8 = g[8]; - int32_t g9 = g[9]; - int32_t h0 = f0 + g0; - int32_t h1 = f1 + g1; - int32_t h2 = f2 + g2; - int32_t h3 = f3 + g3; - int32_t h4 = f4 + g4; - int32_t h5 = f5 + g5; - int32_t h6 = f6 + g6; - int32_t h7 = f7 + g7; - int32_t h8 = f8 + g8; - int32_t h9 = f9 + g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_cmov.c */ - -/* -Replace (f,g) with (g,g) if b == 1; -replace (f,g) with (f,g) if b == 0. - -Preconditions: b in {0,1}. -*/ - -static void fe_cmov(fe f, const fe g, unsigned int b) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t g0 = g[0]; - int32_t g1 = g[1]; - int32_t g2 = g[2]; - int32_t g3 = g[3]; - int32_t g4 = g[4]; - int32_t g5 = g[5]; - int32_t g6 = g[6]; - int32_t g7 = g[7]; - int32_t g8 = g[8]; - int32_t g9 = g[9]; - int32_t x0 = f0 ^ g0; - int32_t x1 = f1 ^ g1; - int32_t x2 = f2 ^ g2; - int32_t x3 = f3 ^ g3; - int32_t x4 = f4 ^ g4; - int32_t x5 = f5 ^ g5; - int32_t x6 = f6 ^ g6; - int32_t x7 = f7 ^ g7; - int32_t x8 = f8 ^ g8; - int32_t x9 = f9 ^ g9; - assert((((b - 1) & ~b) | ((b - 2) & ~(b - 1))) == (unsigned int) -1); - b = -b; - x0 &= b; - x1 &= b; - x2 &= b; - x3 &= b; - x4 &= b; - x5 &= b; - x6 &= b; - x7 &= b; - x8 &= b; - x9 &= b; - f[0] = f0 ^ x0; - f[1] = f1 ^ x1; - f[2] = f2 ^ x2; - f[3] = f3 ^ x3; - f[4] = f4 ^ x4; - f[5] = f5 ^ x5; - f[6] = f6 ^ x6; - f[7] = f7 ^ x7; - f[8] = f8 ^ x8; - f[9] = f9 ^ x9; -} - -/* From fe_copy.c */ - -/* -h = f -*/ - -static void fe_copy(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - h[0] = f0; - h[1] = f1; - h[2] = f2; - h[3] = f3; - h[4] = f4; - h[5] = f5; - h[6] = f6; - h[7] = f7; - h[8] = f8; - h[9] = f9; -} - -/* From fe_invert.c */ - -void fe_invert(fe out, const fe z) { - fe t0; - fe t1; - fe t2; - fe t3; - int i; - - fe_sq(t0, z); - fe_sq(t1, t0); - fe_sq(t1, t1); - fe_mul(t1, z, t1); - fe_mul(t0, t0, t1); - fe_sq(t2, t0); - fe_mul(t1, t1, t2); - fe_sq(t2, t1); - for (i = 0; i < 4; ++i) { - fe_sq(t2, t2); - } - fe_mul(t1, t2, t1); - fe_sq(t2, t1); - for (i = 0; i < 9; ++i) { - fe_sq(t2, t2); - } - fe_mul(t2, t2, t1); - fe_sq(t3, t2); - for (i = 0; i < 19; ++i) { - fe_sq(t3, t3); - } - fe_mul(t2, t3, t2); - fe_sq(t2, t2); - for (i = 0; i < 9; ++i) { - fe_sq(t2, t2); - } - fe_mul(t1, t2, t1); - fe_sq(t2, t1); - for (i = 0; i < 49; ++i) { - fe_sq(t2, t2); - } - fe_mul(t2, t2, t1); - fe_sq(t3, t2); - for (i = 0; i < 99; ++i) { - fe_sq(t3, t3); - } - fe_mul(t2, t3, t2); - fe_sq(t2, t2); - for (i = 0; i < 49; ++i) { - fe_sq(t2, t2); - } - fe_mul(t1, t2, t1); - fe_sq(t1, t1); - for (i = 0; i < 4; ++i) { - fe_sq(t1, t1); - } - fe_mul(out, t1, t0); - - return; -} - -/* From fe_isnegative.c */ - -/* -return 1 if f is in {1,3,5,...,q-2} -return 0 if f is in {0,2,4,...,q-1} - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static int fe_isnegative(const fe f) { - unsigned char s[32]; - fe_tobytes(s, f); - return s[0] & 1; -} - -/* From fe_isnonzero.c, modified */ - -int fe_isnonzero(const fe f) { - unsigned char s[32]; - fe_tobytes(s, f); - return (((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] | - s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] | - s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] | - s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1; -} - -int fe_cmp(const fe a, const fe b) -{ - for (size_t i = 9; i != SIZE_MAX; --i) - { - if ((const uint32_t)a[i] < (const uint32_t)b[i]) return -1; - if ((const uint32_t)a[i] > (const uint32_t)b[i]) return 1; - } - return 0; -} - -/* From fe_mul.c */ - -/* -h = f * g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -Notes on implementation strategy: - -Using schoolbook multiplication. -Karatsuba would save a little in some cost models. - -Most multiplications by 2 and 19 are 32-bit precomputations; -cheaper than 64-bit postcomputations. - -There is one remaining multiplication by 19 in the carry chain; -one *19 precomputation can be merged into this, -but the resulting data flow is considerably less clean. - -There are 12 carries below. -10 of them are 2-way parallelizable and vectorizable. -Can get away with 11 carries, but then data flow is much deeper. - -With tighter constraints on inputs can squeeze carries into int32. -*/ - -void fe_mul(fe h, const fe f, const fe g) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t g0 = g[0]; - int32_t g1 = g[1]; - int32_t g2 = g[2]; - int32_t g3 = g[3]; - int32_t g4 = g[4]; - int32_t g5 = g[5]; - int32_t g6 = g[6]; - int32_t g7 = g[7]; - int32_t g8 = g[8]; - int32_t g9 = g[9]; - int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ - int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ - int32_t g3_19 = 19 * g3; - int32_t g4_19 = 19 * g4; - int32_t g5_19 = 19 * g5; - int32_t g6_19 = 19 * g6; - int32_t g7_19 = 19 * g7; - int32_t g8_19 = 19 * g8; - int32_t g9_19 = 19 * g9; - int32_t f1_2 = 2 * f1; - int32_t f3_2 = 2 * f3; - int32_t f5_2 = 2 * f5; - int32_t f7_2 = 2 * f7; - int32_t f9_2 = 2 * f9; - int64_t f0g0 = f0 * (int64_t) g0; - int64_t f0g1 = f0 * (int64_t) g1; - int64_t f0g2 = f0 * (int64_t) g2; - int64_t f0g3 = f0 * (int64_t) g3; - int64_t f0g4 = f0 * (int64_t) g4; - int64_t f0g5 = f0 * (int64_t) g5; - int64_t f0g6 = f0 * (int64_t) g6; - int64_t f0g7 = f0 * (int64_t) g7; - int64_t f0g8 = f0 * (int64_t) g8; - int64_t f0g9 = f0 * (int64_t) g9; - int64_t f1g0 = f1 * (int64_t) g0; - int64_t f1g1_2 = f1_2 * (int64_t) g1; - int64_t f1g2 = f1 * (int64_t) g2; - int64_t f1g3_2 = f1_2 * (int64_t) g3; - int64_t f1g4 = f1 * (int64_t) g4; - int64_t f1g5_2 = f1_2 * (int64_t) g5; - int64_t f1g6 = f1 * (int64_t) g6; - int64_t f1g7_2 = f1_2 * (int64_t) g7; - int64_t f1g8 = f1 * (int64_t) g8; - int64_t f1g9_38 = f1_2 * (int64_t) g9_19; - int64_t f2g0 = f2 * (int64_t) g0; - int64_t f2g1 = f2 * (int64_t) g1; - int64_t f2g2 = f2 * (int64_t) g2; - int64_t f2g3 = f2 * (int64_t) g3; - int64_t f2g4 = f2 * (int64_t) g4; - int64_t f2g5 = f2 * (int64_t) g5; - int64_t f2g6 = f2 * (int64_t) g6; - int64_t f2g7 = f2 * (int64_t) g7; - int64_t f2g8_19 = f2 * (int64_t) g8_19; - int64_t f2g9_19 = f2 * (int64_t) g9_19; - int64_t f3g0 = f3 * (int64_t) g0; - int64_t f3g1_2 = f3_2 * (int64_t) g1; - int64_t f3g2 = f3 * (int64_t) g2; - int64_t f3g3_2 = f3_2 * (int64_t) g3; - int64_t f3g4 = f3 * (int64_t) g4; - int64_t f3g5_2 = f3_2 * (int64_t) g5; - int64_t f3g6 = f3 * (int64_t) g6; - int64_t f3g7_38 = f3_2 * (int64_t) g7_19; - int64_t f3g8_19 = f3 * (int64_t) g8_19; - int64_t f3g9_38 = f3_2 * (int64_t) g9_19; - int64_t f4g0 = f4 * (int64_t) g0; - int64_t f4g1 = f4 * (int64_t) g1; - int64_t f4g2 = f4 * (int64_t) g2; - int64_t f4g3 = f4 * (int64_t) g3; - int64_t f4g4 = f4 * (int64_t) g4; - int64_t f4g5 = f4 * (int64_t) g5; - int64_t f4g6_19 = f4 * (int64_t) g6_19; - int64_t f4g7_19 = f4 * (int64_t) g7_19; - int64_t f4g8_19 = f4 * (int64_t) g8_19; - int64_t f4g9_19 = f4 * (int64_t) g9_19; - int64_t f5g0 = f5 * (int64_t) g0; - int64_t f5g1_2 = f5_2 * (int64_t) g1; - int64_t f5g2 = f5 * (int64_t) g2; - int64_t f5g3_2 = f5_2 * (int64_t) g3; - int64_t f5g4 = f5 * (int64_t) g4; - int64_t f5g5_38 = f5_2 * (int64_t) g5_19; - int64_t f5g6_19 = f5 * (int64_t) g6_19; - int64_t f5g7_38 = f5_2 * (int64_t) g7_19; - int64_t f5g8_19 = f5 * (int64_t) g8_19; - int64_t f5g9_38 = f5_2 * (int64_t) g9_19; - int64_t f6g0 = f6 * (int64_t) g0; - int64_t f6g1 = f6 * (int64_t) g1; - int64_t f6g2 = f6 * (int64_t) g2; - int64_t f6g3 = f6 * (int64_t) g3; - int64_t f6g4_19 = f6 * (int64_t) g4_19; - int64_t f6g5_19 = f6 * (int64_t) g5_19; - int64_t f6g6_19 = f6 * (int64_t) g6_19; - int64_t f6g7_19 = f6 * (int64_t) g7_19; - int64_t f6g8_19 = f6 * (int64_t) g8_19; - int64_t f6g9_19 = f6 * (int64_t) g9_19; - int64_t f7g0 = f7 * (int64_t) g0; - int64_t f7g1_2 = f7_2 * (int64_t) g1; - int64_t f7g2 = f7 * (int64_t) g2; - int64_t f7g3_38 = f7_2 * (int64_t) g3_19; - int64_t f7g4_19 = f7 * (int64_t) g4_19; - int64_t f7g5_38 = f7_2 * (int64_t) g5_19; - int64_t f7g6_19 = f7 * (int64_t) g6_19; - int64_t f7g7_38 = f7_2 * (int64_t) g7_19; - int64_t f7g8_19 = f7 * (int64_t) g8_19; - int64_t f7g9_38 = f7_2 * (int64_t) g9_19; - int64_t f8g0 = f8 * (int64_t) g0; - int64_t f8g1 = f8 * (int64_t) g1; - int64_t f8g2_19 = f8 * (int64_t) g2_19; - int64_t f8g3_19 = f8 * (int64_t) g3_19; - int64_t f8g4_19 = f8 * (int64_t) g4_19; - int64_t f8g5_19 = f8 * (int64_t) g5_19; - int64_t f8g6_19 = f8 * (int64_t) g6_19; - int64_t f8g7_19 = f8 * (int64_t) g7_19; - int64_t f8g8_19 = f8 * (int64_t) g8_19; - int64_t f8g9_19 = f8 * (int64_t) g9_19; - int64_t f9g0 = f9 * (int64_t) g0; - int64_t f9g1_38 = f9_2 * (int64_t) g1_19; - int64_t f9g2_19 = f9 * (int64_t) g2_19; - int64_t f9g3_38 = f9_2 * (int64_t) g3_19; - int64_t f9g4_19 = f9 * (int64_t) g4_19; - int64_t f9g5_38 = f9_2 * (int64_t) g5_19; - int64_t f9g6_19 = f9 * (int64_t) g6_19; - int64_t f9g7_38 = f9_2 * (int64_t) g7_19; - int64_t f9g8_19 = f9 * (int64_t) g8_19; - int64_t f9g9_38 = f9_2 * (int64_t) g9_19; - int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; - int64_t h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; - int64_t h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; - int64_t h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; - int64_t h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; - int64_t h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; - int64_t h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; - int64_t h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; - int64_t h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; - int64_t h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - /* - |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 - */ - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.71*2^59 */ - /* |h5| <= 1.71*2^59 */ - - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.41*2^60 */ - /* |h6| <= 1.41*2^60 */ - - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.71*2^59 */ - /* |h7| <= 1.71*2^59 */ - - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.72*2^34 */ - /* |h8| <= 1.41*2^60 */ - - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.71*2^59 */ - - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.1*2^39 */ - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_neg.c */ - -/* -h = -f - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -*/ - -static void fe_neg(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t h0 = -f0; - int32_t h1 = -f1; - int32_t h2 = -f2; - int32_t h3 = -f3; - int32_t h4 = -f4; - int32_t h5 = -f5; - int32_t h6 = -f6; - int32_t h7 = -f7; - int32_t h8 = -f8; - int32_t h9 = -f9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_sq.c */ - -/* -h = f * f -Can overlap h with f. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -See fe_mul.c for discussion of implementation strategy. -*/ - -void fe_sq(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t f0_2 = 2 * f0; - int32_t f1_2 = 2 * f1; - int32_t f2_2 = 2 * f2; - int32_t f3_2 = 2 * f3; - int32_t f4_2 = 2 * f4; - int32_t f5_2 = 2 * f5; - int32_t f6_2 = 2 * f6; - int32_t f7_2 = 2 * f7; - int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ - int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ - int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ - int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ - int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ - int64_t f0f0 = f0 * (int64_t) f0; - int64_t f0f1_2 = f0_2 * (int64_t) f1; - int64_t f0f2_2 = f0_2 * (int64_t) f2; - int64_t f0f3_2 = f0_2 * (int64_t) f3; - int64_t f0f4_2 = f0_2 * (int64_t) f4; - int64_t f0f5_2 = f0_2 * (int64_t) f5; - int64_t f0f6_2 = f0_2 * (int64_t) f6; - int64_t f0f7_2 = f0_2 * (int64_t) f7; - int64_t f0f8_2 = f0_2 * (int64_t) f8; - int64_t f0f9_2 = f0_2 * (int64_t) f9; - int64_t f1f1_2 = f1_2 * (int64_t) f1; - int64_t f1f2_2 = f1_2 * (int64_t) f2; - int64_t f1f3_4 = f1_2 * (int64_t) f3_2; - int64_t f1f4_2 = f1_2 * (int64_t) f4; - int64_t f1f5_4 = f1_2 * (int64_t) f5_2; - int64_t f1f6_2 = f1_2 * (int64_t) f6; - int64_t f1f7_4 = f1_2 * (int64_t) f7_2; - int64_t f1f8_2 = f1_2 * (int64_t) f8; - int64_t f1f9_76 = f1_2 * (int64_t) f9_38; - int64_t f2f2 = f2 * (int64_t) f2; - int64_t f2f3_2 = f2_2 * (int64_t) f3; - int64_t f2f4_2 = f2_2 * (int64_t) f4; - int64_t f2f5_2 = f2_2 * (int64_t) f5; - int64_t f2f6_2 = f2_2 * (int64_t) f6; - int64_t f2f7_2 = f2_2 * (int64_t) f7; - int64_t f2f8_38 = f2_2 * (int64_t) f8_19; - int64_t f2f9_38 = f2 * (int64_t) f9_38; - int64_t f3f3_2 = f3_2 * (int64_t) f3; - int64_t f3f4_2 = f3_2 * (int64_t) f4; - int64_t f3f5_4 = f3_2 * (int64_t) f5_2; - int64_t f3f6_2 = f3_2 * (int64_t) f6; - int64_t f3f7_76 = f3_2 * (int64_t) f7_38; - int64_t f3f8_38 = f3_2 * (int64_t) f8_19; - int64_t f3f9_76 = f3_2 * (int64_t) f9_38; - int64_t f4f4 = f4 * (int64_t) f4; - int64_t f4f5_2 = f4_2 * (int64_t) f5; - int64_t f4f6_38 = f4_2 * (int64_t) f6_19; - int64_t f4f7_38 = f4 * (int64_t) f7_38; - int64_t f4f8_38 = f4_2 * (int64_t) f8_19; - int64_t f4f9_38 = f4 * (int64_t) f9_38; - int64_t f5f5_38 = f5 * (int64_t) f5_38; - int64_t f5f6_38 = f5_2 * (int64_t) f6_19; - int64_t f5f7_76 = f5_2 * (int64_t) f7_38; - int64_t f5f8_38 = f5_2 * (int64_t) f8_19; - int64_t f5f9_76 = f5_2 * (int64_t) f9_38; - int64_t f6f6_19 = f6 * (int64_t) f6_19; - int64_t f6f7_38 = f6 * (int64_t) f7_38; - int64_t f6f8_38 = f6_2 * (int64_t) f8_19; - int64_t f6f9_38 = f6 * (int64_t) f9_38; - int64_t f7f7_38 = f7 * (int64_t) f7_38; - int64_t f7f8_38 = f7_2 * (int64_t) f8_19; - int64_t f7f9_76 = f7_2 * (int64_t) f9_38; - int64_t f8f8_19 = f8 * (int64_t) f8_19; - int64_t f8f9_38 = f8 * (int64_t) f9_38; - int64_t f9f9_38 = f9 * (int64_t) f9_38; - int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; - int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; - int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; - int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; - int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; - int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; - int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; - int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; - int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; - int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_sq2.c */ - -/* -h = 2 * f * f -Can overlap h with f. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -See fe_mul.c for discussion of implementation strategy. -*/ - -static void fe_sq2(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t f0_2 = 2 * f0; - int32_t f1_2 = 2 * f1; - int32_t f2_2 = 2 * f2; - int32_t f3_2 = 2 * f3; - int32_t f4_2 = 2 * f4; - int32_t f5_2 = 2 * f5; - int32_t f6_2 = 2 * f6; - int32_t f7_2 = 2 * f7; - int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ - int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ - int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ - int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ - int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ - int64_t f0f0 = f0 * (int64_t) f0; - int64_t f0f1_2 = f0_2 * (int64_t) f1; - int64_t f0f2_2 = f0_2 * (int64_t) f2; - int64_t f0f3_2 = f0_2 * (int64_t) f3; - int64_t f0f4_2 = f0_2 * (int64_t) f4; - int64_t f0f5_2 = f0_2 * (int64_t) f5; - int64_t f0f6_2 = f0_2 * (int64_t) f6; - int64_t f0f7_2 = f0_2 * (int64_t) f7; - int64_t f0f8_2 = f0_2 * (int64_t) f8; - int64_t f0f9_2 = f0_2 * (int64_t) f9; - int64_t f1f1_2 = f1_2 * (int64_t) f1; - int64_t f1f2_2 = f1_2 * (int64_t) f2; - int64_t f1f3_4 = f1_2 * (int64_t) f3_2; - int64_t f1f4_2 = f1_2 * (int64_t) f4; - int64_t f1f5_4 = f1_2 * (int64_t) f5_2; - int64_t f1f6_2 = f1_2 * (int64_t) f6; - int64_t f1f7_4 = f1_2 * (int64_t) f7_2; - int64_t f1f8_2 = f1_2 * (int64_t) f8; - int64_t f1f9_76 = f1_2 * (int64_t) f9_38; - int64_t f2f2 = f2 * (int64_t) f2; - int64_t f2f3_2 = f2_2 * (int64_t) f3; - int64_t f2f4_2 = f2_2 * (int64_t) f4; - int64_t f2f5_2 = f2_2 * (int64_t) f5; - int64_t f2f6_2 = f2_2 * (int64_t) f6; - int64_t f2f7_2 = f2_2 * (int64_t) f7; - int64_t f2f8_38 = f2_2 * (int64_t) f8_19; - int64_t f2f9_38 = f2 * (int64_t) f9_38; - int64_t f3f3_2 = f3_2 * (int64_t) f3; - int64_t f3f4_2 = f3_2 * (int64_t) f4; - int64_t f3f5_4 = f3_2 * (int64_t) f5_2; - int64_t f3f6_2 = f3_2 * (int64_t) f6; - int64_t f3f7_76 = f3_2 * (int64_t) f7_38; - int64_t f3f8_38 = f3_2 * (int64_t) f8_19; - int64_t f3f9_76 = f3_2 * (int64_t) f9_38; - int64_t f4f4 = f4 * (int64_t) f4; - int64_t f4f5_2 = f4_2 * (int64_t) f5; - int64_t f4f6_38 = f4_2 * (int64_t) f6_19; - int64_t f4f7_38 = f4 * (int64_t) f7_38; - int64_t f4f8_38 = f4_2 * (int64_t) f8_19; - int64_t f4f9_38 = f4 * (int64_t) f9_38; - int64_t f5f5_38 = f5 * (int64_t) f5_38; - int64_t f5f6_38 = f5_2 * (int64_t) f6_19; - int64_t f5f7_76 = f5_2 * (int64_t) f7_38; - int64_t f5f8_38 = f5_2 * (int64_t) f8_19; - int64_t f5f9_76 = f5_2 * (int64_t) f9_38; - int64_t f6f6_19 = f6 * (int64_t) f6_19; - int64_t f6f7_38 = f6 * (int64_t) f7_38; - int64_t f6f8_38 = f6_2 * (int64_t) f8_19; - int64_t f6f9_38 = f6 * (int64_t) f9_38; - int64_t f7f7_38 = f7 * (int64_t) f7_38; - int64_t f7f8_38 = f7_2 * (int64_t) f8_19; - int64_t f7f9_76 = f7_2 * (int64_t) f9_38; - int64_t f8f8_19 = f8 * (int64_t) f8_19; - int64_t f8f9_38 = f8 * (int64_t) f9_38; - int64_t f9f9_38 = f9 * (int64_t) f9_38; - int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; - int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; - int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; - int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; - int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; - int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; - int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; - int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; - int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; - int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - h0 += h0; - h1 += h1; - h2 += h2; - h3 += h3; - h4 += h4; - h5 += h5; - h6 += h6; - h7 += h7; - h8 += h8; - h9 += h9; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_sub.c */ - -/* -h = f - g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static void fe_sub(fe h, const fe f, const fe g) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t g0 = g[0]; - int32_t g1 = g[1]; - int32_t g2 = g[2]; - int32_t g3 = g[3]; - int32_t g4 = g[4]; - int32_t g5 = g[5]; - int32_t g6 = g[6]; - int32_t g7 = g[7]; - int32_t g8 = g[8]; - int32_t g9 = g[9]; - int32_t h0 = f0 - g0; - int32_t h1 = f1 - g1; - int32_t h2 = f2 - g2; - int32_t h3 = f3 - g3; - int32_t h4 = f4 - g4; - int32_t h5 = f5 - g5; - int32_t h6 = f6 - g6; - int32_t h7 = f7 - g7; - int32_t h8 = f8 - g8; - int32_t h9 = f9 - g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* From fe_tobytes.c */ - -/* -Preconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - -Write p=2^255-19; q=floor(h/p). -Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). - -Proof: - Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. - Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. - - Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). - Then 0> 25; - q = (h0 + q) >> 26; - q = (h1 + q) >> 25; - q = (h2 + q) >> 26; - q = (h3 + q) >> 25; - q = (h4 + q) >> 26; - q = (h5 + q) >> 25; - q = (h6 + q) >> 26; - q = (h7 + q) >> 25; - q = (h8 + q) >> 26; - q = (h9 + q) >> 25; - - /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ - h0 += 19 * q; - /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ - - carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; - carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; - carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; - carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; - carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; - carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; - carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; - carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; - carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; - carry9 = h9 >> 25; h9 -= carry9 << 25; - /* h10 = carry9 */ - - /* - Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - Have h0+...+2^230 h9 between 0 and 2^255-1; - evidently 2^255 h10-2^255 q = 0. - Goal: Output h0+...+2^230 h9. - */ - - s[0] = h0 >> 0; - s[1] = h0 >> 8; - s[2] = h0 >> 16; - s[3] = (h0 >> 24) | (h1 << 2); - s[4] = h1 >> 6; - s[5] = h1 >> 14; - s[6] = (h1 >> 22) | (h2 << 3); - s[7] = h2 >> 5; - s[8] = h2 >> 13; - s[9] = (h2 >> 21) | (h3 << 5); - s[10] = h3 >> 3; - s[11] = h3 >> 11; - s[12] = (h3 >> 19) | (h4 << 6); - s[13] = h4 >> 2; - s[14] = h4 >> 10; - s[15] = h4 >> 18; - s[16] = h5 >> 0; - s[17] = h5 >> 8; - s[18] = h5 >> 16; - s[19] = (h5 >> 24) | (h6 << 1); - s[20] = h6 >> 7; - s[21] = h6 >> 15; - s[22] = (h6 >> 23) | (h7 << 3); - s[23] = h7 >> 5; - s[24] = h7 >> 13; - s[25] = (h7 >> 21) | (h8 << 4); - s[26] = h8 >> 4; - s[27] = h8 >> 12; - s[28] = (h8 >> 20) | (h9 << 6); - s[29] = h9 >> 2; - s[30] = h9 >> 10; - s[31] = h9 >> 18; -} - -/* From ge_add.c */ - -void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { - fe t0; - fe_add(r->X, p->Y, p->X); - fe_sub(r->Y, p->Y, p->X); - fe_mul(r->Z, r->X, q->YplusX); - fe_mul(r->Y, r->Y, q->YminusX); - fe_mul(r->T, q->T2d, p->T); - fe_mul(r->X, p->Z, q->Z); - fe_add(t0, r->X, r->X); - fe_sub(r->X, r->Z, r->Y); - fe_add(r->Y, r->Z, r->Y); - fe_add(r->Z, t0, r->T); - fe_sub(r->T, t0, r->T); -} - -/* From ge_double_scalarmult.c, modified */ - -static void slide(signed char *r, const unsigned char *a) { - int i; - int b; - int k; - - for (i = 0; i < 256; ++i) { - r[i] = 1 & (a[i >> 3] >> (i & 7)); - } - - for (i = 0; i < 256; ++i) { - if (r[i]) { - for (b = 1; b <= 6 && i + b < 256; ++b) { - if (r[i + b]) { - if (r[i] + (r[i + b] << b) <= 15) { - r[i] += r[i + b] << b; r[i + b] = 0; - } else if (r[i] - (r[i + b] << b) >= -15) { - r[i] -= r[i + b] << b; - for (k = i + b; k < 256; ++k) { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else - break; - } - } - } - } -} - -void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s) { - ge_p1p1 t; - ge_p3 s2, u; - ge_p3_to_cached(&r[0], s); - ge_p3_dbl(&t, s); ge_p1p1_to_p3(&s2, &t); - ge_add(&t, &s2, &r[0]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[1], &u); - ge_add(&t, &s2, &r[1]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[2], &u); - ge_add(&t, &s2, &r[2]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[3], &u); - ge_add(&t, &s2, &r[3]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[4], &u); - ge_add(&t, &s2, &r[4]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[5], &u); - ge_add(&t, &s2, &r[5]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[6], &u); - ge_add(&t, &s2, &r[6]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[7], &u); -} - -/* -r = a * A + b * B -where a = a[0]+256*a[1]+...+256^31 a[31]. -and b = b[0]+256*b[1]+...+256^31 b[31]. -B is the Ed25519 base point (x,4/5) with x positive. -*/ - -void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { - signed char aslide[256]; - signed char bslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - int i; - - slide(aslide, a); - slide(bslide, b); - ge_dsm_precomp(Ai, A); - - ge_p2_0(r); - - for (i = 255; i >= 0; --i) { - if (aslide[i] || bslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, r); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_madd(&t, &u, &ge_Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]); - } - - ge_p1p1_to_p2(r, &t); - } -} - -/* -r = a * A + b * B -where a = a[0]+256*a[1]+...+256^31 a[31]. -and b = b[0]+256*b[1]+...+256^31 b[31]. -B is the Ed25519 base point (x,4/5) with x positive. -*/ - -void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { - signed char aslide[256]; - signed char bslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r_p2; - int i; - - slide(aslide, a); - slide(bslide, b); - ge_dsm_precomp(Ai, A); - - ge_p2_0(&r_p2); - - for (i = 255; i >= 0; --i) { - if (aslide[i] || bslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, &r_p2); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_madd(&t, &u, &ge_Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]); - } - - if (i != 0) - ge_p1p1_to_p2(&r_p2, &t); - else - ge_p1p1_to_p3(r, &t); // last step - } -} - -void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A) { - signed char aslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r_p2; - int i; - - slide(aslide, a); - ge_dsm_precomp(Ai, A); - - ge_p2_0(&r_p2); - ge_p3_0(r); - - for (i = 255; i >= 0; --i) { - if (aslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, &r_p2); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i] / 2]); - } - else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); - } - - if (i != 0) - ge_p1p1_to_p2(&r_p2, &t); - else - ge_p1p1_to_p3(r, &t); // last step - } -} - - -/* From ge_frombytes.c, modified */ - -int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) { - fe u; - fe v; - fe vxx; - fe check; - - /* From fe_frombytes.c */ - - int64_t h0 = load_4(s); - int64_t h1 = load_3(s + 4) << 6; - int64_t h2 = load_3(s + 7) << 5; - int64_t h3 = load_3(s + 10) << 3; - int64_t h4 = load_3(s + 13) << 2; - int64_t h5 = load_4(s + 16); - int64_t h6 = load_3(s + 20) << 7; - int64_t h7 = load_3(s + 23) << 5; - int64_t h8 = load_3(s + 26) << 4; - int64_t h9 = (load_3(s + 29) & 8388607) << 2; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - /* Validate the number to be canonical */ - if (h9 == 33554428 && h8 == 268435440 && h7 == 536870880 && h6 == 2147483520 && - h5 == 4294967295 && h4 == 67108860 && h3 == 134217720 && h2 == 536870880 && - h1 == 1073741760 && h0 >= 4294967277) { - return -1; - } - - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - h->Y[0] = h0; - h->Y[1] = h1; - h->Y[2] = h2; - h->Y[3] = h3; - h->Y[4] = h4; - h->Y[5] = h5; - h->Y[6] = h6; - h->Y[7] = h7; - h->Y[8] = h8; - h->Y[9] = h9; - - /* End fe_frombytes.c */ - - fe_1(h->Z); - fe_sq(u, h->Y); - fe_mul(v, u, fe_d); - fe_sub(u, u, h->Z); /* u = y^2-1 */ - fe_add(v, v, h->Z); /* v = dy^2+1 */ - - fe_divpowm1(h->X, u, v); /* x = uv^3(uv^7)^((q-5)/8) */ - - fe_sq(vxx, h->X); - fe_mul(vxx, vxx, v); - fe_sub(check, vxx, u); /* vx^2-u */ - if (fe_isnonzero(check)) { - fe_add(check, vxx, u); /* vx^2+u */ - if (fe_isnonzero(check)) { - return -1; - } - fe_mul(h->X, h->X, fe_sqrtm1); - } - - if (fe_isnegative(h->X) != (s[31] >> 7)) { - /* If x = 0, the sign must be positive */ - if (!fe_isnonzero(h->X)) { - return -1; - } - fe_neg(h->X, h->X); - } - - fe_mul(h->T, h->X, h->Y); - return 0; -} - -/* From ge_madd.c */ - -/* -r = p + q -*/ - -static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { - fe t0; - fe_add(r->X, p->Y, p->X); - fe_sub(r->Y, p->Y, p->X); - fe_mul(r->Z, r->X, q->yplusx); - fe_mul(r->Y, r->Y, q->yminusx); - fe_mul(r->T, q->xy2d, p->T); - fe_add(t0, p->Z, p->Z); - fe_sub(r->X, r->Z, r->Y); - fe_add(r->Y, r->Z, r->Y); - fe_add(r->Z, t0, r->T); - fe_sub(r->T, t0, r->T); -} - -/* From ge_msub.c */ - -/* -r = p - q -*/ - -static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { - fe t0; - fe_add(r->X, p->Y, p->X); - fe_sub(r->Y, p->Y, p->X); - fe_mul(r->Z, r->X, q->yminusx); - fe_mul(r->Y, r->Y, q->yplusx); - fe_mul(r->T, q->xy2d, p->T); - fe_add(t0, p->Z, p->Z); - fe_sub(r->X, r->Z, r->Y); - fe_add(r->Y, r->Z, r->Y); - fe_sub(r->Z, t0, r->T); - fe_add(r->T, t0, r->T); -} - -/* From ge_p1p1_to_p2.c */ - -/* -r = p -*/ - -void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { - fe_mul(r->X, p->X, p->T); - fe_mul(r->Y, p->Y, p->Z); - fe_mul(r->Z, p->Z, p->T); -} - -/* From ge_p1p1_to_p3.c */ - -/* -r = p -*/ - -void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { - fe_mul(r->X, p->X, p->T); - fe_mul(r->Y, p->Y, p->Z); - fe_mul(r->Z, p->Z, p->T); - fe_mul(r->T, p->X, p->Y); -} - -/* From ge_p2_0.c */ - -static void ge_p2_0(ge_p2 *h) { - fe_0(h->X); - fe_1(h->Y); - fe_1(h->Z); -} - -/* From ge_p2_dbl.c */ - -/* -r = 2 * p -*/ - -void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { - fe t0; - fe_sq(r->X, p->X); - fe_sq(r->Z, p->Y); - fe_sq2(r->T, p->Z); - fe_add(r->Y, p->X, p->Y); - fe_sq(t0, r->Y); - fe_add(r->Y, r->Z, r->X); - fe_sub(r->Z, r->Z, r->X); - fe_sub(r->X, t0, r->Y); - fe_sub(r->T, r->T, r->Z); -} - -/* From ge_p3_0.c */ - -void ge_p3_0(ge_p3 *h) { - fe_0(h->X); - fe_1(h->Y); - fe_1(h->Z); - fe_0(h->T); -} - -/* From ge_p3_dbl.c */ - -/* -r = 2 * p -*/ - -static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { - ge_p2 q; - ge_p3_to_p2(&q, p); - ge_p2_dbl(r, &q); -} - -/* From ge_p3_to_cached.c */ - -/* -r = p -*/ - -void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { - fe_add(r->YplusX, p->Y, p->X); - fe_sub(r->YminusX, p->Y, p->X); - fe_copy(r->Z, p->Z); - fe_mul(r->T2d, p->T, fe_d2); -} - -/* From ge_p3_to_p2.c */ - -/* -r = p -*/ - -void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { - fe_copy(r->X, p->X); - fe_copy(r->Y, p->Y); - fe_copy(r->Z, p->Z); -} - -/* From ge_p3_tobytes.c */ - -void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) { - fe recip; - fe x; - fe y; - - fe_invert(recip, h->Z); - fe_mul(x, h->X, recip); - fe_mul(y, h->Y, recip); - fe_tobytes(s, y); - s[31] ^= fe_isnegative(x) << 7; -} - -/* From ge_precomp_0.c */ - -static void ge_precomp_0(ge_precomp *h) { - fe_1(h->yplusx); - fe_1(h->yminusx); - fe_0(h->xy2d); -} - -/* From ge_scalarmult_base.c */ - -static unsigned char equal(signed char b, signed char c) { - unsigned char ub = b; - unsigned char uc = c; - unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ - uint32_t y = x; /* 0: yes; 1..255: no */ - y -= 1; /* 4294967295: yes; 0..254: no */ - y >>= 31; /* 1: yes; 0: no */ - return y; -} - -static unsigned char negative(signed char b) { - unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ - x >>= 63; /* 1: yes; 0: no */ - return x; -} - -static void ge_precomp_cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) { - fe_cmov(t->yplusx, u->yplusx, b); - fe_cmov(t->yminusx, u->yminusx, b); - fe_cmov(t->xy2d, u->xy2d, b); -} - -static void select(ge_precomp *t, int pos, signed char b) { - ge_precomp minust; - unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); - - ge_precomp_0(t); - ge_precomp_cmov(t, &ge_base[pos][0], equal(babs, 1)); - ge_precomp_cmov(t, &ge_base[pos][1], equal(babs, 2)); - ge_precomp_cmov(t, &ge_base[pos][2], equal(babs, 3)); - ge_precomp_cmov(t, &ge_base[pos][3], equal(babs, 4)); - ge_precomp_cmov(t, &ge_base[pos][4], equal(babs, 5)); - ge_precomp_cmov(t, &ge_base[pos][5], equal(babs, 6)); - ge_precomp_cmov(t, &ge_base[pos][6], equal(babs, 7)); - ge_precomp_cmov(t, &ge_base[pos][7], equal(babs, 8)); - fe_copy(minust.yplusx, t->yminusx); - fe_copy(minust.yminusx, t->yplusx); - fe_neg(minust.xy2d, t->xy2d); - ge_precomp_cmov(t, &minust, bnegative); -} - -/* -h = a * B -where a = a[0]+256*a[1]+...+256^31 a[31] -B is the Ed25519 base point (x,4/5) with x positive. - -Preconditions: - a[31] <= 127 -*/ - -void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { - signed char e[64]; - signed char carry; - ge_p1p1 r; - ge_p2 s; - ge_precomp t; - int i; - - for (i = 0; i < 32; ++i) { - e[2 * i + 0] = (a[i] >> 0) & 15; - e[2 * i + 1] = (a[i] >> 4) & 15; - } - /* each e[i] is between 0 and 15 */ - /* e[63] is between 0 and 7 */ - - carry = 0; - for (i = 0; i < 63; ++i) { - e[i] += carry; - carry = e[i] + 8; - carry >>= 4; - e[i] -= carry << 4; - } - e[63] += carry; - /* each e[i] is between -8 and 8 */ - - ge_p3_0(h); - for (i = 1; i < 64; i += 2) { - select(&t, i / 2, e[i]); - ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); - } - - ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r); - ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); - ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); - ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r); - - for (i = 0; i < 64; i += 2) { - select(&t, i / 2, e[i]); - ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); - } -} - -/* From ge_sub.c */ - -/* -r = p - q -*/ - -void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { - fe t0; - fe_add(r->X, p->Y, p->X); - fe_sub(r->Y, p->Y, p->X); - fe_mul(r->Z, r->X, q->YminusX); - fe_mul(r->Y, r->Y, q->YplusX); - fe_mul(r->T, q->T2d, p->T); - fe_mul(r->X, p->Z, q->Z); - fe_add(t0, r->X, r->X); - fe_sub(r->X, r->Z, r->Y); - fe_add(r->Y, r->Z, r->Y); - fe_sub(r->Z, t0, r->T); - fe_add(r->T, t0, r->T); -} - -/* From ge_tobytes.c */ - -void ge_tobytes(unsigned char *s, const ge_p2 *h) { - fe recip; - fe x; - fe y; - - fe_invert(recip, h->Z); - fe_mul(x, h->X, recip); - fe_mul(y, h->Y, recip); - fe_tobytes(s, y); - s[31] ^= fe_isnegative(x) << 7; -} - -/* From sc_reduce.c */ - -/* -Input: - s[0]+256*s[1]+...+256^63*s[63] = s - -Output: - s[0]+256*s[1]+...+256^31*s[31] = s mod l - where l = 2^252 + 27742317777372353535851937790883648493. - Overwrites s in place. -*/ - -void sc_reduce(unsigned char *s) { - int64_t s0 = 2097151 & load_3(s); - int64_t s1 = 2097151 & (load_4(s + 2) >> 5); - int64_t s2 = 2097151 & (load_3(s + 5) >> 2); - int64_t s3 = 2097151 & (load_4(s + 7) >> 7); - int64_t s4 = 2097151 & (load_4(s + 10) >> 4); - int64_t s5 = 2097151 & (load_3(s + 13) >> 1); - int64_t s6 = 2097151 & (load_4(s + 15) >> 6); - int64_t s7 = 2097151 & (load_3(s + 18) >> 3); - int64_t s8 = 2097151 & load_3(s + 21); - int64_t s9 = 2097151 & (load_4(s + 23) >> 5); - int64_t s10 = 2097151 & (load_3(s + 26) >> 2); - int64_t s11 = 2097151 & (load_4(s + 28) >> 7); - int64_t s12 = 2097151 & (load_4(s + 31) >> 4); - int64_t s13 = 2097151 & (load_3(s + 34) >> 1); - int64_t s14 = 2097151 & (load_4(s + 36) >> 6); - int64_t s15 = 2097151 & (load_3(s + 39) >> 3); - int64_t s16 = 2097151 & load_3(s + 42); - int64_t s17 = 2097151 & (load_4(s + 44) >> 5); - int64_t s18 = 2097151 & (load_3(s + 47) >> 2); - int64_t s19 = 2097151 & (load_4(s + 49) >> 7); - int64_t s20 = 2097151 & (load_4(s + 52) >> 4); - int64_t s21 = 2097151 & (load_3(s + 55) >> 1); - int64_t s22 = 2097151 & (load_4(s + 57) >> 6); - int64_t s23 = (load_4(s + 60) >> 3); - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* New code */ - -static void fe_divpowm1(fe r, const fe u, const fe v) { - fe v3, uv7, t0, t1, t2; - int i; - - fe_sq(v3, v); - fe_mul(v3, v3, v); /* v3 = v^3 */ - fe_sq(uv7, v3); - fe_mul(uv7, uv7, v); - fe_mul(uv7, uv7, u); /* uv7 = uv^7 */ - - /*fe_pow22523(uv7, uv7);*/ - - /* From fe_pow22523.c */ - - fe_sq(t0, uv7); - fe_sq(t1, t0); - fe_sq(t1, t1); - fe_mul(t1, uv7, t1); - fe_mul(t0, t0, t1); - fe_sq(t0, t0); - fe_mul(t0, t1, t0); - fe_sq(t1, t0); - for (i = 0; i < 4; ++i) { - fe_sq(t1, t1); - } - fe_mul(t0, t1, t0); - fe_sq(t1, t0); - for (i = 0; i < 9; ++i) { - fe_sq(t1, t1); - } - fe_mul(t1, t1, t0); - fe_sq(t2, t1); - for (i = 0; i < 19; ++i) { - fe_sq(t2, t2); - } - fe_mul(t1, t2, t1); - for (i = 0; i < 10; ++i) { - fe_sq(t1, t1); - } - fe_mul(t0, t1, t0); - fe_sq(t1, t0); - for (i = 0; i < 49; ++i) { - fe_sq(t1, t1); - } - fe_mul(t1, t1, t0); - fe_sq(t2, t1); - for (i = 0; i < 99; ++i) { - fe_sq(t2, t2); - } - fe_mul(t1, t2, t1); - for (i = 0; i < 50; ++i) { - fe_sq(t1, t1); - } - fe_mul(t0, t1, t0); - fe_sq(t0, t0); - fe_sq(t0, t0); - fe_mul(t0, t0, uv7); - - /* End fe_pow22523.c */ - /* t0 = (uv^7)^((q-5)/8) */ - fe_mul(t0, t0, v3); - fe_mul(r, t0, u); /* u^(m+1)v^(-(m+1)) */ -} - -static void ge_cached_0(ge_cached *r) { - fe_1(r->YplusX); - fe_1(r->YminusX); - fe_1(r->Z); - fe_0(r->T2d); -} - -static void ge_cached_cmov(ge_cached *t, const ge_cached *u, unsigned char b) { - fe_cmov(t->YplusX, u->YplusX, b); - fe_cmov(t->YminusX, u->YminusX, b); - fe_cmov(t->Z, u->Z, b); - fe_cmov(t->T2d, u->T2d, b); -} - -/* Assumes that a[31] <= 127 */ -void ge_scalarmult(ge_p2 *r, const unsigned char *a, const ge_p3 *A) { - signed char e[64]; - int carry, carry2, i; - ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */ - ge_p1p1 t; - ge_p3 u; - - carry = 0; /* 0..1 */ - for (i = 0; i < 31; i++) { - carry += a[i]; /* 0..256 */ - carry2 = (carry + 8) >> 4; /* 0..16 */ - e[2 * i] = carry - (carry2 << 4); /* -8..7 */ - carry = (carry2 + 8) >> 4; /* 0..1 */ - e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ - } - carry += a[31]; /* 0..128 */ - carry2 = (carry + 8) >> 4; /* 0..8 */ - e[62] = carry - (carry2 << 4); /* -8..7 */ - e[63] = carry2; /* 0..8 */ - - ge_p3_to_cached(&Ai[0], A); - for (i = 0; i < 7; i++) { - ge_add(&t, A, &Ai[i]); - ge_p1p1_to_p3(&u, &t); - ge_p3_to_cached(&Ai[i + 1], &u); - } - - ge_p2_0(r); - for (i = 63; i >= 0; i--) { - signed char b = e[i]; - unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); - ge_cached cur, minuscur; - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p3(&u, &t); - ge_cached_0(&cur); - ge_cached_cmov(&cur, &Ai[0], equal(babs, 1)); - ge_cached_cmov(&cur, &Ai[1], equal(babs, 2)); - ge_cached_cmov(&cur, &Ai[2], equal(babs, 3)); - ge_cached_cmov(&cur, &Ai[3], equal(babs, 4)); - ge_cached_cmov(&cur, &Ai[4], equal(babs, 5)); - ge_cached_cmov(&cur, &Ai[5], equal(babs, 6)); - ge_cached_cmov(&cur, &Ai[6], equal(babs, 7)); - ge_cached_cmov(&cur, &Ai[7], equal(babs, 8)); - fe_copy(minuscur.YplusX, cur.YminusX); - fe_copy(minuscur.YminusX, cur.YplusX); - fe_copy(minuscur.Z, cur.Z); - fe_neg(minuscur.T2d, cur.T2d); - ge_cached_cmov(&cur, &minuscur, bnegative); - ge_add(&t, &u, &cur); - ge_p1p1_to_p2(r, &t); - } -} - -/* Assumes that a[31] <= 127 */ -void ge_scalarmult_p3(ge_p3 *result, const unsigned char *a, const ge_p3 *A) { - signed char e[64]; - int carry, carry2, i; - ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r_tmp; - ge_p2* r = &r_tmp; - - carry = 0; /* 0..1 */ - for (i = 0; i < 31; i++) { - carry += a[i]; /* 0..256 */ - carry2 = (carry + 8) >> 4; /* 0..16 */ - e[2 * i] = carry - (carry2 << 4); /* -8..7 */ - carry = (carry2 + 8) >> 4; /* 0..1 */ - e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ - } - carry += a[31]; /* 0..128 */ - carry2 = (carry + 8) >> 4; /* 0..8 */ - e[62] = carry - (carry2 << 4); /* -8..7 */ - e[63] = carry2; /* 0..8 */ - - ge_p3_to_cached(&Ai[0], A); - for (i = 0; i < 7; i++) { - ge_add(&t, A, &Ai[i]); - ge_p1p1_to_p3(&u, &t); - ge_p3_to_cached(&Ai[i + 1], &u); - } - - ge_p2_0(r); - for (i = 63; i >= 0; i--) { - signed char b = e[i]; - unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); - ge_cached cur, minuscur; - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p2(r, &t); - ge_p2_dbl(&t, r); - ge_p1p1_to_p3(&u, &t); - ge_cached_0(&cur); - ge_cached_cmov(&cur, &Ai[0], equal(babs, 1)); - ge_cached_cmov(&cur, &Ai[1], equal(babs, 2)); - ge_cached_cmov(&cur, &Ai[2], equal(babs, 3)); - ge_cached_cmov(&cur, &Ai[3], equal(babs, 4)); - ge_cached_cmov(&cur, &Ai[4], equal(babs, 5)); - ge_cached_cmov(&cur, &Ai[5], equal(babs, 6)); - ge_cached_cmov(&cur, &Ai[6], equal(babs, 7)); - ge_cached_cmov(&cur, &Ai[7], equal(babs, 8)); - fe_copy(minuscur.YplusX, cur.YminusX); - fe_copy(minuscur.YminusX, cur.YplusX); - fe_copy(minuscur.Z, cur.Z); - fe_neg(minuscur.T2d, cur.T2d); - ge_cached_cmov(&cur, &minuscur, bnegative); - ge_add(&t, &u, &cur); - if (i > 0) - ge_p1p1_to_p2(r, &t); - else - ge_p1p1_to_p3(result, &t); // last iteration - } -} - -void ge_double_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b, const ge_dsmp Bi) { - signed char aslide[256]; - signed char bslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - int i; - - slide(aslide, a); - slide(bslide, b); - ge_dsm_precomp(Ai, A); - - ge_p2_0(r); - - for (i = 255; i >= 0; --i) { - if (aslide[i] || bslide[i]) break; - } - - for (; i >= 0; --i) { - ge_p2_dbl(&t, r); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Bi[(-bslide[i])/2]); - } - - ge_p1p1_to_p2(r, &t); - } -} - -void ge_mul8(ge_p1p1 *r, const ge_p2 *t) { - ge_p2 u; - ge_p2_dbl(r, t); - ge_p1p1_to_p2(&u, r); - ge_p2_dbl(r, &u); - ge_p1p1_to_p2(&u, r); - ge_p2_dbl(r, &u); -} - -void ge_fromfe_frombytes_vartime(ge_p2 *r, const unsigned char *s) { - fe u, v, w, x, y, z; - unsigned char sign; - - /* From fe_frombytes.c */ - - int64_t h0 = load_4(s); - int64_t h1 = load_3(s + 4) << 6; - int64_t h2 = load_3(s + 7) << 5; - int64_t h3 = load_3(s + 10) << 3; - int64_t h4 = load_3(s + 13) << 2; - int64_t h5 = load_4(s + 16); - int64_t h6 = load_3(s + 20) << 7; - int64_t h7 = load_3(s + 23) << 5; - int64_t h8 = load_3(s + 26) << 4; - int64_t h9 = load_3(s + 29) << 2; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - u[0] = h0; - u[1] = h1; - u[2] = h2; - u[3] = h3; - u[4] = h4; - u[5] = h5; - u[6] = h6; - u[7] = h7; - u[8] = h8; - u[9] = h9; - - /* End fe_frombytes.c */ - - fe_sq2(v, u); /* v = 2 * u^2 */ - fe_1(w); /* w = 1 */ - fe_add(w, v, w); /* w = 2 * u^2 + 1 */ - fe_sq(x, w); /* x = w^2 */ - fe_mul(y, fe_ma2, v); /* y = -A^2 * (2 * u^2) = -2 * A^2 * u^2 n.b. A = 2 * (1 - d) / (1 + d) = 486662*/ - fe_add(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */ - fe_divpowm1(r->X, w, x); /* r->X = (w / x)^(m + 1) */ - fe_sq(y, r->X); /* y = (w / x)^(2*(m + 1)) */ - fe_mul(x, y, x); /* x = (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */ - fe_sub(y, w, x); /* y = 2 * u^2 + 1 - (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */ - fe_copy(z, fe_ma); /* z = -A */ - if (fe_isnonzero(y)) { - fe_add(y, w, x); - if (fe_isnonzero(y)) { - goto negative; - } else { - fe_mul(r->X, r->X, fe_fffb1); - } - } else { - fe_mul(r->X, r->X, fe_fffb2); - } - fe_mul(r->X, r->X, u); /* u * sqrt(2 * A * (A + 2) * w / x) */ - fe_mul(z, z, v); /* -2 * A * u^2 */ - sign = 0; - goto setsign; -negative: - fe_mul(x, x, fe_sqrtm1); - fe_sub(y, w, x); - if (fe_isnonzero(y)) { - assert((fe_add(y, w, x), !fe_isnonzero(y))); - fe_mul(r->X, r->X, fe_fffb3); - } else { - fe_mul(r->X, r->X, fe_fffb4); - } - /* r->X = sqrt(A * (A + 2) * w / x) */ - /* z = -A */ - sign = 1; -setsign: - if (fe_isnegative(r->X) != sign) { - assert(fe_isnonzero(r->X)); - fe_neg(r->X, r->X); - } - fe_add(r->Z, z, w); - fe_sub(r->Y, z, w); - fe_mul(r->X, r->X, r->Z); -#if !defined(NDEBUG) - { - fe check_x, check_y, check_iz, check_v; - fe_invert(check_iz, r->Z); - fe_mul(check_x, r->X, check_iz); - fe_mul(check_y, r->Y, check_iz); - fe_sq(check_x, check_x); - fe_sq(check_y, check_y); - fe_mul(check_v, check_x, check_y); - fe_mul(check_v, fe_d, check_v); - fe_add(check_v, check_v, check_x); - fe_sub(check_v, check_v, check_y); - fe_1(check_x); - fe_add(check_v, check_v, check_x); - assert(!fe_isnonzero(check_v)); - } -#endif -} - -void sc_0(unsigned char *s) { - int i; - for (i = 0; i < 32; i++) { - s[i] = 0; - } -} - -void sc_reduce32(unsigned char *s) { - int64_t s0 = 2097151 & load_3(s); - int64_t s1 = 2097151 & (load_4(s + 2) >> 5); - int64_t s2 = 2097151 & (load_3(s + 5) >> 2); - int64_t s3 = 2097151 & (load_4(s + 7) >> 7); - int64_t s4 = 2097151 & (load_4(s + 10) >> 4); - int64_t s5 = 2097151 & (load_3(s + 13) >> 1); - int64_t s6 = 2097151 & (load_4(s + 15) >> 6); - int64_t s7 = 2097151 & (load_3(s + 18) >> 3); - int64_t s8 = 2097151 & load_3(s + 21); - int64_t s9 = 2097151 & (load_4(s + 23) >> 5); - int64_t s10 = 2097151 & (load_3(s + 26) >> 2); - int64_t s11 = (load_4(s + 28) >> 7); - int64_t s12 = 0; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -void sc_add(unsigned char *s, const unsigned char *a, const unsigned char *b) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t s0 = a0 + b0; - int64_t s1 = a1 + b1; - int64_t s2 = a2 + b2; - int64_t s3 = a3 + b3; - int64_t s4 = a4 + b4; - int64_t s5 = a5 + b5; - int64_t s6 = a6 + b6; - int64_t s7 = a7 + b7; - int64_t s8 = a8 + b8; - int64_t s9 = a9 + b9; - int64_t s10 = a10 + b10; - int64_t s11 = a11 + b11; - int64_t s12 = 0; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -void sc_sub(unsigned char *s, const unsigned char *a, const unsigned char *b) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t s0 = a0 - b0; - int64_t s1 = a1 - b1; - int64_t s2 = a2 - b2; - int64_t s3 = a3 - b3; - int64_t s4 = a4 - b4; - int64_t s5 = a5 - b5; - int64_t s6 = a6 - b6; - int64_t s7 = a7 - b7; - int64_t s8 = a8 - b8; - int64_t s9 = a9 - b9; - int64_t s10 = a10 - b10; - int64_t s11 = a11 - b11; - int64_t s12 = 0; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* -Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - c[0]+256*c[1]+...+256^31*c[31] = c - -Output: - s[0]+256*s[1]+...+256^31*s[31] = (c-ab) mod l - where l = 2^252 + 27742317777372353535851937790883648493. -*/ - -void sc_mulsub(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - int64_t c0 = 2097151 & load_3(c); - int64_t c1 = 2097151 & (load_4(c + 2) >> 5); - int64_t c2 = 2097151 & (load_3(c + 5) >> 2); - int64_t c3 = 2097151 & (load_4(c + 7) >> 7); - int64_t c4 = 2097151 & (load_4(c + 10) >> 4); - int64_t c5 = 2097151 & (load_3(c + 13) >> 1); - int64_t c6 = 2097151 & (load_4(c + 15) >> 6); - int64_t c7 = 2097151 & (load_3(c + 18) >> 3); - int64_t c8 = 2097151 & load_3(c + 21); - int64_t c9 = 2097151 & (load_4(c + 23) >> 5); - int64_t c10 = 2097151 & (load_3(c + 26) >> 2); - int64_t c11 = (load_4(c + 28) >> 7); - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; - - s0 = c0 - a0*b0; - s1 = c1 - (a0*b1 + a1*b0); - s2 = c2 - (a0*b2 + a1*b1 + a2*b0); - s3 = c3 - (a0*b3 + a1*b2 + a2*b1 + a3*b0); - s4 = c4 - (a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0); - s5 = c5 - (a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0); - s6 = c6 - (a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0); - s7 = c7 - (a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0); - s8 = c8 - (a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0); - s9 = c9 - (a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0); - s10 = c10 - (a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0); - s11 = c11 - (a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0); - s12 = -(a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1); - s13 = -(a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2); - s14 = -(a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3); - s15 = -(a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4); - s16 = -(a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5); - s17 = -(a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6); - s18 = -(a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7); - s19 = -(a8*b11 + a9*b10 + a10*b9 + a11*b8); - s20 = -(a9*b11 + a10*b10 + a11*b9); - s21 = -(a10*b11 + a11*b10); - s22 = -a11*b11; - s23 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* Assumes that a != INT64_MIN */ -static int64_t signum(int64_t a) { - return (a >> 63) - ((-a) >> 63); -} - -int sc_check(const unsigned char *s) { - int64_t s0 = load_4(s); - int64_t s1 = load_4(s + 4); - int64_t s2 = load_4(s + 8); - int64_t s3 = load_4(s + 12); - int64_t s4 = load_4(s + 16); - int64_t s5 = load_4(s + 20); - int64_t s6 = load_4(s + 24); - int64_t s7 = load_4(s + 28); - return (signum(1559614444 - s0) + (signum(1477600026 - s1) << 1) + (signum(2734136534 - s2) << 2) + (signum(350157278 - s3) << 3) + (signum(-s4) << 4) + (signum(-s5) << 5) + (signum(-s6) << 6) + (signum(268435456 - s7) << 7)) >> 8; -} - -int sc_isnonzero(const unsigned char *s) { - return (((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] | - s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] | - s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] | - s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1; -} - -// see implmentation of ge_frombytes_vartime above -void fe_frombytes(fe h, const unsigned char *s) -{ - /* From fe_frombytes.c */ - - int64_t h0 = load_4(s); - int64_t h1 = load_3(s + 4) << 6; - int64_t h2 = load_3(s + 7) << 5; - int64_t h3 = load_3(s + 10) << 3; - int64_t h4 = load_3(s + 13) << 2; - int64_t h5 = load_4(s + 16); - int64_t h6 = load_3(s + 20) << 7; - int64_t h7 = load_3(s + 23) << 5; - int64_t h8 = load_3(s + 26) << 4; - int64_t h9 = (load_3(s + 29) & 8388607) << 2; - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - - carry9 = (h9 + (int64_t)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (int64_t)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (int64_t)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (int64_t)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (int64_t)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (int64_t)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (int64_t)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (int64_t)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (int64_t)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (int64_t)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -// Old naive and slow implementation using sc_mulsub -void sc_mul(unsigned char *s, const unsigned char *a, const unsigned char *b) -{ - unsigned char c[32]; - unsigned char neg_a[32]; - sc_0(c); - sc_sub(neg_a, c, a); - // s = c - ab - sc_mulsub(s, neg_a, b, c); -} -*/ - -/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ -/* - Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - * - Output: - s[0]+256*s[1]+...+256^31*s[31] = (ab) mod l - where l = 2^252 + 27742317777372353535851937790883648493. - */ -void sc_mul(unsigned char* s, const unsigned char* a, const unsigned char* b) -{ - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; - - s0 = a0 * b0; - s1 = a0 * b1 + a1 * b0; - s2 = a0 * b2 + a1 * b1 + a2 * b0; - s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; - s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; - s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; - s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; - s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + - a6 * b1 + a7 * b0; - s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + - a6 * b2 + a7 * b1 + a8 * b0; - s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + - a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; - s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + - a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; - s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + - a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; - s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + - a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; - s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + - a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; - s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + - a9 * b5 + a10 * b4 + a11 * b3; - s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + - a10 * b5 + a11 * b4; - s16 = - a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; - s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; - s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; - s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; - s20 = a9 * b11 + a10 * b10 + a11 * b9; - s21 = a10 * b11 + a11 * b10; - s22 = a11 * b11; - s23 = 0; - - carry0 = (s0 + (int64_t)(1L << 20)) >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry2 = (s2 + (int64_t)(1L << 20)) >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry4 = (s4 + (int64_t)(1L << 20)) >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry12 = (s12 + (int64_t)(1L << 20)) >> 21; - s13 += carry12; - s12 -= carry12 * ((uint64_t)1L << 21); - carry14 = (s14 + (int64_t)(1L << 20)) >> 21; - s15 += carry14; - s14 -= carry14 * ((uint64_t)1L << 21); - carry16 = (s16 + (int64_t)(1L << 20)) >> 21; - s17 += carry16; - s16 -= carry16 * ((uint64_t)1L << 21); - carry18 = (s18 + (int64_t)(1L << 20)) >> 21; - s19 += carry18; - s18 -= carry18 * ((uint64_t)1L << 21); - carry20 = (s20 + (int64_t)(1L << 20)) >> 21; - s21 += carry20; - s20 -= carry20 * ((uint64_t)1L << 21); - carry22 = (s22 + (int64_t)(1L << 20)) >> 21; - s23 += carry22; - s22 -= carry22 * ((uint64_t)1L << 21); - - carry1 = (s1 + (int64_t)(1L << 20)) >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry3 = (s3 + (int64_t)(1L << 20)) >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry5 = (s5 + (int64_t)(1L << 20)) >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - carry13 = (s13 + (int64_t)(1L << 20)) >> 21; - s14 += carry13; - s13 -= carry13 * ((uint64_t)1L << 21); - carry15 = (s15 + (int64_t)(1L << 20)) >> 21; - s16 += carry15; - s15 -= carry15 * ((uint64_t)1L << 21); - carry17 = (s17 + (int64_t)(1L << 20)) >> 21; - s18 += carry17; - s17 -= carry17 * ((uint64_t)1L << 21); - carry19 = (s19 + (int64_t)(1L << 20)) >> 21; - s20 += carry19; - s19 -= carry19 * ((uint64_t)1L << 21); - carry21 = (s21 + (int64_t)(1L << 20)) >> 21; - s22 += carry21; - s21 -= carry21 * ((uint64_t)1L << 21); - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry12 = (s12 + (int64_t)(1L << 20)) >> 21; - s13 += carry12; - s12 -= carry12 * ((uint64_t)1L << 21); - carry14 = (s14 + (int64_t)(1L << 20)) >> 21; - s15 += carry14; - s14 -= carry14 * ((uint64_t)1L << 21); - carry16 = (s16 + (int64_t)(1L << 20)) >> 21; - s17 += carry16; - s16 -= carry16 * ((uint64_t)1L << 21); - - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - carry13 = (s13 + (int64_t)(1L << 20)) >> 21; - s14 += carry13; - s13 -= carry13 * ((uint64_t)1L << 21); - carry15 = (s15 + (int64_t)(1L << 20)) >> 21; - s16 += carry15; - s15 -= carry15 * ((uint64_t)1L << 21); - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (int64_t)(1L << 20)) >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry2 = (s2 + (int64_t)(1L << 20)) >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry4 = (s4 + (int64_t)(1L << 20)) >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - - carry1 = (s1 + (int64_t)(1L << 20)) >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry3 = (s3 + (int64_t)(1L << 20)) >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry5 = (s5 + (int64_t)(1L << 20)) >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry1 = s1 >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry2 = s2 >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry3 = s3 >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry4 = s4 >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry5 = s5 >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry6 = s6 >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry7 = s7 >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry8 = s8 >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry9 = s9 >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry10 = s10 >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry11 = s11 >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry1 = s1 >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry2 = s2 >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry3 = s3 >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry4 = s4 >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry5 = s5 >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry6 = s6 >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry7 = s7 >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry8 = s8 >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry9 = s9 >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry10 = s10 >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 * ((uint64_t)1 << 5)); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 * ((uint64_t)1 << 2)); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 * ((uint64_t)1 << 7)); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 * ((uint64_t)1 << 4)); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 * ((uint64_t)1 << 1)); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 * ((uint64_t)1 << 6)); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 * ((uint64_t)1 << 3)); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 * ((uint64_t)1 << 5)); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 * ((uint64_t)1 << 2)); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 * ((uint64_t)1 << 7)); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ -/* - Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - c[0]+256*c[1]+...+256^31*c[31] = c - * - Output: - s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l - where l = 2^252 + 27742317777372353535851937790883648493. - */ -void sc_muladd(unsigned char* s, const unsigned char* a, - const unsigned char* b, const unsigned char* c) -{ - int64_t a0 = 2097151 & load_3(a); - int64_t a1 = 2097151 & (load_4(a + 2) >> 5); - int64_t a2 = 2097151 & (load_3(a + 5) >> 2); - int64_t a3 = 2097151 & (load_4(a + 7) >> 7); - int64_t a4 = 2097151 & (load_4(a + 10) >> 4); - int64_t a5 = 2097151 & (load_3(a + 13) >> 1); - int64_t a6 = 2097151 & (load_4(a + 15) >> 6); - int64_t a7 = 2097151 & (load_3(a + 18) >> 3); - int64_t a8 = 2097151 & load_3(a + 21); - int64_t a9 = 2097151 & (load_4(a + 23) >> 5); - int64_t a10 = 2097151 & (load_3(a + 26) >> 2); - int64_t a11 = (load_4(a + 28) >> 7); - - int64_t b0 = 2097151 & load_3(b); - int64_t b1 = 2097151 & (load_4(b + 2) >> 5); - int64_t b2 = 2097151 & (load_3(b + 5) >> 2); - int64_t b3 = 2097151 & (load_4(b + 7) >> 7); - int64_t b4 = 2097151 & (load_4(b + 10) >> 4); - int64_t b5 = 2097151 & (load_3(b + 13) >> 1); - int64_t b6 = 2097151 & (load_4(b + 15) >> 6); - int64_t b7 = 2097151 & (load_3(b + 18) >> 3); - int64_t b8 = 2097151 & load_3(b + 21); - int64_t b9 = 2097151 & (load_4(b + 23) >> 5); - int64_t b10 = 2097151 & (load_3(b + 26) >> 2); - int64_t b11 = (load_4(b + 28) >> 7); - - int64_t c0 = 2097151 & load_3(c); - int64_t c1 = 2097151 & (load_4(c + 2) >> 5); - int64_t c2 = 2097151 & (load_3(c + 5) >> 2); - int64_t c3 = 2097151 & (load_4(c + 7) >> 7); - int64_t c4 = 2097151 & (load_4(c + 10) >> 4); - int64_t c5 = 2097151 & (load_3(c + 13) >> 1); - int64_t c6 = 2097151 & (load_4(c + 15) >> 6); - int64_t c7 = 2097151 & (load_3(c + 18) >> 3); - int64_t c8 = 2097151 & load_3(c + 21); - int64_t c9 = 2097151 & (load_4(c + 23) >> 5); - int64_t c10 = 2097151 & (load_3(c + 26) >> 2); - int64_t c11 = (load_4(c + 28) >> 7); - - int64_t s0; - int64_t s1; - int64_t s2; - int64_t s3; - int64_t s4; - int64_t s5; - int64_t s6; - int64_t s7; - int64_t s8; - int64_t s9; - int64_t s10; - int64_t s11; - int64_t s12; - int64_t s13; - int64_t s14; - int64_t s15; - int64_t s16; - int64_t s17; - int64_t s18; - int64_t s19; - int64_t s20; - int64_t s21; - int64_t s22; - int64_t s23; - - int64_t carry0; - int64_t carry1; - int64_t carry2; - int64_t carry3; - int64_t carry4; - int64_t carry5; - int64_t carry6; - int64_t carry7; - int64_t carry8; - int64_t carry9; - int64_t carry10; - int64_t carry11; - int64_t carry12; - int64_t carry13; - int64_t carry14; - int64_t carry15; - int64_t carry16; - int64_t carry17; - int64_t carry18; - int64_t carry19; - int64_t carry20; - int64_t carry21; - int64_t carry22; - - s0 = c0 + a0 * b0; - s1 = c1 + a0 * b1 + a1 * b0; - s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; - s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; - s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; - s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; - s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + - a6 * b0; - s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + - a6 * b1 + a7 * b0; - s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + - a6 * b2 + a7 * b1 + a8 * b0; - s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + - a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; - s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + - a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; - s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + - a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; - s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + - a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; - s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + - a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; - s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + - a9 * b5 + a10 * b4 + a11 * b3; - s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + - a10 * b5 + a11 * b4; - s16 = - a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; - s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; - s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; - s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; - s20 = a9 * b11 + a10 * b10 + a11 * b9; - s21 = a10 * b11 + a11 * b10; - s22 = a11 * b11; - s23 = 0; - - carry0 = (s0 + (int64_t)(1L << 20)) >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry2 = (s2 + (int64_t)(1L << 20)) >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry4 = (s4 + (int64_t)(1L << 20)) >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry12 = (s12 + (int64_t)(1L << 20)) >> 21; - s13 += carry12; - s12 -= carry12 * ((uint64_t)1L << 21); - carry14 = (s14 + (int64_t)(1L << 20)) >> 21; - s15 += carry14; - s14 -= carry14 * ((uint64_t)1L << 21); - carry16 = (s16 + (int64_t)(1L << 20)) >> 21; - s17 += carry16; - s16 -= carry16 * ((uint64_t)1L << 21); - carry18 = (s18 + (int64_t)(1L << 20)) >> 21; - s19 += carry18; - s18 -= carry18 * ((uint64_t)1L << 21); - carry20 = (s20 + (int64_t)(1L << 20)) >> 21; - s21 += carry20; - s20 -= carry20 * ((uint64_t)1L << 21); - carry22 = (s22 + (int64_t)(1L << 20)) >> 21; - s23 += carry22; - s22 -= carry22 * ((uint64_t)1L << 21); - - carry1 = (s1 + (int64_t)(1L << 20)) >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry3 = (s3 + (int64_t)(1L << 20)) >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry5 = (s5 + (int64_t)(1L << 20)) >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - carry13 = (s13 + (int64_t)(1L << 20)) >> 21; - s14 += carry13; - s13 -= carry13 * ((uint64_t)1L << 21); - carry15 = (s15 + (int64_t)(1L << 20)) >> 21; - s16 += carry15; - s15 -= carry15 * ((uint64_t)1L << 21); - carry17 = (s17 + (int64_t)(1L << 20)) >> 21; - s18 += carry17; - s17 -= carry17 * ((uint64_t)1L << 21); - carry19 = (s19 + (int64_t)(1L << 20)) >> 21; - s20 += carry19; - s19 -= carry19 * ((uint64_t)1L << 21); - carry21 = (s21 + (int64_t)(1L << 20)) >> 21; - s22 += carry21; - s21 -= carry21 * ((uint64_t)1L << 21); - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry12 = (s12 + (int64_t)(1L << 20)) >> 21; - s13 += carry12; - s12 -= carry12 * ((uint64_t)1L << 21); - carry14 = (s14 + (int64_t)(1L << 20)) >> 21; - s15 += carry14; - s14 -= carry14 * ((uint64_t)1L << 21); - carry16 = (s16 + (int64_t)(1L << 20)) >> 21; - s17 += carry16; - s16 -= carry16 * ((uint64_t)1L << 21); - - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - carry13 = (s13 + (int64_t)(1L << 20)) >> 21; - s14 += carry13; - s13 -= carry13 * ((uint64_t)1L << 21); - carry15 = (s15 + (int64_t)(1L << 20)) >> 21; - s16 += carry15; - s15 -= carry15 * ((uint64_t)1L << 21); - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (int64_t)(1L << 20)) >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry2 = (s2 + (int64_t)(1L << 20)) >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry4 = (s4 + (int64_t)(1L << 20)) >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry6 = (s6 + (int64_t)(1L << 20)) >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry8 = (s8 + (int64_t)(1L << 20)) >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry10 = (s10 + (int64_t)(1L << 20)) >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - - carry1 = (s1 + (int64_t)(1L << 20)) >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry3 = (s3 + (int64_t)(1L << 20)) >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry5 = (s5 + (int64_t)(1L << 20)) >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry7 = (s7 + (int64_t)(1L << 20)) >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry9 = (s9 + (int64_t)(1L << 20)) >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry11 = (s11 + (int64_t)(1L << 20)) >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry1 = s1 >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry2 = s2 >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry3 = s3 >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry4 = s4 >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry5 = s5 >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry6 = s6 >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry7 = s7 >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry8 = s8 >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry9 = s9 >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry10 = s10 >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - carry11 = s11 >> 21; - s12 += carry11; - s11 -= carry11 * ((uint64_t)1L << 21); - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - - carry0 = s0 >> 21; - s1 += carry0; - s0 -= carry0 * ((uint64_t)1L << 21); - carry1 = s1 >> 21; - s2 += carry1; - s1 -= carry1 * ((uint64_t)1L << 21); - carry2 = s2 >> 21; - s3 += carry2; - s2 -= carry2 * ((uint64_t)1L << 21); - carry3 = s3 >> 21; - s4 += carry3; - s3 -= carry3 * ((uint64_t)1L << 21); - carry4 = s4 >> 21; - s5 += carry4; - s4 -= carry4 * ((uint64_t)1L << 21); - carry5 = s5 >> 21; - s6 += carry5; - s5 -= carry5 * ((uint64_t)1L << 21); - carry6 = s6 >> 21; - s7 += carry6; - s6 -= carry6 * ((uint64_t)1L << 21); - carry7 = s7 >> 21; - s8 += carry7; - s7 -= carry7 * ((uint64_t)1L << 21); - carry8 = s8 >> 21; - s9 += carry8; - s8 -= carry8 * ((uint64_t)1L << 21); - carry9 = s9 >> 21; - s10 += carry9; - s9 -= carry9 * ((uint64_t)1L << 21); - carry10 = s10 >> 21; - s11 += carry10; - s10 -= carry10 * ((uint64_t)1L << 21); - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 * ((uint64_t)1 << 5)); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 * ((uint64_t)1 << 2)); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 * ((uint64_t)1 << 7)); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 * ((uint64_t)1 << 4)); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 * ((uint64_t)1 << 1)); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 * ((uint64_t)1 << 6)); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 * ((uint64_t)1 << 3)); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 * ((uint64_t)1 << 5)); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 * ((uint64_t)1 << 2)); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 * ((uint64_t)1 << 7)); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ -void sc_sqmul(unsigned char s[32], const int n, const unsigned char a[32]) -{ - int i; - for (i = 0; i < n; ++i) - sc_mul(s, s, s); - sc_mul(s, s, a); -} - -/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ -void sc_invert(unsigned char* recip, const unsigned char* s) -{ - unsigned char _10[32], _100[32], _1000[32], _10000[32], _100000[32], - _1000000[32], _10010011[32], _10010111[32], _100110[32], _1010[32], - _1010000[32], _1010011[32], _1011[32], _10110[32], _10111101[32], - _11[32], _1100011[32], _1100111[32], _11010011[32], _1101011[32], - _11100111[32], _11101011[32], _11110101[32]; - - sc_mul(_10, s, s); - sc_mul(_11, s, _10); - sc_mul(_100, s, _11); - sc_mul(_1000, _100, _100); - sc_mul(_1010, _10, _1000); - sc_mul(_1011, s, _1010); - sc_mul(_10000, _1000, _1000); - sc_mul(_10110, _1011, _1011); - sc_mul(_100000, _1010, _10110); - sc_mul(_100110, _10000, _10110); - sc_mul(_1000000, _100000, _100000); - sc_mul(_1010000, _10000, _1000000); - sc_mul(_1010011, _11, _1010000); - sc_mul(_1100011, _10000, _1010011); - sc_mul(_1100111, _100, _1100011); - sc_mul(_1101011, _100, _1100111); - sc_mul(_10010011, _1000000, _1010011); - sc_mul(_10010111, _100, _10010011); - sc_mul(_10111101, _100110, _10010111); - sc_mul(_11010011, _10110, _10111101); - sc_mul(_11100111, _1010000, _10010111); - sc_mul(_11101011, _100, _11100111); - sc_mul(_11110101, _1010, _11101011); - - sc_mul(recip, _1011, _11110101); - - sc_sqmul(recip, 126, _1010011); - - sc_sqmul(recip, 9, _10); - sc_mul(recip, recip, _11110101); - sc_sqmul(recip, 7, _1100111); - sc_sqmul(recip, 9, _11110101); - sc_sqmul(recip, 11, _10111101); - sc_sqmul(recip, 8, _11100111); - sc_sqmul(recip, 9, _1101011); - sc_sqmul(recip, 6, _1011); - sc_sqmul(recip, 14, _10010011); - sc_sqmul(recip, 10, _1100011); - sc_sqmul(recip, 9, _10010111); - sc_sqmul(recip, 10, _11110101); - sc_sqmul(recip, 8, _11010011); - sc_sqmul(recip, 8, _11101011); -} - -/* - In: t (x, y, z) - Out: r (x, t, z, t) - - Note: expensive conversion because of fe_invert -*/ -void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t) -{ - fe_copy(r->X, t->X); - fe_copy(r->Y, t->Y); - fe_copy(r->Z, t->Z); - fe_invert(r->T, t->Z); - fe_mul(r->T, r->T, t->Y); - fe_mul(r->T, r->T, t->X); -} - - -/* - In: data -- points to 'size' bytes of data - Out: res = Hp(data) - where Hp = 8 * ge_fromfe_frombytes_vartime(cn_fast_hash(data)) -*/ -void ge_bytes_hash_to_ec(ge_p3 *res, const void *data, size_t size) -{ - unsigned char h[HASH_SIZE]; - ge_p2 point; - ge_p1p1 point2; - - cn_fast_hash(data, size, (char*)h); - ge_fromfe_frombytes_vartime(&point, &h[0]); - /*ge_p2_to_p3(res, &point); -- can be used to avoid multiplication by 8 for debugging */ - ge_mul8(&point2, &point); - ge_p1p1_to_p3(res, &point2); -} - -void ge_bytes_hash_to_ec_32(ge_p3 *res, const unsigned char *ge_bytes) -{ - ge_bytes_hash_to_ec(res, ge_bytes, 32); -} - -void ge_mul8_p3(ge_p3 *r, const ge_p3 *t) -{ - ge_p1p1 p1; - ge_p2 p2; - - // TODO: consider removing the following copy, replace &p2 by (ge_p2*)t as it's ugly but possible - ge_p3_to_p2(&p2, t); // copying - - ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub - ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul - ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub - ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul - ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub - - ge_p1p1_to_p3(r, &p1); // 4 fe_mul -} - - -// returns the most non-zero index of r -int slide_v2(signed char *r, const unsigned char *a) -{ - int i; - int b; - int k; - int nzi = 0; - - for (i = 0; i < 256; ++i) { - r[i] = 1 & (a[i >> 3] >> (i & 7)); - } - - for (i = 0; i < 256; ++i) { - if (r[i]) { - for (b = 1; b <= 6 && i + b < 256; ++b) { - if (r[i + b]) { - if (r[i] + (r[i + b] << b) <= 15) { - r[i] += r[i + b] << b; r[i + b] = 0; - } - else if (r[i] - (r[i + b] << b) >= -15) { - r[i] -= r[i + b] << b; - for (k = i + b; k < 256; ++k) { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } - else - break; - } - } - if (r[i]) - nzi = i; - } - } - - return nzi; -} - -void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A) -{ - signed char aslide[256]; - ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ - ge_p1p1 t; - ge_p3 u; - ge_p2 r_p2; - int i; - - i = slide_v2(aslide, a); - - if (i == 0) - { - ge_p3_0(r); - return; - } - - ge_dsm_precomp(Ai, A); - ge_p2_0(&r_p2); - - for (; i >= 0; --i) - { - ge_p2_dbl(&t, &r_p2); - if (aslide[i] > 0) - { - ge_p1p1_to_p3(&u, &t); - ge_add(&t, &u, &Ai[aslide[i] / 2]); - } - else if (aslide[i] < 0) - { - ge_p1p1_to_p3(&u, &t); - ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); - } - if (i != 0) - ge_p1p1_to_p2(&r_p2, &t); - else - ge_p1p1_to_p3(r, &t); - } -} diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h deleted file mode 100644 index 6fb6917..0000000 --- a/src/crypto/crypto-ops.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2018-2021 Zano Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include // size_t - -/* From fe.h */ - -typedef int32_t fe[10]; - -/* From ge.h */ - -typedef struct { - fe X; - fe Y; - fe Z; -} ge_p2; - -typedef struct { - fe X; - fe Y; - fe Z; - fe T; -} ge_p3; - -typedef struct { - fe X; - fe Y; - fe Z; - fe T; -} ge_p1p1; - -typedef struct { - fe yplusx; - fe yminusx; - fe xy2d; -} ge_precomp; - -typedef struct { - fe YplusX; - fe YminusX; - fe Z; - fe T2d; -} ge_cached; - -/* From ge_add.c */ - -void ge_add(ge_p1p1 *, const ge_p3 *, const ge_cached *); - -/* From ge_double_scalarmult.c, modified */ - -typedef ge_cached ge_dsmp[8]; -extern const ge_precomp ge_Bi[8]; -void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s); -void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *); - -/* From ge_frombytes.c, modified */ - -extern const fe fe_sqrtm1; -extern const fe fe_d; -int ge_frombytes_vartime(ge_p3 *, const unsigned char *); - -/* From ge_p1p1_to_p2.c */ - -void ge_p1p1_to_p2(ge_p2 *, const ge_p1p1 *); - -/* From ge_p1p1_to_p3.c */ - -void ge_p1p1_to_p3(ge_p3 *, const ge_p1p1 *); - -/* From ge_p2_dbl.c */ - -void ge_p2_dbl(ge_p1p1 *, const ge_p2 *); - -/* From ge_p3_to_cached.c */ - -extern const fe fe_d2; -void ge_p3_to_cached(ge_cached *, const ge_p3 *); - -/* From ge_p3_to_p2.c */ - -void ge_p3_to_p2(ge_p2 *, const ge_p3 *); - -/* From ge_p3_tobytes.c */ - -void ge_p3_tobytes(unsigned char *, const ge_p3 *); - -/* From ge_scalarmult_base.c */ - -extern const ge_precomp ge_base[32][8]; -void ge_scalarmult_base(ge_p3 *, const unsigned char *); - -/* From ge_tobytes.c */ - -void ge_tobytes(unsigned char *, const ge_p2 *); - -/* From sc_reduce.c */ - -void sc_reduce(unsigned char *); - -/* New code */ - -void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *); -void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *); -void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp); -void ge_mul8(ge_p1p1 *, const ge_p2 *); -void ge_mul8_p3(ge_p3 *, const ge_p3 *); -void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *); -void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t); -void ge_bytes_hash_to_ec(ge_p3 *, const void *, size_t); -void ge_bytes_hash_to_ec_32(ge_p3 *, const unsigned char *); - -void ge_p3_0(ge_p3 *h); -void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *); -void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); -void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A); -void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A); - -extern const fe fe_ma2; -extern const fe fe_ma; -extern const fe fe_fffb1; -extern const fe fe_fffb2; -extern const fe fe_fffb3; -extern const fe fe_fffb4; - -void sc_0(unsigned char *); -void sc_reduce32(unsigned char *); -void sc_add(unsigned char *, const unsigned char *, const unsigned char *); -void sc_sub(unsigned char *, const unsigned char *, const unsigned char *); -void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *); -void sc_mul(unsigned char *, const unsigned char *, const unsigned char *); -void sc_muladd(unsigned char* s, const unsigned char* a, const unsigned char* b, const unsigned char* c); -int sc_check(const unsigned char *); -int sc_isnonzero(const unsigned char *); /* Doesn't normalize */ -void sc_invert(unsigned char*, const unsigned char*); - -void fe_sq(fe h, const fe f); -int fe_isnonzero(const fe f); -int fe_cmp(const fe a, const fe b); -void fe_mul(fe, const fe, const fe); -void fe_frombytes(fe h, const unsigned char *s); -void fe_invert(fe out, const fe z); -void fe_tobytes(unsigned char *s, const fe h); diff --git a/src/crypto/crypto-sugar.cpp b/src/crypto/crypto-sugar.cpp deleted file mode 100644 index 4774e9b..0000000 --- a/src/crypto/crypto-sugar.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2020-2021 Zano Project -// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com) -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// Note: This file originates from tests/functional_tests/crypto_tests.cpp - -#include "crypto-sugar.h" - -namespace crypto -{ - - const point_g_t c_point_G; - - const scalar_t c_scalar_1 = { 1 }; - const scalar_t c_scalar_L = { 0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 }; - const scalar_t c_scalar_Lm1 = { 0x5812631a5cf5d3ec, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 }; - const scalar_t c_scalar_P = { 0xffffffffffffffed, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff }; - const scalar_t c_scalar_Pm1 = { 0xffffffffffffffec, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff }; - const scalar_t c_scalar_256m1 = { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff }; - const scalar_t c_scalar_1div8 = { 0x6106e529e2dc2f79, 0x07d39db37d1cdad0, 0x0, 0x0600000000000000 }; - - const point_t c_point_H = { 0x05087c1f5b9b32d6, 0x00547595f445c3b5, 0x764df64578552f2a, 0x8a49a651e0e0da45 }; // == Hp(G), this is being checked in bpp_basics - const point_t c_point_0 = point_t(point_t::tag_zero()); - -} // namespace crypto diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h deleted file mode 100644 index 600fe91..0000000 --- a/src/crypto/crypto-sugar.h +++ /dev/null @@ -1,1067 +0,0 @@ -// Copyright (c) 2020-2021 Zano Project -// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com) -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// Note: This file originates from tests/functional_tests/crypto_tests.cpp -#pragma once -#include -#include -#include "crypto.h" - -namespace crypto -{ - extern "C" - { -#include "crypto/crypto-ops.h" - } // extern "C" - - - - // - // Helpers - // - - template - std::string pod_to_hex_reversed(const pod_t &h) - { - constexpr char hexmap[] = "0123456789abcdef"; - const unsigned char* data = reinterpret_cast(&h); - size_t len = sizeof h; - - std::string s(len * 2, ' '); - for (size_t i = 0; i < len; ++i) { - s[2 * i] = hexmap[data[len - 1 - i] >> 4]; - s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F]; - } - - return s; - } - - template - std::string pod_to_hex(const pod_t &h) - { - constexpr char hexmap[] = "0123456789abcdef"; - const unsigned char* data = reinterpret_cast(&h); - size_t len = sizeof h; - - std::string s(len * 2, ' '); - for (size_t i = 0; i < len; ++i) { - s[2 * i] = hexmap[data[i] >> 4]; - s[2 * i + 1] = hexmap[data[i] & 0x0F]; - } - - return s; - } - - template - std::string pod_to_hex_comma_separated_bytes(const pod_t &h) - { - std::stringstream ss; - ss << std::hex << std::setfill('0'); - size_t len = sizeof h; - const unsigned char* p = (const unsigned char*)&h; - for (size_t i = 0; i < len; ++i) - { - ss << "0x" << std::setw(2) << static_cast(p[i]); - if (i + 1 != len) - ss << ", "; - } - return ss.str(); - } - - template - std::string pod_to_hex_comma_separated_uint64(const pod_t &h) - { - static_assert((sizeof h) % 8 == 0, "size of h should be a multiple of 64 bit"); - size_t len = (sizeof h) / 8; - std::stringstream ss; - ss << std::hex << std::setfill('0'); - const uint64_t* p = (const uint64_t*)&h; - for (size_t i = 0; i < len; ++i) - { - ss << "0x" << std::setw(16) << static_cast(p[i]); - if (i + 1 != len) - ss << ", "; - } - return ss.str(); - } - - template - bool parse_tpod_from_hex_string(const std::string& hex_str, t_pod_type& t_pod) - { - static const int16_t char_map[256] = { // 0-9, a-f, A-F is only allowed - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00 - 0x1F - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 0x20 - 0x3F - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x40 - 0x5F - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x60 - 0x7F - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x80 - 0x9F - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xA0 - 0xBF - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xC0 - 0xDF - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // 0xE0 - 0xFF - - size_t pod_size = sizeof t_pod; - uint8_t *p = reinterpret_cast(&t_pod); - - if (hex_str.size() != 2 * pod_size) - return false; - - for (size_t i = 0; i < pod_size; ++i) - { - int16_t hi = char_map[static_cast(hex_str[2 * i])]; - int16_t lo = char_map[static_cast(hex_str[2 * i + 1])]; - if (hi < 0 || lo < 0) - { - // invalid characters in hex_str - memset(p, 0, pod_size); - return false; - } - p[i] = static_cast(hi * 16 + lo); // write byte to pod - } - return true; - } - - template - t_pod_type parse_tpod_from_hex_string(const std::string& hex_str) - { - t_pod_type t_pod = AUTO_VAL_INIT(t_pod); - parse_tpod_from_hex_string(hex_str, t_pod); - return t_pod; - } - - // - // scalar_t - holds a 256-bit scalar, normally in [0..L-1] - // - struct alignas(32) scalar_t - { - union - { - uint64_t m_u64[4]; - unsigned char m_s[32]; - }; - - scalar_t() - {} - - // won't check scalar range validity (< L) - scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) - { - m_u64[0] = a0; - m_u64[1] = a1; - m_u64[2] = a2; - m_u64[3] = a3; - } - - // won't check scalar range validity (< L) - scalar_t(const unsigned char(&v)[32]) - { - memcpy(m_s, v, 32); - } - - // won't check secret key validity (sk < L) - scalar_t(const crypto::secret_key& sk) - { - from_secret_key(sk); - } - - // copy data and reduce - scalar_t(const crypto::hash& hash) - { - m_u64[0] = ((uint64_t*)&hash)[0]; - m_u64[1] = ((uint64_t*)&hash)[1]; - m_u64[2] = ((uint64_t*)&hash)[2]; - m_u64[3] = ((uint64_t*)&hash)[3]; - sc_reduce32(&m_s[0]); - } - - scalar_t(uint64_t v) - { - zero(); - m_u64[0] = v; - // do not need to call reduce as 2^64 < L - } - - // copy at most 256 bits (32 bytes) and reduce - template - explicit scalar_t(const boost::multiprecision::number& bigint) - { - zero(); - unsigned int bytes_to_copy = bigint.backend().size() * bigint.backend().limb_bits / 8; - if (bytes_to_copy > sizeof *this) - bytes_to_copy = sizeof *this; - memcpy(&m_s[0], bigint.backend().limbs(), bytes_to_copy); - sc_reduce32(&m_s[0]); - } - - unsigned char* data() - { - return &m_s[0]; - } - - const unsigned char* data() const - { - return &m_s[0]; - } - - crypto::secret_key &as_secret_key() - { - return *(crypto::secret_key*)&m_s[0]; - } - - const crypto::secret_key& as_secret_key() const - { - return *(const crypto::secret_key*)&m_s[0]; - } - - operator crypto::secret_key() const - { - crypto::secret_key result; - memcpy(result.data, &m_s, sizeof result.data); - return result; - } - - void from_secret_key(const crypto::secret_key& sk) - { - uint64_t *p_sk64 = (uint64_t*)&sk; - m_u64[0] = p_sk64[0]; - m_u64[1] = p_sk64[1]; - m_u64[2] = p_sk64[2]; - m_u64[3] = p_sk64[3]; - // assuming secret key is correct (< L), so we don't need to call reduce here - } - - void zero() - { - m_u64[0] = 0; - m_u64[1] = 0; - m_u64[2] = 0; - m_u64[3] = 0; - } - - // genrate 0 <= x < L - static scalar_t random() - { - scalar_t result; - result.make_random(); - return result; - } - - // genrate 0 <= x < L - void make_random() - { - unsigned char tmp[64]; - crypto::generate_random_bytes(64, tmp); - sc_reduce(tmp); - memcpy(&m_s, tmp, sizeof m_s); - - /* // for tests - int x[8] = { rand() }; - crypto::cn_fast_hash(&x, sizeof x, *(crypto::hash*)this); - sc_reduce32(m_s); - */ - } - - bool is_zero() const - { - return sc_isnonzero(&m_s[0]) == 0; - } - - bool is_reduced() const - { - return sc_check(&m_s[0]) == 0; - } - - void reduce() - { - sc_reduce32(&m_s[0]); - } - - scalar_t operator+(const scalar_t& v) const - { - scalar_t result; - sc_add(&result.m_s[0], &m_s[0], &v.m_s[0]); - return result; - } - - scalar_t& operator+=(const scalar_t& v) - { - sc_add(&m_s[0], &m_s[0], &v.m_s[0]); - return *this; - } - - scalar_t operator-(const scalar_t& v) const - { - scalar_t result; - sc_sub(&result.m_s[0], &m_s[0], &v.m_s[0]); - return result; - } - - scalar_t& operator-=(const scalar_t& v) - { - sc_sub(&m_s[0], &m_s[0], &v.m_s[0]); - return *this; - } - - scalar_t operator*(const scalar_t& v) const - { - scalar_t result; - sc_mul(result.m_s, m_s, v.m_s); - return result; - } - - scalar_t& operator*=(const scalar_t& v) - { - sc_mul(m_s, m_s, v.m_s); - return *this; - } - - // returns this = a * b - scalar_t& assign_mul(const scalar_t& a, const scalar_t& b) - { - sc_mul(m_s, a.m_s, b.m_s); - return *this; - } - - /* - I think it has bad symantic (operator-like), consider rename/reimplement -- sowle - */ - // returns this * b + c - scalar_t muladd(const scalar_t& b, const scalar_t& c) const - { - scalar_t result; - sc_muladd(result.m_s, m_s, b.m_s, c.m_s); - return result; - } - - // returns this = a * b + c - scalar_t& assign_muladd(const scalar_t& a, const scalar_t& b, const scalar_t& c) - { - sc_muladd(m_s, a.m_s, b.m_s, c.m_s); - return *this; - } - - scalar_t reciprocal() const - { - scalar_t result; - sc_invert(result.m_s, m_s); - return result; - } - - scalar_t operator/(const scalar_t& v) const - { - return operator*(v.reciprocal()); - } - - scalar_t& operator/=(const scalar_t& v) - { - scalar_t reciprocal; - sc_invert(&reciprocal.m_s[0], &v.m_s[0]); - sc_mul(&m_s[0], &m_s[0], &reciprocal.m_s[0]); - return *this; - } - - bool operator==(const scalar_t& rhs) const - { - return - m_u64[0] == rhs.m_u64[0] && - m_u64[1] == rhs.m_u64[1] && - m_u64[2] == rhs.m_u64[2] && - m_u64[3] == rhs.m_u64[3]; - } - - bool operator!=(const scalar_t& rhs) const - { - return - m_u64[0] != rhs.m_u64[0] || - m_u64[1] != rhs.m_u64[1] || - m_u64[2] != rhs.m_u64[2] || - m_u64[3] != rhs.m_u64[3]; - } - - bool operator<(const scalar_t& rhs) const - { - if (m_u64[3] < rhs.m_u64[3]) return true; - if (m_u64[3] > rhs.m_u64[3]) return false; - if (m_u64[2] < rhs.m_u64[2]) return true; - if (m_u64[2] > rhs.m_u64[2]) return false; - if (m_u64[1] < rhs.m_u64[1]) return true; - if (m_u64[1] > rhs.m_u64[1]) return false; - if (m_u64[0] < rhs.m_u64[0]) return true; - if (m_u64[0] > rhs.m_u64[0]) return false; - return false; - } - - bool operator>(const scalar_t& rhs) const - { - if (m_u64[3] < rhs.m_u64[3]) return false; - if (m_u64[3] > rhs.m_u64[3]) return true; - if (m_u64[2] < rhs.m_u64[2]) return false; - if (m_u64[2] > rhs.m_u64[2]) return true; - if (m_u64[1] < rhs.m_u64[1]) return false; - if (m_u64[1] > rhs.m_u64[1]) return true; - if (m_u64[0] < rhs.m_u64[0]) return false; - if (m_u64[0] > rhs.m_u64[0]) return true; - return false; - } - - friend std::ostream& operator<<(std::ostream& ss, const scalar_t &v) - { - return ss << pod_to_hex(v); - } - - std::string to_string_as_hex_number() const - { - return pod_to_hex_reversed(*this); - } - - std::string to_string_as_secret_key() const - { - return pod_to_hex(*this); - } - - template - MP_type as_boost_mp_type() const - { - MP_type result = 0; - static_assert(sizeof result >= sizeof *this, "size missmatch"); // to avoid using types less than uint256_t - unsigned int sz = sizeof *this / sizeof(boost::multiprecision::limb_type); - result.backend().resize(sz, sz); - memcpy(result.backend().limbs(), &m_s[0], sizeof *this); - result.backend().normalize(); - return result; - } - - }; // struct scalar_t - - // - // Global constants - // - - extern const scalar_t c_scalar_1; - extern const scalar_t c_scalar_L; - extern const scalar_t c_scalar_Lm1; - extern const scalar_t c_scalar_P; - extern const scalar_t c_scalar_Pm1; - extern const scalar_t c_scalar_256m1; - extern const scalar_t c_scalar_1div8; - - // - // - // - struct point_t - { - struct tag_zero {}; - - // A point(x, y) is represented in extended homogeneous coordinates (X, Y, Z, T) - // with x = X / Z, y = Y / Z, x * y = T / Z. - ge_p3 m_p3; - - point_t() - { - } - - explicit point_t(const crypto::public_key& pk) - { - if (!from_public_key(pk)) - zero(); - } - - point_t(const unsigned char(&v)[32]) - { - static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch"); - if (!from_public_key(*(const crypto::public_key*)v)) - zero(); - } - - point_t(const uint64_t(&v)[4]) - { - static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch"); - if (!from_public_key(*(const crypto::public_key*)v)) - zero(); - } - - point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) - { - crypto::public_key pk; - ((uint64_t*)&pk)[0] = a0; - ((uint64_t*)&pk)[1] = a1; - ((uint64_t*)&pk)[2] = a2; - ((uint64_t*)&pk)[3] = a3; - - if (!from_public_key(pk)) - zero(); - } - - explicit point_t(tag_zero&&) - { - zero(); - } - - // as we're using additive notation, zero means identity group element here and after - void zero() - { - ge_p3_0(&m_p3); - } - - bool is_zero() const - { - // (0, 1) ~ (0, z, z, 0) - return fe_isnonzero(m_p3.X) * fe_cmp(m_p3.Y, m_p3.Z) == 0; - } - - bool is_in_main_subgroup() const - { - return (c_scalar_L * *this).is_zero(); - } - - bool from_public_key(const crypto::public_key& pk) - { - return ge_frombytes_vartime(&m_p3, reinterpret_cast(&pk)) == 0; - } - - bool from_key_image(const crypto::key_image& ki) - { - return ge_frombytes_vartime(&m_p3, reinterpret_cast(&ki)) == 0; - } - - bool from_string(const std::string& str) - { - crypto::public_key pk; - if (!parse_tpod_from_hex_string(str, pk)) - return false; - return from_public_key(pk); - } - - crypto::public_key to_public_key() const - { - crypto::public_key result; - ge_p3_tobytes((unsigned char*)&result, &m_p3); - return result; - } - - void to_public_key(crypto::public_key& result) const - { - ge_p3_tobytes((unsigned char*)&result, &m_p3); - } - - crypto::key_image to_key_image() const - { - crypto::key_image result; - ge_p3_tobytes((unsigned char*)&result, &m_p3); - return result; - } - - point_t operator+(const point_t& rhs) const - { - point_t result; - ge_cached rhs_c; - ge_p1p1 t; - ge_p3_to_cached(&rhs_c, &rhs.m_p3); - ge_add(&t, &m_p3, &rhs_c); - ge_p1p1_to_p3(&result.m_p3, &t); - return result; - } - - point_t& operator+=(const point_t& rhs) - { - ge_cached rhs_c; - ge_p1p1 t; - ge_p3_to_cached(&rhs_c, &rhs.m_p3); - ge_add(&t, &m_p3, &rhs_c); - ge_p1p1_to_p3(&m_p3, &t); - return *this; - } - - point_t operator-(const point_t& rhs) const - { - point_t result; - ge_cached rhs_c; - ge_p1p1 t; - ge_p3_to_cached(&rhs_c, &rhs.m_p3); - ge_sub(&t, &m_p3, &rhs_c); - ge_p1p1_to_p3(&result.m_p3, &t); - return result; - } - - point_t& operator-=(const point_t& rhs) - { - ge_cached rhs_c; - ge_p1p1 t; - ge_p3_to_cached(&rhs_c, &rhs.m_p3); - ge_sub(&t, &m_p3, &rhs_c); - ge_p1p1_to_p3(&m_p3, &t); - return *this; - } - - friend point_t operator*(const scalar_t& lhs, const point_t& rhs) - { - point_t result; - ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3); - return result; - } - - point_t& operator*=(const scalar_t& rhs) - { - // TODO: ge_scalarmult_vartime_p3 - ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3); - return *this; - } - - friend point_t operator/(const point_t& lhs, const scalar_t& rhs) - { - point_t result; - scalar_t reciprocal; - sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]); - ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3); - return result; - } - - point_t& modify_mul8() - { - ge_mul8_p3(&m_p3, &m_p3); - return *this; - } - - // returns a * this + G - point_t mul_plus_G(const scalar_t& a) const - { - static const unsigned char one[32] = { 1 }; - static_assert(sizeof one == sizeof(crypto::ec_scalar), "size missmatch"); - - point_t result; - ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &one[0]); - return result; - } - - // returns a * this + b * G - point_t mul_plus_G(const scalar_t& a, const scalar_t& b) const - { - point_t result; - ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &b.m_s[0]); - return result; - } - - // *this = a * A + b * G - void assign_mul_plus_G(const scalar_t& a, const point_t& A, const scalar_t& b) - { - ge_double_scalarmult_base_vartime_p3(&m_p3, &a.m_s[0], &A.m_p3, &b.m_s[0]); - } - - friend bool operator==(const point_t& lhs, const point_t& rhs) - { - // convert to xy form, then compare components (because (x, y, z, t) representation is not unique) - fe lrecip, lx, ly; - fe rrecip, rx, ry; - - fe_invert(lrecip, lhs.m_p3.Z); - fe_invert(rrecip, rhs.m_p3.Z); - - fe_mul(lx, lhs.m_p3.X, lrecip); - fe_mul(rx, rhs.m_p3.X, rrecip); - if (memcmp(&lx, &rx, sizeof lx) != 0) - return false; - - fe_mul(ly, lhs.m_p3.Y, lrecip); - fe_mul(ry, rhs.m_p3.Y, rrecip); - if (memcmp(&ly, &ry, sizeof ly) != 0) - return false; - - return true; - }; - - friend std::ostream& operator<<(std::ostream& ss, const point_t &v) - { - crypto::public_key pk = v.to_public_key(); - return ss << pod_to_hex(pk); - } - - operator std::string() const - { - crypto::public_key pk = to_public_key(); - return pod_to_hex(pk); - } - - std::string to_string() const - { - crypto::public_key pk = to_public_key(); - return pod_to_hex(pk); - } - - std::string to_hex_comma_separated_bytes_str() const - { - crypto::public_key pk = to_public_key(); - return pod_to_hex_comma_separated_bytes(pk); - } - - std::string to_hex_comma_separated_uint64_str() const - { - crypto::public_key pk = to_public_key(); - return pod_to_hex_comma_separated_uint64(pk); - } - - }; // struct point_t - - - // - // point_g_t -- special type for curve's base point - // - struct point_g_t : public point_t - { - point_g_t() - { - scalar_t one(1); - ge_scalarmult_base(&m_p3, &one.m_s[0]); - } - - friend point_t operator*(const scalar_t& lhs, const point_g_t&) - { - point_t result; - ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]); - return result; - } - - friend point_t operator/(const point_g_t&, const scalar_t& rhs) - { - point_t result; - scalar_t reciprocal; - sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]); - ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]); - return result; - } - - static_assert(sizeof(crypto::public_key) == 32, "size error"); - - }; // struct point_g_t - - - // - // vector of scalars - // - struct scalar_vec_t : public std::vector - { - typedef std::vector super_t; - - scalar_vec_t() {} - scalar_vec_t(size_t n) : super_t(n) {} - scalar_vec_t(std::initializer_list init_list) : super_t(init_list) {} - - bool is_reduced() const - { - for (auto& el : *this) - if (!el.is_reduced()) - return false; - return true; - } - - // add a scalar rhs to each element - scalar_vec_t operator+(const scalar_t& rhs) const - { - scalar_vec_t result(size()); - for (size_t i = 0, n = size(); i < n; ++i) - result[i] = at(i) + rhs; - return result; - } - - // subtract a scalar rhs to each element - scalar_vec_t operator-(const scalar_t& rhs) const - { - scalar_vec_t result(size()); - for (size_t i = 0, n = size(); i < n; ++i) - result[i] = at(i) - rhs; - return result; - } - - // multiply each element of the vector by a scalar - scalar_vec_t operator*(const scalar_t& rhs) const - { - scalar_vec_t result(size()); - for (size_t i = 0, n = size(); i < n; ++i) - result[i] = at(i) * rhs; - return result; - } - - // component-wise multiplication (a.k.a the Hadamard product) (only if their sizes match) - scalar_vec_t operator*(const scalar_vec_t& rhs) const - { - scalar_vec_t result; - const size_t n = size(); - if (n != rhs.size()) - return result; - - result.resize(size()); - for (size_t i = 0; i < n; ++i) - result[i] = at(i) * rhs[i]; - return result; - } - - // add each element of two vectors, but only if their sizes match - scalar_vec_t operator+(const scalar_vec_t& rhs) const - { - scalar_vec_t result; - const size_t n = size(); - if (n != rhs.size()) - return result; - - result.resize(size()); - for (size_t i = 0; i < n; ++i) - result[i] = at(i) + rhs[i]; - return result; - } - - // zeroes all elements - void zero() - { - size_t size_bytes = sizeof(scalar_t) * size(); - memset(data(), 0, size_bytes); - } - - // invert all elements in-place efficiently: 4*N muptiplications + 1 inversion - void invert() - { - // muls muls_rev - // 0: 1 2 3 .. n-1 - // 1: 0 2 3 .. n-1 - // 2: 0 1 3 .. n-1 - // - // n-1: 0 1 2 3 .. n-2 - - const size_t size = this->size(); - - if (size < 2) - { - if (size == 1) - at(0) = at(0).reciprocal(); - return; - } - - scalar_vec_t muls(size), muls_rev(size); - muls[0] = 1; - for (size_t i = 0; i < size - 1; ++i) - muls[i + 1] = at(i) * muls[i]; - - muls_rev[size - 1] = 1; - for (size_t i = size - 1; i != 0; --i) - muls_rev[i - 1] = at(i) * muls_rev[i]; - - scalar_t inv = (muls[size - 1] * at(size - 1)).reciprocal(); - - for (size_t i = 0; i < size; ++i) - at(i) = muls[i] * inv * muls_rev[i]; - } - - scalar_t calc_hs() const; - - }; // scalar_vec_t - - - // treats vector of scalars as an M x N matrix just for convenience - template - struct scalar_mat_t : public scalar_vec_t - { - typedef scalar_vec_t super_t; - static_assert(N > 0, "invalid N value"); - - scalar_mat_t() {} - scalar_mat_t(size_t n) : super_t(n) {} - scalar_mat_t(std::initializer_list init_list) : super_t(init_list) {} - - // matrix accessor M rows x N cols - scalar_t& operator()(size_t row, size_t col) - { - return at(row * N + col); - } - }; // scalar_mat_t - - - - // - // Global constants - // - - extern const point_g_t c_point_G; - - extern const point_t c_point_H; - extern const point_t c_point_0; - - // - // hash functions' helper - // - struct hash_helper_t - { - static scalar_t hs(const scalar_t& s) - { - return scalar_t(crypto::cn_fast_hash(s.data(), sizeof s)); // will reduce mod L - } - - static scalar_t hs(const void* data, size_t size) - { - return scalar_t(crypto::cn_fast_hash(data, size)); // will reduce mod L - } - - static scalar_t hs(const std::string& str) - { - return scalar_t(crypto::cn_fast_hash(str.c_str(), str.size())); // will reduce mod L - } - - struct hs_t - { - hs_t() - { - static_assert(sizeof(scalar_t) == sizeof(crypto::public_key), "unexpected size of data"); - } - - void reserve(size_t elements_count) - { - m_elements.reserve(elements_count); - } - - void resize(size_t elements_count) - { - m_elements.resize(elements_count); - } - - void clear() - { - m_elements.clear(); - } - - void add_scalar(const scalar_t& scalar) - { - m_elements.emplace_back(scalar); - } - - void add_point(const point_t& point) - { - m_elements.emplace_back(point.to_public_key()); - - // faster? - /* static_assert(sizeof point.m_p3 == 5 * sizeof(item_t), "size missmatch"); - const item_t *p = (item_t*)&point.m_p3; - m_elements.emplace_back(p[0]); - m_elements.emplace_back(p[1]); - m_elements.emplace_back(p[2]); - m_elements.emplace_back(p[3]); - m_elements.emplace_back(p[4]); */ - } - - void add_pub_key(const crypto::public_key& pk) - { - m_elements.emplace_back(pk); - } - - scalar_t& access_scalar(size_t index) - { - return m_elements[index].scalar; - } - - public_key& access_public_key(size_t index) - { - return m_elements[index].pk; - } - - void add_points_array(const std::vector& points_array) - { - for (size_t i = 0, size = points_array.size(); i < size; ++i) - add_point(points_array[i]); - } - - void add_pub_keys_array(const std::vector& pub_keys_array) - { - for (size_t i = 0, size = pub_keys_array.size(); i < size; ++i) - m_elements.emplace_back(pub_keys_array[i]); - } - - void add_key_images_array(const std::vector& key_image_array) - { - for (size_t i = 0, size = key_image_array.size(); i < size; ++i) - m_elements.emplace_back(key_image_array[i]); - } - - scalar_t calc_hash(bool clear = true) - { - size_t data_size_bytes = m_elements.size() * sizeof(item_t); - crypto::hash hash; - crypto::cn_fast_hash(m_elements.data(), data_size_bytes, hash); - if (clear) - this->clear(); - return scalar_t(hash); // this will reduce to L - } - - void assign_calc_hash(scalar_t& result, bool clear = true) - { - static_assert(sizeof result == sizeof(crypto::hash), "size missmatch"); - size_t data_size_bytes = m_elements.size() * sizeof(item_t); - crypto::cn_fast_hash(m_elements.data(), data_size_bytes, (crypto::hash&)result); - result.reduce(); - if (clear) - this->clear(); - } - - union item_t - { - item_t() {} - item_t(const scalar_t& scalar) : scalar(scalar) {} - item_t(const crypto::public_key& pk) : pk(pk) {} - item_t(const crypto::key_image& ki) : ki(ki) {} - scalar_t scalar; - crypto::public_key pk; - crypto::key_image ki; - }; - - std::vector m_elements; - }; - - static scalar_t hs(const scalar_t& s, const std::vector& ps0, const std::vector& ps1) - { - hs_t hs_calculator; - hs_calculator.add_scalar(s); - hs_calculator.add_points_array(ps0); - hs_calculator.add_points_array(ps1); - return hs_calculator.calc_hash(); - } - - static scalar_t hs(const crypto::hash& s, const std::vector& ps0, const std::vector& ps1) - { - static_assert(sizeof(crypto::hash) == sizeof(scalar_t), "size missmatch"); - hs_t hs_calculator; - hs_calculator.add_scalar(*reinterpret_cast(&s)); - hs_calculator.add_pub_keys_array(ps0); - hs_calculator.add_key_images_array(ps1); - return hs_calculator.calc_hash(); - } - - static scalar_t hs(const std::vector& ps0, const std::vector& ps1) - { - hs_t hs_calculator; - hs_calculator.add_points_array(ps0); - hs_calculator.add_points_array(ps1); - return hs_calculator.calc_hash(); - } - - static point_t hp(const point_t& p) - { - point_t result; - crypto::public_key pk = p.to_public_key(); - - ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&pk); - - return result; - } - - static point_t hp(const crypto::public_key& p) - { - point_t result; - ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&p); - return result; - } - }; // hash_helper_t struct - - - inline scalar_t scalar_vec_t::calc_hs() const - { - // hs won't touch memory if size is 0, so it's safe - return hash_helper_t::hs(data(), sizeof(scalar_t) * size()); - } - - -} // namespace crypto diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp deleted file mode 100644 index a1e0c64..0000000 --- a/src/crypto/crypto.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/varint.h" -#include "warnings.h" -#include "crypto.h" -#include "hash.h" - -#if !defined(NDEBUG) -# define crypto_assert(expression) assert(expression) -#else -# define crypto_assert(expression) ((void)0) -#endif - -namespace crypto { - - DISABLE_GCC_AND_CLANG_WARNING(strict-aliasing) - const unsigned char Z_[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const unsigned char I_[32] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const unsigned char L_[32] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; - - const key_image Z = *reinterpret_cast(&Z_); - const key_image I = *reinterpret_cast(&I_); - const key_image L = *reinterpret_cast(&L_); - - struct random_init_singleton - { - random_init_singleton() - { - grant_random_initialize(); - } - }; - - random_init_singleton init_rand; //place initializer here to avoid grant_random_initialize first call after threads will be possible(local static variables init is not thread-safe) - - using std::abort; - using std::int32_t; - using std::int64_t; - using std::lock_guard; - using std::mutex; - using std::size_t; - using std::uint32_t; - using std::uint64_t; - - extern "C" { -#include "crypto-ops.h" -#include "random.h" - } - - - mutex random_lock; - - static inline unsigned char *operator &(ec_point &point) { - return &reinterpret_cast(point); - } - - static inline const unsigned char *operator &(const ec_point &point) { - return &reinterpret_cast(point); - } - - static inline unsigned char *operator &(ec_scalar &scalar) { - return &reinterpret_cast(scalar); - } - - static inline const unsigned char *operator &(const ec_scalar &scalar) { - return &reinterpret_cast(scalar); - } - - static inline void random_scalar(ec_scalar &res) { - unsigned char tmp[64]; - generate_random_bytes(64, tmp); - sc_reduce(tmp); - memcpy(&res, tmp, 32); - } - - void crypto_ops::keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size) - { - unsigned char tmp[64] = { 0 }; - - if (!(sizeof(tmp) >= keys_seed_binary_size)) - { - throw std::runtime_error("size mismatch"); - } - - memcpy(tmp, a_part, keys_seed_binary_size); - - cn_fast_hash(tmp, 32, (char*)&tmp[32]); - - sc_reduce(tmp); - memcpy(&sec, tmp, 32); - ge_p3 point; - ge_scalarmult_base(&point, &sec); - ge_p3_tobytes(&pub, &point); - } - - void crypto_ops::generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size) - { - keys_seed_binary.resize(keys_seed_binary_size, 0); - generate_random_bytes(keys_seed_binary_size, keys_seed_binary.data()); - keys_from_default(keys_seed_binary.data(), pub, sec, keys_seed_binary_size); - } - - static inline void hash_to_scalar(const void *data, size_t length, ec_scalar &res) - { - cn_fast_hash(data, length, reinterpret_cast(res)); - sc_reduce32(&res); - } - - void crypto_ops::generate_keys(public_key &pub, secret_key &sec) { - lock_guard lock(random_lock); - ge_p3 point; - random_scalar(sec); - ge_scalarmult_base(&point, &sec); - ge_p3_tobytes(&pub, &point); - } - - void crypto_ops::dependent_key(const secret_key& first, secret_key& second) - { - hash_to_scalar(&first, 32, second); - if (sc_check((unsigned char*)&second) != 0) - throw std::runtime_error("Failed to derive key"); - } - - - bool crypto_ops::check_key(const public_key &key) { - ge_p3 point; - return ge_frombytes_vartime(&point, &key) == 0; - } - - /* - Fix discovered by Monero Lab and suggested by "fluffypony" (bitcointalk.org) - */ - key_image scalarmult_key(const key_image & P, const key_image & a) - { - ge_p3 A = ge_p3(); - ge_p2 R = ge_p2(); - if (ge_frombytes_vartime(&A, reinterpret_cast(&P)) != 0) - return Z; - ge_scalarmult(&R, reinterpret_cast(&a), &A); - key_image a_p = key_image(); - ge_tobytes(reinterpret_cast(&a_p), &R); - return a_p; - } - - bool crypto_ops::validate_key_image(const key_image& ki) - { - if (!(scalarmult_key(ki, L) == I)) - return false; - - return true; - } - - bool crypto_ops::secret_key_to_public_key(const secret_key &sec, public_key &pub) { - ge_p3 point; - if (sc_check(&sec) != 0) { - return false; - } - ge_scalarmult_base(&point, &sec); - ge_p3_tobytes(&pub, &point); - return true; - } - - bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { - ge_p3 point; - ge_p2 point2; - ge_p1p1 point3; - crypto_assert(sc_check(&key2) == 0); - if (ge_frombytes_vartime(&point, &key1) != 0) { - return false; - } - ge_scalarmult(&point2, &key2, &point); - ge_mul8(&point3, &point2); - ge_p1p1_to_p2(&point2, &point3); - ge_tobytes(&derivation, &point2); - return true; - } - - static void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) { - struct { - key_derivation derivation; - char output_index[(sizeof(size_t) * 8 + 6) / 7]; - } buf; - char *end = buf.output_index; - buf.derivation = derivation; - tools::write_varint(end, output_index); - if (!(end <= buf.output_index + sizeof buf.output_index)) - { - crypto_assert(false); - return; - } - hash_to_scalar(&buf, end - reinterpret_cast(&buf), res); - } - - bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index, - const public_key &base, public_key &derived_key) { - ec_scalar scalar; - ge_p3 point1; - ge_p3 point2; - ge_cached point3; - ge_p1p1 point4; - ge_p2 point5; - if (ge_frombytes_vartime(&point1, &base) != 0) { - return false; - } - derivation_to_scalar(derivation, output_index, scalar); - ge_scalarmult_base(&point2, &scalar); - ge_p3_to_cached(&point3, &point2); - ge_add(&point4, &point1, &point3); - ge_p1p1_to_p2(&point5, &point4); - ge_tobytes(&derived_key, &point5); - return true; - } - - void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index, - const secret_key &base, secret_key &derived_key) { - ec_scalar scalar; - crypto_assert(sc_check(&base) == 0); - derivation_to_scalar(derivation, output_index, scalar); - sc_add(&derived_key, &base, &scalar); - } - - struct s_comm { - hash h; - ec_point key; - ec_point comm; - }; - - void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { - lock_guard lock(random_lock); - ge_p3 tmp3; - ec_scalar k; - s_comm buf; -#if !defined(NDEBUG) - { - ge_p3 t; - public_key t2; - crypto_assert(sc_check(&sec) == 0); - ge_scalarmult_base(&t, &sec); - ge_p3_tobytes(&t2, &t); - crypto_assert(pub == t2); - } -#endif - buf.h = prefix_hash; - buf.key = pub; - random_scalar(k); - ge_scalarmult_base(&tmp3, &k); - ge_p3_tobytes(&buf.comm, &tmp3); - hash_to_scalar(&buf, sizeof(s_comm), sig.c); - sc_mulsub(&sig.r, &sig.c, &sec, &k); - } - - bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { - ge_p2 tmp2; - ge_p3 tmp3; - ec_scalar c; - s_comm buf; - crypto_assert(check_key(pub)); - buf.h = prefix_hash; - buf.key = pub; - if (ge_frombytes_vartime(&tmp3, &pub) != 0) { - return false; - } - if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) { - return false; - } - ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); - ge_tobytes(&buf.comm, &tmp2); - hash_to_scalar(&buf, sizeof(s_comm), c); - sc_sub(&c, &c, &sig.c); - return sc_isnonzero(&c) == 0; - } - - static void hash_to_ec(const public_key &key, ge_p3 &res) { - hash h; - ge_p2 point; - ge_p1p1 point2; - cn_fast_hash(std::addressof(key), sizeof(public_key), h); - ge_fromfe_frombytes_vartime(&point, reinterpret_cast(&h)); - ge_mul8(&point2, &point); - ge_p1p1_to_p3(&res, &point2); - } - - void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { - ge_p3 point; - ge_p2 point2; - crypto_assert(sc_check(&sec) == 0); - hash_to_ec(pub, point); - ge_scalarmult(&point2, &sec, &point); - ge_tobytes(&image, &point2); - } - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4200) - struct rs_comm_entry - { - ec_point a, b; - }; - - struct rs_comm - { - hash h; - struct rs_comm_entry ab[]; - }; -POP_VS_WARNINGS - - static inline size_t rs_comm_size(size_t pubs_count) { - return sizeof(rs_comm)+pubs_count * sizeof(rs_comm_entry); - } - - void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, size_t pubs_count, - const secret_key &sec, size_t sec_index, - signature *sig) { - lock_guard lock(random_lock); - size_t i; - ge_p3 image_unp; - ge_dsmp image_pre; - ec_scalar sum, k, h; - rs_comm *const buf = reinterpret_cast(alloca(rs_comm_size(pubs_count))); - if (!(sec_index < pubs_count)) - { - crypto_assert(false); - return; - } -#if !defined(NDEBUG) - { - ge_p3 t; - public_key t2; - key_image t3; - crypto_assert(sc_check(&sec) == 0); - ge_scalarmult_base(&t, &sec); - ge_p3_tobytes(&t2, &t); - crypto_assert(*pubs[sec_index] == t2); - generate_key_image(*pubs[sec_index], sec, t3); - crypto_assert(image == t3); - for (i = 0; i < pubs_count; i++) { - crypto_assert(check_key(*pubs[i])); - } - } -#endif - if (ge_frombytes_vartime(&image_unp, &image) != 0) { - abort(); - } - ge_dsm_precomp(image_pre, &image_unp); - sc_0(&sum); - buf->h = prefix_hash; - for (i = 0; i < pubs_count; i++) { - ge_p2 tmp2; - ge_p3 tmp3; - if (i == sec_index) { - random_scalar(k); - ge_scalarmult_base(&tmp3, &k); - ge_p3_tobytes(&buf->ab[i].a, &tmp3); - hash_to_ec(*pubs[i], tmp3); - ge_scalarmult(&tmp2, &k, &tmp3); - ge_tobytes(&buf->ab[i].b, &tmp2); - } else { - random_scalar(sig[i].c); - random_scalar(sig[i].r); - if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { - abort(); - } - ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); - ge_tobytes(&buf->ab[i].a, &tmp2); - hash_to_ec(*pubs[i], tmp3); - ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); - ge_tobytes(&buf->ab[i].b, &tmp2); - sc_add(&sum, &sum, &sig[i].c); - } - } - hash_to_scalar(buf, rs_comm_size(pubs_count), h); - sc_sub(&sig[sec_index].c, &h, &sum); - sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k); - } - - bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, size_t pubs_count, - const signature *sig) { - size_t i; - ge_p3 image_unp; - ge_dsmp image_pre; - ec_scalar sum, h; - rs_comm *const buf = reinterpret_cast(alloca(rs_comm_size(pubs_count))); -#if !defined(NDEBUG) - for (i = 0; i < pubs_count; i++) { - crypto_assert(check_key(*pubs[i])); - } -#endif - if (ge_frombytes_vartime(&image_unp, &image) != 0) { - return false; - } - ge_dsm_precomp(image_pre, &image_unp); - sc_0(&sum); - buf->h = prefix_hash; - for (i = 0; i < pubs_count; i++) { - ge_p2 tmp2; - ge_p3 tmp3; - if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) { - return false; - } - if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { - return false; - } - ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); // L_i = r_i * G + c_i * P_i - ge_tobytes(&buf->ab[i].a, &tmp2); - hash_to_ec(*pubs[i], tmp3); - ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); // R_i = r_i * Hp(P_i) + c_i * I - ge_tobytes(&buf->ab[i].b, &tmp2); - sc_add(&sum, &sum, &sig[i].c); - } - hash_to_scalar(buf, rs_comm_size(pubs_count), h); - sc_sub(&h, &h, &sum); - return sc_isnonzero(&h) == 0; - } - -} // namespace crypto diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h deleted file mode 100644 index 64df244..0000000 --- a/src/crypto/crypto.h +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include - -#include "common/pod-class.h" -#include "generic-ops.h" -#include "hash.h" -#include "warnings.h" - - -PUSH_GCC_WARNINGS -DISABLE_CLANG_WARNING(unused-private-field) - - -namespace crypto { - - extern "C" { -#include "random.h" - } - - extern std::mutex random_lock; - -#pragma pack(push, 1) - POD_CLASS ec_point { - char data[32]; - }; - - POD_CLASS ec_scalar { - char data[32]; - }; - - POD_CLASS public_key: ec_point { - friend class crypto_ops; - }; - - POD_CLASS secret_key: ec_scalar { - friend class crypto_ops; - }; - - POD_CLASS key_derivation: ec_point { - friend class crypto_ops; - }; - - POD_CLASS key_image: public ec_point { - friend class crypto_ops; - }; - - POD_CLASS signature { - ec_scalar c, r; - friend class crypto_ops; - }; -#pragma pack(pop) - - static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 && - sizeof(public_key) == 32 && sizeof(secret_key) == 32 && - sizeof(key_derivation) == 32 && sizeof(key_image) == 32 && - sizeof(signature) == 64, "Invalid structure size"); - - class crypto_ops { - crypto_ops(); - crypto_ops(const crypto_ops &); - void operator=(const crypto_ops &); - ~crypto_ops(); - - static void generate_keys(public_key &, secret_key &); - friend void generate_keys(public_key &, secret_key &); - static void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size); - friend void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size); - static void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size); - friend void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size); - static void dependent_key(const secret_key& first, secret_key& second); - friend void dependent_key(const secret_key& first, secret_key& second); - static bool check_key(const public_key &); - friend bool check_key(const public_key &); - static bool secret_key_to_public_key(const secret_key &, public_key &); - friend bool secret_key_to_public_key(const secret_key &, public_key &); - static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); - friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); - static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); - friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); - static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); - static void generate_signature(const hash &, const public_key &, const secret_key &, signature &); - friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &); - static bool check_signature(const hash &, const public_key &, const signature &); - friend bool check_signature(const hash &, const public_key &, const signature &); - static void generate_key_image(const public_key &, const secret_key &, key_image &); - friend void generate_key_image(const public_key &, const secret_key &, key_image &); - static void generate_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); - friend void generate_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); - static bool check_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const signature *); - friend bool check_ring_signature(const hash &, const key_image &, - const public_key *const *, std::size_t, const signature *); - friend bool validate_key_image(const key_image& ki); - static bool validate_key_image(const key_image& ki); - - }; - - /* Generate a value filled with random bytes. - */ - template - typename std::enable_if::value, T>::type rand() { - typename std::remove_cv::type res; - std::lock_guard lock(random_lock); - generate_random_bytes(sizeof(T), &res); - return res; - } - - /* An adapter, to be used with std::shuffle, etc. - */ - struct uniform_random_bit_generator - { - typedef uint64_t result_type; - static CONSTEXPR uint64_t min() { return 0; } - static CONSTEXPR uint64_t max() { return UINT64_MAX; } - uint64_t operator()() { return rand(); } - }; - - - /* Generate a new key pair - */ - inline void generate_keys(public_key &pub, secret_key &sec) { - crypto_ops::generate_keys(pub, sec); - } - - inline void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size) - { - crypto_ops::generate_seed_keys(pub, sec, keys_seed_binary, keys_seed_binary_size); - } - - inline void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size) - { - crypto_ops::keys_from_default(a_part, pub, sec, keys_seed_binary_size); - } - - inline void dependent_key(const secret_key& first, secret_key& second){ - return crypto_ops::dependent_key(first, second); - } - - /* Check a public key. Returns true if it is valid, false otherwise. - */ - inline bool check_key(const public_key &key) { - return crypto_ops::check_key(key); - } - - inline bool validate_key_image(const key_image& ki){ - return crypto_ops::validate_key_image(ki); - } - /* Checks a private key and computes the corresponding public key. - */ - inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) { - return crypto_ops::secret_key_to_public_key(sec, pub); - } - - /* To generate an ephemeral key used to send money to: - * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field. - * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index. - * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key. - * * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money). - */ - inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { - return crypto_ops::generate_key_derivation(key1, key2, derivation); - } - inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index, - const public_key &base, public_key &derived_key) { - return crypto_ops::derive_public_key(derivation, output_index, base, derived_key); - } - inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, - const secret_key &base, secret_key &derived_key) { - crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); - } - - /* Generation and checking of a standard signature. - */ - inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { - crypto_ops::generate_signature(prefix_hash, pub, sec, sig); - } - inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { - return crypto_ops::check_signature(prefix_hash, pub, sig); - } - - /* To send money to a key: - * * The sender generates an ephemeral key and includes it in transaction output. - * * To spend the money, the receiver generates a key image from it. - * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature. - * To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once. - */ - inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { - crypto_ops::generate_key_image(pub, sec, image); - } - inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, std::size_t pubs_count, - const secret_key &sec, std::size_t sec_index, - signature *sig) { - crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig); - } - inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, - const public_key *const *pubs, std::size_t pubs_count, - const signature *sig) { - return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig); - } - - /* Variants with vector parameters. - */ - inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, - const std::vector &pubs, - const secret_key &sec, std::size_t sec_index, - signature *sig) { - generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig); - } - inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, - const std::vector &pubs, - const signature *sig) { - return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig); - } - - class stream_cn_hash - { - public: - static constexpr size_t DATA_BLOCK_SIZE = 1024 * 1024; - - stream_cn_hash() - : m_buffer(HASH_SIZE + DATA_BLOCK_SIZE, '\0') - , m_p_hash(const_cast(reinterpret_cast(m_buffer.data()))) - , m_p_data(const_cast(reinterpret_cast(m_buffer.data())) + HASH_SIZE) - , m_ready(false) - , m_data_used(0) - { - m_ready = true; - } - - bool update(const void* data, size_t size) - { - if (!m_ready) - return false; - - const uint8_t* p_source_data = reinterpret_cast(data); - - while(size > 0) - { - // fill the buffer up - size_t bytes_to_copy = std::min(size, DATA_BLOCK_SIZE - m_data_used); - memcpy(m_p_data + m_data_used, p_source_data, bytes_to_copy); - m_data_used += bytes_to_copy; - p_source_data += bytes_to_copy; - size -= bytes_to_copy; - - if (m_data_used == DATA_BLOCK_SIZE) - { - // calc imtermediate hash of the whole buffer and put the result into the beginning of the buffer - *m_p_hash = cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used); - // clear data buffer for new bytes - memset(m_p_data, 0, DATA_BLOCK_SIZE); - m_data_used = 0; - } - - // repeat if there are source bytes left - } - - return true; - } - - hash calculate_hash() - { - if (m_data_used == 0) - return *m_p_hash; - - m_ready = false; - return cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used); - } - - private: - const std::string m_buffer; - hash* const m_p_hash; - uint8_t* const m_p_data; - size_t m_data_used; - bool m_ready; - }; // class stream_cn_hash - -} // namespace crypto - -POD_MAKE_HASHABLE(crypto, public_key) -POD_MAKE_COMPARABLE(crypto, secret_key) -POD_MAKE_HASHABLE(crypto, key_image) -POD_MAKE_COMPARABLE(crypto, signature) -POD_MAKE_COMPARABLE(crypto, key_derivation) -POD_MAKE_LESS_OPERATOR(crypto, hash) -POD_MAKE_LESS_OPERATOR(crypto, key_image) -POP_GCC_WARNINGS \ No newline at end of file diff --git a/src/crypto/ecrypt-config.h b/src/crypto/ecrypt-config.h deleted file mode 100644 index 9176de1..0000000 --- a/src/crypto/ecrypt-config.h +++ /dev/null @@ -1,272 +0,0 @@ -/* ecrypt-config.h */ - -/* *** Normally, it should not be necessary to edit this file. *** */ - -#ifndef ECRYPT_CONFIG -#define ECRYPT_CONFIG - -/* ------------------------------------------------------------------------- */ - -/* Guess the endianness of the target architecture. */ - -/* -* The LITTLE endian machines: -*/ -#if defined(__ultrix) /* Older MIPS */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(__alpha) /* Alpha */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(i386) /* x86 (gcc) */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(__i386) /* x86 (gcc) */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(_M_IX86) /* x86 (MSC, Borland) */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(_MSC_VER) /* x86 (surely MSC) */ -#define ECRYPT_LITTLE_ENDIAN -#elif defined(__INTEL_COMPILER) /* x86 (surely Intel compiler icl.exe) */ -#define ECRYPT_LITTLE_ENDIAN - -/* -* The BIG endian machines: -*/ -#elif defined(sun) /* Newer Sparc's */ -#define ECRYPT_BIG_ENDIAN -#elif defined(__ppc__) /* PowerPC */ -#define ECRYPT_BIG_ENDIAN - -/* -* Finally machines with UNKNOWN endianness: -*/ -#elif defined (_AIX) /* RS6000 */ -#define ECRYPT_UNKNOWN -#elif defined(__hpux) /* HP-PA */ -#define ECRYPT_UNKNOWN -#elif defined(__aux) /* 68K */ -#define ECRYPT_UNKNOWN -#elif defined(__dgux) /* 88K (but P6 in latest boxes) */ -#define ECRYPT_UNKNOWN -#elif defined(__sgi) /* Newer MIPS */ -#define ECRYPT_UNKNOWN -#else /* Any other processor */ -#define ECRYPT_UNKNOWN -#endif - -/* ------------------------------------------------------------------------- */ - -/* -* Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit -* integers. -* -* Note: to enable 64-bit types on 32-bit compilers, it might be -* necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc -* -std=c99). -*/ - -#include - -/* --- check char --- */ - -#if (UCHAR_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T char -#define U8C(v) (v##U) - -#if (UCHAR_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (UCHAR_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T char -#define U16C(v) (v##U) -#endif - -#if (UCHAR_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T char -#define U32C(v) (v##U) -#endif - -#if (UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T char -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check short --- */ - -#if (USHRT_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T short -#define U8C(v) (v##U) - -#if (USHRT_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (USHRT_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T short -#define U16C(v) (v##U) -#endif - -#if (USHRT_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T short -#define U32C(v) (v##U) -#endif - -#if (USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T short -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check int --- */ - -#if (UINT_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T int -#define U8C(v) (v##U) - -#if (ULONG_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (UINT_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T int -#define U16C(v) (v##U) -#endif - -#if (UINT_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T int -#define U32C(v) (v##U) -#endif - -#if (UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T int -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check long --- */ - -#if (ULONG_MAX / 0xFUL > 0xFUL) -#ifndef I8T -#define I8T long -#define U8C(v) (v##UL) - -#if (ULONG_MAX == 0xFFUL) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (ULONG_MAX / 0xFFUL > 0xFFUL) -#ifndef I16T -#define I16T long -#define U16C(v) (v##UL) -#endif - -#if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL) -#ifndef I32T -#define I32T long -#define U32C(v) (v##UL) -#endif - -#if (ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL) -#ifndef I64T -#define I64T long -#define U64C(v) (v##UL) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check long long --- */ - -#ifdef ULLONG_MAX - -#if (ULLONG_MAX / 0xFULL > 0xFULL) -#ifndef I8T -#define I8T long long -#define U8C(v) (v##ULL) - -#if (ULLONG_MAX == 0xFFULL) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (ULLONG_MAX / 0xFFULL > 0xFFULL) -#ifndef I16T -#define I16T long long -#define U16C(v) (v##ULL) -#endif - -#if (ULLONG_MAX / 0xFFFFULL > 0xFFFFULL) -#ifndef I32T -#define I32T long long -#define U32C(v) (v##ULL) -#endif - -#if (ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL) -#ifndef I64T -#define I64T long long -#define U64C(v) (v##ULL) -#endif - -#endif -#endif -#endif -#endif - -#endif - -/* --- check __int64 --- */ - -#ifdef _UI64_MAX - -#if (_UI64_MAX / 0xFFFFFFFFui64 > 0xFFFFFFFFui64) -#ifndef I64T -#define I64T __int64 -#define U64C(v) (v##ui64) -#endif - -#endif - -#endif - -/* ------------------------------------------------------------------------- */ - -#endif \ No newline at end of file diff --git a/src/crypto/ecrypt-machine.h b/src/crypto/ecrypt-machine.h deleted file mode 100644 index 83356b1..0000000 --- a/src/crypto/ecrypt-machine.h +++ /dev/null @@ -1,46 +0,0 @@ -/* ecrypt-machine.h */ - -/* -* This file is included by 'ecrypt-portable.h'. It allows to override -* the default macros for specific platforms. Please carefully check -* the machine code generated by your compiler (with optimisations -* turned on) before deciding to edit this file. -*/ - -/* ------------------------------------------------------------------------- */ - -#if (defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT)) - -#define ECRYPT_MACHINE_ROT - -#if (defined(WIN32) && defined(_MSC_VER)) - -#undef ROTL32 -#undef ROTR32 -#undef ROTL64 -#undef ROTR64 - -#include - -#define ROTL32(v, n) _lrotl(v, n) -#define ROTR32(v, n) _lrotr(v, n) -#define ROTL64(v, n) _rotl64(v, n) -#define ROTR64(v, n) _rotr64(v, n) - -#endif - -#endif - -/* ------------------------------------------------------------------------- */ - -#if (defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP)) - -#define ECRYPT_MACHINE_SWAP - -/* -* If you want to overwrite the default swap macros, put it here. And so on. -*/ - -#endif - -/* ------------------------------------------------------------------------- */ \ No newline at end of file diff --git a/src/crypto/ecrypt-portable.h b/src/crypto/ecrypt-portable.h deleted file mode 100644 index 4baa4d6..0000000 --- a/src/crypto/ecrypt-portable.h +++ /dev/null @@ -1,303 +0,0 @@ -/* ecrypt-portable.h */ - -/* -* WARNING: the conversions defined below are implemented as macros, -* and should be used carefully. They should NOT be used with -* parameters which perform some action. E.g., the following two lines -* are not equivalent: -* -* 1) ++x; y = ROTL32(x, n); -* 2) y = ROTL32(++x, n); -*/ - -/* -* *** Please do not edit this file. *** -* -* The default macros can be overridden for specific architectures by -* editing 'ecrypt-machine.h'. -*/ - -#ifndef ECRYPT_PORTABLE -#define ECRYPT_PORTABLE - -#include "ecrypt-config.h" - -/* ------------------------------------------------------------------------- */ - -/* -* The following types are defined (if available): -* -* u8: unsigned integer type, at least 8 bits -* u16: unsigned integer type, at least 16 bits -* u32: unsigned integer type, at least 32 bits -* u64: unsigned integer type, at least 64 bits -* -* s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64 -* -* The selection of minimum-width integer types is taken care of by -* 'ecrypt-config.h'. Note: to enable 64-bit types on 32-bit -* compilers, it might be necessary to switch from ISO C90 mode to ISO -* C99 mode (e.g., gcc -std=c99). -*/ - -#ifdef I8T -typedef signed I8T s8; -typedef unsigned I8T u8; -#endif - -#ifdef I16T -typedef signed I16T s16; -typedef unsigned I16T u16; -#endif - -#ifdef I32T -typedef signed I32T s32; -typedef unsigned I32T u32; -#endif - -#ifdef I64T -typedef signed I64T s64; -typedef unsigned I64T u64; -#endif - -/* -* The following macros are used to obtain exact-width results. -*/ - -#define U8V(v) ((u8)(v) & U8C(0xFF)) -#define U16V(v) ((u16)(v) & U16C(0xFFFF)) -#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) -#define U64V(v) ((u64)(v) & U64C(0xFFFFFFFFFFFFFFFF)) - -/* ------------------------------------------------------------------------- */ - -/* -* The following macros return words with their bits rotated over n -* positions to the left/right. -*/ - -#define ECRYPT_DEFAULT_ROT - -#define ROTL8(v, n) \ - (U8V((v) << (n)) | ((v) >> (8 - (n)))) - -#define ROTL16(v, n) \ - (U16V((v) << (n)) | ((v) >> (16 - (n)))) - -#define ROTL32(v, n) \ - (U32V((v) << (n)) | ((v) >> (32 - (n)))) - -#define ROTL64(v, n) \ - (U64V((v) << (n)) | ((v) >> (64 - (n)))) - -#define ROTR8(v, n) ROTL8(v, 8 - (n)) -#define ROTR16(v, n) ROTL16(v, 16 - (n)) -#define ROTR32(v, n) ROTL32(v, 32 - (n)) -#define ROTR64(v, n) ROTL64(v, 64 - (n)) - -#include "ecrypt-machine.h" - -/* ------------------------------------------------------------------------- */ - -/* -* The following macros return a word with bytes in reverse order. -*/ - -#define ECRYPT_DEFAULT_SWAP - -#define SWAP16(v) \ - ROTL16(v, 8) - -#define SWAP32(v) \ - ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \ - (ROTL32(v, 24) & U32C(0xFF00FF00))) - -#ifdef ECRYPT_NATIVE64 -#define SWAP64(v) \ - ((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | \ - (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \ - (ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | \ - (ROTL64(v, 56) & U64C(0xFF000000FF000000))) -#else -#define SWAP64(v) \ - (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32))) -#endif - -#include "ecrypt-machine.h" - -#define ECRYPT_DEFAULT_WTOW - -#ifdef ECRYPT_LITTLE_ENDIAN -#define U16TO16_LITTLE(v) (v) -#define U32TO32_LITTLE(v) (v) -#define U64TO64_LITTLE(v) (v) - -#define U16TO16_BIG(v) SWAP16(v) -#define U32TO32_BIG(v) SWAP32(v) -#define U64TO64_BIG(v) SWAP64(v) -#endif - -#ifdef ECRYPT_BIG_ENDIAN -#define U16TO16_LITTLE(v) SWAP16(v) -#define U32TO32_LITTLE(v) SWAP32(v) -#define U64TO64_LITTLE(v) SWAP64(v) - -#define U16TO16_BIG(v) (v) -#define U32TO32_BIG(v) (v) -#define U64TO64_BIG(v) (v) -#endif - -#include "ecrypt-machine.h" - -/* -* The following macros load words from an array of bytes with -* different types of endianness, and vice versa. -*/ - -#define ECRYPT_DEFAULT_BTOW - -#if (!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE)) - -#define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0]) -#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0]) -#define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0]) - -#define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0]) -#define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0]) -#define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0]) - -#define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v)) -#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v)) -#define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v)) - -#define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v)) -#define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v)) -#define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v)) - -#else - -#define U8TO16_LITTLE(p) \ - (((u16)((p)[0]) ) | \ - ((u16)((p)[1]) << 8)) - -#define U8TO32_LITTLE(p) \ - (((u32)((p)[0]) ) | \ - ((u32)((p)[1]) << 8) | \ - ((u32)((p)[2]) << 16) | \ - ((u32)((p)[3]) << 24)) - -#ifdef ECRYPT_NATIVE64 -#define U8TO64_LITTLE(p) \ - (((u64)((p)[0]) ) | \ - ((u64)((p)[1]) << 8) | \ - ((u64)((p)[2]) << 16) | \ - ((u64)((p)[3]) << 24) | \ - ((u64)((p)[4]) << 32) | \ - ((u64)((p)[5]) << 40) | \ - ((u64)((p)[6]) << 48) | \ - ((u64)((p)[7]) << 56)) -#else -#define U8TO64_LITTLE(p) \ - ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32)) -#endif - -#define U8TO16_BIG(p) \ - (((u16)((p)[0]) << 8) | \ - ((u16)((p)[1]) )) - -#define U8TO32_BIG(p) \ - (((u32)((p)[0]) << 24) | \ - ((u32)((p)[1]) << 16) | \ - ((u32)((p)[2]) << 8) | \ - ((u32)((p)[3]) )) - -#ifdef ECRYPT_NATIVE64 -#define U8TO64_BIG(p) \ - (((u64)((p)[0]) << 56) | \ - ((u64)((p)[1]) << 48) | \ - ((u64)((p)[2]) << 40) | \ - ((u64)((p)[3]) << 32) | \ - ((u64)((p)[4]) << 24) | \ - ((u64)((p)[5]) << 16) | \ - ((u64)((p)[6]) << 8) | \ - ((u64)((p)[7]) )) -#else -#define U8TO64_BIG(p) \ - (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4)) -#endif - -#define U16TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - } while (0) - -#define U32TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - (p)[2] = U8V((v) >> 16); \ - (p)[3] = U8V((v) >> 24); \ - } while (0) - -#ifdef ECRYPT_NATIVE64 -#define U64TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - (p)[2] = U8V((v) >> 16); \ - (p)[3] = U8V((v) >> 24); \ - (p)[4] = U8V((v) >> 32); \ - (p)[5] = U8V((v) >> 40); \ - (p)[6] = U8V((v) >> 48); \ - (p)[7] = U8V((v) >> 56); \ - } while (0) -#else -#define U64TO8_LITTLE(p, v) \ - do { \ - U32TO8_LITTLE((p), U32V((v) )); \ - U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \ - } while (0) -#endif - -#define U16TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - } while (0) - -#define U32TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) >> 24); \ - (p)[1] = U8V((v) >> 16); \ - (p)[2] = U8V((v) >> 8); \ - (p)[3] = U8V((v) ); \ - } while (0) - -#ifdef ECRYPT_NATIVE64 -#define U64TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) >> 56); \ - (p)[1] = U8V((v) >> 48); \ - (p)[2] = U8V((v) >> 40); \ - (p)[3] = U8V((v) >> 32); \ - (p)[4] = U8V((v) >> 24); \ - (p)[5] = U8V((v) >> 16); \ - (p)[6] = U8V((v) >> 8); \ - (p)[7] = U8V((v) ); \ - } while (0) -#else -#define U64TO8_BIG(p, v) \ - do { \ - U32TO8_BIG((p), U32V((v) >> 32)); \ - U32TO8_BIG((p) + 4, U32V((v) )); \ - } while (0) -#endif - -#endif - -#include "ecrypt-machine.h" - -/* ------------------------------------------------------------------------- */ - -#endif \ No newline at end of file diff --git a/src/crypto/ecrypt-sync.h b/src/crypto/ecrypt-sync.h deleted file mode 100644 index cd5f5d4..0000000 --- a/src/crypto/ecrypt-sync.h +++ /dev/null @@ -1,258 +0,0 @@ -/* ecrypt-sync.h */ - -/* -* Header file for synchronous stream ciphers without authentication -* mechanism. -* -* *** Please only edit parts marked with "[edit]". *** -*/ - -#ifndef ECRYPT_SYNC_AE -#define ECRYPT_SYNC_AE - -#include "ecrypt-portable.h" - -/* ------------------------------------------------------------------------- */ - -/* Cipher parameters */ - -/* -* The name of your cipher. -*/ -#define ECRYPT_NAME "Salsa20 stream cipher" /* [edit] */ - -/* -* Specify which key and IV sizes are supported by your cipher. A user -* should be able to enumerate the supported sizes by running the -* following code: -* -* for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i) -* { -* keysize = ECRYPT_KEYSIZE(i); -* -* ... -* } -* -* All sizes are in bits. -*/ - -#define ECRYPT_MAXKEYSIZE 256 /* [edit] */ -#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */ - -#define ECRYPT_MAXIVSIZE 64 /* [edit] */ -#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */ - -/* ------------------------------------------------------------------------- */ - -/* Data structures */ - -/* -* ECRYPT_ctx is the structure containing the representation of the -* internal state of your cipher. -*/ - -typedef struct -{ - u32 input[16]; /* could be compressed */ - /* - * [edit] - * - * Put here all state variable needed during the encryption process. - */ -} ECRYPT_ctx; - -/* ------------------------------------------------------------------------- */ - -/* Mandatory functions */ - -/* -* Key and message independent initialization. This function will be -* called once when the program starts (e.g., to build expanded S-box -* tables). -*/ -void ECRYPT_init(); - -/* -* Key setup. It is the user's responsibility to select the values of -* keysize and ivsize from the set of supported values specified -* above. -*/ -void ECRYPT_keysetup( - ECRYPT_ctx* ctx, - const u8* key, - u32 keysize, /* Key size in bits. */ - u32 ivsize); /* IV size in bits. */ - - /* - * IV setup. After having called ECRYPT_keysetup(), the user is - * allowed to call ECRYPT_ivsetup() different times in order to - * encrypt/decrypt different messages with the same key but different - * IV's. - */ -void ECRYPT_ivsetup( - ECRYPT_ctx* ctx, - const u8* iv); - -/* -* Encryption/decryption of arbitrary length messages. -* -* For efficiency reasons, the API provides two types of -* encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function -* (declared here) encrypts byte strings of arbitrary length, while -* the ECRYPT_encrypt_blocks() function (defined later) only accepts -* lengths which are multiples of ECRYPT_BLOCKLENGTH. -* -* The user is allowed to make multiple calls to -* ECRYPT_encrypt_blocks() to incrementally encrypt a long message, -* but he is NOT allowed to make additional encryption calls once he -* has called ECRYPT_encrypt_bytes() (unless he starts a new message -* of course). For example, this sequence of calls is acceptable: -* -* ECRYPT_keysetup(); -* -* ECRYPT_ivsetup(); -* ECRYPT_encrypt_blocks(); -* ECRYPT_encrypt_blocks(); -* ECRYPT_encrypt_bytes(); -* -* ECRYPT_ivsetup(); -* ECRYPT_encrypt_blocks(); -* ECRYPT_encrypt_blocks(); -* -* ECRYPT_ivsetup(); -* ECRYPT_encrypt_bytes(); -* -* The following sequence is not: -* -* ECRYPT_keysetup(); -* ECRYPT_ivsetup(); -* ECRYPT_encrypt_blocks(); -* ECRYPT_encrypt_bytes(); -* ECRYPT_encrypt_blocks(); -*/ - -void ECRYPT_encrypt_bytes( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 msglen); /* Message length in bytes. */ - -void ECRYPT_decrypt_bytes( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 msglen); /* Message length in bytes. */ - - /* ------------------------------------------------------------------------- */ - - /* Optional features */ - - /* - * For testing purposes it can sometimes be useful to have a function - * which immediately generates keystream without having to provide it - * with a zero plaintext. If your cipher cannot provide this function - * (e.g., because it is not strictly a synchronous cipher), please - * reset the ECRYPT_GENERATES_KEYSTREAM flag. - */ - -#define ECRYPT_GENERATES_KEYSTREAM -#ifdef ECRYPT_GENERATES_KEYSTREAM - -void ECRYPT_keystream_bytes( - ECRYPT_ctx* ctx, - u8* keystream, - u32 length); /* Length of keystream in bytes. */ - -#endif - - /* ------------------------------------------------------------------------- */ - - /* Optional optimizations */ - - /* - * By default, the functions in this section are implemented using - * calls to functions declared above. However, you might want to - * implement them differently for performance reasons. - */ - - /* - * All-in-one encryption/decryption of (short) packets. - * - * The default definitions of these functions can be found in - * "ecrypt-sync.c". If you want to implement them differently, please - * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag. - */ -#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */ - -void ECRYPT_encrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* plaintext, - u8* ciphertext, - u32 msglen); - -void ECRYPT_decrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* ciphertext, - u8* plaintext, - u32 msglen); - -/* -* Encryption/decryption of blocks. -* -* By default, these functions are defined as macros. If you want to -* provide a different implementation, please undef the -* ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions -* declared below. -*/ - -#define ECRYPT_BLOCKLENGTH 64 /* [edit] */ - -#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */ -#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS - -#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ - ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ - ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#ifdef ECRYPT_GENERATES_KEYSTREAM - -#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \ - ECRYPT_AE_keystream_bytes(ctx, keystream, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#endif - -#else - -void ECRYPT_encrypt_blocks( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 blocks); /* Message length in blocks. */ - -void ECRYPT_decrypt_blocks( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 blocks); /* Message length in blocks. */ - -#ifdef ECRYPT_GENERATES_KEYSTREAM - -void ECRYPT_keystream_blocks( - ECRYPT_AE_ctx* ctx, - const u8* keystream, - u32 blocks); /* Keystream length in blocks. */ - -#endif - -#endif - - /* ------------------------------------------------------------------------- */ - -#endif \ No newline at end of file diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h deleted file mode 100644 index 4fe9a5b..0000000 --- a/src/crypto/generic-ops.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - -#define POD_MAKE_COMPARABLE(space, type) \ -namespace space { \ - inline bool operator==(const type &_v1, const type &_v2) { \ - return std::memcmp(&_v1, &_v2, sizeof(type)) == 0; \ - } \ - inline bool operator!=(const type &_v1, const type &_v2) { \ - return std::memcmp(&_v1, &_v2, sizeof(type)) != 0; \ - } \ -} - -#define POD_MAKE_LESS_OPERATOR(space, type) \ -namespace space { \ - inline bool operator<(const type &_v1, const type &_v2) { \ - return std::memcmp(&_v1, &_v2, sizeof(type)) < 0; \ - } \ -} - -#define POD_MAKE_HASHABLE(space, type) \ - POD_MAKE_COMPARABLE(space, type) \ -namespace space { \ - static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \ - inline std::size_t hash_value(const type &_v) { \ - return reinterpret_cast(_v); \ - } \ -} \ -namespace std { \ - template<> \ - struct hash { \ - std::size_t operator()(const space::type &_v) const { \ - return reinterpret_cast(_v); \ - } \ - }; \ -} - -// -// CONSTEXPR -// -#if ( defined(_MSC_VER) && (_MSC_VER < 1800) ) - #error MS compilers prior to v 18.00 (MSVC 2013) are not supported -#endif - -// compilation workaround for MSVC 2013 Update 5 wich does not support constexpr -#if ( defined(_MSC_VER) && (1800 <= _MSC_VER) && (_MSC_VER < 1900) ) - #define CONSTEXPR -#else // all other platforms or MSVC 2015 and later - #define CONSTEXPR constexpr -#endif - diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h deleted file mode 100644 index fcc06d1..0000000 --- a/src/crypto/hash-ops.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#if !defined(__cplusplus) - -#include -#include -#include -#include - -#include "common/int-util.h" -#include "warnings.h" - -static inline void *padd(void *p, size_t i) { - return (char *) p + i; -} - -static inline const void *cpadd(const void *p, size_t i) { - return (const char *) p + i; -} - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4267) -static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long"); -static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) { - if (sizeof(size_t) == 4) { - *(uint32_t *) padd(buffer, bufsize - 4) = swap32be(length); - } else { - *(uint64_t *) padd(buffer, bufsize - 8) = swap64be(length); - } -} -POP_VS_WARNINGS - -#pragma pack(push, 1) -union hash_state { - uint8_t b[200]; - uint64_t w[25]; -}; -#pragma pack(pop) -static_assert(sizeof(union hash_state) == 200, "Invalid structure size"); - -void hash_permutation(union hash_state *state); -void hash_process(union hash_state *state, const uint8_t *buf, size_t count); - -#endif - - -#define HASH_SIZE 32 -#define HASH_DATA_AREA 136 - - -void cn_fast_hash_old(const void *data, size_t length, char *hash); -void cn_fast_hash(const void *data, size_t length, char *hash); - -void hash_extra_blake(const void *data, size_t length, char *hash); -void hash_extra_groestl(const void *data, size_t length, char *hash); -void hash_extra_jh(const void *data, size_t length, char *hash); -void hash_extra_skein(const void *data, size_t length, char *hash); - -void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash); diff --git a/src/crypto/hash.c b/src/crypto/hash.c deleted file mode 100644 index 0d399f4..0000000 --- a/src/crypto/hash.c +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2020-2021 Zano project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include - -#include "hash-ops.h" -#include "keccak.h" - -void hash_permutation(union hash_state *state) { - keccakf((uint64_t*)state, 24); -} - -void hash_process(union hash_state *state, const uint8_t *buf, size_t count) { - keccak1600(buf, (int)count, (uint8_t*)state); -} - -void cn_fast_hash_old(const void *data, size_t length, char *hash) -{ - union hash_state state; - hash_process(&state, data, length); - memcpy(hash, &state, HASH_SIZE); -} - -void cn_fast_hash(const void *data, size_t length, char *hash) -{ - keccak(data, (int)length, (uint8_t*)hash, HASH_SIZE); -} diff --git a/src/crypto/hash.h b/src/crypto/hash.h deleted file mode 100644 index 7fb0573..0000000 --- a/src/crypto/hash.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include - -#include "common/pod-class.h" -#include "generic-ops.h" -#include "warnings.h" -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4804) -#include "blake2.h" -POP_VS_WARNINGS -namespace crypto { - - extern "C" { -#include "hash-ops.h" - } - -#pragma pack(push, 1) - POD_CLASS hash { - char data[HASH_SIZE]; - }; -#pragma pack(pop) - - static_assert(sizeof(hash) == HASH_SIZE, "Invalid structure size"); - - /* - Cryptonight hash functions - */ - - inline void cn_fast_hash(const void *data, std::size_t length, hash &hash) { - cn_fast_hash(data, length, reinterpret_cast(&hash)); - } - - inline hash cn_fast_hash(const void *data, std::size_t length) { - hash h; - cn_fast_hash(data, length, reinterpret_cast(&h)); - return h; - } - - inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) { - tree_hash(reinterpret_cast(hashes), count, reinterpret_cast(&root_hash)); - } - - inline hash blake2_hash(const void *data, std::size_t length) { - hash h; - blake2(&h, sizeof(h), data, length, nullptr, 0); - return h; - } - -} - -POD_MAKE_HASHABLE(crypto, hash) diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h deleted file mode 100644 index 8c84621..0000000 --- a/src/crypto/initializer.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#if defined(__GNUC__) -#define INITIALIZER(name) __attribute__((constructor(101))) static void name(void) -#define FINALIZER(name) __attribute__((destructor(101))) static void name(void) -#define REGISTER_FINALIZER(name) ((void) 0) - -#elif defined(_MSC_VER) -#include -#include -// http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc -// http://msdn.microsoft.com/en-us/library/bb918180.aspx -#pragma section(".CRT$XCT", read) -#define INITIALIZER(name) \ - static void __cdecl name(void); \ - __declspec(allocate(".CRT$XCT")) void (__cdecl *const _##name)(void) = &name; \ - static void __cdecl name(void) -#define FINALIZER(name) \ - static void __cdecl name(void) -#define REGISTER_FINALIZER(name) \ - do { \ - int _res = atexit(name); \ - assert(_res == 0); \ - } while (0); - -#else -#error Unsupported compiler -#endif diff --git a/src/crypto/keccak.c b/src/crypto/keccak.c deleted file mode 100644 index 3ee2a88..0000000 --- a/src/crypto/keccak.c +++ /dev/null @@ -1,112 +0,0 @@ -// keccak.c -// 19-Nov-11 Markku-Juhani O. Saarinen -// A baseline Keccak (3rd round) implementation. - -#include "hash-ops.h" -#include "keccak.h" - -const uint64_t keccakf_rndc[24] = -{ - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, - 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, - 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, - 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, - 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, - 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 -}; - -const int keccakf_rotc[24] = -{ - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 -}; - -const int keccakf_piln[24] = -{ - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 -}; - -// update the state with given number of rounds - -void keccakf(uint64_t st[25], int rounds) -{ - int i, j, round; - uint64_t t, bc[5]; - - for (round = 0; round < rounds; round++) { - - // Theta - for (i = 0; i < 5; i++) - bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; - - for (i = 0; i < 5; i++) { - t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); - for (j = 0; j < 25; j += 5) - st[j + i] ^= t; - } - - // Rho Pi - t = st[1]; - for (i = 0; i < 24; i++) { - j = keccakf_piln[i]; - bc[0] = st[j]; - st[j] = ROTL64(t, keccakf_rotc[i]); - t = bc[0]; - } - - // Chi - for (j = 0; j < 25; j += 5) { - for (i = 0; i < 5; i++) - bc[i] = st[j + i]; - for (i = 0; i < 5; i++) - st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; - } - - // Iota - st[0] ^= keccakf_rndc[round]; - } -} - -// compute a keccak hash (md) of given byte length from "in" -typedef uint64_t state_t[25]; - -int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) -{ - state_t st; - uint8_t temp[144]; - int i, rsiz, rsizw; - - rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; - rsizw = rsiz / 8; - - memset(st, 0, sizeof(st)); - - for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { - for (i = 0; i < rsizw; i++) - st[i] ^= ((uint64_t *) in)[i]; - keccakf(st, KECCAK_ROUNDS); - } - - // last block and padding - memcpy(temp, in, inlen); - temp[inlen++] = 1; - memset(temp + inlen, 0, rsiz - inlen); - temp[rsiz - 1] |= 0x80; - - for (i = 0; i < rsizw; i++) - st[i] ^= ((uint64_t *) temp)[i]; - - keccakf(st, KECCAK_ROUNDS); - - memcpy(md, st, mdlen); - - return 0; -} - -void keccak1600(const uint8_t *in, int inlen, uint8_t *md) -{ - keccak(in, inlen, md, sizeof(state_t)); -} diff --git a/src/crypto/keccak.h b/src/crypto/keccak.h deleted file mode 100644 index 4f7f857..0000000 --- a/src/crypto/keccak.h +++ /dev/null @@ -1,26 +0,0 @@ -// keccak.h -// 19-Nov-11 Markku-Juhani O. Saarinen - -#ifndef KECCAK_H -#define KECCAK_H - -#include -#include - -#ifndef KECCAK_ROUNDS -#define KECCAK_ROUNDS 24 -#endif - -#ifndef ROTL64 -#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) -#endif - -// compute a keccak hash (md) of given byte length from "in" -int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); - -// update the state -void keccakf(uint64_t st[25], int norounds); - -void keccak1600(const uint8_t *in, int inlen, uint8_t *md); - -#endif diff --git a/src/crypto/random.c b/src/crypto/random.c deleted file mode 100644 index bdac1e7..0000000 --- a/src/crypto/random.c +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include - -#include "hash-ops.h" -//#include "initializer.h" -#include "random.h" - -static_assert(RANDOM_STATE_SIZE >= HASH_DATA_AREA, "Invalid RANDOM_STATE_SIZE"); - -#if defined(_WIN32) - -#include -#include - -void generate_system_random_bytes(size_t n, void *result) { - HCRYPTPROV prov; -#define must_succeed(x) do if (!(x)) assert(0); while (0) - if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - { - int err = GetLastError(); - assert(0); - } - must_succeed(CryptGenRandom(prov, (DWORD)n, result)); - must_succeed(CryptReleaseContext(prov, 0)); -#undef must_succeed -} - -#else - -#include -#include -#include -#include -#include -#include -#include - -void generate_system_random_bytes(size_t n, void *result) { - int fd; - if ((fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) { - err(EXIT_FAILURE, "open /dev/urandom"); - } - for (;;) { - ssize_t res = read(fd, result, n); - if ((size_t) res == n) { - break; - } - if (res < 0) { - if (errno != EINTR) { - err(EXIT_FAILURE, "read /dev/urandom"); - } - } else if (res == 0) { - errx(EXIT_FAILURE, "read /dev/urandom: end of file"); - } else { - result = padd(result, (size_t) res); - n -= (size_t) res; - } - } - if (close(fd) < 0) { - err(EXIT_FAILURE, "close /dev/urandom"); - } -} - -#endif - -static union hash_state state; - -#if !defined(NDEBUG) -static volatile int curstate; /* To catch thread safety problems. */ -#endif -/* -FINALIZER(deinit_random) { -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 0; -#endif - memset(&state, 0, sizeof(union hash_state)); -} -*/ - -//INITIALIZER(init_random) { -void init_random(void) -{ - generate_system_random_bytes(32, &state); - //REGISTER_FINA\LIZER(deinit_random); -#if !defined(NDEBUG) - assert(curstate == 0); - curstate = 1; -#endif -} - - -void grant_random_initialize(void) -{ - static bool initalized = false; - if(!initalized) - { - init_random(); - initalized = true; - } -} - -void random_prng_initialize_with_seed(uint64_t seed) -{ - grant_random_initialize(); -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 3; -#endif - memset(&state, 0, sizeof state); - memcpy(&state, &seed, sizeof seed); - for(size_t i = 0, count = seed & 31; i < count; ++i) - hash_permutation(&state); -#if !defined(NDEBUG) - assert(curstate == 3); - curstate = 1; -#endif -} - -void random_prng_get_state(void *state_buffer, const size_t buffer_size) -{ - grant_random_initialize(); -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 4; -#endif - - assert(sizeof state == buffer_size); - memcpy(state_buffer, &state, buffer_size); - -#if !defined(NDEBUG) - assert(curstate == 4); - curstate = 1; -#endif -} - -void random_prng_set_state(const void *state_buffer, const size_t buffer_size) -{ - grant_random_initialize(); -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 5; -#endif - - assert(sizeof state == buffer_size); - memcpy(&state, state_buffer, buffer_size); - -#if !defined(NDEBUG) - assert(curstate == 5); - curstate = 1; -#endif -} - -void generate_random_bytes(size_t n, void *result) { - grant_random_initialize(); -#if !defined(NDEBUG) - assert(curstate == 1); - curstate = 2; -#endif - if (n == 0) { -#if !defined(NDEBUG) - assert(curstate == 2); - curstate = 1; -#endif - return; - } - for (;;) { - hash_permutation(&state); - if (n <= HASH_DATA_AREA) { - memcpy(result, &state, n); -#if !defined(NDEBUG) - assert(curstate == 2); - curstate = 1; -#endif - return; - } else { - memcpy(result, &state, HASH_DATA_AREA); - result = padd(result, HASH_DATA_AREA); - n -= HASH_DATA_AREA; - } - } -} diff --git a/src/crypto/random.h b/src/crypto/random.h deleted file mode 100644 index dbc7930..0000000 --- a/src/crypto/random.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Copyright (c) 2014-2018 The Boolberry developers -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -// use the cryptographically secure Pseudo-Random Number Generator provided by the operating system -void generate_system_random_bytes(size_t n, void *result); - -void generate_random_bytes(size_t n, void *result); - -// checks if PRNG is initialized and initializes it if necessary -void grant_random_initialize(void); - -#define RANDOM_STATE_SIZE 200 - -// explicitly define USE_INSECURE_RANDOM_RPNG_ROUTINES for using random_initialize_with_seed -#ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES -// reinitializes PRNG with the given seed -// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH! -// Use with care and ONLY for tests or debug purposes! -void random_prng_initialize_with_seed(uint64_t seed); - -// gets internal RPNG state (state_buffer should be 200 bytes long) -void random_prng_get_state(void *state_buffer, const size_t buffer_size); - -// sets internal RPNG state (state_buffer should be 200 bytes long) -// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH! -// Use with care and ONLY for tests or debug purposes! -void random_prng_set_state(const void *state_buffer, const size_t buffer_size); - -#endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES diff --git a/src/crypto/range_proofs.cpp b/src/crypto/range_proofs.cpp deleted file mode 100644 index b6750a0..0000000 --- a/src/crypto/range_proofs.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2021 Zano Project (https://zano.org/) -// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "range_proofs.h" - -namespace crypto -{ - const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H; - - -} diff --git a/src/crypto/range_proofs.h b/src/crypto/range_proofs.h deleted file mode 100644 index b3d04d6..0000000 --- a/src/crypto/range_proofs.h +++ /dev/null @@ -1,823 +0,0 @@ -// Copyright (c) 2021 Zano Project (https://zano.org/) -// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#pragma once - -// -// This file contains the implementation of range proof protocol. -// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735.pdf -// - -#include "epee/include/misc_log_ex.h" -#include "crypto-sugar.h" - -namespace crypto -{ - - // returns x + x^2 + x^3 + ... + x^(2^f) - // == x * (x + 1) * (x^2 + 1) * (x^4 + 1) * ...(x^(f+1) + 1) - inline scalar_t sum_of_powers(scalar_t x, size_t f) - { - scalar_t result = x; - for (size_t i = 0; i < f; ++i) - { - result.assign_muladd(result, x, result); - x *= x; - } - return result; - } - - constexpr size_t c_bpp_log2_n = 6; - constexpr size_t c_bpp_n = 64; // 2^64 is the upper bound for the witness's range - constexpr size_t c_bpp_values_max = 16; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs - constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; - - // returns smallest k, s.t. v <= 2**k - inline size_t calc_exp_power_of_2_upper_bound(size_t v) - { - constexpr size_t max_v = (SIZE_MAX >> 1) + 1; - //if (v > max_v) - // return 0; - - size_t pow = 1, result = 0; - while (v > pow) - { - pow <<= 1; - ++result; - } - return result; - } - - // returns least significant bit uing de Bruijn sequence - // http://graphics.stanford.edu/~seander/bithacks.html - inline uint8_t calc_lsb_32(uint32_t v) - { - static const uint8_t multiply_de_bruijn_bit_position[32] = - { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 - }; - return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27]; - } - - - //////////////////////////////////////// - // crypto trait for Zano - //////////////////////////////////////// - struct bpp_crypto_trait_zano - { - static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment) - { - commitment = value * c_point_G + mask * c_point_H; - } - - static const scalar_t& get_initial_transcript() - { - static scalar_t value = hash_helper_t::hs("Zano BP+ initial transcript"); - return value; - } - - // assumes hsc is cleared - static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector& points) - { - hsc.add_scalar(e); - hsc.add_points_array(points); - e = hsc.calc_hash(); - } - - static const point_t& get_generator(bool select_H, size_t index) - { - if (index >= c_bpp_mn_max) - return c_point_0; // out of bound - - static std::vector generators(2 * c_bpp_mn_max); - static bool calculated = false; - if (!calculated) - { - scalar_t hash_buf[2] = { hash_helper_t::hs("Zano BP+ generator"), 0 }; - for (size_t i = 0; i < 2 * c_bpp_mn_max; ++i) - { - hash_buf[1].m_u64[0] = i; - ge_bytes_hash_to_ec(&generators[i].m_p3, &hash_buf, sizeof hash_buf); - } - calculated = true; - } - - return generators[2 * index + (select_H ? 1 : 0)]; - } - - static const point_t& bpp_H; - }; - - - struct bpp_signature - { - std::vector L; // size = log_2(m * n) - std::vector R; - public_key A0; - public_key A; - public_key B; - scalar_t r; - scalar_t s; - scalar_t delta; - }; - -#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL -#define DBG_PRINT(x) std::cout << x << ENDL - - template - bool bpp_gen(const std::vector& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) - { -#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ - if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ - if (p_err) { *p_err = err_code; } return false; } - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= c_bpp_values_max && values.size() == masks.size(), 1); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); - - const size_t c_bpp_log2_m = calc_exp_power_of_2_upper_bound(values.size()); - const size_t c_bpp_m = 1ull << c_bpp_log2_m; - const size_t c_bpp_mn = c_bpp_m * c_bpp_n; - const size_t c_bpp_log2_mn = c_bpp_log2_m + c_bpp_log2_n; - - // pre-multiply all output points by c_scalar_1div8 - // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) - - // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H - commitments.resize(values.size()); - for (size_t i = 0; i < values.size(); ++i) - CT::calc_pedersen_commitment(scalar_t(values[i]) * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]); - - - // s.a. BP+ paper, page 15, eq. 11 - // decompose v into aL and aR: - // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product - // aR = aL - (1, 1, ... 1) - // aR o aL = 0 - - // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar - - scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); - aLs.zero(); - aRs.zero(); - // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) - for (size_t i = 0; i < values.size(); ++i) - { - uint64_t v = values[i]; - for (size_t j = 0; j < c_bpp_n; ++j) - { - if (v & 1) - aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 - else - aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 - v >>= 1; - } - } - - for (size_t i = values.size(); i < c_bpp_m; ++i) - for (size_t j = 0; j < c_bpp_n; ++j) - aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 - - - // using e as Fiat-Shamir transcript - scalar_t e = CT::get_initial_transcript(); - DBG_PRINT("initial transcript: " << e); - - hash_helper_t::hs_t hsc; - CT::update_transcript(hsc, e, commitments); - - // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) - // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) - - scalar_t alpha = scalar_t::random(); - point_t A0 = alpha * CT::bpp_H; - - for (size_t i = 0; i < c_bpp_mn; ++i) - A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); - - // part of 1/8 defense scheme - A0 *= c_scalar_1div8; - A0.to_public_key(sig.A0); - - DBG_VAL_PRINT(alpha); - DBG_VAL_PRINT(A0); - - // calculate scalar challenges y and z - hsc.add_scalar(e); - hsc.add_pub_key(sig.A0); - scalar_t y = hsc.calc_hash(); - scalar_t z = hash_helper_t::hs(y); - e = z; // transcript for further steps - DBG_VAL_PRINT(y); - DBG_VAL_PRINT(z); - - // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) - // (note: elements is stored column-by-column in memory) - // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | - // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | - // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | - // | ....................................................................................... | - // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | - // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) - - scalar_t z_sq = z * z; - scalar_mat_t d(c_bpp_mn); - d(0, 0) = z_sq; - // first row - for (size_t i = 1; i < c_bpp_m; ++i) - d(i, 0) = d(i - 1, 0) * z_sq; - // all rows - for (size_t j = 1; j < c_bpp_n; ++j) - for (size_t i = 0; i < c_bpp_m; ++i) - d(i, j) = d(i, j - 1) + d(i, j - 1); - - DBG_PRINT("Hs(d): " << d.calc_hs()); - - // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) - // (calculate two more elements (1 and y^(mn+1)) for convenience) - scalar_vec_t y_powers(c_bpp_mn + 2); - y_powers[0] = 1; - for (size_t i = 1; i <= c_bpp_mn + 1; ++i) - y_powers[i] = y_powers[i - 1] * y; - - const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; - - DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); - - // aL_hat = aL - 1*z - scalar_vec_t aLs_hat = aLs - z; - // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) - scalar_vec_t aRs_hat = aRs + z; - for (size_t i = 0; i < c_bpp_mn; ++i) - aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; - - DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); - DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); - - // calculate alpha_hat - // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m - // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j - scalar_t alpha_hat = 0; - for (size_t i = 0; i < masks.size(); ++i) - alpha_hat += d(i, 0) * masks[i]; - alpha_hat = alpha + y_mn_p1 * alpha_hat; - - DBG_VAL_PRINT(alpha_hat); - - // calculate y^-1, y^-2, ... - const scalar_t y_inverse = y.reciprocal(); - scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) - y_inverse_powers[0] = 1; - for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) - y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; - - // prepare generator's vector - std::vector g(c_bpp_mn), h(c_bpp_mn); - for (size_t i = 0; i < c_bpp_mn; ++i) - { - g[i] = CT::get_generator(false, i); - h[i] = CT::get_generator(true, i); - } - - // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) - - scalar_vec_t& a = aLs_hat; - scalar_vec_t& b = aRs_hat; - - sig.L.resize(c_bpp_log2_mn); - sig.R.resize(c_bpp_log2_mn); - - // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) - for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) - { - DBG_PRINT(ENDL << "#" << ni); - - // zk-WIP(g, h, G, H, P, a, b, alpha) - - scalar_t dL = scalar_t::random(); - DBG_VAL_PRINT(dL); - scalar_t dR = scalar_t::random(); - DBG_VAL_PRINT(dR); - - // a = (a1, a2), b = (b1, b2) -- vectors of scalars - // cL = -- scalar - scalar_t cL = 0; - for (size_t i = 0; i < n; ++i) - cL += a[i] * y_powers[i + 1] * b[n + i]; - - DBG_VAL_PRINT(cL); - - // cR = * y^n -- scalar - scalar_t cR = 0; - for (size_t i = 0; i < n; ++i) - cR += a[n + i] * y_powers[i + 1] * b[i]; - cR *= y_powers[n]; - - DBG_VAL_PRINT(cR); - - // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point - point_t sum = c_point_0; - for (size_t i = 0; i < n; ++i) - sum += a[i] * g[n + i]; - point_t L; - CT::calc_pedersen_commitment(cL, dL, L); - for (size_t i = 0; i < n; ++i) - L += b[n + i] * h[i]; - L += y_inverse_powers[n] * sum; - L *= c_scalar_1div8; - DBG_VAL_PRINT(L); - - // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point - sum.zero(); - for (size_t i = 0; i < n; ++i) - sum += a[n + i] * g[i]; - point_t R; - CT::calc_pedersen_commitment(cR, dR, R); - for (size_t i = 0; i < n; ++i) - R += b[i] * h[n + i]; - R += y_powers[n] * sum; - R *= c_scalar_1div8; - DBG_VAL_PRINT(R); - - // put L, R to the sig - L.to_public_key(sig.L[ni]); - R.to_public_key(sig.R[ni]); - - // update the transcript - hsc.add_scalar(e); - hsc.add_pub_key(sig.L[ni]); - hsc.add_pub_key(sig.R[ni]); - e = hsc.calc_hash(); - DBG_VAL_PRINT(e); - - // recalculate arguments for the next round - scalar_t e_squared = e * e; - scalar_t e_inverse = e.reciprocal(); - scalar_t e_inverse_squared = e_inverse * e_inverse; - scalar_t e_y_inv_n = e * y_inverse_powers[n]; - scalar_t e_inv_y_n = e_inverse * y_powers[n]; - - // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points - for (size_t i = 0; i < n; ++i) - g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; - - // h_hat = e * h1 + e^-1 * h2 -- vector of points - for (size_t i = 0; i < n; ++i) - h[i] = e * h[i] + e_inverse * h[n + i]; - - // P_hat = e^2 * L + P + e^-2 * R -- point - - // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars - for (size_t i = 0; i < n; ++i) - a[i] = e * a[i] + e_inv_y_n * a[n + i]; - - // b_hat = e^-1 * b1 + e * b2 -- vector of scalars - for (size_t i = 0; i < n; ++i) - b[i] = e_inverse * b[i] + e * b[n + i]; - - // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar - alpha_hat += e_squared * dL + e_inverse_squared * dR; - - // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) - } - DBG_PRINT(""); - - // zk-WIP last round - scalar_t r = scalar_t::random(); - scalar_t s = scalar_t::random(); - scalar_t delta = scalar_t::random(); - scalar_t eta = scalar_t::random(); - DBG_VAL_PRINT(r); - DBG_VAL_PRINT(s); - DBG_VAL_PRINT(delta); - DBG_VAL_PRINT(eta); - - // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point - point_t A = c_point_0; - CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); - A += r * g[0] + s * h[0]; - A *= c_scalar_1div8; - A.to_public_key(sig.A); - DBG_VAL_PRINT(A); - - // B = (r * y * s) * G + eta * H - point_t B = c_point_0; - CT::calc_pedersen_commitment(r * y * s, eta, B); - B *= c_scalar_1div8; - B.to_public_key(sig.B); - DBG_VAL_PRINT(B); - - // update the transcript - hsc.add_scalar(e); - hsc.add_pub_key(sig.A); - hsc.add_pub_key(sig.B); - e = hsc.calc_hash(); - DBG_VAL_PRINT(e); - - // finalize the signature - sig.r = r + e * a[0]; - sig.s = s + e * b[0]; - sig.delta = eta + e * delta + e * e * alpha_hat; - DBG_VAL_PRINT(sig.r); - DBG_VAL_PRINT(sig.s); - DBG_VAL_PRINT(sig.delta); - - return true; -#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE - } // bpp_gen() - - - // efficient multiexponentiation (naive stub implementation atm, TODO) - template - bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) - { - CHECK_AND_ASSERT_MES(g_scalars.size() < c_bpp_mn_max, false, "g_scalars oversized"); - CHECK_AND_ASSERT_MES(h_scalars.size() < c_bpp_mn_max, false, "h_scalars oversized"); - - point_t result = summand; - - for (size_t i = 0; i < g_scalars.size(); ++i) - result += g_scalars[i] * CT::get_generator(false, i); - - for (size_t i = 0; i < h_scalars.size(); ++i) - result += h_scalars[i] * CT::get_generator(true, i); - - if (!result.is_zero()) - { - LOG_PRINT_L0("multiexp result is non zero: " << result); - return false; - } - return true; - } - - - struct bpp_sig_commit_ref_t - { - bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) - : sig(sig) - , commitments(commitments) - {} - const bpp_signature& sig; - const std::vector& commitments; - }; - - - template - bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) - { -#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ - if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ - if (p_err) { *p_err = err_code; } return false; } - - DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); - - const size_t kn = sigs.size(); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); - - struct intermediate_element_t - { - scalar_t y; - scalar_t z; - scalar_t z_sq; - scalar_vec_t e; - scalar_vec_t e_sq; - scalar_t e_final; - scalar_t e_final_sq; - size_t inv_e_offset; // offset in batch_for_inverse - size_t inv_y_offset; // offset in batch_for_inverse - size_t c_bpp_log2_m; - size_t c_bpp_m; - size_t c_bpp_mn; - point_t A; - point_t A0; - point_t B; - std::vector L; - std::vector R; - }; - std::vector interms(kn); - - size_t c_bpp_log2_m_max = 0; - for (size_t k = 0; k < kn; ++k) - { - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); - - intermediate_element_t& interm = interms[k]; - interm.c_bpp_log2_m = calc_exp_power_of_2_upper_bound(bsc.commitments.size()); - if (c_bpp_log2_m_max < interm.c_bpp_log2_m) - c_bpp_log2_m_max = interm.c_bpp_log2_m; - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + c_bpp_log2_n, 5); - - interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; - interm.c_bpp_mn = interm.c_bpp_m * c_bpp_n; - - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); - interm.L.resize(sig.L.size()); - interm.R.resize(sig.R.size()); - for (size_t i = 0; i < interm.L.size(); ++i) - { - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); - CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); - } - } - const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; - const size_t c_bpp_mn_max = c_bpp_m_max * c_bpp_n; - const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + c_bpp_log2_n; - - - // - // prepare stuff - // - /* - std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); - for (size_t i = 0; i < c_bpp_mn_max; ++i) - { - g[i] = CT::get_generator(false, i); - h[i] = CT::get_generator(true, i); - } - */ - - scalar_vec_t batch_for_inverse; - batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); - - - for (size_t k = 0; k < kn; ++k) - { - DBG_PRINT(ENDL << "SIG #" << k); - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - intermediate_element_t& interm = interms[k]; - - // restore y and z - // using e as Fiat-Shamir transcript - scalar_t e = CT::get_initial_transcript(); - DBG_PRINT("initial transcript: " << e); - hash_helper_t::hs_t hsc; - CT::update_transcript(hsc, e, bsc.commitments); - // calculate scalar challenges y and z - hsc.add_scalar(e); - hsc.add_pub_key(sig.A0); - hsc.assign_calc_hash(interm.y); - interm.z = hash_helper_t::hs(interm.y); - interm.z_sq = interm.z * interm.z; - DBG_VAL_PRINT(interm.y); - DBG_VAL_PRINT(interm.z); - e = interm.z; // transcript for further steps - - interm.inv_y_offset = batch_for_inverse.size(); - batch_for_inverse.push_back(interm.y); - interm.inv_e_offset = batch_for_inverse.size(); - - interm.e.resize(sig.L.size()); - interm.e_sq.resize(sig.L.size()); - - for (size_t i = 0; i < sig.L.size(); ++i) - { - hsc.add_scalar(e); - hsc.add_pub_key(sig.L[i]); - hsc.add_pub_key(sig.R[i]); - hsc.assign_calc_hash(e); - interm.e[i] = e; - interm.e_sq[i] = e * e; - DBG_PRINT("e[" << i << "]: " << e); - batch_for_inverse.push_back(e); - } - - hsc.add_scalar(e); - hsc.add_pub_key(sig.A); - hsc.add_pub_key(sig.B); - hsc.assign_calc_hash(interm.e_final); - interm.e_final_sq = interm.e_final * interm.e_final; - DBG_VAL_PRINT(interm.e_final); - } - - batch_for_inverse.invert(); - - // Notation: - // 1_vec ^ n = (1, 1, 1, ..., 1) - // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) - // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) - // y<^n = (y^n, y^(n-1), ..., y^1) - // y>^n = (y^1, y^2, ..., y^n) - - // from page 13, Fig 1: - // Verifier outputs Accept IFF the following equality holds (single proof): - // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' - // (where g and h are calculated in each round) - // The same equation in additive notation: - // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - // <=> - // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) - // where A, B, r', s', delta' is taken from the signature - // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds - // - // from page 18, Fig 3: - // P and V computes: - // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + - // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + - // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G - // (calculated once) - // - // As suggested in Section 6.1 "Practical Optimizations": - // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): - // - // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - - // - e^2 * A_hat - // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) - // - e * A - B = 0 (**) - // - // where: - // g, h - vector of fixed generators - // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) - // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) - // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) - // b(i, j) = { 2 * ((1< - - // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - - // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + - // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + - // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G - // ) - // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) - // - e * A - B = 0 - - // => - - // (for single signature) - // - // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are - // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators - // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all - // + delta' * H | the signatures - // - // - e^2 * A0 - // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) - // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) - // - e * A - B = 0 (***) - // - // All (***) will be muptiplied by random weightning factor and then summed up. - - // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. - scalar_vec_t g_scalars; - g_scalars.resize(c_bpp_mn_max, 0); - scalar_vec_t h_scalars; - h_scalars.resize(c_bpp_mn_max, 0); - scalar_t G_scalar = 0; - scalar_t H_scalar = 0; - point_t summand = c_point_0; - - for (size_t k = 0; k < kn; ++k) - { - DBG_PRINT(ENDL << "SIG #" << k); - const bpp_sig_commit_ref_t& bsc = sigs[k]; - const bpp_signature& sig = bsc.sig; - intermediate_element_t& interm = interms[k]; - - // random weightning factor for speed-optimized batch verification (preprint page 20) - const scalar_t rwf = scalar_t::random(); - DBG_PRINT("rwf: " << rwf); - - // prepare d vector (see also d structure description in proof function) - scalar_mat_t d(interm.c_bpp_mn); - d(0, 0) = interm.z_sq; - // first row - for (size_t i = 1; i < interm.c_bpp_m; ++i) - d(i, 0) = d(i - 1, 0) * interm.z_sq; - // all rows - for (size_t j = 1; j < c_bpp_n; ++j) - for (size_t i = 0; i < interm.c_bpp_m; ++i) - d(i, j) = d(i, j - 1) + d(i, j - 1); - // sum(d) (see also note in proof function for this) - static const scalar_t c_scalar_2_power_n_minus_1 = { 0xffffffffffffffff, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; - const scalar_t sum_d = c_scalar_2_power_n_minus_1 * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); - - DBG_PRINT("Hs(d): " << d.calc_hs()); - DBG_PRINT("sum(d): " << sum_d); - - const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; - auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] - - // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) - // complexity (sc_mul's): MN+2*log2(MN)-2 - // the idea is the following: - // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 - // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 - const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n - scalar_vec_t s_vec(interm.c_bpp_mn); - s_vec[0] = get_e_inv(0); - for (size_t i = 1; i < log2_mn; ++i) - s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 - DBG_PRINT("[0] " << s_vec[0]); - for (size_t i = 1; i < interm.c_bpp_mn; ++i) - { - size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) - size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base - s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 - DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); - } - - // prepare y_inv vector - scalar_vec_t y_inverse_powers(interm.c_bpp_mn); - y_inverse_powers[0] = 1; - for (size_t i = 1; i < interm.c_bpp_mn; ++i) - y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; - - // y^(mn+1) - scalar_t y_power_mnp1 = interm.y; - for (size_t i = 0; i < log2_mn; ++i) - y_power_mnp1 *= y_power_mnp1; - y_power_mnp1 *= interm.y; - DBG_VAL_PRINT(y_power_mnp1); - - // now calculate all multiplicands for common generators - - // g vector multiplicands: - // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = - // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) - scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; - scalar_t rwf_r_e = rwf * interm.e_final * sig.r; - for (size_t i = 0; i < interm.c_bpp_mn; ++i) - g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; - - DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); - - // h vector multiplicands: - // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) - // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) - //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; - scalar_t rwf_s_e = rwf * sig.s * interm.e_final; - scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; - for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) - { - h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; - rwf_e_sq_y *= interm.y; - } - - DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); - - // G point multiplicands: - // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = - // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) - G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; - G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); - DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); - DBG_PRINT("G_scalar: " << G_scalar); - - // H point multiplicands: - // rwf * delta - H_scalar += rwf * sig.delta; - DBG_PRINT("H_scalar: " << H_scalar); - - // uncommon generators' multiplicands - point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand - // - rwf * e^2 * A0 - summand_8 -= rwf * interm.e_final_sq * interm.A0; - DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); - - // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) - scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; - for (size_t j = 0; j < bsc.commitments.size(); ++j) - { - e_sq_y_mn1_z_sq_power *= interm.z_sq; - summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; - DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); - } - - // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) - scalar_t rwf_e_sq = rwf * interm.e_final_sq; - for (size_t j = 0; j < log2_mn; ++j) - { - summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); - DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); - DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); - } - - // - rwf * e * A - rwf * B = 0 - summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; - DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); - DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); - - summand_8.modify_mul8(); - summand += summand_8; - } - - point_t GH_exponents = c_point_0; - CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); - bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); - if (result) - DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); - return result; -#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE - } - -} // namespace crypto diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c deleted file mode 100644 index 87423fb..0000000 --- a/src/crypto/tree-hash.c +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include - -#include "hash-ops.h" - -void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) { - assert(count > 0); - if (count == 1) { - memcpy(root_hash, hashes, HASH_SIZE); - } else if (count == 2) { - cn_fast_hash(hashes, 2 * HASH_SIZE, root_hash); - } else { - size_t i, j; - size_t cnt = count - 1; - char (*ints)[HASH_SIZE]; - for (i = 1; i < 8 * sizeof(size_t); i <<= 1) { - cnt |= cnt >> i; - } - cnt &= ~(cnt >> 1); - ints = alloca(cnt * HASH_SIZE); - memcpy(ints, hashes, (2 * cnt - count) * HASH_SIZE); - for (i = 2 * cnt - count, j = 2 * cnt - count; j < cnt; i += 2, ++j) { - cn_fast_hash(hashes[i], 64, ints[j]); - } - assert(i == count); - while (cnt > 2) { - cnt >>= 1; - for (i = 0, j = 0; j < cnt; i += 2, ++j) { - cn_fast_hash(ints[i], 64, ints[j]); - } - } - cn_fast_hash(ints[0], 64, root_hash); - } -} diff --git a/src/currency_core/account.cpp b/src/currency_core/account.cpp deleted file mode 100644 index def2025..0000000 --- a/src/currency_core/account.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include - -#include "include_base_utils.h" -#include "account.h" -#include "warnings.h" -#include "crypto/crypto.h" -#include "currency_core/currency_format_utils.h" -#include "common/mnemonic-encoding.h" - -using namespace std; - -//DISABLE_VS_WARNINGS(4244 4345) - -namespace currency -{ - //----------------------------------------------------------------- - account_base::account_base() - { - set_null(); - } - //----------------------------------------------------------------- - void account_base::set_null() - { - // fill sensitive data with random bytes - crypto::generate_random_bytes(sizeof m_keys.spend_secret_key, &m_keys.spend_secret_key); - crypto::generate_random_bytes(sizeof m_keys.view_secret_key, &m_keys.view_secret_key); - if (m_keys_seed_binary.size()) - crypto::generate_random_bytes(m_keys_seed_binary.size(), &m_keys_seed_binary[0]); - - // clear - m_keys = account_keys(); - m_creation_timestamp = 0; - m_keys_seed_binary.clear(); - } - //----------------------------------------------------------------- - void account_base::generate(bool auditable /* = false */) - { - if (auditable) - m_keys.account_address.flags = ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE; - - crypto::generate_seed_keys(m_keys.account_address.spend_public_key, m_keys.spend_secret_key, m_keys_seed_binary, BRAINWALLET_DEFAULT_SEED_SIZE); - crypto::dependent_key(m_keys.spend_secret_key, m_keys.view_secret_key); - if (!crypto::secret_key_to_public_key(m_keys.view_secret_key, m_keys.account_address.view_public_key)) - throw std::runtime_error("Failed to create public view key"); - - - m_creation_timestamp = time(NULL); - } - //----------------------------------------------------------------- - const account_keys& account_base::get_keys() const - { - return m_keys; - } - //----------------------------------------------------------------- - void crypt_with_pass(const void* scr_data, std::size_t src_length, void* dst_data, const std::string& password) - { - crypto::chacha8_key key = AUTO_VAL_INIT(key); - crypto::generate_chacha8_key(password, key); - crypto::hash pass_hash = crypto::cn_fast_hash(password.data(), password.size()); - crypto::chacha8_iv iv = AUTO_VAL_INIT(iv); - CHECK_AND_ASSERT_THROW_MES(sizeof(pass_hash) >= sizeof(iv), "Invalid configuration: hash size is less than keys_file_data.iv"); - iv = *((crypto::chacha8_iv*)&pass_hash); - crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data); - } - //----------------------------------------------------------------- - std::string account_base::get_seed_phrase(const std::string& password) const - { - if (m_keys_seed_binary.empty()) - return ""; - - std::vector processed_seed_binary = m_keys_seed_binary; - if (!password.empty()) - { - //encrypt seed phrase binary data - crypt_with_pass(&m_keys_seed_binary[0], m_keys_seed_binary.size(), &processed_seed_binary[0], password); - } - - std::string keys_seed_text = tools::mnemonic_encoding::binary2text(processed_seed_binary); - std::string timestamp_word = currency::get_word_from_timstamp(m_creation_timestamp, !password.empty()); - - // floor creation time to WALLET_BRAIN_DATE_QUANTUM to make checksum calculation stable - bool self_check_is_password_used = false; - uint64_t creation_timestamp_rounded = get_timstamp_from_word(timestamp_word, self_check_is_password_used); - CHECK_AND_ASSERT_THROW_MES(self_check_is_password_used == !password.empty(), "Account seed phrase internal error: password flag encoded wrong"); - - constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum - std::string binary_for_check_sum((const char*)&m_keys_seed_binary[0], m_keys_seed_binary.size()); - binary_for_check_sum.append(password); - crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size()); - *reinterpret_cast(&h) = creation_timestamp_rounded; - h = crypto::cn_fast_hash(&h, sizeof h); - uint64_t h_64 = *reinterpret_cast(&h); - uint16_t checksum = h_64 % (checksum_max + 1); - - uint8_t auditable_flag = 0; - if (m_keys.account_address.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) - auditable_flag = 1; - - uint32_t auditable_flag_and_checksum = (auditable_flag & 1) | (checksum << 1); - std::string auditable_flag_and_checksum_word = tools::mnemonic_encoding::word_by_num(auditable_flag_and_checksum); - - return keys_seed_text + " " + timestamp_word + " " + auditable_flag_and_checksum_word; - } - //----------------------------------------------------------------- - std::string account_base::get_tracking_seed() const - { - return get_public_address_str() + ":" + - epee::string_tools::pod_to_hex(m_keys.view_secret_key) + - (m_creation_timestamp ? ":" : "") + (m_creation_timestamp ? epee::string_tools::num_to_string_fast(m_creation_timestamp) : ""); - } - //----------------------------------------------------------------- - bool account_base::restore_keys(const std::vector& keys_seed_binary) - { - CHECK_AND_ASSERT_MES(keys_seed_binary.size() == BRAINWALLET_DEFAULT_SEED_SIZE, false, "wrong restore data size: " << keys_seed_binary.size()); - crypto::keys_from_default(keys_seed_binary.data(), m_keys.account_address.spend_public_key, m_keys.spend_secret_key, keys_seed_binary.size()); - crypto::dependent_key(m_keys.spend_secret_key, m_keys.view_secret_key); - bool r = crypto::secret_key_to_public_key(m_keys.view_secret_key, m_keys.account_address.view_public_key); - CHECK_AND_ASSERT_MES(r, false, "failed to secret_key_to_public_key for view key"); - return true; - } - //----------------------------------------------------------------- - bool account_base::restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password) - { - //cut the last timestamp word from restore_dats - std::list words; - boost::split(words, seed_phrase, boost::is_space()); - - std::string keys_seed_text, timestamp_word, auditable_flag_and_checksum_word; - if (words.size() == SEED_PHRASE_V1_WORDS_COUNT) - { - // 24 seed words + one timestamp word = 25 total - timestamp_word = words.back(); - words.erase(--words.end()); - keys_seed_text = boost::algorithm::join(words, " "); - } - else if (words.size() == SEED_PHRASE_V2_WORDS_COUNT) - { - // 24 seed words + one timestamp word + one flags & checksum = 26 total - auditable_flag_and_checksum_word = words.back(); - words.erase(--words.end()); - timestamp_word = words.back(); - words.erase(--words.end()); - keys_seed_text = boost::algorithm::join(words, " "); - } - else - { - LOG_ERROR("Invalid seed words count: " << words.size()); - return false; - } - - uint64_t auditable_flag_and_checksum = UINT64_MAX; - if (!auditable_flag_and_checksum_word.empty()) - { - try { - auditable_flag_and_checksum = tools::mnemonic_encoding::num_by_word(auditable_flag_and_checksum_word); - } - catch (...) - { - return false; - } - - } - - - std::vector keys_seed_binary = tools::mnemonic_encoding::text2binary(keys_seed_text); - std::vector keys_seed_processed_binary = keys_seed_binary; - - - bool has_password = false; - try { - m_creation_timestamp = get_timstamp_from_word(timestamp_word, has_password); - } - catch (...) - { - return false; - } - //double check is password setting from timestamp word match with passed parameters - CHECK_AND_ASSERT_MES(has_password != seed_password.empty(), false, "Seed phrase password wrong interpretation"); - if (has_password) - { - CHECK_AND_ASSERT_MES(!seed_password.empty(), false, "Seed phrase password wrong interpretation: internal error"); - crypt_with_pass(&keys_seed_binary[0], keys_seed_binary.size(), &keys_seed_processed_binary[0], seed_password); - } - - CHECK_AND_ASSERT_MES(keys_seed_processed_binary.size(), false, "text2binary failed to convert the given text"); // don't prints event incorrect seed into the log for security - - bool auditable_flag = false; - - // check the checksum if checksum word provided - if (auditable_flag_and_checksum != UINT64_MAX) - { - auditable_flag = (auditable_flag_and_checksum & 1) != 0; // auditable flag is the lower 1 bit - uint16_t checksum = static_cast(auditable_flag_and_checksum >> 1); // checksum -- everything else - constexpr uint16_t checksum_max = tools::mnemonic_encoding::NUMWORDS >> 1; // maximum value of checksum - std::string binary_for_check_sum((const char*)&keys_seed_processed_binary[0], keys_seed_processed_binary.size()); - binary_for_check_sum.append(seed_password); - crypto::hash h = crypto::cn_fast_hash(binary_for_check_sum.data(), binary_for_check_sum.size()); - *reinterpret_cast(&h) = m_creation_timestamp; - h = crypto::cn_fast_hash(&h, sizeof h); - uint64_t h_64 = *reinterpret_cast(&h); - uint16_t checksum_calculated = h_64 % (checksum_max + 1); - if (checksum != checksum_calculated) - { - LOG_PRINT_L0("seed phase has invalid checksum: " << checksum_calculated << ", while " << checksum << " is expected, check your words"); - return false; - } - } - - bool r = restore_keys(keys_seed_processed_binary); - CHECK_AND_ASSERT_MES(r, false, "restore_keys failed"); - - m_keys_seed_binary = keys_seed_processed_binary; - - if (auditable_flag) - m_keys.account_address.flags |= ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE; - - return true; - } - //----------------------------------------------------------------- - bool account_base::is_seed_tracking(const std::string& seed_phrase) - { - return seed_phrase.find(':') != std::string::npos; - } - //----------------------------------------------------------------- - bool account_base::is_seed_password_protected(const std::string& seed_phrase, bool& is_password_protected) - { - //cut the last timestamp word from restore_dats - std::list words; - boost::split(words, seed_phrase, boost::is_space()); - - //let's validate each word - for (const auto& w: words) - { - if (!tools::mnemonic_encoding::valid_word(w)) - return false; - } - - std::string timestamp_word; - if (words.size() == SEED_PHRASE_V1_WORDS_COUNT) - { - // 24 seed words + one timestamp word = 25 total - timestamp_word = words.back(); - } - else if (words.size() == SEED_PHRASE_V2_WORDS_COUNT) - { - // 24 seed words + one timestamp word + one flags & checksum = 26 total - words.erase(--words.end()); - timestamp_word = words.back(); - } - else - { - return false; - } - - get_timstamp_from_word(timestamp_word, is_password_protected); - - return true; - } - //----------------------------------------------------------------- - bool account_base::restore_from_tracking_seed(const std::string& tracking_seed) - { - set_null(); - bool r = parse_tracking_seed(tracking_seed, m_keys.account_address, m_keys.view_secret_key, m_creation_timestamp); - return r; - } - //----------------------------------------------------------------- - std::string account_base::get_public_address_str() const - { - //TODO: change this code into base 58 - return get_account_address_as_str(m_keys.account_address); - } - //----------------------------------------------------------------- - void account_base::make_account_watch_only() - { - // keep only: - // timestamp - // view pub & spend pub + flags (public address) - // view sec - - // store to local tmp - uint64_t local_ts = m_creation_timestamp; - account_public_address local_addr = m_keys.account_address; - crypto::secret_key local_view_sec = m_keys.view_secret_key; - - // clear - set_null(); - - // restore - m_creation_timestamp = local_ts; - m_keys.account_address = local_addr; - m_keys.view_secret_key = local_view_sec; - } - //----------------------------------------------------------------- - std::string transform_addr_to_str(const account_public_address& addr) - { - return get_account_address_as_str(addr); - } - //----------------------------------------------------------------- - account_public_address transform_str_to_addr(const std::string& str) - { - account_public_address ad = AUTO_VAL_INIT(ad); - if (!get_account_address_from_str(ad, str)) - { - CHECK_AND_ASSERT_THROW_MES(false, "cannot parse address from string: " << str); - } - return ad; - } -} \ No newline at end of file diff --git a/src/currency_core/account.h b/src/currency_core/account.h deleted file mode 100644 index 37a0c95..0000000 --- a/src/currency_core/account.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "currency_core/currency_basic.h" -#include "crypto/crypto.h" -#include "serialization/keyvalue_serialization.h" - -#define BRAINWALLET_DEFAULT_SEED_SIZE 32 -#define ACCOUNT_RESTORE_DATA_SIZE BRAINWALLET_DEFAULT_SEED_SIZE -#define SEED_PHRASE_V1_WORDS_COUNT 25 -#define SEED_PHRASE_V2_WORDS_COUNT 26 - - -#ifndef FORCE_HEADER_ONLY - #define KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, val_name) \ - KV_SERIALIZE_CUSTOM_N(varialble, std::string, currency::transform_addr_to_str, currency::transform_str_to_addr, val_name) - - #define KV_SERIALIZE_ADDRESS_AS_TEXT(varialble) KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, #varialble) -#else - #define KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, val_name) - #define KV_SERIALIZE_ADDRESS_AS_TEXT(varialble) -#endif -namespace currency -{ - - - - struct account_keys - { - account_public_address account_address; - crypto::secret_key spend_secret_key; - crypto::secret_key view_secret_key; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_N(account_address, "m_account_address") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(spend_secret_key, "m_spend_secret_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(view_secret_key, "m_view_secret_key") - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class account_base - { - public: - account_base(); - void generate(bool auditable = false); - const account_keys& get_keys() const; - const account_public_address& get_public_address() const { return m_keys.account_address; }; - std::string get_public_address_str() const; - - std::string get_seed_phrase(const std::string& seed_password) const; - std::string get_tracking_seed() const; - bool restore_from_seed_phrase(const std::string& seed_phrase, const std::string& seed_password); - bool restore_from_tracking_seed(const std::string& tracking_seed); - - uint64_t get_createtime() const { return m_creation_timestamp; } - void set_createtime(uint64_t val) { m_creation_timestamp = val; } - - bool load(const std::string& file_path); - bool store(const std::string& file_path); - - void make_account_watch_only(); - bool is_watch_only() const { return m_keys.spend_secret_key == currency::null_skey; } - bool is_auditable() const { return m_keys.account_address.is_auditable(); } - - template - inline void serialize(t_archive &a, const unsigned int /*ver*/) - { - a & m_keys; - a & m_creation_timestamp; - a & m_keys_seed_binary; - } - - static std::string vector_of_chars_to_string(const std::vector& v) { return std::string(v.begin(), v.end()); } - static std::vector string_to_vector_of_chars(const std::string& v) { return std::vector(v.begin(), v.end()); } - static bool is_seed_password_protected(const std::string& seed_phrase, bool& is_password_protected); - static bool is_seed_tracking(const std::string& seed_phrase); - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_keys) - KV_SERIALIZE(m_creation_timestamp) - KV_SERIALIZE_CUSTOM_N(m_keys_seed_binary, std::string, vector_of_chars_to_string, string_to_vector_of_chars, "m_seed") - END_KV_SERIALIZE_MAP() - - private: - void set_null(); - bool restore_keys(const std::vector& keys_seed_binary); - - account_keys m_keys; - uint64_t m_creation_timestamp; - - std::vector m_keys_seed_binary; - }; - - const static account_keys null_acc_keys = AUTO_VAL_INIT(null_acc_keys); - - std::string transform_addr_to_str(const account_public_address& addr); - account_public_address transform_str_to_addr(const std::string& str); - - inline bool operator==(const account_keys& lhs, const account_keys& rhs) - { - return lhs.account_address == rhs.account_address && - lhs.spend_secret_key == rhs.spend_secret_key && - lhs.view_secret_key == rhs.view_secret_key; - } - inline bool operator!=(const account_keys& lhs, const account_keys& rhs) - { - return !operator==(lhs, rhs); - } -} diff --git a/src/currency_core/account_boost_serialization.h b/src/currency_core/account_boost_serialization.h deleted file mode 100644 index f0f2d63..0000000 --- a/src/currency_core/account_boost_serialization.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "account.h" -#include "currency_core/currency_boost_serialization.h" - -//namespace currency { -namespace boost -{ - namespace serialization - { - template - inline void serialize(Archive &a, currency::account_keys &x, const boost::serialization::version_type ver) - { - a & x.account_address; - a & x.spend_secret_key; - a & x.view_secret_key; - } - - } -} diff --git a/src/currency_core/alias_helper.h b/src/currency_core/alias_helper.h deleted file mode 100644 index 3bc5b33..0000000 --- a/src/currency_core/alias_helper.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "currency_core/currency_basic.h" -#include "rpc/core_rpc_server_commands_defs.h" -#include "wallet/core_rpc_proxy.h" -//--------------------------------------------------------------- -namespace tools -{ - template - bool get_transfer_address_cb(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id, callback_t cb) - { - if (!adr_str.size()) - return false; - - std::string addr_str_local = adr_str; - - if (adr_str[0] == '@') - { - //referred by alias name - if (adr_str.size() < 2) - return false; - std::string pure_alias_name = adr_str.substr(1); - CHECK_AND_ASSERT_MES(currency::validate_alias_name(pure_alias_name), false, "wrong name set in transfer command"); - - - currency::COMMAND_RPC_GET_ALIAS_DETAILS::request req_alias_info = AUTO_VAL_INIT(req_alias_info); - req_alias_info.alias = pure_alias_name; - currency::COMMAND_RPC_GET_ALIAS_DETAILS::response alias_info = AUTO_VAL_INIT(alias_info); - - if (!cb(req_alias_info, alias_info)) - return false; - - if (alias_info.status != API_RETURN_CODE_OK || !alias_info.alias_details.address.size()) - return false; - - addr_str_local = alias_info.alias_details.address; - } - - return get_account_address_and_payment_id_from_str(addr, payment_id, addr_str_local); - } - - inline - bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id, i_core_proxy* proxy) - { - return get_transfer_address_cb(adr_str, addr, payment_id, [&proxy](currency::COMMAND_RPC_GET_ALIAS_DETAILS::request& req_alias_info, - currency::COMMAND_RPC_GET_ALIAS_DETAILS::response& alias_info) - { - return proxy->call_COMMAND_RPC_GET_ALIAS_DETAILS(req_alias_info, alias_info); - }); - } - - /* - inline - bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, epee::net_utils::http::http_simple_client& http_client, const std::string& daemon_address) - { - return get_transfer_address_cb(adr_str, addr, [&http_client, &daemon_address](currency::COMMAND_RPC_GET_ALIAS_DETAILS::request& req_alias_info, - currency::COMMAND_RPC_GET_ALIAS_DETAILS::response& alias_info) - { - return epee::net_utils::invoke_http_json_rpc(daemon_address + "/json_rpc", "get_alias_details", req_alias_info, alias_info, http_client); - }); - } - */ -} - - - diff --git a/src/currency_core/basic_api_response_codes.h b/src/currency_core/basic_api_response_codes.h deleted file mode 100644 index bb1cafe..0000000 --- a/src/currency_core/basic_api_response_codes.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - - -#define BASIC_RESPONSE_STATUS_OK "OK" -#define BASIC_RESPONSE_STATUS_BUSY "BUSY" -#define BASIC_RESPONSE_STATUS_NOT_FOUND "NOT_FOUND" -#define BASIC_RESPONSE_STATUS_FAILED "FAILED" diff --git a/src/currency_core/basic_kv_structs.h b/src/currency_core/basic_kv_structs.h deleted file mode 100644 index 1ff520c..0000000 --- a/src/currency_core/basic_kv_structs.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "warnings.h" - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4100) -DISABLE_VS_WARNINGS(4503) -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -POP_VS_WARNINGS - -namespace currency -{ - template - struct struct_with_one_t_type - { - t_type v; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(v) - END_KV_SERIALIZE_MAP() - }; -} diff --git a/src/currency_core/basic_pow_helpers.cpp b/src/currency_core/basic_pow_helpers.cpp deleted file mode 100644 index ddb8791..0000000 --- a/src/currency_core/basic_pow_helpers.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Copyright (c) 2018-2019 Hyle Team -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#include "include_base_utils.h" -using namespace epee; - -#include "basic_pow_helpers.h" -#include "currency_format_utils.h" -#include "serialization/binary_utils.h" -#include "serialization/stl_containers.h" -#include "currency_core/currency_config.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "common/int-util.h" -#include "ethereum/libethash/ethash/ethash.hpp" -#include "ethereum/libethash/ethash/progpow.hpp" - -namespace currency -{ - - //-------------------------------------------------------------- - int ethash_custom_log_get_level() - { - return epee::log_space::get_set_log_detalisation_level(); - } - //-------------------------------------------------------------- - void ethash_custom_log(const std::string& m, bool add_callstack) - { - std::string msg = epee::log_space::log_singletone::get_prefix_entry() + "[ETHASH]" + m; - if (add_callstack) - msg = msg + "callstask: " + epee::misc_utils::get_callstack(); - - epee::log_space::log_singletone::do_log_message(msg, LOG_LEVEL_0, epee::log_space::console_color_default, true, LOG_DEFAULT_TARGET); - } - //-------------------------------------------------------------- - void init_ethash_log_if_necessary() - { - static bool inited = false; - if (inited) - return; - - ethash::access_custom_log_level_function() = ðash_custom_log_get_level; - ethash::access_custom_log_function() = ðash_custom_log; - - inited = true; - } - //------------------------------------------------------------------ - int ethash_height_to_epoch(uint64_t height) - { - return static_cast(height / ETHASH_EPOCH_LENGTH); - } - //-------------------------------------------------------------- - crypto::hash ethash_epoch_to_seed(int epoch) - { - auto res_eth = ethash_calculate_epoch_seed(epoch); - crypto::hash result = currency::null_hash; - memcpy(&result.data, &res_eth, sizeof(res_eth)); - return result; - } - //-------------------------------------------------------------- - crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_header_hash, uint64_t nonce) - { - init_ethash_log_if_necessary(); - int epoch = ethash_height_to_epoch(height); - std::shared_ptr p_context = progpow::get_global_epoch_context_full(static_cast(epoch)); - CHECK_AND_ASSERT_THROW_MES(p_context, "progpow::get_global_epoch_context_full returned null"); - auto res_eth = progpow::hash(*p_context, static_cast(height), *(ethash::hash256*)&block_header_hash, nonce); - crypto::hash result = currency::null_hash; - memcpy(&result.data, &res_eth.final_hash, sizeof(res_eth.final_hash)); - return result; - } - //--------------------------------------------------------------- - crypto::hash get_block_header_mining_hash(const block& b) - { - blobdata bd = get_block_hashing_blob(b); - - access_nonce_in_block_blob(bd) = 0; - return crypto::cn_fast_hash(bd.data(), bd.size()); - } - //--------------------------------------------------------------- - void get_block_longhash(const block& b, crypto::hash& res) - { - /* - Since etherium hash has a bit different approach in minig, to adopt our code we made little hack: - etherium hash calculates from block's hash and(!) nonce, both passed into PoW hash function. - To achieve the same effect we make blob of data from block in normal way, but then set to zerro nonce - inside serialized buffer, and then pass this nonce to ethash algo as a second argument, as it expected. - */ - crypto::hash bl_hash = get_block_header_mining_hash(b); - res = get_block_longhash(get_block_height(b), bl_hash, b.nonce); - } - //--------------------------------------------------------------- - crypto::hash get_block_longhash(const block& b) - { - crypto::hash p = null_hash; - get_block_longhash(b, p); - return p; - } -} \ No newline at end of file diff --git a/src/currency_core/basic_pow_helpers.h b/src/currency_core/basic_pow_helpers.h deleted file mode 100644 index 32ded45..0000000 --- a/src/currency_core/basic_pow_helpers.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - -#include "account.h" -#include "include_base_utils.h" - -#include "currency_format_utils_abstract.h" -#include "common/crypto_stream_operators.h" -#include "currency_protocol/currency_protocol_defs.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "difficulty.h" -//#include "offers_services_helpers.h" -#include "rpc/core_rpc_server_commands_defs.h" -#include "bc_payments_id_service.h" -#include "bc_attachments_helpers_basic.h" -#include "blockchain_storage_basic.h" - -#define CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET 1 - -namespace currency -{ - int ethash_height_to_epoch(uint64_t height); - crypto::hash ethash_epoch_to_seed(int epoch); - crypto::hash get_block_header_mining_hash(const block& b); - crypto::hash get_block_longhash(uint64_t h, const crypto::hash& block_header_hash, uint64_t nonce); - void get_block_longhash(const block& b, crypto::hash& res); - crypto::hash get_block_longhash(const block& b); - - inline uint64_t& access_nonce_in_block_blob(blobdata& bd) - { - return *reinterpret_cast(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]); - } - - inline const uint64_t& access_nonce_in_block_blob(const blobdata& bd) - { - return *reinterpret_cast(&bd[CURRENCY_MINER_BLOCK_BLOB_NONCE_OFFSET]); - } -} \ No newline at end of file diff --git a/src/currency_core/bc_attachments_helpers.h b/src/currency_core/bc_attachments_helpers.h deleted file mode 100644 index 48f1fac..0000000 --- a/src/currency_core/bc_attachments_helpers.h +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "currency_basic.h" -#include "currency_format_utils.h" -#include "storages/portable_storage_template_helper.h" -#include "zlib_helper.h" - -namespace bc_services -{ - template - bool pack_attachment_as_gzipped_json(const t_attachment_type_t& at, currency::tx_service_attachment& att) - { - //TODO: make json without spaces and line endings here to reduce space - epee::serialization::store_t_to_json(at, att.body); - att.flags |= TX_SERVICE_ATTACHMENT_DEFLATE_BODY; -// if (!epee::zlib_helper::pack(json_buff, att.body)) -// { -// LOG_ERROR("Filed to pack tx_service_attachment as gzipped json, service id: " << att.service_id << " instruction: " << att.instruction << " flags: " << att.flags); -// return false; -// } - return true; - } - - template - bool unpack_attachment_as_gzipped_json(t_attachment_type_t& at, const currency::tx_service_attachment& att) - { - std::string json_buff; - CHECK_AND_ASSERT_MES(att.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY, false, "unpack_attachment_as_gzipped_json didn't find TX_SERVICE_ATTACHMENT_DEFLATE_BODY in flags"); - if (!epee::zlib_helper::unpack(att.body, json_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment as gzipped json, service id: " << att.service_id << " instruction: " << att.instruction << " flags: " << att.flags); - return false; - } - return epee::serialization::load_t_from_json(at, json_buff); - } - - template - bool unpack_attachment_as_gzipped_bin(t_attachment_type_t& at, const currency::tx_service_attachment& att) - { - std::string bin_buff; - CHECK_AND_ASSERT_MES(att.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY, false, "unpack_attachment_as_gzipped_bin didn't find TX_SERVICE_ATTACHMENT_DEFLATE_BODY in flags"); - if (!epee::zlib_helper::unpack(att.body, bin_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment as gzipped bin, service id: " << att.service_id << " instruction: " << att.instruction << " flags: " << att.flags); - return false; - } - return t_unserializable_object_from_blob(at, bin_buff); - } - - template - bool pack_attachment_as_gzipped_bin(const t_attachment_type_t& at, currency::tx_service_attachment& att) - { - //TODO: make json without spaces and line endings here to reduce space - ::t_serializable_object_to_blob(at, att.body); - att.flags |= TX_SERVICE_ATTACHMENT_DEFLATE_BODY; -// if (!epee::zlib_helper::pack(bin_buff, att.body)) -// { -// LOG_ERROR("Filed to pack tx_service_attachment as gzipped bin, service id: " << att.service_id << " instruction: " << att.instruction << " flags: " << att.flags); -// return false; -// } - return true; - } - - template - bool get_service_attachment_by_id_unpack(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res) - { - bool r = get_first_service_attachment_by_id(tx_items, id, instruction, res); - if (r && res.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) - { - r = epee::zlib_helper::unpack(res.body); - CHECK_AND_ASSERT_MES(r, false, "Failed to unpack in get_service_attachment_by_id_unpack"); - } - return r; - } - - inline bool get_first_service_attachment_by_id(const currency::transaction& tx, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res) - { - if (get_first_service_attachment_by_id(tx.extra, id, instruction, res)) - return true; - return get_first_service_attachment_by_id(tx.attachment, id, instruction, res); - } - - template - bool get_service_attachment_json_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, t_result_type& res) - { - currency::tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - if (!get_first_service_attachment_by_id(tx_items, id, instruction, tsa)) - return false; - - return epee::serialization::load_t_from_json(res, tsa.body); - } - - template - bool get_service_attachment_gzipped_json_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, t_result_type& res) - { - currency::tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - if (!get_first_service_attachment_by_id(tx_items, id, instruction, tsa)) - return false; - - return unpack_attachment_as_gzipped_json(res, tsa); - } - - template - bool get_service_attachment_gzipped_bin_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, t_result_type& res) - { - - currency::tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - if (!get_first_service_attachment_by_id(tx_items, id, instruction, tsa)) - return false; - - return unpack_attachment_as_gzipped_bin(res, tsa); - } - template - bool get_service_attachment_bin_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, t_result_type& res) - { - - currency::tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - if (!get_first_service_attachment_by_id(tx_items, id, instruction, tsa)) - return false; - - - return ::t_unserializable_object_from_blob(res, tsa.body); - } -} \ No newline at end of file diff --git a/src/currency_core/bc_attachments_helpers_basic.h b/src/currency_core/bc_attachments_helpers_basic.h deleted file mode 100644 index 18a8e55..0000000 --- a/src/currency_core/bc_attachments_helpers_basic.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "currency_basic.h" - -namespace bc_services -{ - template - bool get_first_service_attachment_by_id(const t_attachment_type_container_t& tx_items, const std::string& id, const std::string& instruction, currency::tx_service_attachment& res) - { - for (const auto& item : tx_items) - { - if (item.type() == typeid(currency::tx_service_attachment)) - { - const currency::tx_service_attachment& tsa = boost::get(item); - if (tsa.service_id == id && tsa.instruction == instruction) - { - res = tsa; - return true; - } - } - } - return false; - } -} \ No newline at end of file diff --git a/src/currency_core/bc_attachments_service_manager.cpp b/src/currency_core/bc_attachments_service_manager.cpp deleted file mode 100644 index c56015b..0000000 --- a/src/currency_core/bc_attachments_service_manager.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "bc_attachments_service_manager.h" - -namespace currency -{ - bool bc_attachment_services_manager::add_service(i_bc_service* pservice) - { - if (pservice == nullptr) - return false; - - if (m_services.count(pservice->get_id())) - { - LOG_ERROR("Service with id " << pservice->get_id() << "already registered"); - return false; - } - m_services[pservice->get_id()] = pservice; - pservice->set_core_runtime_config(m_core_runtime_config); - return true; - } - i_bc_service* bc_attachment_services_manager::get_service_by_id(const std::string& id) const - { - const auto& it = m_services.find(id); - if (it == m_services.end()) - return nullptr; - - return it->second; - } - void bc_attachment_services_manager::set_event_handler(i_core_event_handler* event_handler) - { - for (auto& s : m_services) - { - s.second->set_event_handler(event_handler); - } - } - void bc_attachment_services_manager::set_core_runtime_config(const core_runtime_config& rtc) - { - m_core_runtime_config = rtc; - for (auto& s : m_services) - { - s.second->set_core_runtime_config(rtc); - } - } - bool bc_attachment_services_manager::init(const std::string& config_folder, const boost::program_options::variables_map& vm) - { - //add service - for (auto& s : m_services) - { - s.second->init(config_folder, vm); - } - return true; - } - bool bc_attachment_services_manager::deinit() - { - //add service - for (auto& s : m_services) - { - s.second->deinit(); - } - m_services.clear(); - return true; - } - bool bc_attachment_services_manager::validate_entry(const tx_service_attachment& a, size_t i, const transaction& tx) - { - auto it = m_services.find(a.service_id); - if (it != m_services.end()) - { - return it->second->validate_entry(a, i, tx); - } - return false; - } - void bc_attachment_services_manager::handle_entry_push(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp) - { - auto it = m_services.find(a.service_id); - if (it != m_services.end()) - { - it->second->handle_entry_push(a, i, tx, h, bl_id, timestamp); - } - } - void bc_attachment_services_manager::handle_entry_pop(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, uint64_t timestamp) - { - auto it = m_services.find(a.service_id); - if (it != m_services.end()) - { - it->second->handle_entry_pop(a, i, tx, h, timestamp); - } - } -} diff --git a/src/currency_core/bc_attachments_service_manager.h b/src/currency_core/bc_attachments_service_manager.h deleted file mode 100644 index 632126a..0000000 --- a/src/currency_core/bc_attachments_service_manager.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include "dispatch_core_events.h" -#include "core_runtime_config.h" - -namespace currency -{ - struct i_bc_service - { - virtual ~i_bc_service() = default; - - virtual std::string get_id() = 0; - virtual bool init(const std::string& config_folder, const boost::program_options::variables_map& vm) = 0; - virtual bool deinit() = 0; - virtual void handle_entry_push(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp) = 0; - virtual void handle_entry_pop(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, uint64_t timestamp) = 0; - virtual bool validate_entry(const tx_service_attachment& a, size_t i, const transaction& tx) = 0; - virtual void set_event_handler(i_core_event_handler* event_handler) = 0; - virtual void set_core_runtime_config(const core_runtime_config& rtc) = 0; - }; - - class bc_attachment_services_manager - { - public: - bc_attachment_services_manager(/* i_core_event_handler* pcore_event_handler*/) : /*m_pcore_event_handler(pcore_event_handler),*/ m_core_runtime_config(get_default_core_runtime_config()) - {} - - - void set_event_handler(i_core_event_handler* event_handler); - void set_core_runtime_config(const core_runtime_config& rtc); - bool add_service(i_bc_service* psrv); - i_bc_service* get_service_by_id(const std::string& id) const; - bool init(const std::string& config_folder, const boost::program_options::variables_map& vm); - bool deinit(); - bool validate_entry(const tx_service_attachment& a, size_t i, const transaction& tx); - void handle_entry_push(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp); - void handle_entry_pop(const tx_service_attachment& a, size_t i, const transaction& tx, uint64_t h, uint64_t timestamp); - - private: - std::map m_services; - //i_core_event_handler* m_pcore_event_handler; - core_runtime_config m_core_runtime_config; - - }; - -} diff --git a/src/currency_core/bc_block_datetime_service.h b/src/currency_core/bc_block_datetime_service.h deleted file mode 100644 index 4db3d74..0000000 --- a/src/currency_core/bc_block_datetime_service.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2014-2021 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#pragma once - -#define BC_BLOCK_DATETIME_SERVICE_ID "d" -#define BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT "" diff --git a/src/currency_core/bc_escrow_service.h b/src/currency_core/bc_escrow_service.h deleted file mode 100644 index c9e00ae..0000000 --- a/src/currency_core/bc_escrow_service.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "account.h" - -#define BC_ESCROW_SERVICE_ID "E" - -#define BC_ESCROW_SERVICE_INSTRUCTION_PROPOSAL "PROP" -#define BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_TEMPLATES "REL_TEMPL" -#define BC_ESCROW_SERVICE_INSTRUCTION_CANCEL_PROPOSAL "CAN_PROP" -#define BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL "REL_N" -#define BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_CANCEL "REL_C" -#define BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_BURN "REL_B" -//#define BC_ESCROW_SERVICE_INSTRUCTION_ACCEPT "ACC" -#define BC_ESCROW_SERVICE_INSTRUCTION_CHANGE "CHANGE" -#define BC_ESCROW_SERVICE_INSTRUCTION_PRIVATE_DETAILS "DETAILS" //this part supposed to be in "extra" part, not attachment -#define BC_ESCROW_SERVICE_INSTRUCTION_PUBLIC_DETAILS "PUB" //this part supposed to be in "extra" part, not attachment - -namespace bc_services -{ - - struct contract_private_details - { - std::string title; - std::string comment; - currency::account_public_address a_addr; // usually buyer - currency::account_public_address b_addr; // usually seller - uint64_t amount_to_pay; - uint64_t amount_a_pledge; - uint64_t amount_b_pledge; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_N(title, "t") - KV_SERIALIZE_N(comment, "c") - KV_SERIALIZE_ADDRESS_AS_TEXT_N(a_addr, "a_addr") - KV_SERIALIZE_ADDRESS_AS_TEXT_N(b_addr, "b_addr") - KV_SERIALIZE_N(amount_to_pay, "to_pay") - KV_SERIALIZE_N(amount_a_pledge, "a_pledge") - KV_SERIALIZE_N(amount_b_pledge, "b_pledge") - END_KV_SERIALIZE_MAP() - }; - - struct contract_public_details - { - currency::account_public_address b_addr; // usually seller - uint64_t amount_to_pay; - crypto::signature address_proof; //multisig_id signed by private spend key - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_ADDRESS_AS_TEXT_N(b_addr, "a_b") - KV_SERIALIZE_N(amount_to_pay, "to_pay") - KV_SERIALIZE_POD_AS_HEX_STRING_N(address_proof, "proof") - END_KV_SERIALIZE_MAP() - }; - - - // BC_ESCROW_SERVICE_INSTRUCTION_PROPOSAL - struct proposal_body - { - currency::transaction tx_template; - crypto::secret_key tx_onetime_secret_key; - BEGIN_SERIALIZE() - FIELD(tx_template) - FIELD(tx_onetime_secret_key) - END_SERIALIZE() - }; - - struct escrow_relese_templates_body - { - currency::transaction tx_normal_template; - currency::transaction tx_burn_template; - - BEGIN_SERIALIZE() - FIELD(tx_normal_template) - FIELD(tx_burn_template) - END_SERIALIZE() - }; - - struct escrow_cancel_templates_body - { - currency::transaction tx_cancel_template; - - BEGIN_SERIALIZE() - FIELD(tx_cancel_template) - END_SERIALIZE() - }; - -} - - -#define CURRENCY_CPD_ARCHIVE_VER 1 -BOOST_CLASS_VERSION(bc_services::contract_private_details, CURRENCY_CPD_ARCHIVE_VER) - -namespace boost -{ - namespace serialization - { - template - void serialize(archive_t & ar, bc_services::contract_private_details& cpd, const unsigned int version) - { - ar & cpd.title; - ar & cpd.comment; - if (version == 0 && !archive_t::is_saving::value) - { - // loading from version 0 (pre-auditable address format) - currency::account_public_address_old old_addr = AUTO_VAL_INIT(old_addr); - ar & old_addr; - cpd.a_addr = currency::account_public_address::from_old(old_addr); - ar & old_addr; - cpd.b_addr = currency::account_public_address::from_old(old_addr); - } - else - { - ar & cpd.a_addr; // usually buyer - ar & cpd.b_addr; // usually seller - } - ar & cpd.amount_to_pay; - ar & cpd.amount_a_pledge; - ar & cpd.amount_b_pledge; - } - - - template - inline void serialize(Archive& a, bc_services::escrow_relese_templates_body& x, const unsigned int ver) - { - a & x.tx_normal_template; - a & x.tx_burn_template; - } - - template - inline void serialize(Archive& a, bc_services::escrow_cancel_templates_body& x, const unsigned int ver) - { - a & x.tx_cancel_template; - } - - template - inline void serialize(Archive& a, bc_services::proposal_body& x, const unsigned int ver) - { - a & x.tx_onetime_secret_key; - a & x.tx_template; - } - } -} \ No newline at end of file diff --git a/src/currency_core/bc_offers_serialization.h b/src/currency_core/bc_offers_serialization.h deleted file mode 100644 index cee1e27..0000000 --- a/src/currency_core/bc_offers_serialization.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "common/unordered_containers_boost_serialization.h" -#include "common/crypto_boost_serialization.h" -#include "offers_service_basics.h" -#include "offers_services_helpers.h" - -namespace boost -{ - namespace serialization - { - template - inline void serialize(Archive &a, bc_services::offer_details &x, const boost::serialization::version_type ver) - { - a & x.offer_type; - a & x.amount_primary; - a & x.amount_target; - a & x.bonus; - a & x.target; - a & x.primary; - a & x.location_country; - a & x.location_city; - a & x.contacts; - a & x.comment; - a & x.payment_types; - a & x.expiration_time; - a & x.category; - a & x.deal_option; - - } - - - template - inline void serialize(Archive& a, bc_services::offer_details_ex& x, const boost::serialization::version_type ver) - { - a & static_cast(x); - a & x.timestamp; - a & x.tx_hash; - a & x.index_in_tx; - a & x.tx_original_hash; - a & x.fee; - a & x.stopped; - a & x.security; - } - - template - inline void serialize(Archive& a, bc_services::offer_details_ex_with_hash& x, const boost::serialization::version_type ver) - { - a & static_cast(x); - a & x.h; - a & x.nxt_offer; - } - - template - inline void serialize(Archive &a, bc_services::cancel_offer &x, const boost::serialization::version_type ver) - { - a & x.offer_index; - a & x.sig; - a & x.tx_id; - } - - template - inline void serialize(Archive &a, bc_services::update_offer &x, const boost::serialization::version_type ver) - { - a & x.of; - a & x.offer_index; - a & x.sig; - a & x.tx_id; - } - } -} \ No newline at end of file diff --git a/src/currency_core/bc_offers_service.cpp b/src/currency_core/bc_offers_service.cpp deleted file mode 100644 index 5906463..0000000 --- a/src/currency_core/bc_offers_service.cpp +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "bc_offers_service.h" - -#include "include_base_utils.h" - -#include "zlib_helper.h" -#include "currency_basic.h" -#include "currency_format_utils.h" -#include "storages/portable_storage_template_helper.h" - - -command_line::arg_descriptor arg_market_disable = { "disable-market", "Start GUI with market service disabled", false, true }; - - -namespace bc_services -{ - - bc_offers_service::bc_offers_service(currency::i_core_event_handler* pcore_event_handler) - : m_pcore_event_handler(pcore_event_handler) - , m_last_trimed_height(0) - , m_core_runtime_config(currency::get_default_core_runtime_config()) - , m_last_seen_block_id(currency::null_hash) - , m_deinitialized(false) - , m_disabled(false) - - {} - //------------------------------------------------------------------ - bc_offers_service::~bc_offers_service() - { - TRY_ENTRY(); - if (!m_deinitialized) - deinit(); - CATCH_ENTRY_NO_RETURN(); - } - //------------------------------------------------------------------ - bool bc_offers_service::init(const std::string& config_folder, const boost::program_options::variables_map& vm) - { - if (command_line::get_arg(vm, arg_market_disable)) - { - LOG_PRINT_CYAN("Market DISABLED", LOG_LEVEL_0); - m_disabled = true; - return true; - } - LOG_PRINT_L0("Loading market..."); - m_config_folder = config_folder; - std::string filename = m_config_folder + "/" BC_OFFERS_CURRENCY_MARKET_FILENAME; - if (!tools::unserialize_obj_from_file(*this, filename)) - { - LOG_PRINT_L0("Can't load market from file"); - //TODO: may be rebuild it from blockchain - } - return true; - } - //------------------------------------------------------------------ - void bc_offers_service::set_event_handler(currency::i_core_event_handler* event_handler) - { - m_pcore_event_handler = event_handler; - } - //------------------------------------------------------------------ - bool bc_offers_service::deinit() - { - LOG_PRINT_L0("Storing market..."); - CRITICAL_REGION_LOCAL(m_lock); - std::string filename = m_config_folder + "/" BC_OFFERS_CURRENCY_MARKET_FILENAME; - if (!tools::serialize_obj_to_file(*this, filename)) - { - LOG_PRINT_L0("Can't store market from file"); - //TODO: may be rebuild it from blockchain - } - m_deinitialized = true; - LOG_PRINT_L0("Market stored OK"); - return true; - } - //------------------------------------------------------------------ - void bc_offers_service::handle_entry_push(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp) - { - if (m_disabled) - return; - //unpack data and pars json - std::string json_buff; - if (!epee::zlib_helper::unpack(a.body, json_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment in bc_offers_service, tx_id = " << currency::get_transaction_hash(tx)); - return; - } - - bool r = false; - if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD) - { - offer_details od = AUTO_VAL_INIT(od); - r = handle_entry_push(json_buff, a, od, i, tx, h, timestamp); - CHECK_AND_ASSERT_MES_NO_RET(r, "offers service instruction " << a.instruction << " failed, offer's tx:oid : " << get_transaction_hash(tx) << ":" << i); - }else if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD) - { - update_offer od = AUTO_VAL_INIT(od); - r = handle_entry_push(json_buff, a, od, i, tx, h, timestamp); - }else if(a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_DEL) - { - cancel_offer od = AUTO_VAL_INIT(od); - r = handle_entry_push(json_buff, a, od, i, tx, h, timestamp); - } - - } - //------------------------------------------------------------------ - - - bool bc_offers_service::trim_offers() - { - CRITICAL_REGION_LOCAL(m_lock); - uint64_t current_time = m_core_runtime_config.get_core_time(); - auto& index = m_offers.get(); - uint64_t size_before = m_offers.size(); - for (auto it = index.begin(); it != index.end();) - { - if (it->timestamp + OFFER_MAXIMUM_LIFE_TIME < current_time) - index.erase(it++); - else - break; - } - LOG_PRINT_GREEN("TRIM OFFERS: " << size_before - m_offers.size() << " offers removed", LOG_LEVEL_0); - return true; - } - //------------------------------------------------------------------ - crypto::hash bc_offers_service::get_last_seen_block_id() - { - return m_last_seen_block_id; - } - //------------------------------------------------------------------ - void bc_offers_service::set_last_seen_block_id(const crypto::hash& h) - { - m_last_seen_block_id = h; - } - //------------------------------------------------------------------ - bool bc_offers_service::clear() - { - m_last_trimed_height = 0; - m_last_seen_block_id = currency::null_hash; - CRITICAL_REGION_LOCAL(m_lock); - m_offers.clear(); - return true; - } - //------------------------------------------------------------------ - void bc_offers_service::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_market_disable); - } - //------------------------------------------------------------------ - void bc_offers_service::handle_entry_pop(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - if (m_disabled) - return; - //unpack data and pars json - std::string json_buff; - if (!epee::zlib_helper::unpack(a.body, json_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment in bc_offers_service, tx_id = " << get_transaction_hash(tx)); - return; - } - - bool r = false; - if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD) - { - offer_details od = AUTO_VAL_INIT(od); - r = handle_entry_pop(json_buff, od, i, tx, h, timestamp); - } - else if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD) - { - update_offer od = AUTO_VAL_INIT(od); - r = handle_entry_pop(json_buff, od, i, tx, h, timestamp); - } - else if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_DEL) - { - cancel_offer od = AUTO_VAL_INIT(od); - r = handle_entry_pop(json_buff, od, i, tx, h, timestamp); - } - if (!r) - { - LOG_ERROR("offers service instruction " << a.instruction << " failed, offer's tx:oid : " << get_transaction_hash(tx) << ":" << i); - } - - - //trim offers once a day - if (m_last_trimed_height != h && !(h%CURRENCY_BLOCKS_PER_DAY)) - { - trim_offers(); - m_last_trimed_height = h; - } - - - } - //------------------------------------------------------------------------------------------------------------------------ - // adding new offer - - bool bc_offers_service::handle_push(offer_details& od_, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - offer_details_ex_with_hash od = AUTO_VAL_INIT(od); - static_cast(od) = od_; - od.timestamp = timestamp; - od.index_in_tx = i; - crypto::hash tx_hash = get_transaction_hash(tx); - od.tx_hash = tx_hash; - od.stopped = false; - CHECK_AND_ASSERT_MES(a.security.size(), false, "Add offer command: no security entry"); - od.security = a.security.back(); - od.fee = currency::get_tx_fee(tx) / currency::get_service_attachments_count_in_tx(tx); - od.h = offer_id_from_hash_and_index(tx_hash, od.index_in_tx); - bool r = put_offer_to_container(od); - if (r) - rise_core_event(CORE_EVENT_ADD_OFFER, od); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::validate_entry(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx) - { - if (a.service_id != BC_OFFERS_SERVICE_ID) - return true; - - //don't validate other atm - if (a.instruction != BC_OFFERS_SERVICE_INSTRUCTION_DEL) - return true; - - std::string json_buff; - if (!epee::zlib_helper::unpack(a.body, json_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment in bc_offers_service, tx_id = " << get_transaction_hash(tx)); - return false; - } - - cancel_offer co = AUTO_VAL_INIT(co); - bool r = epee::serialization::load_t_from_json(co, json_buff); - if (!r) - { - LOG_ERROR("Filed to load json from tx_service_attachment in bc_offers_service, tx_id = " << get_transaction_hash(tx) << ", body: " << json_buff); - return false; - } - offers_container::index::type::iterator oit; - return validate_cancel_order(co, oit); - } - //------------------------------------------------------------------------------------------------------------------------ - // updating offer - bool bc_offers_service::handle_push(update_offer& uo, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - CRITICAL_REGION_LOCAL(m_lock); - auto& index = m_offers.get(); - crypto::hash offer_id = offer_id_from_hash_and_index(uo.tx_id, uo.offer_index); - auto it = index.find(offer_id); - if (it == index.end()) - { - LOG_PRINT_L2("Update offer command failed: offer not found, tx:idx : " << uo.tx_id << ":" << uo.offer_index << ", offer_id: " << offer_id); - return false; - } - - - bool r = validate_modify_order_signature(*it, uo); - CHECK_AND_NO_ASSERT_MES(r, false, "validate_modify_order_signature failed while trying to update an offer " << uo.tx_id << ":" << uo.offer_index); - - crypto::hash tx_id = get_transaction_hash(tx); - - offer_details_ex_with_hash new_off = AUTO_VAL_INIT(new_off); - static_cast(new_off) = uo.of; - new_off.timestamp = it->timestamp;// keep original offer's timestmap - new_off.index_in_tx = i; - new_off.tx_hash = tx_id; - new_off.stopped = false; - CHECK_AND_ASSERT_MES(a.security.size(), false, "Update offer command: no security entry"); - new_off.security = a.security.back(); - - new_off.fee = currency::get_tx_fee(tx) / get_service_attachments_count_in_tx(tx); - new_off.h = offer_id_from_hash_and_index(tx_id, new_off.index_in_tx); - put_offer_to_container(new_off); - - //update old order - it->nxt_offer = epee::string_tools::pod_to_hex(new_off.h); - it->stopped = true; - - //notify - update_offer_details uop = AUTO_VAL_INIT(uop); - uop.od = static_cast(new_off); - uop.tx_id = uo.tx_id; - uop.no = uo.offer_index; - uop.wallet_id = 0; // ?? is 0 okay here? - rise_core_event(CORE_EVENT_UPDATE_OFFER, uop); - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - // canceling offer - bool bc_offers_service::handle_push(cancel_offer& co, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - CRITICAL_REGION_LOCAL(m_lock); - offers_container::index::type::iterator it = m_offers.get().end(); - bool r = validate_cancel_order(co, it); - if (!r) - return false; - - it->stopped = true; - LOG_PRINT_MAGENTA("Offer " << co.tx_id << ":" << co.offer_index << " cancelled", LOG_LEVEL_0); - rise_core_event(CORE_EVENT_REMOVE_OFFER, static_cast(*it)); - return true; - } - //------------------------------------------------------------------ - bool bc_offers_service::validate_cancel_order(const cancel_offer& co, offers_container::index::type::iterator& oit) - { - CRITICAL_REGION_LOCAL(m_lock); - auto& index = m_offers.get(); - crypto::hash offer_id = offer_id_from_hash_and_index(co.tx_id, co.offer_index); - oit = index.find(offer_id); - if (oit == index.end()) - { - LOG_PRINT_L2("Cancel offer command: tx " << co.tx_id << " not found in offers"); - return false; - } - - bool r = validate_modify_order_signature(*oit, co); - CHECK_AND_NO_ASSERT_MES(r, false, "failed to validate_modify_order_signature at validate_cancel_order"); - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::handle_pop(offer_details& od, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - crypto::hash tx_hash = currency::get_transaction_hash(tx); - CRITICAL_REGION_LOCAL(m_lock); - auto& index = m_offers.get(); - crypto::hash oid = offer_id_from_hash_and_index(tx_hash, i); - auto it = index.find(oid); - if (it == index.end()) - { - LOG_ERROR("Internal error: unprocess_blockchain_tx_attachments tx_id: " << tx_hash << " cnt_offers_ins=" << i << ", oid: " << oid << " not found"); - } - else - { - rise_core_event(CORE_EVENT_REMOVE_OFFER, *it); - index.erase(it); - } - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::handle_pop(update_offer& uo, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - crypto::hash tx_id = currency::get_transaction_hash(tx); - CRITICAL_REGION_LOCAL(m_lock); - auto& index = m_offers.get(); - crypto::hash oid = offer_id_from_hash_and_index(tx_id, i); - crypto::hash original_oid = offer_id_from_hash_and_index(uo.tx_id, uo.offer_index); - auto it = index.find(oid); - CHECK_AND_ASSERT_MES(it != index.end(), false, "Unprocess update offer command: tx " << tx_id << "(" << oid << ") not found in offers"); - auto original_it = index.find(original_oid); - CHECK_AND_ASSERT_MES(original_it != index.end(), false, "Unprocess update offer command: original tx " << uo.tx_id << "(" << original_oid << ") not found in offers"); - - rise_core_event(CORE_EVENT_REMOVE_OFFER, *it); - original_it->stopped = false; - original_it->nxt_offer.clear(); - index.erase(it); - rise_core_event(CORE_EVENT_ADD_OFFER, *original_it); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::handle_pop(cancel_offer& co, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - CRITICAL_REGION_LOCAL(m_lock); - auto& index = m_offers.get(); - crypto::hash offer_id = offer_id_from_hash_and_index(co.tx_id, co.offer_index); - auto oit = index.find(offer_id); - CHECK_AND_ASSERT_MES(oit != index.end(), false, "Cancel offer command: tx " << co.tx_id << " not found in offers"); - - - CHECK_AND_ASSERT_MES(oit->stopped, false, "Cancel offer command unprocess: tx " - << co.tx_id << ": co.offer_index " << co.offer_index << ": not stopped yet"); - oit->stopped = false; - rise_core_event(CORE_EVENT_ADD_OFFER, static_cast(*oit)); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::put_offer_to_container(const offer_details_ex_with_hash& offer) - { - try - { - CRITICAL_REGION_LOCAL(m_lock); - auto& offers_index = m_offers.get(); - offers_index.insert(offer); - return true; - } - catch (const std::exception& err) - { - LOG_ERROR("Failed to put offer to index, error: " << err.what() << ", offer[" << offer.h << "]: " << epee::serialization::store_t_to_json(offer)); - return false; - } - catch (...) - { - LOG_ERROR("Failed to put offer to index, offer[" << offer.h << "]: " << epee::serialization::store_t_to_json(offer)); - return false; - } - } - //------------------------------------------------------------------------------------------------------------------------ - bool bc_offers_service::get_offers_by_id(const std::list& ids, std::list& offers) - { - for (auto& id : ids) - { - crypto::hash original_id = id.tx_id; - crypto::hash of_id = currency::null_hash; - of_id = offer_id_from_hash_and_index(id); - if (of_id == currency::null_hash) - continue; - - CRITICAL_REGION_LOCAL(m_lock); - auto& index_by_id = m_offers.get(); - auto it = index_by_id.find(of_id); - if (it == index_by_id.end()) - { - LOG_PRINT_L2("Unable to find offer by tx id: " << id.tx_id << ", offer id: " << of_id); - continue; - } - - if (it != index_by_id.end() && it->nxt_offer.size()) - { - crypto::hash nxt_h = currency::null_hash; - if (!epee::string_tools::parse_tpod_from_hex_string(it->nxt_offer, nxt_h)) - { - LOG_PRINT_L2("Unable to parse hash from nxt_h: " << it->nxt_offer); - } - else - { - it = index_by_id.find(nxt_h); - } - } - - if (it == index_by_id.end()) - { - LOG_PRINT_L2("Unable to find offer by tx id: " << id.tx_id << ", offer id: " << of_id); - continue; - } - offers.push_back(*it); - - if (offers.back().tx_hash != original_id) - offers.back().tx_original_hash = original_id; - } - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - void bc_offers_service::print_market(const std::string& file) - { - std::stringstream ss; - CRITICAL_REGION_LOCAL(m_lock); - for (auto& o : m_offers) - { - ss << "id: " << o.h << ENDL - << "nxt_id: " << o.nxt_offer << ENDL - << epee::serialization::store_t_to_json(o) << ENDL - << "----------------------------------------------" << ENDL; - } - if (epee::file_io_utils::save_string_to_file(file, ss.str())) - { - LOG_PRINT_L0("Market writen to file: " << file); - } - else - { - LOG_PRINT_L0("Failed to write market to file: " << file); - } - } - //------------------------------------------------------------------------------------------------------------------------ - void bc_offers_service::set_core_runtime_config(const currency::core_runtime_config& rtc) - { - m_core_runtime_config = rtc; - } - //------------------------------------------------------------------ - bool bc_offers_service::get_offers_ex(const core_offers_filter& cof, std::list& offers, uint64_t& total_count, uint64_t current_core_time) - { - CRITICAL_REGION_LOCAL(m_lock); - total_count = m_offers.size(); -#define SET_CASE_FOR_ORDER_TYPE(order_type_name) case order_type_name: return get_offers_ex_for_index::index_type>(cof, offers, current_core_time); - - switch (cof.order_by) - { - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_TIMESTAMP); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_AMOUNT_PRIMARY); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_AMOUNT_TARGET); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_AMOUNT_RATE); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_PAYMENT_TYPES); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_CONTACTS); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_LOCATION); - SET_CASE_FOR_ORDER_TYPE(ORDER_BY_NAME); - default: - LOG_ERROR("Unknown order_by id: " << cof.order_by); - return false; - } - return true; - } - //------------------------------------------------------------------ - -} diff --git a/src/currency_core/bc_offers_service.h b/src/currency_core/bc_offers_service.h deleted file mode 100644 index 1d7c642..0000000 --- a/src/currency_core/bc_offers_service.h +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "include_base_utils.h" - -#include "bc_offers_service_basic.h" -#include "common/boost_serialization_helper.h" -#include "bc_offers_serialization.h" -#include "bc_attachments_service_manager.h" -#include "offers_services_helpers.h" -#include "currency_format_utils.h" -#include "common/command_line.h" - - -extern command_line::arg_descriptor arg_market_disable; - -namespace bc_services -{ - class bc_offers_service : public currency::i_bc_service - { - public: - bc_offers_service(currency::i_core_event_handler* pcore_event_handler); - ~bc_offers_service(); - - typedef boost::multi_index::multi_index_container < - odeh, - boost::multi_index::indexed_by< - boost::multi_index::hashed_unique, boost::multi_index::global_fun>, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun >, - boost::multi_index::ordered_non_unique, boost::multi_index::global_fun > - > - > offers_container; - template - void serialize(archive_t & ar, const unsigned int version); - bool validate_cancel_order(const cancel_offer& co, offers_container::index::type::iterator& oit); - bool get_offers_by_id(const std::list& ids, std::list& offers); - bool get_offers_ex(const core_offers_filter& cof, std::list& offers, uint64_t& total_count, uint64_t current_core_time); - void print_market(const std::string& file); - - public: - // these members are made public only to be accessible from tests - offers_container& get_offers_container(){ return m_offers; } //TODO: need refactoring, bad design, atm just for performance tests - bool trim_offers(); - crypto::hash get_last_seen_block_id(); - void set_last_seen_block_id(const crypto::hash& h); - bool clear(); - bool set_disabled(bool is_disabled) { m_disabled = is_disabled; return m_disabled; } - bool is_disabled(){ return m_disabled; } - static void init_options(boost::program_options::options_description& desc); - private: - //-------------------- currency::i_bc_service --------------------------------------- - virtual std::string get_id() override { return BC_OFFERS_SERVICE_ID; } - virtual void set_event_handler(currency::i_core_event_handler* event_handler) override; - virtual bool init(const std::string& config_folder, const boost::program_options::variables_map& vm) override; - virtual bool deinit() override; - virtual void handle_entry_push(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp) override; - virtual void handle_entry_pop(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) override; - virtual bool validate_entry(const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx) override; - virtual void set_core_runtime_config(const currency::core_runtime_config& rtc) override; - //----------------------------------------------------------------------------------- - - bool handle_push(offer_details& od, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool handle_push(update_offer& od, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool handle_push(cancel_offer& od, const currency::tx_service_attachment& a, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool handle_pop(offer_details& od, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool handle_pop(update_offer& od, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool handle_pop(cancel_offer& od, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - bool put_offer_to_container(const offer_details_ex_with_hash& offer); - - template - void rise_core_event(const std::string& event_name, const t_event_details& ed); - template - bool handle_entry_push(const std::string& body, const currency::tx_service_attachment& a, t_offer& offer_instruction, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - template - bool handle_entry_pop(const std::string& body, t_offer& offer_instruction, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp); - template - bool validate_modify_order_signature(const offer_details_ex_with_hash &odeh, const t_modify_offer& co); - template - bool get_offers_ex_for_index(const core_offers_filter& cof, std::list& offers, uint64_t current_core_time); - - - //offers - offers_container m_offers; //offers indexed by - currency::i_core_event_handler* m_pcore_event_handler; - uint64_t m_last_trimed_height; - std::string m_config_folder; - crypto::hash m_last_seen_block_id; - epee::critical_section m_lock; - currency::core_runtime_config m_core_runtime_config; - bool m_deinitialized; - bool m_disabled; - //--------------------------------------------------------------------------------------------------------------------------------------------- - - }; - - template - void bc_offers_service::rise_core_event(const std::string& event_name, const t_event_details& ed) - { - currency::core_event_v e(ed); - if (m_pcore_event_handler) - m_pcore_event_handler->on_core_event(event_name, e); - } - //--------------------------------------------------------------------------------------------------------------------------------------------- - template - bool bc_offers_service::handle_entry_push(const std::string& body, const currency::tx_service_attachment& a, t_offer& offer_instruction, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - bool r = epee::serialization::load_t_from_json(offer_instruction, body); - if (!r) - { - LOG_ERROR("Filed to load json from tx_service_attachment in bc_offers_service, tx_id = " << currency::get_transaction_hash(tx) << ", body: " << body); - return false; - } - return handle_push(offer_instruction, a, i, tx, h, timestamp); - } - //--------------------------------------------------------------------------------------------------------------------------------------------- - template - bool bc_offers_service::handle_entry_pop(const std::string& body, t_offer& offer_instruction, size_t i, const currency::transaction& tx, uint64_t h, uint64_t timestamp) - { - bool r = epee::serialization::load_t_from_json(offer_instruction, body); - if (!r) - { - LOG_ERROR("Filed to load json from tx_service_attachment in bc_offers_service, tx_id = " << currency::get_transaction_hash(tx) << ", body: " << body); - return false; - } - return handle_pop(offer_instruction, i, tx, h, timestamp); - } - //--------------------------------------------------------------------------------------------------------------------------------------------- - template - bool bc_offers_service::validate_modify_order_signature(const offer_details_ex_with_hash &odeh, const t_modify_offer& co) - { - if (odeh.stopped) - { - LOG_PRINT_YELLOW("offer command validation failed: already stopped, tx: " << co.tx_id << ", offer_index: " << co.offer_index, LOG_LEVEL_0); - return false; - } - - currency::blobdata buff_to_check_sig = make_offer_sig_blob(co); - bool res = crypto::check_signature(crypto::cn_fast_hash(buff_to_check_sig.data(), buff_to_check_sig.size()), odeh.security, co.sig); - CHECK_AND_ASSERT_MES(res, false, "Signature check failed for offer command: tx " << co.tx_id << ", onetime_offer_pub_key=" << epee::string_tools::pod_to_hex(odeh.security)); - - return true; - } - //--------------------------------------------------------------------------------------------------------------------------------------------- - template - bool bc_offers_service::get_offers_ex_for_index(const core_offers_filter& cof, std::list& offers, uint64_t current_core_time) - { - CRITICAL_REGION_LOCAL(m_lock); - if (!m_offers.size()) - return false; - - auto& current_index = m_offers.get(); - - auto it = current_index.begin(); - if (cof.reverse) - it = --current_index.end(); - - uint64_t selected_index = 0; - while (it != current_index.end()) - { - //-------- - if (selected_index >= cof.offset + cof.limit) - break; - - if (is_offer_matched_by_filter(*it, cof, current_core_time)) - { - //if we after offset position - if (selected_index >= cof.offset) - offers.push_back(*it); - - selected_index++; - } - - //-------- - //prepare next iteration - if (cof.reverse) - { - if (it == current_index.begin()) - break; - else - --it; - } - else - { - ++it; - } - } - - return true; - } - //--------------------------------------------------------------------------------------------------------------------------------------------- - template - void bc_offers_service::serialize(archive_t & ar, const unsigned int version) - { - if (version < BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER) - { - LOG_PRINT_BLUE("[OFFERS_SERVICE] data truncated cz new version", LOG_LEVEL_0); - return; - } - CHECK_PROJECT_NAME(); - ar & m_last_trimed_height; - ar & m_last_seen_block_id; - - std::list temp; - if (archive_t::is_saving::value) - { - auto& index = m_offers.get(); - for (auto it = index.begin(); it != index.end();it++) - { - temp.push_back(*it); - } - ar & temp; - } - else - { - ar & temp; - for (const auto& o : temp) - { - TRY_ENTRY() - m_offers.insert(o); - CATCH_ENTRY("error while reading market storage ", void()); - } - - } - //ar & m_offers; - } -} -BOOST_CLASS_VERSION(bc_services::bc_offers_service, BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER) diff --git a/src/currency_core/bc_offers_service_basic.h b/src/currency_core/bc_offers_service_basic.h deleted file mode 100644 index 41f06c4..0000000 --- a/src/currency_core/bc_offers_service_basic.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#define BC_OFFERS_SERVICE_ID "M" -#define BC_OFFERS_SERVICE_INSTRUCTION_ADD "ADD" -#define BC_OFFERS_SERVICE_INSTRUCTION_UPD "UPD" -#define BC_OFFERS_SERVICE_INSTRUCTION_DEL "DEL" diff --git a/src/currency_core/bc_payments_id_service.h b/src/currency_core/bc_payments_id_service.h deleted file mode 100644 index 070907b..0000000 --- a/src/currency_core/bc_payments_id_service.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#define BC_PAYMENT_ID_SERVICE_ID "P" -#define BC_PAYMENT_ID_SERVICE_SIZE_MAX 128 // (bytes) maximum allowed size of payment id body diff --git a/src/currency_core/block_flags.h b/src/currency_core/block_flags.h deleted file mode 100644 index b7724e1..0000000 --- a/src/currency_core/block_flags.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#define CURRENCY_BLOCK_FLAG_POS_BLOCK 0x01 diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp deleted file mode 100644 index 6bb4771..0000000 --- a/src/currency_core/blockchain_storage.cpp +++ /dev/null @@ -1,6881 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "include_base_utils.h" - -#include "common/db_backend_selector.h" -#include "common/command_line.h" - -#include "blockchain_storage.h" -#include "currency_format_utils.h" -#include "currency_boost_serialization.h" -#include "currency_core/currency_config.h" -#include "miner.h" -#include "misc_language.h" -#include "profile_tools.h" -#include "file_io_utils.h" -#include "common/boost_serialization_helper.h" -#include "warnings.h" -#include "crypto/hash.h" -#include "miner_common.h" -#include "storages/portable_storage_template_helper.h" -#include "basic_pow_helpers.h" -#include "version.h" -#include "tx_semantic_validation.h" -#include "crypto/RIPEMD160_helper.h" -#include "crypto/bitcoin/sha256_helper.h" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "core" -ENABLE_CHANNEL_BY_DEFAULT("core"); - -using namespace std; -using namespace epee; -using namespace currency; - -#define BLOCKCHAIN_STORAGE_CONTAINER_BLOCKS "blocks" -#define BLOCKCHAIN_STORAGE_CONTAINER_BLOCKS_INDEX "blocks_index" -#define BLOCKCHAIN_STORAGE_CONTAINER_TRANSACTIONS "transactions" -#define BLOCKCHAIN_STORAGE_CONTAINER_SPENT_KEYS "spent_keys" -#define BLOCKCHAIN_STORAGE_CONTAINER_OUTPUTS "outputs" -#define BLOCKCHAIN_STORAGE_CONTAINER_MULTISIG_OUTS "multisig_outs" -#define BLOCKCHAIN_STORAGE_CONTAINER_INVALID_BLOCKS "invalid_blocks" -#define BLOCKCHAIN_STORAGE_CONTAINER_SOLO_OPTIONS "solo" -#define BLOCKCHAIN_STORAGE_CONTAINER_ALIASES "aliases" -#define BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS "addr_to_alias" -#define BLOCKCHAIN_STORAGE_CONTAINER_TX_FEE_MEDIAN "median_fee2" -#define BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS "gindex_increments" - -#define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT 0 -#define BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_PRUNED_RS_HEIGHT 1 -#define BLOCKCHAIN_STORAGE_OPTIONS_ID_LAST_WORKED_VERSION 2 -#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 3 //DON'T CHANGE THIS, if you need to resync db change BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION -#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION 4 //mismatch here means some reinitializations - -#define TARGETDATA_CACHE_SIZE DIFFICULTY_WINDOW + 10 - -#ifndef TESTNET -#define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 57000 -#else -#define BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION 18000 -#endif -#define BLOCK_POS_STRICT_SEQUENCE_LIMIT 20 - - - -DISABLE_VS_WARNINGS(4267) - -namespace -{ - const command_line::arg_descriptor arg_db_cache_l1 = { "db-cache-l1", "Specify size of memory mapped db cache file", 0, true }; - const command_line::arg_descriptor arg_db_cache_l2 = { "db-cache-l2", "Specify cached elements in db helpers", 0, true }; -} - -//------------------------------------------------------------------ -blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m_rw_lock), - m_db_blocks(m_db), - m_db_blocks_index(m_db), - m_db_transactions(m_db), - m_db_spent_keys(m_db), - m_db_outputs(m_db), - m_db_multisig_outs(m_db), - m_db_solo_options(m_db), - m_db_aliases(m_db), - m_db_addr_to_alias(m_db), - m_read_lock(m_rw_lock), - m_db_current_block_cumul_sz_limit(BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_BLOCK_CUMUL_SZ_LIMIT, m_db_solo_options), - m_db_current_pruned_rs_height(BLOCKCHAIN_STORAGE_OPTIONS_ID_CURRENT_PRUNED_RS_HEIGHT, m_db_solo_options), - m_db_last_worked_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_LAST_WORKED_VERSION, m_db_solo_options), - m_db_storage_major_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION, m_db_solo_options), - m_db_storage_minor_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION, m_db_solo_options), - m_db_per_block_gindex_incs(m_db), - m_tx_pool(tx_pool), - m_is_in_checkpoint_zone(false), - m_is_blockchain_storing(false), - m_core_runtime_config(get_default_core_runtime_config()), - //m_bei_stub(AUTO_VAL_INIT(m_bei_stub)), - m_event_handler(&m_event_handler_stub), - m_interprocess_locker_file(0), - m_current_fee_median(0), - m_current_fee_median_effective_index(0), - m_is_reorganize_in_process(false), - m_deinit_is_done(false), - m_cached_next_pow_difficulty(0), - m_cached_next_pos_difficulty(0), - m_blockchain_launch_timestamp(0) - - -{ - m_services_mgr.set_core_runtime_config(m_core_runtime_config); - m_performance_data.epic_failure_happend = false; -} -blockchain_storage::~blockchain_storage() -{ - if (!m_deinit_is_done) - deinit(); - -} -//------------------------------------------------------------------ -bool blockchain_storage::have_tx(const crypto::hash &id) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_transactions.find(id) != m_db_transactions.end(); -} -//------------------------------------------------------------------ -bool blockchain_storage::have_tx_keyimg_as_spent(const crypto::key_image &key_im, uint64_t before_height /* = UINT64_MAX */) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto it_ptr = m_db_spent_keys.get(key_im); - if (!it_ptr) - return false; - return *it_ptr < before_height; -} -//------------------------------------------------------------------ -std::shared_ptr blockchain_storage::get_tx(const crypto::hash &id) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto it = m_db_transactions.find(id); - if (it == m_db_transactions.end()) - return std::shared_ptr(nullptr); - - return std::make_shared(it->tx); -} -//------------------------------------------------------------------ -void blockchain_storage::init_options(boost::program_options::options_description& desc) -{ - command_line::add_arg(desc, arg_db_cache_l1); - command_line::add_arg(desc, arg_db_cache_l2); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_block_h_older_then(uint64_t timestamp) const -{ - // get avarage block position - uint64_t last_block_timestamp = m_db_blocks.back()->bl.timestamp; - if (timestamp >= last_block_timestamp) - return get_top_block_height(); - uint64_t difference = last_block_timestamp - timestamp; - uint64_t n_blocks = difference / (DIFFICULTY_TOTAL_TARGET); - if (n_blocks >= get_top_block_height()) - return 0; - uint64_t index = get_top_block_height() - n_blocks; - while (true) - { - if (index == 0) - return 0; - if (m_db_blocks[index]->bl.timestamp < timestamp) - return index; - index--; - } - return 0; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_current_blockchain_size() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_blocks.size(); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_top_block_height() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_blocks.size() - 1; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_instance(const std::string& path) -{ - std::string locker_name = path + "/" + std::string(CURRENCY_CORE_INSTANCE_LOCK_FILE); - bool r = epee::file_io_utils::open_and_lock_file(locker_name, m_interprocess_locker_file); - - if (r) - return true; - else - { - LOG_ERROR("Failed to initialize db: some other instance is already running"); - return false; - } -} -//------------------------------------------------------------------ -bool blockchain_storage::init(const std::string& config_folder, const boost::program_options::variables_map& vm) -{ -// CRITICAL_REGION_LOCAL(m_read_lock); - - tools::db::db_backend_selector dbbs; - dbbs.init(vm); - auto p_backend = dbbs.create_backend(); - if (!p_backend) - { - LOG_PRINT_RED_L0("Failed to create db engine"); - return false; - } - m_db.reset_backend(p_backend); - LOG_PRINT_L0("DB ENGINE USED BY CORE: " << m_db.get_backend()->name()); - - if (!validate_instance(config_folder)) - { - LOG_ERROR("Failed to initialize instance"); - return false; - } - - uint64_t cache_size_l1 = CACHE_SIZE; - if (command_line::has_arg(vm, arg_db_cache_l1)) - { - cache_size_l1 = command_line::get_arg(vm, arg_db_cache_l1); - } - LOG_PRINT_GREEN("Using db file cache size(L1): " << cache_size_l1, LOG_LEVEL_0); - - m_config_folder = config_folder; - - // remove old incompatible DB - const std::string old_db_folder_path = m_config_folder + "/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD; - if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(old_db_folder_path))) - { - LOG_PRINT_YELLOW("Removing old DB in " << old_db_folder_path << "...", LOG_LEVEL_0); - boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path)); - } - - const std::string db_folder_path = dbbs.get_db_folder_path(); - LOG_PRINT_L0("Loading blockchain from " << db_folder_path); - - bool db_opened_okay = false; - for(size_t loading_attempt_no = 0; loading_attempt_no < 2; ++loading_attempt_no) - { - bool res = m_db.open(db_folder_path, cache_size_l1); - if (!res) - { - // if DB could not be opened -- try to remove the whole folder and re-open DB - LOG_PRINT_YELLOW("Failed to initialize database in folder: " << db_folder_path << ", first attempt", LOG_LEVEL_0); - boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path)); - res = m_db.open(db_folder_path, cache_size_l1); - CHECK_AND_ASSERT_MES(res, false, "Failed to initialize database in folder: " << db_folder_path << ", second attempt"); - } - - res = m_db_blocks.init(BLOCKCHAIN_STORAGE_CONTAINER_BLOCKS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_blocks_index.init(BLOCKCHAIN_STORAGE_CONTAINER_BLOCKS_INDEX); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_transactions.init(BLOCKCHAIN_STORAGE_CONTAINER_TRANSACTIONS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_spent_keys.init(BLOCKCHAIN_STORAGE_CONTAINER_SPENT_KEYS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_outputs.init(BLOCKCHAIN_STORAGE_CONTAINER_OUTPUTS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_multisig_outs.init(BLOCKCHAIN_STORAGE_CONTAINER_MULTISIG_OUTS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_solo_options.init(BLOCKCHAIN_STORAGE_CONTAINER_SOLO_OPTIONS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_addr_to_alias.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_per_block_gindex_incs.init(BLOCKCHAIN_STORAGE_CONTAINER_GINDEX_INCS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - - if (command_line::has_arg(vm, arg_db_cache_l2)) - { - uint64_t cache_size = command_line::get_arg(vm, arg_db_cache_l2); - LOG_PRINT_GREEN("Using db items cache size(L2): " << cache_size, LOG_LEVEL_0); - m_db_blocks_index.set_cache_size(cache_size); - m_db_blocks.set_cache_size(cache_size); - m_db_blocks_index.set_cache_size(cache_size); - m_db_transactions.set_cache_size(cache_size); - m_db_spent_keys.set_cache_size(cache_size); - //m_db_outputs.set_cache_size(cache_size); - m_db_multisig_outs.set_cache_size(cache_size); - m_db_solo_options.set_cache_size(cache_size); - m_db_aliases.set_cache_size(cache_size); - m_db_addr_to_alias.set_cache_size(cache_size); - } - - bool need_reinit = false; - if (m_db_blocks.size() != 0) - { -#ifndef TESTNET - if ((m_db_storage_major_compatibility_version == 93 || m_db_storage_major_compatibility_version == 94) && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 95) - { - // migrate DB to rebuild aliases container - LOG_PRINT_MAGENTA("Migrating DB: " << m_db_storage_major_compatibility_version << " -> " << BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0); - - res = m_db_aliases.deinit(); - CHECK_AND_ASSERT_MES(res, false, "Unable to deinit m_db_aliases"); - res = m_db_addr_to_alias.deinit(); - CHECK_AND_ASSERT_MES(res, false, "Unable to deinit m_db_addr_to_alias"); - - typedef tools::db::cached_key_value_accessor, true, true> aliases_container_old; - aliases_container_old db_aliases_old(m_db); - res = db_aliases_old.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db_aliases_old"); - - typedef tools::db::cached_key_value_accessor, true, false> address_to_aliases_container_old; - address_to_aliases_container_old db_addr_to_alias_old(m_db); - res = db_addr_to_alias_old.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db_addr_to_alias_old"); - - // temporary set db compatibility version to zero during migration in order to trigger db reinit on the next lanunch in case the process stops in the middle - m_db.begin_transaction(); - uint64_t tmp_db_maj_version = m_db_storage_major_compatibility_version; - m_db_storage_major_compatibility_version = 0; - m_db.commit_transaction(); - - typedef std::vector>> tmp_container_t; - tmp_container_t temp_container; - db_aliases_old.enumerate_items([&temp_container](uint64_t i, const std::string& alias, const std::list& alias_entries) - { - std::pair> p(alias, std::list()); - for(auto& entry : alias_entries) - p.second.push_back(static_cast(entry)); // here conversion to the new format goes - temp_container.emplace_back(p); - return true; - }); - - typedef std::vector>> add_to_alias_container_t; - add_to_alias_container_t addr_to_alias_container; - db_addr_to_alias_old.enumerate_items([&addr_to_alias_container](uint64_t n, const account_public_address_old& addr_old, const std::set& aliases){ - addr_to_alias_container.emplace_back(std::make_pair(account_public_address::from_old(addr_old), aliases)); - return true; - }); - - // clear and close old format container - m_db.begin_transaction(); - db_aliases_old.clear(); - db_addr_to_alias_old.clear(); - m_db.commit_transaction(); - db_aliases_old.deinit(); - db_addr_to_alias_old.deinit(); - - res = m_db_aliases.init(BLOCKCHAIN_STORAGE_CONTAINER_ALIASES); - CHECK_AND_ASSERT_MES(res, false, "Unable to init m_db_aliases"); - res = m_db_addr_to_alias.init(BLOCKCHAIN_STORAGE_CONTAINER_ADDR_TO_ALIAS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init m_db_addr_to_alias"); - - // re-populate all alias entries back - m_db.begin_transaction(); - for(auto& el : temp_container) - m_db_aliases.set(el.first, el.second); - - for(auto& el : addr_to_alias_container) - m_db_addr_to_alias.set(el.first, el.second); - m_db.commit_transaction(); - - // restore db maj compartibility - m_db.begin_transaction(); - m_db_storage_major_compatibility_version = tmp_db_maj_version; - m_db.commit_transaction(); - - LOG_PRINT_MAGENTA("Migrating DB: successfully done", LOG_LEVEL_0); - } - else if (m_db_storage_major_compatibility_version == 93 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 94) - { - // do not reinit db if moving from version 93 to version 94 - LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v93 to v94", LOG_LEVEL_0); - } -#else - // TESTNET - if (m_db_storage_major_compatibility_version == 95 && BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION == 96) - { - // do not reinit TESTNET db if moving from version 95 to version 96 - LOG_PRINT_MAGENTA("DB storage does not need reinit because moving from v95 to v96", LOG_LEVEL_0); - } -#endif - else if (m_db_storage_major_compatibility_version != BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION) - { - need_reinit = true; - LOG_PRINT_MAGENTA("DB storage needs reinit because it has major compatibility ver " << m_db_storage_major_compatibility_version << ", expected : " << BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0); - } - else if (m_db_storage_minor_compatibility_version > BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION) - { - // reinit db only if minor version in the DB is greather (i.e. newer) than minor version in the code - need_reinit = true; - LOG_PRINT_MAGENTA("DB storage needs reinit because it has minor compatibility ver " << m_db_storage_minor_compatibility_version << " that is greater than BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION: " << BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION, LOG_LEVEL_0); - } - } - - if (need_reinit) - { - LOG_PRINT_L1("DB at " << db_folder_path << " is about to be deleted and re-created..."); - m_db_blocks.deinit(); - m_db_blocks_index.deinit(); - m_db_transactions.deinit(); - m_db_spent_keys.deinit(); - m_db_outputs.deinit(); - m_db_multisig_outs.deinit(); - m_db_solo_options.deinit(); - m_db_aliases.deinit(); - m_db_addr_to_alias.deinit(); - m_db_per_block_gindex_incs.deinit(); - m_db.close(); - size_t files_removed = boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path)); - LOG_PRINT_L1(files_removed << " files at " << db_folder_path << " removed"); - - // try to re-create DB and re-init containers - continue; - } - - db_opened_okay = true; - break; - } - - CHECK_AND_ASSERT_MES(db_opened_okay, false, "All attempts to open DB at " << db_folder_path << " failed"); - - if (!m_db_blocks.size()) - { - // empty DB: generate and add genesis block - block bl = boost::value_initialized(); - block_verification_context bvc = boost::value_initialized(); - generate_genesis_block(bl); - add_new_block(bl, bvc); - CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Failed to add genesis block to blockchain"); - LOG_PRINT_MAGENTA("Storage initialized with genesis", LOG_LEVEL_0); - } - - store_db_solo_options_values(); - - m_services_mgr.init(config_folder, vm); - - //print information message - uint64_t timestamp_diff = m_core_runtime_config.get_core_time() - m_db_blocks.back()->bl.timestamp; - if(!m_db_blocks.back()->bl.timestamp) - timestamp_diff = m_core_runtime_config.get_core_time() - 1341378000; - - m_db.begin_transaction(); - set_lost_tx_unmixable(); - m_db.commit_transaction(); - - LOG_PRINT_GREEN("Blockchain initialized. (v:" << m_db_storage_major_compatibility_version << ") last block: " << m_db_blocks.size() - 1 << ENDL - << "genesis: " << get_block_hash(m_db_blocks[0]->bl) << ENDL - << "last block: " << m_db_blocks.size() - 1 << ", " << misc_utils::get_time_interval_string(timestamp_diff) << " time ago" << ENDL - << "current pos difficulty: " << get_next_diff_conditional(true) << ENDL - << "current pow difficulty: " << get_next_diff_conditional(false) << ENDL - << "total transactions: " << m_db_transactions.size(), - LOG_LEVEL_0); - - return true; -} - -//------------------------------------------------------------------ -bool blockchain_storage::set_lost_tx_unmixable_for_height(uint64_t height) -{ -#ifndef TESTNET - if (height == 75738) - return set_lost_tx_unmixable(); -#endif - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::set_lost_tx_unmixable() -{ -#ifndef TESTNET - if (m_db_blocks.size() > 75738) - { - crypto::hash tx_id_1 = epee::string_tools::parse_tpod_from_hex_string("c2a2229d614e7c026433efbcfdbd0be1f68d9b419220336df3e2c209f5d57314"); - crypto::hash tx_id_2 = epee::string_tools::parse_tpod_from_hex_string("647f936c6ffbd136f5c95d9a90ad554bdb4c01541c6eb5755ad40b984d80da67"); - - auto tx_ptr_1 = m_db_transactions.find(tx_id_1); - CHECK_AND_ASSERT_MES(tx_ptr_1, false, "Internal error: filed to find lost tx"); - transaction_chain_entry tx1_local_entry(*tx_ptr_1); - for (size_t i = 0; i != tx1_local_entry.m_spent_flags.size(); i++) - { - tx1_local_entry.m_spent_flags[i] = true; - } - m_db_transactions.set(tx_id_1, tx1_local_entry); - - auto tx_ptr_2 = m_db_transactions.find(tx_id_2); - transaction_chain_entry tx2_local_entry(*tx_ptr_2); - CHECK_AND_ASSERT_MES(tx_ptr_1, false, "Internal error: filed to find lost tx"); - for (size_t i = 0; i != tx2_local_entry.m_spent_flags.size(); i++) - { - tx2_local_entry.m_spent_flags[i] = true; - } - m_db_transactions.set(tx_id_2, tx2_local_entry); - } -#endif - return true; -} -//------------------------------------------------------------------ -void blockchain_storage::patch_out_if_needed(txout_to_key& out, const crypto::hash& tx_id, uint64_t n) const -{ -#ifndef TESTNET - static crypto::hash tx_id_1 = epee::string_tools::parse_tpod_from_hex_string("c2a2229d614e7c026433efbcfdbd0be1f68d9b419220336df3e2c209f5d57314"); - static crypto::hash tx_id_2 = epee::string_tools::parse_tpod_from_hex_string("647f936c6ffbd136f5c95d9a90ad554bdb4c01541c6eb5755ad40b984d80da67"); - - if (tx_id == tx_id_1 && n == 12) - { - out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; - }else if(tx_id == tx_id_2 && n == 5) - { - out.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; - } -#endif -} -//------------------------------------------------------------------ -void blockchain_storage::store_db_solo_options_values() -{ - m_db.begin_transaction(); - m_db_storage_major_compatibility_version = BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION; - m_db_storage_minor_compatibility_version = BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION; - m_db_last_worked_version = std::string(PROJECT_VERSION_LONG); - m_db.commit_transaction(); -} -//------------------------------------------------------------------ -bool blockchain_storage::deinit() -{ - m_db.close(); - epee::file_io_utils::unlock_and_close_file(m_interprocess_locker_file); - m_deinit_is_done = true; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::pop_block_from_blockchain(transactions_map& onboard_transactions) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - CHECK_AND_ASSERT_MES(m_db_blocks.size() > 1, false, "pop_block_from_blockchain: can't pop from blockchain with size = " << m_db_blocks.size()); - size_t h = m_db_blocks.size()-1; - auto bei_ptr = m_db_blocks[h]; - CHECK_AND_ASSERT_MES(bei_ptr.get(), false, "pop_block_from_blockchain: can't pop from blockchain"); - - uint64_t fee_total = 0; - bool r = purge_block_data_from_blockchain(bei_ptr->bl, bei_ptr->bl.tx_hashes.size(), fee_total, onboard_transactions); - CHECK_AND_ASSERT_MES(r, false, "Failed to purge_block_data_from_blockchain for block " << get_block_hash(bei_ptr->bl) << " on height " << h); - - pop_block_from_per_block_increments(bei_ptr->height); - - //remove from index - r = m_db_blocks_index.erase_validate(get_block_hash(bei_ptr->bl)); - CHECK_AND_ASSERT_MES_NO_RET(r, "pop_block_from_blockchain: block id not found in m_blocks_index while trying to delete it"); - - //pop block from core - m_db_blocks.pop_back(); - - on_block_removed(*bei_ptr); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::set_checkpoints(checkpoints&& chk_pts) -{ - m_checkpoints = chk_pts; - try - { - m_db.begin_transaction(); - if (m_db_blocks.size() < m_checkpoints.get_top_checkpoint_height()) - m_is_in_checkpoint_zone = true; - prune_ring_signatures_and_attachments_if_need(); - m_db.commit_transaction(); - return true; - } - catch (const std::exception& ex) - { - m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS: " << ex.what()); - return false; - } - catch (...) - { - m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS."); - return false; - } - -} -//------------------------------------------------------------------ -bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height, uint64_t& transactions_pruned, uint64_t& signatures_pruned, uint64_t& attachments_pruned) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() = " << m_db_blocks.size()); - auto vptr = m_db_blocks[height]; - CHECK_AND_ASSERT_MES(vptr.get(), false, "Failed to get block on height"); - - for (const auto& h : vptr->bl.tx_hashes) - { - auto it = m_db_transactions.find(h); - CHECK_AND_ASSERT_MES(it != m_db_transactions.end(), false, "failed to find transaction " << h << " in blockchain index, in block on height = " << height); - - - CHECK_AND_ASSERT_MES(it->m_keeper_block_height == height, false, - "failed to validate extra check, it->second.m_keeper_block_height = " << it->m_keeper_block_height << - "is mot equal to height = " << height << " in blockchain index, for block on height = " << height); - - transaction_chain_entry lolcal_chain_entry = *it; - signatures_pruned += lolcal_chain_entry.tx.signatures.size(); - attachments_pruned += lolcal_chain_entry.tx.attachment.size(); - lolcal_chain_entry.tx.signatures.clear(); - lolcal_chain_entry.tx.attachment.clear(); - - //reassign to db - m_db_transactions.set(h, lolcal_chain_entry); - - ++transactions_pruned; - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::prune_ring_signatures_and_attachments_if_need() -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - uint64_t top_block_height = get_top_block_height(); - uint64_t pruning_end_height = m_checkpoints.get_checkpoint_before_height(top_block_height); - if (pruning_end_height > m_db_current_pruned_rs_height) - { - LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_end_height - << " (" << pruning_end_height - m_db_current_pruned_rs_height << " blocks), top block height is " << top_block_height, LOG_LEVEL_0); - uint64_t tx_count = 0, sig_count = 0, attach_count = 0; - for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_end_height; height++) - { - bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count); - CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height); - } - m_db_current_pruned_rs_height = pruning_end_height; - LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::clear() -{ - //CRITICAL_REGION_LOCAL(m_read_lock); - m_db.begin_transaction(); - - m_db_blocks.clear(); - m_db_blocks_index.clear(); - m_db_transactions.clear(); - m_db_spent_keys.clear(); - m_db_solo_options.clear(); - store_db_solo_options_values(); - m_db_outputs.clear(); - m_db_multisig_outs.clear(); - m_db_aliases.clear(); - m_db_addr_to_alias.clear(); - m_db_per_block_gindex_incs.clear(); - m_pos_targetdata_cache.clear(); - m_pow_targetdata_cache.clear(); - - m_db.commit_transaction(); - - - { - CRITICAL_REGION_LOCAL(m_invalid_blocks_lock); - m_invalid_blocks.clear(); // crypto::hash -> block_extended_info - } - { - CRITICAL_REGION_LOCAL(m_alternative_chains_lock); - m_alternative_chains.clear(); - m_altblocks_keyimages.clear(); - m_alternative_chains_txs.clear(); - } - - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::reset_and_set_genesis_block(const block& b) -{ - clear(); - block_verification_context bvc = boost::value_initialized(); - add_new_block(b, bvc); - if(!bvc.m_added_to_main_chain || bvc.m_verification_failed) - { - LOG_ERROR("Blockchain reset failed.") - return false; - } - LOG_PRINT_GREEN("Blockchain reset. Genesis block: " << get_block_hash(b) << ", " << misc_utils::get_time_interval_string(m_core_runtime_config.get_core_time() - b.timestamp) << " ago", LOG_LEVEL_0); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const transaction& tx, bool strict_check) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - struct purge_transaction_visitor: public boost::static_visitor - { - blockchain_storage& m_bcs; - key_images_container& m_spent_keys; - bool m_strict_check; - purge_transaction_visitor(blockchain_storage& bcs, key_images_container& spent_keys, bool strict_check): - m_bcs(bcs), - m_spent_keys(spent_keys), - m_strict_check(strict_check){} - - bool operator()(const txin_to_key& inp) const - { - bool r = m_spent_keys.erase_validate(inp.k_image); - CHECK_AND_ASSERT_MES( !(!r && m_strict_check), false, "purge_transaction_keyimages_from_blockchain: key image " << inp.k_image << " was not found"); - - if(inp.key_offsets.size() == 1) - { - //direct spend detected - if(!m_bcs.update_spent_tx_flags_for_input(inp.amount, inp.key_offsets[0], false)) - { - //internal error - LOG_PRINT_L0("Failed to update_spent_tx_flags_for_input"); - return false; - } - } - - return true; - } - bool operator()(const txin_gen& inp) const - { - return true; - } - bool operator()(const txin_multisig& inp) const - { - if (!m_bcs.update_spent_tx_flags_for_input(inp.multisig_out_id, 0)) - { - LOG_PRINT_L0("update_spent_tx_flags_for_input failed for multisig id " << inp.multisig_out_id << " amount: " << inp.amount); - return false; - } - return true; - } - bool operator()(const txin_htlc& inp) const - { - return this->operator()(static_cast(inp)); - } - }; - - for(const txin_v& in : tx.vin) - { - bool r = boost::apply_visitor(purge_transaction_visitor(*this, m_db_spent_keys, strict_check), in); - CHECK_AND_ASSERT_MES(!strict_check || r, false, "failed to process purge_transaction_visitor"); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee, transaction& tx_) -{ - fee = 0; - CRITICAL_REGION_LOCAL(m_read_lock); - - auto tx_res_ptr = m_db_transactions.find(tx_id); - CHECK_AND_ASSERT_MES(tx_res_ptr != m_db_transactions.end(), false, "transaction " << tx_id << " is not found in blockchain index!!"); - const transaction& tx = tx_res_ptr->tx; - tx_ = tx; - - fee = get_tx_fee(tx_res_ptr->tx); - purge_transaction_keyimages_from_blockchain(tx, true); - - bool r = unprocess_blockchain_tx_extra(tx); - CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra for tx " << tx_id); - - r = unprocess_blockchain_tx_attachments(tx, get_current_blockchain_size(), 0/*TODO: add valid timestamp here in future if need*/); - - bool added_to_the_pool = false; - if(!is_coinbase(tx)) - { - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - added_to_the_pool = m_tx_pool.add_tx(tx, tvc, true, true); - CHECK_AND_ASSERT_MES(added_to_the_pool, false, "failed to add transaction " << tx_id << " to transaction pool"); - } - - bool res = pop_transaction_from_global_index(tx, tx_id); - CHECK_AND_ASSERT_MES_NO_RET(res, "pop_transaction_from_global_index failed for tx " << tx_id); - bool res_erase = m_db_transactions.erase_validate(tx_id); - CHECK_AND_ASSERT_MES_NO_RET(res_erase, "Failed to m_transactions.erase with id = " << tx_id); - - LOG_PRINT_L1("transaction " << tx_id << (added_to_the_pool ? " was removed from blockchain history -> to the pool" : " was removed from blockchain history")); - return res; -} - -//------------------------------------------------------------------ -bool blockchain_storage::purge_block_data_from_blockchain(const block& b, size_t processed_tx_count) -{ - uint64_t total_fee = 0; - transactions_map onboard_transactions; - return purge_block_data_from_blockchain(b, processed_tx_count, total_fee, onboard_transactions); -} -//------------------------------------------------------------------ -bool blockchain_storage::purge_block_data_from_blockchain(const block& bl, size_t processed_tx_count, uint64_t& fee_total, transactions_map& onboard_transactions) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - fee_total = 0; - uint64_t fee = 0; - bool res = true; - CHECK_AND_ASSERT_MES(processed_tx_count <= bl.tx_hashes.size(), false, "wrong processed_tx_count in purge_block_data_from_blockchain"); - for(size_t count = 0; count != processed_tx_count; count++) - { - transaction tx = AUTO_VAL_INIT(tx); - res = purge_transaction_from_blockchain(bl.tx_hashes[(processed_tx_count -1)- count], fee, tx) && res; - fee_total += fee; - onboard_transactions[bl.tx_hashes[(processed_tx_count - 1) - count]] = tx; - } - transaction tx = AUTO_VAL_INIT(tx); - res = purge_transaction_from_blockchain(get_transaction_hash(bl.miner_tx), fee, tx) && res; - return res; -} -//------------------------------------------------------------------ -crypto::hash blockchain_storage::get_top_block_id(uint64_t& height) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - height = get_top_block_height(); - return get_top_block_id(); -} -//------------------------------------------------------------------ -crypto::hash blockchain_storage::get_top_block_id() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - crypto::hash id = null_hash; - if(m_db_blocks.size()) - { - auto val_ptr = m_db_blocks.back(); - CHECK_AND_ASSERT_MES(val_ptr, null_hash, "m_blocks.back() returned null"); - get_block_hash(val_ptr->bl, id); - } - return id; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_top_block(block& b) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(m_db_blocks.size(), false, "Wrong blockchain state, m_blocks.size()=0!"); - auto val_ptr = m_db_blocks.back(); - CHECK_AND_ASSERT_MES(val_ptr.get(), false, "m_blocks.back() returned null"); - b = val_ptr->bl; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_short_chain_history(std::list& ids)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - size_t i = 0; - size_t current_multiplier = 1; - size_t sz = m_db_blocks.size(); - if(!sz) - return true; - size_t current_back_offset = 1; - bool genesis_included = false; - while(current_back_offset < sz) - { - ids.push_back(get_block_hash(m_db_blocks[sz-current_back_offset]->bl)); - if(sz-current_back_offset == 0) - genesis_included = true; - if(i < 10) - { - ++current_back_offset; - }else - { - current_back_offset += current_multiplier *= 2; - } - ++i; - } - if(!genesis_included) - ids.push_back(get_block_hash(m_db_blocks[0]->bl)); - - return true; -} -//------------------------------------------------------------------ -crypto::hash blockchain_storage::get_block_id_by_height(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(height >= m_db_blocks.size()) - return null_hash; - - return get_block_hash(m_db_blocks[height]->bl); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_block_by_hash(const crypto::hash &h, block &blk) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - // try to find block in main chain - auto it = m_db_blocks_index.find(h); - if (m_db_blocks_index.end() != it) - { - blk = m_db_blocks[*it]->bl; - return true; - } - - // try to find block in alternative chain - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - - auto it_alt = m_alternative_chains.find(h); - if (m_alternative_chains.end() != it_alt) - { - blk = it_alt->second.bl; - return true; - } - - return false; -} -bool blockchain_storage::is_tx_related_to_altblock(crypto::hash tx_id) const -{ - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - auto it = m_alternative_chains_txs.find(tx_id); - return it != m_alternative_chains_txs.end(); -} - -//------------------------------------------------------------------ -bool blockchain_storage::get_block_extended_info_by_hash(const crypto::hash &h, block_extended_info &blk) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - // try to find block in main chain - auto vptr = m_db_blocks_index.find(h); - if (vptr) - { - return get_block_extended_info_by_height(*vptr, blk); - } - - // try to find block in alternative chain - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - auto it_alt = m_alternative_chains.find(h); - if (m_alternative_chains.end() != it_alt) - { - blk = it_alt->second; - return true; - } - - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_block_extended_info_by_height(uint64_t h, block_extended_info &blk) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - if (h >= m_db_blocks.size()) - return false; - - blk = *m_db_blocks[h]; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_block_by_height(uint64_t h, block &blk) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(h >= m_db_blocks.size() ) - return false; - blk = m_db_blocks[h]->bl; - return true; -} -//------------------------------------------------------------------ -// void blockchain_storage::get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid) const -// { -// CRITICAL_REGION_LOCAL(m_blockchain_lock); -// -// for (auto &v : m_blocks_index) -// main.push_back(v.first); -// -// for (auto &v : m_alternative_chains) -// alt.push_back(v.first); -// -// for(auto &v: m_invalid_blocks) -// invalid.push_back(v.first); -// } -//------------------------------------------------------------------ -bool blockchain_storage::rollback_blockchain_switching(std::list& original_chain, size_t rollback_height) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - //remove failed subchain - for(size_t i = m_db_blocks.size()-1; i >=rollback_height; i--) - { - transactions_map ot; - bool r = pop_block_from_blockchain(ot); - CHECK_AND_ASSERT_MES(r, false, "PANIC!!! failed to remove block while chain switching during the rollback!"); - } - //return back original chain - BOOST_FOREACH(auto& oce, original_chain) - { - block_verification_context bvc = boost::value_initialized(); - bvc.m_onboard_transactions.swap(oce.onboard_transactions); - bool r = handle_block_to_main_chain(oce.b, bvc); - CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC!!! failed to add (again) block while chain switching during the rollback!"); - } - - LOG_PRINT_L0("Rollback success."); - return true; -} -//------------------------------------------------------------------ -void blockchain_storage::add_alt_block_txs_hashs(const block& b) -{ - CRITICAL_REGION_LOCAL(m_alternative_chains_lock); - for (const auto& tx_hash : b.tx_hashes) - { - m_alternative_chains_txs[tx_hash]++; - } -} -//------------------------------------------------------------------ -void blockchain_storage::purge_alt_block_txs_hashs(const block& b) -{ - CRITICAL_REGION_LOCAL(m_alternative_chains_lock); - for (const auto& h : b.tx_hashes) - { - auto it = m_alternative_chains_txs.find(h); - if (it == m_alternative_chains_txs.end()) - { - LOG_ERROR("Internal error: tx with hash " << h << " not found in m_alternative_chains_txs while removing block " << get_block_hash(b)); - continue; - } - - if (it->second >= 1) - { - it->second--; - } - else - { - LOG_ERROR("Internal error: tx with hash " << h << " has invalid m_alternative_chains_txs entry (zero count) while removing block " << get_block_hash(b)); - } - if (it->second == 0) - m_alternative_chains_txs.erase(it); - } -} -//------------------------------------------------------------------ -void blockchain_storage::do_erase_altblock(alt_chain_container::iterator it) -{ - crypto::hash id = get_block_hash(it->second.bl); - LOG_PRINT_L1("erasing alt block " << print16(id) << " @ " << get_block_height(it->second.bl)); - purge_altblock_keyimages_from_big_heap(it->second.bl, id); - purge_alt_block_txs_hashs(it->second.bl); - m_alternative_chains.erase(it); -} -//------------------------------------------------------------------ -bool blockchain_storage::switch_to_alternative_blockchain(alt_chain_type& alt_chain) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - - CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed"); - - size_t split_height = alt_chain.front()->second.height; - CHECK_AND_ASSERT_MES(m_db_blocks.size() >= split_height, false, "switch_to_alternative_blockchain: blockchain size is lower than split height" << ENDL - << " alt chain: " << ENDL << print_alt_chain(alt_chain) << ENDL - << " main chain: " << ENDL << get_blockchain_string(m_db_blocks.size() - 10, CURRENCY_MAX_BLOCK_NUMBER) - ); - - //disconnecting old chain - std::list disconnected_chain; - for(size_t i = m_db_blocks.size()-1; i >=split_height; i--) - { - disconnected_chain.push_front(block_ws_txs()); - block_ws_txs& bwt = disconnected_chain.front(); - bwt.b = m_db_blocks[i]->bl; - bool r = pop_block_from_blockchain(bwt.onboard_transactions); - CHECK_AND_ASSERT_MES(r, false, "failed to remove block " << get_block_hash(bwt.b) << " @ " << get_block_height(bwt.b) << " on chain switching"); - - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - } - - //connecting new alternative chain - for(auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++) - { - auto ch_ent = *alt_ch_iter; - block_verification_context bvc = boost::value_initialized(); - bvc.m_onboard_transactions = ch_ent->second.onboard_transactions; - bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc); - if(!r || !bvc.m_added_to_main_chain) - { - LOG_PRINT_L0("Failed to switch to alternative blockchain"); - rollback_blockchain_switching(disconnected_chain, split_height); - LOG_PRINT_L0("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl)); - - for(; alt_ch_iter != alt_chain.end(); ++alt_ch_iter) - { - add_block_as_invalid((*alt_ch_iter)->second, (*alt_ch_iter)->first); - do_erase_altblock(*alt_ch_iter); - } - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - return false; - } - } - - //pushing old chain as alternative chain - for(auto& old_ch_ent : disconnected_chain) - { - block_verification_context bvc = boost::value_initialized(); - bvc.m_onboard_transactions.swap(old_ch_ent.onboard_transactions); - bool r = handle_alternative_block(old_ch_ent.b, get_block_hash(old_ch_ent.b), bvc); - if(!r) - { - LOG_ERROR("Failed to push ex-main chain blocks to alternative chain "); - rollback_blockchain_switching(disconnected_chain, split_height); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - - //can't do return false here, because of the risc to get stuck in "PANIC" mode when nor of - //new chain nor altchain can be inserted into main chain. Got core caught in this trap when - //when machine time was wrongly set for a few hours back, then blocks which was detached from main chain - //couldn't be added as alternative due to timestamps validation(timestamps assumed as from future) - //thanks @Gigabyted for reporting this problem - break; - } - } - - //removing all_chain entries from alternative chain - for(auto ch_ent : alt_chain) - { - do_erase_altblock(ch_ent); - } - - LOG_PRINT_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db_blocks.size(), LOG_LEVEL_0); - return true; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - std::vector timestamps; - std::vector commulative_difficulties; - if (!m_db_blocks.size()) - return DIFFICULTY_STARTER; - //skip genesis timestamp - TIME_MEASURE_START_PD(target_calculating_enum_blocks); - CRITICAL_REGION_BEGIN(m_targetdata_cache_lock); - std::list>& targetdata_cache = pos ? m_pos_targetdata_cache : m_pow_targetdata_cache; - //if (targetdata_cache.empty()) - load_targetdata_cache(pos); - - size_t count = 0; - for (auto it = targetdata_cache.rbegin(); it != targetdata_cache.rend() && count < DIFFICULTY_WINDOW; it++) - { - timestamps.push_back(it->second); - commulative_difficulties.push_back(it->first); - ++count; - } - CRITICAL_REGION_END(); - - wide_difficulty_type& dif = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty; - TIME_MEASURE_FINISH_PD(target_calculating_enum_blocks); - TIME_MEASURE_START_PD(target_calculating_calc); - if (m_db_blocks.size() > m_core_runtime_config.hard_fork_01_starts_after_height) - { - dif = next_difficulty_2(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); - } - else - { - dif = next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); - } - - - TIME_MEASURE_FINISH_PD(target_calculating_calc); - return dif; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - std::vector timestamps; - std::vector commulative_difficulties; - size_t count = 0; - if (!m_db_blocks.size()) - return DIFFICULTY_STARTER; - - auto cb = [&](const block_extended_info& bei, bool is_main){ - if (!bei.height) - return false; - bool is_pos_bl = is_pos_block(bei.bl); - if (pos != is_pos_bl) - return true; - timestamps.push_back(bei.bl.timestamp); - commulative_difficulties.push_back(bei.cumulative_diff_precise); - ++count; - if (count >= DIFFICULTY_WINDOW) - return false; - return true; - }; - enum_blockchain(cb, alt_chain, split_height); - - wide_difficulty_type diff = 0; - if(abei.height > m_core_runtime_config.hard_fork_01_starts_after_height) - diff = next_difficulty_2(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); - else - diff = next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET); - return diff; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_cached_next_difficulty(bool pos) const -{ - wide_difficulty_type res = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty; - if (!res) - { - get_next_diff_conditional(pos); - res = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty; - } - return res; -} -//------------------------------------------------------------------ -std::shared_ptr blockchain_storage::get_last_block_of_type(bool looking_for_pos, const alt_chain_type& alt_chain, uint64_t split_height) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - std::shared_ptr pbei(nullptr); - - auto cb = [&](const block_extended_info& bei_local, bool is_main){ - if (looking_for_pos == is_pos_block(bei_local.bl)) - { - pbei.reset(new block_extended_info(bei_local)); - return false; - } - return true; - }; - - - enum_blockchain(cb, alt_chain, split_height); - return pbei; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_next_difficulty_for_alternative_chain(const alt_chain_type& alt_chain, block_extended_info& bei, bool pos) const -{ - std::vector timestamps; - std::vector commulative_difficulties; - - for (auto it = alt_chain.rbegin(); it != alt_chain.rend() && timestamps.size() < DIFFICULTY_BLOCKS_COUNT; it++) - { - bool is_pos_bl = is_pos_block((*it)->second.bl); - if (pos != is_pos_bl) - continue; - timestamps.push_back((*it)->second.bl.timestamp); - commulative_difficulties.push_back((*it)->second.cumulative_diff_precise); - } - - size_t main_chain_start_offset = (alt_chain.size() ? alt_chain.front()->second.height : bei.height)-1; - - for (uint64_t i = main_chain_start_offset; i != 0 && timestamps.size() < DIFFICULTY_BLOCKS_COUNT; --i) - { - bool is_pos_bl = is_pos_block(m_db_blocks[i]->bl); - if (pos != is_pos_bl) - continue; - - timestamps.push_back(m_db_blocks[i]->bl.timestamp); - commulative_difficulties.push_back(m_db_blocks[i]->cumulative_diff_precise); - } - - return next_difficulty_1(timestamps, commulative_difficulties, pos ? DIFFICULTY_POS_TARGET:DIFFICULTY_POW_TARGET); -} -//------------------------------------------------------------------ -bool blockchain_storage::prevalidate_miner_transaction(const block& b, uint64_t height, bool pos) const -{ - CHECK_AND_ASSERT_MES((pos ? (b.miner_tx.vin.size() == 2) : (b.miner_tx.vin.size() == 1)), false, "coinbase transaction in the block has no inputs"); - CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type"); - if(boost::get(b.miner_tx.vin[0]).height != height) - { - LOG_PRINT_RED_L0("The miner transaction in block has invalid height: " << boost::get(b.miner_tx.vin[0]).height << ", expected: " << height); - return false; - } - if (pos) - { - CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key), false, "coinstake transaction in the block has the wrong type"); - } - - if (height > m_core_runtime_config.hard_fork_01_starts_after_height) - { - // new rules that allow different unlock time in coinbase outputs - uint64_t max_unlock_time = 0; - uint64_t min_unlock_time = 0; - bool r = get_tx_max_min_unlock_time(b.miner_tx, max_unlock_time, min_unlock_time); - CHECK_AND_ASSERT_MES(r && min_unlock_time >= height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW, - false, - "coinbase transaction has wrong min_unlock_time: " << min_unlock_time << ", expected: " << height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); - } - else - { - //------------------------------------------------------------------ - //bool blockchain_storage:: - // pre-hard fork rules that don't allow different unlock time in coinbase outputs - uint64_t max_unlock_time = 0; - uint64_t min_unlock_time = 0; - bool r = get_tx_max_min_unlock_time(b.miner_tx, max_unlock_time, min_unlock_time); - CHECK_AND_ASSERT_MES(r && max_unlock_time == min_unlock_time && min_unlock_time == height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW, - false, - "coinbase transaction has wrong min_unlock_time: " << min_unlock_time << ", expected: " << height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); - } - - - //check outs overflow - if(!check_outs_overflow(b.miner_tx)) - { - LOG_PRINT_RED_L0("miner transaction have money overflow in block " << get_block_hash(b)); - return false; - } - - CHECK_AND_ASSERT_MES(b.miner_tx.attachment.empty(), false, "coinbase transaction has attachments; attachments are not allowed for coinbase transactions."); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_miner_transaction(const block& b, - size_t cumulative_block_size, - uint64_t fee, - uint64_t& base_reward, - const boost::multiprecision::uint128_t& already_generated_coins) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - //validate reward - uint64_t money_in_use = get_outs_money_amount(b.miner_tx); - - uint64_t pos_income = 0; - if (is_pos_block(b)) - { - CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key), false, "Wrong miner tx_in"); - pos_income = boost::get(b.miner_tx.vin[1]).amount; - } - - std::vector last_blocks_sizes; - get_last_n_blocks_sizes(last_blocks_sizes, CURRENCY_REWARD_BLOCKS_WINDOW); - size_t blocks_size_median = misc_utils::median(last_blocks_sizes); - if (!get_block_reward(is_pos_block(b), blocks_size_median, cumulative_block_size, already_generated_coins, base_reward, get_block_height(b))) - { - LOG_PRINT_L0("block size " << cumulative_block_size << " is bigger than allowed for this blockchain"); - return false; - } - if (base_reward + pos_income + fee < money_in_use) - { - LOG_ERROR("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + pos_income + fee) << "(" << print_money(base_reward) << "+" << print_money(pos_income) << "+" << print_money(fee) - << ", blocks_size_median = " << blocks_size_median - << ", cumulative_block_size = " << cumulative_block_size - << ", fee = " << fee - << ", already_generated_coins = " << already_generated_coins - << "), tx:"); - LOG_PRINT_L0(currency::obj_to_json_str(b.miner_tx)); - return false; - } - if (base_reward + pos_income + fee != money_in_use) - { - LOG_ERROR("coinbase transaction doesn't use full amount of block reward: spent: (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + pos_income + fee) << "(" << print_money(base_reward) << "+" << print_money(pos_income) << "+" << print_money(fee) - << ", blocks_size_median = " << blocks_size_median - << ", cumulative_block_size = " << cumulative_block_size - << ", fee = " << fee - << ", already_generated_coins = " << already_generated_coins - << "), tx:"); - LOG_PRINT_L0(currency::obj_to_json_str(b.miner_tx)); - return false; - } - LOG_PRINT_MAGENTA("Mining tx verification ok, blocks_size_median = " << blocks_size_median, LOG_LEVEL_2); - return true; -} -//------------------------------------------------------------------ -blockchain_storage::performnce_data& blockchain_storage::get_performnce_data()const -{ - m_db.get_backend()->get_stat_info(m_performance_data.si); - return m_performance_data; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_backward_blocks_sizes(size_t from_height, std::vector& sz, size_t count)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(from_height < m_db_blocks.size(), false, "Internal error: get_backward_blocks_sizes called with from_height=" << from_height << ", blockchain height = " << m_db_blocks.size()); - - size_t start_offset = (from_height+1) - std::min((from_height+1), count); - for(size_t i = start_offset; i != from_height+1; i++) - sz.push_back(m_db_blocks[i]->block_cumulative_size); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_last_n_blocks_sizes(std::vector& sz, size_t count) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(!m_db_blocks.size()) - return true; - return get_backward_blocks_sizes(m_db_blocks.size() -1, sz, count); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_current_comulative_blocksize_limit() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_current_block_cumul_sz_limit; -} -//------------------------------------------------------------------ -bool blockchain_storage::create_block_template(block& b, - const account_public_address& miner_address, - wide_difficulty_type& diffic, - uint64_t& height, - const blobdata& ex_nonce) const -{ - return create_block_template(b, miner_address, miner_address, diffic, height, ex_nonce, false, pos_entry()); -} -//------------------------------------------------------------------ -bool blockchain_storage::create_block_template(block& b, - const account_public_address& miner_address, - const account_public_address& stakeholder_address, - wide_difficulty_type& diffic, - uint64_t& height, - const blobdata& ex_nonce, - bool pos, - const pos_entry& pe, - fill_block_template_func_t custom_fill_block_template_func /* = nullptr */) const -{ - create_block_template_params params = AUTO_VAL_INIT(params); - params.miner_address = miner_address; - params.stakeholder_address = stakeholder_address; - params.ex_nonce = ex_nonce; - params.pos = pos; - params.pe = pe; - params.pcustom_fill_block_template_func = custom_fill_block_template_func; - create_block_template_response resp = AUTO_VAL_INIT(resp); - bool r = create_block_template(params, resp); - b = resp.b; - diffic = resp.diffic; - height = resp.height; - return r; -} - -bool blockchain_storage::create_block_template(const create_block_template_params& params, create_block_template_response& resp) const -{ - const account_public_address& miner_address = params.miner_address; - const account_public_address& stakeholder_address = params.stakeholder_address; - const blobdata& ex_nonce = params.ex_nonce; - bool pos = params.pos; - const pos_entry& pe = params.pe; - fill_block_template_func_t* pcustom_fill_block_template_func = params.pcustom_fill_block_template_func; - - uint64_t& height = resp.height; - block& b = resp.b; - wide_difficulty_type& diffic = resp.diffic; - - - size_t median_size; - boost::multiprecision::uint128_t already_generated_coins; - CRITICAL_REGION_BEGIN(m_read_lock); - height = m_db_blocks.size(); - if(height <= m_core_runtime_config.hard_fork_01_starts_after_height) - b.major_version = BLOCK_MAJOR_VERSION_INITIAL; - else if(height <= m_core_runtime_config.hard_fork_03_starts_after_height) - b.major_version = HF1_BLOCK_MAJOR_VERSION; - else - b.major_version = CURRENT_BLOCK_MAJOR_VERSION; - - b.minor_version = CURRENT_BLOCK_MINOR_VERSION; - b.prev_id = get_top_block_id(); - b.timestamp = m_core_runtime_config.get_core_time(); - b.nonce = 0; - b.flags = 0; - if (pos) - { - b.flags |= CURRENCY_BLOCK_FLAG_POS_BLOCK; - b.timestamp = 0; - } - - diffic = get_next_diff_conditional(pos); - - CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead."); - - - - - median_size = m_db_current_block_cumul_sz_limit / 2; - already_generated_coins = m_db_blocks.back()->already_generated_coins; - - CRITICAL_REGION_END(); - - size_t txs_size = 0; - uint64_t fee = 0; - bool block_filled = false; - if (pcustom_fill_block_template_func == nullptr) - block_filled = m_tx_pool.fill_block_template(b, pos, median_size, already_generated_coins, txs_size, fee, height, params.explicit_txs); - else - block_filled = (*pcustom_fill_block_template_func)(b, pos, median_size, already_generated_coins, txs_size, fee, height); - - if (!block_filled) - return false; - - /* - instead of complicated two-phase template construction and adjustment of cumulative size with block reward we - use CURRENCY_COINBASE_BLOB_RESERVED_SIZE as penalty-free coinbase transaction reservation. - */ - bool r = construct_miner_tx(height, median_size, already_generated_coins, - txs_size, - fee, - miner_address, - stakeholder_address, - b.miner_tx, ex_nonce, - CURRENCY_MINER_TX_MAX_OUTS, - pos, - pe); - CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance"); - uint64_t coinbase_size = get_object_blobsize(b.miner_tx); - // "- 100" - to reserve room for PoS additions into miner tx - CHECK_AND_ASSERT_MES(coinbase_size < CURRENCY_COINBASE_BLOB_RESERVED_SIZE - 100, false, "Failed to get block template (coinbase_size = " << coinbase_size << ") << coinbase structue: " - << ENDL << obj_to_json_str(b.miner_tx)); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::print_transactions_statistics() const -{ - LOG_ERROR("print_transactions_statistics not implemented yet"); -// CRITICAL_REGION_LOCAL(m_blockchain_lock); -// LOG_PRINT_L0("Started to collect transaction statistics, pleas wait..."); -// size_t total_count = 0; -// size_t coinbase_count = 0; -// size_t total_full_blob = 0; -// size_t total_cropped_blob = 0; -// for(auto tx_entry: m_db_transactions) -// { -// ++total_count; -// if(is_coinbase(tx_entry.second.tx)) -// ++coinbase_count; -// else -// { -// total_full_blob += get_object_blobsize(tx_entry.second.tx); -// transaction tx = tx_entry.second.tx; -// tx.signatures.clear(); -// total_cropped_blob += get_object_blobsize(tx); -// } -// } -// LOG_PRINT_L0("Done" << ENDL -// << "total transactions: " << total_count << ENDL -// << "coinbase transactions: " << coinbase_count << ENDL -// << "avarage size of transaction: " << total_full_blob/(total_count-coinbase_count) << ENDL -// << "avarage size of transaction without ring signatures: " << total_cropped_blob/(total_count-coinbase_count) << ENDL -// ); - return true; -} -void blockchain_storage::reset_db_cache() const -{ - m_db_blocks.clear_cache(); - m_db_blocks_index.clear_cache(); - m_db_transactions.clear_cache(); - m_db_spent_keys.clear_cache(); - m_db_solo_options.clear_cache(); - m_db_multisig_outs.clear_cache(); - m_db_aliases.clear_cache(); - m_db_addr_to_alias.clear_cache(); - -} -//------------------------------------------------------------------ -void blockchain_storage::clear_altblocks() -{ - CRITICAL_REGION_LOCAL(m_alternative_chains_lock); - m_alternative_chains.clear(); - m_alternative_chains_txs.clear(); - m_altblocks_keyimages.clear(); -} -//------------------------------------------------------------------ -bool blockchain_storage::complete_timestamps_vector(uint64_t start_top_height, std::vector& timestamps) -{ - - if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) - return true; - - CRITICAL_REGION_LOCAL(m_read_lock); - size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size(); - CHECK_AND_ASSERT_MES(start_top_height < m_db_blocks.size(), false, "internal error: passed start_height = " << start_top_height << " not less then m_blocks.size()=" << m_db_blocks.size()); - size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements:0; - do - { - timestamps.push_back(m_db_blocks[start_top_height]->bl.timestamp); - if(start_top_height == 0) - break; - --start_top_height; - }while(start_top_height != stop_offset); - return true; -} -//------------------------------------------------------------------ -std::string blockchain_storage::print_alt_chain(alt_chain_type alt_chain) -{ - std::stringstream ss; - for (auto it = alt_chain.begin(); it != alt_chain.end(); it++) - { - ss << "[" << (*it)->second.height << "] " << (*it)->first << "(cumul_dif: " << (*it)->second.cumulative_diff_adjusted << "), parent_id: " << (*it)->second.bl.prev_id << ENDL; - } - return ss.str(); -} -//------------------------------------------------------------------ -bool blockchain_storage::append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::unordered_set& alt_block_keyimages) -{ - for (auto& ki : alt_block_keyimages) - m_altblocks_keyimages[ki].push_back(block_id); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& id) -{ - auto it = m_altblocks_keyimages.find(ki); - CHECK_AND_ASSERT_MES(it != m_altblocks_keyimages.end(), false, "internal error: keyimage " << ki - << "from altblock " << id << "not found in m_altblocks_keyimages in purge_keyimage_from_big_heap"); - - //TODO: at the moment here is simple liner algo since having the same txs in few altblocks is rare case - std::list& ki_blocks_ids = it->second; - bool found = false; - for (auto it_in_blocks = ki_blocks_ids.begin(); it_in_blocks != ki_blocks_ids.end(); it_in_blocks++) - { - if (*it_in_blocks == id) - { - //found, erase this entry - ki_blocks_ids.erase(it_in_blocks); - found = true; - break; - } - } - CHECK_AND_ASSERT_MES(found, false, "internal error: keyimage " << ki - << "from altblock " << id << "not found in m_altblocks_keyimages in purge_keyimage_from_big_heap"); - if (!ki_blocks_ids.size()) - m_altblocks_keyimages.erase(it); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::purge_altblock_keyimages_from_big_heap(const block& b, const crypto::hash& id) -{ - if (is_pos_block(b)) - { - CHECK_AND_ASSERT_MES(b.miner_tx.vin.size()>=2, false, "paranoid check failed"); - CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key), false, "paranoid type check failed"); - purge_keyimage_from_big_heap(boost::get(b.miner_tx.vin[1]).k_image, id); - } - for (auto tx_id : b.tx_hashes) - { - std::shared_ptr tx_ptr; - if (!get_transaction_from_pool_or_db(tx_id, tx_ptr)) - { - continue; - } - transaction& tx = *tx_ptr; - for (size_t n = 0; n < tx.vin.size(); ++n) - { - if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc)) - { - purge_keyimage_from_big_heap(get_to_key_input_from_txin_v(tx.vin[n]).k_image, id); - } - } - } - return true; -} - -//------------------------------------------------------------------ -bool blockchain_storage::handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc) -{ - uint64_t coinbase_height = get_block_height(b); - if (m_checkpoints.is_height_passed_zone(coinbase_height, get_top_block_height())) - { - LOG_PRINT_RED_L0("Block with id: " << id << "[" << coinbase_height << "]" << ENDL << " for alternative chain, is under checkpoint zone, declined"); - bvc.m_verification_failed = true; - return false; - } - - TRY_ENTRY(); - - - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - - //block is not related with head of main chain - //first of all - look in alternative chains container - - auto ptr_main_prev = m_db_blocks_index.find(b.prev_id); - auto it_prev = m_alternative_chains.find(b.prev_id); - if (it_prev != m_alternative_chains.end() || ptr_main_prev != m_db_blocks_index.end()) - { - alt_chain_type alt_chain; - { - //we have new block in alternative chain - //build alternative subchain, front -> mainchain, back -> alternative head - alt_chain_container::iterator alt_it = it_prev; //m_alternative_chains.find() - std::vector timestamps; - std::list temp_container; - while (alt_it != m_alternative_chains.end()) - { - temp_container.push_front(alt_it); - timestamps.push_back(alt_it->second.bl.timestamp); - alt_it = m_alternative_chains.find(alt_it->second.bl.prev_id); - } - //TODO: refactoring needed: vector push_front is dramatically ineffective - alt_chain.resize(temp_container.size()); - auto it_vec = alt_chain.begin(); - for (auto it = temp_container.begin(); it != temp_container.end();it++, it_vec++) - { - *it_vec = *it; - } - - - if (alt_chain.size()) - { - //make sure that it has right connection to main chain - CHECK_AND_ASSERT_MES_CUSTOM(m_db_blocks.size() >= alt_chain.front()->second.height, false, bvc.m_verification_failed = true, "main blockchain wrong height: m_db_blocks.size() = " << m_db_blocks.size() - << " and alt_chain.front()->second.height = " << alt_chain.front()->second.height - << " for block " << id << ", prev_id=" << b.prev_id << ENDL - << " alt chain: " << ENDL << print_alt_chain(alt_chain) << ENDL - << " main chain: " << ENDL << get_blockchain_string(m_db_blocks.size() - 10, CURRENCY_MAX_BLOCK_NUMBER) - ); - - crypto::hash h = null_hash; - get_block_hash(m_db_blocks[alt_chain.front()->second.height - 1]->bl, h); - CHECK_AND_ASSERT_MES_CUSTOM(h == alt_chain.front()->second.bl.prev_id, false, bvc.m_verification_failed = true, "alternative chain have wrong connection to main chain"); - complete_timestamps_vector(alt_chain.front()->second.height - 1, timestamps); - } - else - { - CHECK_AND_ASSERT_MES_CUSTOM(ptr_main_prev != m_db_blocks_index.end(), false, bvc.m_verification_failed = true, "internal error: broken imperative condition it_main_prev != m_blocks_index.end()"); - complete_timestamps_vector(*ptr_main_prev, timestamps); - } - //check timestamp correct - if (!check_block_timestamp(std::move(timestamps), b)) - { - LOG_PRINT_RED_L0("Block with id: " << id - << ENDL << " for alternative chain, have invalid timestamp: " << b.timestamp); - //add_block_as_invalid(b, id);//do not add blocks to invalid storage before proof of work check was passed - bvc.m_verification_failed = true; - return false; - } - } - - alt_block_extended_info abei = AUTO_VAL_INIT(abei); - abei.bl = b; - abei.onboard_transactions.swap(bvc.m_onboard_transactions); - //for altblocks we should be sure that all transactions kept in onboard_transactions - for (auto& h: abei.bl.tx_hashes) - { - if (abei.onboard_transactions.count(h) == 0) - { - //need to take if from pool - transaction tx = AUTO_VAL_INIT(tx); - bool r = m_tx_pool.get_transaction(h, tx); - if (!r) - { - //transaction could be in main chain - auto tx_ptr = m_db_transactions.find(h); - if (!tx_ptr) - { - LOG_ERROR("Transaction " << h << " for altblock " << get_block_hash(abei.bl) << " not found"); - } - else - { - abei.onboard_transactions[h] = tx_ptr->tx; - } - } - else - { - abei.onboard_transactions[h] = tx; - } - } - } - - abei.timestamp = m_core_runtime_config.get_core_time(); - abei.height = alt_chain.size() ? it_prev->second.height + 1 : *ptr_main_prev + 1; - CHECK_AND_ASSERT_MES_CUSTOM(coinbase_height == abei.height, false, bvc.m_verification_failed = true, "block coinbase height doesn't match with altchain height, declined"); - uint64_t connection_height = alt_chain.size() ? alt_chain.front()->second.height:abei.height; - CHECK_AND_ASSERT_MES_CUSTOM(connection_height, false, bvc.m_verification_failed = true, "INTERNAL ERROR: Wrong connection_height==0 in handle_alternative_block"); - - if (!m_checkpoints.is_in_checkpoint_zone(abei.height)) - { - m_is_in_checkpoint_zone = false; - } - else - { - m_is_in_checkpoint_zone = true; - if (!m_checkpoints.check_block(abei.height, id)) - { - LOG_ERROR("CHECKPOINT VALIDATION FAILED"); - bvc.m_verification_failed = true; - return false; - } - } - - bool pos_block = is_pos_block(abei.bl); - //check if PoS block allowed on this height - CHECK_AND_ASSERT_MES_CUSTOM(!(pos_block && abei.height < m_core_runtime_config.pos_minimum_heigh), false, bvc.m_verification_failed = true, "PoS block is not allowed on this height"); - - - wide_difficulty_type current_diff = get_next_diff_conditional2(pos_block, alt_chain, connection_height, abei); - - CHECK_AND_ASSERT_MES_CUSTOM(current_diff, false, bvc.m_verification_failed = true, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); - - crypto::hash proof_of_work = null_hash; - uint64_t pos_amount = 0; - wide_difficulty_type pos_diff_final = 0; - if (pos_block) - { - //POS - bool res = validate_pos_block(abei.bl, current_diff, pos_amount, pos_diff_final, abei.stake_hash, id, true, alt_chain, connection_height); - CHECK_AND_ASSERT_MES_CUSTOM(res, false, bvc.m_verification_failed = true, "Failed to validate_pos_block on alternative block, height = " - << abei.height - << ", block id: " << get_block_hash(abei.bl)); - } - else - { - proof_of_work = get_block_longhash(abei.bl); - - if (!check_hash(proof_of_work, current_diff)) - { - LOG_PRINT_RED_L0("Block with id: " << id - << ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work - << ENDL << " expected difficulty: " << current_diff); - bvc.m_verification_failed = true; - return false; - } - // - } - - if (!prevalidate_miner_transaction(b, abei.height, pos_block)) - { - LOG_PRINT_RED_L0("Block with id: " << string_tools::pod_to_hex(id) - << " (as alternative) have wrong miner transaction."); - bvc.m_verification_failed = true; - return false; - } - std::unordered_set alt_block_keyimages; - uint64_t ki_lookup_total = 0; - if (!validate_alt_block_txs(b, id, alt_block_keyimages, abei, alt_chain, connection_height, ki_lookup_total)) - { - LOG_PRINT_RED_L0("Alternative block " << id << " @ " << abei.height << " has invalid transactions. Rejected."); - bvc.m_verification_failed = true; - return false; - } - - abei.difficulty = current_diff; - wide_difficulty_type cumulative_diff_delta = 0; - abei.cumulative_diff_adjusted = alt_chain.size() ? it_prev->second.cumulative_diff_adjusted : m_db_blocks[*ptr_main_prev]->cumulative_diff_adjusted; - - if (pos_block) - cumulative_diff_delta = get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain, abei.height, current_diff, connection_height); - else - cumulative_diff_delta = current_diff; - - size_t sequence_factor = get_current_sequence_factor_for_alt(alt_chain, pos_block, connection_height); - if (abei.height >= m_core_runtime_config.pos_minimum_heigh) - cumulative_diff_delta = correct_difficulty_with_sequence_factor(sequence_factor, cumulative_diff_delta); - - if (abei.height > BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION && abei.height <= m_core_runtime_config.hard_fork_01_starts_after_height && pos_block && sequence_factor > BLOCK_POS_STRICT_SEQUENCE_LIMIT) - { - LOG_PRINT_RED_L0("Alternative block " << id << " @ " << abei.height << " has too big sequence factor: " << sequence_factor << ", rejected"); - bvc.m_verification_failed = true; - return false; - } - - abei.cumulative_diff_adjusted += cumulative_diff_delta; - wide_difficulty_type last_x_cumul_dif_precise_adj = 0; - abei.cumulative_diff_precise = get_last_alt_x_block_cumulative_precise_difficulty(alt_chain, abei.height-1, pos_block, last_x_cumul_dif_precise_adj); - abei.cumulative_diff_precise += current_diff; - ////////////////////////////////////////////////////////////////////////// - - wide_difficulty_type diff_precise_adj = correct_difficulty_with_sequence_factor(sequence_factor, current_diff); - abei.cumulative_diff_precise_adjusted = last_x_cumul_dif_precise_adj + diff_precise_adj; - - ////////////////////////////////////////////////////////////////////////// - -#ifdef _DEBUG - auto i_dres = m_alternative_chains.find(id); - CHECK_AND_ASSERT_MES_CUSTOM(i_dres == m_alternative_chains.end(), false, bvc.m_verification_failed = true, "insertion of new alternative block " << id << " returned as it already exist"); -#endif - auto i_res = m_alternative_chains.insert(alt_chain_container::value_type(id, abei)); - CHECK_AND_ASSERT_MES_CUSTOM(i_res.second, false, bvc.m_verification_failed = true, "insertion of new alternative block " << id << " returned as it already exist"); - append_altblock_keyimages_to_big_heap(id, alt_block_keyimages); - add_alt_block_txs_hashs(i_res.first->second.bl); - alt_chain.push_back(i_res.first); - //check if difficulty bigger then in main chain - - bvc.m_height_difference = get_top_block_height() >= abei.height ? get_top_block_height() - abei.height : 0; - - crypto::hash proof = null_hash; - std::stringstream ss_pow_pos_info; - if (pos_block) - { - ss_pow_pos_info << "PoS:\t" << abei.stake_hash << ", stake amount: " << print_money(pos_amount) << ", final_difficulty: " << pos_diff_final; - proof = abei.stake_hash; - } - else - { - ss_pow_pos_info << "PoW:\t" << proof_of_work; - proof = proof_of_work; - } - - LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << abei.height << (pos_block ? " [PoS] Sq: " : " [PoW] Sq: ") << sequence_factor << ", altchain sz: " << alt_chain.size() << ", split h: " << connection_height - << ENDL << "id:\t" << id - << ENDL << "prev\t" << abei.bl.prev_id - << ENDL << ss_pow_pos_info.str() - << ENDL << "HEIGHT " << abei.height << ", difficulty: " << abei.difficulty << ", cumul_diff_precise: " << abei.cumulative_diff_precise << ", cumul_diff_adj: " << abei.cumulative_diff_adjusted << " (current mainchain cumul_diff_adj: " << m_db_blocks.back()->cumulative_diff_adjusted << ", ki lookup total: " << ki_lookup_total <<")" - , LOG_LEVEL_0); - - if (is_reorganize_required(*m_db_blocks.back(), alt_chain, proof)) - { - auto a = epee::misc_utils::create_scope_leave_handler([&]() { m_is_reorganize_in_process = false; }); - CHECK_AND_ASSERT_THROW_MES(!m_is_reorganize_in_process, "Detected recursive reorganzie"); - m_is_reorganize_in_process = true; - //do reorganize! - LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db_blocks.size() - 1 << " with cumulative_diff_adjusted " << m_db_blocks.back()->cumulative_diff_adjusted - << ENDL << " alternative blockchain size: " << alt_chain.size() << " with cumulative_diff_adjusted " << abei.cumulative_diff_adjusted, LOG_LEVEL_0); - bool r = switch_to_alternative_blockchain(alt_chain); - if(r) - bvc.m_added_to_main_chain = true; - else - bvc.m_verification_failed = true; - return r; - } - bvc.m_added_to_altchain = true; - - //protect ourself from altchains container flood - if (m_alternative_chains.size() > m_core_runtime_config.max_alt_blocks) - prune_aged_alt_blocks(); - - return true; - }else - { - //block orphaned - bvc.m_marked_as_orphaned = true; - - if (m_invalid_blocks.count(id) != 0) - { - LOG_PRINT_RED_L0("Block recognized as blacklisted and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height); - } - else if (m_invalid_blocks.count(b.prev_id) != 0) - { - LOG_PRINT_RED_L0("Block recognized as orphaned (parent " << b.prev_id << " is in blacklist) and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height); - } - else - { - LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id << "," << ENDL << "parent id = " << b.prev_id << ENDL << "height = " << coinbase_height); - } - } - - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - return true; - CATCH_ENTRY_CUSTOM("blockchain_storage::handle_alternative_block", bvc.m_verification_failed = true, false); -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_x_difficulty_after_height(uint64_t height, bool is_pos) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_THROW_MES(height < m_db_blocks.size(), "Internal error: condition failed: height (" << height << ") < m_db_blocks.size() " << m_db_blocks.size()); - wide_difficulty_type diff = 0; - for (uint64_t i = height + 1; i != m_db_blocks.size(); i++) - { - auto bei_ptr = m_db_blocks[i]; - if (is_pos_block(bei_ptr->bl) == is_pos) - { - diff = bei_ptr->difficulty; - break; - } - } - if (diff == 0) - { - //never met x type of block, that meanst that difficulty is current - diff = get_cached_next_difficulty(is_pos); - } - return diff; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt) -{ - //alt_chain - back is latest(top), first - connection with main chain - const block_extended_info& alt_chain_bei = alt_chain.back()->second; - const block_extended_info& connection_point = alt_chain.front()->second; - - if (connection_point.height <= m_core_runtime_config.hard_fork_01_starts_after_height) - { - //use pre-hard fork, old-style comparing - if (main_chain_bei.cumulative_diff_adjusted < alt_chain_bei.cumulative_diff_adjusted) - return true; - else if (main_chain_bei.cumulative_diff_adjusted > alt_chain_bei.cumulative_diff_adjusted) - return false; - else // main_chain_bei.cumulative_diff_adjusted == alt_chain_bei.cumulative_diff_adjusted - { - if (!is_pos_block(main_chain_bei.bl)) - return false; // do not reorganize on the same cummul diff if it's a PoW block - - //in case of simultaneous PoS blocks are happened on the same height (quite common for PoS) - //we also try to weight them to guarantee consensus in network - if (std::memcmp(&main_chain_bei.stake_hash, &proof_alt, sizeof(main_chain_bei.stake_hash)) >= 0) - return false; - - LOG_PRINT_L2("[is_reorganize_required]:TRUE, \"by order of memcmp\" main_stake_hash:" << &main_chain_bei.stake_hash << ", alt_stake_hash" << proof_alt); - return true; - } - } - else if (alt_chain_bei.height > m_core_runtime_config.hard_fork_01_starts_after_height) - { - //new rules, applied after HARD_FORK_1 - //to learn this algo please read https://github.com/hyle-team/docs/blob/master/zano/PoS_Analysis_and_improvements_proposal.pdf - - wide_difficulty_type difficulty_pos_at_split_point = get_x_difficulty_after_height(connection_point.height - 1, true); - wide_difficulty_type difficulty_pow_at_split_point = get_x_difficulty_after_height(connection_point.height - 1, false); - - difficulties main_cumul_diff = AUTO_VAL_INIT(main_cumul_diff); - difficulties alt_cumul_diff = AUTO_VAL_INIT(alt_cumul_diff); - //we use get_last_alt_x_block_cumulative_precise_adj_difficulty for getting both alt chain and main chain diff of given block types - - wide_difficulty_type alt_pos_diff_end = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain, alt_chain_bei.height, true); - wide_difficulty_type alt_pos_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height-1, true); - alt_cumul_diff.pos_diff = alt_pos_diff_end - alt_pos_diff_begin; - - wide_difficulty_type alt_pow_diff_end = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain, alt_chain_bei.height, false); - wide_difficulty_type alt_pow_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height - 1, false); - alt_cumul_diff.pow_diff = alt_pow_diff_end - alt_pow_diff_begin; - - wide_difficulty_type main_pos_diff_end = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), m_db_blocks.size()-1, true); - wide_difficulty_type main_pos_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height - 1, true); - main_cumul_diff.pos_diff = main_pos_diff_end - main_pos_diff_begin; - - wide_difficulty_type main_pow_diff_end = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), m_db_blocks.size() - 1, false); - wide_difficulty_type main_pow_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height - 1, false); - main_cumul_diff.pow_diff = main_pow_diff_end - main_pow_diff_begin; - - //TODO: measurement of precise cumulative difficult - boost::multiprecision::uint1024_t alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff); - boost::multiprecision::uint1024_t main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff); - LOG_PRINT_L1("[FORK_CHOICE]: " << ENDL - << "difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL - << "difficulty_pos_at_split_point:" << difficulty_pos_at_split_point << ENDL - << "alt_cumul_diff.pow_diff:" << alt_cumul_diff.pow_diff << ENDL - << "alt_cumul_diff.pos_diff:" << alt_cumul_diff.pos_diff << ENDL - << "main_cumul_diff.pow_diff:" << main_cumul_diff.pow_diff << ENDL - << "main_cumul_diff.pos_diff:" << main_cumul_diff.pos_diff << ENDL - << "alt:" << alt << ENDL - << "main:" << main << ENDL - ); - if (main < alt) - return true; - else if (main > alt) - return false; - else - { - if (!is_pos_block(main_chain_bei.bl)) - return false; // do not reorganize on the same cummul diff if it's a PoW block - - //in case of simultaneous PoS blocks are happened on the same height (quite common for PoS) - //we also try to weight them to guarantee consensus in network - if (std::memcmp(&main_chain_bei.stake_hash, &proof_alt, sizeof(main_chain_bei.stake_hash)) >= 0) - return false; - - LOG_PRINT_L1("[is_reorganize_required]:TRUE, \"by order of memcmp\" main_stake_hash:" << &main_chain_bei.stake_hash << ", alt_stake_hash" << proof_alt); - return true; - } - } - else - { - ASSERT_MES_AND_THROW("Unknown version of block"); - } -} - -//------------------------------------------------------------------ -bool blockchain_storage::pre_validate_relayed_block(block& bl, block_verification_context& bvc, const crypto::hash& id)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (!(bl.prev_id == get_top_block_id())) - { - bvc.m_added_to_main_chain = false; - bvc.m_verification_failed = false; - return true; - } - //check proof of work - bool is_pos_bl = is_pos_block(bl); - wide_difficulty_type current_diffic = get_next_diff_conditional(is_pos_bl); - CHECK_AND_ASSERT_MES_CUSTOM(current_diffic, false, bvc.m_verification_failed = true, "!!!!!!!!! difficulty overhead !!!!!!!!!"); - crypto::hash proof_hash = AUTO_VAL_INIT(proof_hash); - if (is_pos_bl) - { - wide_difficulty_type this_coin_diff = 0; - uint64_t amount = 0; - bool r = validate_pos_block(bl, current_diffic, amount, this_coin_diff, proof_hash, id, false); - CHECK_AND_ASSERT_MES_CUSTOM(r, false, bvc.m_verification_failed = true, "validate_pos_block failed!!"); - bvc.m_added_to_main_chain = true; - } - else - { - proof_hash = get_block_longhash(bl); //get_block_longhash(bl); - - if (!check_hash(proof_hash, current_diffic)) - { - LOG_PRINT_L0("Block with id: " << id << ENDL - << " : " << proof_hash << ENDL - << "unexpected difficulty: " << current_diffic); - bvc.m_verification_failed = true; - bvc.m_added_to_main_chain = true; - return false; - } - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(start_offset >= m_db_blocks.size()) - return false; - for(size_t i = start_offset; i < start_offset + count && i < m_db_blocks.size();i++) - { - blocks.push_back(m_db_blocks[i]->bl); - std::list missed_ids; - get_transactions(m_db_blocks[i]->bl.tx_hashes, txs, missed_ids); - CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "have missed transactions in own block in main blockchain"); - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_tx_rpc_details(const crypto::hash& h, tx_rpc_extended_info& tei, uint64_t timestamp, bool is_short) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto tx_ptr = m_db_transactions.get(h); - if (!tx_ptr) - { - tei.keeper_block = -1; // tx is not confirmed yet, probably it's in the pool - return false; - } - - - if (tx_ptr && !timestamp) - { - timestamp = get_block_datetime(m_db_blocks[tx_ptr->m_keeper_block_height]->bl); - } - tei.keeper_block = static_cast(tx_ptr->m_keeper_block_height); - fill_tx_rpc_details(tei, tx_ptr->tx, &(*tx_ptr), h, timestamp, is_short); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::search_by_id(const crypto::hash& id, std::list& res) const -{ - auto block_ptr = m_db_blocks_index.get(id); - if (block_ptr) - { - res.push_back("block"); - } - - auto tx_ptr = m_db_transactions.get(id); - if (tx_ptr) - { - res.push_back("tx"); - } - - auto ki_ptr = m_db_spent_keys.get( *reinterpret_cast(&id)); - if (ki_ptr) - { - res.push_back("key_image"); - } - - auto ms_ptr = m_db_multisig_outs.get(id); - if (ms_ptr) - { - res.push_back(std::string("multisig_id:") + epee::string_tools::pod_to_hex(ms_ptr->tx_id) + ":" + std::to_string(ms_ptr->out_no)); - } - - if (m_alternative_chains.end() != m_alternative_chains.find(id)) - { - res.push_back("alt_block"); - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_global_index_details(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::response & resp) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - try - { - auto out_ptr = m_db_outputs.get_subitem(req.amount, req.i); // get_subitem can rise an out_of_range exception - if (!out_ptr) - return false; - resp.tx_id = out_ptr->tx_id; - resp.out_no = out_ptr->out_no; - return true; - } - catch (std::out_of_range&) - { - return false; - } -} -//------------------------------------------------------------------ -bool blockchain_storage::get_multisig_id_details(const COMMAND_RPC_GET_MULTISIG_INFO::request& req, COMMAND_RPC_GET_MULTISIG_INFO::response & resp) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return get_multisig_id_details(req.ms_id, resp.tx_id, resp.out_no); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_multisig_id_details(const crypto::hash& ms_id, crypto::hash& tx_id, uint64_t& out_no) const -{ - auto out_ptr = m_db_multisig_outs.get(ms_id); - if (!out_ptr) - return false; - - tx_id = out_ptr->tx_id; - out_no = out_ptr->out_no; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_main_block_rpc_details(uint64_t i, block_rpc_extended_info& bei) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto core_bei_ptr = m_db_blocks[i]; - crypto::hash id = get_block_hash(core_bei_ptr->bl); - bei.is_orphan = false; - bei.total_fee = 0; - bei.total_txs_size = 0; - if (true/*!ignore_transactions*/) - { - crypto::hash coinbase_id = get_transaction_hash(core_bei_ptr->bl.miner_tx); - //load transactions details - bei.transactions_details.push_back(tx_rpc_extended_info()); - get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true); - for (auto& h : core_bei_ptr->bl.tx_hashes) - { - bei.transactions_details.push_back(tx_rpc_extended_info()); - get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true); - bei.total_fee += bei.transactions_details.back().fee; - bei.total_txs_size += bei.transactions_details.back().blob_size; - } - } - fill_block_rpc_details(bei, *core_bei_ptr, id); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_main_block_rpc_details(const crypto::hash& id, block_rpc_extended_info& bei) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto iptr = m_db_blocks_index.get(id); - if (!iptr) - return false; - return get_main_block_rpc_details(*iptr, bei); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_alt_blocks_rpc_details(uint64_t start_offset, uint64_t count, std::vector& blocks) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - - if (start_offset >= m_alternative_chains.size() || count == 0) - return true; // empty result - - if (start_offset + count >= m_alternative_chains.size()) - count = m_alternative_chains.size() - start_offset; // correct count if it's too big - - // collect iterators to all the alt blocks for speedy sorting - std::vector blocks_its; - blocks_its.reserve(m_alternative_chains.size()); - for (alt_chain_container::const_iterator it = m_alternative_chains.begin(); it != m_alternative_chains.end(); ++it) - blocks_its.push_back(it); - - // partially sort blocks by height, so only 0...(start_offset+count-1) first blocks are sorted - std::partial_sort(blocks_its.begin(), blocks_its.begin() + start_offset + count, blocks_its.end(), - [](const alt_chain_container::const_iterator &lhs, const alt_chain_container::const_iterator& rhs) ->bool { - return lhs->second.height < rhs->second.height; - } - ); - - // erase blocks from 0 till start_offset-1 - blocks_its.erase(blocks_its.begin(), blocks_its.begin() + start_offset); - - // erase the tail - blocks_its.erase(blocks_its.begin() + count, blocks_its.end()); - - // populate the result - blocks.reserve(blocks_its.size()); - for(auto it : blocks_its) - { - blocks.push_back(block_rpc_extended_info()); - get_alt_block_rpc_details(it->second, it->first, blocks.back()); - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_alt_block_rpc_details(const crypto::hash& id, block_rpc_extended_info& bei) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - auto it = m_alternative_chains.find(id); - if (it == m_alternative_chains.end()) - return false; - - const block_extended_info& bei_core = it->second; - return get_alt_block_rpc_details(bei_core, id, bei); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_alt_block_rpc_details(const block_extended_info& bei_core, const crypto::hash& id, block_rpc_extended_info& bei) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - - bei.is_orphan = true; - - crypto::hash coinbase_id = get_transaction_hash(bei_core.bl.miner_tx); - //load transactions details - bei.transactions_details.push_back(tx_rpc_extended_info()); - fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_block_datetime(bei_core.bl)); - - bei.total_fee = 0; - for (auto& h : bei_core.bl.tx_hashes) - { - bei.transactions_details.push_back(tx_rpc_extended_info()); - if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(bei_core.bl), true)) - { - //tx not in blockchain, supposed to be in tx pool - m_tx_pool.get_transaction_details(h, bei.transactions_details.back()); - } - bei.total_fee += bei.transactions_details.back().fee; - } - - fill_block_rpc_details(bei, bei_core, id); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_main_blocks_rpc_details(uint64_t start_offset, size_t count, bool ignore_transactions, std::list& blocks) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (start_offset >= m_db_blocks.size()) - return false; - - for (size_t i = start_offset; i < start_offset + count && i < m_db_blocks.size(); i++) - { - blocks.push_back(block_rpc_extended_info()); - block_rpc_extended_info& bei = blocks.back(); - get_main_block_rpc_details(i, bei); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_blocks(uint64_t start_offset, size_t count, std::list& blocks)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(start_offset >= m_db_blocks.size()) - return false; - - for(size_t i = start_offset; i < start_offset + count && i < m_db_blocks.size();i++) - blocks.push_back(m_db_blocks[i]->bl); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - rsp.current_blockchain_height = get_current_blockchain_size(); - std::list blocks; - get_blocks(arg.blocks, blocks, rsp.missed_ids); - - BOOST_FOREACH(const auto& bl, blocks) - { - std::list txs; - get_transactions(bl.tx_hashes, txs, rsp.missed_ids); - - CHECK_AND_ASSERT_MES(!rsp.missed_ids.size(), false, "Host have requested block with missed transactions missed_tx_id.size()=" << rsp.missed_ids.size() - << ENDL << "for block id = " << get_block_hash(bl)); - rsp.blocks.push_back(block_complete_entry()); - block_complete_entry& e = rsp.blocks.back(); - //pack block - e.block = t_serializable_object_to_blob(bl); - //pack transactions - BOOST_FOREACH(transaction& tx, txs) - e.txs.push_back(t_serializable_object_to_blob(tx)); - - } - //get another transactions, if need - std::list txs; - get_transactions(arg.txs, txs, rsp.missed_ids); - //pack aside transactions - BOOST_FOREACH(const auto& tx, txs) - rsp.txs.push_back(t_serializable_object_to_blob(tx)); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_transactions_daily_stat(uint64_t& daily_cnt, uint64_t& daily_volume) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - daily_cnt = daily_volume = 0; - for(size_t i = (m_db_blocks.size() > CURRENCY_BLOCKS_PER_DAY ? m_db_blocks.size() - CURRENCY_BLOCKS_PER_DAY:0 ); i!=m_db_blocks.size(); i++) - { - auto ptr = m_db_blocks[i]; - for(auto& h : ptr->bl.tx_hashes) - { - ++daily_cnt; - auto tx_ptr = m_db_transactions.find(h); - CHECK_AND_ASSERT_MES(tx_ptr, false, "Wrong transaction hash " << h << " in block on height " << i); - uint64_t am = 0; - bool r = get_inputs_money_amount(tx_ptr->tx, am); - CHECK_AND_ASSERT_MES(r, false, "failed to get_inputs_money_amount"); - daily_volume += am; - } - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::check_keyimages(const std::list& images, std::list& images_stat) const -{ - //true - unspent, false - spent - CRITICAL_REGION_LOCAL(m_read_lock); - for (auto& ki : images) - { - auto ki_ptr = m_db_spent_keys.get(ki); - if(ki_ptr) - images_stat.push_back(*ki_ptr); - else - images_stat.push_back(0); - } - return true; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_seconds_between_last_n_block(size_t n) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (m_db_blocks.size() <= n) - return 0; - - uint64_t top_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1]->bl); - uint64_t n_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1 - n]->bl); - - return top_block_ts > n_block_ts ? top_block_ts - n_block_ts : 0; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_current_hashrate(size_t aprox_count) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (aprox_count == 0 || m_db_blocks.size() <= aprox_count) - return 0; // incorrect parameters - - uint64_t nearest_front_pow_block_i = m_db_blocks.size() - 1; - while (nearest_front_pow_block_i != 0) - { - if (!is_pos_block(m_db_blocks[nearest_front_pow_block_i]->bl)) - break; - --nearest_front_pow_block_i; - } - - uint64_t nearest_back_pow_block_i = m_db_blocks.size() - aprox_count; - while (nearest_back_pow_block_i != 0) - { - if (!is_pos_block(m_db_blocks[nearest_back_pow_block_i]->bl)) - break; - --nearest_back_pow_block_i; - } - - std::shared_ptr front_blk_ptr = m_db_blocks[nearest_front_pow_block_i]; - std::shared_ptr back_blk_ptr = m_db_blocks[nearest_back_pow_block_i]; - uint64_t front_blk_ts = front_blk_ptr->bl.timestamp; - uint64_t back_blk_ts = back_blk_ptr->bl.timestamp; - - uint64_t ts_delta = front_blk_ts > back_blk_ts ? front_blk_ts - back_blk_ts : DIFFICULTY_POW_TARGET; - - wide_difficulty_type w_hr = (front_blk_ptr->cumulative_diff_precise - back_blk_ptr->cumulative_diff_precise) / ts_delta; - - return w_hr.convert_to(); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_alternative_blocks(std::list& blocks) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - BOOST_FOREACH(const auto& alt_bl, m_alternative_chains) - { - blocks.push_back(alt_bl.second.bl); - } - return true; -} -//------------------------------------------------------------------ -size_t blockchain_storage::get_alternative_blocks_count() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - return m_alternative_chains.size(); -} -//------------------------------------------------------------------ -bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto out_ptr = m_db_outputs.get_subitem(amount, i); - auto tx_ptr = m_db_transactions.find(out_ptr->tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "internal error: transaction with id " << out_ptr->tx_id << ENDL << - ", used in mounts global index for amount=" << amount << ": i=" << i << "not found in transactions index"); - CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_ptr->out_no, false, "internal error: in global outs index, transaction out index=" - << out_ptr->out_no << " more than transaction outputs = " << tx_ptr->tx.vout.size() << ", for tx id = " << out_ptr->tx_id); - - const transaction& tx = tx_ptr->tx; - if (tx.vout[out_ptr->out_no].target.type() == typeid(txout_htlc)) - { - //silently return false, it's ok - return false; - } - CHECK_AND_ASSERT_MES(tx.vout[out_ptr->out_no].target.type() == typeid(txout_to_key), false, "unknown tx out type"); - const txout_to_key& otk = boost::get(tx.vout[out_ptr->out_no].target); - - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() == tx.vout.size(), false, "internal error"); - - //do not use outputs that obviously spent for mixins - if (tx_ptr->m_spent_flags[out_ptr->out_no]) - return false; - - // do not use burned coins - if (otk.key == null_pkey) - return false; - - //check if transaction is unlocked - if (!is_tx_spendtime_unlocked(get_tx_unlock_time(tx, out_ptr->out_no))) - return false; - - //use appropriate mix_attr out - uint8_t mix_attr = otk.mix_attr; - - if(mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - return false; //COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS call means that ring signature will have more than one entry. - else if(use_only_forced_to_mix && mix_attr == CURRENCY_TO_KEY_OUT_RELAXED) - return false; //relaxed not allowed - else if(mix_attr != CURRENCY_TO_KEY_OUT_RELAXED && mix_attr > mix_count) - return false;//mix_attr set to specific minimum, and mix_count is less then desired count - - - COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); - oen.global_amount_index = i; - oen.out_key = otk.key; - return true; -} -//------------------------------------------------------------------ -size_t blockchain_storage::find_end_of_allowed_index(uint64_t amount) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint64_t sz = m_db_outputs.get_item_size(amount); - - if (!sz) - return 0; - uint64_t i = sz; - do - { - --i; - auto out_ptr = m_db_outputs.get_subitem(amount, i); - auto tx_ptr = m_db_transactions.find(out_ptr->tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, 0, "internal error: failed to find transaction from outputs index with tx_id=" << out_ptr->tx_id); - if (tx_ptr->m_keeper_block_height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW <= get_current_blockchain_size()) - return i+1; - } while (i != 0); - return 0; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - BOOST_FOREACH(uint64_t amount, req.amounts) - { - COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount()); - result_outs.amount = amount; - uint64_t outs_container_size = m_db_outputs.get_item_size(amount); - if (!outs_container_size) - { - LOG_ERROR("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: not outs for amount " << amount << ", wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist"); - continue;//actually this is strange situation, wallet should use some real outs when it lookup for some mix, so, at least one out for this amount should exist - } - //it is not good idea to use top fresh outs, because it increases possibility of transaction canceling on split - //lets find upper bound of not fresh outs - size_t up_index_limit = find_end_of_allowed_index(amount); - CHECK_AND_ASSERT_MES(up_index_limit <= outs_container_size, false, "internal error: find_end_of_allowed_index returned wrong index=" << up_index_limit << ", with amount_outs.size = " << outs_container_size); - if (up_index_limit >= req.outs_count) - { - std::set used; - size_t try_count = 0; - for(uint64_t j = 0; j != req.outs_count && try_count < up_index_limit;) - { - size_t i = crypto::rand()%up_index_limit; - if(used.count(i)) - continue; - bool added = add_out_to_get_random_outs(result_outs, amount, i, req.outs_count, req.use_forced_mix_outs); - used.insert(i); - if(added) - ++j; - ++try_count; - } - if (result_outs.outs.size() < req.outs_count) - { - LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << result_outs.outs.size() << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total"); - } - }else - { - size_t added = 0; - for (size_t i = 0; i != up_index_limit; i++) - added += add_out_to_get_random_outs(result_outs, amount, i, req.outs_count, req.use_forced_mix_outs) ? 1 : 0; - LOG_PRINT_RED_L0("Not enough inputs for amount " << print_money_brief(amount) << ", needed " << req.outs_count << ", added " << added << " good outs from " << up_index_limit << " unlocked of " << outs_container_size << " total - respond with all good outs"); - } - } - return true; -} -//------------------------------------------------------------------ -boost::multiprecision::uint128_t blockchain_storage::total_coins() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (!m_db_blocks.size()) - return 0; - - return m_db_blocks.back()->already_generated_coins; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_pos_allowed() const -{ - return get_top_block_height() >= m_core_runtime_config.pos_minimum_heigh; -} -//------------------------------------------------------------------ -bool blockchain_storage::update_spent_tx_flags_for_input(uint64_t amount, const txout_ref_v& o, bool spent) -{ - if (o.type() == typeid(ref_by_id)) - return update_spent_tx_flags_for_input(boost::get(o).tx_id, boost::get(o).n, spent); - else if (o.type() == typeid(uint64_t)) - return update_spent_tx_flags_for_input(amount, boost::get(o), spent); - - LOG_ERROR("Unknown txout_v type"); - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::update_spent_tx_flags_for_input(uint64_t amount, uint64_t global_index, bool spent) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint64_t outs_count = m_db_outputs.get_item_size(amount); - CHECK_AND_ASSERT_MES(outs_count, false, "Amount " << amount << " have not found during update_spent_tx_flags_for_input()"); - CHECK_AND_ASSERT_MES(global_index < outs_count, false, "Global index" << global_index << " for amount " << amount << " bigger value than amount's vector size()=" << outs_count); - auto out_ptr = m_db_outputs.get_subitem(amount, global_index); - return update_spent_tx_flags_for_input(out_ptr->tx_id, out_ptr->out_no, spent); -} -//------------------------------------------------------------------ -bool blockchain_storage::update_spent_tx_flags_for_input(const crypto::hash& tx_id, size_t n, bool spent) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto tx_ptr = m_db_transactions.find(tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "Can't find transaction id: " << tx_id); - transaction_chain_entry tce_local = *tx_ptr; - - CHECK_AND_ASSERT_MES(n < tce_local.m_spent_flags.size(), false, "Wrong input offset: " << n << " in transaction id: " << tx_id); - - tce_local.m_spent_flags[n] = spent; - m_db_transactions.set(tx_id, tce_local); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::update_spent_tx_flags_for_input(const crypto::hash& multisig_id, uint64_t spent_height) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto ms_ptr = m_db_multisig_outs.find(multisig_id); - CHECK_AND_ASSERT_MES(ms_ptr, false, "unable to find multisig_id " << multisig_id); - - // update spent height at ms container - ms_output_entry msoe_local = *ms_ptr; - if (msoe_local.spent_height != 0 && spent_height != 0) - { - LOG_PRINT_YELLOW(LOCATION_SS << ": WARNING: ms out " << multisig_id << " was already marked as SPENT at height " << msoe_local.spent_height << ", new spent_height: " << spent_height , LOG_LEVEL_0); - } - msoe_local.spent_height = spent_height; - m_db_multisig_outs.set(multisig_id, msoe_local); - - return update_spent_tx_flags_for_input(ms_ptr->tx_id, ms_ptr->out_no, spent_height != 0); -} -//------------------------------------------------------------------ -bool blockchain_storage::has_multisig_output(const crypto::hash& multisig_id) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return static_cast(m_db_multisig_outs.find(multisig_id)); -} -//------------------------------------------------------------------ -bool blockchain_storage::is_multisig_output_spent(const crypto::hash& multisig_id) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - auto multisig_ptr = m_db_multisig_outs.find(multisig_id); - if (!multisig_ptr) - return false; // there's no such output - treat as not spent - - const crypto::hash& source_tx_id = multisig_ptr->tx_id; - size_t ms_out_index = multisig_ptr->out_no; // index of multisig output in source tx - - auto source_tx_ptr = m_db_transactions.find(source_tx_id); - CHECK_AND_ASSERT_MES(source_tx_ptr, true, "Internal error: source tx not found for ms out " << multisig_id << ", ms out is treated as spent for safety"); - CHECK_AND_ASSERT_MES(ms_out_index < source_tx_ptr->m_spent_flags.size(), true, "Internal error: ms out " << multisig_id << " has incorrect index " << ms_out_index << " in source tx " << source_tx_id << ", ms out is treated as spent for safety"); - - return source_tx_ptr->m_spent_flags[ms_out_index]; -} -//------------------------------------------------------------------ -bool blockchain_storage::find_blockchain_supplement(const std::list& qblock_ids, uint64_t& starter_offset)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - if(!qblock_ids.size() /*|| !req.m_total_height*/) - { - LOG_ERROR("Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection"); - return false; - } - //check genesis match - if(qblock_ids.back() != get_block_hash(m_db_blocks[0]->bl)) - { - LOG_ERROR("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block missmatch: " << ENDL << "id: " - << string_tools::pod_to_hex(qblock_ids.back()) << ", " << ENDL << "expected: " << get_block_hash(m_db_blocks[0]->bl) - << "," << ENDL << " dropping connection"); - return false; - } - - /* Figure out what blocks we should request to get state_normal */ - for(auto& bl: qblock_ids) - { - auto block_index_ptr = m_db_blocks_index.find(bl); - if(block_index_ptr) - { - //we start to put block ids INCLUDING last known id, just to make other side be sure - starter_offset = *block_index_ptr; - return true; - } - } - - LOG_ERROR("Internal error handling connection, can't find split point"); - return false; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::block_difficulty(size_t i) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(i < m_db_blocks.size(), false, "wrong block index i = " << i << " at blockchain_storage::block_difficulty()"); - return m_db_blocks[i]->difficulty; -} -//------------------------------------------------------------------ -bool blockchain_storage::forecast_difficulty(std::vector> &out_height_2_diff_vector, bool pos) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - std::vector timestamps; - std::vector cumulative_difficulties; - - uint64_t blocks_size = m_db_blocks.size(); - size_t count = 0; - - uint64_t max_block_height_for_this_type = 0; - uint64_t min_block_height_for_this_type = UINT64_MAX; - wide_difficulty_type last_block_diff_for_this_type = 0; - - for (uint64_t cur_ind = blocks_size - 1; cur_ind != 0 && count < DIFFICULTY_WINDOW; cur_ind--) - { - auto beiptr = m_db_blocks[cur_ind]; - bool is_pos_bl = is_pos_block(beiptr->bl); - if (pos != is_pos_bl) - continue; - - if (max_block_height_for_this_type < beiptr->height) - max_block_height_for_this_type = beiptr->height; - if (min_block_height_for_this_type > beiptr->height) - min_block_height_for_this_type = beiptr->height; - if (last_block_diff_for_this_type == 0) - last_block_diff_for_this_type = beiptr->difficulty; - - timestamps.push_back(beiptr->bl.timestamp); - cumulative_difficulties.push_back(beiptr->cumulative_diff_precise); - ++count; - } - - if (count != DIFFICULTY_WINDOW) - return false; - - const uint64_t target_seconds = pos ? DIFFICULTY_POS_TARGET : DIFFICULTY_POW_TARGET; - const uint64_t avg_interval = std::max(static_cast(1), (max_block_height_for_this_type - min_block_height_for_this_type) / count); - uint64_t height = max_block_height_for_this_type; - out_height_2_diff_vector.clear(); - out_height_2_diff_vector.push_back(std::make_pair(height, last_block_diff_for_this_type)); // the first element corresponds to the last block of this type - for (size_t i = 0; i < DIFFICULTY_CUT; ++i) - { - wide_difficulty_type diff = next_difficulty_1(timestamps, cumulative_difficulties, target_seconds); - height += avg_interval; - out_height_2_diff_vector.push_back(std::make_pair(height, diff)); - - timestamps.pop_back(); // keep sorted in descending order - timestamps.insert(timestamps.begin(), timestamps.front() + target_seconds); // increment time so it won't be affected by sorting in next_difficulty - - cumulative_difficulties.pop_back(); - cumulative_difficulties.insert(cumulative_difficulties.begin(), 0); // does not matter - } - - return true; -} -//------------------------------------------------------------------ -size_t blockchain_storage::get_current_sequence_factor(bool pos) const -{ - size_t n = 0; - CRITICAL_REGION_LOCAL(m_read_lock); - uint64_t sz = m_db_blocks.size(); - if (!sz) - return n; - - for (uint64_t i = sz - 1; i != 0; --i, n++) - { - if (pos != is_pos_block(m_db_blocks[i]->bl)) - break; - } - return n; -} -//------------------------------------------------------------------ -size_t blockchain_storage::get_current_sequence_factor_for_alt(alt_chain_type& alt_chain, bool pos, uint64_t connection_height) const -{ - size_t n = 0; - for (auto it = alt_chain.rbegin(); it != alt_chain.rend(); it++, n++) - { - if (pos != is_pos_block((*it)->second.bl)) - return n; - } - - CRITICAL_REGION_LOCAL(m_read_lock); - for (uint64_t h = connection_height - 1; h != 0; --h, n++) - { - if (pos != is_pos_block(m_db_blocks[h]->bl)) - { - return n; - } - } - return n; -} -//------------------------------------------------------------------ -std::string blockchain_storage::get_blockchain_string(uint64_t start_index, uint64_t end_index) const -{ - std::stringstream ss; - CRITICAL_REGION_LOCAL(m_read_lock); - if (start_index >= m_db_blocks.size()) - { - LOG_PRINT_L0("Wrong starter index set: " << start_index << ", expected max index " << m_db_blocks.size() - 1); - return ss.str(); - } - - for (size_t i = start_index; i != m_db_blocks.size() && i != end_index; i++) - { - ss << (is_pos_block(m_db_blocks[i]->bl) ? "[PoS]" : "[PoW]") << "h: " << i << ", timestamp: " << m_db_blocks[i]->bl.timestamp << "(" << epee::misc_utils::get_time_str_v2(m_db_blocks[i]->bl.timestamp) << ")" - << ", cumul_diff_adj: " << m_db_blocks[i]->cumulative_diff_adjusted - << ", cumul_diff_pcs: " << m_db_blocks[i]->cumulative_diff_precise - << ", cumul_size: " << m_db_blocks[i]->block_cumulative_size - << ", id: " << get_block_hash(m_db_blocks[i]->bl) - << ", difficulty: " << block_difficulty(i) << ", nonce " << m_db_blocks[i]->bl.nonce << ", tx_count " << m_db_blocks[i]->bl.tx_hashes.size() << ENDL; - } - return ss.str(); -} -//------------------------------------------------------------------ -void blockchain_storage::print_blockchain(uint64_t start_index, uint64_t end_index) const -{ - //LOG_ERROR("NOT IMPLEMENTED YET"); - - LOG_PRINT_L1("Current blockchain:" << ENDL << get_blockchain_string(start_index, end_index)); - LOG_PRINT_L0("Blockchain printed with log level 1"); -} - -void blockchain_storage::print_blockchain_with_tx(uint64_t start_index, uint64_t end_index) const -{ - boost::filesystem::ofstream ss; - ss.exceptions(/*std::ifstream::failbit |*/ std::ifstream::badbit); - ss.open(epee::string_encoding::utf8_to_wstring(log_space::log_singletone::get_default_log_folder() + "/blockchain_with_tx.txt"), - std::ios_base::binary | std::ios_base::out | std::ios_base::trunc); - - - CRITICAL_REGION_LOCAL(m_read_lock); - if (start_index >= m_db_blocks.size()) - { - LOG_PRINT_L0("Wrong starter index set: " << start_index << ", expected max index " << m_db_blocks.size() - 1); - return; - } - - for (size_t i = start_index; i != m_db_blocks.size() && i != end_index; i++) - { - ss << (is_pos_block(m_db_blocks[i]->bl) ? "[PoS]" : "[PoW]") << "h: " << i << ", timestamp: " << m_db_blocks[i]->bl.timestamp << "(" << epee::misc_utils::get_time_str_v2(m_db_blocks[i]->bl.timestamp) << ")" - << ", cumul_diff_adj: " << m_db_blocks[i]->cumulative_diff_adjusted - << ", cumul_diff_pcs: " << m_db_blocks[i]->cumulative_diff_precise - << ", cumul_size: " << m_db_blocks[i]->block_cumulative_size - << ", id: " << get_block_hash(m_db_blocks[i]->bl) - << ", difficulty: " << block_difficulty(i) << ", nonce " << m_db_blocks[i]->bl.nonce << ", tx_count " << m_db_blocks[i]->bl.tx_hashes.size() << ENDL; - - ss << "[miner id]: " << get_transaction_hash(m_db_blocks[i]->bl.miner_tx) << ENDL << currency::obj_to_json_str(m_db_blocks[i]->bl.miner_tx) << ENDL; - - for (size_t j = 0; j != m_db_blocks[i]->bl.tx_hashes.size(); j++) - { - auto tx_it = m_db_transactions.find(m_db_blocks[i]->bl.tx_hashes[j]); - if (tx_it == m_db_transactions.end()) - { - LOG_ERROR("internal error: tx id " << m_db_blocks[i]->bl.tx_hashes[j] << " not found in transactions index"); - continue; - } - ss << "[id]:" << m_db_blocks[i]->bl.tx_hashes[j] << ENDL << currency::obj_to_json_str(tx_it->tx) << ENDL; - } - - } - ss.close(); -} -//------------------------------------------------------------------ -void blockchain_storage::print_blockchain_index() const -{ - LOG_ERROR("NOT IMPLEMENTED YET"); -// std::stringstream ss; -// CRITICAL_REGION_LOCAL(m_blockchain_lock); -// BOOST_FOREACH(const blocks_by_id_index::value_type& v, m_db_blocks_index) -// ss << "id\t\t" << v.first << " height" << v.second << ENDL << ""; -// -// LOG_PRINT_L0("Current blockchain index:" << ENDL << ss.str()); -} -//------------------------------------------------------------------ -void blockchain_storage::print_db_cache_perfeormance_data() const -{ -#define DB_CONTAINER_PERF_DATA_ENTRY(container_name) \ - << #container_name << ": hit_percent: " << m_db_blocks.get_performance_data().hit_percent.get_avg() << "%," \ - << " read_cache: " << container_name.get_performance_data().read_cache_microsec.get_avg() \ - << " read_db: " << container_name.get_performance_data().read_db_microsec.get_avg() \ - << " upd_cache: " << container_name.get_performance_data().update_cache_microsec.get_avg() \ - << " write_cache: " << container_name.get_performance_data().write_to_cache_microsec.get_avg() \ - << " write_db: " << container_name.get_performance_data().write_to_db_microsec.get_avg() \ - << " native_db_set_t: " << container_name.get_performance_data_native().backend_set_t_time.get_avg() \ - << " native_db_set_pod: " << container_name.get_performance_data_native().backend_set_pod_time.get_avg() \ - << " native_db_seriz: " << container_name.get_performance_data_native().set_serialize_t_time.get_avg() - - - LOG_PRINT_L0("DB_PERFORMANCE_DATA: " << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_blocks) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_blocks_index) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_transactions) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_spent_keys) << ENDL - //DB_CONTAINER_PERF_DATA_ENTRY(m_db_outputs) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_multisig_outs) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_solo_options) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_aliases) << ENDL - DB_CONTAINER_PERF_DATA_ENTRY(m_db_addr_to_alias) << ENDL - //DB_CONTAINER_PERF_DATA_ENTRY(m_db_per_block_gindex_incs) << ENDL - //DB_CONTAINER_PERF_DATA_ENTRY(m_tx_fee_median) << ENDL - ); -} -//------------------------------------------------------------------ -void blockchain_storage::get_last_n_x_blocks(uint64_t n, bool pos_blocks, std::list>& blocks) const -{ - uint64_t count = 0; - for (uint64_t i = m_db_blocks.size() - 1; i != 0; --i) - { - auto block_ptr = m_db_blocks[i]; - if (is_pos_block(block_ptr->bl) == pos_blocks) - { - blocks.push_back(block_ptr); - ++count; - if (count >= n) - break; - } - } -} -//------------------------------------------------------------------ -void blockchain_storage::print_last_n_difficulty_numbers(uint64_t n) const -{ - - std::stringstream ss; - std::list> pos_blocks; - std::list> pow_blocks; - - get_last_n_x_blocks(n, true, pos_blocks); - get_last_n_x_blocks(n, false, pow_blocks); - ss << "PoS blocks difficulty:" << ENDL; - for (auto& bl_ptr : pos_blocks) - { - ss << bl_ptr->difficulty << ENDL; - } - - ss << "PoW blocks difficulty:" << ENDL; - for (auto& bl_ptr : pow_blocks) - { - ss << bl_ptr->difficulty << ENDL; - } - LOG_PRINT_L0("LAST BLOCKS:" << ss.str()); -} -//------------------------------------------------------------------ -void blockchain_storage::print_blockchain_outs_stats() const -{ - std::stringstream ss; - CRITICAL_REGION_LOCAL(m_read_lock); - - struct output_stat_t - { - uint64_t total = 0; - uint64_t unspent = 0; - uint64_t mixable = 0; - }; - - std::map outputs_stats; - - const uint64_t subitems_cnt = m_db_outputs.size(); - uint64_t progress = 0; - - auto lambda_handler = [&](uint64_t i, uint64_t amount, uint64_t index, const currency::global_output_entry& output_entry) -> bool - { - uint64_t progress_current = 20 * i / subitems_cnt; - if (progress_current != progress) - { - progress = progress_current; - LOG_PRINT_L0(progress * 5 << "%"); - } - - auto p_tx = m_db_transactions.find(output_entry.tx_id); - if (!p_tx) - { - LOG_ERROR("tx " << output_entry.tx_id << " not found"); - return true; // continue - } - if (output_entry.out_no >= p_tx->m_spent_flags.size()) - { - LOG_ERROR("tx with id " << output_entry.tx_id << " has wrong entry in global index, out_no = " << output_entry.out_no - << ", p_tx->m_spent_flags.size() = " << p_tx->m_spent_flags.size() - << ", p_tx->tx.vin.size() = " << p_tx->tx.vin.size()); - return true; // continue - } - if (p_tx->tx.vout.size() != p_tx->m_spent_flags.size()) - { - LOG_ERROR("Tx with id " << output_entry.tx_id << " has wrong entry in global index, out_no = " << output_entry.out_no - << ", p_tx->tx.vout.size() = " << p_tx->tx.vout.size() - << ", p_tx->m_spent_flags.size() = " << p_tx->m_spent_flags.size()); - return true; // continue - } - - auto& stat = outputs_stats[amount]; - ++stat.total; - - bool spent = p_tx->m_spent_flags[output_entry.out_no]; - if (!spent) - ++stat.unspent; - - if (!spent && p_tx->tx.vout[output_entry.out_no].target.type() == typeid(txout_to_key)) - { - if (boost::get(p_tx->tx.vout[output_entry.out_no].target).mix_attr != CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - ++stat.mixable; - } - return true; - }; - - m_db_outputs.enumerate_subitems(lambda_handler); - - ss << std::right << std::setw(15) << "amount" << std::setw(10) << "total" << std::setw(10) << "unspent" << std::setw(10) << "mixable" << ENDL; - for(auto it = outputs_stats.begin(); it != outputs_stats.end(); ++it) - ss << std::setw(15) << print_money_brief(it->first) << std::setw(10) << it->second.total << std::setw(10) << it->second.unspent << std::setw(10) << it->second.mixable << ENDL; - - LOG_PRINT_L0("OUTS: " << ENDL << ss.str()); -} -//------------------------------------------------------------------ -void blockchain_storage::print_blockchain_outs(const std::string& file) const -{ - LOG_ERROR("NOT IMPLEMENTED YET"); -// std::stringstream ss; -// CRITICAL_REGION_LOCAL(m_blockchain_lock); -// BOOST_FOREACH(const outputs_container::value_type& v, m_db_outputs) -// { -// const std::vector >& vals = v.second; -// if(vals.size()) -// { -// ss << "amount: " << print_money(v.first) << ENDL; -// for (size_t i = 0; i != vals.size(); i++) -// { -// bool used = false; -// auto it_tx = m_db_transactions.find(vals[i].first); -// if (it_tx == m_db_transactions.end()) -// { -// LOG_ERROR("Tx with id not found " << vals[i].first); -// } -// else -// { -// if (vals[i].second >= it_tx->second.m_spent_flags.size()) -// { -// LOG_ERROR("Tx with id " << vals[i].first << " in global index have wrong entry in global index, offset in tx = " << vals[i].second -// << ", it_tx->second.m_spent_flags.size()=" << it_tx->second.m_spent_flags.size() -// << ", it_tx->second.tx.vin.size()=" << it_tx->second.tx.vin.size()); -// } -// used = it_tx->second.m_spent_flags[vals[i].second]; -// } -// -// ss << "\t" << vals[i].first << ": " << vals[i].second << ",used:" << used << ENDL; -// } -// } -// } -// if(file_io_utils::save_string_to_file(file, ss.str())) -// { -// LOG_PRINT_L0("Current outputs index writen to file: " << file); -// }else -// { -// LOG_PRINT_L0("Failed to write current outputs index to file: " << file); -// } -} -//------------------------------------------------------------------ - -//------------------------------------------------------------------ -bool blockchain_storage::find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(!find_blockchain_supplement(qblock_ids, resp.start_height)) - return false; - - resp.total_height = get_current_blockchain_size(); - size_t count = 0; - - block_context_info* pprevinfo = nullptr; - size_t i = 0; - for (i = resp.start_height; i != m_db_blocks.size() && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++) - { - resp.m_block_ids.push_back(block_context_info()); - - if (pprevinfo) - pprevinfo->h = m_db_blocks[i]->bl.prev_id; - resp.m_block_ids.back().cumul_size = m_db_blocks[i]->block_cumulative_size; - pprevinfo = &resp.m_block_ids.back(); - } - if (pprevinfo) - pprevinfo->h = get_block_hash(m_db_blocks[--i]->bl); - - return true; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_blockchain_launch_timestamp()const -{ - if (m_blockchain_launch_timestamp) - return m_blockchain_launch_timestamp; - - if (m_db_blocks.size() > 2) - { - m_blockchain_launch_timestamp = m_db_blocks[1]->bl.timestamp; - } - return m_blockchain_launch_timestamp; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_est_height_from_date(uint64_t date, uint64_t& res_h)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); -#define GET_EST_HEIGHT_FROM_DATE_THRESHOLD 1440 - - res_h = 0; - - if (date < get_blockchain_launch_timestamp()) - { - return true; - } - - - uint64_t calculated_estimated_height = (date - get_blockchain_launch_timestamp()) / DIFFICULTY_TOTAL_TARGET; - - if (date > m_db_blocks[m_db_blocks.size() - 1]->bl.timestamp) - { - //that suspicious but also could be(in case someone just created wallet offline in - //console and then got it synchronyzing and last block had a little timestamp shift) - //let's just return 1 day behind for safety reasons. - if (m_db_blocks.size() > 1440) - { - res_h = m_db_blocks.size() - 1440; - } - else - { - //likely impossible, but just in case - res_h = 0; - } - return true; - } - if (calculated_estimated_height > m_db_blocks.size() - 1) - calculated_estimated_height = m_db_blocks.size() - 1; - - //goal is to get timestamp in window in between 1day+1hour and 1 hour before target(1 hour is just to be sure that - //we didn't miss actual wallet start because of timestamp and difficulty fluctuations) - uint64_t low_boundary = date - 90000; //1 day + 1 hour - uint64_t high_boundary = date - 3600; //1 hour - - //std::cout << "ENTRY: low_boundary(minutes):" << low_boundary/60 << " high_boundary(minutes): " << high_boundary / 60 << std::endl; - - uint64_t iteration_coun = 0; - uint64_t current_low_boundary = 0; - uint64_t current_height_boundary = m_db_blocks.size() - 1; - while (true) - { - iteration_coun++; - if (iteration_coun > 29) // Log2(CURRENCY_MAX_BLOCK_NUMBER) - { - LOG_ERROR("Internal error: too much iterations on get_est_height_from_date, date = " << date); - return true; - } - uint64_t ts = m_db_blocks[calculated_estimated_height]->bl.timestamp; - if (ts > high_boundary) - { - //we moved too much forward - - current_height_boundary = calculated_estimated_height; - CHECK_AND_ASSERT_MES(current_height_boundary > current_low_boundary, true, - "Internal error: current_hight_boundary(" << current_height_boundary << ") > current_low_boundary("<< current_low_boundary << ")"); - uint64_t offset = (current_height_boundary - current_low_boundary)/2; - if (offset <= 2) - { - //something really wrong with distribution of blocks, just use current_low_boundary to be sure that we didn't mess any transactions - res_h = current_low_boundary; - return true; - } - - //std::cout << "est_h:" << calculated_estimated_height << ", ts(min): " << ts / 60 << " distance to RIGHT minutes: " << int64_t((int64_t(ts) - int64_t(high_boundary))) / 60 << std::endl; - //std::cout << "OOFFSET: -" << offset << std::endl; - calculated_estimated_height -= offset; - } - else if (ts < low_boundary) - { - //we too much in past - current_low_boundary = calculated_estimated_height; - CHECK_AND_ASSERT_MES(current_height_boundary > current_low_boundary, true, - "Internal error: current_hight_boundary(" << current_height_boundary << ") > current_low_boundary(" << current_low_boundary << ")"); - uint64_t offset = (current_height_boundary - current_low_boundary) / 2; - if (offset <= 2) - { - //something really wrong with distribution of blocks, just use current_low_boundary to be sure that we didn't mess any transactions - res_h = current_low_boundary; - return true; - } - //CHECK_AND_ASSERT_MES(offset > 2, true, - // "offset is too low = " << offset); - - //std::cout << "est_h:" << calculated_estimated_height << ", ts(min): " << ts / 60 << " distance to LEFT minutes: " << int64_t((int64_t(low_boundary) - int64_t(ts))) / 60 << std::endl; - //std::cout << "OOFFSET: +" << offset << std::endl; - calculated_estimated_height += offset; - } - else - { - res_h = calculated_estimated_height; - break; - } - } - - LOG_PRINT_L0("[get_est_height_from_date] returned " << calculated_estimated_height << " with " << iteration_coun << " iterations"); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height, bool need_global_indexes)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - blocks_direct_container blocks_direct; - if (!find_blockchain_supplement(qblock_ids, blocks_direct, total_height, start_height, max_count, minimum_height)) - return false; - - for (auto& bd : blocks_direct) - { - blocks.push_back(std::pair >()); - blocks.back().first = bd.first->bl; - for (auto& tx_ptr : bd.second) - { - blocks.back().second.push_back(tx_ptr->tx); - } - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::find_blockchain_supplement(const std::list& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height, bool request_coinbase_info)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if (!find_blockchain_supplement(qblock_ids, start_height)) - return false; - if (minimum_height > start_height) - start_height = minimum_height; - - total_height = get_current_blockchain_size(); - size_t count = 0; - for (size_t i = start_height; i != m_db_blocks.size() && count < max_count; i++, count++) - { - blocks.resize(blocks.size() + 1); - blocks.back().first = m_db_blocks[i]; - std::list mis; - get_transactions_direct(m_db_blocks[i]->bl.tx_hashes, blocks.back().second, mis); - CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, block " << get_block_hash(m_db_blocks[i]->bl) << " [" << i << "] contains missing transactions: " << mis); - if(request_coinbase_info) - blocks.back().third = m_db_transactions.find(get_transaction_hash(m_db_blocks[i]->bl.miner_tx)); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::add_block_as_invalid(const block& bl, const crypto::hash& h) -{ - block_extended_info bei = AUTO_VAL_INIT(bei); - bei.bl = bl; - return add_block_as_invalid(bei, h); -} -//------------------------------------------------------------------ -bool blockchain_storage::add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_invalid_blocks_lock); - auto i_res = m_invalid_blocks.insert(std::map::value_type(h, bei)); - CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed"); - LOG_PRINT_L0("BLOCK ADDED AS INVALID: " << h << ENDL << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size()); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!"); - return true; -} -//------------------------------------------------------------------ -void blockchain_storage::inspect_blocks_index()const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - LOG_PRINT_L0("Started block index inspecting...."); - m_db_blocks_index.enumerate_items([&](uint64_t count, const crypto::hash& id, uint64_t index) - { - CHECK_AND_ASSERT_MES(index < m_db_blocks.size(), true, "invalid index " << index << "(m_db_blocks.size()=" << m_db_blocks.size() << ") for id " << id << " "); - crypto::hash calculated_id = get_block_hash(m_db_blocks[index]->bl); - CHECK_AND_ASSERT_MES(id == calculated_id, true, "ID MISSMATCH ON INDEX " << index << ENDL - << "m_db_blocks_index keeps: " << id << ENDL - << "referenced to block with id " << calculated_id - ); - return true; - }); - LOG_PRINT_L0("Block index inspecting finished"); -} -//------------------------------------------------------------------ -bool blockchain_storage::have_block(const crypto::hash& id)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - if(m_db_blocks_index.find(id)) - return true; - { - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - if (m_alternative_chains.count(id)) - return true; - - } - /*if(m_orphaned_blocks.get().count(id)) - return true;*/ - - /*if(m_orphaned_by_tx.count(id)) - return true;*/ - { - CRITICAL_REGION_LOCAL1(m_invalid_blocks_lock); - if (m_invalid_blocks.count(id)) - return true; - } - - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::handle_block_to_main_chain(const block& bl, block_verification_context& bvc) -{ - crypto::hash id = get_block_hash(bl); - return handle_block_to_main_chain(bl, id, bvc); -} -//------------------------------------------------------------------ -bool blockchain_storage::push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector& global_indexes) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - size_t i = 0; - BOOST_FOREACH(const auto& ot, tx.vout) - { - if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) - { - m_db_outputs.push_back_item(ot.amount, global_output_entry::construct(tx_id, i)); - global_indexes.push_back(m_db_outputs.get_item_size(ot.amount) - 1); - if (ot.target.type() == typeid(txout_htlc) && !is_after_hardfork_3_zone()) - { - LOG_ERROR("Error: Transaction with txout_htlc before is_after_hardfork_3_zone(before height " << m_core_runtime_config.hard_fork_03_starts_after_height <<")"); - return false; - } - } - else if (ot.target.type() == typeid(txout_multisig)) - { - - crypto::hash multisig_out_id = get_multisig_out_id(tx, i); - CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); - CHECK_AND_ASSERT_MES(!m_db_multisig_outs.find(multisig_out_id), false, "Internal error: already have multisig_out_id " << multisig_out_id << "in multisig outs index"); - m_db_multisig_outs.set(multisig_out_id, ms_output_entry::construct(tx_id, i)); - global_indexes.push_back(0); // just stub to make other code easier - } - - ++i; - } - return true; -} -//------------------------------------------------------------------ -size_t blockchain_storage::get_total_transactions()const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_transactions.size(); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_outs(uint64_t amount, std::list& pkeys)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint64_t sz = m_db_outputs.get_item_size(amount); - - if (!sz) - return true; - - for (uint64_t i = 0; i != sz; i++) - { - auto out_entry_ptr = m_db_outputs.get_subitem(amount, i); - - auto tx_ptr = m_db_transactions.find(out_entry_ptr->tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "transactions outs global index consistency broken: can't find tx " << out_entry_ptr->tx_id << " in DB, for amount: " << amount << ", gindex: " << i); - CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_entry_ptr->out_no, false, "transactions outs global index consistency broken: index in tx_outx == " << out_entry_ptr->out_no << " is greather than tx.vout size == " << tx_ptr->tx.vout.size() << ", for amount: " << amount << ", gindex: " << i); - //CHECK_AND_ASSERT_MES(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key), false, "transactions outs global index consistency broken: out #" << out_entry_ptr->out_no << " in tx " << out_entry_ptr->tx_id << " has wrong type, for amount: " << amount << ", gindex: " << i); - if (tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_to_key)) - { - pkeys.push_back(boost::get(tx_ptr->tx.vout[out_entry_ptr->out_no].target).key); - }else if(tx_ptr->tx.vout[out_entry_ptr->out_no].target.type() == typeid(txout_htlc)) - { - pkeys.push_back(boost::get(tx_ptr->tx.vout[out_entry_ptr->out_no].target).pkey_redeem); - } - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - size_t i = tx.vout.size()-1; - BOOST_REVERSE_FOREACH(const auto& ot, tx.vout) - { - if (ot.target.type() == typeid(txout_to_key) || ot.target.type() == typeid(txout_htlc)) - { - uint64_t sz= m_db_outputs.get_item_size(ot.amount); - CHECK_AND_ASSERT_MES(sz, false, "transactions outs global index: empty index for amount: " << ot.amount); - auto back_item = m_db_outputs.get_subitem(ot.amount, sz - 1); - CHECK_AND_ASSERT_MES(back_item->tx_id == tx_id, false, "transactions outs global index consistency broken: tx id missmatch"); - CHECK_AND_ASSERT_MES(back_item->out_no == i, false, "transactions outs global index consistency broken: in transaction index missmatch"); - m_db_outputs.pop_back_item(ot.amount); - //if (!it->second.size()) - // m_db_outputs.erase(it); - } - else if (ot.target.type() == typeid(txout_multisig)) - { - crypto::hash multisig_out_id = get_multisig_out_id(tx, i); - CHECK_AND_ASSERT_MES(multisig_out_id != null_hash, false, "internal error during handling get_multisig_out_id() with tx id " << tx_id); - bool res = m_db_multisig_outs.erase_validate(multisig_out_id); - CHECK_AND_ASSERT_MES(res, false, "Internal error: multisig out not found, multisig_out_id " << multisig_out_id << "in multisig outs index"); - } - --i; - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) -{ - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra on unprocess_blockchain_tx_extra"); - if(ei.m_alias.m_alias.size()) - { - r = pop_alias_info(ei.m_alias); - CHECK_AND_ASSERT_MES(r, false, "failed to pop_alias_info"); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_alias_info(const std::string& alias, extra_alias_entry_base& info)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto al_ptr = m_db_aliases.find(alias); - if (al_ptr) - { - if (al_ptr->size()) - { - info = al_ptr->back(); - return true; - } - } - return false; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_aliases_count() const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_aliases.size(); -} -//------------------------------------------------------------------ -std::string blockchain_storage::get_alias_by_address(const account_public_address& addr)const -{ - auto alias_ptr = m_db_addr_to_alias.find(addr); - if (alias_ptr && alias_ptr->size()) - { - return *(alias_ptr->begin()); - } - - return ""; -} -//------------------------------------------------------------------ -bool blockchain_storage::pop_alias_info(const extra_alias_entry& ai) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - CHECK_AND_ASSERT_MES(ai.m_alias.size(), false, "empty name in pop_alias_info"); - auto alias_history_ptr = m_db_aliases.find(ai.m_alias); - CHECK_AND_ASSERT_MES(alias_history_ptr && alias_history_ptr->size(), false, "empty name list in pop_alias_info"); - - auto addr_to_alias_ptr = m_db_addr_to_alias.find(alias_history_ptr->back().m_address); - if (addr_to_alias_ptr) - { - //update db - address_to_aliases_container::t_value_type local_v = *addr_to_alias_ptr; - - auto it_in_set = local_v.find(ai.m_alias); - CHECK_AND_ASSERT_MES(it_in_set != local_v.end(), false, "it_in_set != it->second.end() validation failed"); - - local_v.erase(it_in_set); - if (!local_v.size()) - { - //delete the whole record from db - m_db_addr_to_alias.erase(alias_history_ptr->back().m_address); - } - else - { - //update db - m_db_addr_to_alias.set(alias_history_ptr->back().m_address, local_v); - } - } - else - { - LOG_ERROR("In m_addr_to_alias not found " << get_account_address_as_str(alias_history_ptr->back().m_address)); - } - - aliases_container::t_value_type local_alias_hist = *alias_history_ptr; - local_alias_hist.pop_back(); - if(local_alias_hist.size()) - m_db_aliases.set(ai.m_alias, local_alias_hist); - else - m_db_aliases.erase(ai.m_alias); - - if (local_alias_hist.size()) - { - address_to_aliases_container::t_value_type local_copy = AUTO_VAL_INIT(local_copy); - auto set_ptr = m_db_addr_to_alias.get(local_alias_hist.back().m_address); - if (set_ptr) - local_copy = *set_ptr; - - local_copy.insert(ai.m_alias); - m_db_addr_to_alias.set(local_alias_hist.back().m_address, local_copy); - } - - LOG_PRINT_MAGENTA("[ALIAS_UNREGISTERED]: " << ai.m_alias << ": " << get_account_address_as_str(ai.m_address) << " -> " << (!local_alias_hist.empty() ? get_account_address_as_str(local_alias_hist.back().m_address) : "(available)"), LOG_LEVEL_1); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entry & ai) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - CHECK_AND_ASSERT_MES(ai.m_alias.size(), false, "empty name in put_alias_info"); - aliases_container::t_value_type local_alias_history = AUTO_VAL_INIT(local_alias_history); - auto alias_history_ptr_ = m_db_aliases.get(ai.m_alias); - if (alias_history_ptr_) - local_alias_history = *alias_history_ptr_; - - if (!local_alias_history.size()) - { - - //update alias entry in db - local_alias_history.push_back(ai); - m_db_aliases.set(ai.m_alias, local_alias_history); - - //update addr-to-alias db entry - address_to_aliases_container::t_value_type addr_to_alias_local = AUTO_VAL_INIT(addr_to_alias_local); - auto addr_to_alias_ptr_ = m_db_addr_to_alias.get(local_alias_history.back().m_address); - if (addr_to_alias_ptr_) - addr_to_alias_local = *addr_to_alias_ptr_; - - addr_to_alias_local.insert(ai.m_alias); - m_db_addr_to_alias.set(local_alias_history.back().m_address, addr_to_alias_local); - - //@@ remove get_tx_fee_median(); - LOG_PRINT_MAGENTA("[ALIAS_REGISTERED]: " << ai.m_alias << ": " << get_account_address_as_str(ai.m_address) << ", fee median: " << get_tx_fee_median(), LOG_LEVEL_1); - rise_core_event(CORE_EVENT_ADD_ALIAS, alias_info_to_rpc_alias_info(ai)); - }else - { - //update procedure - CHECK_AND_ASSERT_MES(ai.m_sign.size() == 1, false, "alias " << ai.m_alias << " can't be update, wrong ai.m_sign.size() count: " << ai.m_sign.size()); - //std::string signed_buff; - //make_tx_extra_alias_entry(signed_buff, ai, true); - std::string old_address = currency::get_account_address_as_str(local_alias_history.back().m_address); - bool r = crypto::check_signature(get_sign_buff_hash_for_alias_update(ai), local_alias_history.back().m_address.spend_public_key, ai.m_sign.back()); - CHECK_AND_ASSERT_MES(r, false, "Failed to check signature, alias update failed." << ENDL - << "alias: " << ai.m_alias << ENDL - << "signed_buff_hash: " << get_sign_buff_hash_for_alias_update(ai) << ENDL - << "public key: " << local_alias_history.back().m_address.spend_public_key << ENDL - << "new_address: " << get_account_address_as_str(ai.m_address) << ENDL - << "signature: " << epee::string_tools::pod_to_hex(ai.m_sign) << ENDL - << "alias_history.size() = " << local_alias_history.size()); - - //update adr-to-alias db - auto addr_to_alias_ptr_ = m_db_addr_to_alias.find(local_alias_history.back().m_address); - if (addr_to_alias_ptr_) - { - address_to_aliases_container::t_value_type addr_to_alias_local = *addr_to_alias_ptr_; - auto it_in_set = addr_to_alias_local.find(ai.m_alias); - if (it_in_set == addr_to_alias_local.end()) - { - LOG_ERROR("it_in_set == it->second.end()"); - } - else - { - addr_to_alias_local.erase(it_in_set); - } - - if (!addr_to_alias_local.size()) - m_db_addr_to_alias.erase(local_alias_history.back().m_address); - else - m_db_addr_to_alias.set(local_alias_history.back().m_address, addr_to_alias_local); - } - else - { - LOG_ERROR("Wrong m_addr_to_alias state: address not found " << get_account_address_as_str(local_alias_history.back().m_address)); - - std::stringstream ss; - ss << "History for alias " << ai.m_alias << ":" << ENDL; - size_t i = 0; - for (auto el : local_alias_history) - { - ss << std::setw(2) << i++ << " " - << get_account_address_as_str(el.m_address) << " " - << (el.m_sign.empty() ? " no sig " : " SIGNED ") << " " - << el.m_text_comment << ENDL; - } - - LOG_PRINT_L0(ss.str()); - - } - - //update alias db - local_alias_history.push_back(ai); - m_db_aliases.set(ai.m_alias, local_alias_history); - - //update addr_to_alias db - address_to_aliases_container::t_value_type addr_to_alias_local2 = AUTO_VAL_INIT(addr_to_alias_local2); - auto addr_to_alias_ptr_2 = m_db_addr_to_alias.get(local_alias_history.back().m_address); - if (addr_to_alias_ptr_2) - addr_to_alias_local2 = *addr_to_alias_ptr_2; - - addr_to_alias_local2.insert(ai.m_alias); - m_db_addr_to_alias.set(local_alias_history.back().m_address, addr_to_alias_local2); - - LOG_PRINT_MAGENTA("[ALIAS_UPDATED]: " << ai.m_alias << ": from: " << old_address << " to " << get_account_address_as_str(ai.m_address), LOG_LEVEL_1); - rise_core_event(CORE_EVENT_UPDATE_ALIAS, alias_info_to_rpc_update_alias_info(ai, old_address)); - - } - return true; -} -//------------------------------------------------------------------ -void blockchain_storage::set_event_handler(i_core_event_handler* event_handler) const -{ - if (event_handler == nullptr) - { - m_event_handler = &m_event_handler_stub; - m_services_mgr.set_event_handler(nullptr); - } - else - { - m_event_handler = event_handler; - m_services_mgr.set_event_handler(event_handler); - } - -} -//------------------------------------------------------------------ -i_core_event_handler* blockchain_storage::get_event_handler() const -{ - return m_event_handler; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::validate_alias_reward(const transaction& tx, const std::string& alias) const -{ - - //validate alias coast - uint64_t fee_for_alias = get_alias_coast(alias); - - //validate the price had been paid - uint64_t found_alias_reward = get_amount_for_zero_pubkeys(tx); - - //@#@ - //work around for net 68's generation -#if CURRENCY_FORMATION_VERSION == 68 - if (alias == "bhrfrrrtret" && get_transaction_hash(tx) == epee::string_tools::parse_tpod_from_hex_string("760b85546678d2235a1843e18d8a016a2e4d9b8273cc4d7c09bebff1f6fa7eaf") ) - return true; - if (alias == "test-420" && get_transaction_hash(tx) == epee::string_tools::parse_tpod_from_hex_string("10f8a2539b2551bd0919bf7e3b1dfbae7553eca63e58cd2264ae60f90030edf8")) - return true; -#endif - - CHECK_AND_ASSERT_MES(found_alias_reward >= fee_for_alias, false, "registration of alias '" - << alias << "' goes with a reward of " << print_money(found_alias_reward) << " which is less than expected: " << print_money(fee_for_alias) - <<"(fee median: " << get_tx_fee_median() << ")" - << ", tx: " << get_transaction_hash(tx)); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::prevalidate_alias_info(const transaction& tx, const extra_alias_entry& eae) -{ - - bool r = validate_alias_name(eae.m_alias); - CHECK_AND_ASSERT_MES(r, false, "failed to validate alias name!"); - bool already_have_alias = false; - { - CRITICAL_REGION_LOCAL(m_read_lock); - auto existing_ptr = m_db_aliases.find(eae.m_alias); - if (existing_ptr && existing_ptr->size()) - { - already_have_alias = true; - } - - } - //auto alias_history_ptr_ = m_db_aliases.get(eae.m_alias); - if (!already_have_alias) - { - bool r = validate_alias_reward(tx, eae.m_alias); - CHECK_AND_ASSERT_MES(r, false, "failed to validate_alias_reward"); - - if (eae.m_alias.size() < ALIAS_MINIMUM_PUBLIC_SHORT_NAME_ALLOWED) - { - //short alias name, this aliases should be issued only by specific authority - CHECK_AND_ASSERT_MES(eae.m_sign.size() == 1, false, "alias " << eae.m_alias << " can't be update, wrong ai.m_sign.size() count: " << eae.m_sign.size()); - - bool r = crypto::check_signature(get_sign_buff_hash_for_alias_update(eae), m_core_runtime_config.alias_validation_pubkey, eae.m_sign.back()); - CHECK_AND_ASSERT_MES(r, false, "Failed to check signature, short alias registration failed." << ENDL - << "alias: " << eae.m_alias << ENDL - << "signed_buff_hash: " << get_sign_buff_hash_for_alias_update(eae) << ENDL - << "public key: " << m_core_runtime_config.alias_validation_pubkey << ENDL - << "new_address: " << get_account_address_as_str(eae.m_address) << ENDL - << "signature: " << epee::string_tools::pod_to_hex(eae.m_sign)); - } - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::process_blockchain_tx_extra(const transaction& tx) -{ - //check transaction extra - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra"); - if (ei.m_alias.m_alias.size()) - { - r = prevalidate_alias_info(tx, ei.m_alias); - CHECK_AND_ASSERT_MES(r, false, "failed to prevalidate_alias_info"); - - r = put_alias_info(tx, ei.m_alias); - CHECK_AND_ASSERT_MES(r, false, "failed to put_alias_info"); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_outs_index_stat(outs_index_stat& outs_stat) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - outs_stat.amount_0_001 = m_db_outputs.get_item_size(COIN / 1000); - outs_stat.amount_0_01 = m_db_outputs.get_item_size(COIN / 100); - outs_stat.amount_0_1 = m_db_outputs.get_item_size(COIN / 10); - outs_stat.amount_1 = m_db_outputs.get_item_size(COIN); - outs_stat.amount_10 = m_db_outputs.get_item_size(COIN * 10); - outs_stat.amount_100 = m_db_outputs.get_item_size(COIN * 100); - outs_stat.amount_1000 = m_db_outputs.get_item_size(COIN * 1000); - outs_stat.amount_10000 = m_db_outputs.get_item_size(COIN * 10000); - outs_stat.amount_100000 = m_db_outputs.get_item_size(COIN * 100000); - outs_stat.amount_1000000 = m_db_outputs.get_item_size(COIN * 1000000); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp) -{ - //check transaction extra - uint64_t count = 0; - - for (const auto& at : tx.attachment) - { - if (at.type() == typeid(tx_service_attachment)) - { - m_services_mgr.handle_entry_push(boost::get(at), count, tx, h, bl_id, timestamp); //handle service - ++count; - } - } - return true; -} - -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_tx_fee_median() const -{ - uint64_t h = m_db_blocks.size(); - if (m_current_fee_median_effective_index != get_tx_fee_median_effective_index(h)) - { - m_current_fee_median = tx_fee_median_for_height(h); - m_current_fee_median_effective_index = get_tx_fee_median_effective_index(h); - } - - if (!m_current_fee_median) - m_current_fee_median = ALIAS_VERY_INITAL_COAST; - return m_current_fee_median; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_alias_coast(const std::string& alias) const -{ - uint64_t median_fee = get_tx_fee_median(); - //CHECK_AND_ASSERT_MES_NO_RET(median_fee, "can't calculate median"); - - if (!median_fee) - median_fee = ALIAS_VERY_INITAL_COAST; - - - return get_alias_coast_from_fee(alias, median_fee); -} -//------------------------------------------------------------------ -bool blockchain_storage::unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp) -{ - - size_t cnt_serv_attach = get_service_attachments_count_in_tx(tx); - if (cnt_serv_attach == 0) - return true; - - --cnt_serv_attach; - for (auto it = tx.attachment.rbegin(); it != tx.attachment.rend(); it++) - { - auto& at = *it; - if (at.type() == typeid(tx_service_attachment)) - { - m_services_mgr.handle_entry_pop(boost::get(at), cnt_serv_attach, tx, h, timestamp); - --cnt_serv_attach; - } - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx) const -{ - return m_services_mgr.validate_entry(a, i, tx); -} -//------------------------------------------------------------------ -namespace currency -{ - struct add_transaction_input_visitor : public boost::static_visitor - { - blockchain_storage& m_bcs; - blockchain_storage::key_images_container& m_db_spent_keys; - const crypto::hash& m_tx_id; - const crypto::hash& m_bl_id; - const uint64_t m_bl_height; - uint64_t &m_mixins_count; - add_transaction_input_visitor(blockchain_storage& bcs, blockchain_storage::key_images_container& m_db_spent_keys, const crypto::hash& tx_id, const crypto::hash& bl_id, const uint64_t bl_height, uint64_t& mixins_count) : - m_bcs(bcs), - m_db_spent_keys(m_db_spent_keys), - m_tx_id(tx_id), - m_bl_id(bl_id), - m_bl_height(bl_height), - m_mixins_count(mixins_count) - {} - bool operator()(const txin_to_key& in) const - { - const crypto::key_image& ki = in.k_image; - - auto ki_ptr = m_db_spent_keys.get(ki); - if (ki_ptr) - { - //double spend detected - LOG_PRINT_RED_L0("tx with id: " << m_tx_id << " in block id: " << m_bl_id << " have input marked as spent with key image: " << ki << ", block declined"); - return false; - } - m_db_spent_keys.set(ki, m_bl_height); - - if (in.key_offsets.size() == 1) - { - //direct spend detected - if (!m_bcs.update_spent_tx_flags_for_input(in.amount, in.key_offsets[0], true)) - { - //internal error - LOG_PRINT_RED_L0("Failed to update_spent_tx_flags_for_input"); - return false; - } - } - if (m_mixins_count < in.key_offsets.size()) - m_mixins_count = in.key_offsets.size(); - return true; - } - bool operator()(const txin_htlc& in) const - { - if (!m_bcs.is_after_hardfork_3_zone()) - { - LOG_ERROR("Error: Transaction with txin_htlc before is_after_hardfork_3_zone(before height " << m_bcs.get_core_runtime_config().hard_fork_03_starts_after_height << ")"); - return false; - } - return this->operator()(static_cast(in)); - } - bool operator()(const txin_gen& in) const { return true; } - bool operator()(const txin_multisig& in) const - { - //mark out as spent - if (!m_bcs.update_spent_tx_flags_for_input(in.multisig_out_id, m_bl_height)) - { - //internal error - LOG_PRINT_RED_L0("Failed to update_spent_tx_flags_for_input"); - return false; - } - return true; - } - }; -} - - -bool blockchain_storage::add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height, uint64_t timestamp) -{ - bool need_to_profile = !is_coinbase(tx); - TIME_MEASURE_START_PD(tx_append_rl_wait); - CRITICAL_REGION_LOCAL(m_read_lock); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_append_rl_wait); - - TIME_MEASURE_START_PD(tx_append_is_expired); - CHECK_AND_ASSERT_MES(!is_tx_expired(tx), false, "Transaction can't be added to the blockchain since it's already expired. tx expiration time: " << get_tx_expiration_time(tx) << ", blockchain median time: " << get_tx_expiration_median()); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_append_is_expired); - - CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(tx, tx_id, bl_height), false, "tx " << tx_id << ": hardfork-specific validation failed"); - - TIME_MEASURE_START_PD(tx_process_extra); - bool r = process_blockchain_tx_extra(tx); - CHECK_AND_ASSERT_MES(r, false, "failed to process_blockchain_tx_extra"); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_extra); - - TIME_MEASURE_START_PD(tx_process_attachment); - process_blockchain_tx_attachments(tx, bl_height, bl_id, timestamp); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_attachment); - - uint64_t mixins_count = 0; - TIME_MEASURE_START_PD(tx_process_inputs); - for(const txin_v& in : tx.vin) - { - if(!boost::apply_visitor(add_transaction_input_visitor(*this, m_db_spent_keys, tx_id, bl_id, bl_height, mixins_count), in)) - { - LOG_ERROR("critical internal error: add_transaction_input_visitor failed. but key_images should be already checked"); - purge_transaction_keyimages_from_blockchain(tx, false); - bool r = unprocess_blockchain_tx_extra(tx); - CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra"); - - unprocess_blockchain_tx_attachments(tx, bl_height, timestamp); - - return false; - } - } - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_inputs); - if (need_to_profile && mixins_count > 0) - { - m_performance_data.tx_mixin_count.push(mixins_count); -#ifdef _DEBUG - LOG_PRINT_L0("[TX_MIXINS]: " << mixins_count); -#endif - } - - //check if there is already transaction with this hash - TIME_MEASURE_START_PD(tx_check_exist); - auto tx_entry_ptr = m_db_transactions.get(tx_id); - if (tx_entry_ptr) - { - LOG_ERROR("critical internal error: tx with id: " << tx_id << " in block id: " << bl_id << " already in blockchain"); - purge_transaction_keyimages_from_blockchain(tx, true); - bool r = unprocess_blockchain_tx_extra(tx); - CHECK_AND_ASSERT_MES(r, false, "failed to unprocess_blockchain_tx_extra"); - - unprocess_blockchain_tx_attachments(tx, bl_height, timestamp); - return false; - } - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_check_exist); - TIME_MEASURE_START_PD(tx_push_global_index); - transaction_chain_entry ch_e; - ch_e.m_keeper_block_height = bl_height; - ch_e.m_spent_flags.resize(tx.vout.size(), false); - ch_e.tx = tx; - r = push_transaction_to_global_outs_index(tx, tx_id, ch_e.m_global_output_indexes); - CHECK_AND_ASSERT_MES(r, false, "failed to return push_transaction_to_global_outs_index tx id " << tx_id); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_push_global_index); - - //store everything to db - TIME_MEASURE_START_PD(tx_store_db); - m_db_transactions.set(tx_id, ch_e); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_store_db); - - TIME_MEASURE_START_PD(tx_print_log); - LOG_PRINT_L1("Added tx to blockchain: " << tx_id << " via block at " << bl_height << " id " << print16(bl_id) - << ", ins: " << tx.vin.size() << ", outs: " << tx.vout.size() << ", outs sum: " << print_money_brief(get_outs_money_amount(tx)) << " (fee: " << (is_coinbase(tx) ? "0[coinbase]" : print_money_brief(get_tx_fee(tx))) << ")"); - TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_print_log); - //@#@ del me -// LOG_PRINT_L0("APPEND_TX_TIME_INNER: " << m_performance_data.tx_append_rl_wait.get_last_val() -// << " | " << m_performance_data.tx_append_is_expired.get_last_val() -// << " | " << m_performance_data.tx_process_extra.get_last_val() -// << " | " << m_performance_data.tx_process_attachment.get_last_val() -// << " | " << m_performance_data.tx_process_inputs.get_last_val() -// << " | " << m_performance_data.tx_check_exist.get_last_val() -// << " | " << m_performance_data.tx_push_global_index.get_last_val() -// << " | " << m_performance_data.tx_store_db.get_last_val() -// << " | " << m_performance_data.tx_print_log.get_last_val() -// ); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto tx_ptr = m_db_transactions.find(tx_id); - if (!tx_ptr) - { - LOG_PRINT_RED_L0("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id); - return false; - } - - CHECK_AND_ASSERT_MES(tx_ptr->m_global_output_indexes.size(), false, "internal error: global indexes for transaction " << tx_id << " is empty"); - indexs = tx_ptr->m_global_output_indexes; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - bool res = check_tx_inputs(tx, tx_prefix_hash, max_used_block_height); - if(!res) return false; - CHECK_AND_ASSERT_MES(max_used_block_height < m_db_blocks.size(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db_blocks.size()); - get_block_hash(m_db_blocks[max_used_block_height]->bl, max_used_block_id); - return true; -} -//------------------------------------------------------------------ -#define PERIOD_DISABLED 0xffffffffffffffffLL - -bool blockchain_storage::rebuild_tx_fee_medians() -{ - uint64_t sz = m_db_blocks.size(); - m_db.begin_transaction(); - LOG_PRINT_L0("Started reinitialization of median fee..."); - math_helper::once_a_time_seconds<10> log_idle; - - epee::misc_utils::median_helper blocks_median; - for (uint64_t i = 0; i != sz; i++) - { - log_idle.do_call([&]() {std::cout << "block " << i << " of " << sz << std::endl; return true; }); - - auto bptr = m_db_blocks[i]; - block_extended_info new_bei = *bptr; - //assign effective median - new_bei.effective_tx_fee_median = blocks_median.get_median(); - - //calculate current median for this particular block - std::vector fees; - for (auto& h: new_bei.bl.tx_hashes) - { - auto txptr = get_tx_chain_entry(h); - CHECK_AND_ASSERT_MES(txptr, false, "failed to find tx id " << h << " from block " << i); - fees.push_back(get_tx_fee(txptr->tx)); - } - new_bei.this_block_tx_fee_median = epee::misc_utils::median(fees); - m_db_blocks.set(i, new_bei); - - - //prepare median helper for next block - if(new_bei.this_block_tx_fee_median) - blocks_median.push_item(new_bei.this_block_tx_fee_median, i); - - //create callbacks - - bool is_pos_allowed_l = i >= m_core_runtime_config.pos_minimum_heigh; - uint64_t period = is_pos_allowed_l ? ALIAS_COAST_PERIOD : ALIAS_COAST_PERIOD / 2; - if (period >= i+1) - continue; - uint64_t starter_block_index = i+1 - period; - - uint64_t purge_recent_period = is_pos_allowed_l ? ALIAS_COAST_RECENT_PERIOD : ALIAS_COAST_RECENT_PERIOD / 2; - uint64_t purge_recent_block_index = 0; - if (purge_recent_period >= i + 1) - purge_recent_block_index = PERIOD_DISABLED; - else - purge_recent_block_index = i + 1 - purge_recent_period; - - - auto cb = [&](uint64_t fee, uint64_t height) - { - if (height >= starter_block_index) - return true; - return false; - }; - - auto cb_final_eraser = [&](uint64_t fee, uint64_t height) - { - if (purge_recent_block_index == PERIOD_DISABLED) - return true; - if (height >= purge_recent_block_index) - return true; - - return false; - }; - - blocks_median.scan_items(cb, cb_final_eraser); - } - - m_db.commit_transaction(); - LOG_PRINT_L0("Reinitialization of median fee finished!") - return true; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_tx_fee_median_effective_index(uint64_t h)const -{ - if (h <= ALIAS_MEDIAN_RECALC_INTERWAL + 1) - return 0; - - h -= 1; // for transactions of block that h%ALIAS_MEDIAN_RECALC_INTERWAL==0 we still handle fee median from previous day - return h - (h % ALIAS_MEDIAN_RECALC_INTERWAL); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::tx_fee_median_for_height(uint64_t h)const -{ - uint64_t effective_index = get_tx_fee_median_effective_index(h); - CHECK_AND_ASSERT_THROW_MES(effective_index < m_db_blocks.size(), "internal error: effective_index= " << effective_index << " while m_db_blocks.size()=" << m_db_blocks.size()); - return m_db_blocks[effective_index]->effective_tx_fee_median; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_all_aliases_for_new_median_mode() -{ - LOG_PRINT_L0("Started reinitialization of median fee..."); - math_helper::once_a_time_seconds<10> log_idle; - uint64_t sz = m_db_blocks.size(); - for (uint64_t i = 0; i != sz; i++) - { - log_idle.do_call([&]() {std::cout << "block " << i << " of " << sz << std::endl; return true; }); - - auto bptr = m_db_blocks[i]; - for (auto& tx_id : bptr->bl.tx_hashes) - { - auto tx_ptr = m_db_transactions.find(tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "Internal error: tx " << tx_id << " from block " << i << " not found"); - tx_extra_info tei = AUTO_VAL_INIT(tei); - bool r = parse_and_validate_tx_extra(tx_ptr->tx, tei); - CHECK_AND_ASSERT_MES(r, false, "Internal error: tx " << tx_id << " from block " << i << " was failed to parse"); - if (tei.m_alias.m_alias.size() && !tei.m_alias.m_sign.size()) - { - //reward - //validate alias coast - uint64_t median_fee = tx_fee_median_for_height(i); - uint64_t fee_for_alias = get_alias_coast_from_fee(tei.m_alias.m_alias, median_fee); - - //validate the price had been paid - uint64_t found_alias_reward = get_amount_for_zero_pubkeys(tx_ptr->tx); - if (found_alias_reward < fee_for_alias) - { - LOG_PRINT_RED_L0("[" << i << "]Found collision on alias: " << tei.m_alias.m_alias - << ", expected fee: " << print_money(fee_for_alias) << "(median:" << print_money(median_fee) << ")" - <<" found reward: " << print_money(found_alias_reward) <<". tx_id: " << tx_id); - } - } - } - } - - LOG_PRINT_L0("Finished."); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::print_tx_outputs_lookup(const crypto::hash& tx_id)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto tx_ptr = m_db_transactions.find(tx_id); - - if (!tx_ptr) - { - LOG_PRINT_RED_L0("Tx " << tx_id << " not found"); - return true; - } - - //amount -> index -> [{tx_id, rind_count}] - std::map > > > usage_stat; - std::stringstream strm_tx; - CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() == tx_ptr->m_global_output_indexes.size(), false, "Internal error: output size missmatch"); - for (uint64_t i = 0; i!= tx_ptr->tx.vout.size();i++) - { - strm_tx << "[" << i << "]: " << print_money(tx_ptr->tx.vout[i].amount) << ENDL; - if (tx_ptr->tx.vout[i].target.type() != typeid(currency::txout_to_key)) - continue; - - usage_stat[tx_ptr->tx.vout[i].amount][tx_ptr->m_global_output_indexes[i]]; - - } - - LOG_PRINT_L0("Lookup in all transactions...."); - for (uint64_t i = 0; i != m_db_blocks.size(); i++) - { - auto block_ptr = m_db_blocks[i]; - for (auto block_tx_id : block_ptr->bl.tx_hashes) - { - auto block_tx_ptr = m_db_transactions.find(block_tx_id); - for (auto txi_in : block_tx_ptr->tx.vin) - { - if(txi_in.type() != typeid(currency::txin_to_key)) - continue; - currency::txin_to_key& txi_in_tokey = boost::get(txi_in); - uint64_t amount = txi_in_tokey.amount; - auto amount_it = usage_stat.find(amount); - if(amount_it == usage_stat.end()) - continue; - - for (txout_ref_v& off : txi_in_tokey.key_offsets) - { - if(off.type() != typeid(uint64_t)) - continue; - uint64_t index = boost::get(off); - auto index_it = amount_it->second.find(index); - if(index_it == amount_it->second.end()) - continue; - index_it->second.push_back(std::pair(block_tx_id, txi_in_tokey.key_offsets.size())); - } - } - } - } - - std::stringstream ss; - for (auto& amount : usage_stat) - { - for (auto& index : amount.second) - { - ss << "[" << print_money(amount.first) << ":" << index.first << "]" << ENDL ; - for (auto& list_entry : index.second) - { - ss << " " << list_entry.first << ": " << list_entry.second << ENDL; - } - } - } - - LOG_PRINT_L0("Results: " << ENDL << strm_tx.str() << ENDL << ss.str()); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::have_tx_keyimges_as_spent(const transaction &tx) const -{ - // check all tx's inputs for being already spent - for (const txin_v& in : tx.vin) - { - if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc)) - { - if (have_tx_keyimg_as_spent(get_to_key_input_from_txin_v(in).k_image)) - { - return true; - } - } - else if (in.type() == typeid(txin_multisig)) - { - if (is_multisig_output_spent(boost::get(in).multisig_out_id)) - return true; - } - else if (in.type() == typeid(txin_gen)) - { - // skip txin_gen - } - else - { - LOG_ERROR("Unexpected input type: " << in.type().name()); - } - } - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const -{ - uint64_t stub = 0; - return check_tx_inputs(tx, tx_prefix_hash, stub); -} -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height) const -{ - size_t sig_index = 0; - max_used_block_height = 0; - - std::vector sig_stub; - const std::vector* psig = &sig_stub; - - TIME_MEASURE_START_PD(tx_check_inputs_loop); - for(const auto& txin : tx.vin) - { - if (!m_is_in_checkpoint_zone) - { - CHECK_AND_ASSERT_MES(sig_index < tx.signatures.size(), false, "Wrong transaction: missing signature entry for input #" << sig_index << " tx: " << tx_prefix_hash); - psig = &tx.signatures[sig_index]; - } - - if (txin.type() == typeid(txin_to_key)) - { - const txin_to_key& in_to_key = boost::get(txin); - - CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash); - TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check); - if (have_tx_keyimg_as_spent(in_to_key.k_image)) - { - LOG_ERROR("Key image was already spent in blockchain: " << string_tools::pod_to_hex(in_to_key.k_image) << " for input #" << sig_index << " tx: " << tx_prefix_hash); - return false; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check); - uint64_t max_unlock_time = 0; - if (!check_tx_input(tx, sig_index, in_to_key, tx_prefix_hash, *psig, max_used_block_height, max_unlock_time)) - { - LOG_ERROR("Failed to validate input #" << sig_index << " tx: " << tx_prefix_hash); - return false; - } - } - else if (txin.type() == typeid(txin_multisig)) - { - const txin_multisig& in_ms = boost::get(txin); - if (!check_tx_input(tx, sig_index, in_ms, tx_prefix_hash, *psig, max_used_block_height)) - { - LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << in_ms.multisig_out_id << ") in tx: " << tx_prefix_hash); - return false; - } - } - else if (txin.type() == typeid(txin_htlc)) - { - if (!is_after_hardfork_3_zone()) - { - LOG_ERROR("Error: Transaction with txin_htlc before is_after_hardfork_3_zone(before height " << m_core_runtime_config.hard_fork_03_starts_after_height << ")"); - return false; - } - - const txin_htlc& in_htlc = boost::get(txin); - CHECK_AND_ASSERT_MES(in_htlc.key_offsets.size(), false, "Empty in_to_key.key_offsets for input #" << sig_index << " tx: " << tx_prefix_hash); - TIME_MEASURE_START_PD(tx_check_inputs_loop_kimage_check); - if (have_tx_keyimg_as_spent(in_htlc.k_image)) - { - LOG_ERROR("Key image was already spent in blockchain: " << string_tools::pod_to_hex(in_htlc.k_image) << " for input #" << sig_index << " tx: " << tx_prefix_hash); - return false; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_kimage_check); - if (!check_tx_input(tx, sig_index, in_htlc, tx_prefix_hash, *psig, max_used_block_height)) - { - LOG_ERROR("Failed to validate multisig input #" << sig_index << " (ms out id: " << obj_to_json_str(in_htlc) << ") in tx: " << tx_prefix_hash); - return false; - } - } - sig_index++; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop); - - TIME_MEASURE_START_PD(tx_check_inputs_attachment_check); - if (!m_is_in_checkpoint_zone) - { - CHECK_AND_ASSERT_MES(tx.signatures.size() == sig_index, false, "tx signatures count differs from inputs"); - if (!(get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE)) - { - bool r = validate_attachment_info(tx.extra, tx.attachment, false); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate attachments in tx " << tx_prefix_hash << ": incorrect extra_attachment_info in tx.extra"); - } - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_attachment_check); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const -{ - return currency::is_tx_spendtime_unlocked(unlock_time, get_current_blockchain_size(), m_core_runtime_config.get_core_time()); -} -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - //TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop); - - std::vector output_keys; - scan_for_keys_context scan_context = AUTO_VAL_INIT(scan_context); - if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase)) - { - LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")"); - return false; - } - //TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_ch_in_get_keys_loop); - - std::vector output_keys_ptrs; - output_keys_ptrs.reserve(output_keys.size()); - for (auto& ptr : output_keys) - output_keys_ptrs.push_back(&ptr); - - return check_input_signature(tx, in_index, txin, tx_prefix_hash, sig, output_keys_ptrs); -} -//---------------------------------------------------------------- -struct outputs_visitor -{ - std::vector& m_results_collector; - blockchain_storage::scan_for_keys_context& m_scan_context; - const blockchain_storage& m_bch; - uint64_t& m_source_max_unlock_time_for_pos_coinbase; - outputs_visitor(std::vector& results_collector, - const blockchain_storage& bch, - uint64_t& source_max_unlock_time_for_pos_coinbase, - blockchain_storage::scan_for_keys_context& scan_context) - : m_results_collector(results_collector) - , m_bch(bch) - , m_source_max_unlock_time_for_pos_coinbase(source_max_unlock_time_for_pos_coinbase) - , m_scan_context(scan_context) - {} - bool handle_output(const transaction& source_tx, const transaction& validated_tx, const tx_out& out, uint64_t out_i) - { - //check tx unlock time - uint64_t source_out_unlock_time = get_tx_unlock_time(source_tx, out_i); - //let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward - if (is_coinbase(validated_tx) && is_pos_block(validated_tx)) - { - CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase"); - if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase) - m_source_max_unlock_time_for_pos_coinbase = source_out_unlock_time; - } - else - { - if (!m_bch.is_tx_spendtime_unlocked(source_out_unlock_time)) - { - LOG_PRINT_L0("One of outputs for one of inputs have wrong tx.unlock_time = " << get_tx_unlock_time(source_tx, out_i)); - return false; - } - } - if (out.target.type() == typeid(txout_to_key)) - { - crypto::public_key pk = boost::get(out.target).key; - m_results_collector.push_back(pk); - } - else if (out.target.type() == typeid(txout_htlc)) - { - m_scan_context.htlc_outs.push_back(boost::get(out.target)); - crypto::public_key pk = null_pkey; - if (m_scan_context.htlc_is_expired) - { - pk = boost::get(out.target).pkey_refund; - } - else - { - pk = boost::get(out.target).pkey_redeem; - } - m_results_collector.push_back(pk); - }else - { - LOG_PRINT_L0("Output have wrong type id, which=" << out.target.which()); - return false; - } - - return true; - } -}; - -//------------------------------------------------------------------ -// Checks each referenced output for: -// 1) source tx unlock time validity -// 2) mixin restrictions -// 3) general gindex/ref_by_id corectness -bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verifying_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - outputs_visitor vi(output_keys, *this, source_max_unlock_time_for_pos_coinbase, scan_context); - return scan_outputkeys_for_indexes(tx, verifying_input, vi, max_related_block_height, scan_context); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verifying_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const -{ - scan_for_keys_context scan_context_dummy = AUTO_VAL_INIT(scan_context_dummy); - return get_output_keys_for_input_with_checks(tx, verifying_input, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase, scan_context_dummy); -} - -//------------------------------------------------------------------ -// Note: this function can be used for checking to_key inputs against either main chain or alt chain, that's why it has output_keys_ptrs parameter -// Doesn't check spent flags, the caller must check it. -bool blockchain_storage::check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const std::vector& output_keys_ptrs) const -{ - if (txin.key_offsets.size() != output_keys_ptrs.size()) - { - LOG_PRINT_L0("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys_ptrs.size()); - return false; - } - - return check_input_signature(tx, in_index, /*txin.key_offsets,*/ txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs); -} -//------------------------------------------------------------------ -bool blockchain_storage::check_input_signature(const transaction& tx, - size_t in_index, - uint64_t in_amount, - const crypto::key_image& in_k_image, - const std::vector& in_etc_details, - const crypto::hash& tx_prefix_hash, - const std::vector& sig, - const std::vector& output_keys_ptrs) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_val_sig); - - if(m_is_in_checkpoint_zone) - return true; - - if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) - { - // check attachments, mentioned directly in this input - bool r = validate_attachment_info(in_etc_details, tx.attachment, in_index != tx.vin.size() - 1); // attachment info can be omitted for all inputs, except the last one - CHECK_AND_ASSERT_MES(r, false, "Failed to validate attachments in tx " << tx_prefix_hash << ": incorrect extra_attachment_info in etc_details in input #" << in_index); - } - else - { - // make sure normal tx does not have extra_attachment_info in etc_details - CHECK_AND_ASSERT_MES(!have_type_in_variant_container(in_etc_details), false, "Incorrect using of extra_attachment_info in etc_details in input #" << in_index << " for tx " << tx_prefix_hash); - } - - // check signatures - size_t expected_signatures_count = output_keys_ptrs.size(); - bool need_to_check_extra_sign = false; - if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) - { - expected_signatures_count++; - need_to_check_extra_sign = true; - } - - CHECK_AND_ASSERT_MES(expected_signatures_count == sig.size(), false, "internal error: tx signatures count=" << sig.size() << " mismatch with outputs keys count for inputs=" << expected_signatures_count); - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, in_index, tx_prefix_hash); - CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "failed to prepare_prefix_hash_for_sign"); - - LOG_PRINT_L4("CHECK RING SIGNATURE: tx_prefix_hash " << tx_prefix_hash - << "tx_hash_for_signature" << tx_hash_for_signature - << "in_k_image" << in_k_image - << "key_ptr:" << *output_keys_ptrs[0] - << "signature:" << sig[0]); - bool r = crypto::validate_key_image(in_k_image); - CHECK_AND_ASSERT_MES(r, false, "key image for input #" << in_index << " is invalid: " << in_k_image); - - r = crypto::check_ring_signature(tx_hash_for_signature, in_k_image, output_keys_ptrs, sig.data()); - CHECK_AND_ASSERT_MES(r, false, "failed to check ring signature for input #" << in_index << ENDL << dump_ring_sig_data(tx_hash_for_signature, in_k_image, output_keys_ptrs, sig)); - if (need_to_check_extra_sign) - { - //here we check extra signature to validate that transaction was finalized by authorized subject - r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), sig.back()); - CHECK_AND_ASSERT_MES(r, false, "failed to check extra signature for last input with TX_FLAG_SIGNATURE_MODE_SEPARATE"); - } - - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_ch_in_val_sig); - return r; -} -//------------------------------------------------------------------ -// Note: this function doesn't check spent flags by design (to be able to use either for main chain and alt chains). -// The caller MUST check spent flags. -bool blockchain_storage::check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const transaction& source_tx, size_t out_n) const -{ -#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, "ms input check failed: ms_id: " << txin.multisig_out_id << ", input #" << in_index << " in tx " << tx_prefix_hash << ", refers to ms output #" << out_n << " in source tx " << get_transaction_hash(source_tx) << ENDL << msg) - CRITICAL_REGION_LOCAL(m_read_lock); - - uint64_t unlock_time = get_tx_unlock_time(source_tx, out_n); - LOC_CHK(is_tx_spendtime_unlocked(unlock_time), "Source transaction is LOCKED! unlock_time: " << unlock_time << ", now is " << m_core_runtime_config.get_core_time() << ", blockchain size is " << get_current_blockchain_size()); - - LOC_CHK(source_tx.vout.size() > out_n, "internal error: out_n==" << out_n << " is out-of-bounds of source_tx.vout, size=" << source_tx.vout.size()); - const tx_out& source_tx_out = source_tx.vout[out_n]; - const txout_multisig& source_ms_out_target = boost::get(source_tx_out.target); - - LOC_CHK(txin.sigs_count == source_ms_out_target.minimum_sigs, - "ms input's sigs_count (" << txin.sigs_count << ") does not match to ms output's minimum signatures expected (" << source_ms_out_target.minimum_sigs << ")" - << ", source_tx_out.amount=" << print_money(source_tx_out.amount) - << ", txin.amount = " << print_money(txin.amount)); - - LOC_CHK(source_tx_out.amount == txin.amount, - "amount missmatch" - << ", source_tx_out.amount=" << print_money(source_tx_out.amount) - << ", txin.amount = " << print_money(txin.amount)); - - if (m_is_in_checkpoint_zone) - return true; - - if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) - { - // check attachments, mentioned directly in this input - bool r = validate_attachment_info(txin.etc_details, tx.attachment, in_index != tx.vin.size() - 1); // attachment info can be omitted for all inputs, except the last one - LOC_CHK(r, "Failed to validate attachments in tx " << tx_prefix_hash << ": incorrect extra_attachment_info in etc_details in input #" << in_index); - } - else - { - // make sure normal tx does not have extra_attachment_info in etc_details - LOC_CHK(!have_type_in_variant_container(txin.etc_details), "Incorrect using of extra_attachment_info in etc_details in input #" << in_index << " for tx " << tx_prefix_hash); - } - - LOC_CHK(tx.signatures.size() > in_index, "ms input index is out of signatures container bounds, tx.signatures.size() = " << tx.signatures.size()); - const std::vector& input_signatures = tx.signatures[in_index]; - - size_t expected_signatures_count = txin.sigs_count; - bool need_to_check_extra_sign = false; - if (get_tx_flags(tx)&TX_FLAG_SIGNATURE_MODE_SEPARATE && in_index == tx.vin.size() - 1) // last input in TX_FLAG_SIGNATURE_MODE_SEPARATE must contain one more signature to ensure that tx was completed by an authorized subject - { - expected_signatures_count++; - need_to_check_extra_sign = true; - } - - LOC_CHK(expected_signatures_count == input_signatures.size(), "Invalid input's signatures count: " << input_signatures.size() << ", expected: " << expected_signatures_count); - - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, in_index, tx_prefix_hash); - LOC_CHK(tx_hash_for_signature != null_hash, "prepare_prefix_hash_for_sign failed"); - - LOC_CHK(txin.sigs_count <= source_ms_out_target.keys.size(), "source tx invariant failed: ms output's minimum sigs == ms input's sigs_count (" << txin.sigs_count << ") is GREATHER than keys.size() = " << source_ms_out_target.keys.size()); // NOTE: sig_count == minimum_sigs as checked above - size_t out_key_index = 0; // index in source_ms_out_target.keys - for (size_t i = 0; i != txin.sigs_count; /* nothing */) - { - // if we run out of keys for this signature, then it's invalid signature - LOC_CHK(out_key_index < source_ms_out_target.keys.size(), "invalid signature #" << i << ": " << input_signatures[i]); - - // check signature #i against ms output key #out_key_index - if (crypto::check_signature(tx_hash_for_signature, source_ms_out_target.keys[out_key_index], input_signatures[i])) - { - // match: go for the next signature and the next key - i++; - out_key_index++; - } - else - { - // missmatch: go for the next key for this signature - out_key_index++; - } - } - if (need_to_check_extra_sign) - { - //here we check extra signature to validate that transaction was finilized by authorized subject - bool r = crypto::check_signature(tx_prefix_hash, get_tx_pub_key_from_extra(tx), tx.signatures[in_index].back()); - LOC_CHK(r, "failed to check extra signature for last out with TX_FLAG_SIGNATURE_MODE_SEPARATE"); - } - - return true; -#undef LOC_CHK -} - -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - auto multisig_ptr = m_db_multisig_outs.find(txin.multisig_out_id); - CHECK_AND_ASSERT_MES(multisig_ptr, false, "Unable to find txin.multisig_out_id=" << txin.multisig_out_id << " for ms input #" << in_index << " in tx " << tx_prefix_hash); - - const crypto::hash& source_tx_id = multisig_ptr->tx_id; // source tx hash - size_t n = multisig_ptr->out_no; // index of multisig output in source tx - -#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, "ms input check failed: ms_id: " << txin.multisig_out_id << ", input #" << in_index << " in tx " << tx_prefix_hash << ", refers to ms output #" << n << " in source tx " << source_tx_id << ENDL << msg) - - LOC_CHK(multisig_ptr->spent_height == 0, "ms output is already spent on height " << multisig_ptr->spent_height); - - auto source_tx_ptr = m_db_transactions.find(source_tx_id); - LOC_CHK(source_tx_ptr, "Can't find source transaction"); - LOC_CHK(source_tx_ptr->tx.vout.size() > n, "ms output index is incorrect, source tx's vout size is " << source_tx_ptr->tx.vout.size()); - LOC_CHK(source_tx_ptr->tx.vout[n].target.type() == typeid(txout_multisig), "ms output has wrong type, txout_multisig expected"); - LOC_CHK(source_tx_ptr->m_spent_flags.size() > n, "Internal error, m_spent_flags size (" << source_tx_ptr->m_spent_flags.size() << ") less then expected, n: " << n); - LOC_CHK(source_tx_ptr->m_spent_flags[n] == false, "Internal error, ms output is already spent"); // should never happen as multisig_ptr->spent_height is checked above - - if (!check_ms_input(tx, in_index, txin, tx_prefix_hash, sig, source_tx_ptr->tx, n)) - return false; - - max_related_block_height = source_tx_ptr->m_keeper_block_height; - - return true; -#undef LOC_CHK -} -//------------------------------------------------------------------ -bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - //TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop); - - std::vector output_keys; - scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex); - uint64_t source_max_unlock_time_for_pos_coinbase_dummy = AUTO_VAL_INIT(source_max_unlock_time_for_pos_coinbase_dummy); - if (!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase_dummy, scan_contex)) - { - LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")"); - return false; - } - - CHECK_AND_ASSERT_THROW_MES(scan_contex.htlc_outs.size() == 1, "htlc output not found for input, tx: " << get_transaction_hash(tx)); - const txout_htlc& related_out = *scan_contex.htlc_outs.begin(); - bool use_sha256 = !(related_out.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK); - if (use_sha256) - { - //doing sha256 hash - crypto::hash sha256 = crypto::sha256_hash(txin.hltc_origin.data(), txin.hltc_origin.size()); - CHECK_AND_ASSERT_THROW_MES(sha256 == related_out.htlc_hash, "htlc hash missmatched for tx: " << get_transaction_hash(tx) - << " calculated hash: " << sha256 << " expected hash(related_out.htlc_hash): " << related_out.htlc_hash); - } - else - { - //doing RIPEMD160 - crypto::hash160 ripemd160 = crypto::RIPEMD160_hash(txin.hltc_origin.data(), txin.hltc_origin.size()); - crypto::hash160 expected_ripemd160 = *(crypto::hash160*)&related_out.htlc_hash; - CHECK_AND_ASSERT_THROW_MES(ripemd160 == expected_ripemd160, "htlc hash missmatched for tx: " << get_transaction_hash(tx) - << " calculated hash: " << ripemd160 << " expected hash(related_out.htlc_hash): " << expected_ripemd160); - } - - - //TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_ch_in_get_keys_loop); - - - - std::vector output_keys_ptrs; - output_keys_ptrs.reserve(output_keys.size()); - for (auto& ptr : output_keys) - output_keys_ptrs.push_back(&ptr); - - CHECK_AND_ASSERT_THROW_MES(output_keys_ptrs.size() == 1, "Internal error: output_keys_ptrs.size() is not equal 1 for HTLC"); - - return check_input_signature(tx, in_index, txin.amount, txin.k_image, txin.etc_details, tx_prefix_hash, sig, output_keys_ptrs); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_adjusted_time() const -{ - //TODO: add collecting median time - return m_core_runtime_config.get_core_time(); -} -//------------------------------------------------------------------ -std::vector blockchain_storage::get_last_n_blocks_timestamps(size_t n) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - std::vector timestamps; - size_t offset = m_db_blocks.size() <= n ? 0 : m_db_blocks.size() - n; - for (; offset != m_db_blocks.size(); ++offset) - timestamps.push_back(m_db_blocks[offset]->bl.timestamp); - return timestamps; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_last_n_blocks_timestamps_median(size_t n) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto it = m_timestamps_median_cache.find(n); - if (it != m_timestamps_median_cache.end()) - return it->second; - - std::vector timestamps = get_last_n_blocks_timestamps(n); - uint64_t median_res = epee::misc_utils::median(timestamps); - m_timestamps_median_cache[n] = median_res; - return median_res; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_last_timestamps_check_window_median() const -{ - return get_last_n_blocks_timestamps_median(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW); -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_tx_expiration_median() const -{ - return get_last_n_blocks_timestamps_median(TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW); -} -//------------------------------------------------------------------ -bool blockchain_storage::check_block_timestamp_main(const block& b) const -{ - if(b.timestamp > get_adjusted_time() + CURRENCY_BLOCK_FUTURE_TIME_LIMIT) - { - LOG_PRINT_L0("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + " + epee::misc_utils::get_time_interval_string(CURRENCY_BLOCK_FUTURE_TIME_LIMIT)); - return false; - } - if (is_pos_block(b) && b.timestamp > get_adjusted_time() + CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT) - { - LOG_PRINT_L0("Timestamp of PoS block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + " + epee::misc_utils::get_time_interval_string(CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT) + ": " << get_adjusted_time() << " (" << b.timestamp - get_adjusted_time() << ")"); - return false; - } - - std::vector timestamps = get_last_n_blocks_timestamps(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW); - - return check_block_timestamp(std::move(timestamps), b); -} -//------------------------------------------------------------------ -bool blockchain_storage::check_block_timestamp(std::vector timestamps, const block& b) const -{ - if(timestamps.size() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) - return true; - - if (is_pos_block(b) && b.timestamp > get_adjusted_time() + CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT) - { - LOG_PRINT_L0("Timestamp of PoS block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + " + epee::misc_utils::get_time_interval_string(CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT) + ": " << get_adjusted_time() << " (" << b.timestamp - get_adjusted_time() << ")"); - return false; - } - - uint64_t median_ts = epee::misc_utils::median(timestamps); - - if(b.timestamp < median_ts) - { - LOG_PRINT_L0("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts); - return false; - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_tx_expired(const transaction& tx) const -{ - return currency::is_tx_expired(tx, get_tx_expiration_median()); -} -//------------------------------------------------------------------ -std::shared_ptr blockchain_storage::find_key_image_and_related_tx(const crypto::key_image& ki, crypto::hash& id_result) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - auto ki_index_ptr = m_db_spent_keys.find(ki); - if (!ki_index_ptr) - return std::shared_ptr(); - - auto block_entry = m_db_blocks[*ki_index_ptr]; - if (!block_entry) - { - LOG_ERROR("Internal error: broken index, key image " << ki - << " reffered to height " << *ki_index_ptr << " but couldnot find block on this height"); - return std::shared_ptr(); - } - - //look up coinbase - for (auto& in: block_entry->bl.miner_tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - if (boost::get(in).k_image == ki) - { - id_result = get_transaction_hash(block_entry->bl.miner_tx); - return get_tx_chain_entry(id_result); - } - } - } - //lookup transactions - for (auto& tx_id : block_entry->bl.tx_hashes) - { - auto tx_chain_entry = get_tx_chain_entry(tx_id); - if (!tx_chain_entry) - { - LOG_ERROR("Internal error: broken index, tx_id " << tx_id - << " not found in tx index, block no " << *ki_index_ptr); - return std::shared_ptr(); - } - for (auto& in : tx_chain_entry->tx.vin) - { - if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc)) - { - if (get_to_key_input_from_txin_v(in).k_image == ki) - { - id_result = get_transaction_hash(tx_chain_entry->tx); - return tx_chain_entry; - } - } - } - } - return std::shared_ptr(); -} -//------------------------------------------------------------------ -bool blockchain_storage::prune_aged_alt_blocks() -{ - CRITICAL_REGION_LOCAL(m_read_lock); - CRITICAL_REGION_LOCAL1(m_alternative_chains_lock); - uint64_t current_height = get_current_blockchain_size(); - - size_t count_to_delete = 0; - if(m_alternative_chains.size() > m_core_runtime_config.max_alt_blocks) - count_to_delete = m_alternative_chains.size() - m_core_runtime_config.max_alt_blocks; - - std::map alts_to_delete; - - for(auto it = m_alternative_chains.begin(); it != m_alternative_chains.end();) - { - if (current_height > it->second.height && current_height - it->second.height > CURRENCY_ALT_BLOCK_LIVETIME_COUNT) - { - do_erase_altblock(it++); - } - else - { - if (count_to_delete) - { - if (!alts_to_delete.size()) - alts_to_delete[it->second.timestamp] = it; - else - { - if (it->second.timestamp >= alts_to_delete.rbegin()->first) - alts_to_delete[it->second.timestamp] = it; - - if (alts_to_delete.size() > count_to_delete) - alts_to_delete.erase(alts_to_delete.begin()); - } - } - - ++it; - } - } - //now, if there was count_to_delete we should erase most oldest entries of altblocks - for (auto& itd : alts_to_delete) - { - m_alternative_chains.erase(itd.second); - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain) const -{ - //validate - wide_difficulty_type basic_diff = get_next_diff_conditional(true); - return validate_pos_block(b, basic_diff, id, for_altchain); -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain) const -{ - uint64_t coin_age = 0; - wide_difficulty_type final_diff = 0; - crypto::hash proof_hash = null_hash; - return validate_pos_block(b, basic_diff, coin_age, final_diff, proof_hash, id, for_altchain); -} -//------------------------------------------------------------------ -#define POS_STAKE_TO_DIFF_COEFF 100 // total_coins_in_minting * POS_STAKE_TO_DIFF_COEFF =~ pos_difficulty - -void blockchain_storage::get_pos_mining_estimate(uint64_t amount_coins, - uint64_t time, - uint64_t& estimate_result, - uint64_t& pos_diff_and_amount_rate, - std::vector& days) const -{ - estimate_result = 0; - if (!is_pos_allowed()) - return; - - // new algo - // 1. get (CURRENCY_BLOCKS_PER_DAY / 2) PoS blocks (a day in case of PoS/PoW==50/50) - // 2. calculate total minted money C (normalized for 1 day interval) and average difficulty D (based on last (CURRENCY_BLOCKS_PER_DAY / 2) PoS blocks) - // 3. calculate total coins participating in PoS minting as M = D / pos_diff_ratio - // 4. calculate owner's money proportion as P = amount_coins / (M + amount_coins) - // 5. estimate PoS minting income for this day as I = C * P - // 6. amount_coins += I, goto 3 - - epee::critical_region_t read_lock_region(m_read_lock); - - size_t estimated_pos_blocks_count_per_day = CURRENCY_BLOCKS_PER_DAY / 2; // 50% of all blocks in a perfect world - - uint64_t pos_ts_min = UINT64_MAX, pos_ts_max = 0; - size_t pos_blocks_count = 0; - uint64_t pos_total_minted_money = 0; - wide_difficulty_type pos_avg_difficulty = 0; - // scan blockchain backward for PoS blocks and collect data - for (size_t h = m_db_blocks.size() - 1; h != 0 && pos_blocks_count < estimated_pos_blocks_count_per_day; --h) - { - auto bei = m_db_blocks[h]; - if (!is_pos_block(bei->bl)) - continue; - uint64_t ts = get_block_datetime(bei->bl); - pos_ts_min = min(pos_ts_min, ts); - pos_ts_max = max(pos_ts_max, ts); - pos_total_minted_money += get_reward_from_miner_tx(bei->bl.miner_tx); - pos_avg_difficulty += bei->difficulty; - ++pos_blocks_count; - } - if (pos_blocks_count < estimated_pos_blocks_count_per_day || pos_ts_max <= pos_ts_min) - return; // too little pos blocks found or invalid ts - pos_avg_difficulty /= pos_blocks_count; - uint64_t found_blocks_interval = pos_ts_max - pos_ts_min; // will be close to 24 * 60 * 60 in case of PoS/PoW == 50/50 - uint64_t pos_last_day_total_minted_money = pos_total_minted_money * (24 * 60 * 60) / found_blocks_interval; // total minted money normalized for 1 day interval - - uint64_t estimated_total_minting_coins = static_cast(pos_avg_difficulty / POS_STAKE_TO_DIFF_COEFF); - - uint64_t current_amount = amount_coins; - uint64_t days_count = time / (60 * 60 * 24); - for (uint64_t d = 0; d != days_count; d++) - { - double user_minting_coins_proportion = static_cast(current_amount) / (estimated_total_minting_coins + current_amount); - current_amount += pos_last_day_total_minted_money * user_minting_coins_proportion; - days.push_back(current_amount); - } - estimate_result = current_amount; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const -{ - uint64_t block_height = m_db_blocks.size(); - return validate_tx_for_hardfork_specific_terms(tx, tx_id, block_height); -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const -{ - auto is_allowed_before_hardfork2 = [&](const payload_items_v& el) -> bool - { - CHECK_AND_ASSERT_MES(el.type() != typeid(tx_payer), false, "tx " << tx_id << " contains tx_payer which is not allowed on height " << block_height); - CHECK_AND_ASSERT_MES(el.type() != typeid(tx_receiver), false, "tx " << tx_id << " contains tx_receiver which is not allowed on height " << block_height); - CHECK_AND_ASSERT_MES(el.type() != typeid(extra_alias_entry), false, "tx " << tx_id << " contains extra_alias_entry which is not allowed on height " << block_height); - return true; - }; - - auto is_allowed_before_hardfork1 = [&](const payload_items_v& el) -> bool - { - CHECK_AND_ASSERT_MES(el.type() != typeid(etc_tx_details_unlock_time2), false, "tx " << tx_id << " contains etc_tx_details_unlock_time2 which is not allowed on height " << block_height); - return true; - }; - - bool var_is_after_hardfork_1_zone = is_after_hardfork_1_zone(block_height); - bool var_is_after_hardfork_2_zone = is_after_hardfork_2_zone(block_height); - bool var_is_after_hardfork_3_zone = is_after_hardfork_3_zone(block_height); - - //inputs - for (const auto in : tx.vin) - { - if (in.type() == typeid(txin_htlc)) - { - if (!var_is_after_hardfork_3_zone) - return false; - } - } - //outputs - for (const auto out : tx.vout) - { - if (out.target.type() == typeid(txout_htlc)) - { - if (!var_is_after_hardfork_3_zone) - return false; - } - } - - //extra - for (const auto el : tx.extra) - { - if (!var_is_after_hardfork_1_zone && !is_allowed_before_hardfork1(el)) - return false; - if (!var_is_after_hardfork_2_zone && !is_allowed_before_hardfork2(el)) - return false; - } - - //attachments - for (const auto el : tx.attachment) - { - if (!var_is_after_hardfork_2_zone && !is_allowed_before_hardfork2(el)) - return false; - } - - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const -{ - uint64_t major_unlock_time = get_tx_x_detail(miner_tx); - if (major_unlock_time) - { - //if there was etc_tx_details_unlock_time present in tx, then ignore etc_tx_details_unlock_time2 - if (major_unlock_time < source_max_unlock_time) - return false; - else - return true; - } - - CHECK_AND_ASSERT_MES(get_block_height(miner_tx) > m_core_runtime_config.hard_fork_01_starts_after_height, false, "error in block [" << get_block_height(miner_tx) << "] etc_tx_details_unlock_time2 can exist only after hard fork point : " << m_core_runtime_config.hard_fork_01_starts_after_height); - - //etc_tx_details_unlock_time2 can be kept only after hard_fork_1 point - etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2); - get_type_in_variant_container(miner_tx.extra, ut2); - CHECK_AND_ASSERT_MES(ut2.unlock_time_array.size() == miner_tx.vout.size(), false, "ut2.unlock_time_array.size()<" << ut2.unlock_time_array.size() - << "> != miner_tx.vout.size()<" << miner_tx.vout.size() << ">"); - - uint64_t amount_of_coins_in_unlock_in_range = 0; // amount of outputs locked for at least the same time - - for (uint64_t i = 0; i != miner_tx.vout.size(); i++) - { - uint64_t unlock_value = ut2.unlock_time_array[i]; - CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase"); - if (unlock_value >= source_max_unlock_time) - amount_of_coins_in_unlock_in_range += miner_tx.vout[i].amount; - } - - if (amount_of_coins_in_unlock_in_range >= staked_amount) - return true; - LOG_ERROR("amount_of_coins_in_unlock_in_range<" << amount_of_coins_in_unlock_in_range << "> is less then staked_amount<" << staked_amount); - return false; - -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_pos_block(const block& b, - wide_difficulty_type basic_diff, - uint64_t& amount, - wide_difficulty_type& final_diff, - crypto::hash& proof_hash, - const crypto::hash& id, - bool for_altchain, - const alt_chain_type& alt_chain, - uint64_t split_height - )const -{ - bool is_pos = is_pos_block(b); - CHECK_AND_ASSERT_MES(is_pos, false, "is_pos_block() returned false validate_pos_block()"); - - //check timestamp - CHECK_AND_ASSERT_MES(b.timestamp%POS_SCAN_STEP == 0, false, "wrong timestamp in PoS block(b.timestamp%POS_SCAN_STEP == 0), b.timestamp = " <(b.miner_tx.vin[1]); - if (!for_altchain && have_tx_keyimg_as_spent(in_to_key.k_image)) - { - LOG_PRINT_L0("Key image in coinstake already spent in blockchain: " << string_tools::pod_to_hex(in_to_key.k_image)); - return false; - } - - - // the following check is de-facto not applicable since 2021-10, but left intact to avoid consensus issues - // PoS blocks don't use etc_tx_time anymore to store actual timestamp; instead, they use tx_service_attachment in mining tx extra - uint64_t actual_ts = get_actual_timestamp(b); - if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) || - (actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) - ) - { - LOG_PRINT_L0("PoS block actual timestamp " << actual_ts << " differs from b.timestamp " << b.timestamp << " by " << ((int64_t)actual_ts - (int64_t)b.timestamp) << " s, it's more than allowed " << POS_MAX_ACTUAL_TIMESTAMP_TO_MINED << " s."); - return false; - } - - //check kernel - stake_kernel sk = AUTO_VAL_INIT(sk); - - stake_modifier_type sm = AUTO_VAL_INIT(sm); - bool r = build_stake_modifier(sm, alt_chain, split_height); - CHECK_AND_ASSERT_MES(r, false, "failed to build_stake_modifier"); - amount = 0; - r = build_kernel(b, sk, amount, sm); - CHECK_AND_ASSERT_MES(r, false, "failed to build kernel_stake"); - CHECK_AND_ASSERT_MES(amount!=0, false, "failed to build kernel_stake, amount == 0"); - - proof_hash = crypto::cn_fast_hash(&sk, sizeof(sk)); - - LOG_PRINT_L2("STAKE KERNEL for bl ID: " << get_block_hash(b) << ENDL - << print_stake_kernel_info(sk) - << "amount: " << print_money(amount) << ENDL - << "kernel_hash: " << proof_hash); - - - final_diff = basic_diff / amount; - if (!check_hash(proof_hash, final_diff)) - { - LOG_ERROR("PoS difficulty check failed for block " << get_block_hash(b) << " @ HEIGHT " << get_block_height(b) << ":" << ENDL - << " basic_diff: " << basic_diff << ENDL - << " final_diff: " << final_diff << ENDL - << " amount: " << print_money_brief(amount) << ENDL - << " kernel_hash: " << proof_hash << ENDL - ); - return false; - } - - //validate signature - uint64_t max_related_block_height = 0; - const txin_to_key& coinstake_in = boost::get(b.miner_tx.vin[1]); - CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "PoS block's miner_tx has incorrect signatures size = " << b.miner_tx.signatures.size() << ", block_id = " << get_block_hash(b)); - if (!for_altchain) - { - // Do coinstake input validation for main chain only. - // Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs() - uint64_t source_max_unlock_time_for_pos_coinbase = 0; - r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b)); - - if (get_block_height(b) > m_core_runtime_config.hard_fork_01_starts_after_height) - { - uint64_t last_pow_h = get_last_x_block_height(false); - CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")"); - //let's check that coinbase amount and unlock time - r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase); - CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b) - << "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase); - } - else - { - CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")"); - } - } - - uint64_t block_height = for_altchain ? split_height + alt_chain.size() : m_db_blocks.size(); - uint64_t coinstake_age = block_height - max_related_block_height - 1; - - CHECK_AND_ASSERT_MES(coinstake_age >= m_core_runtime_config.min_coinstake_age, false, - "Coinstake age is: " << coinstake_age << " is less than minimum expected: " << m_core_runtime_config.min_coinstake_age); - - return true; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_adjusted_cumulative_difficulty_for_next_pos(wide_difficulty_type next_diff) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - wide_difficulty_type last_pow_diff = 0; - wide_difficulty_type last_pos_diff = 0; - uint64_t sz = m_db_blocks.size(); - if (!sz) - return next_diff; - - uint64_t i = sz - 1; - - for (; i < sz && !(last_pow_diff && last_pos_diff); i--) - { - if (is_pos_block(m_db_blocks[i]->bl)) - { - if (!last_pos_diff) - { - last_pos_diff = m_db_blocks[i]->difficulty; - } - }else - { - if (!last_pow_diff) - { - last_pow_diff = m_db_blocks[i]->difficulty; - } - } - } - if (!last_pos_diff) - return next_diff; - return next_diff*last_pow_diff/last_pos_diff; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain_type& alt_chain, uint64_t block_height, wide_difficulty_type next_diff, uint64_t connection_height) const -{ - - wide_difficulty_type last_pow_diff = 0; - wide_difficulty_type last_pos_diff = 0; - - for (auto it = alt_chain.rbegin(); it != alt_chain.rend() && !(last_pos_diff && last_pow_diff); it++) - { - if (is_pos_block((*it)->second.bl )) - { - if (!last_pos_diff) - { - last_pos_diff = (*it)->second.difficulty; - } - } - else - { - if (!last_pow_diff) - { - last_pow_diff = (*it)->second.difficulty; - } - } - } - - CRITICAL_REGION_LOCAL(m_read_lock); - for (uint64_t h = connection_height - 1; h != 0 && !(last_pos_diff && last_pow_diff); --h) - { - if (is_pos_block(m_db_blocks[h]->bl)) - { - if (!last_pos_diff) - { - last_pos_diff = m_db_blocks[h]->difficulty; - } - } - else - { - if (!last_pow_diff) - { - last_pow_diff = m_db_blocks[h]->difficulty; - } - } - } - if (!last_pos_diff) - return next_diff; - return next_diff*last_pow_diff / last_pos_diff; -} -//------------------------------------------------------------------ -uint64_t blockchain_storage::get_last_x_block_height(bool pos) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint64_t sz = m_db_blocks.size(); - if (!sz) - return 0; - - uint64_t i = sz-1; - - for (; i < sz; i--) - { - if (is_pos_block(m_db_blocks[i]->bl) == pos) - return i; - } - return 0; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_last_alt_x_block_cumulative_precise_adj_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos) const -{ - wide_difficulty_type res = 0; - get_last_alt_x_block_cumulative_precise_difficulty(alt_chain, block_height, pos, res); - return res; -} -//------------------------------------------------------------------ -wide_difficulty_type blockchain_storage::get_last_alt_x_block_cumulative_precise_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos, wide_difficulty_type& cumulative_diff_precise_adj) const -{ - uint64_t main_chain_first_block = block_height; - for (auto it = alt_chain.rbegin(); it != alt_chain.rend(); it++) - { - if (is_pos_block((*it)->second.bl) == pos) - { - cumulative_diff_precise_adj = (*it)->second.cumulative_diff_precise_adjusted; - return (*it)->second.cumulative_diff_precise; - } - main_chain_first_block = (*it)->second.height - 1; - } - - - CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(main_chain_first_block < m_db_blocks.size(), false, "Intrnal error: main_chain_first_block(" << main_chain_first_block << ") < m_blocks.size() (" << m_db_blocks.size() << ")"); - - for (uint64_t i = main_chain_first_block; i != 0; i--) - { - if (is_pos_block(m_db_blocks[i]->bl) == pos) - { - cumulative_diff_precise_adj = m_db_blocks[i]->cumulative_diff_precise_adjusted; - return m_db_blocks[i]->cumulative_diff_precise; - } - } - cumulative_diff_precise_adj = 0; - return 0; -} -//------------------------------------------------------------------ -bool get_tx_from_cache(const crypto::hash& tx_id, transactions_map& tx_cache, transaction& tx, size_t& blob_size, uint64_t& fee) -{ - auto it = tx_cache.find(tx_id); - if (it == tx_cache.end()) - return false; - - tx = it->second; - blob_size = get_object_blobsize(tx); - fee = get_tx_fee(tx); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc) -{ - TIME_MEASURE_START_PD_MS(block_processing_time_0_ms); - CRITICAL_REGION_LOCAL(m_read_lock); - TIME_MEASURE_START_PD(block_processing_time_1); - if(bl.prev_id != get_top_block_id()) - { - LOG_PRINT_L0("Block with id: " << id << ENDL - << "have wrong prev_id: " << bl.prev_id << ENDL - << "expected: " << get_top_block_id()); - return false; - } - - if(!check_block_timestamp_main(bl)) - { - LOG_PRINT_L0("Block with id: " << id << ENDL - << "have invalid timestamp: " << bl.timestamp); - //add_block_as_invalid(bl, id);//do not add blocks to invalid storage befor proof of work check was passed - bvc.m_verification_failed = true; - return false; - } - - if (m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_size())) - { - m_is_in_checkpoint_zone = true; - if (!m_checkpoints.check_block(get_current_blockchain_size(), id)) - { - LOG_ERROR("CHECKPOINT VALIDATION FAILED"); - bvc.m_verification_failed = true; - return false; - } - } - else - m_is_in_checkpoint_zone = false; - - crypto::hash proof_hash = null_hash; - uint64_t pos_coinstake_amount = 0; - wide_difficulty_type this_coin_diff = 0; - bool is_pos_bl = is_pos_block(bl); - //check if PoS allowed in this height - CHECK_AND_ASSERT_MES_CUSTOM(!(is_pos_bl && m_db_blocks.size() < m_core_runtime_config.pos_minimum_heigh), false, bvc.m_verification_failed = true, "PoS block not allowed on height " << m_db_blocks.size()); - - //check proof of work - TIME_MEASURE_START_PD(target_calculating_time_2); - wide_difficulty_type current_diffic = get_next_diff_conditional(is_pos_bl); - CHECK_AND_ASSERT_MES_CUSTOM(current_diffic, false, bvc.m_verification_failed = true, "!!!!!!!!! difficulty overhead !!!!!!!!!"); - TIME_MEASURE_FINISH_PD(target_calculating_time_2); - - TIME_MEASURE_START_PD(longhash_calculating_time_3); - if (is_pos_bl) - { - bool r = validate_pos_block(bl, current_diffic, pos_coinstake_amount, this_coin_diff, proof_hash, id, false); - CHECK_AND_ASSERT_MES_CUSTOM(r, false, bvc.m_verification_failed = true, "validate_pos_block failed!!"); - } - else - { - - proof_hash = get_block_longhash(bl); - - if (!check_hash(proof_hash, current_diffic)) - { - LOG_ERROR("Block with id: " << id << ENDL - << "PoW hash: " << proof_hash << ENDL - << "nonce: " << bl.nonce << ENDL - << "header_mining_hash: " << get_block_header_mining_hash(bl) << ENDL - << "expected difficulty: " << current_diffic); - bvc.m_verification_failed = true; - return false; - } - } - TIME_MEASURE_FINISH_PD(longhash_calculating_time_3); - - size_t aliases_count_befor_block = m_db_aliases.size(); - - if (!prevalidate_miner_transaction(bl, m_db_blocks.size(), is_pos_bl)) - { - LOG_PRINT_L0("Block with id: " << id - << " failed to pass prevalidation"); - bvc.m_verification_failed = true; - return false; - } - size_t cumulative_block_size = 0; - size_t coinbase_blob_size = get_object_blobsize(bl.miner_tx); - - /* - instead of complicated two-phase template construction and adjustment of cumulative size with block reward we - use CURRENCY_COINBASE_BLOB_RESERVED_SIZE as penalty-free coinbase transaction reservation. - */ - if (coinbase_blob_size > CURRENCY_COINBASE_BLOB_RESERVED_SIZE) - { - cumulative_block_size += coinbase_blob_size; - LOG_PRINT_CYAN("Big coinbase transaction detected: coinbase_blob_size = " << coinbase_blob_size, LOG_LEVEL_0); - } - - std::vector block_fees; - block_fees.reserve(bl.tx_hashes.size()); - //process transactions - TIME_MEASURE_START_PD(all_txs_insert_time_5); - if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_block_datetime(bl))) - { - LOG_PRINT_L0("Block with id: " << id << " failed to add transaction to blockchain storage"); - bvc.m_verification_failed = true; - return false; - } - //preserve extra data to support alt pos blocks validation - //amount = > gindex_increment; a map to store how many txout_to_key outputs with such amount this block has in its transactions(including miner tx) - std::unordered_map gindices; - append_per_block_increments_for_tx(bl.miner_tx, gindices); - - - - size_t tx_processed_count = 0; - uint64_t fee_summary = 0; - uint64_t burned_coins = 0; - std::list block_summary_kimages; - - for(const crypto::hash& tx_id : bl.tx_hashes) - { - transaction tx; - size_t blob_size = 0; - uint64_t fee = 0; - - bool taken_from_cache = get_tx_from_cache(tx_id, bvc.m_onboard_transactions, tx, blob_size, fee); - bool taken_from_pool = m_tx_pool.take_tx(tx_id, tx, blob_size, fee); - if(!taken_from_cache && !taken_from_pool) - { - LOG_PRINT_L0("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id); - purge_block_data_from_blockchain(bl, tx_processed_count); - //add_block_as_invalid(bl, id); - bvc.m_verification_failed = true; - return false; - } - - if (!validate_tx_semantic(tx, blob_size)) - { - LOG_PRINT_L0("Block with id: " << id << " has at least one transaction with wrong semantic, tx_id: " << tx_id); - purge_block_data_from_blockchain(bl, tx_processed_count); - //add_block_as_invalid(bl, id); - bvc.m_verification_failed = true; - return false; - } - - append_per_block_increments_for_tx(tx, gindices); - - //If we under checkpoints, ring signatures should be pruned - if(m_is_in_checkpoint_zone) - { - tx.signatures.clear(); - tx.attachment.clear(); - } - TIME_MEASURE_START_PD(tx_add_one_tx_time); - TIME_MEASURE_START_PD(tx_check_inputs_time); - if(!check_tx_inputs(tx, tx_id)) - { - LOG_PRINT_L0("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - if (taken_from_pool) - { - bool add_res = m_tx_pool.add_tx(tx, tvc, true, true); - m_tx_pool.add_transaction_to_black_list(tx); - CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool"); - } - purge_block_data_from_blockchain(bl, tx_processed_count); - add_block_as_invalid(bl, id); - LOG_PRINT_L0("Block with id " << id << " added as invalid because of wrong inputs in transactions"); - bvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_time); - burned_coins += get_burned_amount(tx); - - TIME_MEASURE_START_PD(tx_prapare_append); - uint64_t current_bc_size = get_current_blockchain_size(); - uint64_t actual_timestamp = get_block_datetime(bl); - TIME_MEASURE_FINISH_PD(tx_prapare_append); - TIME_MEASURE_START_PD(tx_append_time); - if(!add_transaction_from_block(tx, tx_id, id, current_bc_size, actual_timestamp)) - { - LOG_PRINT_L0("Block " << id << " contains tx " << tx_id << " that can't be added to the blockchain storage"); - if (taken_from_pool) - { - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - bool add_res = m_tx_pool.add_tx(tx, tvc, true, true); - m_tx_pool.add_transaction_to_black_list(tx); - CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool"); - } - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(tx_append_time); - //LOG_PRINT_L0("APPEND_TX_TIME: " << m_performance_data.tx_append_time.get_last_val()); - TIME_MEASURE_FINISH_PD(tx_add_one_tx_time); - fee_summary += fee; - cumulative_block_size += blob_size; - ++tx_processed_count; - if (fee) - block_fees.push_back(fee); - - read_keyimages_from_tx(tx, block_summary_kimages); - } - TIME_MEASURE_FINISH_PD(all_txs_insert_time_5); - - TIME_MEASURE_START_PD(etc_stuff_6); - //check aliases count - if (m_db_aliases.size() - aliases_count_befor_block > MAX_ALIAS_PER_BLOCK) - { - LOG_PRINT_L0("Block with id: " << id - << " have registered too many aliases " << m_db_aliases.size() - aliases_count_befor_block << ", expected no more than " << MAX_ALIAS_PER_BLOCK); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - - uint64_t base_reward = 0; - boost::multiprecision::uint128_t already_generated_coins = m_db_blocks.size() ? m_db_blocks.back()->already_generated_coins:0; - if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins)) - { - LOG_PRINT_L0("Block with id: " << id - << " have wrong miner transaction"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - - //fill block_extended_info - block_extended_info bei = boost::value_initialized(); - bei.bl = bl; - bei.height = m_db_blocks.size(); - bei.block_cumulative_size = cumulative_block_size; - bei.difficulty = current_diffic; - if (is_pos_bl) - bei.stake_hash = proof_hash; - - ////////////////////////////////////////////////////////////////////////// - - //old style cumulative difficulty collecting - - //precise difficulty - difficulty used to calculate next difficulty - uint64_t last_x_h = get_last_x_block_height(is_pos_bl); - if (!last_x_h) - bei.cumulative_diff_precise = current_diffic; - else - bei.cumulative_diff_precise = m_db_blocks[last_x_h]->cumulative_diff_precise + current_diffic; - - if (m_db_blocks.size()) - { - bei.cumulative_diff_adjusted = m_db_blocks.back()->cumulative_diff_adjusted; - } - - //adjusted difficulty - difficulty used to switch blockchain - wide_difficulty_type cumulative_diff_delta = 0; - if (is_pos_bl) - cumulative_diff_delta = get_adjusted_cumulative_difficulty_for_next_pos(current_diffic); - else - cumulative_diff_delta = current_diffic; - - - size_t sequence_factor = get_current_sequence_factor(is_pos_bl); - if (bei.height >= m_core_runtime_config.pos_minimum_heigh) - cumulative_diff_delta = correct_difficulty_with_sequence_factor(sequence_factor, cumulative_diff_delta); - - if (bei.height > BLOCKCHAIN_HEIGHT_FOR_POS_STRICT_SEQUENCE_LIMITATION && is_pos_bl && sequence_factor > BLOCK_POS_STRICT_SEQUENCE_LIMIT) - { - LOG_PRINT_RED_L0("Block " << id << " @ " << bei.height << " has too big sequence factor: " << sequence_factor << ", rejected"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - - bei.cumulative_diff_adjusted += cumulative_diff_delta; - - ////////////////////////////////////////////////////////////////////////// - // rebuild cumulative_diff_precise_adjusted for whole period - wide_difficulty_type diff_precise_adj = correct_difficulty_with_sequence_factor(sequence_factor, current_diffic); - bei.cumulative_diff_precise_adjusted = last_x_h ? m_db_blocks[last_x_h]->cumulative_diff_precise_adjusted + diff_precise_adj : diff_precise_adj; - - ////////////////////////////////////////////////////////////////////////// - - //etc - if (already_generated_coins < burned_coins) - { - LOG_ERROR("Condition failed: already_generated_coins(" << already_generated_coins << ") >= burned_coins(" << burned_coins << ")"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - bei.already_generated_coins = already_generated_coins - burned_coins + base_reward; - - auto blocks_index_ptr = m_db_blocks_index.get(id); - if (blocks_index_ptr) - { - LOG_ERROR("block with id: " << id << " already in block indexes"); - purge_block_data_from_blockchain(bl, tx_processed_count); - bvc.m_verification_failed = true; - return false; - } - if (bei.height%ALIAS_MEDIAN_RECALC_INTERWAL) - { - bei.effective_tx_fee_median = get_tx_fee_median(); - } - else - { - if (bei.height == 0) - bei.effective_tx_fee_median = 0; - else - { - LOG_PRINT_L0("Recalculating median fee..."); - std::vector blocks_medians; - blocks_medians.reserve(ALIAS_COAST_PERIOD); - for (uint64_t i = bei.height - 1; i != 0 && ALIAS_COAST_PERIOD >= bei.height - i ; i--) - { - uint64_t i_median = m_db_blocks[i]->this_block_tx_fee_median; - if (i_median) - blocks_medians.push_back(i_median); - } - bei.effective_tx_fee_median = epee::misc_utils::median(blocks_medians); - LOG_PRINT_L0("Median fee recalculated for h = " << bei.height << " as " << print_money(bei.effective_tx_fee_median)); - } - } - if (block_fees.size()) - { - uint64_t block_fee_median = epee::misc_utils::median(block_fees); - bei.this_block_tx_fee_median = block_fee_median; - } - - m_db_blocks_index.set(id, bei.height); - push_block_to_per_block_increments(bei.height, gindices); - TIME_MEASURE_FINISH_PD(etc_stuff_6); - - - TIME_MEASURE_START_PD(insert_time_4); - m_db_blocks.push_back(bei); - TIME_MEASURE_FINISH_PD(insert_time_4); - TIME_MEASURE_FINISH_PD(block_processing_time_1); - TIME_MEASURE_FINISH_PD_MS(block_processing_time_0_ms); - - //print result - stringstream powpos_str_entry, timestamp_str_entry; - if (is_pos_bl) - { // PoS - int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here - int64_t ts_diff = actual_ts - m_core_runtime_config.get_core_time(); - powpos_str_entry << "PoS:\t" << proof_hash << ", stake amount: " << print_money_brief(pos_coinstake_amount) << ", final_difficulty: " << this_coin_diff; - timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast(bei.bl.timestamp) - actual_ts << ")"; - } - else - { // PoW - int64_t ts_diff = bei.bl.timestamp - static_cast(m_core_runtime_config.get_core_time()); - powpos_str_entry << "PoW:\t" << proof_hash; - timestamp_str_entry << ", block ts: " << bei.bl.timestamp << " (diff: " << std::showpos << ts_diff << "s)"; - } - //explanation of this code will be provided later with public announce - set_lost_tx_unmixable_for_height(bei.height); - - - LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED " << (is_pos_bl ? "[PoS]" : "[PoW]") << "["<< static_cast(bei.bl.major_version) << "." << static_cast(bei.bl.minor_version) << "] "<< " Sq: " << sequence_factor - << ENDL << "id:\t" << id << timestamp_str_entry.str() - << ENDL << powpos_str_entry.str() - << ENDL << "HEIGHT " << bei.height << ", difficulty: " << current_diffic << ", cumul_diff_precise: " << bei.cumulative_diff_precise << ", cumul_diff_adj: " << bei.cumulative_diff_adjusted << " (+" << cumulative_diff_delta << ")" - << ENDL << "block reward: " << print_money_brief(base_reward + fee_summary) << " (" << print_money_brief(base_reward) << " + " << print_money_brief(fee_summary) - << ")" << ", coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", tx_count: " << bei.bl.tx_hashes.size() - << ", timing: " << block_processing_time_0_ms << "ms" - << "(micrsec:" << block_processing_time_1 - << "(" << target_calculating_time_2 << "(" << m_performance_data.target_calculating_enum_blocks.get_last_val() << "/" << m_performance_data.target_calculating_calc.get_last_val() << ")" - << "/" << longhash_calculating_time_3 - << "/" << insert_time_4 - << "/" << all_txs_insert_time_5 - << "/" << etc_stuff_6 - << "))"); - - on_block_added(bei, id, block_summary_kimages); - - bvc.m_added_to_main_chain = true; - return true; -} -//------------------------------------------------------------------ -void blockchain_storage::on_block_added(const block_extended_info& bei, const crypto::hash& id, const std::list& bsk) -{ - update_next_comulative_size_limit(); - m_timestamps_median_cache.clear(); - m_tx_pool.on_blockchain_inc(bei.height, id, bsk); - - update_targetdata_cache_on_block_added(bei); - - TIME_MEASURE_START_PD(raise_block_core_event); - rise_core_event(CORE_EVENT_BLOCK_ADDED, void_struct()); - TIME_MEASURE_FINISH_PD(raise_block_core_event); - -} -//------------------------------------------------------------------ -void blockchain_storage::on_block_removed(const block_extended_info& bei) -{ - m_tx_pool.on_blockchain_dec(m_db_blocks.size() - 1, get_top_block_id()); - m_timestamps_median_cache.clear(); - update_targetdata_cache_on_block_removed(bei); - LOG_PRINT_L2("block at height " << bei.height << " was removed from the blockchain"); -} -//------------------------------------------------------------------ -void blockchain_storage::update_targetdata_cache_on_block_added(const block_extended_info& bei) -{ - CRITICAL_REGION_LOCAL(m_targetdata_cache_lock); - if (bei.height == 0) - return; //skip genesis - std::list>& targetdata_cache = is_pos_block(bei.bl) ? m_pos_targetdata_cache : m_pow_targetdata_cache; - targetdata_cache.push_back(std::pair(bei.cumulative_diff_precise, bei.bl.timestamp)); - while (targetdata_cache.size() > TARGETDATA_CACHE_SIZE) - targetdata_cache.pop_front(); -} -//------------------------------------------------------------------ -void blockchain_storage::update_targetdata_cache_on_block_removed(const block_extended_info& bei) -{ - CRITICAL_REGION_LOCAL(m_targetdata_cache_lock); - std::list>& targetdata_cache = is_pos_block(bei.bl) ? m_pos_targetdata_cache : m_pow_targetdata_cache; - if (targetdata_cache.size()) - targetdata_cache.pop_back(); - if (targetdata_cache.size() < DIFFICULTY_WINDOW) - targetdata_cache.clear(); -} -//------------------------------------------------------------------ -void blockchain_storage::load_targetdata_cache(bool is_pos)const -{ - CRITICAL_REGION_LOCAL(m_targetdata_cache_lock); - std::list>& targetdata_cache = is_pos? m_pos_targetdata_cache: m_pow_targetdata_cache; - targetdata_cache.clear(); - uint64_t stop_ind = 0; - uint64_t blocks_size = m_db_blocks.size(); - size_t count = 0; - for (uint64_t cur_ind = blocks_size - 1; cur_ind != stop_ind && count < DIFFICULTY_WINDOW + 5; cur_ind--) - { - auto beiptr = m_db_blocks[cur_ind]; - - bool is_pos_bl = is_pos_block(beiptr->bl); - if (is_pos != is_pos_bl) - continue; - targetdata_cache.push_front(std::pair(beiptr->cumulative_diff_precise, beiptr->bl.timestamp)); - ++count; - } -} -//------------------------------------------------------------------ -void blockchain_storage::on_abort_transaction() -{ - if (m_event_handler) m_event_handler->on_clear_events(); - CHECK_AND_ASSERT_MES_NO_RET(validate_blockchain_prev_links(), "EPIC FAIL! 4"); - m_timestamps_median_cache.clear(); -} -//------------------------------------------------------------------ -bool blockchain_storage::update_next_comulative_size_limit() -{ - std::vector sz; - get_last_n_blocks_sizes(sz, CURRENCY_REWARD_BLOCKS_WINDOW); - - uint64_t median = misc_utils::median(sz); - if(median <= CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE) - median = CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE; - - m_db_current_block_cumul_sz_limit = median * 2; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_1_zone()const -{ - return is_after_hardfork_1_zone(m_db_blocks.size()); -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_1_zone(uint64_t height)const -{ - if (height > m_core_runtime_config.hard_fork_01_starts_after_height) - return true; - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_2_zone()const -{ - return is_after_hardfork_2_zone(m_db_blocks.size()); -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_3_zone()const -{ - return is_after_hardfork_3_zone(m_db_blocks.size()); -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_2_zone(uint64_t height)const -{ - if (height > m_core_runtime_config.hard_fork_02_starts_after_height) - return true; - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_after_hardfork_3_zone(uint64_t height)const -{ - if (height > m_core_runtime_config.hard_fork_03_starts_after_height) - return true; - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::prevalidate_block(const block& bl) -{ - //before hard_fork1 - if (bl.major_version == BLOCK_MAJOR_VERSION_INITIAL && get_block_height(bl) <= m_core_runtime_config.hard_fork_01_starts_after_height) - return true; - - - //after hard_fork1 and before hard_fork3 - if ( get_block_height(bl) > m_core_runtime_config.hard_fork_01_starts_after_height && - get_block_height(bl) <= m_core_runtime_config.hard_fork_03_starts_after_height - ) - { - if (bl.major_version <= HF1_BLOCK_MAJOR_VERSION ) - return true; - else - return false; - } - - //after hard_fork3 - if (bl.major_version > CURRENT_BLOCK_MAJOR_VERSION) - { - LOG_ERROR("prevalidation failed for block " << get_block_hash(bl) << ": major block version " << static_cast(bl.major_version) << " is incorrect, " << CURRENT_BLOCK_MAJOR_VERSION << " is expected" << ENDL - << obj_to_json_str(bl)); - return false; - } - - if (bl.minor_version > CURRENT_BLOCK_MINOR_VERSION) - { - //this means that binary block is compatible, but semantics got changed due to hardfork, daemon should be updated - LOG_PRINT_MAGENTA("Block's MINOR_VERSION is: " << bl.minor_version - << ", while current build supports not bigger then " << CURRENT_BLOCK_MINOR_VERSION - << ", please make sure you using latest version.", LOG_LEVEL_0 - ); - return false; - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::add_new_block(const block& bl, block_verification_context& bvc) -{ - try - { - m_db.begin_transaction(); - - //block bl = bl_; - crypto::hash id = get_block_hash(bl); - CRITICAL_REGION_LOCAL(m_tx_pool); - //CRITICAL_REGION_LOCAL1(m_read_lock); - if (have_block(id)) - { - LOG_PRINT_L3("block with id = " << id << " already exists"); - bvc.m_already_exists = true; - m_db.commit_transaction(); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL! 1"); - return false; - } - - if (!prevalidate_block(bl)) - { - LOG_PRINT_RED_L0("block with id = " << id << " failed to prevalidate"); - bvc.m_added_to_main_chain = false; - bvc.m_verification_failed = true; - m_db.commit_transaction(); - return false; - } - - - //check that block refers to chain tail - - - if (!(bl.prev_id == get_top_block_id())) - { - //chain switching or wrong block - bvc.m_added_to_main_chain = false; - bool r = handle_alternative_block(bl, id, bvc); - if (!r || bvc.m_verification_failed) - { - m_db.abort_transaction(); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL! 2.2"); - m_tx_pool.on_finalize_db_transaction(); - return r; - } - m_db.commit_transaction(); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL! 2"); - m_tx_pool.on_finalize_db_transaction(); - return r; - //never relay alternative blocks - } - - - bool res = handle_block_to_main_chain(bl, id, bvc); - if (bvc.m_verification_failed || !res) - { - m_db.abort_transaction(); - m_tx_pool.on_finalize_db_transaction(); - on_abort_transaction(); - if (m_event_handler) m_event_handler->on_clear_events(); - return res; - } - m_db.commit_transaction(); - CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL! 3"); - m_tx_pool.on_finalize_db_transaction(); - if (m_event_handler) m_event_handler->on_complete_events(); - - return res; - } - catch (const std::exception& ex) - { - bvc.m_verification_failed = true; - bvc.m_added_to_main_chain = false; - m_db.abort_transaction(); - m_tx_pool.on_finalize_db_transaction(); - on_abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK: " << ex.what()); - - return false; - } - catch (...) - { - bvc.m_verification_failed = true; - bvc.m_added_to_main_chain = false; - m_db.abort_transaction(); - m_tx_pool.on_finalize_db_transaction(); - on_abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK."); - return false; - } -} -//------------------------------------------------------------------ -bool blockchain_storage::truncate_blockchain(uint64_t to_height) -{ - m_db.begin_transaction(); - uint64_t inital_height = get_current_blockchain_size(); - while (get_current_blockchain_size() > to_height) - { - transactions_map ot; - pop_block_from_blockchain(ot); - } - CRITICAL_REGION_LOCAL(m_alternative_chains_lock); - m_alternative_chains.clear(); - m_altblocks_keyimages.clear(); - m_alternative_chains_txs.clear(); - LOG_PRINT_MAGENTA("Blockchain truncated from " << inital_height << " to " << get_current_blockchain_size(), LOG_LEVEL_0); - m_db.commit_transaction(); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::calc_tx_cummulative_blob(const block& bl)const -{ - uint64_t cummulative_size_pool = 0; - uint64_t cummulative_size_calc = 0; - uint64_t cummulative_size_serialized = 0; - uint64_t i = 0; - std::stringstream ss; - uint64_t calculated_sz_miner = get_object_blobsize(bl.miner_tx); - blobdata b = t_serializable_object_to_blob(bl.miner_tx); - uint64_t serialized_size_miner = b.size(); - - ss << "[COINBASE]: " << calculated_sz_miner << "|" << serialized_size_miner << ENDL; - - for (auto& h : bl.tx_hashes) - { - uint64_t calculated_sz = 0; - uint64_t serialized_size = 0; - tx_memory_pool::tx_details td = AUTO_VAL_INIT(td); - bool in_pool = m_tx_pool.get_transaction(h, td); - if (in_pool) - { - calculated_sz = get_object_blobsize(td.tx); - blobdata b = t_serializable_object_to_blob(td.tx); - serialized_size = b.size(); - if (td.blob_size != calculated_sz || calculated_sz != serialized_size) - { - LOG_PRINT_RED("BLOB SIZE MISMATCH IN TX: " << h << " calculated_sz: " << calculated_sz - << " serialized_size: " << serialized_size - << " td.blob_size: " << td.blob_size, LOG_LEVEL_0); - } - cummulative_size_pool += td.blob_size; - } - else - { - auto tx_ptr = m_db_transactions.get(h); - CHECK_AND_ASSERT_MES(tx_ptr, false, "tx " << h << " not found in blockchain nor tx_pool"); - calculated_sz = get_object_blobsize(tx_ptr->tx); - blobdata b = t_serializable_object_to_blob(tx_ptr->tx); - serialized_size = b.size(); - if (calculated_sz != serialized_size) - { - LOG_PRINT_RED("BLOB SIZE MISMATCH IN TX: " << h << " calculated_sz: " << calculated_sz - << " serialized_size: " << serialized_size, LOG_LEVEL_0); - } - } - cummulative_size_calc += calculated_sz; - cummulative_size_serialized += serialized_size; - ss << "[" << i << "]" << h << ": " << calculated_sz << ENDL; - i++; - - } - LOG_PRINT_MAGENTA("CUMMULATIVE_BLOCK_SIZE_TRACE: " << get_block_hash(bl) << ENDL - << "cummulative_size_calc: " << cummulative_size_calc << ENDL - << "cummulative_size_serialized: " << cummulative_size_serialized << ENDL - << "cummulative_size_pool: " << cummulative_size_pool << ENDL - << ss.str(), LOG_LEVEL_0); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::build_kernel(const block& bl, stake_kernel& kernel, uint64_t& amount, const stake_modifier_type& stake_modifier) const -{ - CHECK_AND_ASSERT_MES(bl.miner_tx.vin.size() == 2, false, "wrong miner transaction"); - CHECK_AND_ASSERT_MES(bl.miner_tx.vin[0].type() == typeid(txin_gen), false, "wrong miner transaction"); - CHECK_AND_ASSERT_MES(bl.miner_tx.vin[1].type() == typeid(txin_to_key), false, "wrong miner transaction"); - - const txin_to_key& txin = boost::get(bl.miner_tx.vin[1]); - CHECK_AND_ASSERT_MES(txin.key_offsets.size(), false, "wrong miner transaction"); - amount = txin.amount; - - return build_kernel(txin.amount, txin.k_image, kernel, stake_modifier, bl.timestamp); -} -//------------------------------------------------------------------ -bool blockchain_storage::build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain, uint64_t split_height, crypto::hash *p_last_block_hash /* = nullptr */) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - sm = stake_modifier_type(); - - auto pbei_last_pos = get_last_block_of_type(true, alt_chain, split_height); - auto pbei_last_pow = get_last_block_of_type(false, alt_chain, split_height); - CHECK_AND_ASSERT_THROW_MES(pbei_last_pow, "Internal error: pbei_last_pow is null"); - - if (pbei_last_pos) - sm.last_pos_kernel_id = pbei_last_pos->stake_hash; - else - { - bool r = string_tools::parse_tpod_from_hex_string(POS_STARTER_KERNEL_HASH, sm.last_pos_kernel_id); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse POS_STARTER_KERNEL_HASH"); - } - - sm.last_pow_id = get_block_hash(pbei_last_pow->bl); - - if (p_last_block_hash != nullptr) - *p_last_block_hash = get_block_hash(m_db_blocks.back()->bl); - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::build_kernel(uint64_t amount, - const crypto::key_image& ki, - stake_kernel& kernel, - const stake_modifier_type& stake_modifier, - uint64_t timestamp)const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - kernel = stake_kernel(); - kernel.kimage = ki; - kernel.stake_modifier = stake_modifier; - kernel.block_timestamp = timestamp; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp) const -{ - uint64_t timstamp_start = 0; - wide_difficulty_type basic_diff = 0; - CRITICAL_REGION_BEGIN(m_read_lock); - timstamp_start = m_db_blocks.back()->bl.timestamp; - basic_diff = get_next_diff_conditional(true); - CRITICAL_REGION_END(); - - stake_modifier_type sm = AUTO_VAL_INIT(sm); - bool r = build_stake_modifier(sm); - CHECK_AND_ASSERT_MES(r, false, "failed to build_stake_modifier"); - - for (size_t i = 0; i != sp.pos_entries.size(); i++) - { - stake_kernel sk = AUTO_VAL_INIT(sk); - build_kernel(sp.pos_entries[i].amount, sp.pos_entries[i].keyimage, sk, sm, 0); - - for (uint64_t ts = timstamp_start; ts < timstamp_start + POS_SCAN_WINDOW; ts++) - { - sk.block_timestamp = ts; - crypto::hash kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk)); - wide_difficulty_type this_coin_diff = basic_diff / sp.pos_entries[i].amount; - if (!check_hash(kernel_hash, this_coin_diff)) - continue; - else - { - //found kernel - LOG_PRINT_GREEN("Found kernel: amount=" << print_money(sp.pos_entries[i].amount) << ", key_image" << sp.pos_entries[i].keyimage, LOG_LEVEL_0); - rsp.index = i; - rsp.block_timestamp = ts; - rsp.status = API_RETURN_CODE_OK; - return true; - } - } - } - rsp.status = API_RETURN_CODE_NOT_FOUND; - return false; -} -//------------------------------------------------------------------ -void blockchain_storage::set_core_runtime_config(const core_runtime_config& pc) const -{ - m_core_runtime_config = pc; - m_services_mgr.set_core_runtime_config(pc); -} -//------------------------------------------------------------------ -const core_runtime_config& blockchain_storage::get_core_runtime_config() const -{ - return m_core_runtime_config; -} -//------------------------------------------------------------------ -std::shared_ptr blockchain_storage::get_tx_chain_entry(const crypto::hash& tx_hash) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - return m_db_transactions.find(tx_hash); -} -//------------------------------------------------------------------ -bool blockchain_storage::get_tx_chain_entry(const crypto::hash& tx_hash, transaction_chain_entry& entry) const -{ - auto ch_entry_ptr = get_tx_chain_entry(tx_hash); - if (!ch_entry_ptr) - return false; - entry = *ch_entry_ptr; - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_blockchain_prev_links(size_t last_n_blocks_to_check /* = 10 */) const -{ - CRITICAL_REGION_LOCAL(m_read_lock); - - TRY_ENTRY() - - if (m_db_blocks.size() < 2 || last_n_blocks_to_check < 1) - return true; - - bool ok = true; - for(size_t attempt_counter = 1; attempt_counter <= 2; ++attempt_counter) - { - ok = true; - for (size_t height = m_db_blocks.size() - 1, blocks_to_check = last_n_blocks_to_check; height != 0 && blocks_to_check != 0; --height, --blocks_to_check) - { - auto bei_ptr = m_db_blocks[height]; - auto& bei = *bei_ptr; - if (bei.height != height) - { - LOG_ERROR("bei.height = " << bei.height << ", expected: " << height); - ok = false; - } - - auto prev_bei_ptr = m_db_blocks[height - 1]; - auto& prev_bei = *prev_bei_ptr; - crypto::hash prev_id = get_block_hash(prev_bei.bl); - if (bei.bl.prev_id != prev_id) - { - LOG_ERROR("EPIC FAIL: Block " << get_block_hash(bei.bl) << " @ " << height << " has prev_id == " << bei.bl.prev_id << - " while block @ " << height - 1 << " has id: " << prev_id << ENDL << - "Block @" << height << ":" << ENDL << currency::obj_to_json_str(bei.bl) << ENDL << - "Block @" << height - 1 << ":" << ENDL << currency::obj_to_json_str(prev_bei.bl)); - m_performance_data.epic_failure_happend = true; - ok = false; - } - } - - if (ok && attempt_counter == 1) - { - break; - } - else if (!ok && attempt_counter == 1) - { - LOG_PRINT_YELLOW("************* EPIC FAIL workaround attempt: try to reset DB cache and re-check *************", LOG_LEVEL_0); - reset_db_cache(); - continue; - } - else if (!ok && attempt_counter == 2) - { - LOG_PRINT_RED("************* EPIC FAIL workaround attempt failed *************", LOG_LEVEL_0); - break; - } - else if (ok && attempt_counter == 2) - { - LOG_PRINT_GREEN("************* EPIC FAIL workaround attempt succeded! *************", LOG_LEVEL_0); - break; - } - else - { - LOG_ERROR("should never get here"); - return false; - } - - LOG_ERROR("should never get here also"); - return false; - } - - return ok; - - CATCH_ENTRY2(false); -} -//------------------------------------------------------------------ -void blockchain_storage::push_block_to_per_block_increments(uint64_t height_, std::unordered_map& gindices) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint32_t height = static_cast(height_); - - block_gindex_increments bgi = AUTO_VAL_INIT(bgi); - bgi.increments.reserve(gindices.size()); - for (auto& v : gindices) - bgi.increments.push_back(gindex_increment::construct(v.first, v.second)); - - m_db_per_block_gindex_incs.set(height, bgi); -} -//------------------------------------------------------------------ -void blockchain_storage::pop_block_from_per_block_increments(uint64_t height_) -{ - CRITICAL_REGION_LOCAL(m_read_lock); - uint32_t height = static_cast(height_); - m_db_per_block_gindex_incs.erase(height); -} -//------------------------------------------------------------------ -void blockchain_storage::calculate_local_gindex_lookup_table_for_height(uint64_t height, std::map& gindexes) const -{ - gindexes.clear(); - - CHECK_AND_ASSERT_THROW_MES(m_db_per_block_gindex_incs.size() == m_db_blocks.size(), "invariant failure: m_db_per_block_gindex_incs.size() == " << m_db_per_block_gindex_incs.size() << ", m_db_blocks.size() == " << m_db_blocks.size()); - - CRITICAL_REGION_LOCAL(m_read_lock); - - // Calculate total number of outputs for each amount in the main chain from given height - size_t top_block_height = static_cast(m_db_blocks.size()) - 1; - uint64_t h = height; - while (h <= top_block_height) - { - auto p = m_db_per_block_gindex_incs.get(h); - CHECK_AND_ASSERT_THROW_MES(p, "null p for height " << h); - - for (auto& el : p->increments) - gindexes[el.amount] += el.increment; - - ++h; - } - - // Translate total number of outputs for each amount into global output indexes these amounts had at given height. - // (those amounts which are not present in the main chain after given height have the same gindexes at given height and at the most recent block) - for (auto it = gindexes.begin(); it != gindexes.end(); ++it) - { - uint64_t amount = it->first; - uint64_t gindexes_in_mainchain = m_db_outputs.get_item_size(amount); - CHECK_AND_ASSERT_THROW_MES(gindexes_in_mainchain >= it->second, "inconsistent gindex increments for amount " << amount << ": gindexes_in_mainchain == " << gindexes_in_mainchain << ", gindex increment for height " << height << " is " << it->second); - it->second = gindexes_in_mainchain - it->second; - } -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_alt_block_input(const transaction& input_tx, - std::unordered_set& collected_keyimages, - const txs_by_id_and_height_altchain& alt_chain_tx_ids, - const crypto::hash& bl_id, - const crypto::hash& input_tx_hash, - size_t input_index, - const std::vector& input_sigs, - uint64_t split_height, - const alt_chain_type& alt_chain, - const std::unordered_set& alt_chain_block_ids, - uint64_t& ki_lookuptime, - uint64_t* p_max_related_block_height /* = nullptr */) const -{ - // Main and alt chain outline: - // - // A- A- A- B- B- B- B- <-- main chain - // | - // \- C- C- C- <-- alt chain - // ^ - // | - // split height - // - // List of possible cases - // - // | src tx | another | this tx | - // # | output | tx input | input | meaning - // ------------ bad cases ------------------ - // b1 A A C already spent in main chain - // b2 A C C already spent in alt chain - // b3 C C C already spent in alt chain - // b4 B B/- C output not found (in case there's no valid outs in altchain C) - // ------------ good cases ------------------ - // g1 A - C normal spending output from main chain A - // g2 A B C normal spending output from main chain A (although it is spent in main chain B as well) - // g3 C - C normal spending output from alt chain C - // g4 B,C - C src tx added to both main chain B and alt chain C - // g5 B,C B C src tx added to both main chain B and alt chain C, also spent in B - - CRITICAL_REGION_LOCAL(m_read_lock); - bool r = false; - - if (p_max_related_block_height != nullptr) - *p_max_related_block_height = 0; - - CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size(), false, "invalid input index: " << input_index); - const txin_v& input_v = input_tx.vin[input_index]; - const txin_to_key& input_to_key = get_to_key_input_from_txin_v(input_v); - - // check case b1: key_image spent status in main chain, should be either non-spent or has spent height >= split_height - auto p = m_db_spent_keys.get(input_to_key.k_image); - CHECK_AND_ASSERT_MES(p == nullptr || *p >= split_height, false, "key image " << input_to_key.k_image << " has been already spent in main chain at height " << *p << ", split height: " << split_height); - - TIME_MEASURE_START(ki_lookup_time); - //check key_image in altchain - //check among this alt block already collected key images first - if (collected_keyimages.find(input_to_key.k_image) != collected_keyimages.end()) - { - // cases b2, b3 - LOG_ERROR("key image " << input_to_key.k_image << " already spent in this alt block"); - return false; - } - auto ki_it = m_altblocks_keyimages.find(input_to_key.k_image); - if (ki_it != m_altblocks_keyimages.end()) - { - //have some entry for this key image. Check if this key image belongs to this alt chain - const std::list& key_image_block_ids = ki_it->second; - for (auto& h : key_image_block_ids) - { - if (alt_chain_block_ids.find(h) != alt_chain_block_ids.end()) - { - // cases b2, b3 - LOG_ERROR("key image " << input_to_key.k_image << " already spent in altchain"); - return false; - } - } - } - //update altchain with key image - collected_keyimages.insert(input_to_key.k_image); - TIME_MEASURE_FINISH(ki_lookup_time); - ki_lookuptime = ki_lookup_time; - - std::vector abs_key_offsets = relative_output_offsets_to_absolute(input_to_key.key_offsets); - CHECK_AND_ASSERT_MES(abs_key_offsets.size() > 0 && abs_key_offsets.size() == input_to_key.key_offsets.size(), false, "internal error: abs_key_offsets.size()==" << abs_key_offsets.size() << ", input_to_key.key_offsets.size()==" << input_to_key.key_offsets.size()); - // eventually we should found all public keys for all outputs this input refers to, for checking ring signature - std::vector pub_keys(abs_key_offsets.size(), null_pkey); - - // - // let's try to resolve references and populate pub keys container for check_tokey_input() - // - uint64_t global_outs_for_amount = 0; - //figure out if this amount touched alt_chain amount's index and if it is, get - bool amount_touched_altchain = false; - //auto abg_it = abei.gindex_lookup_table.find(input_to_key.amount); - //if (abg_it == abei.gindex_lookup_table.end()) - - if (!alt_chain.empty()) - { - auto abg_it = alt_chain.back()->second.gindex_lookup_table.find(input_to_key.amount); - if (abg_it != alt_chain.back()->second.gindex_lookup_table.end()) - { - amount_touched_altchain = true; - // local gindex lookup table contains last used gindex, so we can't get total number of outs - // just skip setting global_outs_for_amount - } - else - { - //quite easy, - global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount); - } - } - else - { - //quite easy, - global_outs_for_amount = m_db_outputs.get_item_size(input_to_key.amount); - } - - CHECK_AND_ASSERT_MES(pub_keys.size() == abs_key_offsets.size(), false, "pub_keys.size()==" << pub_keys.size() << " != abs_key_offsets.size()==" << abs_key_offsets.size()); // just a little bit of paranoia - std::vector pub_key_pointers; - - uint64_t height_of_current_alt_block = alt_chain.size() ? alt_chain.back()->second.height + 1 : split_height + 1; - - for (size_t pk_n = 0; pk_n < pub_keys.size(); ++pk_n) - { - crypto::public_key& pk = pub_keys[pk_n]; - crypto::hash tx_id = null_hash; - uint64_t out_n = UINT64_MAX; - auto &off = abs_key_offsets[pk_n]; - if (off.type() == typeid(uint64_t)) - { - uint64_t offset_gindex = boost::get(off); - CHECK_AND_ASSERT_MES(amount_touched_altchain || (offset_gindex < global_outs_for_amount), false, - "invalid global output index " << offset_gindex << " for amount=" << input_to_key.amount << - ", max is " << global_outs_for_amount << - ", referred to by offset #" << pk_n << - ", amount_touched_altchain = " << amount_touched_altchain); - if (amount_touched_altchain) - { - bool found_the_key = false; - for (auto alt_it = alt_chain.rbegin(); alt_it != alt_chain.rend(); alt_it++) - { - auto it_aag = (*alt_it)->second.gindex_lookup_table.find(input_to_key.amount); - if (it_aag == (*alt_it)->second.gindex_lookup_table.end()) - { - CHECK_AND_ASSERT_MES(alt_it != alt_chain.rbegin(), false, "internal error: was marked as amount_touched_altchain but unable to find on first entry"); - //item supposed to be in main chain - break; - } - if (offset_gindex >= it_aag->second) - { - //source tx found in altchain - //GOT IT!! - //TODO: At the moment we ignore check of mix_attr against mixing to simplify alt chain check, but in future consider it for stronger validation - uint64_t local_offset = offset_gindex - it_aag->second; - auto& alt_keys = (*alt_it)->second.outputs_pub_keys; - CHECK_AND_ASSERT_MES(local_offset < alt_keys[input_to_key.amount].size(), false, "Internal error: local_offset=" << local_offset << " while alt_keys[" << input_to_key.amount << " ].size()=" << alt_keys.size()); - const output_key_or_htlc_v& out_in_alt = alt_keys[input_to_key.amount][local_offset]; - - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - uint64_t height_of_source_block = (*alt_it)->second.height; - CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - bool r = is_output_allowed_for_input(out_in_alt, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (out_in_alt.type() == typeid(crypto::public_key)) - { - pk = boost::get(out_in_alt); - } - else - { - const txout_htlc& out_htlc = boost::get(out_in_alt); - bool htlc_expired = out_htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false:true; - pk = htlc_expired ? out_htlc.pkey_refund : out_htlc.pkey_redeem; - //input_v - } - pub_key_pointers.push_back(&pk); - found_the_key = true; - break; - } - } - if (found_the_key) - continue; - //otherwise lookup in main chain index - } - auto p = m_db_outputs.get_subitem(input_to_key.amount, offset_gindex); - CHECK_AND_ASSERT_MES(p != nullptr, false, "global output was not found, amount: " << input_to_key.amount << ", gindex: " << offset_gindex << ", referred to by offset #" << pk_n); - tx_id = p->tx_id; - out_n = p->out_no; - } - else if (off.type() == typeid(ref_by_id)) - { - auto &rbi = boost::get(off); - tx_id = rbi.tx_id; - out_n = rbi.n; - //look up in alt-chain transactions fist - auto it = alt_chain_tx_ids.find(tx_id); - if (it != alt_chain_tx_ids.end()) - { - uint64_t height_of_source_block = it->second.second; - CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - - //source tx found in altchain - CHECK_AND_ASSERT_MES(it->second.first.vout.size() > out_n, false, "Internal error: out_n(" << out_n << ") >= it->second.vout.size()(" << it->second.first.vout.size() << ")"); - txout_target_v out_target_v = it->second.first.vout[out_n].target; - - bool r = is_output_allowed_for_input(out_target_v, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - - if (out_target_v.type() == typeid(txout_htlc)) - { - //source is hltc out - const txout_htlc& htlc = boost::get(out_target_v); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - pub_key_pointers.push_back(&pk); - continue; - } - else if (out_target_v.type() == typeid(txout_to_key)) - { - //source is to_key out - pk = boost::get(out_target_v).key; - pub_key_pointers.push_back(&pk); - continue; - } - else - { - ASSERT_MES_AND_THROW("Unexpected out type for tx_in in altblock: " << out_target_v.type().name()); - } - } - - } - - auto p = m_db_transactions.get(tx_id); - CHECK_AND_ASSERT_MES(p != nullptr && out_n < p->tx.vout.size(), false, "can't find output #" << out_n << " for tx " << tx_id << " referred by offset #" << pk_n); - auto &t = p->tx.vout[out_n].target; - - /* - here we do validation against compatibility of input and output type - - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - uint64_t height_of_source_block = p->m_keeper_block_height; - CHECK_AND_ASSERT_MES(height_of_current_alt_block > height_of_source_block, false, "Intenral error: height_of_current_alt_block > height_of_source_block failed"); - bool r = is_output_allowed_for_input(t, input_v, height_of_current_alt_block - height_of_source_block); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (t.type() == typeid(txout_to_key)) - { - const txout_to_key& out_tk = boost::get(t); - pk = out_tk.key; - - bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(out_tk.mix_attr, abs_key_offsets.size() - 1); - CHECK_AND_ASSERT_MES(mixattr_ok, false, "input offset #" << pk_n << " violates mixin restrictions: mix_attr = " << static_cast(out_tk.mix_attr) << ", input's key_offsets.size = " << abs_key_offsets.size()); - - } - else if (t.type() == typeid(txout_htlc)) - { - const txout_htlc& htlc = boost::get(t); - bool htlc_expired = htlc.expiration > (height_of_current_alt_block - height_of_source_block) ? false : true; - pk = htlc_expired ? htlc.pkey_refund : htlc.pkey_redeem; - } - - // case b4 (make sure source tx in the main chain is preceding split point, otherwise this referece is invalid) - CHECK_AND_ASSERT_MES(p->m_keeper_block_height < split_height, false, "input offset #" << pk_n << " refers to main chain tx " << tx_id << " at height " << p->m_keeper_block_height << " while split height is " << split_height); - - if (p_max_related_block_height != nullptr && *p_max_related_block_height < p->m_keeper_block_height) - *p_max_related_block_height = p->m_keeper_block_height; - - // TODO: consider checking p->tx for unlock time validity as it's checked in get_output_keys_for_input_with_checks() - // make sure it was actually found - - // let's disable this check due to missing equal check in main chain validation code - //TODO: implement more strict validation with next hard fork - //CHECK_AND_ASSERT_MES(pk != null_pkey, false, "Can't determine output public key for offset " << pk_n << " in related tx: " << tx_id << ", out_n = " << out_n); - pub_key_pointers.push_back(&pk); - } - - // do input checks (attachment_info, ring signature and extra signature, etc.) - r = check_input_signature(input_tx, input_index, input_to_key, input_tx_hash, input_sigs, pub_key_pointers); - CHECK_AND_ASSERT_MES(r, false, "to_key input validation failed"); - - // TODO: consider checking input_tx for valid extra attachment info as it's checked in check_tx_inputs() - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_output_allowed_for_input(const txout_target_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const -{ - - /* - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - - - if (out_v.type() == typeid(txout_to_key)) - { - return is_output_allowed_for_input(boost::get(out_v), in_v); - } - else if (out_v.type() == typeid(txout_htlc)) - { - return is_output_allowed_for_input(boost::get(out_v), in_v, top_minus_source_height); - } - else - { - LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << out_v.type().name()); - return false; - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const -{ - bool htlc_expired = out_v.expiration > (top_minus_source_height) ? false : true; - if (!htlc_expired) - { - //HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input - CHECK_AND_ASSERT_MES(in_v.type() == typeid(txin_htlc), false, "[TXOUT_HTLC]: Unexpected output type of non-HTLC input"); - } - else - { - //HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input - CHECK_AND_ASSERT_MES(in_v.type() == typeid(txin_to_key), false, "[TXOUT_HTLC]: Unexpected output type of HTLC input"); - } - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v)const -{ - //HTLC input CAN'T refer to regular to_key output - CHECK_AND_ASSERT_MES(in_v.type() != typeid(txin_htlc), false, "[TXOUT_TO_KEY]: Unexpected output type of HTLC input"); - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const -{ - if (out_v.type() == typeid(crypto::public_key)) - { - return is_output_allowed_for_input(txout_to_key(), in_v); - } - else if (out_v.type() == typeid(txout_htlc)) - { - return is_output_allowed_for_input(boost::get(out_v), in_v, top_minus_source_height); - } - else { - ASSERT_MES_AND_THROW("Unexpected type in output_key_or_htlc_v: " << out_v.type().name()); - } -} -//------------------------------------------------------------------ -bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const -{ - // Main and alt chain outline: - // - // A- A- A- B- B- B- B- <-- main chain - // | - // \- C- C- C- <-- alt chain - // ^ - // | - // split height - // - // List of possible cases - // - // | src tx | another | this tx | - // # | output | tx input | input | meaning - // ------------ bad cases ------------------ - // b1 A A C already spent in main chain - // b2 A C C already spent in alt chain - // b3 C C C already spent in alt chain - // b4 B B/- C output not found (in case there's no valid outs in altchain C) - // ------------ good cases ------------------ - // g1 A - C normal spending output from main chain A - // g2 A B C normal spending output from main chain A (although it is spent in main chain B as well) - // g3 C - C normal spending output from alt chain C - // g4 B,C - C src tx added to both main chain B and alt chain C - // g5 B,C B C src tx added to both main chain B and alt chain C, also spent in B - - CRITICAL_REGION_LOCAL(m_read_lock); - bool r = false; - - CHECK_AND_ASSERT_MES(input_index < input_tx.vin.size() && input_tx.vin[input_index].type() == typeid(txin_multisig), false, "invalid ms input index: " << input_index << " or type"); - const txin_multisig& input = boost::get(input_tx.vin[input_index]); - - // check corresponding ms out in the main chain - auto p = m_db_multisig_outs.get(input.multisig_out_id); - if (p != nullptr) - { - // check case b1 (note: need to distinguish from case g2) - CHECK_AND_ASSERT_MES(p->spent_height == 0 || p->spent_height >= split_height, false, "ms output was already spent in main chain at height " << p->spent_height << " while split_height is " << split_height); - - const crypto::hash& source_tx_id = p->tx_id; - auto p_source_tx = m_db_transactions.get(source_tx_id); - CHECK_AND_ASSERT_MES(p_source_tx != nullptr, false, "source tx for ms output " << source_tx_id << " was not found, ms out id: " << input.multisig_out_id); - - if (p_source_tx->m_keeper_block_height < split_height) - { - // cases g1, g2 - return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, p_source_tx->tx, p->out_no); - } - - // p_source_tx is above split_height in main chain B, so it can't be a source for this input - // do nohting here and proceed to alt chain scan for possible cases b4, g4, g5 - } - else - { - // ms out was not found in DB - // do nothing here and proceed to alt chain scan for possible cases b2, b3, g3, g4, g5 - } - - - // walk the alt chain backward (from the the last added alt block towards split point -- it important as we stop scanning when find correct output, need to make sure it was not already spent) - for (alt_chain_type::const_reverse_iterator it = alt_chain.rbegin(); it != alt_chain.rend(); ++it) - { - const block_extended_info& bei = (*it)->second; - const block& b = bei.bl; - bool output_found = false; - - auto tx_altchain_checker = [&](const transaction& tx, const crypto::hash& tx_id) -> bool - { - // check ms out being already spent in current alt chain - for (auto& in : tx.vin) - { - if (in.type() == typeid(txin_multisig)) - { - // check cases b2, b3 - CHECK_AND_ASSERT_MES(input.multisig_out_id != boost::get(in).multisig_out_id, false, "ms out " << input.multisig_out_id << " has been already spent in altchain by tx " << tx_id << " in block " << get_block_hash(b) << " height " << bei.height); - } - } - - for (size_t out_n = 0; out_n < tx.vout.size(); ++out_n) - { - const tx_out& out = tx.vout[out_n]; - if (out.target.type() == typeid(txout_multisig)) - { - const crypto::hash& ms_out_id = get_multisig_out_id(tx, out_n); - if (ms_out_id == input.multisig_out_id) - { - // cases g3, g4, g5 - output_found = true; - return check_ms_input(input_tx, input_index, input, input_tx_hash, input_sigs, tx, out_n); - } - } - } - return true; - }; - - // for each alt block look into miner_tx and txs - CHECK_AND_ASSERT_MES(tx_altchain_checker(b.miner_tx, get_transaction_hash(b.miner_tx)), false, "tx_altchain_checker failed for miner tx"); - if (output_found) - return true; // g3, g4, g5 - for (auto& tx_id : b.tx_hashes) - { - std::shared_ptr tx_ptr; - r = get_transaction_from_pool_or_db(tx_id, tx_ptr, split_height); - CHECK_AND_ASSERT_MES(r, false, "can't get transaction " << tx_id << " for alt block " << get_block_hash(b) << " height " << bei.height << ", split height is " << split_height); - transaction& tx = *tx_ptr; - CHECK_AND_ASSERT_MES(tx_altchain_checker(tx, tx_id), false, "tx_altchain_checker failed for tx " << tx_id); - if (output_found) - return true; // g3, g4, g5 - } - } - - // case b4 - LOG_ERROR("ms outout " << input.multisig_out_id << " was not found neither in main chain, nor in alt chain"); - return false; -} -//------------------------------------------------------------------ -bool blockchain_storage::get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr& tx_ptr, uint64_t min_allowed_block_height /* = 0 */) const -{ - tx_ptr.reset(new transaction()); - - if (!m_tx_pool.get_transaction(tx_id, *tx_ptr)) // first try to get from the pool - { - auto p = m_db_transactions.get(tx_id); // if not found in the pool -- get from the DB - if (p == nullptr) - { - return false; - } - //CHECK_AND_ASSERT_MES(p != nullptr, false, "can't get tx " << tx_id << " neither from the pool, nor from db_transactions"); - CHECK_AND_ASSERT_MES(p->m_keeper_block_height >= min_allowed_block_height, false, "tx " << tx_id << " found in the main chain at height " << p->m_keeper_block_height << " while required min allowed height is " << min_allowed_block_height); - *tx_ptr = p->tx; - } - - return true; -} -//------------------------------------------------------------------ -bool blockchain_storage::update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei) const -{ - //add tx outputs to gindex_lookup_table - for (auto o : tx.vout) - { - if (o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_htlc)) - { - //LOG_PRINT_MAGENTA("ALT_OUT KEY ON H[" << abei.height << "] AMOUNT: " << o.amount, LOG_LEVEL_0); - // first, look at local gindexes tables - if (abei.gindex_lookup_table.find(o.amount) == abei.gindex_lookup_table.end()) - { - // amount was not found in altchain gindexes container, start indexing from current main chain gindex - abei.gindex_lookup_table[o.amount] = m_db_outputs.get_item_size(o.amount); - //LOG_PRINT_MAGENTA("FIRST TOUCH: size=" << abei.gindex_lookup_table[o.amount], LOG_LEVEL_0); - } - if (o.target.type() == typeid(txout_to_key)) - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target).key); - } - else - { - abei.outputs_pub_keys[o.amount].push_back(boost::get(o.target)); - } - - //TODO: At the moment we ignore check of mix_attr again mixing to simplify alt chain check, but in future consider it for stronger validation - } - } - return true; -} - -bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const -{ - uint64_t height = abei.height; - bool r = false; - std::unordered_set alt_chain_block_ids; - txs_by_id_and_height_altchain alt_chain_tx_ids; - - - alt_chain_block_ids.insert(id); - // prepare data structure for output global indexes tracking within current alt chain - if (alt_chain.size()) - { - //TODO: in this two lines we scarify memory to earn speed for algo, but need to be careful with RAM consuming on long switches - abei.gindex_lookup_table = alt_chain.back()->second.gindex_lookup_table; - - //adjust indices for next alt block entry according to emount of pubkeys in txs of prev block - auto& prev_alt_keys = alt_chain.back()->second.outputs_pub_keys; - for (auto it = prev_alt_keys.begin(); it != prev_alt_keys.end(); it++) - { - auto it_amont_in_abs_ind = abei.gindex_lookup_table.find(it->first); - CHECK_AND_ASSERT_MES(it_amont_in_abs_ind != abei.gindex_lookup_table.end(), false, "internal error: not found amount " << it->first << "in gindex_lookup_table"); - //increase index starter for amount of outputs in prev block - it_amont_in_abs_ind->second += it->second.size(); - } - //generate set of alt block ids - for (auto& ch : alt_chain) - { - alt_chain_block_ids.insert(get_block_hash(ch->second.bl)); - for (auto & on_board_tx : ch->second.onboard_transactions) - { - alt_chain_tx_ids.insert(txs_by_id_and_height_altchain::value_type(on_board_tx.first, txs_by_id_and_height_altchain::value_type::second_type(on_board_tx.second, ch->second.height))); - } - //TODO: consider performance optimization (get_transaction_hash might slow down deep reorganizations ) - alt_chain_tx_ids.insert(txs_by_id_and_height_altchain::value_type(get_transaction_hash(ch->second.bl.miner_tx), txs_by_id_and_height_altchain::value_type::second_type(ch->second.bl.miner_tx, ch->second.height))); - } - } - else - { - // initialize alt chain entry with initial gindexes - calculate_local_gindex_lookup_table_for_height(split_height, abei.gindex_lookup_table); - } - - if (is_pos_block(b)) - { - // check PoS block miner tx in a special way - CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 && b.miner_tx.vin.size() == 2, false, "invalid PoS block's miner_tx, signatures size = " << b.miner_tx.signatures.size() << ", miner_tx.vin.size() = " << b.miner_tx.vin.size()); - uint64_t max_related_block_height = 0; - uint64_t ki_lookup = 0; - r = validate_alt_block_input(b.miner_tx, collected_keyimages, alt_chain_tx_ids, id, get_block_hash(b), 1, b.miner_tx.signatures[0], split_height, alt_chain, alt_chain_block_ids, ki_lookup, &max_related_block_height); - CHECK_AND_ASSERT_MES(r, false, "miner tx " << get_transaction_hash(b.miner_tx) << ": validation failed"); - ki_lookup_time_total += ki_lookup; - // check stake age - uint64_t coinstake_age = height - max_related_block_height - 1; - CHECK_AND_ASSERT_MES(coinstake_age >= m_core_runtime_config.min_coinstake_age, false, - "miner tx's coinstake age is " << coinstake_age << ", that is less than minimum required " << m_core_runtime_config.min_coinstake_age << "; max_related_block_height == " << max_related_block_height); - } - update_alt_out_indexes_for_tx_in_block(b.miner_tx, abei); - - CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(b.miner_tx, null_hash, height), false, "miner tx hardfork-specific validation failed"); - - for (auto tx_id : b.tx_hashes) - { - std::shared_ptr tx_ptr; - auto it = abei.onboard_transactions.find(tx_id); - if (it == abei.onboard_transactions.end()) - { - CHECK_AND_ASSERT_MES(get_transaction_from_pool_or_db(tx_id, tx_ptr, split_height), false, "failed to get alt block tx " << tx_id << " with split_height == " << split_height); - } - const transaction& tx = it == abei.onboard_transactions.end() ? *tx_ptr : it->second; - CHECK_AND_ASSERT_MES(tx.signatures.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << tx.signatures.size() << ", tx.vin.size() == " << tx.vin.size()); - for (size_t n = 0; n < tx.vin.size(); ++n) - { - if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc)) - { - uint64_t ki_lookup = 0; - r = validate_alt_block_input(tx, collected_keyimages, alt_chain_tx_ids, id, tx_id, n, tx.signatures[n], split_height, alt_chain, alt_chain_block_ids, ki_lookup); - CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << ": validation failed"); - ki_lookup_time_total += ki_lookup; - } - else if (tx.vin[n].type() == typeid(txin_multisig)) - { - r = validate_alt_block_ms_input(tx, tx_id, n, tx.signatures[n], split_height, alt_chain); - CHECK_AND_ASSERT_MES(r, false, "tx " << tx_id << ", input #" << n << " (multisig): validation failed"); - } - else if (tx.vin[n].type() == typeid(txin_gen)) - { - // genesis can't be in tx_hashes - CHECK_AND_ASSERT_MES(false, false, "input #" << n << " has unexpected type (" << tx.vin[n].type().name() << ", genesis can't be in tx_hashes), tx " << tx_id); - } - else - { - CHECK_AND_ASSERT_MES(false, false, "input #" << n << " has unexpected type (" << tx.vin[n].type().name() << "), tx " << tx_id); - } - } - - CHECK_AND_ASSERT_MES(validate_tx_for_hardfork_specific_terms(tx, tx_id, height), false, "tx " << tx_id << ": hardfork-specific validation failed"); - - // Updating abei (and not updating alt_chain) during this cycle is safe because txs in the same block can't reference one another, - // so only valid references are either to previous alt blocks (accessed via alt_chain) or to main chain blocks. - update_alt_out_indexes_for_tx_in_block(tx, abei); - } - - - return true; -} - - diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h deleted file mode 100644 index cad2ca9..0000000 --- a/src/currency_core/blockchain_storage.h +++ /dev/null @@ -1,889 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include - -#include - -#include -#include -#include - -#include -#include - -#include "file_io_utils.h" -#include "serialization/serialization.h" -#include "serialization/string.h" -#include "serialization/multiprecision.h" - -#include "tx_pool.h" -#include "blockchain_storage_basic.h" -#include "common/util.h" -#include "common/db_abstract_accessor.h" -#include "currency_protocol/currency_protocol_defs.h" -#include "rpc/core_rpc_server_commands_defs.h" -#include "difficulty.h" -#include "common/difficulty_boost_serialization.h" -#include "currency_core/currency_format_utils.h" -#include "verification_context.h" -#include "crypto/hash.h" -#include "checkpoints.h" -#include "core_runtime_config.h" -#include "dispatch_core_events.h" -#include "bc_attachments_service_manager.h" -#include "common/median_db_cache.h" - - - -MARK_AS_POD_C11(crypto::key_image); -typedef std::pair macro_alias_1; -MARK_AS_POD_C11(macro_alias_1); - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "core" - -namespace currency -{ - - // blue core - - class blockchain_storage - { - public: - struct performnce_data - { - //block processing zone - epee::math_helper::average block_processing_time_0_ms; - epee::math_helper::average block_processing_time_1; - epee::math_helper::average target_calculating_time_2; - epee::math_helper::average longhash_calculating_time_3; - epee::math_helper::average all_txs_insert_time_5; - epee::math_helper::average etc_stuff_6; - epee::math_helper::average insert_time_4; - epee::math_helper::average raise_block_core_event; - //target_calculating_time_2 - epee::math_helper::average target_calculating_enum_blocks; - epee::math_helper::average target_calculating_calc; - - //tx processing zone - epee::math_helper::average tx_check_inputs_time; - epee::math_helper::average tx_add_one_tx_time; - epee::math_helper::average tx_process_extra; - epee::math_helper::average tx_process_attachment; - epee::math_helper::average tx_process_inputs ; - epee::math_helper::average tx_push_global_index; - epee::math_helper::average tx_check_exist; - epee::math_helper::average tx_print_log; - epee::math_helper::average tx_prapare_append; - - epee::math_helper::average tx_append_time; - epee::math_helper::average tx_append_rl_wait; - epee::math_helper::average tx_append_is_expired; - - epee::math_helper::average tx_store_db; - - epee::math_helper::average tx_check_inputs_prefix_hash; - epee::math_helper::average tx_check_inputs_attachment_check; - epee::math_helper::average tx_check_inputs_loop; - epee::math_helper::average tx_check_inputs_loop_kimage_check; - epee::math_helper::average tx_check_inputs_loop_ch_in_val_sig; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_get_item_size; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_find_tx; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_handle_output; - - epee::math_helper::average tx_mixin_count; - - - //TODO: move this to suitable place or remove it all - std::atomic epic_failure_happend; - tools::db::stat_info si; - }; - - - struct key_images_ptr_compare - { - bool operator()(const std::shared_ptr& a, const std::shared_ptr& b) const - { - return *a == *b; - } - }; - - struct key_images_ptr_hash - { - std::size_t operator()(const std::shared_ptr& i) const - { - return crypto::hash_value(*i); // TODO: BAD hash function, replace with something better! - } - }; - - struct key_images_ptr_less - { - typedef bool result_type; - bool operator()(const std::shared_ptr& _Left, const std::shared_ptr& _Right) const - { - return (*_Left < *_Right); - } - }; - - struct scan_for_keys_context - { - bool htlc_is_expired; - std::list htlc_outs; - }; - - // == Output indexes local lookup table conception == - // Main chain gindex table (outputs_container) contains data which is valid only for the most recent block. - // Thus it can't be used to get output's global index for any arbitrary height because there's no height data. - // Having local gindex lookup table for a given height one could retrieve global output index table as it was - // at the given height using the following algorithm: - // - // local_gindex_lookup_table = calculate_local_gindex_lookup_table_for_height(height) - // if amount exists in local_gindex_lookup_table: - // retrieve gindex from local_gindex_lookup_table # there are outputs having given amount after the given height - // else: - // retrieve gindex from main chain gindex table # not outputs having given amount are present after the given height - // - - typedef boost::variant output_key_or_htlc_v; - - struct alt_block_extended_info: public block_extended_info - { - // {amount -> gindex } output global index lookup table for this altblock (if an amount isn't present -- it's retreived from main outputs_container) - std::map gindex_lookup_table; - - // {amount -> pub_keys} map of outputs' pub_keys appeared in this alt block ( index_in_vector == output_gindex - gindex_lookup_table[output_amount] ) - std::map > outputs_pub_keys; - - //date added to alt chain storage - uint64_t timestamp; - - //transactions associated with the block - transactions_map onboard_transactions; - }; - typedef std::unordered_map alt_chain_container; - typedef std::vector alt_chain_type; // alternative subchain, front -> mainchain(split point), back -> alternative head - - typedef std::unordered_map blocks_ext_by_hash; - - typedef tools::db::basic_key_to_array_accessor outputs_container; // out_amount => ['global_output', ...] - typedef tools::db::cached_key_value_accessor key_images_container; - typedef std::list, std::list >, std::shared_ptr > > blocks_direct_container; - - friend struct add_transaction_input_visitor; - //--------------------------------------------------------------------------------- - - blockchain_storage(tx_memory_pool& tx_pool); - ~blockchain_storage(); - - - bool init(const boost::program_options::variables_map& vm) { return init(tools::get_default_data_dir(), vm); } - bool init(const std::string& config_folder, const boost::program_options::variables_map& vm); - bool deinit(); - static void init_options(boost::program_options::options_description& desc); - - bool set_checkpoints(checkpoints&& chk_pts); - - //TODO: set this method to const - checkpoints& get_checkpoints() { return m_checkpoints; } - bool is_in_checkpoint_zone() const { return m_is_in_checkpoint_zone; } - - //------------- modifying members -------------- - bool add_new_block(const block& bl_, block_verification_context& bvc); - bool prevalidate_block(const block& bl); - bool clear(); - bool reset_and_set_genesis_block(const block& b); - //debug function - bool truncate_blockchain(uint64_t to_height); - //------------- readers members ----------------- - bool pre_validate_relayed_block(block& b, block_verification_context& bvc, const crypto::hash& id)const ; - //bool push_new_block(); - bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const ; - bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks) const; - bool get_main_blocks_rpc_details(uint64_t start_offset, size_t count, bool ignore_transactions, std::list& blocks) const; - bool get_main_block_rpc_details(uint64_t i, block_rpc_extended_info& bei) const; - bool get_main_block_rpc_details(const crypto::hash& id, block_rpc_extended_info& bei) const; - bool get_alt_block_rpc_details(const crypto::hash& id, block_rpc_extended_info& bei) const; - bool get_alt_block_rpc_details(const block_extended_info& bei_core, const crypto::hash& id, block_rpc_extended_info& bei) const; - bool get_alt_blocks_rpc_details(uint64_t start_offset, uint64_t count, std::vector& blocks) const; - bool get_tx_rpc_details(const crypto::hash&, tx_rpc_extended_info& tei, uint64_t timestamp, bool is_short) const; - bool search_by_id(const crypto::hash& id, std::list& res) const; - bool get_global_index_details(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::response & resp) const; - bool get_multisig_id_details(const COMMAND_RPC_GET_MULTISIG_INFO::request& req, COMMAND_RPC_GET_MULTISIG_INFO::response & resp) const; - bool get_multisig_id_details(const crypto::hash& ms_id, crypto::hash& tx_id, uint64_t& out_no) const; - bool get_alternative_blocks(std::list& blocks) const; - size_t get_alternative_blocks_count() const; - crypto::hash get_block_id_by_height(uint64_t height) const; - bool get_block_by_hash(const crypto::hash &h, block &blk) const; - bool get_block_extended_info_by_height(uint64_t h, block_extended_info &blk) const; - bool get_block_extended_info_by_hash(const crypto::hash &h, block_extended_info &blk) const; - bool get_block_by_height(uint64_t h, block &blk) const; - bool is_tx_related_to_altblock(crypto::hash tx_id) const; - //void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid) const; - - bc_attachment_services_manager& get_attachment_services_manager(){ return m_services_mgr; } - - bool have_tx(const crypto::hash &id) const; - bool have_tx_keyimges_as_spent(const transaction &tx) const; - bool have_tx_keyimg_as_spent(const crypto::key_image &key_im, uint64_t before_height = UINT64_MAX) const; - std::shared_ptr get_tx(const crypto::hash &id) const; - - - template - bool scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_to_key& tx_in_to_key, visitor_t& vis) - { - scan_for_keys_context cntx_stub = AUTO_VAL_INIT(cntx_stub); - uint64_t stub = 0; - return scan_outputkeys_for_indexes(validated_tx, tx_in_to_key, vis, stub, cntx_stub); - } - template - bool scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& /*scan_context*/) const; - - - uint64_t get_current_blockchain_size() const; - uint64_t get_top_block_height() const; - crypto::hash get_top_block_id() const; - crypto::hash get_top_block_id(uint64_t& height) const; - bool get_top_block(block& b) const; - wide_difficulty_type get_next_diff_conditional(bool pos) const; - wide_difficulty_type get_next_diff_conditional2(bool pos, const alt_chain_type& alt_chain, uint64_t split_height, const alt_block_extended_info& abei) const; - wide_difficulty_type get_cached_next_difficulty(bool pos) const; - - - bool create_block_template(block& b, const account_public_address& miner_address, const account_public_address& stakeholder_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe, fill_block_template_func_t custom_fill_block_template_func = nullptr) const; - bool create_block_template(block& b, const account_public_address& miner_address, wide_difficulty_type& di, uint64_t& height, const blobdata& ex_nonce) const; - bool create_block_template(const create_block_template_params& params, create_block_template_response& resp) const; - - bool have_block(const crypto::hash& id) const; - size_t get_total_transactions()const; - bool get_outs(uint64_t amount, std::list& pkeys)const; - bool get_short_chain_history(std::list& ids)const; - bool find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp)const; - bool find_blockchain_supplement(const std::list& qblock_ids, uint64_t& starter_offset)const; - bool find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0, bool need_global_indexes = false)const; - bool find_blockchain_supplement(const std::list& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0, bool request_coinbase_info = false)const; - //bool find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count)const; - bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const; - bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const; - bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const; - bool get_backward_blocks_sizes(size_t from_height, std::vector& sz, size_t count)const; - bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs)const; - bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const; - std::string get_alias_by_address(const account_public_address& addr)const; - template - bool enumerate_aliases(cb_t cb) const; - template - bool get_aliases(cb_t cb, uint64_t offset, uint64_t count) const; - uint64_t get_aliases_count()const; - uint64_t get_block_h_older_then(uint64_t timestamp) const; - bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const; - bool check_tx_input(const transaction& tx, size_t in_index, const txin_htlc& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, uint64_t& max_related_block_height)const; - bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const; - bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const; - bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const; - bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const transaction& source_tx, size_t out_n) const; - bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const; - bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id) const; - bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase, scan_for_keys_context& scan_context) const; - bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_v& verified_input, std::vector& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const; - bool check_input_signature(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector& sig, const std::vector& output_keys_ptrs) const; - bool check_input_signature(const transaction& tx, - size_t in_index, - uint64_t in_amount, - const crypto::key_image& k_image, - const std::vector& in_etc_details, - const crypto::hash& tx_prefix_hash, - const std::vector& sig, - const std::vector& output_keys_ptrs) const; - - uint64_t get_current_comulative_blocksize_limit()const; - uint64_t get_current_hashrate(size_t aprox_count)const; - uint64_t get_seconds_between_last_n_block(size_t n)const; - bool has_multisig_output(const crypto::hash& multisig_id) const; - bool is_multisig_output_spent(const crypto::hash& multisig_id) const; - boost::multiprecision::uint128_t total_coins()const; - bool is_pos_allowed()const; - uint64_t get_tx_fee_median()const; - uint64_t get_tx_expiration_median() const; - uint64_t validate_alias_reward(const transaction& tx, const std::string& ai)const; - void set_event_handler(i_core_event_handler* event_handler) const; - i_core_event_handler* get_event_handler() const; - uint64_t get_last_timestamps_check_window_median() const; - uint64_t get_last_n_blocks_timestamps_median(size_t n) const; - bool prevalidate_alias_info(const transaction& tx, const extra_alias_entry& eae); - bool validate_miner_transaction(const block& b, size_t cumulative_block_size, uint64_t fee, uint64_t& base_reward, const boost::multiprecision::uint128_t& already_generated_coins) const; - performnce_data& get_performnce_data()const; - bool validate_instance(const std::string& path); - bool is_tx_expired(const transaction& tx) const; - std::shared_ptr find_key_image_and_related_tx(const crypto::key_image& ki, crypto::hash& id_result) const; - - wide_difficulty_type block_difficulty(size_t i)const; - bool forecast_difficulty(std::vector> &out_height_2_diff_vector, bool pos) const; - bool prune_aged_alt_blocks(); - bool get_transactions_daily_stat(uint64_t& daily_cnt, uint64_t& daily_volume)const; - bool check_keyimages(const std::list& images, std::list& images_stat)const;//true - unspent, false - spent - bool build_kernel(const block& bl, stake_kernel& kernel, uint64_t& amount, const stake_modifier_type& stake_modifier)const; - // --- PoS --- - bool build_kernel(uint64_t amount, - const crypto::key_image& ki, - stake_kernel& kernel, - const stake_modifier_type& stake_modifier, - uint64_t timestamp)const; - bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const; - - bool scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp)const; - bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const; - bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const; - bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const; - bool validate_pos_block(const block& b, - wide_difficulty_type basic_diff, - uint64_t& amount, - wide_difficulty_type& final_diff, - crypto::hash& proof_hash, - const crypto::hash& id, - bool for_altchain, - const alt_chain_type& alt_chain = alt_chain_type(), - uint64_t split_height = 0)const; - void set_core_runtime_config(const core_runtime_config& pc) const; - const core_runtime_config& get_core_runtime_config()const; - size_t get_current_sequence_factor(bool pos)const; - bool get_last_n_blocks_sizes(std::vector& sz, size_t count)const; - std::shared_ptr get_last_block_of_type(bool looking_for_pos, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0)const; - void get_pos_mining_estimate(uint64_t amuont_coins, - uint64_t time, - uint64_t& estimate_result, - uint64_t& pos_coins_and_pos_diff_rate, - std::vector& days)const; - - uint64_t get_alias_coast(const std::string& alias)const; - const outputs_container& get_outputs_container() const { return m_db_outputs; } - std::shared_ptr get_tx_chain_entry(const crypto::hash& tx_hash) const; - bool get_tx_chain_entry(const crypto::hash& tx_hash, transaction_chain_entry& entry) const; - template - void enumerate_transactions(cb_t cb) const { CRITICAL_REGION_LOCAL(m_read_lock); m_db_transactions.enumerate_keys(cb); } - - - - //this function mostly made for debug purposes - template - void rise_core_event(const std::string& event_name, const t_event_details& ed) - { - core_event_v e(ed); - m_event_handler->on_core_event(event_name, e); - } - - template - bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs)const - { - CRITICAL_REGION_LOCAL(m_read_lock); - - for(const auto& bl_id: block_ids) - { - auto block_ind_ptr = m_db_blocks_index.find(bl_id); - if (!block_ind_ptr) - missed_bs.push_back(bl_id); - else - { - CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id) - << " have index record with offset=" << *block_ind_ptr << ", bigger then m_db_blocks.size()=" << m_db_blocks.size()); - blocks.push_back(m_db_blocks[*block_ind_ptr]->bl); - } - } - return true; - } - - template - bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs)const - { - CRITICAL_REGION_LOCAL(m_read_lock); - - BOOST_FOREACH(const auto& tx_id, txs_ids) - { - auto tx_ptr = m_db_transactions.find(tx_id); - if (!tx_ptr) - { - transaction tx; - if (!m_tx_pool.get_transaction(tx_id, tx)) - missed_txs.push_back(tx_id); - else - txs.push_back(tx); - } - else - txs.push_back(tx_ptr->tx); - } - return true; - } - - - template - bool get_transactions_direct(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs)const - { - CRITICAL_REGION_LOCAL(m_read_lock); - - for(const auto& tx_id: txs_ids) - { - auto tx_ptr = m_db_transactions.find(tx_id); - if (!tx_ptr) - missed_txs.push_back(tx_id); - else - txs.push_back(tx_ptr); - } - return true; - } - - //TODO: set to const - void get_alternative_chains(alt_chain_container& ach) { CRITICAL_REGION_LOCAL(m_alternative_chains_lock); ach = m_alternative_chains; } - void set_alternative_chains(const alt_chain_container& ach) { CRITICAL_REGION_LOCAL(m_alternative_chains_lock); m_alternative_chains = ach; } - - template - void serialize(archive_t & ar, const unsigned int version); - bool get_est_height_from_date(uint64_t date, uint64_t& res_h)const; - - - //debug functions - bool validate_blockchain_prev_links(size_t last_n_blocks_to_check = 10) const; - bool print_transactions_statistics()const; - void print_blockchain(uint64_t start_index, uint64_t end_index) const ; - std::string get_blockchain_string(uint64_t start_index, uint64_t end_index) const; - void print_blockchain_with_tx(uint64_t start_index, uint64_t end_index) const; - void print_blockchain_index() const; - void print_blockchain_outs(const std::string& file) const; - void print_blockchain_outs_stats() const; - void print_db_cache_perfeormance_data() const; - void print_last_n_difficulty_numbers(uint64_t n) const; - bool calc_tx_cummulative_blob(const block& bl)const; - bool get_outs_index_stat(outs_index_stat& outs_stat)const; - bool print_lookup_key_image(const crypto::key_image& ki) const; - void reset_db_cache() const; - void clear_altblocks(); - void inspect_blocks_index() const; - bool rebuild_tx_fee_medians(); - bool validate_all_aliases_for_new_median_mode(); - bool print_tx_outputs_lookup(const crypto::hash& tx_id) const; - uint64_t get_last_x_block_height(bool pos)const; - bool is_tx_spendtime_unlocked(uint64_t unlock_time)const; - private: - - //-------------- DB containers -------------- - typedef tools::db::cached_key_value_accessor blocks_by_id_index; - typedef tools::db::cached_key_value_accessor transactions_container; - - typedef tools::db::array_accessor blocks_container; - - typedef tools::db::cached_key_value_accessor, true, true> aliases_container; - typedef tools::db::cached_key_value_accessor, true, false> address_to_aliases_container; - typedef tools::db::cached_key_value_accessor multisig_outs_container;// ms out id => ms_output_entry - typedef tools::db::cached_key_value_accessor solo_options_container; - typedef tools::db::basic_key_value_accessor per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...] - - //----------------------------------------- - - typedef std::unordered_map > txs_by_id_and_height_altchain; - - tx_memory_pool& m_tx_pool; - mutable bc_attachment_services_manager m_services_mgr; - - /* - At the moment we don't use synchronization for read operations since db do all dirty work. - Write operation synchronized by db_backend.begin_transaction() if it called with write permissions - and caches disabled for all other threads while writer is acting. - The only problem left is that when readers threads still do some work, writer can commit changes and enable cache, - which can lead to wrong interpretation of core data structure (state of the core changed while reader assume that state is the same). - To avoid this cases we use read-write lock, which acquired exclusive access only when writer finished his work and want to commit changes - and enable caches - with this acquiring writer wait wile all readers finish their reading. - */ - epee::shared_recursive_mutex m_rw_lock; - //mutable dummy_critical_section m_read_lock; - mutable epee::shared_membership m_read_lock; - - //---------- db members --------------------- - //main accessor - tools::db::basic_db_accessor m_db; - //containers - blocks_container m_db_blocks; - blocks_by_id_index m_db_blocks_index; - transactions_container m_db_transactions; - key_images_container m_db_spent_keys; - solo_options_container m_db_solo_options; - tools::db::solo_db_value m_db_current_block_cumul_sz_limit; - tools::db::solo_db_value m_db_current_pruned_rs_height; - tools::db::solo_db_value m_db_last_worked_version; - tools::db::solo_db_value m_db_storage_major_compatibility_version; - tools::db::solo_db_value m_db_storage_minor_compatibility_version; - outputs_container m_db_outputs; - multisig_outs_container m_db_multisig_outs; - aliases_container m_db_aliases; - address_to_aliases_container m_db_addr_to_alias; - per_block_gindex_increments_container m_db_per_block_gindex_incs; - - - - - - mutable critical_section m_invalid_blocks_lock; - blocks_ext_by_hash m_invalid_blocks; // crypto::hash -> block_extended_info - mutable critical_section m_alternative_chains_lock; - alt_chain_container m_alternative_chains; // crypto::hash -> alt_block_extended_info - std::unordered_map m_alternative_chains_txs; // tx_id -> how many alt blocks it related to (always >= 1) - std::unordered_map> m_altblocks_keyimages; // key image -> list of alt blocks hashes where it appears in inputs - - std::atomic m_is_in_checkpoint_zone; - std::atomic m_is_blockchain_storing; - - std::string m_config_folder; - //events - checkpoints m_checkpoints; - mutable core_runtime_config m_core_runtime_config; - mutable i_core_event_handler* m_event_handler; - mutable i_core_event_handler m_event_handler_stub; - - //tools::median_db_cache m_tx_fee_median; - mutable std::unordered_map m_timestamps_median_cache; - mutable performnce_data m_performance_data; - std::list m_core_events_pack; - mutable epee::file_io_utils::native_filesystem_handle m_interprocess_locker_file; - //just informational - mutable wide_difficulty_type m_cached_next_pow_difficulty; - mutable wide_difficulty_type m_cached_next_pos_difficulty; - - mutable critical_section m_targetdata_cache_lock; - mutable std::list > m_pos_targetdata_cache; - mutable std::list > m_pow_targetdata_cache; - //work like a cache to avoid recalculation on read operations - mutable uint64_t m_current_fee_median; - mutable uint64_t m_current_fee_median_effective_index; - bool m_is_reorganize_in_process; - mutable std::atomic m_deinit_is_done; - mutable uint64_t m_blockchain_launch_timestamp; - - bool init_tx_fee_median(); - bool update_tx_fee_median(); - void store_db_solo_options_values(); - bool set_lost_tx_unmixable(); - bool set_lost_tx_unmixable_for_height(uint64_t height); - void patch_out_if_needed(txout_to_key& out, const crypto::hash& tx_id, uint64_t n)const ; - bool switch_to_alternative_blockchain(alt_chain_type& alt_chain); - void purge_alt_block_txs_hashs(const block& b); - void add_alt_block_txs_hashs(const block& b); - bool pop_block_from_blockchain(transactions_map& onboard_transactions); - bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count); - bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count, uint64_t& fee, transactions_map& onboard_transactions); - bool purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee, transaction& tx); - bool purge_transaction_keyimages_from_blockchain(const transaction& tx, bool strict_check); - wide_difficulty_type get_next_difficulty_for_alternative_chain(const alt_chain_type& alt_chain, block_extended_info& bei, bool pos) const; - bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc); - bool handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc); - std::string print_alt_chain(alt_chain_type alt_chain); - bool handle_alternative_block(const block& b, const crypto::hash& id, block_verification_context& bvc); - bool is_reorganize_required(const block_extended_info& main_chain_bei, const alt_chain_type& alt_chain, const crypto::hash& proof_alt); - wide_difficulty_type get_x_difficulty_after_height(uint64_t height, bool is_pos); - bool purge_keyimage_from_big_heap(const crypto::key_image& ki, const crypto::hash& id); - bool purge_altblock_keyimages_from_big_heap(const block& b, const crypto::hash& id); - bool append_altblock_keyimages_to_big_heap(const crypto::hash& block_id, const std::unordered_set& alt_block_keyimages); - bool validate_alt_block_input(const transaction& input_tx, - std::unordered_set& collected_keyimages, - const txs_by_id_and_height_altchain& alt_chain_tx_ids, - const crypto::hash& bl_id, - const crypto::hash& input_tx_hash, - size_t input_index, - const std::vector& input_sigs, - uint64_t split_height, - const alt_chain_type& alt_chain, - const std::unordered_set& alt_chain_block_ids, - uint64_t& ki_lookuptime, - uint64_t* p_max_related_block_height = nullptr) const; - bool validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const std::vector& input_sigs, uint64_t split_height, const alt_chain_type& alt_chain) const; - bool validate_alt_block_txs(const block& b, const crypto::hash& id, std::unordered_set& collected_keyimages, alt_block_extended_info& abei, const alt_chain_type& alt_chain, uint64_t split_height, uint64_t& ki_lookup_time_total) const; - bool update_alt_out_indexes_for_tx_in_block(const transaction& tx, alt_block_extended_info& abei)const; - bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr& tx_ptr, uint64_t min_allowed_block_height = 0) const; - void get_last_n_x_blocks(uint64_t n, bool pos_blocks, std::list>& blocks) const; - bool prevalidate_miner_transaction(const block& b, uint64_t height, bool pos)const; - bool rollback_blockchain_switching(std::list& original_chain, size_t rollback_height); - bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height, uint64_t timestamp); - bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector& global_indexes); - bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id); - bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false) const; - bool add_block_as_invalid(const block& bl, const crypto::hash& h); - bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h); - size_t find_end_of_allowed_index(uint64_t amount)const; - bool check_block_timestamp_main(const block& b)const; - bool check_block_timestamp(std::vector timestamps, const block& b)const; - std::vector get_last_n_blocks_timestamps(size_t n)const; - const std::vector& get_txin_etc_options(const txin_v& in)const; - void on_block_added(const block_extended_info& bei, const crypto::hash& id, const std::list& bsk); - void on_block_removed(const block_extended_info& bei); - void update_targetdata_cache_on_block_added(const block_extended_info& bei); - void update_targetdata_cache_on_block_removed(const block_extended_info& bei); - uint64_t tx_fee_median_for_height(uint64_t h) const; - uint64_t get_tx_fee_median_effective_index(uint64_t h) const; - void on_abort_transaction(); - void load_targetdata_cache(bool is_pos) const; - - - uint64_t get_adjusted_time()const; - bool complete_timestamps_vector(uint64_t start_height, std::vector& timestamps); - bool update_next_comulative_size_limit(); - bool process_blockchain_tx_extra(const transaction& tx); - bool unprocess_blockchain_tx_extra(const transaction& tx); - bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp); - bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp); - bool pop_alias_info(const extra_alias_entry& ai); - bool put_alias_info(const transaction& tx, extra_alias_entry& ai); - void fill_addr_to_alias_dict(); - //bool resync_spent_tx_flags(); - bool prune_ring_signatures_and_attachments_if_need(); - bool prune_ring_signatures_and_attachments(uint64_t height, uint64_t& transactions_pruned, uint64_t& signatures_pruned, uint64_t& attachments_pruned); - // bool build_stake_modifier_for_alt(const alt_chain_type& alt_chain, stake_modifier_type& sm); - template - bool enum_blockchain(visitor_t& v, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0) const; - bool update_spent_tx_flags_for_input(uint64_t amount, const txout_ref_v& o, bool spent); - bool update_spent_tx_flags_for_input(uint64_t amount, uint64_t global_index, bool spent); - bool update_spent_tx_flags_for_input(const crypto::hash& multisig_id, uint64_t spent_height); - bool update_spent_tx_flags_for_input(const crypto::hash& tx_id, size_t n, bool spent); - - void push_block_to_per_block_increments(uint64_t height_, std::unordered_map& gindices); - void pop_block_from_per_block_increments(uint64_t height_); - void calculate_local_gindex_lookup_table_for_height(uint64_t split_height, std::map& increments) const; - void do_erase_altblock(alt_chain_container::iterator it); - uint64_t get_blockchain_launch_timestamp()const; - bool is_output_allowed_for_input(const txout_target_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; - bool is_output_allowed_for_input(const output_key_or_htlc_v& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; - bool is_output_allowed_for_input(const txout_to_key& out_v, const txin_v& in_v)const; - bool is_output_allowed_for_input(const txout_htlc& out_v, const txin_v& in_v, uint64_t top_minus_source_height)const; - bool is_after_hardfork_1_zone()const; - bool is_after_hardfork_1_zone(uint64_t height)const; - bool is_after_hardfork_2_zone()const; - bool is_after_hardfork_2_zone(uint64_t height)const; - bool is_after_hardfork_3_zone()const; - bool is_after_hardfork_3_zone(uint64_t height)const; - - - - - //POS - wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_pos(wide_difficulty_type next_diff)const; - wide_difficulty_type get_adjusted_cumulative_difficulty_for_next_alt_pos(alt_chain_type& alt_chain, uint64_t block_height, wide_difficulty_type next_diff, uint64_t connection_height)const; - wide_difficulty_type get_last_alt_x_block_cumulative_precise_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos, wide_difficulty_type& cumulative_diff_precise_adj)const; - wide_difficulty_type get_last_alt_x_block_cumulative_precise_adj_difficulty(const alt_chain_type& alt_chain, uint64_t block_height, bool pos) const; - size_t get_current_sequence_factor_for_alt(alt_chain_type& alt_chain, bool pos, uint64_t connection_height)const; - }; - - /************************************************************************/ - /* end of class class blockchain_storage */ - /************************************************************************/ - - template - bool blockchain_storage::enum_blockchain(visitor_t& v, const alt_chain_type& alt_chain, uint64_t split_height) const - { - - bool keep_going = true; - for (auto it = alt_chain.rbegin(); it != alt_chain.rend() && keep_going; it++) - { - keep_going = v((*it)->second, false); - } - - if (!keep_going || !m_db_blocks.size()) - return !keep_going; - - size_t main_chain_start_offset = 0; - if (split_height) - main_chain_start_offset = split_height - 1; - else - main_chain_start_offset = (alt_chain.size() ? alt_chain.front()->second.height : m_db_blocks.size()) - 1; - - CRITICAL_REGION_LOCAL(m_read_lock); - for (uint64_t i = main_chain_start_offset; i != 0 && keep_going; --i) - { - keep_going = v(*m_db_blocks[i], true); - } - - return !keep_going; - } - //------------------------------------------------------------------ - template - bool blockchain_storage::scan_outputkeys_for_indexes(const transaction &validated_tx, const txin_v& verified_input, visitor_t& vis, uint64_t& max_related_block_height, scan_for_keys_context& scan_context) const - { - const txin_to_key& input_to_key = get_to_key_input_from_txin_v(verified_input); - - uint64_t amount = input_to_key.amount; - const std::vector& key_offsets = input_to_key.key_offsets; - - CRITICAL_REGION_LOCAL(m_read_lock); - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_get_item_size); - - uint64_t outs_count_for_amount = m_db_outputs.get_item_size(amount); - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_get_item_size); - if (!outs_count_for_amount) - return false; - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute); - std::vector absolute_offsets = relative_output_offsets_to_absolute(key_offsets); - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute); - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop); - size_t output_index = 0; - for(const txout_ref_v& o : absolute_offsets) - { - crypto::hash tx_id = null_hash; - size_t n = 0; - if (o.type() == typeid(ref_by_id)) - { - tx_id = boost::get(o).tx_id; - n = boost::get(o).n; - } - else if (o.type() == typeid(uint64_t)) - { - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem); - uint64_t i = boost::get(o); - if (i >= outs_count_for_amount) - { - LOG_ERROR("Wrong index in transaction inputs: " << i << ", expected maximum " << outs_count_for_amount - 1); - return false; - } - auto out_ptr = m_db_outputs.get_subitem(amount, i); - tx_id = out_ptr->tx_id; - n = out_ptr->out_no; - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem); - } - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_find_tx); - auto tx_ptr = m_db_transactions.find(tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "Wrong transaction id in output indexes: " << string_tools::pod_to_hex(tx_id)); - CHECK_AND_ASSERT_MES(n < tx_ptr->tx.vout.size(), false, - "Wrong index in transaction outputs: " << n << ", expected less then " << tx_ptr->tx.vout.size()); - //check mix_attr - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_find_tx); - - //CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false); - CHECK_AND_ASSERT_MES(key_offsets.size() >= 1, false, "internal error: tx input has empty key_offsets"); // should never happen as input correctness must be handled by the caller - - /* - TxOutput | TxInput | Allowed - ---------------------------- - HTLC | HTLC | ONLY IF HTLC NOT EXPIRED - HTLC | TO_KEY | ONLY IF HTLC IS EXPIRED - TO_KEY | HTLC | NOT - TO_KEY | TO_KEY | YES - */ - - bool r = is_output_allowed_for_input(tx_ptr->tx.vout[n].target, verified_input, get_current_blockchain_size() - tx_ptr->m_keeper_block_height); - CHECK_AND_ASSERT_MES(r, false, "Input and output incompatible type"); - - if (tx_ptr->tx.vout[n].target.type() == typeid(txout_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(tx_ptr->tx.vout[n].target, const txout_to_key, outtk, false); - //fix for burned money - patch_out_if_needed(const_cast(outtk), tx_id, n); - - bool mixattr_ok = is_mixattr_applicable_for_fake_outs_counter(outtk.mix_attr, key_offsets.size() - 1); - CHECK_AND_ASSERT_MES(mixattr_ok, false, "tx output #" << output_index << " violates mixin restrictions: mix_attr = " << static_cast(outtk.mix_attr) << ", key_offsets.size = " << key_offsets.size()); - } - else if (tx_ptr->tx.vout[n].target.type() == typeid(txout_htlc)) - { - //check for spend flags - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags.size() > n, false, - "Internal error: tx_ptr->m_spent_flags.size(){" << tx_ptr->m_spent_flags.size() << "} > n{" << n << "}"); - CHECK_AND_ASSERT_MES(tx_ptr->m_spent_flags[n] == false, false, "HTLC out already spent, double spent attempt detected"); - - const txout_htlc& htlc_out = boost::get(tx_ptr->tx.vout[n].target); - if (htlc_out.expiration > get_current_blockchain_size() - tx_ptr->m_keeper_block_height) - { - //HTLC IS NOT expired, can be used ONLY by pkey_before_expiration and ONLY by HTLC input - scan_context.htlc_is_expired = false; - } - else - { - //HTLC IS expired, can be used ONLY by pkey_after_expiration and ONLY by to_key input - scan_context.htlc_is_expired = true; - } - }else - { - LOG_ERROR("[scan_outputkeys_for_indexes]: Wrong output type in : " << tx_ptr->tx.vout[n].target.type().name()); - return false; - } - - - TIME_MEASURE_START_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - if (!vis.handle_output(tx_ptr->tx, validated_tx, tx_ptr->tx.vout[n], n)) - { - LOG_PRINT_L0("Failed to handle_output for output id = " << tx_id << ", no " << n); - return false; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - - if (max_related_block_height < tx_ptr->m_keeper_block_height) - max_related_block_height = tx_ptr->m_keeper_block_height; - - - ++output_index; - } - TIME_MEASURE_FINISH_PD(tx_check_inputs_loop_scan_outputkeys_loop); - return true; - } - - //------------------------------------------------------------------ - template - bool blockchain_storage::get_aliases(cb_t cb, uint64_t offset, uint64_t count) const - { - CRITICAL_REGION_LOCAL(m_read_lock); - - uint64_t counter = 0; - - m_db_aliases.enumerate_items([&](uint64_t i, const std::string& alias, const std::list& alias_entries) - { - if (alias_entries.empty()) - return true; // continue - - if (counter < offset) - { - ++counter; - return true; // continue - } - - if (counter >= offset + count) - return false; // stop - - ++counter; - - cb(alias, alias_entries.back()); - return true; - }); - return true; - } - //------------------------------------------------------------------ - // callback: (uint64_t i, const std::string& alias, const extra_alias_entry_base& alias_entry) -> bool - // callback should return false to stop enumeration, true - to continue - template - bool blockchain_storage::enumerate_aliases(cb_t cb) const - { - CRITICAL_REGION_LOCAL(m_read_lock); - - m_db_aliases.enumerate_items([&](uint64_t i, const std::string& alias, const std::list& alias_entries) - { - return cb(i, alias, alias_entries.back()); - }); - - return true; - } - - - -} // namespace currency - - -BOOST_CLASS_VERSION(currency::transaction_chain_entry, CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER) -BOOST_CLASS_VERSION(currency::block_extended_info, CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER) - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - -#include "blockchain_storage_boost_serialization.h" -#include "currency_boost_serialization.h" diff --git a/src/currency_core/blockchain_storage_basic.h b/src/currency_core/blockchain_storage_basic.h deleted file mode 100644 index 8a48700..0000000 --- a/src/currency_core/blockchain_storage_basic.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include - -#include - -#include -#include -#include - -#include "currency_basic.h" -#include "difficulty.h" -#include "currency_protocol/blobdatatype.h" -namespace currency -{ - - struct transaction_chain_entry - { - transaction tx; - uint64_t m_keeper_block_height; - std::vector m_global_output_indexes; - std::vector m_spent_flags; - uint32_t version; - - DEFINE_SERIALIZATION_VERSION(1); - BEGIN_SERIALIZE_OBJECT() - VERSION_ENTRY(version) - FIELD(version) - FIELDS(tx) - FIELD(m_keeper_block_height) - FIELD(m_global_output_indexes) - FIELD(m_spent_flags) - END_SERIALIZE() - }; - - struct block_extended_info - { - block bl; - uint64_t height; - uint64_t block_cumulative_size; - wide_difficulty_type cumulative_diff_adjusted; - wide_difficulty_type cumulative_diff_precise; - wide_difficulty_type cumulative_diff_precise_adjusted; - wide_difficulty_type difficulty; - boost::multiprecision::uint128_t already_generated_coins; - crypto::hash stake_hash; //TODO: unused field for PoW blocks, subject for refactoring - uint32_t version; - uint64_t this_block_tx_fee_median; //tx fee median for current block transactions - uint64_t effective_tx_fee_median; //current fee median which applied for current block's alias registrations - - DEFINE_SERIALIZATION_VERSION(1); - BEGIN_SERIALIZE_OBJECT() - VERSION_ENTRY(version) - FIELDS(bl) - FIELD(height) - FIELD(block_cumulative_size) - FIELD(cumulative_diff_adjusted) - FIELD(cumulative_diff_precise) - FIELD(cumulative_diff_precise_adjusted) - FIELD(difficulty) - FIELD(already_generated_coins) - FIELD(stake_hash) - FIELD(this_block_tx_fee_median) - FIELD(effective_tx_fee_median) - END_SERIALIZE() - }; - - struct gindex_increment - { - uint64_t amount; // the amount in global outputs table - uint32_t increment; // how many outputs of such amount a block adds to global outputs container - - static gindex_increment construct(uint64_t amount, uint32_t increment) - { - gindex_increment r = { amount, increment }; - return r; - } - - BEGIN_SERIALIZE() - VARINT_FIELD(amount) - VARINT_FIELD(increment) - END_SERIALIZE() - }; - - struct block_gindex_increments - { - std::vector increments; - - BEGIN_SERIALIZE() - FIELD(increments) - END_SERIALIZE() - }; - - // element of txout_to_key global outputs container - struct global_output_entry - { - crypto::hash tx_id; // corresponding tx - uint32_t out_no; // local output index in tx - - static global_output_entry construct(crypto::hash tx_id, uint32_t out_no) - { - global_output_entry v = { tx_id, out_no }; - return v; - } - }; - - // element of multisig DB container - struct ms_output_entry - { - crypto::hash tx_id; // source tx id - uint32_t out_no; // output index in source tx - uint32_t spent_height; // height at which this output was spent (0 - not spent yet) - - static ms_output_entry construct(crypto::hash tx_id, uint32_t out_no, uint32_t spent_height = 0) - { - ms_output_entry v = { tx_id, out_no, spent_height }; - return v; - } - }; - - typedef bool fill_block_template_func_t(block &bl, bool pos, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height); - - struct create_block_template_params - { - account_public_address miner_address; - account_public_address stakeholder_address; - blobdata ex_nonce; - bool pos = false; - pos_entry pe; - std::list explicit_txs; - fill_block_template_func_t *pcustom_fill_block_template_func; - }; - - struct create_block_template_response - { - block b; - wide_difficulty_type diffic; - uint64_t height; - }; - - typedef std::unordered_map transactions_map; - - struct block_ws_txs - { - block b; - transactions_map onboard_transactions; - }; - - - -} \ No newline at end of file diff --git a/src/currency_core/blockchain_storage_boost_serialization.h b/src/currency_core/blockchain_storage_boost_serialization.h deleted file mode 100644 index ce1babf..0000000 --- a/src/currency_core/blockchain_storage_boost_serialization.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "currency_boost_serialization.h" - -namespace boost -{ - namespace serialization - { - - - template - void serialize(archive_t & ar, currency::transaction_chain_entry& te, const unsigned int version) - { - ar & te.tx; - ar & te.m_keeper_block_height; - ar & te.m_global_output_indexes; - ar & te.m_spent_flags; - } - - // The following method is used in tests only atm - // TODO: Consider to remove completely - template - void serialize(archive_t & ar, currency::block_extended_info& ei, const unsigned int version) - { - ar & ei.bl; - ar & ei.height; - ar & ei.cumulative_diff_adjusted; - ar & ei.cumulative_diff_precise; - ar & ei.difficulty; - ar & ei.block_cumulative_size; - ar & ei.already_generated_coins; - ar & ei.stake_hash; - - ar & ei.cumulative_diff_precise_adjusted; - //ar & ei.version; - ar & ei.this_block_tx_fee_median; - ar & ei.effective_tx_fee_median; - } - - } -} diff --git a/src/currency_core/checkpoints.cpp b/src/currency_core/checkpoints.cpp deleted file mode 100644 index bbce981..0000000 --- a/src/currency_core/checkpoints.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "include_base_utils.h" -using namespace epee; - -#include "checkpoints.h" - -namespace currency -{ - //--------------------------------------------------------------------------- - checkpoints::checkpoints() - { - } - //--------------------------------------------------------------------------- - bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str) - { - crypto::hash h = null_hash; - bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); - CHECK_AND_ASSERT_MES(r, false, "WRONG HASH IN CHECKPOINTS!!!"); - CHECK_AND_ASSERT_MES(0 == m_points.count(height), false, "WRONG HASH IN CHECKPOINTS!!!"); - m_points[height] = h; - return true; - } - //--------------------------------------------------------------------------- - bool checkpoints::is_in_checkpoint_zone(uint64_t height) const - { - return !m_points.empty() && (height <= (--m_points.end())->first); - } - //--------------------------------------------------------------------------- - bool checkpoints::is_height_passed_zone(uint64_t height, uint64_t blockchain_last_block_height) const - { - if(height > blockchain_last_block_height) - return false; - - auto it = m_points.lower_bound(height); // if found, it->first >= height - if(it == m_points.end()) - return false; - if(it->first <= blockchain_last_block_height) - return true; // this is the case only if height <= it->first <= blockchain_last_block_height - else - return false; - } - //--------------------------------------------------------------------------- - uint64_t checkpoints::get_top_checkpoint_height() const - { - if (!m_points.size()) - return 0; - return (--m_points.end())->first; - } - //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const - { - auto it = m_points.find(height); - if(it == m_points.end()) - return true; - - if(it->second == h) - { - LOG_PRINT_GREEN("CHECKPOINT PASSED FOR HEIGHT " << height << " " << h, LOG_LEVEL_0); - return true; - }else - { - LOG_ERROR("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h); - return false; - } - } - //--------------------------------------------------------------------------- - uint64_t checkpoints::get_checkpoint_before_height(uint64_t height) const - { - // returns height of the leftmost CP with height that is LESS than the given height - // ex: - // If there are two CP at 11 and 15: - // get_checkpoint_before_height(10) = 0 - // get_checkpoint_before_height(11) = 0 - // get_checkpoint_before_height(12) = 11 - // get_checkpoint_before_height(13) = 11 - // get_checkpoint_before_height(14) = 11 - // get_checkpoint_before_height(15) = 11 - // get_checkpoint_before_height(16) = 15 - - uint64_t top_cp = get_top_checkpoint_height(); - if (height > top_cp) - return top_cp; - - auto it = m_points.lower_bound(height); // if found, it->first >= height - if (it == m_points.end() || it == m_points.begin()) - return 0; - return (--it)->first; - } -} diff --git a/src/currency_core/checkpoints.h b/src/currency_core/checkpoints.h deleted file mode 100644 index 76675e6..0000000 --- a/src/currency_core/checkpoints.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include - -#include "currency_core/currency_format_utils.h" - -namespace currency -{ - class checkpoints - { - public: - checkpoints(); - bool add_checkpoint(uint64_t height, const std::string& hash_str); - bool is_in_checkpoint_zone(uint64_t height) const; - bool is_height_passed_zone(uint64_t height, uint64_t blockchain_last_block_height) const; - bool check_block(uint64_t height, const crypto::hash& h) const; - uint64_t get_top_checkpoint_height() const; - - uint64_t get_checkpoint_before_height(uint64_t height) const; - private: - std::map m_points; - }; -} diff --git a/src/currency_core/checkpoints_create.h b/src/currency_core/checkpoints_create.h deleted file mode 100644 index 059d190..0000000 --- a/src/currency_core/checkpoints_create.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "checkpoints.h" -#include "misc_log_ex.h" - -#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(checkpoints.add_checkpoint(h, hash), false) - -namespace currency -{ - - inline bool create_checkpoints(currency::checkpoints& checkpoints) - { -#ifdef TESTNET - -#else - // MAINNET - ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8"); - ADD_CHECKPOINT(525000, "8c1ac57e67448130207a224b2d6e33ccdc64d6dd1c59dbcf9ad2361dc0d07d51"); - ADD_CHECKPOINT(600000, "d9fe316086e1aaea07d94082973ec764eff5fc5a05ed6e1eca273cee59daeeb4"); - ADD_CHECKPOINT(900000, "2205b73cd79d4937b087b02a8b001171b73c34464bc4a952834eaf7c2bd63e86"); - ADD_CHECKPOINT(1161000, "96990d851b484e30190678756ba2a4d3a2f92b987e2470728ac1e38b2bf35908"); -#endif - - return true; - } - -} // namespace currency diff --git a/src/currency_core/connection_context.h b/src/currency_core/connection_context.h deleted file mode 100644 index 6c242cc..0000000 --- a/src/currency_core/connection_context.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include "net/net_utils_base.h" -#include "copyable_atomic.h" - -namespace currency -{ - - struct block_context_info - { - crypto::hash h; - uint64_t cumul_size; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(h) - KV_SERIALIZE(cumul_size) - END_KV_SERIALIZE_MAP() - }; - - - struct uncopybale_currency_context - { - uncopybale_currency_context() = default; - uncopybale_currency_context(const uncopybale_currency_context& /**/) {} - uncopybale_currency_context& operator =(const uncopybale_currency_context& /**/) { return *this; } - //members that supposed to be accessed only from one thread - std::list m_needed_objects; - std::unordered_set m_requested_objects; - std::atomic m_callback_request_count; //in debug purpose: problem with double callback rise - - }; - - struct currency_connection_context: public epee::net_utils::connection_context_base - { - enum state - { - state_befor_handshake = 0, //default state - state_synchronizing, - state_idle, - state_normal - }; - - state m_state; - uint64_t m_remote_blockchain_height; - uint64_t m_last_response_height; - int64_t m_time_delta; - std::string m_remote_version; - private: - template friend class t_currency_protocol_handler; - uncopybale_currency_context m_priv; - }; - - inline std::string get_protocol_state_string(currency_connection_context::state s) - { - switch (s) - { - case currency_connection_context::state_befor_handshake: - return "state_befor_handshake"; - case currency_connection_context::state_synchronizing: - return "state_synchronizing"; - case currency_connection_context::state_idle: - return "state_idle"; - case currency_connection_context::state_normal: - return "state_normal"; - default: - return "unknown"; - } - } - -} diff --git a/src/currency_core/core_runtime_config.h b/src/currency_core/core_runtime_config.h deleted file mode 100644 index a2bbe84..0000000 --- a/src/currency_core/core_runtime_config.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2014-2020 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "misc_language.h" -#include "string_tools.h" - -namespace currency -{ - typedef uint64_t (*core_time_func_t)(); - - struct core_runtime_config - { - uint64_t min_coinstake_age; - uint64_t pos_minimum_heigh; //height - uint64_t tx_pool_min_fee; - uint64_t tx_default_fee; - uint64_t max_alt_blocks; - crypto::public_key alias_validation_pubkey; - core_time_func_t get_core_time; - - uint64_t hard_fork_01_starts_after_height; - uint64_t hard_fork_02_starts_after_height; - uint64_t hard_fork_03_starts_after_height; - - bool is_hardfork_active_for_height(size_t hardfork_id, uint64_t height) const - { - switch (hardfork_id) - { - case 0: return true; - case 1: return height > hard_fork_01_starts_after_height; - case 2: return height > hard_fork_02_starts_after_height; - case 3: return height > hard_fork_03_starts_after_height; - default: return false; - } - } - - static uint64_t _default_core_time_function() - { - return time(NULL); - } - }; - - inline core_runtime_config get_default_core_runtime_config() - { - core_runtime_config pc = AUTO_VAL_INIT(pc); - pc.min_coinstake_age = POS_MINIMUM_COINSTAKE_AGE; - pc.pos_minimum_heigh = POS_START_HEIGHT; - pc.tx_pool_min_fee = TX_MINIMUM_FEE; - pc.tx_default_fee = TX_DEFAULT_FEE; - pc.max_alt_blocks = CURRENCY_ALT_BLOCK_MAX_COUNT; - - pc.hard_fork_01_starts_after_height = ZANO_HARDFORK_01_AFTER_HEIGHT; - pc.hard_fork_02_starts_after_height = ZANO_HARDFORK_02_AFTER_HEIGHT; - pc.hard_fork_03_starts_after_height = ZANO_HARDFORK_03_AFTER_HEIGHT; - - pc.get_core_time = &core_runtime_config::_default_core_time_function; - bool r = epee::string_tools::hex_to_pod(ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY, pc.alias_validation_pubkey); - CHECK_AND_ASSERT_THROW_MES(r, "failed to parse alias_validation_pub_key"); - return pc; - } -} diff --git a/src/currency_core/core_tools.h b/src/currency_core/core_tools.h deleted file mode 100644 index 38d7362..0000000 --- a/src/currency_core/core_tools.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "blockchain_storage.h" -#include "bc_offers_service.h" - -namespace currency -{ - inline - bool resync_market(blockchain_storage& bcs, bc_services::bc_offers_service& offers_service) - { - offers_service.clear(); - uint64_t top_block_height = bcs.get_top_block_height(); - currency::block b = AUTO_VAL_INIT(b); - bcs.get_top_block(b); - uint64_t start_height = bcs.get_block_h_older_then(b.timestamp - OFFER_MAXIMUM_LIFE_TIME); - uint64_t print_height_interval = std::max((top_block_height - start_height) / 10ull + 1, 10ull), next_print_height = start_height + print_height_interval; - LOG_PRINT_MAGENTA("Resynchronizing market from height " << start_height << " to height " << top_block_height, LOG_LEVEL_0); - for (uint64_t i = start_height; i <= top_block_height; i++) - { - if (i == next_print_height) - { - LOG_PRINT_MAGENTA("Resynchronizing market: height " << i << " of " << top_block_height << " (" << ((i - start_height) * 100 / (top_block_height - start_height)) << "%)", LOG_LEVEL_0); - next_print_height += print_height_interval; - } - - bcs.get_block_by_height(i, b); - crypto::hash block_id = get_block_hash(b); - for (auto tx_id : b.tx_hashes) - { - auto tx_ptr = bcs.get_tx(tx_id); - CHECK_AND_ASSERT_MES(tx_ptr, false, "Internal error: Failed to get transaction " << tx_id << "from block[" << i << "]"); - uint64_t count = 0; - for (const auto& at : tx_ptr->attachment) - { - if (at.type() == typeid(currency::tx_service_attachment)) - { - const currency::tx_service_attachment& tsa = boost::get(at); - if (tsa.service_id == BC_OFFERS_SERVICE_ID) - { - static_cast(&offers_service)->handle_entry_push(tsa, count, *tx_ptr, i, block_id, b.timestamp); //handle service - } - ++count; - } - } - } - } - LOG_PRINT_MAGENTA("Resynchronizing market finished.", LOG_LEVEL_0); - return true; - } -} \ No newline at end of file diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h deleted file mode 100644 index dc973a6..0000000 --- a/src/currency_core/currency_basic.h +++ /dev/null @@ -1,819 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2014-2015 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include // memcmp -#include -#include - -#include "include_base_utils.h" - -#include "serialization/binary_archive.h" -#include "serialization/crypto.h" -#include "serialization/stl_containers.h" -#include "serialization/serialization.h" -#include "serialization/variant.h" -#include "serialization/json_archive.h" -#include "serialization/debug_archive.h" -#include "serialization/keyvalue_serialization.h" // epee key-value serialization -#include "string_tools.h" -#include "currency_config.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "misc_language.h" -#include "block_flags.h" -#include "etc_custom_serialization.h" - -namespace currency -{ - - const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash); - const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey); - const static crypto::key_image null_ki = AUTO_VAL_INIT(null_ki); - const static crypto::secret_key null_skey = AUTO_VAL_INIT(null_skey); - const static crypto::signature null_sig = AUTO_VAL_INIT(null_sig); - const static crypto::key_derivation null_derivation = AUTO_VAL_INIT(null_derivation); - - const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852"); - - typedef std::string payment_id_t; - - - /************************************************************************/ - /* */ - /************************************************************************/ - -//since structure used in blockchain as a key accessor, then be sure that there is no padding inside -#pragma pack(push, 1) - struct account_public_address_old - { - crypto::public_key spend_public_key; - crypto::public_key view_public_key; - - BEGIN_SERIALIZE_OBJECT() - FIELD(spend_public_key) - FIELD(view_public_key) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(spend_public_key, "m_spend_public_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(view_public_key, "m_view_public_key") - END_KV_SERIALIZE_MAP() - }; -#pragma pack(pop) - - -#define ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER 1 - -#define ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE 0x01 // auditable address - -//since structure used in blockchain as a key accessor, then be sure that there is no padding inside -#pragma pack(push, 1) - struct account_public_address - { - crypto::public_key spend_public_key; - crypto::public_key view_public_key; - uint8_t flags; - - DEFINE_SERIALIZATION_VERSION(ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER) - BEGIN_SERIALIZE_OBJECT() - FIELD(spend_public_key) - FIELD(view_public_key) - FIELD(flags) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(spend_public_key, "m_spend_public_key") - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(view_public_key, "m_view_public_key") - KV_SERIALIZE(flags) - END_KV_SERIALIZE_MAP() - - bool is_auditable() const - { - return (flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) != 0; - } - - static account_public_address from_old(const account_public_address_old& rhs) - { - account_public_address result = AUTO_VAL_INIT(result); - result.spend_public_key = rhs.spend_public_key; - result.view_public_key = rhs.view_public_key; - return result; - } - - account_public_address_old to_old() const - { - account_public_address_old result = AUTO_VAL_INIT(result); - result.spend_public_key = spend_public_key; - result.view_public_key = view_public_key; - return result; - } - }; -#pragma pack(pop) - - - const static account_public_address null_pub_addr = AUTO_VAL_INIT(null_pub_addr); - - typedef std::vector ring_signature; - - /************************************************************************/ - /* extra structures */ - /************************************************************************/ - struct extra_attachment_info - { - uint64_t sz; - crypto::hash hsh; - uint64_t cnt; - - BEGIN_SERIALIZE() - VARINT_FIELD(sz) - FIELD(hsh) - VARINT_FIELD(cnt) - END_SERIALIZE() - }; - - /* outputs */ - -// 'mix_attr' possible values -#define CURRENCY_TO_KEY_OUT_RELAXED 0 // the output may be mixed with any fake outputs -#define CURRENCY_TO_KEY_OUT_FORCED_NO_MIX 1 // the output can't be mixed, only direct spend allowed -#define CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND 2 // this and greather values means minimum number of total outputs (fakes + 1) must be mixed together for using that one - - #pragma pack(push, 1) - struct txout_to_key - { - txout_to_key() : key(null_pkey), mix_attr(0) { } - txout_to_key(const crypto::public_key &_key) : key(_key), mix_attr(0) { } - - crypto::public_key key; - uint8_t mix_attr; - }; - #pragma pack(pop) - - /* inputs */ - - struct txin_gen - { - size_t height; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(height) - END_SERIALIZE() - }; - - // ref_by_id is used by txin_to_key to reference an output by source transaction hash and output's internal index, - // rather than amount and global output index (by default). Useful when output global index is unknown or may change. - struct ref_by_id - { - crypto::hash tx_id; // source transaction hash - uint32_t n; // output index in source transaction - - BEGIN_SERIALIZE_OBJECT() - FIELD(tx_id) - VARINT_FIELD(n) - END_SERIALIZE() - }; - - typedef boost::variant txout_ref_v; - - - struct signed_parts - { - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(n_outs) - VARINT_FIELD(n_extras) - END_SERIALIZE() - - uint32_t n_outs; - uint32_t n_extras; - }; - - - typedef boost::variant txin_etc_details_v; - - struct txin_to_key - { - uint64_t amount; - std::vector key_offsets; - crypto::key_image k_image; // double spending protection - std::vector etc_details; //this flag used when TX_FLAG_SIGNATURE_MODE_SEPARATE flag is set, point to which amount of outputs(starting from zero) used in signature - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(key_offsets) - FIELD(k_image) - FIELD(etc_details) - END_SERIALIZE() - }; - - struct txin_htlc: public txin_to_key - { - std::string hltc_origin; - BEGIN_SERIALIZE_OBJECT() - FIELD(hltc_origin) - FIELDS(*static_cast(this)) - END_SERIALIZE() - }; - - struct txin_multisig - { - uint64_t amount; - crypto::hash multisig_out_id; - uint32_t sigs_count; // actual number of signatures that are used to sign this input; needed to calculate tx blob size; must be equal to minimum_sigs of corresponding ms output - std::vector etc_details; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(multisig_out_id) - VARINT_FIELD(sigs_count) - FIELD(etc_details) - END_SERIALIZE() - }; - - struct txout_multisig - { - uint32_t minimum_sigs; - std::vector keys; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(minimum_sigs) - FIELD(keys) - END_SERIALIZE() - }; - -#define CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK 0x01 // 0 - SHA256, 1 - RIPEMD160 - - struct txout_htlc - { - crypto::hash htlc_hash; - uint8_t flags; //select type of the hash, may be some extra info in future - uint64_t expiration; - crypto::public_key pkey_redeem; //works before expiration - crypto::public_key pkey_refund; //works after expiration - - BEGIN_SERIALIZE_OBJECT() - FIELD(htlc_hash) - FIELD(flags) - VARINT_FIELD(expiration) - FIELD(pkey_redeem) - FIELD(pkey_refund) - END_SERIALIZE() - }; - - typedef boost::variant txin_v; - - typedef boost::variant txout_target_v; - - //typedef std::pair out_t; - struct tx_out - { - uint64_t amount; - txout_target_v target; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(target) - END_SERIALIZE() - }; - - - - struct tx_comment - { - std::string comment; - - BEGIN_SERIALIZE() - FIELD(comment) - END_SERIALIZE() - }; - - struct tx_payer_old - { - account_public_address_old acc_addr; - - BEGIN_SERIALIZE() - FIELD(acc_addr) - END_SERIALIZE() - }; - - struct tx_payer - { - tx_payer() = default; - tx_payer(const tx_payer_old& old) : acc_addr(account_public_address::from_old(old.acc_addr)) {} - - account_public_address acc_addr{}; - - BEGIN_SERIALIZE() - FIELD(acc_addr) - END_SERIALIZE() - }; - - struct tx_receiver_old - { - account_public_address_old acc_addr; - - BEGIN_SERIALIZE() - FIELD(acc_addr) - END_SERIALIZE() - }; - - struct tx_receiver - { - tx_receiver() = default; - tx_receiver(const tx_receiver_old& old) : acc_addr(account_public_address::from_old(old.acc_addr)) {} - - account_public_address acc_addr{}; - - BEGIN_SERIALIZE() - FIELD(acc_addr) - END_SERIALIZE() - }; - - struct tx_crypto_checksum - { - //we put tx encrypted key_derivation into tx attachment/extra, to let sender decrypt attachments that had been encrypted. - // key_derivation encrypted on sender private send address - crypto::key_derivation encrypted_key_derivation; - uint32_t derivation_hash; - - BEGIN_SERIALIZE() - FIELD(encrypted_key_derivation) - FIELD(derivation_hash) - END_SERIALIZE() - }; - - struct tx_derivation_hint - { - std::string msg; - - BEGIN_SERIALIZE() - FIELD(msg) - END_SERIALIZE() - }; - - struct tx_service_attachment - { - std::string service_id; //string identifying service which addressed this attachment - std::string instruction; //string identifying specific instructions for service/way to interpret data - std::string body; //any data identifying service, options etc - std::vector security; //some of commands need proof of owner - uint8_t flags; //special flags (ex: TX_SERVICE_ATTACHMENT_ENCRYPT_BODY), see below - - BEGIN_SERIALIZE() - FIELD(service_id) - FIELD(instruction) - FIELD(body) - FIELD(security) - FIELD(flags) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(service_id) - KV_SERIALIZE(instruction) - KV_SERIALIZE_BLOB_AS_HEX_STRING(body) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(security) - KV_SERIALIZE(flags) - END_KV_SERIALIZE_MAP() - }; - -// applicable flags for tx_service_attachment::flags, can be combined using bitwise OR -#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast(1 << 0) -#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast(1 << 1) - -// with this flag enabled body encrypted/decrypted with the key created as a derivation from onetime key and "spend keys" of receiver -#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE static_cast(1 << 2) -// add proof of content, without revealing secrete -#define TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF static_cast(1 << 3) - - //, - - - struct extra_user_data - { - std::string buff; - - BEGIN_SERIALIZE() - FIELD(buff) - END_SERIALIZE() - }; - - - struct extra_alias_entry_base_old - { - account_public_address_old m_address; - std::string m_text_comment; - std::vector m_view_key; // only one or zero elments expected (std::vector is using as memory efficient container for such a case) - std::vector m_sign; // only one or zero elments expected (std::vector is using as memory efficient container for such a case) - - BEGIN_SERIALIZE() - FIELD(m_address) - FIELD(m_text_comment) - FIELD(m_view_key) - FIELD(m_sign) - END_SERIALIZE() - }; - - struct extra_alias_entry_old : public extra_alias_entry_base_old - { - std::string m_alias; - - BEGIN_SERIALIZE() - FIELD(m_alias) - FIELDS(*static_cast(this)) - END_SERIALIZE() - }; - - struct extra_alias_entry_base - { - extra_alias_entry_base() = default; - extra_alias_entry_base(const extra_alias_entry_base_old& old) - : m_address(account_public_address::from_old(old.m_address)) - , m_text_comment(old.m_text_comment) - , m_view_key(old.m_view_key) - , m_sign(old.m_sign) - { - } - - account_public_address m_address; - std::string m_text_comment; - std::vector m_view_key; // only one or zero elments expected (std::vector is using as memory efficient container for such a case) - std::vector m_sign; // only one or zero elments expected (std::vector is using as memory efficient container for such a case) - - BEGIN_SERIALIZE() - FIELD(m_address) - FIELD(m_text_comment) - FIELD(m_view_key) - FIELD(m_sign) - END_SERIALIZE() - }; - - struct extra_alias_entry : public extra_alias_entry_base - { - extra_alias_entry() = default; - extra_alias_entry(const extra_alias_entry_old& old) - : extra_alias_entry_base(old) - , m_alias(old.m_alias) - { - } - - std::string m_alias; - - BEGIN_SERIALIZE() - FIELD(m_alias) - FIELDS(*static_cast(this)) - END_SERIALIZE() - - extra_alias_entry_old to_old() const - { - extra_alias_entry_old result = AUTO_VAL_INIT(result); - result.m_address = m_address.to_old(); - result.m_text_comment = m_text_comment; - result.m_view_key = m_view_key; - result.m_sign = m_sign; - result.m_alias = m_alias; - return result; - } - }; - - - - struct extra_padding - { - std::vector buff; //stub - - BEGIN_SERIALIZE() - FIELD(buff) - END_SERIALIZE() - }; - - - //number of block (or timestamp if v bigger then CURRENCY_MAX_BLOCK_NUMBER), used as a limitation: spend this tx not early then block/time - struct etc_tx_details_unlock_time - { - uint64_t v; - BEGIN_SERIALIZE() - VARINT_FIELD(v) - END_SERIALIZE() - }; - - //number of block (or timestamp if unlock_time_array[i] bigger then CURRENCY_MAX_BLOCK_NUMBER), used as a limitation: spend this tx not early then block/time - //unlock_time_array[i], i - index of output, unlock_time_array.size() == vout.size() - struct etc_tx_details_unlock_time2 - { - std::vector unlock_time_array; - BEGIN_SERIALIZE() - FIELD(unlock_time_array) - END_SERIALIZE() - }; - - struct etc_tx_details_expiration_time - { - uint64_t v; - BEGIN_SERIALIZE() - VARINT_FIELD(v) - END_SERIALIZE() - }; - - /* - this structure used to put real time into PoS block(or could be other meaning), to have more suitable dates in transactions - */ - struct etc_tx_time - { - uint64_t v; - BEGIN_SERIALIZE() - VARINT_FIELD(v) - END_SERIALIZE() - }; - - struct etc_tx_details_flags - { - uint64_t v; - BEGIN_SERIALIZE() - VARINT_FIELD(v) - END_SERIALIZE() - }; - - struct etc_tx_flags16_t - { - uint16_t v; - BEGIN_SERIALIZE() - FIELD(v) - END_SERIALIZE() - }; - - typedef boost::mpl::vector21< - tx_service_attachment, tx_comment, tx_payer_old, tx_receiver_old, tx_derivation_hint, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time, - etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry_old, extra_user_data, extra_padding, etc_tx_flags16_t, etc_tx_details_unlock_time2, - tx_payer, tx_receiver, extra_alias_entry - > all_payload_types; - - typedef boost::make_variant_over::type payload_items_v; - typedef payload_items_v extra_v; - typedef payload_items_v attachment_v; - - - class transaction_prefix - { - public: - // tx version information - uint64_t version{}; - //extra - std::vector extra; - std::vector vin; - std::vector vout; - - BEGIN_SERIALIZE() - VARINT_FIELD(version) - if(CURRENT_TRANSACTION_VERSION < version) return false; - FIELD(vin) - FIELD(vout) - FIELD(extra) - END_SERIALIZE() - - protected: - transaction_prefix(){} - }; - -/* - TX_FLAG_SIGNATURE_MODE_SEPARATE - flag that set different signature validation mode. - With this mode each signature sign prefix with it's own txin entry only, that allow - construct transaction partially, supposed to be in use to construct multisig-based escrow transaction. -*/ -#define TX_FLAG_SIGNATURE_MODE_SEPARATE 0x01 - - - - - class transaction: public transaction_prefix - { - public: - std::vector > signatures; //count signatures always the same as inputs count - std::vector attachment; - - transaction(); - - BEGIN_SERIALIZE_OBJECT() - FIELDS(*static_cast(this)) - FIELD(signatures) - FIELD(attachment) - END_SERIALIZE() - - - }; - - - - - inline - transaction::transaction() - { - version = 0; - vin.clear(); - vout.clear(); - extra.clear(); - signatures.clear(); - attachment.clear(); - - } - /* - inline - transaction::~transaction() - { - //set_null(); - } - - inline - void transaction::set_null() - { - version = 0; - unlock_time = 0; - vin.clear(); - vout.clear(); - extra.clear(); - signatures.clear(); - } - */ - - - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct block_header - { - uint8_t major_version; - uint8_t minor_version; - uint64_t timestamp; - crypto::hash prev_id; - uint64_t nonce; - uint8_t flags; - - BEGIN_SERIALIZE() - FIELD(major_version) - if(major_version > CURRENT_BLOCK_MAJOR_VERSION) return false; - FIELD(nonce) - FIELD(prev_id) - VARINT_FIELD(minor_version) - VARINT_FIELD(timestamp) - FIELD(flags) - END_SERIALIZE() - }; - - struct block: public block_header - { - transaction miner_tx; - std::vector tx_hashes; - - BEGIN_SERIALIZE_OBJECT() - FIELDS(*static_cast(this)) - FIELD(miner_tx) - FIELD(tx_hashes) - END_SERIALIZE() - }; - - - - - struct keypair - { - crypto::public_key pub; - crypto::secret_key sec; - - static inline keypair generate() - { - keypair k; - generate_keys(k.pub, k.sec); - return k; - } - }; - const static keypair null_keypair = AUTO_VAL_INIT(null_keypair); - //--------------------------------------------------------------- - //PoS - //based from ppcoin/novacoin approach - - /* - POS PROTOCOL, stake modifier - */ - //------------------------------------------------------------------------------------------------------------------- - - - -#pragma pack(push, 1) - struct stake_modifier_type - { - crypto::hash last_pow_id; - crypto::hash last_pos_kernel_id; - }; - - struct stake_kernel - { - - stake_modifier_type stake_modifier; - uint64_t block_timestamp; //this block timestamp - crypto::key_image kimage; - }; -#pragma pack(pop) - - struct pos_entry - { - uint64_t amount; - uint64_t index; - crypto::key_image keyimage; - uint64_t block_timestamp; - uint64_t stake_unlock_time; - //not for serialization - uint64_t wallet_index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(index) - KV_SERIALIZE(stake_unlock_time) - KV_SERIALIZE(block_timestamp) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(keyimage) - END_KV_SERIALIZE_MAP() - }; - -} // namespace currency - -POD_MAKE_HASHABLE(currency, account_public_address); -POD_MAKE_HASHABLE(currency, account_public_address_old); - -BLOB_SERIALIZER(currency::txout_to_key); - -#define SET_VARIANT_TAGS(type_name, id, json_tag) \ - VARIANT_TAG(binary_archive, type_name, id); \ - VARIANT_TAG(json_archive, type_name, json_tag) - - - -// txin_v variant currency -SET_VARIANT_TAGS(currency::txin_gen, 0, "gen"); -SET_VARIANT_TAGS(currency::txin_to_key, 1, "key"); -SET_VARIANT_TAGS(currency::txin_multisig, 2, "multisig"); -// txout_target_v variant definitions -SET_VARIANT_TAGS(currency::txout_to_key, 3, "key"); -SET_VARIANT_TAGS(currency::txout_multisig, 4, "multisig"); -SET_VARIANT_TAGS(currency::transaction, 5, "tx"); -SET_VARIANT_TAGS(currency::block, 6, "block"); -//attachment_v definitions -SET_VARIANT_TAGS(currency::tx_comment, 7, "comment"); -SET_VARIANT_TAGS(currency::tx_payer_old, 8, "payer"); -SET_VARIANT_TAGS(std::string, 9, "string"); -SET_VARIANT_TAGS(currency::tx_crypto_checksum, 10, "checksum"); -SET_VARIANT_TAGS(currency::tx_derivation_hint, 11, "derivation_hint"); -SET_VARIANT_TAGS(currency::tx_service_attachment, 12, "attachment"); -//SET_VARIANT_TAGS(currency::tx_onetime_secret_key, 13, "sec_key"); -SET_VARIANT_TAGS(currency::etc_tx_details_unlock_time, 14, "unlock_time"); -SET_VARIANT_TAGS(currency::etc_tx_details_expiration_time, 15, "expiration_time"); -SET_VARIANT_TAGS(currency::etc_tx_details_flags, 16, "flags"); -//txin_etc_details_v definitions -SET_VARIANT_TAGS(currency::signed_parts, 17, "signed_outs"); -//extra_v definitions -SET_VARIANT_TAGS(currency::extra_attachment_info, 18, "extra_attach_info"); -SET_VARIANT_TAGS(currency::extra_user_data, 19, "user_data"); -SET_VARIANT_TAGS(currency::extra_alias_entry_old, 20, "alias_entry"); -SET_VARIANT_TAGS(currency::extra_padding, 21, "extra_padding"); -SET_VARIANT_TAGS(crypto::public_key, 22, "pub_key"); -SET_VARIANT_TAGS(currency::etc_tx_flags16_t, 23, "etc_tx_flags16"); -SET_VARIANT_TAGS(uint16_t, 24, "derive_xor"); -//txout_v -SET_VARIANT_TAGS(currency::ref_by_id, 25, "ref_by_id"); -SET_VARIANT_TAGS(uint64_t, 26, "uint64_t"); -//etc -SET_VARIANT_TAGS(currency::etc_tx_time, 27, "etc_tx_time"); -SET_VARIANT_TAGS(uint32_t, 28, "uint32_t"); -SET_VARIANT_TAGS(currency::tx_receiver_old, 29, "payer"); // -- original -//SET_VARIANT_TAGS(currency::tx_receiver_old, 29, "receiver"); -SET_VARIANT_TAGS(currency::etc_tx_details_unlock_time2, 30, "unlock_time2"); - -SET_VARIANT_TAGS(currency::tx_payer, 31, "payer2"); -SET_VARIANT_TAGS(currency::tx_receiver, 32, "receiver2"); - -// @#@ TODO @#@ -SET_VARIANT_TAGS(currency::extra_alias_entry, 33, "alias_entry2"); - -//htlc -SET_VARIANT_TAGS(currency::txin_htlc, 34, "txin_htlc"); -SET_VARIANT_TAGS(currency::txout_htlc, 35, "txout_htlc"); - - - -#undef SET_VARIANT_TAGS diff --git a/src/currency_core/currency_boost_serialization.h b/src/currency_core/currency_boost_serialization.h deleted file mode 100644 index 96f95bd..0000000 --- a/src/currency_core/currency_boost_serialization.h +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "currency_basic.h" -#include "common/unordered_containers_boost_serialization.h" -#include "common/crypto_boost_serialization.h" -#include "offers_services_helpers.h" - -#define CURRENT_BLOCK_ARCHIVE_VER 2 -BOOST_CLASS_VERSION(currency::block, CURRENT_BLOCK_ARCHIVE_VER) - -namespace boost -{ - namespace serialization - { - - template - inline void serialize(Archive &a, currency::account_public_address &x, const boost::serialization::version_type ver) - { - //a & x.version; - a & x.flags; - a & x.spend_public_key; - a & x.view_public_key; - } - - template - inline void serialize(Archive &a, currency::account_public_address_old &x, const boost::serialization::version_type ver) - { - a & x.spend_public_key; - a & x.view_public_key; - } - - template - inline void serialize(Archive &a, currency::txout_to_key &x, const boost::serialization::version_type ver) - { - a & x.key; - a & x.mix_attr; - } - - template - inline void serialize(Archive &a, currency::txout_multisig &x, const boost::serialization::version_type ver) - { - a & x.minimum_sigs; - a & x.keys; - } - - template - inline void serialize(Archive &a, currency::txout_htlc &x, const boost::serialization::version_type ver) - { - a & x.expiration; - a & x.flags; - a & x.htlc_hash; - a & x.pkey_redeem; - a & x.pkey_refund; - } - - template - inline void serialize(Archive &a, currency::txin_gen &x, const boost::serialization::version_type ver) - { - a & x.height; - } - - - template - inline void serialize(Archive &a, currency::txin_multisig &x, const boost::serialization::version_type ver) - { - - a & x.amount; - a & x.multisig_out_id; - a & x.sigs_count; - a & x.etc_details; - } - - - template - inline void serialize(Archive &a, currency::txin_to_key &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.key_offsets; - a & x.k_image; - a & x.etc_details; - } - - template - inline void serialize(Archive &a, currency::txin_htlc &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.etc_details; - a & x.hltc_origin; - a & x.k_image; - a & x.key_offsets; - } - - template - inline void serialize(Archive &a, currency::tx_out &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.target; - } - - - - template - inline void serialize(Archive &a, currency::tx_comment &x, const boost::serialization::version_type ver) - { - a & x.comment; - } - - template - inline void serialize(Archive &a, currency::tx_payer_old &x, const boost::serialization::version_type ver) - { - a & x.acc_addr; - } - - template - inline void serialize(Archive &a, currency::tx_payer &x, const boost::serialization::version_type ver) - { - a & x.acc_addr; - } - - template - inline void serialize(Archive &a, currency::tx_receiver_old &x, const boost::serialization::version_type ver) - { - a & x.acc_addr; - } - - template - inline void serialize(Archive &a, currency::tx_receiver &x, const boost::serialization::version_type ver) - { - a & x.acc_addr; - } - - template - inline void serialize(Archive &a, currency::tx_crypto_checksum &x, const boost::serialization::version_type ver) - { - a & x.encrypted_key_derivation; - a & x.derivation_hash; - } - template - inline void serialize(Archive &a, currency::tx_derivation_hint &x, const boost::serialization::version_type ver) - { - a & x.msg; - } - - template - inline void serialize(Archive &a, currency::extra_attachment_info &x, const boost::serialization::version_type ver) - { - a & x.hsh; - a & x.sz; - a & x.cnt; - } - - template - inline void serialize(Archive &a, currency::extra_user_data &x, const boost::serialization::version_type ver) - { - a & x.buff; - } - - template - inline void serialize(Archive &a, currency::extra_alias_entry_base &x, const boost::serialization::version_type ver) - { - a & x.m_address; - a & x.m_text_comment; - a & x.m_view_key; - a & x.m_sign; - } - - template - inline void serialize(Archive &a, currency::extra_alias_entry &x, const boost::serialization::version_type ver) - { - a & x.m_alias; - a & static_cast(x); - } - - template - inline void serialize(Archive &a, currency::extra_alias_entry_base_old &x, const boost::serialization::version_type ver) - { - a & x.m_address; - a & x.m_text_comment; - a & x.m_view_key; - a & x.m_sign; - } - - template - inline void serialize(Archive &a, currency::extra_alias_entry_old &x, const boost::serialization::version_type ver) - { - a & x.m_alias; - a & static_cast(x); - } - - template - inline void serialize(Archive &a, currency::signed_parts &x, const boost::serialization::version_type ver) - { - a & x.n_outs; - a & x.n_extras; - } - - template - inline void serialize(Archive &a, currency::extra_padding &x, const boost::serialization::version_type ver) - { - a & x.buff; - } - - template - inline void serialize(Archive &a, currency::transaction &x, const boost::serialization::version_type ver) - { - a & x.version; - a & x.vin; - a & x.vout; - a & x.extra; - a & x.signatures; - a & x.attachment; - } - - template - inline void serialize(Archive &a, currency::keypair &kp, const boost::serialization::version_type ver) - { - a & kp.pub; - a & kp.sec; - } - - template - inline void serialize(Archive &a, currency::tx_service_attachment &at, const boost::serialization::version_type ver) - { - a & at.service_id; - a & at.security; - a & at.instruction; - a & at.body; - a & at.flags; - } - - template - inline void serialize(Archive &a, currency::etc_tx_details_unlock_time &at, const boost::serialization::version_type ver) - { - a & at.v; - } - - template - inline void serialize(Archive &a, currency::etc_tx_details_unlock_time2 &at, const boost::serialization::version_type ver) - { - a & at.unlock_time_array; - } - - template - inline void serialize(Archive &a, currency::etc_tx_details_expiration_time &at, const boost::serialization::version_type ver) - { - a & at.v; - } - - template - inline void serialize(Archive &a, currency::etc_tx_details_flags &at, const boost::serialization::version_type ver) - { - a & at.v; - } - - template - inline void serialize(Archive &a, currency::etc_tx_time &at, const boost::serialization::version_type ver) - { - a & at.v; - } - - template - inline void serialize(Archive &a, currency::etc_tx_flags16_t&at, const boost::serialization::version_type ver) - { - a & at.v; - } - - - template - inline void serialize(Archive &a, currency::block &b, const boost::serialization::version_type ver) - { - if (ver < CURRENT_BLOCK_ARCHIVE_VER) - { - throw std::runtime_error("wrong block serialization version"); - } - a & b.major_version; - a & b.minor_version; - a & b.timestamp; - a & b.prev_id; - a & b.nonce; - //------------------ - a & b.miner_tx; - a & b.tx_hashes; - a & b.flags; - } - - - template - inline void serialize(Archive &a, currency::ref_by_id &o, const boost::serialization::version_type ver) - { - a & o.tx_id; - a & o.n; - } - - - } -} diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h deleted file mode 100644 index 4dfa5e1..0000000 --- a/src/currency_core/currency_config.h +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#ifndef TESTNET -#define CURRENCY_FORMATION_VERSION 84 -#else -#define CURRENCY_FORMATION_VERSION 88 -#endif - -#define CURRENCY_GENESIS_NONCE (CURRENCY_FORMATION_VERSION + 101011010121) //bender's nightmare - - - -#define CURRENCY_MAX_BLOCK_NUMBER 500000000 -#define CURRENCY_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used! -#define CURRENCY_TX_MAX_ALLOWED_OUTS 2000 -#define CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX 0xc5 // addresses start with 'Zx' -#define CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x3678 // integrated addresses start with 'iZ' -#define CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX 0x36f8 // integrated addresses start with 'iZ' (new format) -#define CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX 0x98c8 // auditable addresses start with 'aZx' -#define CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX 0x8a49 // auditable integrated addresses start with 'aiZX' -#define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10 -#define CURRENT_TRANSACTION_VERSION 1 -#define HF1_BLOCK_MAJOR_VERSION 1 -#define CURRENT_BLOCK_MAJOR_VERSION 2 - -#define CURRENT_BLOCK_MINOR_VERSION 0 -#define CURRENCY_BLOCK_FUTURE_TIME_LIMIT 60*60*2 -#define CURRENCY_POS_BLOCK_FUTURE_TIME_LIMIT 60*20 - -#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60 - -#define POS_START_HEIGHT 0 - -#define CURRENCY_REWARD_BLOCKS_WINDOW 400 -#define CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE 125000 //size of block (bytes) after which reward for block calculated using block size -#define CURRENCY_COINBASE_BLOB_RESERVED_SIZE 1100 -#define CURRENCY_MAX_TRANSACTION_BLOB_SIZE (CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE - CURRENCY_COINBASE_BLOB_RESERVED_SIZE*2) -#define CURRENCY_FREE_TX_MAX_BLOB_SIZE 1024 // soft txpool-based limit for free-of-charge txs (such as BC_OFFERS_SERVICE_INSTRUCTION_DEL) -#define CURRENCY_DISPLAY_DECIMAL_POINT 12 - -// COIN - number of smallest units in one coin -#define COIN ((uint64_t)1000000000000) // pow(10, CURRENCY_DISPLAY_DECIMAL_POINT) -#define BASE_REWARD_DUST_THRESHOLD ((uint64_t)1000000) // pow(10, 6) - change this will cause hard-fork! -#define DEFAULT_DUST_THRESHOLD ((uint64_t)0) - -#define TX_DEFAULT_FEE ((uint64_t)10000000000) // .01 -#define TX_MINIMUM_FEE ((uint64_t)10000000000) // .01 - -#define CURRENCY_BLOCK_REWARD 1000000000000 // 1.0 coin == pow(10, CURRENCY_DISPLAY_DECIMAL_POINT) - - -#define WALLET_MAX_ALLOWED_OUTPUT_AMOUNT ((uint64_t)0xffffffffffffffffLL) -#define CURRENCY_MINER_TX_MAX_OUTS CURRENCY_TX_MAX_ALLOWED_OUTS - -#define DIFFICULTY_STARTER 1 -#define DIFFICULTY_POS_TARGET 120 // seconds -#define DIFFICULTY_POW_TARGET 120 // seconds -#define DIFFICULTY_TOTAL_TARGET ((DIFFICULTY_POS_TARGET + DIFFICULTY_POW_TARGET) / 4) -#define DIFFICULTY_WINDOW 720 // blocks -#define DIFFICULTY_LAG 15 // !!! -#define DIFFICULTY_CUT 60 // timestamps to cut after sorting -#define DIFFICULTY_BLOCKS_COUNT (DIFFICULTY_WINDOW + DIFFICULTY_LAG) - -#define CURRENCY_BLOCKS_PER_DAY ((60*60*24)/(DIFFICULTY_TOTAL_TARGET)) - - -#define TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW 20 -#define TX_EXPIRATION_MEDIAN_SHIFT ((TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW)/2)*DIFFICULTY_TOTAL_TARGET - -#define CURRENCY_LOCKED_TX_ALLOWED_DELTA_SECONDS (DIFFICULTY_TOTAL_TARGET * CURRENCY_LOCKED_TX_ALLOWED_DELTA_BLOCKS) -#define CURRENCY_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1 - -#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN DIFFICULTY_TOTAL_TARGET //just alias - -#define MAX_ALIAS_PER_BLOCK 1000 -#define ALIAS_COAST_PERIOD CURRENCY_BLOCKS_PER_DAY*7 //week -#define ALIAS_COAST_RECENT_PERIOD CURRENCY_BLOCKS_PER_DAY*8 //week + 1 day (we guarantee split depth at least 1 day) -#define ALIAS_VERY_INITAL_COAST ((uint64_t)10000) // to avoid split when default fee changed -#define ALIAS_MEDIAN_RECALC_INTERWAL CURRENCY_BLOCKS_PER_DAY - - -#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 2000 //by default, blocks ids count in synchronizing -#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading -#define BLOCKS_SYNCHRONIZING_DEFAULT_SIZE 2000000 //by default keep synchronizing packets not bigger then 2MB -#define CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT 500 -#define CURRENCY_PROTOCOL_MAX_TXS_REQUEST_COUNT 500 - - -#define CURRENCY_ALT_BLOCK_LIVETIME_COUNT (CURRENCY_BLOCKS_PER_DAY*7)//one week -#define CURRENCY_ALT_BLOCK_MAX_COUNT 43200 //30 days -#define CURRENCY_MEMPOOL_TX_LIVETIME 345600 //seconds, 4 days - - -#ifndef TESTNET -#define P2P_DEFAULT_PORT 11121 -#define RPC_DEFAULT_PORT 11211 -#define STRATUM_DEFAULT_PORT 11777 -#define P2P_NETWORK_ID_TESTNET_FLAG 0 -#define P2P_MAINTAINERS_PUB_KEY "8f138bb73f6d663a3746a542770781a09579a7b84cb4125249e95530824ee607" -#else -#define P2P_DEFAULT_PORT (11112 + CURRENCY_FORMATION_VERSION) -#define RPC_DEFAULT_PORT 12111 -#define STRATUM_DEFAULT_PORT 11888 -#define STRARUM_DEFAULT_PORT 51113 -#define P2P_NETWORK_ID_TESTNET_FLAG 1 -#define P2P_MAINTAINERS_PUB_KEY "aaa2d7aabc8d383fd53a3ae898697b28f236ceade6bafc1eecff413a6a02272a" -#endif - -#define P2P_NETWORK_ID_VER (CURRENCY_FORMATION_VERSION+0) - -#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT 4000 - -#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000 -#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000 - -#define P2P_DEFAULT_CONNECTIONS_COUNT 8 -#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //seconds -#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size -#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250 -#define P2P_DEFAULT_CONNECTION_TIMEOUT 5000 //5 seconds -#define P2P_DEFAULT_PING_CONNECTION_TIMEOUT 2000 //2 seconds -#define P2P_DEFAULT_INVOKE_TIMEOUT 60*2*1000 //2 minutes -#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 10000 //10 seconds -#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70 -#define P2P_FAILED_ADDR_FORGET_SECONDS (60*5) //5 minutes - -#define P2P_IP_BLOCKTIME (60*60*24) //24 hours -#define P2P_IP_FAILS_BEFOR_BLOCK 10 -#define P2P_IDLE_CONNECTION_KILL_INTERVAL (5*60) //5 minutes - -//PoS definitions -#define POS_SCAN_WINDOW 60*10 //seconds // 10 minutes -#define POS_SCAN_STEP 15 //seconds -#define POS_MAX_ACTUAL_TIMESTAMP_TO_MINED (POS_SCAN_WINDOW+100) - -#define POS_STARTER_KERNEL_HASH "00000000000000000006382a8d8f94588ce93a1351924f6ccb9e07dd287c6e4b" -#define POS_MODFIFIER_INTERVAL 10 -#define POS_WALLET_MINING_SCAN_INTERVAL POS_SCAN_STEP //seconds -#define POS_MINIMUM_COINSTAKE_AGE 10 // blocks count - - -#define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare -#define WALLET_FILE_SIGNATURE_V2 0x1111011201101011LL // another Bender's nightmare -#define WALLET_FILE_BINARY_HEADER_VERSION_INITAL 1000 -#define WALLET_FILE_BINARY_HEADER_VERSION_2 1001 -//#define WALLET_FILE_BINARY_HEADER_VERSION_3 1002 - -#define WALLET_FILE_MAX_KEYS_SIZE 10000 // -#define WALLET_BRAIN_DATE_OFFSET 1543622400 -#define WALLET_BRAIN_DATE_QUANTUM 604800 //by last word we encode a number of week since launch of the project AND password flag, - //which let us to address tools::mnemonic_encoding::NUMWORDS weeks after project launch - //which is about 15 years -#define WALLET_BRAIN_DATE_MAX_WEEKS_COUNT 800 - -#define OFFER_MAXIMUM_LIFE_TIME (60*60*24*30) // 30 days - -#define GUI_BLOCKS_DISPLAY_COUNT 40 -#define GUI_DISPATCH_QUE_MAXSIZE 100 - -#define ALLOW_DEBUG_COMMANDS - - - -#define CURRENCY_NAME_ABR "ZANO" -#define CURRENCY_NAME_BASE "Zano" -#define CURRENCY_NAME_SHORT_BASE "Zano" -#ifndef TESTNET -#define CURRENCY_NAME CURRENCY_NAME_BASE -#define CURRENCY_NAME_SHORT CURRENCY_NAME_SHORT_BASE -#else -#define CURRENCY_NAME CURRENCY_NAME_BASE"_testnet" -#define CURRENCY_NAME_SHORT CURRENCY_NAME_SHORT_BASE"_testnet" -#endif - -//premine -#define PREMINE_AMOUNT (17517203000000000000U) // 13827203.0 reserved for coinswap, 3690000.0 - premine - -//alias registration wallet -#define ALIAS_REWARDS_ACCOUNT_SPEND_PUB_KEY "0000000000000000000000000000000000000000000000000000000000000000" //burn alias money -#define ALIAS_REWARDS_ACCOUNT_VIEW_PUB_KEY "0000000000000000000000000000000000000000000000000000000000000000" //burn alias money -#define ALIAS_REWARDS_ACCOUNT_VIEW_SEC_KEY "0000000000000000000000000000000000000000000000000000000000000000" //burn alias money - -#define ALIAS_MINIMUM_PUBLIC_SHORT_NAME_ALLOWED 6 -#define ALIAS_SHORT_NAMES_VALIDATION_PUB_KEY "37947f7b6a5268c5d0a48bde73d7a426f0b5f24648f74024279540207dc70031" - - -#define ALIAS_NAME_MAX_LEN 255 -#define ALIAS_VALID_CHARS "0123456789abcdefghijklmnopqrstuvwxyz-." -#define ALIAS_COMMENT_MAX_SIZE_BYTES 400 - -#define CURRENCY_CORE_INSTANCE_LOCK_FILE "lock.lck" - - -#define CURRENCY_POOLDATA_FOLDERNAME_OLD "poolstate" -#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD "blockchain" - - -#define CURRENCY_POOLDATA_FOLDERNAME_PREFIX "poolstate_" -#define CURRENCY_POOLDATA_FOLDERNAME_SUFFIX "_v1" -#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX "blockchain_" -#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX "_v1" - -#define P2P_NET_DATA_FILENAME "p2pstate.bin" -#define MINER_CONFIG_FILENAME "miner_conf.json" -#define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin" -#define GUI_CONFIG_FILENAME "gui_settings.json" -#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json" - - - -#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3 -#define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1 - -#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 11 -#define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 1 - - -#define BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER CURRENCY_FORMATION_VERSION + BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 9 -#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin" - -#ifndef TESTNET -#define WALLET_FILE_SERIALIZATION_VERSION 153 -#else -#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+69) -#endif - -#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31) - -//hard forks section -#define BLOCK_MAJOR_VERSION_GENESIS 1 -#define BLOCK_MINOR_VERSION_GENESIS 0 -#define BLOCK_MAJOR_VERSION_INITIAL 0 -#ifndef TESTNET -#define ZANO_HARDFORK_01_AFTER_HEIGHT 194624 -#define ZANO_HARDFORK_02_AFTER_HEIGHT 999999 -#define ZANO_HARDFORK_03_AFTER_HEIGHT 1082577 -#else -#define ZANO_HARDFORK_01_AFTER_HEIGHT 1440 -#define ZANO_HARDFORK_02_AFTER_HEIGHT 1800 -#define ZANO_HARDFORK_03_AFTER_HEIGHT 1801 -#endif - - - -static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit"); -static_assert(PREMINE_AMOUNT / WALLET_MAX_ALLOWED_OUTPUT_AMOUNT < CURRENCY_MINER_TX_MAX_OUTS, "Premine can't be divided into reasonable number of outs"); - diff --git a/src/currency_core/currency_core.cpp b/src/currency_core/currency_core.cpp deleted file mode 100644 index cd0b5d8..0000000 --- a/src/currency_core/currency_core.cpp +++ /dev/null @@ -1,706 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "include_base_utils.h" -using namespace epee; - -#include -#include -#include "currency_core.h" -#include "common/command_line.h" -#include "common/util.h" -#include "warnings.h" -#include "crypto/crypto.h" -#include "currency_core/currency_config.h" -#include "currency_format_utils.h" -#include "misc_language.h" -#include "string_coding.h" -#include "tx_semantic_validation.h" - -#define MINIMUM_REQUIRED_FREE_SPACE_BYTES (1024 * 1024 * 100) - -DISABLE_VS_WARNINGS(4355) -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "core" -ENABLE_CHANNEL_BY_DEFAULT("core"); -namespace currency -{ - - //----------------------------------------------------------------------------------------------- - core::core(i_currency_protocol* pprotocol) - : m_mempool(m_blockchain_storage, pprotocol) - , m_blockchain_storage(m_mempool) - , m_miner(this, m_blockchain_storage) - , m_miner_address(boost::value_initialized()) - , m_starter_message_showed(false) - , m_critical_error_handler(nullptr) - , m_stop_after_height(0) - { - set_currency_protocol(pprotocol); - } - //----------------------------------------------------------------------------------- - void core::set_currency_protocol(i_currency_protocol* pprotocol) - { - if(pprotocol) - m_pprotocol = pprotocol; - else - m_pprotocol = &m_protocol_stub; - - m_mempool.set_protocol(m_pprotocol); - } - //----------------------------------------------------------------------------------- - void core::set_critical_error_handler(i_critical_error_handler* handler) - { - m_critical_error_handler = handler; - } - //----------------------------------------------------------------------------------- - bool core::set_checkpoints(checkpoints&& chk_pts) - { - return m_blockchain_storage.set_checkpoints(std::move(chk_pts)); - } - //----------------------------------------------------------------------------------- - void core::init_options(boost::program_options::options_description& desc) - { - blockchain_storage::init_options(desc); - } - //----------------------------------------------------------------------------------------------- - std::string core::get_config_folder() - { - return m_config_folder; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_command_line(const boost::program_options::variables_map& vm) - { - m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); - m_stop_after_height = static_cast(command_line::get_arg(vm, command_line::arg_stop_after_height)); - if (m_stop_after_height != 0) - { - LOG_PRINT_YELLOW("Daemon will STOP after block " << m_stop_after_height, LOG_LEVEL_0); - } - return true; - } - //----------------------------------------------------------------------------------------------- - uint64_t core::get_current_blockchain_size() const - { - return m_blockchain_storage.get_current_blockchain_size(); - } - //----------------------------------------------------------------------------------------------- - uint64_t core::get_top_block_height() const - { - return m_blockchain_storage.get_top_block_height(); - } - //----------------------------------------------------------------------------------------------- - bool core::get_blockchain_top(uint64_t& height, crypto::hash& top_id) const - { - top_id = m_blockchain_storage.get_top_block_id(height); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) - { - return m_blockchain_storage.get_blocks(start_offset, count, blocks, txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks) - { - return m_blockchain_storage.get_blocks(start_offset, count, blocks); - } //----------------------------------------------------------------------------------------------- - bool core::get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs) - { - return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_transaction(const crypto::hash &h, transaction &tx) - { - std::vector ids; - ids.push_back(h); - std::list ltx; - std::list missing; - if (m_blockchain_storage.get_transactions(ids, ltx, missing)) - { - if (ltx.size() > 0) - { - tx = *ltx.begin(); - return true; - } - } - - return false; - } - //----------------------------------------------------------------------------------------------- - bool core::get_alternative_blocks(std::list& blocks) - { - return m_blockchain_storage.get_alternative_blocks(blocks); - } - //----------------------------------------------------------------------------------------------- - size_t core::get_alternative_blocks_count() - { - return m_blockchain_storage.get_alternative_blocks_count(); - } - //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm) - { - bool r = handle_command_line(vm); - - uint64_t available_space = 0; - CHECK_AND_ASSERT_MES(!check_if_free_space_critically_low(&available_space), false, "free space in data folder is critically low: " << std::fixed << available_space / (1024 * 1024) << " MB"); - - r = m_mempool.init(m_config_folder, vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); - - r = m_blockchain_storage.init(m_config_folder, vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); - - r = m_miner.init(vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner"); - - //check if tx_pool module synchronized with blockchaine storage -// if (m_blockchain_storage.get_top_block_id() != m_mempool.get_last_core_hash()) -// { -// m_mempool.clear(); -// LOG_PRINT_MAGENTA("Tx pool had been reset due to missmatch top block id", LOG_LEVEL_0); -// } - - return load_state_data(); - } - //----------------------------------------------------------------------------------------------- - bool core::set_genesis_block(const block& b) - { - return m_blockchain_storage.reset_and_set_genesis_block(b); - } - //----------------------------------------------------------------------------------------------- - bool core::load_state_data() - { - // may be some code later - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::deinit() - { - //m_mempool.set_last_core_hash(m_blockchain_storage.get_top_block_id()); - - m_miner.stop(); - m_miner.deinit(); - m_mempool.deinit(); - m_blockchain_storage.deinit(); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block, const crypto::hash& tx_hash_ /* = null_hash */) - { - TIME_MEASURE_START_MS(wait_lock_time); - CRITICAL_REGION_LOCAL(m_incoming_tx_lock); - TIME_MEASURE_FINISH_MS(wait_lock_time); - - crypto::hash tx_hash = tx_hash_; - if (tx_hash == null_hash) - tx_hash = get_transaction_hash(tx); - - TIME_MEASURE_START_MS(add_new_tx_time); - bool r = add_new_tx(tx, tx_hash, get_object_blobsize(tx), tvc, kept_by_block); - TIME_MEASURE_FINISH_MS(add_new_tx_time); - - if(tvc.m_verification_failed) - {LOG_PRINT_RED_L0("Transaction verification failed: " << tx_hash);} - else if(tvc.m_verification_impossible) - {LOG_PRINT_RED_L0("Transaction verification impossible: " << tx_hash);} - - if (tvc.m_added_to_pool) - { - LOG_PRINT_L2("incoming tx " << tx_hash << " was added to the pool"); - } - LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX1]: timing " << wait_lock_time - << "/" << add_new_tx_time); - return r; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool kept_by_block) - { - CHECK_AND_ASSERT_MES(!kept_by_block, false, "Transaction associated with block came throw handle_incoming_tx!(not allowed anymore)"); - - tvc = boost::value_initialized(); - //want to process all transactions sequentially - TIME_MEASURE_START_MS(wait_lock_time); - CRITICAL_REGION_LOCAL(m_incoming_tx_lock); - TIME_MEASURE_FINISH_MS(wait_lock_time); - - if(tx_blob.size() > CURRENCY_MAX_TRANSACTION_BLOB_SIZE) - { - LOG_PRINT_L0("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected"); - tvc.m_verification_failed = true; - return false; - } - - crypto::hash tx_hash = null_hash; - transaction tx; - TIME_MEASURE_START_MS(parse_tx_time); - if(!parse_tx_from_blob(tx, tx_hash, tx_blob)) - { - LOG_PRINT_L0("WRONG TRANSACTION BLOB, Failed to parse, rejected"); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_MS(parse_tx_time); - - TIME_MEASURE_START_MS(check_tx_semantic_time); - if(!validate_tx_semantic(tx, tx_blob.size())) - { - LOG_PRINT_L0("WRONG TRANSACTION SEMANTICS, Failed to check tx " << tx_hash << " semantic, rejected"); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_MS(check_tx_semantic_time); - - bool r = handle_incoming_tx(tx, tvc, kept_by_block, tx_hash); - LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX2]: timing " << wait_lock_time - << "/" << parse_tx_time - << "/" << check_tx_semantic_time); - return r; - } - //----------------------------------------------------------------------------------------------- - bool core::get_stat_info(const core_stat_info::params& pr, core_stat_info& st_inf) - { - st_inf.mining_speed = m_miner.get_speed(); - st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count(); - st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_size(); - st_inf.tx_pool_size = m_mempool.get_transactions_count(); - st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_top_block_id()); - - std::list blocks; - m_blockchain_storage.get_blocks(m_blockchain_storage.get_current_blockchain_size() - pr.chain_len, static_cast(pr.chain_len), blocks); - for (auto& b : blocks) - { - st_inf.main_chain_blocks.push_back(chain_entry()); - st_inf.main_chain_blocks.back().h = get_block_height(b); - st_inf.main_chain_blocks.back().id = epee::string_tools::pod_to_hex(get_block_hash(b)); - } - blocks.clear(); - m_blockchain_storage.get_alternative_blocks(blocks); - for (auto& b : blocks) - { - st_inf.alt_chain_blocks.push_back(chain_entry()); - st_inf.alt_chain_blocks.back().h = get_block_height(b); - st_inf.alt_chain_blocks.back().id = epee::string_tools::pod_to_hex(get_block_hash(b)); - } - blocks.clear(); - - auto ch_locked_proxy_container = epee::log_space::get_channels_errors_stat_container(); - epee::log_space::channels_err_stat_container_type& ch_container_std = *ch_locked_proxy_container; - for (const auto& entry : ch_container_std) - { - st_inf.errors_stat.push_back(error_stat_entry()); - st_inf.errors_stat.back().channel = entry.first; - st_inf.errors_stat.back().err_count = entry.second; - } - st_inf.epic_failure_happend = m_blockchain_storage.get_performnce_data().epic_failure_happend; - epee::log_space::log_singletone::get_journal_items(st_inf.errors_journal, pr.logs_journal_len); - //check deadlocks - auto dl_list = epee::deadlock_guard_singleton::get_deadlock_journal(); - if (dl_list.size()) - { - st_inf.epic_failure_happend = true; - st_inf.errors_journal.insert(st_inf.errors_journal.end(), dl_list.begin(), dl_list.end()); - } - - return true; - } - - - - - //----------------------------------------------------------------------------------------------- - bool core::add_new_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block) - { - crypto::hash tx_hash = null_hash; - uint64_t blob_size = 0; - get_transaction_hash(tx, tx_hash, blob_size); - return add_new_tx(tx, tx_hash, blob_size, tvc, kept_by_block); - } - //----------------------------------------------------------------------------------------------- - size_t core::get_blockchain_total_transactions() - { - return m_blockchain_storage.get_total_transactions(); - } - //----------------------------------------------------------------------------------------------- - bool core::get_outs(uint64_t amount, std::list& pkeys) - { - return m_blockchain_storage.get_outs(amount, pkeys); - } - //----------------------------------------------------------------------------------------------- - bool core::add_new_tx(const transaction& tx, const crypto::hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool kept_by_block) - { - if(m_mempool.have_tx(tx_hash)) - { - LOG_PRINT_L3("add_new_tx: already have tx " << tx_hash << " in the pool"); - return true; - } - - if(m_blockchain_storage.have_tx(tx_hash)) - { - LOG_PRINT_L3("add_new_tx: already have tx " << tx_hash << " in the blockchain"); - return true; - } - - return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, kept_by_block); - } - //----------------------------------------------------------------------------------------------- - bool core::get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos, const pos_entry& pe) - { - return m_blockchain_storage.create_block_template(b, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe); - } - //----------------------------------------------------------------------------------------------- - bool core::get_block_template(const create_block_template_params& params, create_block_template_response& resp) - { - return m_blockchain_storage.create_block_template(params, resp); - } - //----------------------------------------------------------------------------------------------- - bool core::find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const - { - return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp); - } - //----------------------------------------------------------------------------------------------- - bool core::find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const - { - return m_blockchain_storage.find_blockchain_supplement(qblock_ids, blocks, total_height, start_height, max_count); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain(uint64_t start_index, uint64_t end_index) - { - m_blockchain_storage.print_blockchain(start_index, end_index); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain_index() - { - m_blockchain_storage.print_blockchain_index(); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain_outs(const std::string& file) - { - m_blockchain_storage.print_blockchain_outs(file); - } - //----------------------------------------------------------------------------------------------- - bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) - { - return m_blockchain_storage.get_random_outs_for_amounts(req, res); - } - //----------------------------------------------------------------------------------------------- - bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) - { - return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs); - } - //----------------------------------------------------------------------------------------------- - void core::pause_mine() - { - m_miner.pause(); - } - //----------------------------------------------------------------------------------------------- - void core::resume_mine() - { - m_miner.resume(); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_block_found(const block& b, block_verification_context* p_verification_result, bool need_update_miner_block_template) - { - TIME_MEASURE_START_MS(time_total_ms); - block_verification_context bvc = boost::value_initialized(); - if (!p_verification_result) - p_verification_result = &bvc; - - m_miner.pause(); - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([this]() - { - m_miner.resume(); - }); - - TIME_MEASURE_START_MS(time_add_new_block_ms); - m_blockchain_storage.add_new_block(b, *p_verification_result); - TIME_MEASURE_FINISH_MS(time_add_new_block_ms); - - - //anyway - update miner template - TIME_MEASURE_START_MS(time_update_block_template_ms); - if (need_update_miner_block_template) - update_miner_block_template(); - TIME_MEASURE_FINISH_MS(time_update_block_template_ms); - - uint64_t time_pack_txs_ms = 0, time_relay_ms = 0; - - if (p_verification_result->m_verification_failed || !p_verification_result->m_added_to_main_chain) - { - LOG_PRINT2("failed_mined_blocks.log", "verification_failed: " << p_verification_result->m_verification_failed << ", added_to_main_chain: " << p_verification_result->m_added_to_main_chain << ENDL << - currency::obj_to_json_str(b), LOG_LEVEL_0); - } - CHECK_AND_ASSERT_MES(!p_verification_result->m_verification_failed, false, "mined block has failed to pass verification: id " << get_block_hash(b) << " @ height " << get_block_height(b) << " prev_id: " << b.prev_id); - - if(p_verification_result->m_added_to_main_chain) - { - time_pack_txs_ms = epee::misc_utils::get_tick_count(); - currency_connection_context exclude_context = boost::value_initialized(); - NOTIFY_NEW_BLOCK::request arg = AUTO_VAL_INIT(arg); - arg.hop = 0; - arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_size(); - std::list missed_txs; - std::list txs; - m_blockchain_storage.get_transactions(b.tx_hashes, txs, missed_txs); - if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) - { - LOG_PRINT_L0("Block found (id " << get_block_hash(b) << " @ height " << get_block_height(b) << ") but it seems that reorganize just happened after that, do not relay this block"); - return true; - } - if (txs.size() != b.tx_hashes.size() || missed_txs.size() != 0) - { - std::stringstream ss; - ss << "txs:" << ENDL; - for (auto& t : txs) - ss << get_transaction_hash(t) << ENDL; - ss << "missed txs:" << ENDL; - for (auto& tx_id : missed_txs) - ss << tx_id << ENDL; - LOG_ERROR("can't find some transactions in found block: " << get_block_hash(b) << ", txs.size()=" << txs.size() - << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()=" << missed_txs.size() << ENDL << ss.str()); - return false; - } - - block_to_blob(b, arg.b.block); - //pack transactions - for(auto& tx : txs) - arg.b.txs.push_back(t_serializable_object_to_blob(tx)); - - TIME_MEASURE_FINISH_MS(time_pack_txs_ms); - - time_relay_ms = epee::misc_utils::get_tick_count(); - m_pprotocol->relay_block(arg, exclude_context); - TIME_MEASURE_FINISH_MS(time_relay_ms); - } - - TIME_MEASURE_FINISH_MS(time_total_ms); - LOG_PRINT_L2("handle_block_found timings (ms): total: " << time_total_ms << ", add new block: " << time_add_new_block_ms << ", update template: " << time_update_block_template_ms << ", pack txs: " << time_pack_txs_ms << ", relay: " << time_relay_ms); - - return p_verification_result->m_added_to_main_chain; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_block_found(const block& b, block_verification_context* p_verification_result /* = nullptr */) - { - return handle_block_found(b, p_verification_result, true); - } - //----------------------------------------------------------------------------------------------- - void core::on_synchronized() - { - m_miner.on_synchronized(); - } - bool core::get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count) - { - return m_blockchain_storage.get_backward_blocks_sizes(from_height, sizes, count); - } - //----------------------------------------------------------------------------------------------- - bool core::add_new_block(const block& b, block_verification_context& bvc) - { - bool r = m_blockchain_storage.add_new_block(b, bvc); - if (r && bvc.m_added_to_main_chain) - { - uint64_t h = get_block_height(b); - auto& crc = m_blockchain_storage.get_core_runtime_config(); - if (h == crc.hard_fork_01_starts_after_height + 1) - { LOG_PRINT_GREEN("Hardfork 1 activated at height " << h, LOG_LEVEL_0); } - else if (h == crc.hard_fork_02_starts_after_height + 1) - { LOG_PRINT_GREEN("Hardfork 2 activated at height " << h, LOG_LEVEL_0); } - - if (h == m_stop_after_height) - { - LOG_PRINT_YELLOW("Reached block " << h << ", the daemon will now stop as requested", LOG_LEVEL_0); - if (m_critical_error_handler) - return m_critical_error_handler->on_immediate_stop_requested(); - return false; - } - } - return r; - } - //----------------------------------------------------------------------------------------------- - bool core::parse_block(const blobdata& block_blob, block& b, block_verification_context& bvc) - { - if (block_blob.size() > get_max_block_size()) - { - LOG_PRINT_L0("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); - bvc.m_verification_failed = true; - return false; - } - - b = AUTO_VAL_INIT_T(block); - if (!parse_and_validate_block_from_blob(block_blob, b)) - { - LOG_PRINT_L0("Failed to parse and validate new block"); - bvc.m_verification_failed = true; - return false; - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::pre_validate_block(block& b, block_verification_context& bvc, const crypto::hash& id) - { - return m_blockchain_storage.pre_validate_relayed_block(b, bvc, id); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate) - { - block b = AUTO_VAL_INIT(b); - if (!parse_block(block_blob, b, bvc)) - { - LOG_PRINT_L0("Failed to parse and validate new block"); - bvc.m_verification_failed = true; - return false; - } - return handle_incoming_block(b, bvc, update_miner_blocktemplate); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_block(const block& b, block_verification_context& bvc, bool update_miner_blocktemplate) - { - bool r = add_new_block(b, bvc); - if (update_miner_blocktemplate && bvc.m_added_to_main_chain) - update_miner_block_template(); - return r; - } - //----------------------------------------------------------------------------------------------- - crypto::hash core::get_tail_id() - { - return m_blockchain_storage.get_top_block_id(); - } - //----------------------------------------------------------------------------------------------- - size_t core::get_pool_transactions_count() - { - return m_mempool.get_transactions_count(); - } - //----------------------------------------------------------------------------------------------- - bool core::have_block(const crypto::hash& id) - { - return m_blockchain_storage.have_block(id); - } - //----------------------------------------------------------------------------------------------- - bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob) - { - return parse_and_validate_tx_from_blob(blob, tx, tx_hash); - } - //----------------------------------------------------------------------------------------------- - bool core::get_pool_transactions(std::list& txs) - { - return m_mempool.get_transactions(txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_short_chain_history(std::list& ids) - { - return m_blockchain_storage.get_short_chain_history(ids); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, currency_connection_context& context)const - { - return m_blockchain_storage.handle_get_objects(arg, rsp); - } - //----------------------------------------------------------------------------------------------- - crypto::hash core::get_block_id_by_height(uint64_t height)const - { - return m_blockchain_storage.get_block_id_by_height(height); - } - //----------------------------------------------------------------------------------------------- - bool core::get_block_by_hash(const crypto::hash &h, block &blk) { - return m_blockchain_storage.get_block_by_hash(h, blk); - } - //----------------------------------------------------------------------------------------------- -// void core::get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid) { -// m_blockchain_storage.get_all_known_block_ids(main, alt, invalid); -// } - //----------------------------------------------------------------------------------------------- - std::string core::print_pool(bool short_format) - { - return m_mempool.print_pool(short_format); - } - //----------------------------------------------------------------------------------------------- - bool core::update_miner_block_template() - { - notify_blockchain_update_listeners(); - m_miner.on_block_chain_update(); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::on_idle() - { - if(!m_starter_message_showed) - { - LOG_PRINT_L0(ENDL - << "**********************************************************************" << ENDL - << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL - << ENDL - << "You can adjust verbosity by using command: \"set_log \", where 0 is the least verbose and 3 is the most." << ENDL - << ENDL - << "Use \"help\" command to list all available commands." << ENDL - << ENDL - << "Note: in case you need to interrupt the process, use \"exit\" command. Otherwise, the current progress might not be saved." << ENDL - << "**********************************************************************"); - m_starter_message_showed = true; - } - - m_prune_alt_blocks_interval.do_call([this](){return m_blockchain_storage.prune_aged_alt_blocks();}); - m_check_free_space_interval.do_call([this](){ check_free_space(); return true; }); - m_miner.on_idle(); - m_mempool.on_idle(); - return true; - } - //----------------------------------------------------------------------------------------------- - void core::add_blockchain_update_listener(i_blockchain_update_listener *l) - { - CRITICAL_REGION_LOCAL(m_blockchain_update_listeners_lock); - m_blockchain_update_listeners.push_back(l); - } - //----------------------------------------------------------------------------------------------- - void core::remove_blockchain_update_listener(i_blockchain_update_listener *l) - { - CRITICAL_REGION_LOCAL(m_blockchain_update_listeners_lock); - m_blockchain_update_listeners.erase(std::remove(m_blockchain_update_listeners.begin(), m_blockchain_update_listeners.end(), l), m_blockchain_update_listeners.end()); - } - //----------------------------------------------------------------------------------------------- - void core::notify_blockchain_update_listeners() - { - CRITICAL_REGION_LOCAL(m_blockchain_update_listeners_lock); - for(auto l : m_blockchain_update_listeners) - l->on_blockchain_update(); - } - //----------------------------------------------------------------------------------------------- - bool core::check_if_free_space_critically_low(uint64_t* p_available_space /* = nullptr */) - { - namespace fs = boost::filesystem; - - try - { - CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_config_folder), false, "create_directories_if_necessary failed: " << m_config_folder); - std::wstring config_folder_w = epee::string_encoding::utf8_to_wstring(m_config_folder); - fs::space_info si = fs::space(config_folder_w); - if (p_available_space != nullptr) - *p_available_space = si.available; - return si.available < MINIMUM_REQUIRED_FREE_SPACE_BYTES; - } - catch (std::exception& e) - { - LOG_ERROR("failed to determine free space: " << e.what()); - return false; - } - catch (...) - { - LOG_ERROR("failed to determine free space: unknown exception"); - return false; - } - } - - void core::check_free_space() - { - if (!m_critical_error_handler) - return; - - uint64_t available_space = 0; - if (check_if_free_space_critically_low(&available_space)) - m_critical_error_handler->on_critical_low_free_space(available_space, MINIMUM_REQUIRED_FREE_SPACE_BYTES); - } - //----------------------------------------------------------------------------------------------- - -} diff --git a/src/currency_core/currency_core.h b/src/currency_core/currency_core.h deleted file mode 100644 index 354fd77..0000000 --- a/src/currency_core/currency_core.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -#include "p2p/net_node_common.h" -#include "currency_protocol/currency_protocol_handler_common.h" -#include "storages/portable_storage_template_helper.h" -#include "tx_pool.h" -#include "blockchain_storage.h" -#include "miner.h" -#include "connection_context.h" -#include "currency_core/currency_stat_info.h" -#include "warnings.h" -#include "crypto/hash.h" - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4355) - -namespace currency -{ - struct i_blockchain_update_listener - { - virtual void on_blockchain_update() = 0; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - class core: public i_miner_handler - { - public: - core(i_currency_protocol* pprotocol); - bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, currency_connection_context& context)const ; - bool on_idle(); - bool handle_incoming_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block, const crypto::hash& tx_hash_ = null_hash); - bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool kept_by_block); - bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true); - bool handle_incoming_block(const block& b, block_verification_context& bvc, bool update_miner_blocktemplate = true); - bool parse_block(const blobdata& block_blob, block& b, block_verification_context& bvc); - bool pre_validate_block(block& b, block_verification_context& bvc, const crypto::hash& id); - i_currency_protocol* get_protocol(){return m_pprotocol;} - tx_memory_pool& get_tx_pool(){ return m_mempool; }; - - bool handle_block_found(const block& b, block_verification_context* p_verification_result, bool need_update_miner_block_template); - - //-------------------- i_miner_handler ----------------------- - virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr); - virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp); - bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()); - - miner& get_miner(){ return m_miner; } - static void init_options(boost::program_options::options_description& desc); - bool init(const boost::program_options::variables_map& vm); - bool set_genesis_block(const block& b); - bool deinit(); - uint64_t get_current_blockchain_size() const; - uint64_t get_top_block_height() const; - std::string get_config_folder(); - bool get_blockchain_top(uint64_t& heeight, crypto::hash& top_id) const; - bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs); - bool get_blocks(uint64_t start_offset, size_t count, std::list& blocks); - template - bool get_blocks(const t_ids_container& block_ids, t_blocks_container& blocks, t_missed_container& missed_bs) - { - return m_blockchain_storage.get_blocks(block_ids, blocks, missed_bs); - } - crypto::hash get_block_id_by_height(uint64_t height)const ; - bool get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs); - bool get_transaction(const crypto::hash &h, transaction &tx); - bool get_block_by_hash(const crypto::hash &h, block &blk); -// void get_all_known_block_ids(std::list &main, std::list &alt, std::list &invalid); - - bool get_alternative_blocks(std::list& blocks); - size_t get_alternative_blocks_count(); - - void set_currency_protocol(i_currency_protocol* pprotocol); - void set_critical_error_handler(i_critical_error_handler *handler); - i_critical_error_handler* get_critical_error_handler() const { return m_critical_error_handler; } - bool set_checkpoints(checkpoints&& chk_pts); - - bool get_pool_transactions(std::list& txs); - size_t get_pool_transactions_count(); - size_t get_blockchain_total_transactions(); - bool get_outs(uint64_t amount, std::list& pkeys); - bool have_block(const crypto::hash& id); - bool get_short_chain_history(std::list& ids); - bool find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const ; - bool find_blockchain_supplement(const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const ; - bool get_stat_info(const core_stat_info::params& pr, core_stat_info& st_inf); - bool get_backward_blocks_sizes(uint64_t from_height, std::vector& sizes, size_t count); - bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs); - crypto::hash get_tail_id(); - bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res); - void pause_mine(); - void resume_mine(); - blockchain_storage& get_blockchain_storage() { return m_blockchain_storage; } - const blockchain_storage& get_blockchain_storage() const { return m_blockchain_storage; } - //debug functions - void print_blockchain(uint64_t start_index, uint64_t end_index); - void print_blockchain_index(); - std::string print_pool(bool short_format); - void print_blockchain_outs(const std::string& file); - void on_synchronized(); - - void add_blockchain_update_listener(i_blockchain_update_listener *l); - void remove_blockchain_update_listener(i_blockchain_update_listener *l); - - private: - bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool kept_by_block); - bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block); - bool add_new_block(const block& b, block_verification_context& bvc); - bool load_state_data(); - bool parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob); - - bool is_key_image_spent(const crypto::key_image& key_im); - - bool check_tx_ring_signature(const txin_to_key& tx, const crypto::hash& tx_prefix_hash, const std::vector& sig); - bool is_tx_spendtime_unlocked(uint64_t unlock_time); - bool update_miner_block_template(); - bool handle_command_line(const boost::program_options::variables_map& vm); - bool on_update_blocktemplate_interval(); - - void notify_blockchain_update_listeners(); - - bool check_if_free_space_critically_low(uint64_t* p_available_space = nullptr); - void check_free_space(); - - - blockchain_storage m_blockchain_storage; - tx_memory_pool m_mempool; - i_currency_protocol* m_pprotocol; - i_critical_error_handler* m_critical_error_handler; - critical_section m_incoming_tx_lock; - miner m_miner; - account_public_address m_miner_address; - std::string m_config_folder; - uint64_t m_stop_after_height; - currency_protocol_stub m_protocol_stub; - math_helper::once_a_time_seconds<60*60*12, false> m_prune_alt_blocks_interval; - math_helper::once_a_time_seconds<60, true> m_check_free_space_interval; - friend class tx_validate_inputs; - std::atomic m_starter_message_showed; - - critical_section m_blockchain_update_listeners_lock; - std::vector m_blockchain_update_listeners; - }; -} - -POP_VS_WARNINGS diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp deleted file mode 100644 index 3eb451c..0000000 --- a/src/currency_core/currency_format_utils.cpp +++ /dev/null @@ -1,3285 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "include_base_utils.h" -#include -#ifndef ANDROID_BUILD - #include -#endif -using namespace epee; - -#include "print_fixed_point_helper.h" -#include "currency_format_utils.h" -#include "serialization/binary_utils.h" -#include "serialization/stl_containers.h" -#include "currency_core/currency_config.h" -#include "miner.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "common/int-util.h" -#include "common/base58.h" -#include "bc_offers_service_basic.h" -#include "bc_payments_id_service.h" -#include "bc_escrow_service.h" -#include "bc_attachments_helpers.h" -#include "bc_block_datetime_service.h" -#include "genesis.h" -#include "genesis_acc.h" -#include "common/mnemonic-encoding.h" -#include "crypto/bitcoin/sha256_helper.h" - -namespace currency -{ - - //--------------------------------------------------------------- - bool add_tx_extra_alias(transaction& tx, const extra_alias_entry& alinfo) - { - tx.extra.push_back(alinfo); - return true; - } - - //--------------------------------------------------------------- - /* - bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, - size_t current_block_size, - uint64_t fee, - const account_public_address &miner_address, - transaction& tx, - const blobdata& extra_nonce, - size_t max_outs) - { - - alias_info alias = AUTO_VAL_INIT(alias); - return construct_miner_tx(height, median_size, already_generated_coins, current_block_size, - fee, - miner_address, - tx, - extra_nonce, - max_outs, - alias, - false, - pos_entry()); - }*/ - //--------------------------------------------------------------- - wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff) - { - //delta=delta*(0.75^n) - for (size_t i = 0; i != sequence_factor; i++) - { - diff = diff - diff / 4; - } - return diff; - } - //------------------------------------------------------------------ - bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, - size_t current_block_size, - uint64_t fee, - const account_public_address &miner_address, - const account_public_address &stakeholder_address, - transaction& tx, - const blobdata& extra_nonce, - size_t max_outs, - bool pos, - const pos_entry& pe) - { - uint64_t block_reward = 0; - if (!get_block_reward(pos, median_size, current_block_size, already_generated_coins, block_reward, height)) - { - LOG_ERROR("Block is too big"); - return false; - } - block_reward += fee; - - std::vector out_amounts; - decompose_amount_into_digits(block_reward, DEFAULT_DUST_THRESHOLD, - [&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); }, - [&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); }); - - CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero"); - while (max_outs < out_amounts.size()) - { - out_amounts[out_amounts.size() - 2] += out_amounts.back(); - out_amounts.resize(out_amounts.size() - 1); - } - - - std::vector destinations; - for (auto a : out_amounts) - { - tx_destination_entry de = AUTO_VAL_INIT(de); - de.addr.push_back(miner_address); - de.amount = a; - if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW) - { - //this means that block is creating after hardfork_1 and unlock_time is needed to set for every destination separately - de.unlock_time = height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW; - } - destinations.push_back(de); - } - - if (pos) - { - uint64_t stake_lock_time = 0; - if (pe.stake_unlock_time && pe.stake_unlock_time > height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW) - stake_lock_time = pe.stake_unlock_time; - destinations.push_back(tx_destination_entry(pe.amount, stakeholder_address, stake_lock_time)); - } - - - return construct_miner_tx(height, median_size, already_generated_coins, current_block_size, fee, destinations, tx, extra_nonce, max_outs, pos, pe); - } - //------------------------------------------------------------------ - bool apply_unlock_time(const std::vector& destinations, transaction& tx) - { - currency::etc_tx_details_unlock_time2 unlock_time2 = AUTO_VAL_INIT(unlock_time2); - unlock_time2.unlock_time_array.resize(destinations.size()); - bool found_unlock_time = false; - for (size_t i = 0; i != unlock_time2.unlock_time_array.size(); i++) - { - if (destinations[i].unlock_time) - { - found_unlock_time = true; - unlock_time2.unlock_time_array[i] = destinations[i].unlock_time; - } - } - if (found_unlock_time) - { - tx.extra.push_back(unlock_time2); - } - - return true; - } - //------------------------------------------------------------------ - bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, - size_t current_block_size, - uint64_t fee, - const std::vector& destinations, - transaction& tx, - const blobdata& extra_nonce, - size_t max_outs, - bool pos, - const pos_entry& pe) - { - CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS || height == 0, false, "Too many outs (" << destinations.size() << ")! Miner tx can't be constructed."); - - tx.vin.clear(); - tx.vout.clear(); - tx.extra.clear(); - - keypair txkey = keypair::generate(); - add_tx_pub_key_to_extra(tx, txkey.pub); - if (extra_nonce.size()) - if (!add_tx_extra_userdata(tx, extra_nonce)) - return false; - - //at this moment we do apply_unlock_time only for coin_base transactions - apply_unlock_time(destinations, tx); - //we always add extra_padding with 2 bytes length to make possible for get_block_template to adjust cumulative size - tx.extra.push_back(extra_padding()); - - - txin_gen in; - in.height = height; - tx.vin.push_back(in); - - if (pos) - { - txin_to_key posin; - posin.amount = pe.amount; - posin.key_offsets.push_back(pe.index); - posin.k_image = pe.keyimage; - tx.vin.push_back(posin); - //reserve place for ring signature - tx.signatures.resize(1); - tx.signatures[0].resize(posin.key_offsets.size()); - } - - uint64_t no = 0; - std::set deriv_cache; - for (auto& d : destinations) - { - bool r = construct_tx_out(d, txkey.sec, no, tx, deriv_cache, account_keys()); - CHECK_AND_ASSERT_MES(r, false, "Failed to contruct miner tx out"); - no++; - } - - - tx.version = CURRENT_TRANSACTION_VERSION; - if (!have_type_in_variant_container(tx.extra)) - { - //if stake unlock time was not set, then we can use simple "whole transaction" lock scheme - set_tx_unlock_time(tx, height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); - } - - return true; - } - //--------------------------------------------------------------- - bool derive_ephemeral_key_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral) - { - crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); - bool r = crypto::generate_key_derivation(tx_public_key, ack.view_secret_key, recv_derivation); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.view_secret_key << ")"); - - r = crypto::derive_public_key(recv_derivation, real_output_index, ack.account_address.spend_public_key, in_ephemeral.pub); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to derive_public_key(" << recv_derivation << ", " << real_output_index << ", " << ack.account_address.spend_public_key << ")"); - - crypto::derive_secret_key(recv_derivation, real_output_index, ack.spend_secret_key, in_ephemeral.sec); - return true; - } - //--------------------------------------------------------------- - alias_rpc_details alias_info_to_rpc_alias_info(const currency::extra_alias_entry& ai) - { - alias_rpc_details ari; - alias_info_to_rpc_alias_info(ai, ari); - return ari; - } - //--------------------------------------------------------------- - update_alias_rpc_details alias_info_to_rpc_update_alias_info(const currency::extra_alias_entry& ai, const std::string& old_address) - { - update_alias_rpc_details uard; - alias_info_to_rpc_alias_info(ai, uard); - uard.old_address = old_address; - return uard; - } - //--------------------------------------------------------------- - bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki) - { - bool r = derive_ephemeral_key_helper(ack, tx_public_key, real_output_index, in_ephemeral); - CHECK_AND_ASSERT_MES(r, false, "Failed to call derive_ephemeral_key_helper(...)"); - - crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); - return true; - } - //--------------------------------------------------------------- - uint64_t power_integral(uint64_t a, uint64_t b) - { - if (b == 0) - return 1; - uint64_t total = a; - for (uint64_t i = 1; i != b; i++) - total *= a; - return total; - } - //--------------------------------------------------------------- - bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_outputs_count) - { - if (mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) - return fake_outputs_count + 1 >= mix_attr; - else if (mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - return fake_outputs_count == 0; - else - return true; - } - //--------------------------------------------------------------- - bool parse_amount(uint64_t& amount, const std::string& str_amount_) - { - std::string str_amount = str_amount_; - boost::algorithm::trim(str_amount); - - size_t point_index = str_amount.find_first_of('.'); - size_t fraction_size; - if (std::string::npos != point_index) - { - fraction_size = str_amount.size() - point_index - 1; - while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back()) - { - str_amount.erase(str_amount.size() - 1, 1); - --fraction_size; - } - if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size) - return false; - str_amount.erase(point_index, 1); - } - else - { - fraction_size = 0; - } - - if (str_amount.empty()) - return false; - - if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT) - { - str_amount.append(CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size, '0'); - } - - return string_tools::get_xtype_from_string(amount, str_amount); - } - //-------------------------------------------------------------------------------- - bool parse_tracking_seed(const std::string& tracking_seed, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp) - { - std::vector parts; - boost::split(parts, tracking_seed, [](char x){ return x == ':'; } ); - if (parts.size() != 2 && parts.size() != 3) - return false; - - if (!get_account_address_from_str(address, parts[0])) - return false; - - if (!address.is_auditable()) - return false; - - if (!epee::string_tools::parse_tpod_from_hex_string(parts[1], view_sec_key)) - return false; - - crypto::public_key view_pub_key = AUTO_VAL_INIT(view_pub_key); - if (!crypto::secret_key_to_public_key(view_sec_key, view_pub_key)) - return false; - - if (view_pub_key != address.view_public_key) - return false; - - creation_timestamp = 0; - if (parts.size() == 3) - { - // parse timestamp - int64_t ts = 0; - if (!epee::string_tools::string_to_num_fast(parts[2], ts)) - return false; - - if (ts < WALLET_BRAIN_DATE_OFFSET) - return false; - - creation_timestamp = ts; - } - - return true; - } - //-------------------------------------------------------------------------------- - std::string print_stake_kernel_info(const stake_kernel& sk) - { - std::stringstream ss; - ss << "block_timestamp: " << sk.block_timestamp << ENDL - << "kimage: " << sk.kimage << ENDL - << "stake_modifier.last_pos_kernel_id: " << sk.stake_modifier.last_pos_kernel_id << ENDL - << "stake_modifier.last_pow_id: " << sk.stake_modifier.last_pow_id << ENDL; - return ss.str(); - } - - //--------------------------------------------------------------- - bool get_tx_fee(const transaction& tx, uint64_t & fee) - { - fee = 0; - if (is_coinbase(tx)) - return true; - uint64_t amount_in = 0; - uint64_t amount_out = get_outs_money_amount(tx); - - BOOST_FOREACH(auto& in, tx.vin) - { - amount_in += get_amount_from_variant(in); - } - - - - CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spend (" << amount_in << ") more than it has (" << amount_out << ")"); - fee = amount_in - amount_out; - return true; - } - //--------------------------------------------------------------- - uint64_t get_tx_fee(const transaction& tx) - { - uint64_t r = 0; - if (!get_tx_fee(tx, r)) - return 0; - return r; - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx) - { - crypto::public_key pk = null_pkey; - get_type_in_variant_container(tx.extra, pk); - return pk; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_extra(const transaction& tx, crypto::public_key& tx_pub_key) - { - tx_extra_info e = AUTO_VAL_INIT(e); - bool r = parse_and_validate_tx_extra(tx, e); - tx_pub_key = e.m_tx_pub_key; - return r; - } - //--------------------------------------------------------------- - bool sign_extra_alias_entry(extra_alias_entry& ai, const crypto::public_key& pkey, const crypto::secret_key& skey) - { - ai.m_sign.clear(); - get_sign_buff_hash_for_alias_update(ai); - crypto::signature sig = AUTO_VAL_INIT(sig); - crypto::generate_signature(get_sign_buff_hash_for_alias_update(ai), pkey, skey, sig); - ai.m_sign.push_back(sig); - return true; - } - //--------------------------------------------------------------- - crypto::hash get_sign_buff_hash_for_alias_update(const extra_alias_entry& ai) - { - extra_alias_entry_old ai_old = ai.to_old(); - if (ai_old.m_sign.size()) - ai_old.m_sign.clear(); - return get_object_hash(ai_old); - } - //--------------------------------------------------------------- - struct tx_extra_handler : public boost::static_visitor - { - mutable bool was_padding; //let the padding goes only at the end - mutable bool was_pubkey; - mutable bool was_attachment; - mutable bool was_userdata; - mutable bool was_alias; - - tx_extra_info& rei; - const transaction& rtx; - - tx_extra_handler(tx_extra_info& ei, const transaction& tx) :rei(ei), rtx(tx) - { - was_padding = was_pubkey = was_attachment = was_userdata = was_alias = false; - } - -#define ENSURE_ONETIME(varname, entry_name) CHECK_AND_ASSERT_MES(varname == false, false, "double entry in tx_extra: " entry_name); varname = true; - - - bool operator()(const crypto::public_key& k) const - { - ENSURE_ONETIME(was_pubkey, "public_key"); - rei.m_tx_pub_key = k; - return true; - } - bool operator()(const extra_attachment_info& ai) const - { - ENSURE_ONETIME(was_attachment, "attachment"); - rei.m_attachment_info = ai; - return true; - } - bool operator()(const extra_alias_entry& ae) const - { - ENSURE_ONETIME(was_alias, "alias"); - rei.m_alias = ae; - return true; - } - bool operator()(const extra_alias_entry_old& ae) const - { - return operator()(static_cast(ae)); - } - bool operator()(const extra_user_data& ud) const - { - ENSURE_ONETIME(was_userdata, "userdata"); - if (!ud.buff.empty()) - rei.m_user_data_blob.assign((const char*)&ud.buff[0], ud.buff.size()); - return true; - } - bool operator()(const extra_padding& k) const - { - ENSURE_ONETIME(was_padding, "padding"); - return true; - } - template - bool operator()(const t_extra_typename& k) const - { - //do notheing for rest - return true; - } - }; - //------------------------------------------------------------------------------------ - bool parse_and_validate_tx_extra(const transaction& tx, tx_extra_info& extra) - { - extra.m_tx_pub_key = null_pkey; - - tx_extra_handler vtr(extra, tx); - - for (const auto& ex_v : tx.extra) - { - if (!boost::apply_visitor(vtr, ex_v)) - return false; - } - return true; - } - //--------------------------------------------------------------- - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key) - { - tx.extra.push_back(tx_pub_key); - return true; - } - //--------------------------------------------------------------- - //--------------------------------------------------------------- - - struct multisig_id_generator - { - //std::vector vin; - crypto::public_key onetime_key; - std::vector vout; - - BEGIN_SERIALIZE() - //FIELD(vin) - FIELD(onetime_key) - FIELD(vout) - END_SERIALIZE() - }; - crypto::hash get_multisig_out_id(const transaction& tx, size_t n) - { - multisig_id_generator msg = AUTO_VAL_INIT(msg); - //msg.vin = tx.vin; - msg.onetime_key = get_tx_pub_key_from_extra(tx); - CHECK_AND_ASSERT_MES(tx.vout.size() > n, null_hash, "tx.vout.size() > n condition failed "); - CHECK_AND_ASSERT_MES(tx.vout[n].target.type() == typeid(txout_multisig), null_hash, "tx.vout[n].target.type() == typeid(txout_multisig) condition failed"); - msg.vout.push_back(tx.vout[n]); - return get_object_hash(msg); - } - //--------------------------------------------------------------- - bool add_tx_extra_userdata(transaction& tx, const blobdata& extra_nonce) - { - CHECK_AND_ASSERT_MES(extra_nonce.size() <= 255, false, "extra nonce could be 255 bytes max"); - extra_user_data eud = AUTO_VAL_INIT(eud); - eud.buff = extra_nonce; - tx.extra.push_back(eud); - return true; - } - //--------------------------------------------------------------- - bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key) - { - crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); - return derive_public_key_from_target_address(destination_addr, tx_sec_key, index, out_eph_public_key, derivation); - } - //--------------------------------------------------------------- - bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation) - { - bool r = crypto::generate_key_derivation(destination_addr.view_public_key, tx_sec_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << destination_addr.view_public_key << ", " << tx_sec_key << ")"); - - r = crypto::derive_public_key(derivation, index, destination_addr.spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << index << ", " << destination_addr.view_public_key << ")"); - return r; - } - //--------------------------------------------------------------- - uint16_t get_derivation_hint(const crypto::key_derivation& derivation) - { - crypto::hash h = blake2_hash(&derivation, sizeof(derivation)); - - uint16_t* pderiv_hash_as_array = (uint16_t*)&h; - uint16_t res = pderiv_hash_as_array[0]; - for (size_t i = 1; i != sizeof(h) / sizeof(uint16_t); i++) - res ^= pderiv_hash_as_array[i]; - return res; - } - //--------------------------------------------------------------- - uint64_t get_string_uint64_hash(const std::string& str) - { - crypto::hash h = crypto::cn_fast_hash(str.data(), str.size()); - uint64_t* phash_as_array = (uint64_t*)&h; - return phash_as_array[0] ^ phash_as_array[1] ^ phash_as_array[2] ^ phash_as_array[3]; - } - //--------------------------------------------------------------- - tx_derivation_hint make_tx_derivation_hint_from_uint16(uint16_t hint) - { - tx_derivation_hint dh = AUTO_VAL_INIT(dh); - dh.msg.assign((const char*)&hint, sizeof(hint)); - return dh; - } - //--------------------------------------------------------------- -// bool get_uint16_from_tx_derivation_hint(const tx_derivation_hint& dh, uint16_t& hint) -// { -// tx_derivation_hint dh; -// if (dh.msg.size() != sizeof(hint)) -// return false; -// hint = *((uint16_t*)dh.msg.data()); -// return true; -// } - //--------------------------------------------------------------- - std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys) - { - std::string blob; - string_tools::append_pod_to_strbuff(blob, htlc.pkey_redeem); - string_tools::append_pod_to_strbuff(blob, htlc.pkey_refund); - string_tools::append_pod_to_strbuff(blob, acc_keys.spend_secret_key); - crypto::hash origin_hs = crypto::cn_fast_hash(blob.data(), blob.size()); - std::string origin_blob; - string_tools::append_pod_to_strbuff(origin_blob, origin_hs); - return origin_blob; - } - //--------------------------------------------------------------- - bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, uint8_t tx_outs_attr) - { - finalized_tx result = AUTO_VAL_INIT(result); - return construct_tx_out(de, tx_sec_key, output_index, tx, deriv_cache, self, result, tx_outs_attr); - } - //--------------------------------------------------------------- - bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr) - { - CHECK_AND_ASSERT_MES(de.addr.size() == 1 || (de.addr.size() > 1 && de.minimum_sigs <= de.addr.size()), false, "Invalid destination entry: amount: " << de.amount << " minimum_sigs: " << de.minimum_sigs << " addr.size(): " << de.addr.size()); - - std::vector target_keys; - target_keys.reserve(de.addr.size()); - for (auto& apa : de.addr) - { - crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); - if (apa.spend_public_key == null_pkey && apa.view_public_key == null_pkey) - { - //burning money(for example alias reward) - out_eph_public_key = null_pkey; - } - else - { - crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); - bool r = derive_public_key_from_target_address(apa, tx_sec_key, output_index, out_eph_public_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address"); - - uint16_t hint = get_derivation_hint(derivation); - if (deriv_cache.count(hint) == 0) - { - tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint)); - deriv_cache.insert(hint); - } - } - target_keys.push_back(out_eph_public_key); - } - - tx_out out; - out.amount = de.amount; - if (de.htlc_options.expiration != 0) - { - const destination_option_htlc_out& htlc_dest = de.htlc_options; - //out htlc - CHECK_AND_ASSERT_MES(target_keys.size() == 1, false, "Unexpected htl keys count = " << target_keys.size() << ", expected ==1"); - txout_htlc htlc = AUTO_VAL_INIT(htlc); - htlc.expiration = htlc_dest.expiration; - htlc.flags = 0; //0 - SHA256, 1 - RIPEMD160, by default leave SHA256 - //receiver key - htlc.pkey_redeem = *target_keys.begin(); - //generate refund key - crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); - crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); - bool r = derive_public_key_from_target_address(self.account_address, tx_sec_key, output_index, out_eph_public_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address"); - htlc.pkey_refund = out_eph_public_key; - //add derivation hint for refund address - uint16_t hint = get_derivation_hint(derivation); - if (deriv_cache.count(hint) == 0) - { - tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint)); - deriv_cache.insert(hint); - } - - - if (htlc_dest.htlc_hash == null_hash) - { - //we use deterministic origin, to make possible access origin on different wallets copies - - result.htlc_origin = generate_origin_for_htlc(htlc, self); - - //calculate hash - if (!htlc.flags&CURRENCY_TXOUT_HTLC_FLAGS_HASH_TYPE_MASK) - { - htlc.htlc_hash = crypto::sha256_hash(result.htlc_origin.data(), result.htlc_origin.size()); - } - else - { - crypto::hash160 h160 = crypto::RIPEMD160_hash(result.htlc_origin.data(), result.htlc_origin.size()); - std::memcpy(&htlc.htlc_hash, &h160, sizeof(h160)); - } - } - else - { - htlc.htlc_hash = htlc_dest.htlc_hash; - } - out.target = htlc; - } - else if (target_keys.size() == 1) - { - //out to key - txout_to_key tk = AUTO_VAL_INIT(tk); - tk.key = target_keys.back(); - - if (de.addr.front().is_auditable()) // check only the first address because there's only one in this branch - tk.mix_attr = CURRENCY_TO_KEY_OUT_FORCED_NO_MIX; // override mix_attr to 1 for auditable target addresses - else - tk.mix_attr = tx_outs_attr; - - out.target = tk; - } - else - { - //multisig out - txout_multisig ms = AUTO_VAL_INIT(ms); - ms.keys = std::move(target_keys); - ms.minimum_sigs = de.minimum_sigs; - out.target = ms; - } - tx.vout.push_back(out); - return true; - } - //--------------------------------------------------------------- - bool have_attachment_service_in_container(const std::vector& av, const std::string& service_id, const std::string& instruction) - { - for (auto& ai : av) - { - if (ai.type() == typeid(tx_service_attachment)) - { - const tx_service_attachment& tsa = boost::get(ai); - if (tsa.service_id == service_id && tsa.instruction == instruction) - return true; - } - } - return false; - } - //--------------------------------------------------------------- - void get_attachment_extra_info_details(const std::vector& attachment, extra_attachment_info& eai) - { - eai = extra_attachment_info(); - if (!attachment.size()) - return; - - //put hash into extra - std::stringstream ss; - binary_archive oar(ss); - if (!::do_serialize(oar, const_cast&>(attachment))) - return; - std::string buff = ss.str(); - eai.sz = buff.size(); - eai.hsh = get_blob_hash(buff); - eai.cnt = attachment.size(); - } - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, - const std::vector& destinations, - const std::vector& attachments, - transaction& tx, - uint64_t unlock_time, - uint8_t tx_outs_attr, bool shuffle) - { - crypto::secret_key one_time_secret_key = AUTO_VAL_INIT(one_time_secret_key); - return construct_tx(sender_account_keys, sources, destinations, std::vector(), attachments, tx, one_time_secret_key, unlock_time, tx_outs_attr, shuffle); - } - //--------------------------------------------------------------- - struct encrypt_attach_visitor : public boost::static_visitor - { - bool& m_was_crypted_entries; - const keypair& m_onetime_keypair; - const account_public_address& m_destination_addr; - const crypto::key_derivation& m_key; - - encrypt_attach_visitor(bool& was_crypted_entries, const crypto::key_derivation& key, const keypair& onetime_keypair = null_keypair, const account_public_address& destination_addr = null_pub_addr) : - m_was_crypted_entries(was_crypted_entries), m_key(key), m_onetime_keypair(onetime_keypair), m_destination_addr(destination_addr) - {} - void operator()(tx_comment& comment) - { - crypto::chacha_crypt(comment.comment, m_key); - m_was_crypted_entries = true; - } - void operator()(tx_payer& pr) - { - crypto::chacha_crypt(pr.acc_addr, m_key); - m_was_crypted_entries = true; - } - void operator()(tx_receiver& m) - { - crypto::chacha_crypt(m.acc_addr, m_key); - m_was_crypted_entries = true; - } - void operator()(tx_payer_old& pr) - { - crypto::chacha_crypt(pr.acc_addr, m_key); - m_was_crypted_entries = true; - } - void operator()(tx_receiver_old& m) - { - crypto::chacha_crypt(m.acc_addr, m_key); - m_was_crypted_entries = true; - } - void operator()(tx_service_attachment& sa) - { - const std::string original_body = sa.body; - if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) - { - zlib_helper::pack(sa.body); - } - - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY) - { - crypto::key_derivation derivation_local = m_key; - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE) - { - CHECK_AND_ASSERT_THROW_MES(m_destination_addr.spend_public_key != currency::null_pkey && m_onetime_keypair.sec != currency::null_skey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized"); - //encrypt with "spend keys" only, to prevent auditable watchers decrypt it - bool r = crypto::generate_key_derivation(m_destination_addr.spend_public_key, m_onetime_keypair.sec, derivation_local); - CHECK_AND_ASSERT_THROW_MES(r, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: Failed to make derivation"); - crypto::chacha_crypt(sa.body, derivation_local); - } - else - { - crypto::chacha_crypt(sa.body, derivation_local); - } - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF) - { - //take hash from derivation and use it as a salt - crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local)); - std::string salted_body = original_body; - string_tools::append_pod_to_strbuff(salted_body, derivation_hash); - crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size()); - sa.security.push_back(*(crypto::public_key*)&proof_hash); - } - m_was_crypted_entries = true; - } - } - - template - void operator()(attachment_t& comment) - {} - }; - - struct decrypt_attach_visitor : public boost::static_visitor - { - const account_keys& m_acc_keys; - const crypto::public_key& m_tx_onetime_pubkey; - const crypto::key_derivation& rkey; - std::vector& rdecrypted_att; - decrypt_attach_visitor(const crypto::key_derivation& key, - std::vector& decrypted_att, - const account_keys& acc_keys = null_acc_keys, - const crypto::public_key& tx_onetime_pubkey = null_pkey) : - rkey(key), - rdecrypted_att(decrypted_att), - m_acc_keys(acc_keys), - m_tx_onetime_pubkey(tx_onetime_pubkey) - {} - void operator()(const tx_comment& comment) - { - tx_comment local_comment = comment; - crypto::chacha_crypt(local_comment.comment, rkey); - rdecrypted_att.push_back(local_comment); - } - - void operator()(const tx_service_attachment& sa) - { - tx_service_attachment local_sa = sa; - crypto::key_derivation derivation_local = rkey; - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY) - { - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE) - { - if (m_acc_keys.spend_secret_key == null_skey) - { - //this watch only wallet, decrypting supposed to be impossible - return; - } - CHECK_AND_ASSERT_THROW_MES(m_acc_keys.spend_secret_key != currency::null_skey && m_tx_onetime_pubkey != currency::null_pkey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized"); - bool r = crypto::generate_key_derivation(m_tx_onetime_pubkey, m_acc_keys.spend_secret_key, derivation_local); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate_key_derivation at TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE"); - crypto::chacha_crypt(local_sa.body, derivation_local); - - } - else - { - crypto::chacha_crypt(local_sa.body, derivation_local); - } - } - - if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) - { - zlib_helper::unpack(local_sa.body); - } - - if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY && sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF) - { - CHECK_AND_ASSERT_MES(sa.security.size() == 1, void(), "Unexpected key in tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE"); - //take hash from derivation and use it as a salt - crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local)); - std::string salted_body = local_sa.body; - string_tools::append_pod_to_strbuff(salted_body, derivation_hash); - crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size()); // proof_hash = Hs(local_sa.body || Hs(s * R)), s - spend secret, R - tx pub - CHECK_AND_ASSERT_MES(*(crypto::public_key*)&proof_hash == sa.security.front(), void(), "Proof hash missmatch on decrypting with TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF"); - } - - rdecrypted_att.push_back(local_sa); - } - - void operator()(const tx_payer& pr) - { - tx_payer payer_local = pr; - crypto::chacha_crypt(payer_local.acc_addr, rkey); - rdecrypted_att.push_back(payer_local); - } - void operator()(const tx_receiver& pr) - { - tx_receiver receiver_local = pr; - crypto::chacha_crypt(receiver_local.acc_addr, rkey); - rdecrypted_att.push_back(receiver_local); - } - void operator()(const tx_payer_old& pr) - { - tx_payer_old payer_local = pr; - crypto::chacha_crypt(payer_local.acc_addr, rkey); - rdecrypted_att.push_back(payer_local); - } - void operator()(const tx_receiver_old& pr) - { - tx_receiver_old receiver_local = pr; - crypto::chacha_crypt(receiver_local.acc_addr, rkey); - rdecrypted_att.push_back(receiver_local); - } - template - void operator()(const attachment_t& att) - { - rdecrypted_att.push_back(att); - } - }; - - //--------------------------------------------------------------- - template - bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector& decrypted_att, const account_keys& acc_keys = null_acc_keys, - const crypto::public_key& tx_onetime_pubkey = null_pkey) - { - decrypt_attach_visitor v(derivation, decrypted_att, acc_keys, tx_onetime_pubkey); - for (auto& a : items_to_decrypt) - boost::apply_visitor(v, a); - - return true; - } - //--------------------------------------------------------------- - bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation) - { - tx_crypto_checksum crypto_info = AUTO_VAL_INIT(crypto_info); - if (!get_type_in_variant_container(tx.extra, crypto_info) && !get_type_in_variant_container(tx.attachment, crypto_info)) - { - //no crypt info in tx - return false; - } - //validate derivation we here. - crypto::hash hash_for_check_sum = crypto::cn_fast_hash(&derivation, sizeof(derivation)); - if (*(uint32_t*)&hash_for_check_sum == crypto_info.derivation_hash) - return true; - - return false; - } - //--------------------------------------------------------------- - crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys) - { - crypto::key_derivation derivation = null_derivation; - tx_crypto_checksum crypto_info = AUTO_VAL_INIT(crypto_info); - if (!get_type_in_variant_container(tx.extra, crypto_info) && !get_type_in_variant_container(tx.attachment, crypto_info)) - { - //no crypt info in tx - return null_derivation; - } - - if (is_income) - { - crypto::public_key tx_pub_key = currency::get_tx_pub_key_from_extra(tx); - - bool r = crypto::generate_key_derivation(tx_pub_key, acc_keys.view_secret_key, derivation); - CHECK_AND_ASSERT_MES(r, null_derivation, "failed to generate_key_derivation"); - LOG_PRINT_GREEN("DECRYPTING ON KEY: " << epee::string_tools::pod_to_hex(derivation) << ", key derived from destination addr: " << currency::get_account_address_as_str(acc_keys.account_address), LOG_LEVEL_0); - } - else - { - derivation = crypto_info.encrypted_key_derivation; - crypto::chacha_crypt(derivation, acc_keys.spend_secret_key); - LOG_PRINT_GREEN("DECRYPTING ON KEY: " << epee::string_tools::pod_to_hex(derivation) << ", key decrypted from sender address: " << currency::get_account_address_as_str(acc_keys.account_address), LOG_LEVEL_0); - } - - //validate derivation we here. Yoda style - crypto::hash hash_for_check_sum = crypto::cn_fast_hash(&derivation, sizeof(derivation)); - CHECK_AND_ASSERT_MES(*(uint32_t*)&hash_for_check_sum == crypto_info.derivation_hash, null_derivation, "Derivation hash missmatched in tx id " << currency::get_transaction_hash(tx)); - return derivation; - } - //--------------------------------------------------------------- - template - struct back_inserter : public boost::static_visitor - { - total_t_container& ttc; - back_inserter(total_t_container& tt) :ttc(tt) - {} - template - void operator()(const attachment_t& att) - { - ttc.push_back(att); - } - }; - - bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector& decrypted_items) - { - PROFILE_FUNC("currency::decrypt_payload_items"); - crypto::key_derivation derivation = get_encryption_key_derivation(is_income, tx, acc_keys); - if (derivation == null_derivation) - { - back_inserter > v(decrypted_items); - for (auto& a : tx.extra) - boost::apply_visitor(v, a); - - for (auto& a : tx.attachment) - boost::apply_visitor(v, a); - - return true; - } - - decrypt_payload_items(derivation, tx.extra, decrypted_items, is_income ? acc_keys: account_keys(), get_tx_pub_key_from_extra(tx)); - decrypt_payload_items(derivation, tx.attachment, decrypted_items, is_income ? acc_keys : account_keys(), get_tx_pub_key_from_extra(tx)); - return true; - } - - //--------------------------------------------------------------- - void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key) - { - crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); - bool r = crypto::generate_key_derivation(destination_addr.view_public_key, tx_random_key.sec, derivation); - CHECK_AND_ASSERT_MES(r, void(), "failed to generate_key_derivation"); - bool was_attachment_crypted_entries = false; - bool was_extra_crypted_entries = false; - - encrypt_attach_visitor v(was_attachment_crypted_entries, derivation, tx_random_key, destination_addr); - for (auto& a : tx.attachment) - boost::apply_visitor(v, a); - - encrypt_attach_visitor v2(was_extra_crypted_entries, derivation, tx_random_key, destination_addr); - for (auto& a : tx.extra) - boost::apply_visitor(v2, a); - - - if (was_attachment_crypted_entries || was_extra_crypted_entries) - { - crypto::hash hash_for_check_sum = crypto::cn_fast_hash(&derivation, sizeof(derivation)); - tx_crypto_checksum chs; - //put derivation hash to be sure that we decrypting right way - chs.derivation_hash = *(uint32_t*)&hash_for_check_sum; - //put encrypted derivation to let sender decrypt all this data from attachment/extra - chs.encrypted_key_derivation = derivation; - crypto::chacha_crypt(chs.encrypted_key_derivation, sender_keys.spend_secret_key); - if (was_extra_crypted_entries) - tx.extra.push_back(chs); - else - tx.attachment.push_back(chs); - } - } - //--------------------------------------------------------------- - // void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x) - // { - // x.is_service = currency::is_service_tx(x.tx); - // x.is_mixing = currency::does_tx_have_only_mixin_inputs(x.tx); - // x.is_mining = currency::is_coinbase(x.tx); - // if (!x.is_mining) - // x.fee = currency::get_tx_fee(x.tx); - // else - // x.fee = 0; - // x.show_sender = currency::is_showing_sender_addres(x.tx); - // tx_out htlc_out = AUTO_VAL_INIT(htlc_out); - // txin_htlc htlc_in = AUTO_VAL_INIT(htlc_in); - - // x.tx_type = get_tx_type_ex(x.tx, htlc_out, htlc_in); - // if(x.tx_type == GUI_TX_TYPE_HTLC_DEPOSIT && x.is_income == true) - // { - // //need to override amount - // x.amount = htlc_out.amount; - // } - // } - - //--------------------------------------------------------------- - uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in) - { - if (is_coinbase(tx)) - return GUI_TX_TYPE_COIN_BASE; - - // aliases - tx_extra_info ei = AUTO_VAL_INIT(ei); - parse_and_validate_tx_extra(tx, ei); - if (ei.m_alias.m_alias.size()) - { - if (ei.m_alias.m_sign.size()) - return GUI_TX_TYPE_UPDATE_ALIAS; - else - return GUI_TX_TYPE_NEW_ALIAS; - } - - // offers - tx_service_attachment a = AUTO_VAL_INIT(a); - if (get_type_in_variant_container(tx.attachment, a)) - { - if (a.service_id == BC_OFFERS_SERVICE_ID) - { - if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD) - return GUI_TX_TYPE_PUSH_OFFER; - else if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD) - return GUI_TX_TYPE_UPDATE_OFFER; - else if (a.instruction == BC_OFFERS_SERVICE_INSTRUCTION_DEL) - return GUI_TX_TYPE_CANCEL_OFFER; - } - } - - // escrow - tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_TEMPLATES, tsa)) - return GUI_TX_TYPE_ESCROW_TRANSFER; - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_PROPOSAL, tsa)) - return GUI_TX_TYPE_ESCROW_PROPOSAL; - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_NORMAL, tsa)) - return GUI_TX_TYPE_ESCROW_RELEASE_NORMAL; - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_BURN, tsa)) - return GUI_TX_TYPE_ESCROW_RELEASE_BURN; - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_RELEASE_CANCEL, tsa)) - return GUI_TX_TYPE_ESCROW_RELEASE_CANCEL; - if (bc_services::get_first_service_attachment_by_id(tx, BC_ESCROW_SERVICE_ID, BC_ESCROW_SERVICE_INSTRUCTION_CANCEL_PROPOSAL, tsa)) - return GUI_TX_TYPE_ESCROW_CANCEL_PROPOSAL; - - for (auto o : tx.vout) - { - if (o.target.type() == typeid(txout_htlc)) - { - htlc_out = o; - return GUI_TX_TYPE_HTLC_DEPOSIT; - } - } - - if (get_type_in_variant_container(tx.vin, htlc_in)) - { - return GUI_TX_TYPE_HTLC_REDEEM; - } - - - return GUI_TX_TYPE_NORMAL; - } - //--------------------------------------------------------------- - uint64_t get_tx_type(const transaction& tx) - { - tx_out htlc_out = AUTO_VAL_INIT(htlc_out); - txin_htlc htlc_in = AUTO_VAL_INIT(htlc_in); - return get_tx_type_ex(tx, htlc_out, htlc_in); - } - //--------------------------------------------------------------- - size_t get_multisig_out_index(const std::vector& outs) - { - size_t n = 0; - for (; n != outs.size(); n++) - { - if (outs[n].target.type() == typeid(txout_multisig)) - break; - } - return n; - } - //--------------------------------------------------------------- - size_t get_multisig_in_index(const std::vector& inputs) - { - size_t n = 0; - for (; n != inputs.size(); n++) - { - if (inputs[n].type() == typeid(txin_multisig)) - break; - } - return n; - } - - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, - const std::vector& sources, - const std::vector& destinations, - const std::vector& extra, - const std::vector& attachments, - transaction& tx, - crypto::secret_key& one_time_secret_key, - uint64_t unlock_time, - uint8_t tx_outs_attr, - bool shuffle, - uint64_t flags) - { - // - //find target account to encrypt attachment. - //for now we use just firs target account that is not sender, - //in case if there is no real targets we use sender credentials to encrypt attachments - account_public_address crypt_destination_addr = get_crypt_address_from_destinations(sender_account_keys, destinations); - - return construct_tx(sender_account_keys, sources, destinations, extra, attachments, tx, one_time_secret_key, unlock_time, - crypt_destination_addr, - 0, - tx_outs_attr, - shuffle, - flags); - } - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, - const std::vector& destinations, - const std::vector& extra, - const std::vector& attachments, - transaction& tx, - crypto::secret_key& one_time_secret_key, - uint64_t unlock_time, - const account_public_address& crypt_destination_addr, - uint64_t expiration_time, - uint8_t tx_outs_attr, - bool shuffle, - uint64_t flags) - { - //extra copy operation, but creating transaction is not sensitive to this - finalize_tx_param ftp = AUTO_VAL_INIT(ftp); - ftp.sources = sources; - ftp.prepared_destinations = destinations; - ftp.extra = extra; - ftp.attachments = attachments; - ftp.unlock_time = unlock_time; - ftp.crypt_address = crypt_destination_addr; - ftp.expiration_time = expiration_time; - ftp.tx_outs_attr = tx_outs_attr; - ftp.shuffle = shuffle; - ftp.flags = flags; - - finalized_tx ft = AUTO_VAL_INIT(ft); - ft.tx = tx; - ft.one_time_key = one_time_secret_key; - bool r = construct_tx(sender_account_keys, ftp, ft); - tx = ft.tx; - one_time_secret_key = ft.one_time_key; - return r; - } - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& ftp, finalized_tx& result) - { - const std::vector& sources = ftp.sources; - const std::vector& destinations = ftp.prepared_destinations; - const std::vector& extra = ftp.extra; - const std::vector& attachments = ftp.attachments; - const uint64_t& unlock_time = ftp.unlock_time; - const account_public_address& crypt_destination_addr = ftp.crypt_address; - const uint64_t& expiration_time = ftp.expiration_time; - const uint8_t& tx_outs_attr = ftp.tx_outs_attr; - const bool& shuffle = ftp.shuffle; - const uint64_t& flags = ftp.flags; - - transaction& tx = result.tx; - crypto::secret_key& one_time_secret_key = result.one_time_key; - - result.ftp = ftp; - CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "Too many outs (" << destinations.size() << ")! Tx can't be constructed."); - - bool watch_only_mode = sender_account_keys.spend_secret_key == null_skey; - - bool append_mode = false; - if (flags&TX_FLAG_SIGNATURE_MODE_SEPARATE && tx.vin.size()) - append_mode = true; - - keypair txkey = AUTO_VAL_INIT(txkey); - - - if (!append_mode) - { - tx.vin.clear(); - tx.vout.clear(); - tx.signatures.clear(); - tx.extra = extra; - - tx.version = CURRENT_TRANSACTION_VERSION; - if (unlock_time != 0) - set_tx_unlock_time(tx, unlock_time); - - if (flags != 0) - set_tx_flags(tx, flags); - //generate key pair - if (expiration_time != 0) - set_tx_expiration_time(tx, expiration_time); - - txkey = keypair::generate(); - add_tx_pub_key_to_extra(tx, txkey.pub); - one_time_secret_key = txkey.sec; - - //add flags - etc_tx_flags16_t e = AUTO_VAL_INIT(e); - //todo: add some flags here - update_or_add_field_to_extra(tx.extra, e); - - //include offers if need - tx.attachment = attachments; - encrypt_attachments(tx, sender_account_keys, crypt_destination_addr, txkey); - } - else - { - txkey.pub = get_tx_pub_key_from_extra(tx); - txkey.sec = one_time_secret_key; - CHECK_AND_ASSERT_MES(txkey.pub != null_pkey && txkey.sec != null_skey, false, "In append mode both public and secret keys must be provided"); - - //separately encrypt attachments without putting extra - crypto::key_derivation derivation = get_encryption_key_derivation(true, tx, sender_account_keys); - CHECK_AND_ASSERT_MES(derivation != null_derivation, false, "failed to generate_key_derivation"); - bool was_attachment_crypted_entries = false; - std::vector extra_local = extra; - std::vector attachments_local = attachments; - - encrypt_attach_visitor v(was_attachment_crypted_entries, derivation); - for (auto& a : attachments_local) - boost::apply_visitor(v, a); - for (auto& a : extra_local) - boost::apply_visitor(v, a); - - - tx.attachment.insert(tx.attachment.end(), attachments_local.begin(), attachments_local.end()); - tx.extra.insert(tx.extra.end(), extra_local.begin(), extra_local.end()); - } - - - - // prepare inputs - struct input_generation_context_data - { - keypair in_ephemeral; - //std::vector participants_derived_keys; - }; - std::vector in_contexts; - - size_t input_starter_index = tx.vin.size(); - uint64_t summary_inputs_money = 0; - //fill inputs - for (const tx_source_entry& src_entr : sources) - { - in_contexts.push_back(input_generation_context_data()); - if(src_entr.is_multisig()) - {//multisig input - txin_multisig input_multisig = AUTO_VAL_INIT(input_multisig); - summary_inputs_money += input_multisig.amount = src_entr.amount; - input_multisig.multisig_out_id = src_entr.multisig_id; - input_multisig.sigs_count = src_entr.ms_sigs_count; - tx.vin.push_back(input_multisig); - } - else if (src_entr.htlc_origin.size()) - { - //htlc redeem - keypair& in_ephemeral = in_contexts.back().in_ephemeral; - //txin_to_key - if(src_entr.outputs.size() != 1) - { - LOG_ERROR("htlc in: wrong output src_entr.outputs.size() = " << src_entr.outputs.size()); - return false; - } - summary_inputs_money += src_entr.amount; - - //key_derivation recv_derivation; - crypto::key_image img; - if (!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img)) - return false; - - //check that derivated key is equal with real output key - if (!(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second)) - { - LOG_ERROR("derived public key missmatch with output public key! " << ENDL << "derived_key:" - << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" - << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second)); - return false; - } - - //put key image into tx input - txin_htlc input_to_key; - input_to_key.amount = src_entr.amount; - input_to_key.k_image = img; - input_to_key.hltc_origin = src_entr.htlc_origin; - - //fill outputs array and use relative offsets - BOOST_FOREACH(const tx_source_entry::output_entry& out_entry, src_entr.outputs) - input_to_key.key_offsets.push_back(out_entry.first); - - input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); - tx.vin.push_back(input_to_key); - } - else - { - //regular to key out - keypair& in_ephemeral = in_contexts.back().in_ephemeral; - //txin_to_key - if (src_entr.real_output >= src_entr.outputs.size()) - { - LOG_ERROR("real_output index (" << src_entr.real_output << ") greater than or equal to output_keys.size()=" << src_entr.outputs.size()); - return false; - } - summary_inputs_money += src_entr.amount; - - //key_derivation recv_derivation; - crypto::key_image img; - if (!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img)) - return false; - - //check that derivated key is equal with real output key - if (!(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second)) - { - LOG_ERROR("derived public key missmatch with output public key! " << ENDL << "derived_key:" - << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" - << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second)); - return false; - } - - //put key image into tx input - txin_v in_v; - txin_to_key* ptokey = nullptr; - if (src_entr.htlc_origin.size()) - { - //add txin_htlc - txin_htlc in_htlc = AUTO_VAL_INIT(in_htlc); - in_htlc.hltc_origin = src_entr.htlc_origin; - in_v = in_htlc; - txin_htlc& in_v_ref = boost::get(in_v); - ptokey = static_cast(&in_v_ref); - } - else - { - in_v = txin_to_key(); - txin_to_key& in_v_ref = boost::get(in_v); - ptokey = &in_v_ref; - } - txin_to_key& input_to_key = *ptokey; - - - input_to_key.amount = src_entr.amount; - input_to_key.k_image = img; - - //fill outputs array and use relative offsets - BOOST_FOREACH(const tx_source_entry::output_entry& out_entry, src_entr.outputs) - input_to_key.key_offsets.push_back(out_entry.first); - - input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); - tx.vin.push_back(in_v); - } - - } - - // "Shuffle" outs - std::vector shuffled_dsts(destinations); - if (shuffle) - std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; }); - - uint64_t summary_outs_money = 0; - //fill outputs - size_t output_index = tx.vout.size(); // in case of append mode we need to start output indexing from the last one + 1 - std::set deriv_cache; - for(const tx_destination_entry& dst_entr : shuffled_dsts) - { - CHECK_AND_ASSERT_MES(dst_entr.amount > 0, false, "Destination with wrong amount: " << dst_entr.amount); - bool r = construct_tx_out(dst_entr, txkey.sec, output_index, tx, deriv_cache, sender_account_keys, result, tx_outs_attr); - CHECK_AND_ASSERT_MES(r, false, "Failed to construc tx out"); - output_index++; - summary_outs_money += dst_entr.amount; - } - - //check money - if (!(flags&TX_FLAG_SIGNATURE_MODE_SEPARATE)) - { - if (summary_outs_money > summary_inputs_money) - { - LOG_ERROR("Transaction inputs money (" << summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")"); - return false; - } - } - - - - //process offers and put there offers derived keys - uint64_t att_count = 0; - for (auto& o : tx.attachment) - { - if (o.type() == typeid(tx_service_attachment)) - { - tx_service_attachment& tsa = boost::get(o); - if (tsa.security.size()) - { - CHECK_AND_ASSERT_MES(tsa.security.size() == 1, false, "Wrong tsa.security.size() = " << tsa.security.size()); - - bool r = derive_public_key_from_target_address(sender_account_keys.account_address, one_time_secret_key, att_count, tsa.security.back()); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive_public_key_from_target_address"); - } - att_count++; - } - } - if (!(flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)) - { - //take hash from attachment and put into extra - if (tx.attachment.size()) - add_attachments_info_to_extra(tx.extra, tx.attachment); - } - else - { - // for separately signed tx each input has to contain information about corresponding outputs, extra entries and attachments - for (size_t in_index = input_starter_index; in_index != tx.vin.size(); in_index++) - { - // add signed_parts to each input's details (number of outputs and extra entries) - signed_parts so = AUTO_VAL_INIT(so); - so.n_outs = tx.vout.size(); - so.n_extras = tx.extra.size(); - get_txin_etc_options(tx.vin[in_index]).push_back(so); - - // put attachment extra info to each input's details (in case there are attachments) - add_attachments_info_to_extra(get_txin_etc_options(tx.vin[in_index]), tx.attachment); - } - } - - //generate ring signatures - crypto::hash tx_prefix_hash; - get_transaction_prefix_hash(tx, tx_prefix_hash); - - std::stringstream ss_ring_s; - size_t input_index = input_starter_index; - size_t in_context_index = 0; - BOOST_FOREACH(const tx_source_entry& src_entr, sources) - { - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, input_index, tx_prefix_hash); - CHECK_AND_ASSERT_MES(tx_hash_for_signature != null_hash, false, "failed to prepare_prefix_hash_for_sign"); - - tx.signatures.push_back(std::vector()); - std::vector& sigs = tx.signatures.back(); - - if(src_entr.is_multisig()) - { - // txin_multisig -- don't sign anything here (see also sign_multisig_input_in_tx()) - sigs.resize(src_entr.ms_keys_count, null_sig); // just reserve keys.size() null signatures (NOTE: not minimum_sigs!) - } - else - { - // regular txin_to_key or htlc - ss_ring_s << "input #" << input_index << ", pub_keys:" << ENDL; - std::vector keys_ptrs; - BOOST_FOREACH(const tx_source_entry::output_entry& o, src_entr.outputs) - { - keys_ptrs.push_back(&o.second); - ss_ring_s << o.second << ENDL; - } - sigs.resize(src_entr.outputs.size()); - - if (!watch_only_mode) - crypto::generate_ring_signature(tx_hash_for_signature, get_to_key_input_from_txin_v(tx.vin[input_index]).k_image, keys_ptrs, in_contexts[in_context_index].in_ephemeral.sec, src_entr.real_output, sigs.data()); - - ss_ring_s << "signatures:" << ENDL; - std::for_each(sigs.begin(), sigs.end(), [&ss_ring_s](const crypto::signature& s) { ss_ring_s << s << ENDL; }); - ss_ring_s << "prefix_hash: " << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[in_context_index].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output << ENDL; - } - if (src_entr.separately_signed_tx_complete) - { - // if separately signed tx is complete, put one more signature to the last bunch using tx secret key, which confirms that transaction has been generated by authorized subject - CHECK_AND_ASSERT_MES(input_index == tx.vin.size() - 1, false, "separately_signed_tx_complete flag is set for source entry #" << input_index << ", allowed only for the last one"); - CHECK_AND_ASSERT_MES(flags & TX_FLAG_SIGNATURE_MODE_SEPARATE, false, "sorce entry separately_signed_tx_complete flag is set for tx with no TX_FLAG_SIGNATURE_MODE_SEPARATE flag"); - CHECK_AND_ASSERT_MES(tx_hash_for_signature == tx_prefix_hash, false, "internal error: hash_for_sign for the last input of separately signed complete tx expected to be the same as tx prefix hash"); - sigs.resize(sigs.size() + 1); - crypto::generate_signature(tx_prefix_hash, txkey.pub, txkey.sec, sigs.back()); - } - - input_index++; - in_context_index++; - } - - LOG_PRINT2("construct_tx.log", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str(), LOG_LEVEL_3); - - return true; - } - //--------------------------------------------------------------- - uint64_t get_reward_from_miner_tx(const transaction& tx) - { - uint64_t income = 0; - for (auto& in : tx.vin) - { - if (in.type() == typeid(txin_gen)) - { - continue; - } - else if (in.type() == typeid(txin_to_key)) - { - income += boost::get(in).amount; - } - } - uint64_t reward = 0; - for (auto& out : tx.vout) - { - reward += out.amount; - } - reward -= income; - return reward; - } - //--------------------------------------------------------------- - std::string get_word_from_timstamp(uint64_t timestamp, bool use_password) - { - uint64_t date_offset = timestamp > WALLET_BRAIN_DATE_OFFSET ? timestamp - WALLET_BRAIN_DATE_OFFSET : 0; - uint64_t weeks_count = date_offset / WALLET_BRAIN_DATE_QUANTUM; - CHECK_AND_ASSERT_THROW_MES(weeks_count < WALLET_BRAIN_DATE_MAX_WEEKS_COUNT, "SEED PHRASE need to be extended or refactored"); - - if (use_password) - weeks_count += WALLET_BRAIN_DATE_MAX_WEEKS_COUNT; - - CHECK_AND_ASSERT_THROW_MES(weeks_count < std::numeric_limits::max(), "internal error: unable to convert to uint32, val = " << weeks_count); - uint32_t weeks_count_32 = static_cast(weeks_count); - - return tools::mnemonic_encoding::word_by_num(weeks_count_32); - } - //--------------------------------------------------------------- - uint64_t get_timstamp_from_word(std::string word, bool& password_used) - { - uint64_t count_of_weeks = tools::mnemonic_encoding::num_by_word(word); - if (count_of_weeks >= WALLET_BRAIN_DATE_MAX_WEEKS_COUNT) - { - count_of_weeks -= WALLET_BRAIN_DATE_MAX_WEEKS_COUNT; - password_used = true; - } - else { - password_used = false; - } - uint64_t timestamp = count_of_weeks * WALLET_BRAIN_DATE_QUANTUM + WALLET_BRAIN_DATE_OFFSET; - - return timestamp; - } - //--------------------------------------------------------------- - bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed /* = nullptr */) - { -#define LOC_CHK(cond, msg) CHECK_AND_ASSERT_MES(cond, false, msg << ", ms input index: " << ms_input_index << ", tx: " << get_transaction_hash(tx) << ", source tx: " << get_transaction_hash(source_tx)) - if (p_is_input_fully_signed != nullptr) - *p_is_input_fully_signed = false; - - LOC_CHK(ms_input_index < tx.vin.size(), "ms input index is out of bounds, vin.size() = " << tx.vin.size()); - LOC_CHK(tx.vin[ms_input_index].type() == typeid(txin_multisig), "ms input has wrong type, txin_multisig expected"); - const txin_multisig& ms_in = boost::get(tx.vin[ms_input_index]); - - // search ms output in source tx by ms_in.multisig_out_id - size_t ms_out_index = SIZE_MAX; - for (size_t i = 0; i < source_tx.vout.size(); ++i) - { - if (source_tx.vout[i].target.type() == typeid(txout_multisig) && ms_in.multisig_out_id == get_multisig_out_id(source_tx, i)) - { - ms_out_index = i; - break; - } - } - LOC_CHK(ms_out_index != SIZE_MAX, "failed to find ms output in source tx " << get_transaction_hash(source_tx) << " by ms id " << ms_in.multisig_out_id); - const txout_multisig& out_ms = boost::get(source_tx.vout[ms_out_index].target); - - crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx); - - keypair ms_in_ephemeral_key = AUTO_VAL_INIT(ms_in_ephemeral_key); - bool r = currency::derive_ephemeral_key_helper(keys, source_tx_pub_key, ms_out_index, ms_in_ephemeral_key); - LOC_CHK(r, "derive_ephemeral_key_helper failed"); - - size_t participant_index = std::find(out_ms.keys.begin(), out_ms.keys.end(), ms_in_ephemeral_key.pub) - out_ms.keys.begin(); - LOC_CHK(participant_index < out_ms.keys.size(), "Can't find given participant's ms key in ms output keys list"); - LOC_CHK(ms_input_index < tx.signatures.size(), "transaction does not have signatures vectory entry for ms input #" << ms_input_index); - - auto& sigs = tx.signatures[ms_input_index]; - LOC_CHK(!sigs.empty(), "empty signatures container"); - - bool extra_signature_expected = (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) && ms_input_index == tx.vin.size() - 1; - size_t allocated_sigs_for_participants = extra_signature_expected ? sigs.size() - 1 : sigs.size(); - LOC_CHK(participant_index < allocated_sigs_for_participants, "participant index (" << participant_index << ") is out of bound: " << allocated_sigs_for_participants); // NOTE: this may fail if the input has already been fully signed and 'sigs' was compacted - - crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, ms_input_index, get_transaction_hash(tx)); - LOC_CHK(tx_hash_for_signature != null_hash, "failed to prepare_prefix_hash_for_sign"); - - crypto::generate_signature(tx_hash_for_signature, ms_in_ephemeral_key.pub, ms_in_ephemeral_key.sec, sigs[participant_index]); - - // check whether the input is fully signed - size_t non_null_sigs_count = 0; - for (size_t i = 0; i < allocated_sigs_for_participants; ++i) - { - if (sigs[i] != null_sig) - ++non_null_sigs_count; - } - LOC_CHK(non_null_sigs_count <= out_ms.minimum_sigs, "somehow there are too many non-null signatures for this input: " << non_null_sigs_count << ", minimum_sigs: " << out_ms.minimum_sigs); - if (non_null_sigs_count == out_ms.minimum_sigs) - { - // this input is fully signed, now we gonna compact sigs container by removing null signatures - sigs.erase(std::remove(sigs.begin(), sigs.end(), null_sig), sigs.end()); - - if (p_is_input_fully_signed != nullptr) - *p_is_input_fully_signed = true; - } - - return true; -#undef LOC_CHK - } - //--------------------------------------------------------------- - uint64_t get_inputs_money_amount(const transaction& tx) - { - uint64_t r = 0; - get_inputs_money_amount(tx, r); - return r; - } - //--------------------------------------------------------------- - bool get_inputs_money_amount(const transaction& tx, uint64_t& money) - { - money = 0; - for(const auto& in : tx.vin) - { - uint64_t this_amount = get_amount_from_variant(in); - if (!this_amount) - return false; - money += this_amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_block_height(const transaction& coinbase) - { - CHECK_AND_ASSERT_MES(coinbase.vin.size() == 1 || coinbase.vin.size() == 2, 0, "wrong miner tx in block: -----, b.miner_tx.vin.size() != 1"); - CHECKED_GET_SPECIFIC_VARIANT(coinbase.vin[0], const txin_gen, coinbase_in, 0); - return coinbase_in.height; - } - //--------------------------------------------------------------- - uint64_t get_block_height(const block& b) - { - return get_block_height(b.miner_tx); - } - //--------------------------------------------------------------- - bool check_inputs_types_supported(const transaction& tx) - { - for(const auto& in : tx.vin) - { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_multisig) || in.type() == typeid(txin_htlc), false, "wrong variant type: " - << in.type().name() - << ", in transaction id=" << get_transaction_hash(tx)); - } - return true; - } - //------------------------------------------------------------------ - /* - bool add_padding_to_tx(transaction& tx, size_t count) - { - - WARNING: potantially unsafe implementation! - 1) requires extra_padding being previously added to tx's extra; - 2) transaction size may increase by more than 'count' bytes due to varint encoding (thus, if 'count' is 128 it will add 129 bytes) - See also check_add_padding_to_tx test (uncomment and update it, if necessary). - - if (!count) - return true; - - for (auto& ex : tx.extra) - { - if (ex.type() == typeid(extra_padding)) - { - boost::get(ex).buff.insert(boost::get(ex).buff.end(), count, 0); - return true; - } - } - CHECK_AND_ASSERT_THROW_MES(false, "extra_padding entry not found in template mining transaction"); - return false; - } - */ - //------------------------------------------------------------------ - bool remove_padding_from_tx(transaction& tx, size_t count) - { - if (!count) - return true; - - for (auto ex : tx.extra) - { - if (ex.type() == typeid(extra_padding)) - { - std::vector& buff = boost::get(ex).buff; - CHECK_AND_ASSERT_MES(buff.size() >= count, false, "Attempt to remove_padding_from_tx for count = " << count << ", while buff.size()=" << buff.size()); - buff.resize(buff.size() - count); - return true; - } - } - CHECK_AND_ASSERT_THROW_MES(false, "extra_padding entry not found in template mining transaction"); - return false; - } - //------------------------------------------------------------------ - bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time) - { - if (unlock_time < CURRENCY_MAX_BLOCK_NUMBER) - { - //interpret as block index - return unlock_time <= current_blockchain_size - 1 + CURRENCY_LOCKED_TX_ALLOWED_DELTA_BLOCKS; - } - - //interpret as time - return unlock_time <= current_time + CURRENCY_LOCKED_TX_ALLOWED_DELTA_SECONDS; - } - //----------------------------------------------------------------------------------------------- - bool check_outs_valid(const transaction& tx) - { - for(const tx_out& out : tx.vout) - { - CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); - if (out.target.type() == typeid(txout_to_key)) - { - if (!check_key(boost::get(out.target).key)) - return false; - } - else if (out.target.type() == typeid(txout_htlc)) - { - const txout_htlc& htlc = boost::get(out.target); - if (!check_key(htlc.pkey_redeem)) - return false; - if (!check_key(htlc.pkey_refund)) - return false; - } - else if (out.target.type() == typeid(txout_multisig)) - { - const txout_multisig& ms = boost::get(out.target); - if (!(ms.keys.size() > 0 && ms.minimum_sigs > 0 && ms.minimum_sigs <= ms.keys.size())) - { - LOG_ERROR("wrong multisig in transaction id=" << get_transaction_hash(tx)); - return false; - } - } - else - { - LOG_ERROR("wrong variant type: " << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); - } - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_money_overflow(const transaction& tx) - { - return check_inputs_overflow(tx) && check_outs_overflow(tx); - } - //--------------------------------------------------------------- - bool check_inputs_overflow(const transaction& tx) - { - uint64_t money = 0; - BOOST_FOREACH(const auto& in, tx.vin) - { - uint64_t this_amount = 0; - if (in.type() == typeid(txin_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - this_amount = tokey_in.amount; - } - else if (in.type() == typeid(txin_multisig)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_multisig, ms_in, false); - this_amount = ms_in.amount; - } - else if (in.type() == typeid(txin_htlc)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_htlc, htlc_in, false); - this_amount = htlc_in.amount; - } - else - { - LOG_ERROR("Unknow type in in: " << in.type().name()); - return false; - } - if (money > this_amount + money) - return false; - money += this_amount; - } - return true; - } - //--------------------------------------------------------------- - bool check_outs_overflow(const transaction& tx) - { - uint64_t money = 0; - BOOST_FOREACH(const auto& o, tx.vout) - { - if (money > o.amount + money) - return false; - money += o.amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_outs_money_amount(const transaction& tx) - { - uint64_t outputs_amount = 0; - for(const auto& o : tx.vout) - outputs_amount += o.amount; - return outputs_amount; - } - //--------------------------------------------------------------- - std::string short_hash_str(const crypto::hash& h) - { - std::string res = string_tools::pod_to_hex(h); - CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion"); - auto erased_pos = res.erase(8, 48); - res.insert(8, "...."); - return res; - } - //--------------------------------------------------------------- - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index) - { - crypto::public_key pk; - if (!derive_public_key(derivation, output_index, acc.account_address.spend_public_key, pk)) - return false; - return pk == out_key.key; - } - //--------------------------------------------------------------- - bool is_out_to_acc(const account_keys& acc, const txout_multisig& out_multisig, const crypto::key_derivation& derivation, size_t output_index) - { - crypto::public_key pk; - if (!derive_public_key(derivation, output_index, acc.account_address.spend_public_key, pk)) - return false; - auto it = std::find(out_multisig.keys.begin(), out_multisig.keys.end(), pk); - if (out_multisig.keys.end() == it) - return false; - return true; - } - //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation) - { - crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); - if (null_pkey == tx_pub_key) - return false; - return lookup_acc_outs(acc, tx, get_tx_pub_key_from_extra(tx), outs, money_transfered, derivation); - } - //--------------------------------------------------------------- - bool check_tx_derivation_hint(const transaction& tx, const crypto::key_derivation& derivation) - { - bool found_der_xor = false; - uint16_t hint = get_derivation_hint(derivation); - tx_derivation_hint dh = make_tx_derivation_hint_from_uint16(hint); - for (auto& e : tx.extra) - { - if (e.type() == typeid(tx_derivation_hint)) - { - const tx_derivation_hint& tdh = boost::get(e); - if (tdh.msg.size() == sizeof(uint16_t)) - { - found_der_xor = true; - if (dh.msg == tdh.msg) - return true; - } - } - } - //if tx doesn't have any hints - feature is not supported, use full scan - if (!found_der_xor) - return true; - - return false; - } - //--------------------------------------------------------------- - bool lookup_acc_outs_genesis(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation) - { - uint64_t offset = 0; - bool r = get_account_genesis_offset_by_address(get_account_address_as_str(acc.account_address), offset); - if (!r) - return true; - - CHECK_AND_ASSERT_MES(offset < tx.vout.size(), false, "condition failed: offset(" << offset << ") < tx.vout.size() (" << tx.vout.size() << ")"); - auto& o = tx.vout[offset]; - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "condition failed: o.target.type() == typeid(txout_to_key)"); - if (is_out_to_acc(acc, boost::get(o.target), derivation, offset)) - { - outs.push_back(offset); - money_transfered += o.amount; - } - return true; - } - //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation) - { - std::list htlc_info_list; - return lookup_acc_outs(acc, tx, tx_pub_key, outs, money_transfered, derivation, htlc_info_list); - } - //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list) - { - money_transfered = 0; - bool r = generate_key_derivation(tx_pub_key, acc.view_secret_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "unable to generate derivation from tx_pub = " << tx_pub_key << " * view_sec, invalid tx_pub?"); - - if (is_coinbase(tx) && get_block_height(tx) == 0 && tx_pub_key == ggenesis_tx_pub_key) - { - //genesis coinbase - return lookup_acc_outs_genesis(acc, tx, tx_pub_key, outs, money_transfered, derivation); - } - - if (!check_tx_derivation_hint(tx, derivation)) - return true; - - size_t i = 0; - for(const tx_out& o : tx.vout) - { - if (o.target.type() == typeid(txout_to_key)) - { - if (is_out_to_acc(acc, boost::get(o.target), derivation, i)) - { - outs.push_back(i); - money_transfered += o.amount; - } - } - else if (o.target.type() == typeid(txout_multisig)) - { - if (is_out_to_acc(acc, boost::get(o.target), derivation, i)) - { - outs.push_back(i); - //don't count this money - } - } - else if (o.target.type() == typeid(txout_htlc)) - { - htlc_info hi = AUTO_VAL_INIT(hi); - const txout_htlc& htlc = boost::get(o.target); - if (is_out_to_acc(acc, htlc.pkey_redeem, derivation, i)) - { - hi.hltc_our_out_is_before_expiration = true; - htlc_info_list.push_back(hi); - outs.push_back(i); - } - else if (is_out_to_acc(acc, htlc.pkey_refund, derivation, i)) - { - hi.hltc_our_out_is_before_expiration = false; - htlc_info_list.push_back(hi); - outs.push_back(i); - } - } - else - { - LOG_ERROR("Wrong type at lookup_acc_outs, unexpected type is: " << o.target.type().name()); - return false; - } - i++; - } - return true; - } - //--------------------------------------------------------------- - bool set_payment_id_to_tx(std::vector& att, const std::string& payment_id) - { - if (!is_payment_id_size_ok(payment_id)) - return false; - - tx_service_attachment tsa = AUTO_VAL_INIT(tsa); - tsa.service_id = BC_PAYMENT_ID_SERVICE_ID; - tsa.body = payment_id; - att.push_back(tsa); - return true; - } - - - - //--------------------------------------------------------------- - std::string print_money_brief(uint64_t amount) - { - uint64_t remainder = amount % COIN; - amount /= COIN; - if (remainder == 0) - return std::to_string(amount) + ".0"; - std::string r = std::to_string(remainder); - if (r.size() < CURRENCY_DISPLAY_DECIMAL_POINT) - r.insert(0, CURRENCY_DISPLAY_DECIMAL_POINT - r.size(), '0'); - return std::to_string(amount) + '.' + r.substr(0, r.find_last_not_of('0') + 1); - } - //--------------------------------------------------------------- - /*bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size) - { - - - return get_object_hash(t, res, blob_size); - }*/ - //------------------------------------------------------------------ - template - crypto::hash hash_together(const pod_operand_a& a, const pod_operand_b& b) - { - std::string blob; - string_tools::append_pod_to_strbuff(blob, a); - string_tools::append_pod_to_strbuff(blob, b); - return crypto::cn_fast_hash(blob.data(), blob.size()); - } - //------------------------------------------------------------------ - //-------------------------------------------------------------- - bool unserialize_block_complete_entry(const currency::COMMAND_RPC_GET_BLOCKS_FAST::response& serialized, - currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& unserialized) - { - for (const auto& bl_entry : serialized.blocks) - { - unserialized.blocks.push_back(block_direct_data_entry()); - block_direct_data_entry& bdde = unserialized.blocks.back(); - auto blextin_ptr = std::make_shared(); - bool r = currency::parse_and_validate_block_from_blob(bl_entry.block, blextin_ptr->bl); - bdde.block_ptr = blextin_ptr; - CHECK_AND_ASSERT_MES(r, false, "failed to parse block from blob: " << string_tools::buff_to_hex_nodelimer(bl_entry.block)); - size_t i = 0; - if (bl_entry.tx_global_outs.size()) - { - CHECK_AND_ASSERT_MES(bl_entry.tx_global_outs.size() == bl_entry.txs.size(), false, "tx_global_outs count " << bl_entry.tx_global_outs.size() << " count missmatch with bl_entry.txs count " << bl_entry.txs.size()); - } - if (bl_entry.coinbase_global_outs.size()) - { - std::shared_ptr tche_ptr(new currency::transaction_chain_entry()); - tche_ptr->m_global_output_indexes = bl_entry.coinbase_global_outs; - bdde.coinbase_ptr = tche_ptr; - } - for (const auto& tx_blob : bl_entry.txs) - { - std::shared_ptr tche_ptr(new currency::transaction_chain_entry()); - r = parse_and_validate_tx_from_blob(tx_blob, tche_ptr->tx); - CHECK_AND_ASSERT_MES(r, false, "failed to parse tx from blob: " << string_tools::buff_to_hex_nodelimer(tx_blob)); - bdde.txs_ptr.push_back(tche_ptr); - if (bl_entry.tx_global_outs.size()) - { - CHECK_AND_ASSERT_MES(bl_entry.tx_global_outs[i].v.size() == tche_ptr->tx.vout.size(), false, "tx_global_outs for tx" << bl_entry.tx_global_outs[i].v.size() << " count missmatch with tche_ptr->tx.vout.size() count " << tche_ptr->tx.vout.size()); - tche_ptr->m_global_output_indexes = bl_entry.tx_global_outs[i].v; - } - i++; - } - } - return true; - } - - //--------------------------------------------------------------- - uint64_t get_alias_coast_from_fee(const std::string& alias, uint64_t median_fee) - { - return median_fee * 10; - } - //--------------------------------------------------------------- - // NOTE: this function is obsolete and depricated - // PoS block real timestamp is set using a service attachment in mining tx extra since 2021-10 - uint64_t get_actual_timestamp(const block& b) - { - uint64_t tes_ts = b.timestamp; - if (is_pos_block(b)) - { - etc_tx_time t = AUTO_VAL_INIT(t); - if(get_type_in_variant_container(b.miner_tx.extra, t)) - tes_ts = t.v; - } - return tes_ts; - } - //--------------------------------------------------------------- - // returns timestamp from BC_BLOCK_DATETIME_SERVICE_ID via tx_service_attachment in extra - // fallbacks to old-style actual timestamp via etc_tx_time, then to block timestamp - uint64_t get_block_datetime(const block& b) - { - // first try BC_BLOCK_DATETIME_SERVICE_ID - tx_service_attachment sa = AUTO_VAL_INIT(sa); - if (get_type_in_variant_container(b.miner_tx.extra, sa)) - { - if (sa.service_id == BC_BLOCK_DATETIME_SERVICE_ID && sa.instruction == BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT) - { - uint64_t ts; - if (epee::string_tools::get_pod_from_strbuff(sa.body, ts)) - return ts; - } - } - - // next try etc_tx_time - etc_tx_time t = AUTO_VAL_INIT(t); - if (get_type_in_variant_container(b.miner_tx.extra, t)) - return t.v; - - // otherwise return default: block.ts - return b.timestamp; - } - //--------------------------------------------------------------- - void set_block_datetime(uint64_t datetime, block& b) - { - tx_service_attachment sa = AUTO_VAL_INIT(sa); - sa.service_id = BC_BLOCK_DATETIME_SERVICE_ID; - sa.instruction = BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT; - sa.flags = 0; - epee::string_tools::append_pod_to_strbuff(sa.body, datetime); - b.miner_tx.extra.push_back(sa); - } - //------------------------------------------------------------------ - bool validate_alias_name(const std::string& al) - { - CHECK_AND_ASSERT_MES(al.size() <= ALIAS_NAME_MAX_LEN, false, "Too long alias name, please use name no longer than " << ALIAS_NAME_MAX_LEN); - /*allowed symbols "0-9", "a-z", "-", "." */ - static bool alphabet[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - for (const auto ch : al) - { - CHECK_AND_ASSERT_MES(alphabet[static_cast(ch)], false, "Wrong character in alias: '" << ch << "'"); - } - return true; - } - //------------------------------------------------------------------ - bool validate_password(const std::string& password) - { - static const std::string allowed_password_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!?@#$%^&*_+|{}[]()<>:;\"'-=\\/.,"; - size_t n = password.find_first_not_of(allowed_password_symbols, 0); - return n == std::string::npos; - } - - //------------------------------------------------------------------ -#define ANTI_OVERFLOW_AMOUNT 1000000 -#define GET_PERECENTS_BIG_NUMBERS(per, total) (per/ANTI_OVERFLOW_AMOUNT)*100 / (total/ANTI_OVERFLOW_AMOUNT) - - void print_reward_change() - { - std::cout << std::endl << "Reward change for 10 years:" << std::endl; - std::cout << std::setw(10) << std::left << "day" << std::setw(19) << "block reward" << std::setw(19) << "generated coins" << std::endl; - - boost::multiprecision::uint128_t already_generated_coins = PREMINE_AMOUNT; - boost::multiprecision::uint128_t money_was_at_begining_of_year = already_generated_coins; - boost::multiprecision::uint128_t total_generated_in_year_by_pos = 0; - boost::multiprecision::uint128_t total_generated_in_year_by_pow = 0; - //uint64_t total_money_supply = TOTAL_MONEY_SUPPLY; - uint64_t h = 0; - for (uint64_t day = 0; day != 365 * 10; ++day) - { - if (!(day % 366)) - { - uint64_t emission_reward = 0; - get_block_reward(h % 2, 0, 0, already_generated_coins, emission_reward, h); - - std::cout << std::left - << std::setw(10) << day - << std::setw(19) << print_money(emission_reward) - << std::setw(4) << print_money(already_generated_coins) - << "(POS: " << boost::lexical_cast(GET_PERECENTS_BIG_NUMBERS(total_generated_in_year_by_pos, money_was_at_begining_of_year)) << "%" - << ", POW: " << boost::lexical_cast(GET_PERECENTS_BIG_NUMBERS(total_generated_in_year_by_pow, money_was_at_begining_of_year)) << "%)" - - << std::setw(19) << ",PoS coins/year: " << print_money(total_generated_in_year_by_pos) - << std::setw(19) << ",PoW coins/year:" << print_money(total_generated_in_year_by_pow) - - - << std::endl; - - - total_generated_in_year_by_pos = total_generated_in_year_by_pow = 0; - money_was_at_begining_of_year = already_generated_coins; - - } - - - for (size_t i = 0; i != CURRENCY_BLOCKS_PER_DAY; i++) - { - uint64_t emission_reward = 0; - h++; - get_block_reward(h % 2, 0, 0, already_generated_coins, emission_reward, h); - already_generated_coins += emission_reward; - if (h % 2) - total_generated_in_year_by_pos += emission_reward; - else - total_generated_in_year_by_pow += emission_reward; - - } - } - } - void print_reward_change_short() - { -// std::cout << std::endl << "Reward change for 20 days:" << std::endl; -// std::cout << std::setw(10) << std::left << "day" << std::setw(19) << "block reward" << std::setw(19) << "generated coins" << std::endl; -// -// const boost::multiprecision::uint128_t& already_generated_coins = PREMINE_AMOUNT; -// //uint64_t total_money_supply = TOTAL_MONEY_SUPPLY; -// uint64_t h = 0; -// for (uint64_t day = 0; day != 20; ++day) -// { -// uint64_t emission_reward = 0; -// get_block_reward(h % 2, 0, 0, already_generated_coins, emission_reward, h, (already_generated_coins - PREMINE_AMOUNT) * 140); -// -// std::cout << std::left -// << std::setw(10) << day -// << std::setw(19) << print_money(emission_reward) -// << std::setw(4) << print_money(already_generated_coins)//std::string(std::to_string(GET_PERECENTS_BIG_NUMBERS((already_generated_coins), total_money_supply)) + "%") -// << std::endl; -// -// -// -// for (size_t i = 0; i != 720; i++) -// { -// h++; -// get_block_reward(h % 2, 0, 0, already_generated_coins, emission_reward, h, (already_generated_coins - PREMINE_AMOUNT) * 140); -// already_generated_coins += emission_reward; -// if (h < POS_START_HEIGHT && i > 360) -// break; -// } -// } - } - - std::string print_reward_change_first_blocks(size_t n_of_first_blocks) - { - std::stringstream ss; - ss << std::endl << "Reward change for the first " << n_of_first_blocks << " blocks:" << std::endl; - ss << std::setw(10) << std::left << "block #" << std::setw(20) << "block reward" << std::setw(20) << "generated coins" << std::setw(8) << "type" << std::endl; - - boost::multiprecision::uint128_t already_generated_coins = 0; - uint64_t total_generated_pos = 0; - uint64_t total_generated_pow = 0; - - for (size_t h = 0; h != n_of_first_blocks; ++h) - { - bool is_pos = h < 10 ? false : h % 2 == 0; - uint64_t emission_reward = 0; - - if (h == 0) - { - emission_reward = PREMINE_AMOUNT; - } - else - { - currency::get_block_reward(is_pos, 0, 0, already_generated_coins, emission_reward, h); - (is_pos ? total_generated_pos : total_generated_pow) += emission_reward; - } - - already_generated_coins += emission_reward; - - ss << std::left - << std::setw(10) << h - << std::setw(20) << currency::print_money(emission_reward) - << std::setw(20) << currency::print_money(already_generated_coins) - << std::setw(8) << (h == 0 ? "genesis" : (is_pos ? "PoS" : "PoW")) - << std::endl; - } - ss << "total generated PoW: " << currency::print_money(total_generated_pow) << std::endl; - ss << "total generated PoS: " << currency::print_money(total_generated_pos) << std::endl; - return ss.str(); - } - //------------------------------------------------------------------ - void print_currency_details() - { - //for future forks - - std::cout << "Currency name: \t\t" << CURRENCY_NAME << "(" << CURRENCY_NAME_SHORT << ")" << std::endl; - std::cout << "Money supply: \t\t " << CURRENCY_BLOCK_REWARD * CURRENCY_BLOCKS_PER_DAY * 365 << " coins per year" << std::endl; - std::cout << "PoS block interval: \t" << DIFFICULTY_POS_TARGET << " seconds" << std::endl; - std::cout << "PoW block interval: \t" << DIFFICULTY_POW_TARGET << " seconds" << std::endl; - std::cout << "Total blocks per day: \t" << CURRENCY_BLOCKS_PER_DAY << " seconds" << std::endl; - std::cout << "Default p2p port: \t" << P2P_DEFAULT_PORT << std::endl; - std::cout << "Default rpc port: \t" << RPC_DEFAULT_PORT << std::endl; -#ifndef TEST_FAST_EMISSION_CURVE - print_reward_change(); -#else - print_reward_change_short(); -#endif - } - //------------------------------------------------------------------ - std::string dump_patch(const std::map& patch) - { - std::stringstream ss; - for (auto& p : patch) - { - ss << "[" << p.first << "]" << p.second << ENDL; - } - return ss.str(); - } - //--------------------------------------------------------------- - bool generate_genesis_block(block& bl) - { - //genesis block - bl = boost::value_initialized(); - -#ifndef TESTNET -// std::string genesis_coinbase_tx_hex((const char*)&ggenesis_tx_raw, sizeof(ggenesis_tx_raw)); - -#else - std::string genesis_coinbase_tx_hex = ""; -#endif - - //genesis proof phrase: "Liverpool beat Barcelona: Greatest Champions League comebacks of all time" - //taken from: https://www.bbc.com/sport/football/48163330 - //sha3-256 from proof phrase: a074236b1354901d5dbc029c0ac4c05c948182c34f3030f32b0c93aee7ba275c (included in genesis block) - - - blobdata tx_bl((const char*)&ggenesis_tx_raw, sizeof(ggenesis_tx_raw)); - //string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl); - bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); - CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); - bl.major_version = BLOCK_MAJOR_VERSION_GENESIS; - bl.minor_version = BLOCK_MINOR_VERSION_GENESIS; - bl.timestamp = 0; - bl.nonce = CURRENCY_GENESIS_NONCE; - LOG_PRINT_GREEN("Generated genesis: " << get_block_hash(bl), LOG_LEVEL_0); - return true; - } - //---------------------------------------------------------------------------------------------------- - const crypto::hash& get_genesis_hash(bool need_to_set, const crypto::hash& h) - { - static crypto::hash genesis_id = null_hash; - if (genesis_id == null_hash && !need_to_set) - { - LOG_PRINT_GREEN("Calculating genesis....", LOG_LEVEL_0); - block b = AUTO_VAL_INIT(b); - bool r = generate_genesis_block(b); - CHECK_AND_ASSERT_MES(r, null_hash, "failed to generate genesis block"); - genesis_id = get_block_hash(b); - } - - if (need_to_set) - { - genesis_id = h; - } - return genesis_id; - } - //--------------------------------------------------------------- - std::vector relative_output_offsets_to_absolute(const std::vector& off) - { - //if array has both types of outs, then global index (uint64_t) should be first, and then the rest could be out_by_id - - std::vector res = off; - for (size_t i = 1; i < res.size(); i++) - { - if (res[i].type() == typeid(ref_by_id)) - break; - boost::get(res[i]) += boost::get(res[i - 1]); - } - - return res; - } - //--------------------------------------------------------------- - std::vector absolute_output_offsets_to_relative(const std::vector& off) - { - std::vector res = off; - if (off.size() < 2) - return res; - - std::sort(res.begin(), res.end(), [](const txout_ref_v& lft, const txout_ref_v& rght) - { - if (lft.type() == typeid(uint64_t)) - { - if (rght.type() == typeid(uint64_t)) - return boost::get(lft) < boost::get(rght); - else if (rght.type() == typeid(ref_by_id)) - return true; - else - LOG_ERROR("Unknown type in txout_v"); - } - else if (lft.type() == typeid(ref_by_id)) - { - if (rght.type() == typeid(uint64_t)) - return false; - else if (rght.type() == typeid(ref_by_id)) - return false; // don't change the order of ref_by_id elements - else - LOG_ERROR("Unknown type in txout_v"); - } - return false; - });//just to be sure, actually it is already should be sorted - - //find starter index - skip ref_by_id entries - size_t i = res.size() - 1; - while (i != 0 && res[i].type() == typeid(ref_by_id)) - --i; - - for (; i != 0; i--) - { - boost::get(res[i]) -= boost::get(res[i - 1]); - } - - - return res; - } - //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b) - { - return parse_and_validate_object_from_blob(b_blob, b); - } - - //--------------------------------------------------------------- - bool is_service_tx(const transaction& tx) - { - auto tx_type = get_tx_type(tx); - if (GUI_TX_TYPE_NORMAL == tx_type || - GUI_TX_TYPE_COIN_BASE == tx_type) - return false; - - return true; - } - //--------------------------------------------------------------- - bool is_showing_sender_addres(const transaction& tx) - { - return have_type_in_variant_container(tx.attachment) || have_type_in_variant_container(tx.attachment); - } - //--------------------------------------------------------------- - bool does_tx_have_only_mixin_inputs(const transaction& tx) - { - for (const auto& e : tx.vin) - { - if (e.type() != typeid(txin_to_key) || e.type() != typeid(txin_multisig) || e.type() != typeid(txin_htlc)) - return false; - if (boost::get(e).key_offsets.size() < 2) - return false; - } - - return true; - } - //--------------------------------------------------------------- - uint64_t get_amount_for_zero_pubkeys(const transaction& tx) - { - uint64_t found_alias_reward = 0; - for (const auto& out : tx.vout) - { - if (out.target.type() != typeid(txout_to_key)) - continue; - - const txout_to_key& o = boost::get(out.target); - if (o.key == null_pkey) - found_alias_reward += out.amount; - } - return found_alias_reward; - } - - //--------------------------------------------------------------- - bool get_aliases_reward_account(account_public_address& acc) - { - bool r = string_tools::parse_tpod_from_hex_string(ALIAS_REWARDS_ACCOUNT_SPEND_PUB_KEY, acc.spend_public_key); - r &= string_tools::parse_tpod_from_hex_string(ALIAS_REWARDS_ACCOUNT_VIEW_PUB_KEY, acc.view_public_key); - return r; - } - //------------------------------------------------------------------ - size_t get_service_attachments_count_in_tx(const transaction& tx) - { - size_t cnt = 0; - for (const auto& at : tx.attachment) - { - if (at.type() == typeid(tx_service_attachment)) - ++cnt; - } - return cnt; - } - - struct rpc_tx_payload_handler : public boost::static_visitor - { - tx_extra_rpc_entry& tv; - rpc_tx_payload_handler(tx_extra_rpc_entry& t) : tv(t) - {} - - bool operator()(const tx_service_attachment& ee) - { - tv.type = "service"; - tv.short_view = ee.service_id + ":" + ee.instruction; - if (ee.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY) - tv.short_view += "(encrypted)"; - else - { - std::string deflated_buff; - const std::string* pfinalbuff = &ee.body; - if (ee.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) - { - bool r = epee::zlib_helper::unpack(ee.body, deflated_buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to unpack"); - pfinalbuff = &deflated_buff; - } - if (ee.service_id == BC_PAYMENT_ID_SERVICE_ID || ee.service_id == BC_OFFERS_SERVICE_ID) - tv.datails_view = *pfinalbuff; - else - tv.datails_view = "BINARY DATA"; - } - return true; - } - bool operator()(const tx_crypto_checksum& ee) - { - tv.type = "crypto_checksum"; - tv.short_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash); - tv.datails_view = std::string("derivation_hash: ") + epee::string_tools::pod_to_hex(ee.derivation_hash) + "\n" - + "encrypted_key_derivation: " + epee::string_tools::pod_to_hex(ee.encrypted_key_derivation); - - return true; - } - bool operator()(const etc_tx_time& ee) - { - tv.type = "pos_time"; - tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v); - return true; - } - bool operator()(const etc_tx_details_unlock_time& ee) - { - tv.type = "unlock_time"; - if (ee.v < CURRENCY_MAX_BLOCK_NUMBER) - tv.short_view = std::string("height: ") + std::to_string(ee.v); - else - tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v); - - return true; - } - bool operator()(const etc_tx_details_unlock_time2& ee) - { - tv.type = "unlock_time"; - std::stringstream ss; - ss << "["; - for (auto v : ee.unlock_time_array) - { - ss << " " << v; - } - ss << "]"; - tv.short_view = ss.str(); - - return true; - } - bool operator()(const etc_tx_details_expiration_time& ee) - { - tv.type = "expiration_time"; - if (ee.v < CURRENCY_MAX_BLOCK_NUMBER) - tv.short_view = std::string("height: ") + std::to_string(ee.v); - else - tv.short_view = std::string("timestamp: ") + std::to_string(ee.v) + " " + epee::misc_utils::get_internet_time_str(ee.v); - - return true; - } - bool operator()(const etc_tx_details_flags& ee) - { - tv.type = "details_flags"; - tv.short_view = epee::string_tools::pod_to_hex(ee.v); - return true; - } - bool operator()(const crypto::public_key& ee) - { - tv.type = "pub_key"; - tv.short_view = epee::string_tools::pod_to_hex(ee); - return true; - } - bool operator()(const extra_attachment_info& ee) - { - tv.type = "attachment_info"; - tv.short_view = std::to_string(ee.sz) + " bytes"; - tv.datails_view = currency::obj_to_json_str(ee); - return true; - } - bool operator()(const extra_alias_entry& ee) - { - tv.type = "alias_info"; - tv.short_view = ee.m_alias + "-->" + get_account_address_as_str(ee.m_address); - tv.datails_view = currency::obj_to_json_str(ee); - - return true; - } - bool operator()(const extra_alias_entry_old& ee) - { - return operator()(static_cast(ee)); - } - bool operator()(const extra_user_data& ee) - { - tv.type = "user_data"; - tv.short_view = std::to_string(ee.buff.size()) + " bytes"; - tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(ee.buff); - - return true; - } - bool operator()(const extra_padding& ee) - { - tv.type = "extra_padding"; - tv.short_view = std::to_string(ee.buff.size()) + " bytes"; - if (!ee.buff.empty()) - tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(&ee.buff[0]), ee.buff.size())); - - return true; - } - bool operator()(const tx_comment& ee) - { - tv.type = "comment"; - tv.short_view = std::to_string(ee.comment.size()) + " bytes(encrypted)"; - tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(ee.comment); - - return true; - } - bool operator()(const tx_payer& ee) - { - //const tx_payer& ee = boost::get(extra); - tv.type = "payer"; - tv.short_view = "(encrypted)"; - - return true; - } - bool operator()(const tx_payer_old&) - { - tv.type = "payer_old"; - tv.short_view = "(encrypted)"; - - return true; - } - bool operator()(const tx_receiver& ee) - { - //const tx_payer& ee = boost::get(extra); - tv.type = "receiver"; - tv.short_view = "(encrypted)"; - - return true; - } - bool operator()(const tx_receiver_old& ee) - { - tv.type = "receiver_old"; - tv.short_view = "(encrypted)"; - - return true; - } - bool operator()(const tx_derivation_hint& ee) - { - tv.type = "derivation_hint"; - tv.short_view = std::to_string(ee.msg.size()) + " bytes"; - tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg); - - return true; - } - bool operator()(const std::string& ee) - { - tv.type = "string"; - tv.short_view = std::to_string(ee.size()) + " bytes"; - tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(ee); - - return true; - } - bool operator()(const etc_tx_flags16_t& dh) - { - tv.type = "FLAGS16"; - tv.short_view = epee::string_tools::pod_to_hex(dh); - tv.datails_view = epee::string_tools::pod_to_hex(dh); - - return true; - } - }; - //------------------------------------------------------------------ - template - bool fill_tx_rpc_payload_items(std::vector& target_vector, const t_container& tc) - { - //handle extra - for (auto& extra : tc) - { - target_vector.push_back(tx_extra_rpc_entry()); - tx_extra_rpc_entry& tv = target_vector.back(); - - rpc_tx_payload_handler vstr(tv); - boost::apply_visitor(vstr, extra); - } - return true; - } - //------------------------------------------------------------------ - bool fill_tx_rpc_outputs(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce) - { - size_t i = 0; - for (auto& out : tx.vout) - { - tei.outs.push_back(tx_out_rpc_entry()); - tei.outs.back().amount = out.amount; - tei.outs.back().is_spent = ptce ? ptce->m_spent_flags[i] : false; - tei.outs.back().global_index = ptce ? ptce->m_global_output_indexes[i] : 0; - - if (out.target.type() == typeid(txout_to_key)) - { - const txout_to_key& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.key)); - if (otk.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX) - tei.outs.back().pub_keys.back() += "(FORCED_NO_MIX)"; - if (otk.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND) - tei.outs.back().pub_keys.back() += std::string("(FORCED_MIX_LOWER_BOUND: ") + std::to_string(otk.mix_attr) + ")"; - } - else if (out.target.type() == typeid(txout_multisig)) - { - const txout_multisig& otm = boost::get(out.target); - for (auto& k : otm.keys) - { - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(k)); - } - tei.outs.back().minimum_sigs = otm.minimum_sigs; - } - else if (out.target.type() == typeid(txout_htlc)) - { - const txout_htlc& otk = boost::get(out.target); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_redeem) + "(htlc_pkey_redeem)"); - tei.outs.back().pub_keys.push_back(epee::string_tools::pod_to_hex(otk.pkey_refund) + "(htlc_pkey_refund)"); - } - - ++i; - } - return true; - } - //------------------------------------------------------------------ - bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx) - { - //handle inputs - for (auto in : tx.vin) - { - tei.ins.push_back(tx_in_rpc_entry()); - if (in.type() == typeid(txin_gen)) - { - tei.ins.back().amount = 0; - } - else if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc)) - { - //TODO: add htlc info - const txin_to_key& tk = get_to_key_input_from_txin_v(in); - tei.ins.back().amount = tk.amount; - tei.ins.back().kimage_or_ms_id = epee::string_tools::pod_to_hex(tk.k_image); - std::vector absolute_offsets = relative_output_offsets_to_absolute(tk.key_offsets); - for (auto& ao : absolute_offsets) - { - tei.ins.back().global_indexes.push_back(0); - if (ao.type() == typeid(uint64_t)) - { - tei.ins.back().global_indexes.back() = boost::get(ao); - } - else// if (ao.type() == typeid(ref_by_id)) - { - //disable for the reset at the moment - tei.ins.back().global_indexes.back() = std::numeric_limits::max(); - } - } - if (in.type() == typeid(txin_htlc)) - { - tei.ins.back().htlc_origin = epee::string_tools::buff_to_hex_nodelimer(boost::get(in).hltc_origin); - } - //tk.etc_details -> visualize it may be later - } - else if (in.type() == typeid(txin_multisig)) - { - txin_multisig& tms = boost::get(in); - tei.ins.back().amount = tms.amount; - tei.ins.back().kimage_or_ms_id = epee::string_tools::pod_to_hex(tms.multisig_out_id); - if (tx.signatures.size() >= tei.ins.size()) - tei.ins.back().multisig_count = tx.signatures[tei.ins.size() - 1].size(); - } - } - return true; - } - bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h) - { - pei_rpc.difficulty = bei_chain.difficulty.convert_to(); - pei_rpc.cumulative_diff_adjusted = bei_chain.cumulative_diff_adjusted.convert_to(); - pei_rpc.cumulative_diff_precise = bei_chain.cumulative_diff_precise.convert_to(); - pei_rpc.block_cumulative_size = bei_chain.block_cumulative_size; - pei_rpc.timestamp = bei_chain.bl.timestamp; - pei_rpc.id = epee::string_tools::pod_to_hex(h); - pei_rpc.prev_id = epee::string_tools::pod_to_hex(bei_chain.bl.prev_id); - pei_rpc.actual_timestamp = get_block_datetime(bei_chain.bl); - pei_rpc.type = is_pos_block(bei_chain.bl) ? 0 : 1; - pei_rpc.already_generated_coins = boost::lexical_cast(bei_chain.already_generated_coins); - pei_rpc.this_block_fee_median = bei_chain.this_block_tx_fee_median; - pei_rpc.effective_fee_median = bei_chain.effective_tx_fee_median; - pei_rpc.height = bei_chain.height; - pei_rpc.object_in_json = currency::obj_to_json_str(bei_chain.bl); - - extra_user_data eud = AUTO_VAL_INIT(eud); - if (get_type_in_variant_container(bei_chain.bl.miner_tx.extra, eud)) - { - pei_rpc.miner_text_info = eud.buff; - } - - pei_rpc.base_reward = get_base_block_reward(is_pos_block(bei_chain.bl), bei_chain.already_generated_coins, bei_chain.height); - pei_rpc.summary_reward = get_reward_from_miner_tx(bei_chain.bl.miner_tx); - pei_rpc.penalty = (pei_rpc.base_reward + pei_rpc.total_fee) - pei_rpc.summary_reward; - return true; - } - //--------------------------------------------------------------- - bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short) - { - //tei.blob = tx_ptr->tx - tei.id = epee::string_tools::pod_to_hex(h); - if(!tei.blob_size) - tei.blob_size = get_object_blobsize(tx); - - tei.fee = get_tx_fee(tx); - tei.pub_key = epee::string_tools::pod_to_hex(get_tx_pub_key_from_extra(tx)); - tei.timestamp = timestamp; - tei.amount = get_outs_money_amount(tx); - - if (is_short) - return true; - - fill_tx_rpc_inputs(tei, tx); - fill_tx_rpc_outputs(tei, tx, ptce); - fill_tx_rpc_payload_items(tei.extra, tx.extra); - fill_tx_rpc_payload_items(tei.attachments, tx.attachment); - return true; - } - //------------------------------------------------------------------ - void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map& gindices) - { - for (size_t n = 0; n < tx.vout.size(); ++n) - { - if (tx.vout[n].target.type() == typeid(txout_to_key) || tx.vout[n].target.type() == typeid(txout_htlc)) - { - uint64_t amount = tx.vout[n].amount; - gindices[amount] += 1; - } - } - } - //--------------------------------------------------------------- - bool get_aliases_reward_account(account_public_address& acc, crypto::secret_key& acc_view_key) - { - bool r = get_aliases_reward_account(acc); - r &= string_tools::parse_tpod_from_hex_string(ALIAS_REWARDS_ACCOUNT_VIEW_SEC_KEY, acc_view_key); - return r; - } - //--------------------------------------------------------------- - bool is_pos_block(const block& b) - { - if (!(b.flags & CURRENCY_BLOCK_FLAG_POS_BLOCK)) - return false; - return is_pos_block(b.miner_tx); - } - //--------------------------------------------------------------- - bool is_pos_block(const transaction& tx) - { - if (tx.vin.size() == 2 && - tx.vin[0].type() == typeid(txin_gen) && - tx.vin[1].type() == typeid(txin_to_key)) - return true; - return false; - } - size_t get_max_block_size() - { - return CURRENCY_MAX_BLOCK_SIZE; - } - //----------------------------------------------------------------------------------------------- - uint64_t get_base_block_reward(bool is_pos, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t height) - { - if (!height) - return PREMINE_AMOUNT; - - return CURRENCY_BLOCK_REWARD; - } - //----------------------------------------------------------------------------------------------- - bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t &reward, uint64_t height) - { - uint64_t base_reward = get_base_block_reward(is_pos, already_generated_coins, height); - - //make it soft - if (median_size < CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE) - { - median_size = CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE; - } - - - if (current_block_size <= median_size || height == 0) - { - reward = base_reward; - return true; - } - - if (current_block_size > 2 * median_size) - { - LOG_PRINT_L4("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); - return false; - } - - uint64_t product_hi; - // BUGFIX(taken from Monero): 32-bit saturation bug (e.g. ARM7), the result was being - // treated as 32-bit by default. - uint64_t multiplicand = 2 * median_size - current_block_size; - multiplicand *= current_block_size; - - uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi); - - uint64_t reward_hi; - uint64_t reward_lo; - div128_32(product_hi, product_lo, static_cast(median_size), &reward_hi, &reward_lo); - div128_32(reward_hi, reward_lo, static_cast(median_size), &reward_hi, &reward_lo); - CHECK_AND_ASSERT_MES(0 == reward_hi, false, "0 == reward_hi"); - CHECK_AND_ASSERT_MES(reward_lo < base_reward, false, "reward_lo < base_reward, reward_lo: " << reward_lo << ", base_reward: " << base_reward << ", current_block_size: " << current_block_size << ", median_size: " << median_size); - - reward = reward_lo; - return true; - } - - //----------------------------------------------------------------------- - bool is_coinbase(const transaction& tx) - { - if (!tx.vin.size() || tx.vin.size() > 2) - return false; - - if (tx.vin[0].type() != typeid(txin_gen)) - return false; - - return true; - } - //----------------------------------------------------------------------- - bool is_coinbase(const transaction& tx, bool& pos_coinbase) - { - if (!is_coinbase(tx)) - return false; - - pos_coinbase = (tx.vin.size() == 2 && tx.vin[1].type() == typeid(txin_to_key)); - return true; - } - //----------------------------------------------------------------------- - bool is_payment_id_size_ok(const payment_id_t& payment_id) - { - return payment_id.size() <= BC_PAYMENT_ID_SERVICE_SIZE_MAX; - } - //----------------------------------------------------------------------- - std::string get_account_address_as_str(const account_public_address& addr) - { - if (addr.flags == 0) - return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr.to_old())); // classic Zano address - - if (addr.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) - return tools::base58::encode_addr(CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (auditable) - - return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (normal) - } - //----------------------------------------------------------------------- - bool is_address_like_wrapped(const std::string& addr) - { - if (addr.length() == 42 && addr.substr(0, 2) == "0x") - return true; - else return false; - } - //----------------------------------------------------------------------- - std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id) - { - if (addr.flags == 0) - return tools::base58::encode_addr(CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr.to_old()) + payment_id); // classic integrated Zano address - - if (addr.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) - return tools::base58::encode_addr(CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr) + payment_id); // new format integrated Zano address (auditable) - - return tools::base58::encode_addr(CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX, t_serializable_object_to_blob(addr) + payment_id); // new format integrated Zano address (normal) - } - //----------------------------------------------------------------------- - bool get_account_address_from_str(account_public_address& addr, const std::string& str) - { - std::string integrated_payment_id; // won't be used - return get_account_address_and_payment_id_from_str(addr, integrated_payment_id, str); - } - //----------------------------------------------------------------------- - bool get_account_address_and_payment_id_from_str(account_public_address& addr, payment_id_t& payment_id, const std::string& str) - { - payment_id.clear(); - blobdata blob; - uint64_t prefix; - if (!tools::base58::decode_addr(str, prefix, blob)) - { - LOG_PRINT_L1("Invalid address format: base58 decoding failed for \"" << str << "\""); - return false; - } - - if (blob.size() < sizeof(account_public_address_old)) - { - LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is less, than expected " << sizeof(account_public_address_old)); - return false; - } - - if (blob.size() > sizeof(account_public_address) + BC_PAYMENT_ID_SERVICE_SIZE_MAX) - { - LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is more, than allowed " << sizeof(account_public_address) + BC_PAYMENT_ID_SERVICE_SIZE_MAX); - return false; - } - - bool parse_as_old_format = false; - - if (prefix == CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX) - { - // normal address - if (blob.size() == sizeof(account_public_address_old)) - { - parse_as_old_format = true; - } - else if (blob.size() == sizeof(account_public_address)) - { - parse_as_old_format = false; - } - else - { - LOG_PRINT_L1("Account public address cannot be parsed from \"" << str << "\", incorrect size"); - return false; - } - } - else if (prefix == CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX) - { - // auditable, parse as new format - parse_as_old_format = false; - } - else if (prefix == CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX) - { - payment_id = blob.substr(sizeof(account_public_address_old)); - blob = blob.substr(0, sizeof(account_public_address_old)); - parse_as_old_format = true; - } - else if (prefix == CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX || prefix == CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX) - { - payment_id = blob.substr(sizeof(account_public_address)); - blob = blob.substr(0, sizeof(account_public_address)); - parse_as_old_format = false; - } - else - { - LOG_PRINT_L1("Address " << str << " has wrong prefix " << prefix); - return false; - } - - if (parse_as_old_format) - { - account_public_address_old addr_old = AUTO_VAL_INIT(addr_old); - if (!::serialization::parse_binary(blob, addr_old)) - { - LOG_PRINT_L1("Account public address (old) cannot be parsed from \"" << str << "\""); - return false; - } - addr = account_public_address::from_old(addr_old); - } - else - { - if (!::serialization::parse_binary(blob, addr)) - { - LOG_PRINT_L1("Account public address cannot be parsed from \"" << str << "\""); - return false; - } - } - - if (payment_id.size() > BC_PAYMENT_ID_SERVICE_SIZE_MAX) - { - LOG_PRINT_L1("Failed to parse address from \"" << str << "\": payment id size exceeded: " << payment_id.size()); - return false; - } - - if (!crypto::check_key(addr.spend_public_key) || !crypto::check_key(addr.view_public_key)) - { - LOG_PRINT_L1("Failed to validate address keys for public address \"" << str << "\""); - return false; - } - - return true; - } - //--------------------------------------------------------------- - bool parse_payment_id_from_hex_str(const std::string& payment_id_str, payment_id_t& payment_id) - { - return epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id); - } - //-------------------------------------------------------------------------------- - crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id) - { - CHECK_AND_ASSERT_MES(tx.vin.size() > in_index, null_hash, "condition failed: tx.vin.size(" << tx.vin.size() << ") > in_index( " << in_index << " )"); - - crypto::hash tx_hash_for_signature = tx_id; - if (get_tx_flags(tx) & TX_FLAG_SIGNATURE_MODE_SEPARATE) - { - // separately signed transaction case - figure out all the outputs, extra entries and attachments the given input refers to - size_t signed_outputs_count = 0; - size_t signed_extras_count = 0; - size_t signed_att_count = 0; - - // extra_attachment_info can be stored either in the tx extra (default) and/or in the input's etc_details (it overrides the default one) - extra_attachment_info eai = AUTO_VAL_INIT(eai); - if (get_type_in_variant_container(tx.extra, eai)) - signed_att_count = static_cast(eai.cnt); // get signed attachments count from default extra_attachment_info (if exists) - - for (size_t i = 0; i != in_index + 1; i++) - { - // get signed outputs and extra entries count from input's details (each input has to have it) - signed_parts so = AUTO_VAL_INIT(so); - bool r = get_type_in_variant_container(get_txin_etc_options(tx.vin[i]), so); - CHECK_AND_ASSERT_MES(r, null_hash, "Invalid input #" << i << " (of " << tx.vin.size() << ") contains no signed_parts"); - CHECK_AND_ASSERT_MES(signed_outputs_count <= so.n_outs, null_hash, "Invalid input #" << i << " (of " << tx.vin.size() << "): Next signed_outputs_count is less then prev"); - CHECK_AND_ASSERT_MES(signed_extras_count <= so.n_extras, null_hash, "Invalid input #" << i << " (of " << tx.vin.size() << "): Next signed_extras_count is less then prev"); - signed_outputs_count = so.n_outs; - signed_extras_count = so.n_extras; - - // get signed attachments count from input's extra_attachment_info (it's optional, if exists - override default) - if (get_type_in_variant_container(get_txin_etc_options(tx.vin[i]), eai)) - { - CHECK_AND_ASSERT_MES(signed_att_count <= eai.cnt, null_hash, "Invalid input #" << i << " (of " << tx.vin.size() << "): Next signed_att_count is less then prev"); - signed_att_count = static_cast(eai.cnt); - } - } - - if (in_index == tx.vin.size() - 1) - { - // for the last input make sure all outs, extra entries and attachments was counted correctly - CHECK_AND_ASSERT_MES(signed_outputs_count == tx.vout.size(), null_hash, "Separately signed complete tx has to mention all the outputs in its inputs: signed_outputs_count=" << signed_outputs_count << " tx.vout.size()=" << tx.vout.size()); - CHECK_AND_ASSERT_MES(signed_extras_count == tx.extra.size(), null_hash, "Separately signed complete tx has to mention all the extra entries in its inputs: signed_extras_count=" << signed_extras_count << " tx.extra.size()=" << tx.extra.size()); - CHECK_AND_ASSERT_MES(signed_att_count == tx.attachment.size(), null_hash, "Separately signed complete tx has to mention all the attachments in its inputs: signed_att_count=" << signed_att_count << " tx.attachment.size()=" << tx.attachment.size()); - // okay, there's nothing to crop - tx_hash_for_signature is tx prefix hash - } - else - { - // the given input isn't the last one - we have to crop some data in order to calculate correct hash for signing - transaction tx_local = tx; - - // crop all inputs past the given one - tx_local.vin.resize(static_cast(in_index) + 1); - - // crop outs - CHECK_AND_ASSERT_MES(signed_outputs_count <= tx_local.vout.size(), null_hash, "signed_outputs_count(" << signed_outputs_count << " ) more than tx_local.vout.size()" << tx_local.vout.size()); - tx_local.vout.resize(signed_outputs_count); - - // crop extra - CHECK_AND_ASSERT_MES(signed_extras_count <= tx_local.extra.size(), null_hash, "signed_extras_count(" << signed_extras_count << " ) more than tx_local.extra.size()" << tx_local.vout.size()); - tx_local.extra.resize(signed_extras_count); - - // crop attachments - CHECK_AND_ASSERT_MES(signed_att_count <= tx_local.attachment.size(), null_hash, "signed_att_count(" << signed_att_count << " ) more than tx_local.attachment.size()" << tx_local.attachment.size()); - tx_local.attachment.resize(signed_att_count); - - // calculate hash of cropped tx as the result - tx_hash_for_signature = get_transaction_hash(tx_local); - } - } - - return tx_hash_for_signature; - } - //------------------------------------------------------------------ - std::string dump_ring_sig_data(const crypto::hash& hash_for_sig, const crypto::key_image& k_image, const std::vector& output_keys_ptrs, const std::vector& sig) - { - std::stringstream s; - s << " hash for sig: " << hash_for_sig << ENDL - << " k_image: " << k_image << ENDL - << " out keys (" << output_keys_ptrs.size() << ")" << ENDL; - size_t i = 0; - for (auto& p_out_k : output_keys_ptrs) - s << " " << std::setw(2) << i++ << " " << *p_out_k << ENDL; - - s << " signatures (" << sig.size() << ")" << ENDL; - i = 0; - for (auto& sig_el : sig) - s << " " << std::setw(2) << i++ << " " << sig_el << ENDL; - - return s.str(); - } - - - //-------------------------------------------------------------------------------- - std::ostream& operator <<(std::ostream& o, const ref_by_id& r) - { - return o << "<" << r.n << ":" << r.tx_id << ">"; - } - //-------------------------------------------------------------------------------- -#ifndef ANDROID_BUILD - const std::locale& utf8_get_conversion_locale() - { - static std::locale loc = boost::locale::generator().generate("en_US.UTF-8"); - return loc; - } - std::string utf8_to_upper(const std::string& s) - { - return boost::locale::to_upper(s, utf8_get_conversion_locale()); - } - std::string utf8_to_lower(const std::string& s) - { - return boost::locale::to_lower(s, utf8_get_conversion_locale()); - } - bool utf8_substring_test_case_insensitive(const std::string& match, const std::string& s) - { - if (match.empty()) - return true; - return utf8_to_lower(s).find(utf8_to_lower(match), 0) != std::string::npos; - } -#endif - //-------------------------------------------------------------------------------- - bool operator ==(const currency::transaction& a, const currency::transaction& b) { - return currency::get_transaction_hash(a) == currency::get_transaction_hash(b); - } - - bool operator ==(const currency::block& a, const currency::block& b) { - return currency::get_block_hash(a) == currency::get_block_hash(b); - } - bool operator ==(const currency::extra_attachment_info& a, const currency::extra_attachment_info& b) - { - if (a.cnt == b.cnt && a.hsh == b.hsh && a.sz == b.sz) - return true; - else - return false; - } - - - boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point, - const wide_difficulty_type& difficulty_pow_at_split_point, - const difficulties& a_diff, - const difficulties& b_diff ) - { - static const wide_difficulty_type difficulty_starter = DIFFICULTY_STARTER; - const wide_difficulty_type& a_pos_cumulative_difficulty = a_diff.pos_diff > 0 ? a_diff.pos_diff : difficulty_starter; - const wide_difficulty_type& b_pos_cumulative_difficulty = b_diff.pos_diff > 0 ? b_diff.pos_diff : difficulty_starter; - const wide_difficulty_type& a_pow_cumulative_difficulty = a_diff.pow_diff > 0 ? a_diff.pow_diff : difficulty_starter; - const wide_difficulty_type& b_pow_cumulative_difficulty = b_diff.pow_diff > 0 ? b_diff.pow_diff : difficulty_starter; - - boost::multiprecision::uint1024_t basic_sum = boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty) + (boost::multiprecision::uint1024_t(a_pos_cumulative_difficulty)*difficulty_pow_at_split_point) / difficulty_pos_at_split_point; - boost::multiprecision::uint1024_t res = - (basic_sum * a_pow_cumulative_difficulty * a_pos_cumulative_difficulty) / (boost::multiprecision::uint1024_t(b_pow_cumulative_difficulty)*b_pos_cumulative_difficulty); - -// if (res > boost::math::tools::max_value()) -// { -// ASSERT_MES_AND_THROW("[INTERNAL ERROR]: Failed to get_a_to_b_relative_cumulative_difficulty, res = " << res << ENDL -// << ", difficulty_pos_at_split_point: " << difficulty_pos_at_split_point << ENDL -// << ", difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL -// << ", a_pos_cumulative_difficulty:" << a_pos_cumulative_difficulty << ENDL -// << ", b_pos_cumulative_difficulty:" << b_pos_cumulative_difficulty << ENDL -// << ", a_pow_cumulative_difficulty:" << a_pow_cumulative_difficulty << ENDL -// << ", b_pow_cumulative_difficulty:" << b_pow_cumulative_difficulty << ENDL -// ); -// } - TRY_ENTRY(); -// wide_difficulty_type short_res = res.convert_to(); - return res; - CATCH_ENTRY_WITH_FORWARDING_EXCEPTION(); - } - - - -} // namespace currency - - diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h deleted file mode 100644 index e9b7854..0000000 --- a/src/currency_core/currency_format_utils.h +++ /dev/null @@ -1,765 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include - -#include "account.h" -#include "include_base_utils.h" - -#include "print_fixed_point_helper.h" -#include "currency_format_utils_abstract.h" -#include "common/crypto_stream_operators.h" -#include "currency_protocol/currency_protocol_defs.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "difficulty.h" -#include "rpc/core_rpc_server_commands_defs.h" -#include "bc_payments_id_service.h" -#include "bc_attachments_helpers_basic.h" -#include "blockchain_storage_basic.h" -#include "currency_format_utils_blocks.h" -#include "currency_format_utils_transactions.h" -#include "core_runtime_config.h" -// #include "wallet/wallet_public_structs_defs.h" - - -// ------ get_tx_type_definition ------------- -#define GUI_TX_TYPE_NORMAL 0 -#define GUI_TX_TYPE_PUSH_OFFER 1 -#define GUI_TX_TYPE_UPDATE_OFFER 2 -#define GUI_TX_TYPE_CANCEL_OFFER 3 -#define GUI_TX_TYPE_NEW_ALIAS 4 -#define GUI_TX_TYPE_UPDATE_ALIAS 5 -#define GUI_TX_TYPE_COIN_BASE 6 -#define GUI_TX_TYPE_ESCROW_PROPOSAL 7 -#define GUI_TX_TYPE_ESCROW_TRANSFER 8 -#define GUI_TX_TYPE_ESCROW_RELEASE_NORMAL 9 -#define GUI_TX_TYPE_ESCROW_RELEASE_BURN 10 -#define GUI_TX_TYPE_ESCROW_CANCEL_PROPOSAL 11 -#define GUI_TX_TYPE_ESCROW_RELEASE_CANCEL 12 -#define GUI_TX_TYPE_HTLC_DEPOSIT 13 -#define GUI_TX_TYPE_HTLC_REDEEM 14 - - - - -namespace currency -{ - bool operator ==(const currency::transaction& a, const currency::transaction& b); - bool operator ==(const currency::block& a, const currency::block& b); - bool operator ==(const currency::extra_attachment_info& a, const currency::extra_attachment_info& b); - - - typedef boost::multiprecision::uint128_t uint128_tl; - - - struct tx_extra_info - { - crypto::public_key m_tx_pub_key; - //crypto::hash m_offers_hash; - extra_alias_entry m_alias; - std::string m_user_data_blob; - extra_attachment_info m_attachment_info; - }; - - //--------------------------------------------------------------------------------------------------------------- - struct genesis_payment_entry - { - std::string paid_prm; - std::string prm_usd_price; - std::string paid_xmr; - std::string xmr_usd_price; - std::string paid_qtum; - std::string qtum_usd_price; - std::string paid_bch; - std::string bch_usd_price; - std::string paid_rep; - std::string rep_usd_price; - std::string paid_dash; - std::string dash_usd_price; - std::string paid_ltc; - std::string ltc_usd_price; - std::string paid_eos; - std::string eos_usd_price; - std::string paid_eth; - std::string eth_usd_price; - std::string paid_btc; - std::string btc_usd_price; - std::string address_this; - double amount_this_coin_fl; - double amount_this_coin_int; - std::string this_usd_price; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(paid_prm) - KV_SERIALIZE(prm_usd_price) - KV_SERIALIZE(paid_xmr) - KV_SERIALIZE(xmr_usd_price) - KV_SERIALIZE(paid_qtum) - KV_SERIALIZE(qtum_usd_price) - KV_SERIALIZE(paid_bch) - KV_SERIALIZE(bch_usd_price) - KV_SERIALIZE(paid_rep) - KV_SERIALIZE(rep_usd_price) - KV_SERIALIZE(paid_dash) - KV_SERIALIZE(dash_usd_price) - KV_SERIALIZE(paid_ltc) - KV_SERIALIZE(ltc_usd_price) - KV_SERIALIZE(paid_eos) - KV_SERIALIZE(eos_usd_price) - KV_SERIALIZE(paid_eth) - KV_SERIALIZE(eth_usd_price) - KV_SERIALIZE(paid_btc) - KV_SERIALIZE(btc_usd_price) - KV_SERIALIZE(address_this) - KV_SERIALIZE_N(amount_this_coin_fl, "amount_this") - KV_SERIALIZE(this_usd_price) - END_KV_SERIALIZE_MAP() - }; - struct genesis_config_json_struct - { - std::list payments; - std::string proof_string; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(payments) - KV_SERIALIZE(proof_string) - END_KV_SERIALIZE_MAP() - }; - - struct htlc_info - { - bool hltc_our_out_is_before_expiration; - }; - - - struct finalize_tx_param - { - uint64_t unlock_time; - std::vector extra; - std::vector attachments; - currency::account_public_address crypt_address; - uint8_t tx_outs_attr; - bool shuffle; - uint8_t flags; - crypto::hash multisig_id; - std::vector sources; - std::vector selected_transfers; - std::vector prepared_destinations; - uint64_t expiration_time; - crypto::public_key spend_pub_key; // only for validations - - BEGIN_SERIALIZE_OBJECT() - FIELD(unlock_time) - FIELD(extra) - FIELD(attachments) - FIELD(crypt_address) - FIELD(tx_outs_attr) - FIELD(shuffle) - FIELD(flags) - FIELD(multisig_id) - FIELD(sources) - FIELD(selected_transfers) - FIELD(prepared_destinations) - FIELD(expiration_time) - FIELD(spend_pub_key) - END_SERIALIZE() - }; - - struct finalized_tx - { - currency::transaction tx; - crypto::secret_key one_time_key; - finalize_tx_param ftp; - std::string htlc_origin; - std::vector> outs_key_images; // pairs (out_index, key_image) for each change output - - BEGIN_SERIALIZE_OBJECT() - FIELD(tx) - FIELD(one_time_key) - FIELD(ftp) - FIELD(htlc_origin) - FIELD(outs_key_images) - END_SERIALIZE() - }; - - - //--------------------------------------------------------------- - bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, - size_t current_block_size, - uint64_t fee, - const account_public_address &miner_address, - const account_public_address &stakeholder_address, - transaction& tx, - const blobdata& extra_nonce = blobdata(), - size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS, - bool pos = false, - const pos_entry& pe = pos_entry()); - - bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, - size_t current_block_size, - uint64_t fee, - const std::vector& destinations, - transaction& tx, - const blobdata& extra_nonce = blobdata(), - size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS, - bool pos = false, - const pos_entry& pe = pos_entry()); - - - //--------------------------------------------------------------- - uint64_t get_string_uint64_hash(const std::string& str); - bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, finalized_tx& result, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED); - bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set& deriv_cache, const account_keys& self, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED); - bool validate_alias_name(const std::string& al); - bool validate_password(const std::string& password); - void get_attachment_extra_info_details(const std::vector& attachment, extra_attachment_info& eai); - bool construct_tx(const account_keys& sender_account_keys, - const std::vector& sources, - const std::vector& destinations, - const std::vector& attachments, - transaction& tx, - uint64_t unlock_time, - uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED, - bool shuffle = true); - bool construct_tx(const account_keys& sender_account_keys, - const std::vector& sources, - const std::vector& destinations, - const std::vector& extra, - const std::vector& attachments, - transaction& tx, - crypto::secret_key& one_time_secret_key, - uint64_t unlock_time, - uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED, - bool shuffle = true, - uint64_t flags = 0); - - bool construct_tx(const account_keys& sender_account_keys, - const std::vector& sources, - const std::vector& destinations, - const std::vector& extra, - const std::vector& attachments, - transaction& tx, - crypto::secret_key& one_time_secret_key, - uint64_t unlock_time, - const account_public_address& crypt_account, - uint64_t expiration_time, - uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED, - bool shuffle = true, - uint64_t flags = 0); - - bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result); - - - bool sign_multisig_input_in_tx(currency::transaction& tx, size_t ms_input_index, const currency::account_keys& keys, const currency::transaction& source_tx, bool *p_is_input_fully_signed = nullptr); - - bool sign_extra_alias_entry(extra_alias_entry& ai, const crypto::public_key& pkey, const crypto::secret_key& skey); - crypto::hash get_sign_buff_hash_for_alias_update(const extra_alias_entry& ai); - bool add_tx_extra_alias(transaction& tx, const extra_alias_entry& alinfo); - bool parse_and_validate_tx_extra(const transaction& tx, tx_extra_info& extra); - bool parse_and_validate_tx_extra(const transaction& tx, crypto::public_key& tx_pub_key); - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx); - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key); - bool add_tx_extra_userdata(transaction& tx, const blobdata& extra_nonce); - - crypto::hash get_multisig_out_id(const transaction& tx, size_t n); - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index); - bool is_out_to_acc(const account_keys& acc, const txout_multisig& out_multisig, const crypto::key_derivation& derivation, size_t output_index); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation, std::list& htlc_info_list); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered, crypto::key_derivation& derivation); - bool get_tx_fee(const transaction& tx, uint64_t & fee); - uint64_t get_tx_fee(const transaction& tx); - bool derive_ephemeral_key_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral); - bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki); - bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key, crypto::key_derivation& derivation); - bool derive_public_key_from_target_address(const account_public_address& destination_addr, const crypto::secret_key& tx_sec_key, size_t index, crypto::public_key& out_eph_public_key); - std::string short_hash_str(const crypto::hash& h); - bool is_mixattr_applicable_for_fake_outs_counter(uint8_t mix_attr, uint64_t fake_attr_count); - bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t current_blockchain_size, uint64_t current_time); - crypto::key_derivation get_encryption_key_derivation(bool is_income, const transaction& tx, const account_keys& acc_keys); - bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector& decrypted_items); - void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key); - bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation); - bool is_address_like_wrapped(const std::string& addr); - // void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x); - uint64_t get_tx_type(const transaction& tx); - uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in); - size_t get_multisig_out_index(const std::vector& outs); - size_t get_multisig_in_index(const std::vector& inputs); - - uint64_t get_reward_from_miner_tx(const transaction& tx); - - //bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size); - bool generate_genesis_block(block& bl); - const crypto::hash& get_genesis_hash(bool need_to_set = false, const crypto::hash& h = null_hash); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); - uint64_t get_inputs_money_amount(const transaction& tx); - bool get_inputs_money_amount(const transaction& tx, uint64_t& money); - uint64_t get_outs_money_amount(const transaction& tx); - bool check_inputs_types_supported(const transaction& tx); - bool check_outs_valid(const transaction& tx); - bool parse_amount(uint64_t& amount, const std::string& str_amount); - bool parse_tracking_seed(const std::string& tracking_seed, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp); - - - - bool unserialize_block_complete_entry(const COMMAND_RPC_GET_BLOCKS_FAST::response& serialized, - COMMAND_RPC_GET_BLOCKS_DIRECT::response& unserialized); - - - uint64_t get_alias_coast_from_fee(const std::string& alias, uint64_t fee_median); - //const crypto::public_key get_offer_secure_key_by_index_from_tx(const transaction& tx, size_t index); - - bool check_money_overflow(const transaction& tx); - bool check_outs_overflow(const transaction& tx); - bool check_inputs_overflow(const transaction& tx); - uint64_t get_block_height(const transaction& coinbase); - uint64_t get_block_height(const block& b); - std::vector relative_output_offsets_to_absolute(const std::vector& off); - std::vector absolute_output_offsets_to_relative(const std::vector& off); - - // prints amount in format "3.14", "0.0" - std::string print_money_brief(uint64_t amount); - uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime - uint64_t get_block_datetime(const block& b); - void set_block_datetime(uint64_t datetime, block& b); - - bool addendum_to_hexstr(const std::vector& add, std::string& hex_buff); - bool hexstr_to_addendum(const std::string& hex_buff, std::vector& add); - bool set_payment_id_to_tx(std::vector& att, const std::string& payment_id); - bool add_padding_to_tx(transaction& tx, size_t count); - bool is_service_tx(const transaction& tx); - bool does_tx_have_only_mixin_inputs(const transaction& tx); - bool is_showing_sender_addres(const transaction& tx); - uint64_t get_amount_for_zero_pubkeys(const transaction& tx); - //std::string get_comment_from_tx(const transaction& tx); - std::string print_stake_kernel_info(const stake_kernel& sk); - std::string dump_ring_sig_data(const crypto::hash& hash_for_sig, const crypto::key_image& k_image, const std::vector& output_keys_ptrs, const std::vector& sig); - - //PoS - bool is_pos_block(const block& b); - bool is_pos_block(const transaction& tx); - wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff); - void print_currency_details(); - std::string print_reward_change_first_blocks(size_t n_of_first_blocks); - bool get_aliases_reward_account(account_public_address& acc, crypto::secret_key& acc_view_key); - bool get_aliases_reward_account(account_public_address& acc); - alias_rpc_details alias_info_to_rpc_alias_info(const currency::extra_alias_entry& ai); - update_alias_rpc_details alias_info_to_rpc_update_alias_info(const currency::extra_alias_entry& ai, const std::string& old_address); - size_t get_service_attachments_count_in_tx(const transaction& tx); - bool fill_tx_rpc_outputs(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce); - bool fill_tx_rpc_inputs(tx_rpc_extended_info& tei, const transaction& tx); - bool fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short = false); - bool fill_block_rpc_details(block_rpc_extended_info& pei_rpc, const block_extended_info& bei_chain, const crypto::hash& h); - void append_per_block_increments_for_tx(const transaction& tx, std::unordered_map& gindices); - std::string get_word_from_timstamp(uint64_t timestamp, bool use_password); - uint64_t get_timstamp_from_word(std::string word, bool& password_used); - std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys); - template - typename std::conditional::value, const std::vector, std::vector >::type& get_txin_etc_options(t_txin_v& in) - { - static typename std::conditional::value, const std::vector, std::vector >::type stub; - - - //static stub; - - if (in.type() == typeid(txin_to_key)) - return boost::get(in).etc_details; - else if (in.type() == typeid(txin_htlc)) - return boost::get(in).etc_details; - else if (in.type() == typeid(txin_multisig)) - return boost::get(in).etc_details; - else - return stub; - } - - template - bool add_attachments_info_to_extra(t_extra_container& extra_container, const std::vector& attachments) - { - if (!attachments.empty()) - { - extra_attachment_info eai = AUTO_VAL_INIT(eai); - get_attachment_extra_info_details(attachments, eai); - extra_container.push_back(eai); - } - return true; - } - - - /************************************************************************/ - /* helper functions */ - /************************************************************************/ - size_t get_max_block_size(); - size_t get_max_tx_size(); - bool get_block_reward(bool is_pos, size_t median_size, size_t current_block_size, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t &reward, uint64_t height); - uint64_t get_base_block_reward(bool is_pos, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t height); - bool is_payment_id_size_ok(const payment_id_t& payment_id); - std::string get_account_address_as_str(const account_public_address& addr); - std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id); - bool get_account_address_from_str(account_public_address& addr, const std::string& str); - bool get_account_address_and_payment_id_from_str(account_public_address& addr, payment_id_t& payment_id, const std::string& str); - bool parse_payment_id_from_hex_str(const std::string& payment_id_str, payment_id_t& payment_id); - bool is_coinbase(const transaction& tx); - bool is_coinbase(const transaction& tx, bool& pos_coinbase); - bool have_attachment_service_in_container(const std::vector& av, const std::string& service_id, const std::string& instruction); - crypto::hash prepare_prefix_hash_for_sign(const transaction& tx, uint64_t in_index, const crypto::hash& tx_id); - - //--------------------------------------------------------------- - template - bool is_out_to_acc(const account_keys& acc, const tx_out_t& out_key, const crypto::public_key& tx_pub_key, size_t output_index) - { - crypto::key_derivation derivation; - generate_key_derivation(tx_pub_key, acc.view_secret_key, derivation); - return is_out_to_acc(acc, out_key, derivation, output_index); - } - //---------------------------------------------------------------------------------------------------- - template - bool validate_attachment_info(const t_container& container, const std::vector& attachments, bool allow_no_info_for_non_empty_attachments_container) - { - // this routine makes sure the container has correct and valid extra_attachment_info - extra_attachment_info eai = AUTO_VAL_INIT(eai); - bool r = get_type_in_variant_container(container, eai); - if (!r && allow_no_info_for_non_empty_attachments_container) - return true; - - // two valid options here: 1) no attachment info and empty attachements container; 2) attachment info present and the container is not empty - CHECK_AND_ASSERT_MES(r == !attachments.empty(), false, "Invalid attachment info: extra_attachment_info is " << (r ? "present" : "not present") << " while attachments size is " << attachments.size()); - - CHECK_AND_ASSERT_MES(eai.cnt <= attachments.size(), false, "Incorrect attachments counter: " << eai.cnt << " while attachments size is " << attachments.size()); - - extra_attachment_info eai_local = AUTO_VAL_INIT(eai_local); - if (eai.cnt == attachments.size()) - { - get_attachment_extra_info_details(attachments, eai_local); - } - else - { - std::vector attachments_local(attachments.begin(), attachments.begin() + static_cast(eai.cnt)); // make a local copy of eai.cnt attachments - get_attachment_extra_info_details(attachments_local, eai_local); - } - - // ...and compare with the one from the container - CHECK_AND_ASSERT_MES(eai == eai_local, false, "Invalid attachments info: (" << eai.cnt << "," << eai.hsh << "," << eai.sz << ") expected: (" << eai_local.cnt << "," << eai_local.hsh << "," << eai_local.sz << ")"); - - return true; - } - - //------------------------------------------------------------------ - template - bool alias_info_to_rpc_alias_info(const currency::extra_alias_entry& ai, alias_rpc_details_t& ari) - { - return alias_info_to_rpc_alias_info(ai.m_alias, ai, ari); - } - //--------------------------------------------------------------- - template - bool alias_info_to_rpc_alias_info(const std::string& alias, const currency::extra_alias_entry_base& aib, alias_rpc_details_t& ari) - { - ari.alias = alias; - ari.details.address = currency::get_account_address_as_str(aib.m_address); - ari.details.comment = aib.m_text_comment; - if (aib.m_view_key.size()) - ari.details.tracking_key = epee::string_tools::pod_to_hex(aib.m_view_key.back()); - - return true; - } - //--------------------------------------------------------------- - template - std::string print_fixed_decimal_point(t_number amount, size_t decimal_point) - { - return epee::string_tools::print_fixed_decimal_point(amount, decimal_point); - } - //--------------------------------------------------------------- - template - std::string print_money(t_number amount) - { - return print_fixed_decimal_point(amount, CURRENCY_DISPLAY_DECIMAL_POINT); - } - //--------------------------------------------------------------- - template - bool alias_rpc_details_to_alias_info(const alias_rpc_details_t& ard, currency::extra_alias_entry& ai) - { - if (!currency::get_account_address_from_str(ai.m_address, ard.details.address)) - { - LOG_ERROR("Failed to parse address: " << ard.details.address); - return false; - } - if (ard.details.tracking_key.size()) - { - if (!epee::string_tools::parse_tpod_from_hex_string(ard.details.tracking_key, ai.m_view_key)) - { - LOG_ERROR("Failed to parse tracking_key: " << ard.details.tracking_key); - return false; - } - } - //ai.m_sign; atm alias updating disabled - ai.m_text_comment = ard.details.comment; - ai.m_alias = ard.alias; - return true; - } - //--------------------------------------------------------------- - template - add_type_t& get_or_add_field_to_variant_vector(container_type& container) - { - for (auto& ev : container) - { - if (ev.type() == typeid(add_type_t)) - return boost::get(ev); - } - container.push_back(add_type_t()); - return boost::get(container.back()); - } - //--------------------------------------------------------------- - template - extra_t& get_or_add_field_to_extra(std::vector& extra) - { -// for (auto& ev : extra) -// { -// if (ev.type() == typeid(extra_t)) -// return boost::get(ev); -// } -// extra.push_back(extra_t()); -// return boost::get(extra.back()); - return get_or_add_field_to_variant_vector(extra); - } - //--------------------------------------------------------------- - template - void update_or_add_field_to_extra(std::vector& variant_container, const variant_type_t& v) - { - for (auto& ev : variant_container) - { - if (ev.type() == typeid(variant_type_t)) - { - boost::get(ev) = v; - return; - } - } - variant_container.push_back(v); - } - //--------------------------------------------------------------- - template - void remove_field_of_type_from_extra(std::vector& variant_container) - { - for (size_t i = 0; i != variant_container.size();) - { - if (variant_container[i].type() == typeid(variant_type_t)) - { - variant_container.erase(variant_container.begin()+i); - } - else - { - i++; - } - } - } - //--------------------------------------------------------------- - template - bool get_payment_id_from_tx(const t_container& att, std::string& payment_id) - { - tx_service_attachment sa = AUTO_VAL_INIT(sa); - if (bc_services::get_first_service_attachment_by_id(att, BC_PAYMENT_ID_SERVICE_ID, "", sa)) - { - payment_id = sa.body; - return true; - } - return false; - } - - //--------------------------------------------------------------- - // 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold - template - void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler, uint64_t max_output_allowed, size_t max_outs_count, size_t outs_count = 0) - { - CHECK_AND_ASSERT_MES(amount != 0, void(), "zero amount"); - CHECK_AND_ASSERT_MES(amount / max_output_allowed <= max_outs_count, void(), "too big amount: " << print_money(amount) << " for given max_output_allowed: " << print_money(max_output_allowed) << ", it would require >" << amount / max_output_allowed << " outputs"); - - bool is_dust_handled = false; - uint64_t dust = 0; - uint64_t multiplier = 1; - while (0 != amount ) - { - uint64_t chunk = (amount % 10) * multiplier; - if (chunk > max_output_allowed) - break; - amount /= 10; - multiplier *= 10; - - - - if (dust + chunk <= dust_threshold) - { - dust += chunk; - } - else - { - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - is_dust_handled = true; - } - if (0 != chunk) - { - chunk_handler(chunk); - ++outs_count; - } - } - } - if (amount) - { - //CHECK_AND_ASSERT_MES_NO_RET(max_output_allowed >= multiplier, "max_output_allowed > multiplier"); - CHECK_AND_ASSERT_MES(multiplier != 0, void(), "decompose_amount_into_digits: internal error: multiplier == 0"); - uint64_t amount_multiplied = amount * multiplier; - while (amount_multiplied >= max_output_allowed) - { - amount_multiplied -= max_output_allowed; - chunk_handler(max_output_allowed); - ++outs_count; - CHECK_AND_ASSERT_MES(outs_count < max_outs_count || amount_multiplied == 0, void(), "decompose_amount_into_digits: too many outputs"); - } - - if (amount_multiplied != 0) - decompose_amount_into_digits(amount_multiplied, dust_threshold, chunk_handler, dust_handler, max_output_allowed, max_outs_count, outs_count); - } - - - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - } - } - - template - void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler) - { - decompose_amount_into_digits(amount, dust_threshold, chunk_handler, dust_handler, WALLET_MAX_ALLOWED_OUTPUT_AMOUNT, CURRENCY_TX_MAX_ALLOWED_OUTS, 0); - } - - template - void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler, uint64_t max_output_allowed) - { - decompose_amount_into_digits(amount, dust_threshold, chunk_handler, dust_handler, max_output_allowed, CURRENCY_TX_MAX_ALLOWED_OUTS, 0); - } - //--------------------------------------------------------------- - inline size_t get_input_expected_signatures_count(const txin_v& tx_in) - { - struct txin_signature_size_visitor : public boost::static_visitor - { - size_t operator()(const txin_gen& /*txin*/) const { return 0; } - size_t operator()(const txin_to_key& txin) const { return txin.key_offsets.size(); } - size_t operator()(const txin_multisig& txin) const { return txin.sigs_count; } - size_t operator()(const txin_htlc& txin) const { return 1; } - }; - - return boost::apply_visitor(txin_signature_size_visitor(), tx_in); - } - //--------------------------------------------------------------- - inline const std::vector* get_input_etc_details(const txin_v& in) - { - if (in.type().hash_code() == typeid(txin_to_key).hash_code()) - return &boost::get(in).etc_details; - if (in.type().hash_code() == typeid(txin_htlc).hash_code()) - return &boost::get(in).etc_details; - if (in.type().hash_code() == typeid(txin_multisig).hash_code()) - return &boost::get(in).etc_details; - return nullptr; - } - //--------------------------------------------------------------- - inline std::vector* get_input_etc_details(txin_v& in) - { - if (in.type().hash_code() == typeid(txin_to_key).hash_code()) - return &boost::get(in).etc_details; - if (in.type().hash_code() == typeid(txin_htlc).hash_code()) - return &boost::get(in).etc_details; - if (in.type().hash_code() == typeid(txin_multisig).hash_code()) - return &boost::get(in).etc_details; - return nullptr; - } - //--------------------------------------------------------------- - - struct input_amount_getter : public boost::static_visitor - { - template - uint64_t operator()(const t_input& i) const{return i.amount;} - uint64_t operator()(const txin_gen& i) const {return 0;} - }; - - inline uint64_t get_amount_from_variant(const txin_v& v) - { - return boost::apply_visitor(input_amount_getter(), v); - } - //--------------------------------------------------------------- - template - void create_and_add_tx_payer_to_container_from_address(container_t& container, const account_public_address& addr, uint64_t top_block_height, const core_runtime_config& crc) - { - if (top_block_height > crc.hard_fork_02_starts_after_height) - { - // after hardfork 2 - tx_payer result = AUTO_VAL_INIT(result); - result.acc_addr = addr; - container.push_back(result); - } - else - { - // before hardfork 2 -- add only if addr is not auditable - if (!addr.is_auditable()) - { - tx_payer_old result = AUTO_VAL_INIT(result); - result.acc_addr = addr.to_old(); - container.push_back(result); - } - } - } - //--------------------------------------------------------------- - template - void create_and_add_tx_receiver_to_container_from_address(container_t& container, const account_public_address& addr, uint64_t top_block_height, const core_runtime_config& crc) - { - if (top_block_height > crc.hard_fork_02_starts_after_height) - { - // after hardfork 2 - tx_receiver result = AUTO_VAL_INIT(result); - result.acc_addr = addr; - container.push_back(result); - } - else - { - // before hardfork 2 -- add only if addr is not auditable - if (!addr.is_auditable()) - { - tx_receiver_old result = AUTO_VAL_INIT(result); - result.acc_addr = addr.to_old(); - container.push_back(result); - } - } - } - //--------------------------------------------------------------- - //--------------------------------------------------------------- - std::ostream& operator <<(std::ostream& o, const ref_by_id& r); - //--------------------------------------------------------------- -#ifndef ANDROID_BUILD - std::string utf8_to_upper(const std::string& s); - std::string utf8_to_lower(const std::string& s); - bool utf8_substring_test_case_insensitive(const std::string& match, const std::string& s); // Returns true is 's' contains 'match' (case-insensitive) -#endif - - struct difficulties - { - wide_difficulty_type pos_diff; - wide_difficulty_type pow_diff; - }; - - boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point, - const wide_difficulty_type& difficulty_pow_at_split_point, - const difficulties& a_diff, - const difficulties& b_diff - ); - - -} // namespace currency diff --git a/src/currency_core/currency_format_utils_abstract.h b/src/currency_core/currency_format_utils_abstract.h deleted file mode 100644 index 451b46e..0000000 --- a/src/currency_core/currency_format_utils_abstract.h +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include - - -#include "include_base_utils.h" -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "currency_core/currency_basic.h" -#include "currency_protocol/blobdatatype.h" -#include "common/crypto_stream_operators.h" - -namespace currency -{ - - template - std::string print_kv_structure(const type_t& v) - { - return epee::serialization::store_t_to_json(v); - } - - template - std::string print_t_array(const std::vector& vec) - { - std::stringstream ss; - for (auto& v : vec) - ss << v << " "; - return ss.str(); - } - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct array_hasher : std::unary_function - { - std::size_t operator()(const t_array& val) const - { - return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]); - } - }; - - //------------------------------------------------------------------------------------ - template - result_type get_pod_checksum(const t_pod_type& bl) - { - const unsigned char* pbuf = reinterpret_cast(&bl); - result_type summ = 0; - for (size_t i = 0; i != sizeof(t_pod_type)-1; i++) - summ += pbuf[i]; - - return summ; - } - - template - bool parse_and_validate_object_from_blob(const blobdata& b_blob, object_t& b) - { - return t_unserializable_object_from_blob(b, b_blob); - } - //--------------------------------------------------------------- - template - bool have_type_in_variant_container(const variant_t_container& av) - { - for (auto& ai : av) - { - if (ai.type() == typeid(specific_type_t)) - { - return true; - } - } - return false; - } - //--------------------------------------------------------------- - template - size_t count_type_in_variant_container(const variant_t_container& av) - { - size_t result = 0; - for (auto& ai : av) - { - if (ai.type() == typeid(specific_type_t)) - ++result; - } - return result; - } - //--------------------------------------------------------------- - template - bool get_type_in_variant_container(const variant_t_container& av, specific_type_t& a) - { - for (auto& ai : av) - { - if (ai.type() == typeid(specific_type_t)) - { - a = boost::get(ai); - return true; - } - } - return false; - } - //--------------------------------------------------------------- - // callback should return true to continue iterating through the container - template - bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb) - { - bool found = false; - for (auto& item : container) - { - if (item.type() == typeid(A)) - { - found = true; - if (!cb(boost::get
(item))) - break; - } - else if (item.type() == typeid(B)) - { - found = true; - if (!cb(boost::get(item))) - break; - } - } - return found; - } - inline - const txin_to_key& get_to_key_input_from_txin_v(const txin_v& in_v) - { - if (in_v.type() == typeid(txin_to_key)) - { - return boost::get(in_v); - } - else if (in_v.type() == typeid(txin_htlc)) - { - const txin_htlc& in = boost::get(in_v); - return static_cast(in); - } - else { - ASSERT_MES_AND_THROW("[get_to_key_input_from_txin_v] Wrong type " << in_v.type().name()); - } - } - //--------------------------------------------------------------- - template - bool check_allowed_types_in_variant_container(const variant_container_t& container, const std::unordered_set& allowed_types, bool elements_must_be_unique = true) - { - for (auto it = container.begin(); it != container.end(); ++it) - { - if (allowed_types.count(std::type_index(it->type())) == 0) - return false; - - if (elements_must_be_unique) - { - for (auto jt = it + 1; jt != container.end(); ++jt) - if (it->type().hash_code() == jt->type().hash_code()) - return false; - } - } - return true; - } - //--------------------------------------------------------------- - template - bool check_allowed_types_in_variant_container(const variant_container_t& container, const variant_container_t& allowed_types_examples, bool elements_must_be_unique = true) - { - std::unordered_set allowed_types; - for (auto& el : allowed_types_examples) - if (!allowed_types.insert(std::type_index(el.type())).second) - return false; // invalid allowed_types_examples container - - return check_allowed_types_in_variant_container(container, allowed_types, elements_must_be_unique); - } - //--------------------------------------------------------------- - template - std::string stringize_types_in_variant_container(const variant_container_t& container) - { - std::string result; - for (auto it = container.begin(); it != container.end(); ++it) - result = (result + it->type().name()) + (it + 1 != container.end() ? ", " : ""); - return result; - } - //--------------------------------------------------------------- - inline - void get_blob_hash(const blobdata& blob, crypto::hash& res) - { - cn_fast_hash(blob.data(), blob.size(), res); - } - //--------------------------------------------------------------- - inline - crypto::hash get_blob_hash(const blobdata& blob) - { - crypto::hash h = null_hash; - get_blob_hash(blob, h); - return h; - } - - template - bool get_object_hash(const t_object& o, crypto::hash& res) - { - get_blob_hash(t_serializable_object_to_blob(o), res); - return true; - } - //--------------------------------------------------------------- - template - crypto::hash get_object_hash(const t_object& o) - { - crypto::hash h; - get_object_hash(o, h); - return h; - } - //--------------------------------------------------------------- - - template - size_t get_object_blobsize(const t_object& o) - { - blobdata b = t_serializable_object_to_blob(o); - return b.size(); - } - //--------------------------------------------------------------- - template - bool get_object_hash(const t_object& o, crypto::hash& res, uint64_t& blob_size) - { - blobdata bl = t_serializable_object_to_blob(o); - blob_size = bl.size(); - get_blob_hash(bl, res); - return true; - } - //--------------------------------------------------------------- - template - std::string obj_to_json_str(const T& obj) - { - std::stringstream ss; - json_archive ar(ss, true); - bool r = ::serialization::serialize(ar, const_cast(obj)); - CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); - return ss.str(); - } - //--------------------------------------------------------------- - - //--------------------------------------------------------------- - size_t get_object_blobsize(const transaction& t); - size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size); - - - -#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ - CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ - specific_type& variable_name = boost::get(variant_var); - -} // namespace currency - - - diff --git a/src/currency_core/currency_format_utils_blocks.cpp b/src/currency_core/currency_format_utils_blocks.cpp deleted file mode 100644 index 30d7f26..0000000 --- a/src/currency_core/currency_format_utils_blocks.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - - -#include "currency_format_utils_blocks.h" -#include "serialization/serialization.h" -#include "currency_format_utils.h" -#include "currency_format_utils_abstract.h" -#include "currency_format_utils_transactions.h" -namespace currency -{ - //--------------------------------------------------------------- - blobdata get_block_hashing_blob(const block& b) - { - blobdata blob = t_serializable_object_to_blob(static_cast(b)); - crypto::hash tree_root_hash = get_tx_tree_hash(b); - blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash)); - blob.append(tools::get_varint_data(b.tx_hashes.size() + 1)); - return blob; - } - //--------------------------------------------------------------- - bool get_block_hash(const block& b, crypto::hash& res) - { - return get_object_hash(get_block_hashing_blob(b), res); - } - //--------------------------------------------------------------- - crypto::hash get_block_hash(const block& b) - { - crypto::hash p = null_hash; - get_block_hash(b, p); - return p; - } - //--------------------------------------------------------------- - blobdata block_to_blob(const block& b) - { - return t_serializable_object_to_blob(b); - } - //--------------------------------------------------------------- - bool block_to_blob(const block& b, blobdata& b_blob) - { - return t_serializable_object_to_blob(b, b_blob); - } - //--------------------------------------------------------------- - void get_tx_tree_hash(const std::vector& tx_hashes, crypto::hash& h) - { - tree_hash(tx_hashes.data(), tx_hashes.size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const std::vector& tx_hashes) - { - crypto::hash h = null_hash; - get_tx_tree_hash(tx_hashes, h); - return h; - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const block& b) - { - std::vector txs_ids; - crypto::hash h = null_hash; - get_transaction_hash(b.miner_tx, h); - txs_ids.push_back(h); - BOOST_FOREACH(auto& th, b.tx_hashes) - txs_ids.push_back(th); - return get_tx_tree_hash(txs_ids); - } -} diff --git a/src/currency_core/currency_format_utils_blocks.h b/src/currency_core/currency_format_utils_blocks.h deleted file mode 100644 index e1a3eb4..0000000 --- a/src/currency_core/currency_format_utils_blocks.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#include "include_base_utils.h" -#include "crypto/crypto.h" -#include "currency_core/currency_basic.h" -#include "currency_protocol/blobdatatype.h" - -namespace currency -{ - blobdata get_block_hashing_blob(const block& b); - bool get_block_hash(const block& b, crypto::hash& res); - crypto::hash get_block_hash(const block& b); - - blobdata block_to_blob(const block& b); - bool block_to_blob(const block& b, blobdata& b_blob); - void get_tx_tree_hash(const std::vector& tx_hashes, crypto::hash& h); - crypto::hash get_tx_tree_hash(const std::vector& tx_hashes); - crypto::hash get_tx_tree_hash(const block& b); - -} diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp deleted file mode 100644 index 264f604..0000000 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - - -#include "currency_format_utils_transactions.h" -#include "serialization/serialization.h" -#include "currency_format_utils.h" -#include "currency_format_utils_abstract.h" - -namespace currency -{ - //--------------------------------------------------------------- - account_public_address get_crypt_address_from_destinations(const account_keys& sender_account_keys, const std::vector& destinations) - { - for (const auto& de : destinations) - { - if (de.addr.size() == 1 && sender_account_keys.account_address != de.addr.back()) - return de.addr.back(); // return the first destination address that is non-multisig and not equal to the sender's address - } - return sender_account_keys.account_address; // otherwise, fallback to sender's address - } - //------------------------------------------------------------------ - bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median) - { - /// tx expiration condition (tx is ok if the following is true) - /// tx_expiration_time - TX_EXPIRATION_MEDIAN_SHIFT > get_last_n_blocks_timestamps_median(TX_EXPIRATION_TIMESTAMP_CHECK_WINDOW) - uint64_t expiration_time = get_tx_expiration_time(tx); - if (expiration_time == 0) - return false; // 0 means it never expires - return expiration_time <= expiration_ts_median + TX_EXPIRATION_MEDIAN_SHIFT; - } - //--------------------------------------------------------------- - uint64_t get_burned_amount(const transaction& tx) - { - uint64_t res = 0; - for (auto& o : tx.vout) - { - if (o.target.type() == typeid(txout_to_key)) - { - if (boost::get(o.target).key == null_pkey) - res += o.amount; - } - } - return res; - } - //--------------------------------------------------------------- - uint64_t get_tx_max_unlock_time(const transaction& tx) - { - // etc_tx_details_unlock_time have priority over etc_tx_details_unlock_time2 - uint64_t v = get_tx_x_detail(tx); - if (v) - return v; - - etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2); - get_type_in_variant_container(tx.extra, ut2); - if (!ut2.unlock_time_array.size()) - return 0; - - uint64_t max_unlock_time = 0; - CHECK_AND_ASSERT_THROW_MES(ut2.unlock_time_array.size() == tx.vout.size(), "unlock_time_array.size=" << ut2.unlock_time_array.size() - << " is not the same as tx.vout.size =" << tx.vout.size() << " in tx: " << get_transaction_hash(tx)); - for (size_t i = 0; i != tx.vout.size(); i++) - { - if (ut2.unlock_time_array[i] > max_unlock_time) - max_unlock_time = ut2.unlock_time_array[i]; - } - - return max_unlock_time; - } - - //--------------------------------------------------------------- - uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i) - { - // etc_tx_details_expiration_time have priority over etc_tx_details_expiration_time2 - uint64_t v = get_tx_x_detail(tx); - if (v) - return v; - - CHECK_AND_ASSERT_THROW_MES(tx.vout.size() > o_i, "tx.vout.size=" << tx.vout.size() - << " is not bigger then o_i=" << o_i << " in tx: " << get_transaction_hash(tx)); - - - etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2); - get_type_in_variant_container(tx.extra, ut2); - if (!ut2.unlock_time_array.size()) - return 0; - - CHECK_AND_ASSERT_THROW_MES(ut2.unlock_time_array.size() > o_i, "unlock_time_array.size=" << ut2.unlock_time_array.size() - << " is less or equal to o_i=" << o_i << " in tx: " << get_transaction_hash(tx)); - - return ut2.unlock_time_array[o_i]; - } - //--------------------------------------------------------------- - bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time) - { - max_unlock_time = min_unlock_time = 0; - // etc_tx_details_expiration_time have priority over etc_tx_details_expiration_time2 - uint64_t v = get_tx_x_detail(tx); - if (v) - { - max_unlock_time = min_unlock_time = v; - return true; - } - - etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2); - get_type_in_variant_container(tx.extra, ut2); - if (!ut2.unlock_time_array.size()) - { - return true; - } - CHECK_AND_ASSERT_THROW_MES(ut2.unlock_time_array.size() == tx.vout.size(), "unlock_time_array.size=" << ut2.unlock_time_array.size() - << " is not equal tx.vout.size()=" << tx.vout.size() << " in tx: " << get_transaction_hash(tx)); - if (ut2.unlock_time_array.size()) - { - max_unlock_time = min_unlock_time = ut2.unlock_time_array[0]; - for (size_t i = 1; i != ut2.unlock_time_array.size(); i++) - { - if (ut2.unlock_time_array[i] > max_unlock_time) - max_unlock_time = ut2.unlock_time_array[i]; - if (ut2.unlock_time_array[i] < min_unlock_time) - min_unlock_time = ut2.unlock_time_array[i]; - } - } - - - return true; - } - //--------------------------------------------------------------- - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h) - { - std::ostringstream s; - binary_archive a(s); - ::serialization::serialize(a, const_cast(tx)); - std::string data = s.str(); - crypto::cn_fast_hash(data.data(), data.size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx) - { - crypto::hash h = null_hash; - get_transaction_prefix_hash(tx, h); - return h; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx) - { - std::stringstream ss; - ss << tx_blob; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - return true; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash) - { - std::stringstream ss; - ss << tx_blob; - binary_archive ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - //TODO: validate tx - - //crypto::cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash); - get_transaction_prefix_hash(tx, tx_hash); - return true; - } - //--------------------------------------------------------------- - crypto::hash get_transaction_hash(const transaction& t) - { - return get_transaction_prefix_hash(t); - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res) - { - uint64_t blob_size = 0; - return get_object_hash(static_cast(t), res, blob_size); - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size) - { - blob_size = 0; - bool r = get_object_hash(static_cast(t), res, blob_size); - blob_size = get_object_blobsize(t, blob_size); - return r; - } - //--------------------------------------------------------------- - size_t get_object_blobsize(const transaction& t) - { - size_t tx_blob_size = get_object_blobsize(static_cast(t)); - return get_object_blobsize(t, tx_blob_size); - } - //--------------------------------------------------------------- - size_t get_objects_blobsize(const std::list& ls) - { - size_t total = 0; - for (const auto& tx : ls) - { - total += get_object_blobsize(tx); - } - return total; - } - //--------------------------------------------------------------- - size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size) - { - size_t tx_blob_size = prefix_blob_size; - - if (is_coinbase(t)) - return tx_blob_size; - - // for purged tx, with empty signatures and attachments, this function should return the blob size - // which the tx would have if the signatures and attachments were correctly filled with actual data - - // 1. signatures - bool separately_signed_tx = get_tx_flags(t) & TX_FLAG_SIGNATURE_MODE_SEPARATE; - - tx_blob_size += tools::get_varint_packed_size(t.vin.size()); // size of transaction::signatures (equals to total inputs count) - - for (size_t i = 0; i != t.vin.size(); i++) - { - size_t sig_count = get_input_expected_signatures_count(t.vin[i]); - if (separately_signed_tx && i == t.vin.size() - 1) - ++sig_count; // count in one more signature for the last input in a complete separately signed tx - tx_blob_size += tools::get_varint_packed_size(sig_count); // size of transaction::signatures[i] - tx_blob_size += sizeof(crypto::signature) * sig_count; // size of signatures' data itself - } - - // 2. attachments (try to find extra_attachment_info in tx prefix and count it in if succeed) - extra_attachment_info eai = AUTO_VAL_INIT(eai); - bool got_eai = false; - if (separately_signed_tx) - { - // for separately-signed tx, try to obtain extra_attachment_info from the last input's etc_details - const std::vector* p_etc_details = get_input_etc_details(t.vin.back()); - got_eai = p_etc_details != nullptr && get_type_in_variant_container(*p_etc_details, eai); - } - if (!got_eai) - got_eai = get_type_in_variant_container(t.extra, eai); // then from the extra - - if (got_eai) - tx_blob_size += eai.sz; // sz is a size of whole serialized attachment blob, including attachments vector size - else - tx_blob_size += tools::get_varint_packed_size(static_cast(0)); // no extra_attachment_info found - just add zero vector's size, 'cause it's serialized anyway - - return tx_blob_size; - } - //--------------------------------------------------------------- - blobdata tx_to_blob(const transaction& tx) - { - return t_serializable_object_to_blob(tx); - } - //--------------------------------------------------------------- - bool tx_to_blob(const transaction& tx, blobdata& b_blob) - { - return t_serializable_object_to_blob(tx, b_blob); - } - //--------------------------------------------------------------- - bool read_keyimages_from_tx(const transaction& tx, std::list& kil) - { - std::unordered_set ki; - BOOST_FOREACH(const auto& in, tx.vin) - { - if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc)) - { - - if (!ki.insert(get_to_key_input_from_txin_v(in).k_image).second) - return false; - } - } - return true; - } - -} \ No newline at end of file diff --git a/src/currency_core/currency_format_utils_transactions.h b/src/currency_core/currency_format_utils_transactions.h deleted file mode 100644 index 337d40d..0000000 --- a/src/currency_core/currency_format_utils_transactions.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#include "include_base_utils.h" -#include "crypto/crypto.h" -#include "currency_core/currency_basic.h" -#include "currency_protocol/blobdatatype.h" -#include "currency_core/account.h" - - -namespace currency -{ - struct tx_source_entry - { - typedef serializable_pair output_entry; // txout_v is either global output index or ref_by_id; public_key - is output ephemeral pub key - - std::vector outputs; //index + key - uint64_t real_output; //index in outputs vector of real output_entry - crypto::public_key real_out_tx_key; //real output's transaction's public key - size_t real_output_in_tx_index; //index in transaction outputs vector - uint64_t amount; //money - uint64_t transfer_index; //money - crypto::hash multisig_id; //if txin_multisig: multisig output id - size_t ms_sigs_count; //if txin_multisig: must be equal to output's minimum_sigs - size_t ms_keys_count; //if txin_multisig: must be equal to size of output's keys container - bool separately_signed_tx_complete; //for separately signed tx only: denotes the last source entry in complete tx to explicitly mark the final step of tx creation - std::string htlc_origin; //for htlc, specify origin - - bool is_multisig() const { return ms_sigs_count > 0; } - - BEGIN_SERIALIZE_OBJECT() - FIELD(outputs) - FIELD(real_output) - FIELD(real_out_tx_key) - FIELD(real_output_in_tx_index) - FIELD(amount) - FIELD(transfer_index) - FIELD(multisig_id) - FIELD(ms_sigs_count) - FIELD(ms_keys_count) - FIELD(separately_signed_tx_complete) - FIELD(htlc_origin) - END_SERIALIZE() - }; - - - //if this struct is present, then creating htlc out, expiration -> number of blocks that htlc proposal is active - struct destination_option_htlc_out - { - uint64_t expiration; - crypto::hash htlc_hash; - - BEGIN_SERIALIZE_OBJECT() - FIELD(expiration) - FIELD(htlc_hash) - END_SERIALIZE() - }; - - - struct tx_destination_entry - { - uint64_t amount; //money - std::list addr; //destination address, in case of 1 address - txout_to_key, in case of more - txout_multisig - size_t minimum_sigs; //if txout_multisig: minimum signatures that are required to spend this output (minimum_sigs <= addr.size()) IF txout_to_key - not used - uint64_t amount_to_provide; //amount money that provided by initial creator of tx, used with partially created transactions - uint64_t unlock_time; - destination_option_htlc_out htlc_options; //htlc options - - - tx_destination_entry() : amount(0), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()){} - tx_destination_entry(uint64_t a, const account_public_address& ad) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()) {} - tx_destination_entry(uint64_t a, const account_public_address& ad, uint64_t ut) : amount(a), addr(1, ad), minimum_sigs(0), amount_to_provide(0), unlock_time(ut), htlc_options(destination_option_htlc_out()) {} - tx_destination_entry(uint64_t a, const std::list& addr) : amount(a), addr(addr), minimum_sigs(addr.size()), amount_to_provide(0), unlock_time(0), htlc_options(destination_option_htlc_out()) {} - - BEGIN_SERIALIZE_OBJECT() - FIELD(amount) - FIELD(addr) - FIELD(minimum_sigs) - FIELD(amount_to_provide) - FIELD(unlock_time) - FIELD(htlc_options) - END_SERIALIZE() - }; - - template - uint64_t get_tx_x_detail(const transaction& tx) - { - extra_type_t e = AUTO_VAL_INIT(e); - get_type_in_variant_container(tx.extra, e); - return e.v; - } - template - void set_tx_x_detail(transaction& tx, uint64_t v) - { - extra_type_t e = AUTO_VAL_INIT(e); - e.v = v; - update_or_add_field_to_extra(tx.extra, e); - } - - uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i); - uint64_t get_tx_max_unlock_time(const transaction& tx); - bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time); - inline bool should_unlock_value_be_treated_as_block_height(uint64_t v) { return v < CURRENCY_MAX_BLOCK_NUMBER; } - inline uint64_t get_tx_flags(const transaction& tx) { return get_tx_x_detail(tx); } - inline uint64_t get_tx_expiration_time(const transaction& tx) {return get_tx_x_detail(tx); } - inline void set_tx_unlock_time(transaction& tx, uint64_t v) { set_tx_x_detail(tx, v); } - inline void set_tx_flags(transaction& tx, uint64_t v) { set_tx_x_detail(tx, v); } - inline void set_tx_expiration_time(transaction& tx, uint64_t v) { set_tx_x_detail(tx, v); } - account_public_address get_crypt_address_from_destinations(const account_keys& sender_account_keys, const std::vector& destinations); - //----------------------------------------------------------------------------------------------- - - bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median); - uint64_t get_burned_amount(const transaction& tx); - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); - crypto::hash get_transaction_hash(const transaction& t); - bool get_transaction_hash(const transaction& t, crypto::hash& res); - bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size); - size_t get_object_blobsize(const transaction& t); - size_t get_objects_blobsize(const std::list& ls); - size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size); - blobdata tx_to_blob(const transaction& b); - bool tx_to_blob(const transaction& b, blobdata& b_blob); - bool read_keyimages_from_tx(const transaction& tx, std::list& kil); - - -} diff --git a/src/currency_core/currency_stat_info.h b/src/currency_core/currency_stat_info.h deleted file mode 100644 index 2c490a2..0000000 --- a/src/currency_core/currency_stat_info.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "serialization/keyvalue_serialization.h" - - -namespace currency -{ - - struct chain_entry - { - uint64_t h; - std::string id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(h) - KV_SERIALIZE(id) - END_KV_SERIALIZE_MAP() - }; - - - struct error_stat_entry - { - std::string channel; - uint64_t err_count; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(channel) - KV_SERIALIZE(err_count) - END_KV_SERIALIZE_MAP() - }; - - struct core_stat_info - { - struct params - { - uint64_t chain_len; - uint64_t logs_journal_len; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(chain_len) - KV_SERIALIZE(logs_journal_len) - END_KV_SERIALIZE_MAP() - }; - - uint64_t tx_pool_size; - uint64_t blockchain_height; - uint64_t mining_speed; - uint64_t alternative_blocks; - bool epic_failure_happend; - std::string top_block_id_str; - std::list main_chain_blocks; - std::list alt_chain_blocks; - std::list errors_stat; - std::list errors_journal; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(blockchain_height) - KV_SERIALIZE(mining_speed) - KV_SERIALIZE(alternative_blocks) - KV_SERIALIZE(main_chain_blocks) - KV_SERIALIZE(top_block_id_str) - //KV_SERIALIZE(alt_chain_blocks) - KV_SERIALIZE(errors_stat) - KV_SERIALIZE(epic_failure_happend) - KV_SERIALIZE(errors_journal) - END_KV_SERIALIZE_MAP() - }; -} diff --git a/src/currency_core/difficulty.cpp b/src/currency_core/difficulty.cpp deleted file mode 100644 index 68d82c1..0000000 --- a/src/currency_core/difficulty.cpp +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include -#include - -#include "misc_log_ex.h" - -#include "common/int-util.h" -#include "crypto/hash.h" -#include "currency_core/currency_config.h" -#include "difficulty.h" -#include "profile_tools.h" - -namespace currency { - - using std::size_t; - using std::uint64_t; - using std::vector; - -//#if defined(_MSC_VER) -//#include -//#include - - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - boost::multiprecision::uint128_t res = boost::multiprecision::uint128_t(a) * b; - low = (res & 0xffffffffffffffffLL).convert_to(); - high = (res >> 64).convert_to(); - //low = _umul128(a, b, &high); - //low = UnsignedMultiply128(a, b, &high); - } - -/* #else - - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - typedef unsigned __int128 uint128_t; - uint128_t res = (uint128_t)a * (uint128_t)b; - low = (uint64_t)res; - high = (uint64_t)(res >> 64); - } - -#endif */ - - static inline bool cadd(uint64_t a, uint64_t b) { - return a + b < a; - } - - static inline bool cadc(uint64_t a, uint64_t b, bool c) { - return a + b < a || (c && a + b == (uint64_t)-1); - } - - -#if defined(_MSC_VER) -#ifdef max -#undef max -#endif -#endif - - const wide_difficulty_type max64bit(std::numeric_limits::max()); - const boost::multiprecision::uint256_t max128bit(std::numeric_limits::max()); - const boost::multiprecision::uint512_t max256bit(std::numeric_limits::max()); - - bool check_hash(const crypto::hash &hash_, wide_difficulty_type difficulty) - { - //revert byte order - crypto::hash h = {}; - for (size_t i = 0; i != sizeof(h); i++) - { - *(((char*)&h) + (sizeof(h) - (i + 1))) = *(((char*)&hash_) + i); - } - - PROFILE_FUNC("check_hash"); - if (difficulty < max64bit) - { // if can convert to small difficulty - do it - std::uint64_t dl = difficulty.convert_to(); - uint64_t low, high, top, cur; - // First check the highest word, this will most likely fail for a random hash. - mul(swap64le(((const uint64_t *)&h)[3]), dl, top, high); - if (high != 0) - return false; - mul(swap64le(((const uint64_t *)&h)[0]), dl, low, cur); - mul(swap64le(((const uint64_t *)&h)[1]), dl, low, high); - bool carry = cadd(cur, low); - cur = high; - mul(swap64le(((const uint64_t *)&h)[2]), dl, low, high); - carry = cadc(cur, low, carry); - carry = cadc(high, top, carry); - return !carry; - } - // fast check - if (((const uint64_t *)&h)[3] > 0) - return false; - // usual slow check - boost::multiprecision::uint512_t hashVal = 0; - for(int i = 0; i < 4; i++) - { - hashVal <<= 64; - hashVal |= swap64le(((const uint64_t *) &h)[3-i]); - } - return (hashVal * difficulty <= max256bit); - } - - uint64_t difficulty_to_boundary(wide_difficulty_type difficulty) - { - boost::multiprecision::uint256_t nominal_hash = std::numeric_limits::max(); - nominal_hash = nominal_hash / difficulty; - uint64_t res = (nominal_hash >> 192).convert_to(); - return res; - } - - void difficulty_to_boundary_long(wide_difficulty_type difficulty, crypto::hash& result) - { - boost::multiprecision::uint256_t nominal_hash = std::numeric_limits::max(); - nominal_hash = nominal_hash / difficulty; - - static_assert(sizeof(uint64_t) * 4 == sizeof(result), "!"); - for (size_t i = 0; i < 4; ++i) - { - (reinterpret_cast(&result))[i] = nominal_hash.convert_to(); - nominal_hash >>= 64; - } - } - - void get_cut_location_from_len(size_t length, size_t& cut_begin, size_t& cut_end, size_t REDEF_DIFFICULTY_WINDOW, size_t REDEF_DIFFICULTY_CUT_OLD, size_t REDEF_DIFFICULTY_CUT_LAST) - { - if (length <= REDEF_DIFFICULTY_WINDOW) - { - cut_begin = 0; - cut_end = length; - } - else - { - cut_begin = REDEF_DIFFICULTY_WINDOW - REDEF_DIFFICULTY_CUT_LAST + 1; - cut_end = cut_begin + (REDEF_DIFFICULTY_WINDOW - (REDEF_DIFFICULTY_CUT_OLD + REDEF_DIFFICULTY_CUT_LAST)); - } - } - - void get_adjustment_zone(size_t length, size_t& cut_begin, size_t& cut_end, size_t REDEF_DIFFICULTY_WINDOW, size_t REDEF_DIFFICULTY_CUT_OLD, size_t REDEF_DIFFICULTY_CUT_LAST) - { - //cutoff DIFFICULTY_LAG - if (length <= REDEF_DIFFICULTY_WINDOW - (REDEF_DIFFICULTY_CUT_OLD + REDEF_DIFFICULTY_CUT_LAST)) - { - cut_begin = 0; - cut_end = length; - } - else - { - cut_begin = REDEF_DIFFICULTY_CUT_LAST; - cut_end = cut_begin + (REDEF_DIFFICULTY_WINDOW - (REDEF_DIFFICULTY_CUT_OLD + REDEF_DIFFICULTY_CUT_LAST)); - if (cut_end > length) - cut_end = length; - - } - CHECK_AND_ASSERT_THROW_MES(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length, "validation in next_difficulty is failed"); - } - - wide_difficulty_type get_adjustment_for_zone(vector& timestamps_sorted, vector& cumulative_difficulties, size_t target_seconds, size_t REDEF_DIFFICULTY_WINDOW, size_t REDEF_DIFFICULTY_CUT_OLD, size_t REDEF_DIFFICULTY_CUT_LAST) - { - size_t length = timestamps_sorted.size(); - size_t cut_begin = 0; - size_t cut_end = 0; - get_adjustment_zone(length, cut_begin, cut_end, REDEF_DIFFICULTY_WINDOW, REDEF_DIFFICULTY_CUT_OLD, REDEF_DIFFICULTY_CUT_LAST); - - uint64_t time_span = timestamps_sorted[cut_begin] - timestamps_sorted[cut_end - 1]; - if (time_span == 0) - { - time_span = 1; - } - wide_difficulty_type total_work = cumulative_difficulties[cut_begin] - cumulative_difficulties[cut_end - 1]; - boost::multiprecision::uint256_t res = (boost::multiprecision::uint256_t(total_work) * target_seconds + time_span - 1) / time_span; - if (res > max128bit) - return 0; // to behave like previous implementation, may be better return max128bit? - return res.convert_to(); - } - - wide_difficulty_type next_difficulty_1(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds) - { - - // timestamps - first is latest, back - is oldest timestamps - if (timestamps.size() > DIFFICULTY_WINDOW) - { - timestamps.resize(DIFFICULTY_WINDOW); - cumulative_difficulties.resize(DIFFICULTY_WINDOW); - } - - - size_t length = timestamps.size(); - CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), 0, "Check \"length == cumulative_difficulties.size()\" failed"); - if (length <= 1) - { - return DIFFICULTY_STARTER; - } - static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); - - CHECK_AND_ASSERT_MES(length <= DIFFICULTY_WINDOW, 0, "length <= DIFFICULTY_WINDOW check failed, length=" << length); - - sort(timestamps.begin(), timestamps.end(), std::greater()); - - static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); - wide_difficulty_type dif_slow = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW, DIFFICULTY_CUT/2, DIFFICULTY_CUT/2); - wide_difficulty_type dif_medium = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW/3, DIFFICULTY_CUT / 8, DIFFICULTY_CUT / 12); - wide_difficulty_type dif_fast = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW/18, DIFFICULTY_CUT / 10, 2); - uint64_t devider = 1; - wide_difficulty_type summ = dif_slow; - if (dif_medium != 0) - { - summ += dif_medium; - ++devider; - } - if (dif_fast != 0) - { - summ += dif_fast; - ++devider; - } - return summ / devider; - } - - wide_difficulty_type next_difficulty_2(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds) - { - - // timestamps - first is latest, back - is oldest timestamps - if (timestamps.size() > DIFFICULTY_WINDOW) - { - timestamps.resize(DIFFICULTY_WINDOW); - cumulative_difficulties.resize(DIFFICULTY_WINDOW); - } - - - size_t length = timestamps.size(); - CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), 0, "Check \"length == cumulative_difficulties.size()\" failed"); - if (length <= 1) - { - return DIFFICULTY_STARTER; - } - static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); - - CHECK_AND_ASSERT_MES(length <= DIFFICULTY_WINDOW, 0, "length <= DIFFICULTY_WINDOW check failed, length=" << length); - - sort(timestamps.begin(), timestamps.end(), std::greater()); - - static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); - wide_difficulty_type dif_slow = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW, DIFFICULTY_CUT / 2, DIFFICULTY_CUT / 2); - wide_difficulty_type dif_medium = get_adjustment_for_zone(timestamps, cumulative_difficulties, target_seconds, DIFFICULTY_WINDOW / 3, DIFFICULTY_CUT / 8, DIFFICULTY_CUT / 12); - uint64_t devider = 1; - wide_difficulty_type summ = dif_slow; - if (dif_medium != 0) - { - summ += dif_medium; - ++devider; - } - return summ / devider; - } -} diff --git a/src/currency_core/difficulty.h b/src/currency_core/difficulty.h deleted file mode 100644 index ab97f14..0000000 --- a/src/currency_core/difficulty.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -#include - -#include "crypto/hash.h" - -namespace currency -{ - - typedef boost::multiprecision::uint128_t wide_difficulty_type; - - bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty); - wide_difficulty_type next_difficulty_1(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds); - wide_difficulty_type next_difficulty_2(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds); - uint64_t difficulty_to_boundary(wide_difficulty_type difficulty); - void difficulty_to_boundary_long(wide_difficulty_type difficulty, crypto::hash& result); -} diff --git a/src/currency_core/dispatch_core_events.h b/src/currency_core/dispatch_core_events.h deleted file mode 100644 index dadff8b..0000000 --- a/src/currency_core/dispatch_core_events.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2014-2015 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "currency_basic.h" -#include "offers_service_basics.h" //TODO: point to refactoring -#include "rpc/core_rpc_server_commands_defs.h" -//#include "serialization/keyvalue_serialization_boost_variant.h" - -#define CORE_EVENT_ADD_OFFER "CORE_EVENT_ADD_OFFER" -#define CORE_EVENT_REMOVE_OFFER "CORE_EVENT_REMOVE_OFFER" -#define CORE_EVENT_UPDATE_OFFER "CORE_EVENT_UPDATE_OFFER" -#define CORE_EVENT_ADD_ALIAS "CORE_EVENT_ADD_ALIAS" -#define CORE_EVENT_UPDATE_ALIAS "CORE_EVENT_UPDATE_ALIAS" -#define CORE_EVENT_BLOCK_ADDED "CORE_EVENT_BLOCK_ADDED" - - -namespace currency -{ - typedef boost::variant core_event_v; - - struct core_event - { - std::string method; - core_event_v details; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(method) - //KV_SERIALIZE(details) - END_KV_SERIALIZE_MAP() - }; - - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_core_event_handler - { - virtual void on_core_event(const std::string event_name, const core_event_v& e){}; - virtual void on_complete_events(){}; - virtual void on_clear_events(){}; - }; -} \ No newline at end of file diff --git a/src/currency_core/etc_custom_serialization.cpp b/src/currency_core/etc_custom_serialization.cpp deleted file mode 100644 index 555ec79..0000000 --- a/src/currency_core/etc_custom_serialization.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2014-2015 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "currency_format_utils.h" -#include "etc_custom_serialization.h" - -namespace bc_services -{ - std::string transform_amount_to_string(const uint64_t& a) - { -// double d = static_cast(a); -// d /= ETC_AMOUNT_DIVIDER; - return std::to_string(a);//print_money(a, ETC_AMOUNT_DIVIDER_DECIMAL_POINT); - } - - uint64_t transform_string_to_amount(const std::string& d) - { - uint64_t n = 0; - epee::string_tools::get_xtype_from_string(n, d); - return n; - } -} \ No newline at end of file diff --git a/src/currency_core/etc_custom_serialization.h b/src/currency_core/etc_custom_serialization.h deleted file mode 100644 index b0269ba..0000000 --- a/src/currency_core/etc_custom_serialization.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2014-2015 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#define ETC_AMOUNT_DIVIDER 100000000 -#define ETC_AMOUNT_DIVIDER_DECIMAL_POINT 8 - -namespace bc_services -{ - std::string transform_amount_to_string(const uint64_t& a); - uint64_t transform_string_to_amount(const std::string& a); - -} diff --git a/src/currency_core/genesis.cpp b/src/currency_core/genesis.cpp deleted file mode 100644 index a58dcb4..0000000 --- a/src/currency_core/genesis.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "genesis.h" - -namespace currency -{ -#ifndef TESTNET - const genesis_tx_raw_data ggenesis_tx_raw = { { - 0xa080801a00000101,0x800326b0b4a0f2fd,0xeebe5a6d44a03ed5,0x0e146a5322076dcf,0x992269ec1e34796e,0x003b14d1fe6c757e,0xb0b4a0f2fda08080,0xfd92adf982e70326,0xd8d4b6458b60e1a4,0xa69adb9475e808ed,0x4c383fcedfb6e20a,0xf2fda08080003458,0x8b177f0326b0b4a0,0xef9769ed70d152cd,0x04097d0daa65d123,0x9cd9f8e708f25bbc,0x8080005dfb23beac,0x0326b0b4a0f2fda0,0x6752077f8e75fc8a,0x437f68e0bf774836,0x5a38b52ff21c01c0,0x2d3727ec82ce1425,0xb4f89aecdce08000,0xa07d9fe35f0326b0,0x6c742533eb3b4261,0xfc2ed631332e5e16,0x3d025449393e538b,0x93dc80800015e433,0x70a20307d0ffc2e0,0xb81808dc5029bd46,0x04129413283e31f1,0x143e631cc81020b0,0x80008519d1377ae3,0x05c6c5bc97b1a080,0xf71887a841a72a03,0x681b659b8d2832d4,0x5677f9b15d11d1e6,0xffb2ad80c02a341c,0xbc97b1a08080003f,0xf9cebe7c0305c6c5,0xee223954dc682820,0x8194d2bac0dff6d6,0x86d8a55a30e30183,0xa08080006775f5f0,0x220305c6c5bc97b1,0x3c36e1ebdcee584a,0x4e9ed1a89532ef46,0xf0cb8b411bf6d579,0x00d0e6392ada64d4,0xc6c5bc97b1a08080,0x2fc2b05779450305,0xc9cf47618cc5283e,0xa9e088224807a77e,0xda854e29d2f49646,0x97b1a08080002e74,0xed35180305c6c5bc,0xa78d5545117b8293,0x5c3f8babc16e7062,0xef9324ecd7f86e39,0x808000231900ee9c,0x0305c6c5bc97b1a0,0x0c5bfd9450e89e30,0x194b86e8316970bc,0x5dd8c2e3c2af6ff1,0x4d2ba46f683df89c,0xc5bc97b1a0808000,0xc7cc22ad390305c6,0x891b500cb0799642,0xf5884473a7c01f07,0xeb88d74972d8e36f,0x91ed808000b5d239,0x535a0302fddecd95,0x791c7275cd15d685,0xc2536511d4132e01,0x0c9ad1ee9196aa77,0x80002d55a4efc7d3,0x018e8df2b7f0a080,0x0848b53f974a6a03,0x96b2572cb6015b7d,0xa71b18d2755de52c,0x075e4ca4bd0e4487,0xef93bf82808000ca,0xe23077bc730308f0,0x266a622b7bd9de26,0x4b80410b36c32203,0xb3026d0a2610916c,0xfe8480800084746d,0x6f34b90311e1dea6,0xeb38aee70a8febba,0x8b45df519f0df12e,0x258f0a71e83385da,0x8080000b85701a76,0xdf0308f0ef93bf82,0xb3170ab580f881a3,0x07f0a33f0756a3f4,0xf0721645b2b2bd7b,0x00b0077e03f43a85,0x08f0ef93bf828080,0xf91c1f6308c00f03,0x901a68f4adcc918b,0xad0346f5b7869662,0xd3ed49961fccd915,0xafeaa69a808000f0,0x2c99a01fe90301e3,0xd28642bcae6728d9,0xa6f38c4c630c2b6c,0x2c8a361de6b9294f,0xa69a8080002191e8,0xe134670301e3afea,0x6cf0798aeae985c8,0x4c9b90e1ff211b81,0xc32a954ce05a738b,0x8080009fd2412c6f,0x790301e3afeaa69a,0xb3b0062d6c27a6bb,0x12e133832172b705,0xf3f7d1dfdf336fb8,0x00922d0a879c6027,0x03c6dfd4ccb48080,0x7aa13f278feecf03,0x464f78f86a3e4553,0xa5a464e65c4cf651,0x18f07e7ed8bdd351,0xef93bf82808000dd,0x70b4e3ebae0308f0,0x74c452ecdce312d9,0xca3fb591982461fc,0x3e01aaf9b53ede69,0xfe84808000a4fa65,0x20e5ba0311e1dea6,0xb3e07ec0aabd06a5,0x7bf14a03bf83ccfd,0x6024154f95fd3220,0x808000c13077fa8b,0x5c580316deb183e9,0xc2c948248ab422c3,0xebd3db36bad27d52,0x5fe30392c1525a4e,0x1e00952287d66a6d,0x163df474d5ba8816,0x86f8892015449a71,0x22c93333d9ecb472,0x64fa5516bddfebb3,0x3234373061401303,0x3934353331623633,0x3063626435643130,0x6334636130633932,0x3831383439633530,0x3330336634336332,0x3963306232336630,0x3261623765656133,0x80c9170015633537,0x4c17fba117829117,0x17624a17d2f21711,0xfec81731f9178ced,0x9c17624117a36017,0x1786df17edda1708,0x9ffa17d6e1171b42,0x8b17aa69177ff417,0x179815170a83170c,0xc7e8171ce317da27 }, - { 0x17,0x86,0xd6,0x0e,0x0a,0x00,0x00 } }; -#else - const genesis_tx_raw_data ggenesis_tx_raw = {{ - 0xd880800500000101,0x0301f2ee9fa8ff8a,0xac88983c159856b0,0x6334c7d1b567f262,0x284f7f961a7b1266,0x8c0c68c45bab62fc,0xe1dea6fe84808000,0x337be98b45240311,0xab6cd1e4c66e5a33,0x70e889d98e70fd57,0xb97de43fb09861d4,0xf9f0cde08000d574,0x0270187703048dba,0xcac58027c0851473,0xaa10d864c4c87b46,0x820d371e2ba469e8,0xfea08000fce35acc,0x357903049598bddf,0x15df9e58bd0002aa,0xc940a97b60484e8d,0xf94f171e77d0b2d9,0x80003602c681487a,0x0304c38fbab1f8e0,0xc2529eba91cf7476,0x0bbee139aab295f9,0xf1cb8c58a828a2ca,0xcac8f5469af83932,0x5c8a1027cc160900,0x50bdcc9348baf32a,0xa7bd03751819d9fd,0xd6acc8dbbb0d9b29,0x3730614013368b02,0x3533316236333234,0x6264356431303934,0x6361306339323063,0x3834396335306334,0x3366343363323831,0x3062323366303330,0x6237656561333963,0x1700156335373261,0xce5017baa917a8f0,0x0a0eefcc17975617}, - {0x00,0x00}}; -#endif -} - diff --git a/src/currency_core/genesis.h b/src/currency_core/genesis.h deleted file mode 100644 index 8ea77d8..0000000 --- a/src/currency_core/genesis.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -namespace currency -{ -#pragma pack(push, 1) -#ifndef TESTNET - struct genesis_tx_raw_data - { - uint64_t const v[161]; - uint8_t const r[7]; - }; - -#else - struct genesis_tx_raw_data - { - uint64_t const v[42]; - uint8_t const r[2]; - }; -#endif -#pragma pack(pop) - extern const genesis_tx_raw_data ggenesis_tx_raw; -} - - - - diff --git a/src/currency_core/genesis_acc.cpp b/src/currency_core/genesis_acc.cpp deleted file mode 100644 index f49a9c0..0000000 --- a/src/currency_core/genesis_acc.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "genesis_acc.h" - - -namespace currency -{ -#ifndef TESTNET - const std::string ggenesis_tx_pub_key_str = "88bad574f43d16719a44152089f88672b4ecd93333c922b3ebdfbd1655fa6403"; - const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string(ggenesis_tx_pub_key_str); - const genesis_tx_dictionary_entry ggenesis_dict[26] = { - { 898363347618325980ULL,7 }, - { 1234271292339965434ULL,1 }, - { 2785329203593578547ULL,12 }, - { 2912579291078040461ULL,18 }, - { 3515932779881697835ULL,17 }, - { 4955366495399988463ULL,11 }, - { 5233257582118330150ULL,5 }, - { 5931539148443336682ULL,24 }, - { 6436517662239927298ULL,19 }, - { 6604452700210763953ULL,13 }, - { 7200550178847042641ULL,15 }, - { 8712326356392296687ULL,9 }, - { 8863158309745010598ULL,4 }, - { 9048445805125559105ULL,16 }, - { 9527474759752332295ULL,2 }, - { 9647541513390373765ULL,20 }, - { 9921730437908704447ULL,8 }, - { 10751885755236960099ULL,25 }, - { 11032572278436047420ULL,22 }, - { 11109691972771859220ULL,0 }, - { 13554174209305230569ULL,23 }, - { 14297297752337562678ULL,3 }, - { 15636081871140663679ULL,21 }, - { 15951161519112687845ULL,6 }, - { 17146058209502212345ULL,14 }, - { 17472133472787764818ULL,10 } - }; -#else - const std::string ggenesis_tx_pub_key_str = "cc27108a5c2af3ba4893ccbd50fdd919187503bda7299b0dbbdbc8acd6028b36"; - const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string(ggenesis_tx_pub_key_str); - const genesis_tx_dictionary_entry ggenesis_dict[5] = { - { 4413532107669521528ULL, 2 }, - { 4848259848862559835ULL, 4 }, - { 4891306118630423916ULL, 1 }, - { 6536034028979999929ULL, 0 }, - { 15528122346224653564ULL, 3 } -}; -#endif - - - -} - - - diff --git a/src/currency_core/genesis_acc.h b/src/currency_core/genesis_acc.h deleted file mode 100644 index f26ee95..0000000 --- a/src/currency_core/genesis_acc.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include "currency_format_utils.h" - -namespace currency { - -#pragma pack(push, 1) -struct genesis_tx_dictionary_entry { - uint64_t addr_hash; - uint64_t offset; - - bool operator<(const genesis_tx_dictionary_entry& s) const - { - return addr_hash < s.addr_hash; - } -}; -#pragma pack(pop) - -#ifndef TESTNET -extern const genesis_tx_dictionary_entry ggenesis_dict[26]; -#else -extern const genesis_tx_dictionary_entry ggenesis_dict[5]; -#endif - -extern const crypto::public_key ggenesis_tx_pub_key; - -inline bool get_account_genesis_offset_by_address(const std::string& addr, uint64_t& offset) -{ - genesis_tx_dictionary_entry key_entry = AUTO_VAL_INIT(key_entry); - key_entry.addr_hash = get_string_uint64_hash(addr); - - const genesis_tx_dictionary_entry* pfirst = &ggenesis_dict[0]; - const genesis_tx_dictionary_entry* plast = &ggenesis_dict[sizeof(ggenesis_dict) / sizeof(ggenesis_dict[0])]; - const genesis_tx_dictionary_entry* plower = std::lower_bound(pfirst, plast, key_entry); - if(plower == plast) - return false; - if(plower->addr_hash != key_entry.addr_hash) - return false; - offset = plower->offset; - return true; -} -} diff --git a/src/currency_core/miner.cpp b/src/currency_core/miner.cpp deleted file mode 100644 index 005c274..0000000 --- a/src/currency_core/miner.cpp +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include -#include -#include -#include "misc_language.h" -#include "include_base_utils.h" - -#include "currency_format_utils.h" -#include "file_io_utils.h" -#include "common/command_line.h" -#include "string_coding.h" -#include "version.h" -#include "storages/portable_storage_template_helper.h" -#include "basic_pow_helpers.h" - -using namespace epee; - -#include "miner.h" - - - -namespace currency -{ - - namespace - { - const command_line::arg_descriptor arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true}; - const command_line::arg_descriptor arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; - const command_line::arg_descriptor arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; - const command_line::arg_descriptor arg_block_template_extra_text = { "miner-text-info", "Set block extra text info", "", true }; - } - - - miner::miner(i_miner_handler* phandler, blockchain_storage& bc):m_stop(1), - //m_bc(bc), - m_template(boost::value_initialized()), - m_template_no(0), - m_diffic(0), - m_thread_index(0), - m_phandler(phandler), - m_height(0), - m_pausers_count(0), - m_threads_total(0), - m_starter_nonce(0), - m_do_print_hashrate(false), - m_do_mining(false), - m_current_hash_rate(0), - m_last_hr_merge_time(0), - m_hashes(0), - m_config(AUTO_VAL_INIT(m_config)), - m_mine_address{} - { - } - //----------------------------------------------------------------------------------------------------- - miner::~miner() - { - TRY_ENTRY(); - stop(); - CATCH_ENTRY_NO_RETURN(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_block_template(const block& bl, const wide_difficulty_type& di, uint64_t height) - { - CRITICAL_REGION_LOCAL(m_template_lock); - m_template = bl; - m_diffic = di; - m_height = height; - ++m_template_no; - m_starter_nonce = crypto::rand(); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_block_chain_update() - { - if(!is_mining()) - return true; - - //here miner threads may work few rounds without - return request_block_template(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::request_block_template() - { - block bl = AUTO_VAL_INIT(bl); - wide_difficulty_type di = AUTO_VAL_INIT(di); - uint64_t height = AUTO_VAL_INIT(height); - currency::blobdata extra_nonce = m_template_extra_text; - if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size()) - { - extra_nonce += std::string("|") + m_extra_messages[m_config.current_extra_message_index]; - } - if(!m_phandler->get_block_template(bl, m_mine_address, m_mine_address, di, height, extra_nonce)) - { - LOG_ERROR("Failed to get_block_template()"); - return false; - } - set_block_template(bl, di, height); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_idle() - { - m_update_block_template_interval.do_call([&](){ - if(is_mining())request_block_template(); - return true; - }); - - m_update_merge_hr_interval.do_call([&](){ - merge_hr(); - return true; - }); - - return true; - } - //----------------------------------------------------------------------------------------------------- - void miner::do_print_hashrate(bool do_hr) - { - m_do_print_hashrate = do_hr; - } - //----------------------------------------------------------------------------------------------------- - void miner::merge_hr() - { - if(m_last_hr_merge_time && is_mining()) - { - m_current_hash_rate = (m_hashes * 1000) / ((misc_utils::get_tick_count() - m_last_hr_merge_time + 1)); - } - m_last_hr_merge_time = misc_utils::get_tick_count(); - m_hashes = 0; - if(m_do_print_hashrate && is_mining()) - std::cout << "hr: " << m_current_hash_rate << ENDL; - } - //----------------------------------------------------------------------------------------------------- - void miner::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_extra_messages); - command_line::add_arg(desc, arg_start_mining); - command_line::add_arg(desc, arg_mining_threads); - command_line::add_arg(desc, arg_block_template_extra_text); - } - //----------------------------------------------------------------------------------------------------- - bool miner::init(const boost::program_options::variables_map& vm) - { - m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); - epee::serialization::load_t_from_json_file(m_config, m_config_folder + "/" + MINER_CONFIG_FILENAME); - - if(command_line::has_arg(vm, arg_extra_messages)) - { - std::string buff; - bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages)); - std::vector extra_vec; - boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on ); - m_extra_messages.resize(extra_vec.size()); - for(size_t i = 0; i != extra_vec.size(); i++) - { - string_tools::trim(extra_vec[i]); - if(!extra_vec[i].size()) - continue; - buff = string_encoding::base64_decode(extra_vec[i]); - if(buff != "0") - m_extra_messages[i] = buff; - } - LOG_PRINT_L0("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index); - } - - if(command_line::has_arg(vm, arg_start_mining)) - { - if(!currency::get_account_address_from_str(m_mine_address, command_line::get_arg(vm, arg_start_mining))) - { - LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled"); - return false; - } - m_threads_total = 1; - m_do_mining = true; - if(command_line::has_arg(vm, arg_mining_threads)) - { - m_threads_total = command_line::get_arg(vm, arg_mining_threads); - } - } - - if (command_line::has_arg(vm, arg_block_template_extra_text)) - { - m_template_extra_text = command_line::get_arg(vm, arg_block_template_extra_text); - } - else - { - m_template_extra_text = PROJECT_VERSION_LONG; - } - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::deinit() - { - if (!tools::create_directories_if_necessary(m_config_folder)) - { - LOG_PRINT_L0("Failed to create data directory: " << m_config_folder); - return false; - } - epee::serialization::store_t_to_json_file(m_config, m_config_folder + "/" + MINER_CONFIG_FILENAME); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::is_mining() - { - return !m_stop; - } - //----------------------------------------------------------------------------------------------------- - bool miner::start(const account_public_address& adr, size_t threads_count) - { - - m_mine_address = adr; - m_threads_total = static_cast(threads_count); - m_starter_nonce = crypto::rand(); - CRITICAL_REGION_LOCAL(m_threads_lock); - if(is_mining()) - { - LOG_PRINT_L0("Starting miner: miner already running"); - return false; - } - - if(!m_threads.empty()) - { - LOG_ERROR("Starting miner canceled: there are still active mining threads"); - return false; - } - - if(!m_template_no) - request_block_template();//lets update block template - - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); - boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); - - for(size_t i = 0; i != threads_count; i++) - m_threads.push_back(boost::thread(boost::bind(&miner::worker_thread, this))); - - LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" ) - return true; - } - //----------------------------------------------------------------------------------------------------- - uint64_t miner::get_speed() - { - if(is_mining()) - return m_current_hash_rate; - else - return 0; - } - //----------------------------------------------------------------------------------------------------- - void miner::send_stop_signal() - { - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1); - } - //----------------------------------------------------------------------------------------------------- - bool miner::stop() - { - send_stop_signal(); - CRITICAL_REGION_LOCAL(m_threads_lock); - - BOOST_FOREACH(boost::thread& th, m_threads) - th.join(); - - m_threads.clear(); - LOG_PRINT_L0("Mining has been stopped, " << m_threads.size() << " finished" ); - return true; - } - //----------------------------------------------------------------------------------------------------- - void miner::on_synchronized() - { - if(m_do_mining) - { - start(m_mine_address, m_threads_total); - } - } - //----------------------------------------------------------------------------------------------------- - void miner::pause() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - ++m_pausers_count; - if(m_pausers_count == 1 && is_mining()) - LOG_PRINT_L2("MINING PAUSED"); - } - //----------------------------------------------------------------------------------------------------- - void miner::resume() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - --m_pausers_count; - if(m_pausers_count < 0) - { - m_pausers_count = 0; - LOG_PRINT_RED_L0("Unexpected miner::resume() called"); - } - if(!m_pausers_count && is_mining()) - LOG_PRINT_L2("MINING RESUMED"); - } - //----------------------------------------------------------------------------------------------------- - bool miner::worker_thread() - { - uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - LOG_PRINT_L0("Miner thread was started ["<< th_local_index << "]"); - log_space::log_singletone::set_thread_log_prefix(std::string("[miner ") + std::to_string(th_local_index) + "]"); - uint64_t nonce = m_starter_nonce + th_local_index; - wide_difficulty_type local_diff = 0; - uint32_t local_template_ver = 0; - blobdata local_blob_data; - uint64_t local_height = 0; - crypto::hash local_blob_data_hash = null_hash; - - //uint64_t local_template_height = 0; - block b; - - while(!m_stop) - { - if(m_pausers_count)//anti split workaround - { - misc_utils::sleep_no_w(100); - continue; - } - - if(local_template_ver != m_template_no) - { - CRITICAL_REGION_BEGIN(m_template_lock); - b = m_template; - b.nonce = 0; - local_diff = m_diffic; - local_height = m_height; - CRITICAL_REGION_END(); - //local_template_height = get_block_height(b); - local_template_ver = m_template_no; - nonce = m_starter_nonce + th_local_index; - local_blob_data = get_block_hashing_blob(b); - local_blob_data_hash = crypto::cn_fast_hash(local_blob_data.data(), local_blob_data.size()); - } - - if(!local_template_ver)//no any set_block_template call - { - LOG_PRINT_L2("Block template not set yet"); - epee::misc_utils::sleep_no_w(1000); - continue; - } - //b.nonce = nonce; - //access_nonce_in_block_blob(local_blob_data) = b.nonce; - crypto::hash h = get_block_longhash(local_height, local_blob_data_hash, nonce); - - if(check_hash(h, local_diff)) - { - b.nonce = nonce; - ++m_config.current_extra_message_index; - LOG_PRINT_GREEN("Found block for difficulty: " << local_diff << ", height: " << local_height << ", PoW hash: " << h << ", local_blob_data_hash: " << local_blob_data_hash << ", nonce: " << std::hex << nonce, LOG_LEVEL_0); - if(!m_phandler->handle_block_found(b)) - { - --m_config.current_extra_message_index; - } - else - { - //success, let's update config - epee::serialization::store_t_to_json_file(m_config, m_config_folder + "/" + MINER_CONFIG_FILENAME); - } - } - nonce+=m_threads_total; - ++m_hashes; - } - LOG_PRINT_L0("Miner thread stopped ["<< th_local_index << "]"); - return true; - } - //----------------------------------------------------------------------------------------------------- -} - diff --git a/src/currency_core/miner.h b/src/currency_core/miner.h deleted file mode 100644 index 69a4bdc..0000000 --- a/src/currency_core/miner.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include "currency_basic.h" -#include "difficulty.h" -#include "math_helper.h" -#include "blockchain_storage.h" -#include "basic_pow_helpers.h" - - - -namespace currency -{ - - struct i_miner_handler - { - virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr) = 0; - virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp) = 0; - virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()) = 0; - protected: - ~i_miner_handler(){}; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class miner - { - public: - miner(i_miner_handler* phandler, blockchain_storage& bc); - ~miner(); - bool init(const boost::program_options::variables_map& vm); - bool deinit(); - static void init_options(boost::program_options::options_description& desc); - bool on_block_chain_update(); - bool start(const account_public_address& adr, size_t threads_count); - uint64_t get_speed(); - void send_stop_signal(); - bool stop(); - bool is_mining(); - bool on_idle(); - void on_synchronized(); - //synchronous analog (for fast calls) - void pause(); - void resume(); - void do_print_hashrate(bool do_hr); - - inline - static bool find_nonce_for_given_block(block& bl, const wide_difficulty_type& diffic, uint64_t height) - { - bl.nonce = 0; - blobdata bd = get_block_hashing_blob(bl); - crypto::hash bd_hash = crypto::cn_fast_hash(bd.data(), bd.size()); - //uint64_t& nonce_ref = access_nonce_in_block_blob(bd); - //nonce_ref = 0; - - for(; bl.nonce != std::numeric_limits::max(); bl.nonce++) - { - crypto::hash h = get_block_longhash(height, bd_hash, bl.nonce); - if(check_hash(h, diffic)) - { - LOG_PRINT_L0("Found nonce for block: " << get_block_hash(bl) << "[" << height << "]: PoW:" << h << "(diff:" << diffic << "), ts: " << bl.timestamp); - return true; - } - } - return false; - } - - private: - bool set_block_template(const block& bl, const wide_difficulty_type& diffic, uint64_t height); - bool worker_thread(); - bool request_block_template(); - void merge_hr(); - - struct miner_config - { - uint64_t current_extra_message_index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_extra_message_index) - END_KV_SERIALIZE_MAP() - }; - - - volatile uint32_t m_stop; - ::critical_section m_template_lock; - block m_template; - std::atomic m_template_no; - std::atomic m_starter_nonce; - wide_difficulty_type m_diffic; - std::atomic m_height; - volatile uint32_t m_thread_index; - volatile uint32_t m_threads_total; - std::atomic m_pausers_count; - ::critical_section m_miners_count_lock; - - std::list m_threads; - ::critical_section m_threads_lock; - i_miner_handler* m_phandler; - //blockchain_storage& m_bc; - account_public_address m_mine_address; - math_helper::once_a_time_seconds<5> m_update_block_template_interval; - math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; - std::vector m_extra_messages; - miner_config m_config; - std::string m_config_folder; - std::string m_template_extra_text; - std::atomic m_current_hash_rate; - std::atomic m_last_hr_merge_time; - std::atomic m_hashes; - bool m_do_print_hashrate; - bool m_do_mining; - - }; -} - - - diff --git a/src/currency_core/miner_common.h b/src/currency_core/miner_common.h deleted file mode 100644 index 9c6db39..0000000 --- a/src/currency_core/miner_common.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - diff --git a/src/currency_core/offers_service_basics.h b/src/currency_core/offers_service_basics.h deleted file mode 100644 index 16d2990..0000000 --- a/src/currency_core/offers_service_basics.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - - -#include "serialization/keyvalue_serialization.h" -#include "crypto/crypto.h" -#include "etc_custom_serialization.h" -namespace bc_services -{ - /************************************************************************/ - /* offer structures */ - /************************************************************************/ - struct offer_details - { - - //fields filled in UI - uint8_t offer_type; // OFFER_TYPE_PRIMARY_TO_TARGET(SELL ORDER) - 0, OFFER_TYPE_TARGET_TO_PRIMARY(BUY ORDER) - 1 etc. - uint64_t amount_primary; // amount of the currency - uint64_t amount_target; // amount of other currency or goods - std::string bonus; // - std::string target; // [] currency / goods - std::string primary; // currency for goods - std::string location_country; // ex: US - std::string location_city; // ex: ChIJD7fiBh9u5kcRYJSMaMOCCwQ (google geo-autocomplete id) - std::string contacts; // [] (Skype, mail, ICQ, etc., website) - std::string comment; // [] - std::string payment_types; // []money accept type(bank transaction, internet money, cash, etc) - std::string deal_option; // []full amount, by parts - std::string category; // [] - uint8_t expiration_time; // n-days - //----------------- - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_N(offer_type, "ot") - KV_SERIALIZE_CUSTOM_N(amount_primary, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "ap") - KV_SERIALIZE_CUSTOM_N(amount_target, std::string, bc_services::transform_amount_to_string, bc_services::transform_string_to_amount, "at") - KV_SERIALIZE_N(bonus, "b") - KV_SERIALIZE_N(target, "t") - KV_SERIALIZE_N(primary, "p") - KV_SERIALIZE_N(location_country, "lco") - KV_SERIALIZE_N(location_city, "lci") - KV_SERIALIZE_N(contacts, "cnt") - KV_SERIALIZE_N(comment, "com") - KV_SERIALIZE_N(payment_types, "pt") - KV_SERIALIZE_N(deal_option, "do") - KV_SERIALIZE_N(category, "cat") - KV_SERIALIZE_N(expiration_time, "et") - END_KV_SERIALIZE_MAP() - }; - - struct offer_details_ex : public offer_details - { - //fields contained in dictionary and also returned to UI/ - crypto::hash tx_hash; - crypto::hash tx_original_hash; - uint64_t index_in_tx; - uint64_t timestamp; //this is not kept by transaction, info filled by corresponding transaction - uint64_t fee; //value of fee to pay(or paid in case of existing offers) to rank it - crypto::public_key security; //key used for updating offer - //----------------- - - mutable bool stopped; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_hash) - KV_SERIALIZE_POD_AS_HEX_STRING(tx_original_hash) - KV_SERIALIZE(index_in_tx) - KV_SERIALIZE(timestamp) - KV_SERIALIZE(fee) - KV_SERIALIZE_POD_AS_HEX_STRING(security) - KV_CHAIN_BASE(offer_details) - END_KV_SERIALIZE_MAP() - }; - - struct cancel_offer - { - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING_N(tx_id, "id") - KV_SERIALIZE_N(offer_index, "oi") - KV_SERIALIZE_POD_AS_HEX_STRING_N(sig, "sig") - END_KV_SERIALIZE_MAP() - - crypto::hash tx_id; - uint64_t offer_index; - crypto::signature sig; //tx_id signed by transaction secret key - }; - - - struct update_offer - { - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING_N(tx_id, "id") - KV_SERIALIZE_N(offer_index, "oi") - KV_SERIALIZE_POD_AS_HEX_STRING_N(sig, "sig") - KV_SERIALIZE_N(of, "of") - END_KV_SERIALIZE_MAP() - - crypto::hash tx_id; - uint64_t offer_index; - crypto::signature sig; //tx_id signed by transaction secret key - offer_details of; - }; - - struct update_offer_details - { - uint64_t wallet_id; - crypto::hash tx_id; - uint64_t no; - offer_details_ex od; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(wallet_id) - KV_SERIALIZE_POD_AS_HEX_STRING_N(tx_id, "id") - KV_SERIALIZE_N(no, "oi") - KV_SERIALIZE_N(od, "of") - END_KV_SERIALIZE_MAP() - }; - - - typedef boost::variant offers_attachment_t; - - inline std::string transform_double_to_string(const double& a) - { - return std::to_string(a); - } - - inline double transform_string_to_double(const std::string& d) - { - double n = 0; - epee::string_tools::get_xtype_from_string(n, d); - return n; - } - - - struct core_offers_filter - { - uint64_t order_by; - bool reverse; - uint64_t offset; - uint64_t limit; - //filter entry - uint64_t timestamp_start; - uint64_t timestamp_stop; - uint64_t offer_type_mask; - uint64_t amount_low_limit; - uint64_t amount_up_limit; - double rate_low_limit; - double rate_up_limit; - std::list payment_types; - std::string location_country; - std::string location_city; - std::string target; - std::string primary; - bool bonus; - std::string category; - std::string keyword; - bool fake; - uint64_t current_time; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(order_by) - KV_SERIALIZE(reverse) - KV_SERIALIZE(offset) - KV_SERIALIZE(limit) - KV_SERIALIZE(timestamp_start) - KV_SERIALIZE(timestamp_stop) - KV_SERIALIZE(offer_type_mask) - KV_SERIALIZE(amount_low_limit) - KV_SERIALIZE(amount_up_limit) - KV_SERIALIZE_CUSTOM(rate_low_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double) - KV_SERIALIZE_CUSTOM(rate_up_limit, std::string, bc_services::transform_double_to_string, bc_services::transform_string_to_double) - KV_SERIALIZE(payment_types) - KV_SERIALIZE(location_country) - KV_SERIALIZE(location_city) - KV_SERIALIZE(target) - KV_SERIALIZE(primary) - KV_SERIALIZE(bonus) - KV_SERIALIZE(category) - KV_SERIALIZE(keyword) - KV_SERIALIZE(fake) - END_KV_SERIALIZE_MAP() - }; - - -} \ No newline at end of file diff --git a/src/currency_core/offers_services_helpers.cpp b/src/currency_core/offers_services_helpers.cpp deleted file mode 100644 index d99bf4d..0000000 --- a/src/currency_core/offers_services_helpers.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#include - -#include "string_coding.h" -#include "offers_services_helpers.h" -#include "etc_custom_serialization.h" - -#include "misc_language.h" -#include "currency_basic.h" - - -namespace bc_services -{ - - - bool order_offers_by_timestamp(const offer_details_ex* a, const offer_details_ex* b) - { - return a->timestamp < b->timestamp; - } - //------------------------------------------------------------------ - bool order_offers_by_amount_primary(const offer_details_ex* a, const offer_details_ex* b) - { - return a->amount_primary < b->amount_primary; - } - //------------------------------------------------------------------ - bool order_offers_by_amount_target(const offer_details_ex* a, const offer_details_ex* b) - { - return a->amount_target < b->amount_target; - } - //------------------------------------------------------------------ - bool order_offers_by_rate(const offer_details_ex* a, const offer_details_ex* b) - { - return calculate_offer_rate(*a) < calculate_offer_rate(*b); - } - //------------------------------------------------------------------ - bool order_offers_by_payment_types(const offer_details_ex* a, const offer_details_ex* b) - { - return a->payment_types < b->payment_types; - } - //------------------------------------------------------------------ - bool order_offers_by_contacts(const offer_details_ex* a, const offer_details_ex* b) - { - return a->contacts < b->contacts; - } - //------------------------------------------------------------------ - bool order_offers_by_location(const offer_details_ex* a, const offer_details_ex* b) - { - return a->location_city < b->location_city; - } - //------------------------------------------------------------------ - bool order_offers_by_name(const offer_details_ex* a, const offer_details_ex* b) - { -#ifndef ANDROID_BUILD - return currency::utf8_to_lower(a->target) < currency::utf8_to_lower(b->target); -#else - return false; -#endif - } - //------------------------------------------------------------------ - std::vector gsort_offers_predicates; - bool init_vector = epee::misc_utils::static_initializer([](){ - gsort_offers_predicates.resize(ORDER_CALLBACKS_COUNT); - gsort_offers_predicates[ORDER_BY_TIMESTAMP] = &order_offers_by_timestamp; - gsort_offers_predicates[ORDER_BY_AMOUNT_PRIMARY] = &order_offers_by_amount_primary; - gsort_offers_predicates[ORDER_BY_AMOUNT_TARGET] = &order_offers_by_amount_target; - gsort_offers_predicates[ORDER_BY_AMOUNT_RATE] = &order_offers_by_rate; - gsort_offers_predicates[ORDER_BY_PAYMENT_TYPES] = &order_offers_by_payment_types; - gsort_offers_predicates[ORDER_BY_CONTACTS] = &order_offers_by_contacts; - gsort_offers_predicates[ORDER_BY_LOCATION] = &order_offers_by_location; - gsort_offers_predicates[ORDER_BY_NAME] = &order_offers_by_name; - return true; - }); - // std::locale locale_utf8; - bool init_locale = epee::misc_utils::static_initializer([](){ - setlocale(LC_ALL, ""); - return true; - }); - - - - - to_low_case_ptr_type to_low_case_external = nullptr; - - void set_external_to_low_converter(to_low_case_ptr_type cb) - { - to_low_case_external = cb; - } - - - std::wstring to_lower_local_w(const std::string& s) - { - //std::u16string a; - std::wstring ws = epee::string_encoding::utf8_to_wstring(s); - if (to_low_case_external) - return to_low_case_external(ws); - //std::transform(ws.begin(), ws.end(), ws.begin(), ::towlower); - boost::algorithm::to_lower(ws); - return ws; - } - -#define SECONDS_IN_ONE_DAY (60*60*24) - - - bool is_offer_matched_by_filter(const offer_details_ex& o, const core_offers_filter& of, uint64_t current_time) - { - if (o.stopped) - return false; - //check offer type condition - if (of.offer_type_mask) - { - switch (o.offer_type) - { - case OFFER_TYPE_PRIMARY_TO_TARGET: - if (!(of.offer_type_mask & OFFER_TYPE_MASK_PRIMARY_TO_TARGET)) - return false; - break; - case OFFER_TYPE_TARGET_TO_PRIMARY: - if (!(of.offer_type_mask & OFFER_TYPE_MASK_TARGET_TO_PRIMARY)) - return false; - break; - case OFFER_TYPE_GOODS_TO_PRIMARY: - if (!(of.offer_type_mask & OFFER_TYPE_MASK_GOODS_TO_PRIMARY)) - return false; - break; - case OFFER_TYPE_PRIMARY_TO_GOODS: - if (!(of.offer_type_mask & OFFER_TYPE_MASK_PRIMARY_TO_GOODS)) - return false; - break; - default: - return false; - } - } - - //check timestamp condition - if (of.timestamp_start && (o.timestamp < of.timestamp_start)) - return false; - if (of.timestamp_stop && (o.timestamp > of.timestamp_stop)) - return false; - - //check bonus field - if (of.bonus && o.bonus.empty()) - return false; - - //check category - if (!of.category.empty() && o.category.find(of.category) == std::string::npos) - return false; -#ifndef ANDROID_BUILD - //check target condition - if (of.target.size() && !currency::utf8_substring_test_case_insensitive(of.target, o.target)) - return false; - - if (of.primary.size() && !currency::utf8_substring_test_case_insensitive(of.primary, o.primary)) - return false; -#endif - - //check payment_types condition (TODO: add more complicated algo here) - if (of.payment_types.size()) - { - for (const auto& ot : of.payment_types) - { - if (std::string::npos == o.payment_types.find(ot)) - return false; - } - } - - - //check target condition - if (of.location_country.size() && (of.location_country != o.location_country)) - return false; -#ifndef ANDROID_BUILD - //check target condition - if (of.location_city.size() && !currency::utf8_substring_test_case_insensitive(of.location_city, o.location_city)) - return false; -#endif - //check amount - if (of.amount_low_limit && (of.amount_low_limit > o.amount_primary)) - return false; - if (of.amount_up_limit && (of.amount_up_limit < o.amount_primary)) - return false; - - double rate = ((static_cast(o.amount_target) / ETC_AMOUNT_DIVIDER)) / (static_cast(o.amount_primary) / COIN); - //check rate - if (of.rate_low_limit && (of.rate_low_limit > rate)) - return false; - if (of.rate_up_limit && (of.rate_up_limit < rate)) - return false; - - - - //check keywords - if (!of.keyword.empty()) - { - std::wstring all_in_apper; - all_in_apper += to_lower_local_w(o.bonus); - all_in_apper += to_lower_local_w(o.target); - all_in_apper += to_lower_local_w(o.location_country); - all_in_apper += to_lower_local_w(o.location_city); - all_in_apper += to_lower_local_w(o.contacts); - all_in_apper += to_lower_local_w(o.comment); - all_in_apper += to_lower_local_w(o.payment_types); - all_in_apper += to_lower_local_w(o.deal_option); - all_in_apper += to_lower_local_w(o.category); - std::wstring keyword_lowcase = to_lower_local_w(of.keyword); - if (all_in_apper.find(keyword_lowcase) == std::wstring::npos) - { - return false; - } - } - if (o.expiration_time && current_time > o.timestamp && current_time - o.timestamp > o.expiration_time*SECONDS_IN_ONE_DAY) - return false; - - - return true; - } - //-------------------------------------------------------------------------------- - bool filter_offers_list(std::list& offers, const bc_services::core_offers_filter& filter, uint64_t current_core_time) - { -#ifndef ANDROID_BUILD - //filter - offers.remove_if([&](bc_services::offer_details_ex& o) -> bool { - return !is_offer_matched_by_filter(o, filter, current_core_time); - }); -#endif - //sort - CHECK_AND_ASSERT_MES(filter.order_by < gsort_offers_predicates.size(), false, "Wrong cof.order_by value"); - auto cb = *gsort_offers_predicates[static_cast(filter.order_by)]; - - //sort iterators in needed way - if (!filter.reverse) - { - offers.sort([&](const bc_services::offer_details_ex& a, const bc_services::offer_details_ex& b) - { - return cb(&a, &b); - }); - } - else - { - offers.sort([&](const bc_services::offer_details_ex& a, const bc_services::offer_details_ex& b) - { - return cb(&b, &a); - }); - } - - //now cut what not needed - auto it = std::next(offers.begin(), std::min(filter.offset, static_cast(offers.size()))); - offers.erase(offers.begin(), it); - // cut limit - it = std::next(offers.begin(), std::min(filter.limit, static_cast(offers.size()))); - offers.erase(it, offers.end()); - - return true; - } - //-------------------------------------------------------------------------------- - crypto::hash offer_id_from_hash_and_index(const crypto::hash& tx_id, uint64_t index) - { - crypto::hash r = tx_id; - //xor - *(uint64_t*)&r ^= index; - return r; - } - //--------------------------------------------------------------- - crypto::hash offer_id_from_hash_and_index(const offer_id& oid) - { - return offer_id_from_hash_and_index(oid.tx_id, oid.index); - } - //--------------------------------------------------------------- - const crypto::public_key get_offer_secure_key_by_index_from_tx(const currency::transaction& tx, size_t index) - { - size_t count = 0; - for (const auto& a : tx.attachment) - { - if (a.type() == typeid(currency::tx_service_attachment)) - { - const currency::tx_service_attachment& txsa = boost::get(a); - if (txsa.service_id == BC_OFFERS_SERVICE_ID) - { - if (count != index) - { - count++; - continue; - } - - if (txsa.security.empty()) - return currency::null_pkey; - return txsa.security.back(); - } - } - } - return currency::null_pkey; - } - - -} // namespace bc_services diff --git a/src/currency_core/offers_services_helpers.h b/src/currency_core/offers_services_helpers.h deleted file mode 100644 index 1484622..0000000 --- a/src/currency_core/offers_services_helpers.h +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Boolberry developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "profile_tools.h" -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" -#include "currency_basic.h" -#include "offers_service_basics.h" -#include "currency_protocol/blobdatatype.h" -#include "zlib_helper.h" -#include "bc_offers_service_basic.h" -#include "bc_attachments_helpers.h" - -namespace bc_services -{ - - - struct offer_id - { - crypto::hash tx_id; - uint64_t index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) - KV_SERIALIZE(index) - END_KV_SERIALIZE_MAP() - }; - -#define ORDER_BY_TIMESTAMP 0 -#define ORDER_BY_AMOUNT_PRIMARY 1 -#define ORDER_BY_AMOUNT_TARGET 2 -#define ORDER_BY_AMOUNT_RATE 3 -#define ORDER_BY_PAYMENT_TYPES 4 -#define ORDER_BY_CONTACTS 5 -#define ORDER_BY_LOCATION 6 -#define ORDER_BY_NAME 7 - -#define ORDER_CALLBACKS_COUNT 8 - - - typedef std::wstring(*to_low_case_ptr_type)(const std::wstring& soruce); - - void set_external_to_low_converter(to_low_case_ptr_type cb); - - typedef bool(*sort_offers_func_type)(const offer_details_ex* a, const offer_details_ex* b); - extern std::vector gsort_offers_predicates; - bool is_offer_matched_by_filter(const offer_details_ex& o, const core_offers_filter& of, uint64_t currnet_time); - bool filter_offers_list(std::list& offers, const core_offers_filter& filter, uint64_t current_core_time); - crypto::hash offer_id_from_hash_and_index(const crypto::hash& tx_id, uint64_t index); - crypto::hash offer_id_from_hash_and_index(const offer_id& oid); - const crypto::public_key get_offer_secure_key_by_index_from_tx(const currency::transaction& tx, size_t index); - - inline double calculate_offer_rate(const offer_details& od) - { - return od.amount_primary > 0 ? static_cast(od.amount_target) / od.amount_primary : 0; - } - - template - void put_offer_into_attachment(const offer_instruction_t& oi, std::vector& att_container) - { - std::string json_buff; - currency::tx_service_attachment att = AUTO_VAL_INIT(att); - - bool r = bc_services::pack_attachment_as_gzipped_json(oi, att); - CHECK_AND_ASSERT_MES(r, void(), "Failed to pack_attachment_as_gzipped_json"); - - att.service_id = BC_OFFERS_SERVICE_ID; - if (typeid(offer_instruction_t) == typeid(offer_details)) - { - att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_ADD; - } - else if (typeid(offer_instruction_t) == typeid(update_offer)) - { - att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_UPD; - } - else if (typeid(offer_instruction_t) == typeid(cancel_offer)) - { - att.instruction = BC_OFFERS_SERVICE_INSTRUCTION_DEL; - } - else - { - LOG_ERROR("Filed to pack tx_service_attachment in bc_offers_service, unknown_type: " << typeid(offer_instruction_t).name()); - return; - } - - //if att.security vector contain public_key then transaction constructor put there correct public_key related with one time transaction keys - if (att.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD || att.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD) - att.security.push_back(currency::null_pkey); - - att_container.push_back(att); - } - - inline currency::blobdata make_offer_sig_blob(const update_offer& uo) - { - currency::blobdata bd; - epee::string_tools::append_pod_to_strbuff(bd, uo.tx_id); - epee::string_tools::append_pod_to_strbuff(bd, uo.offer_index); - bd += epee::serialization::store_t_to_binary(uo.of); - return bd; - } - - inline currency::blobdata make_offer_sig_blob(const cancel_offer& co) - { - currency::blobdata bd; - epee::string_tools::append_pod_to_strbuff(bd, co.tx_id); - epee::string_tools::append_pod_to_strbuff(bd, co.offer_index); - return bd; - } - - //---------------------------------------------------------------------------------------------------- - template - bool extract_type_and_add(const std::string& body, t_srv_attachments_container& srv_cnt) - { - std::string json_buff; - if (!epee::zlib_helper::unpack(body, json_buff)) - { - LOG_ERROR("Filed to unpack tx_service_attachment in bc_offers_service, tx_id"); - return false; - } - t_contained_type obj = AUTO_VAL_INIT(obj); - bool r = epee::serialization::load_t_from_json(obj, json_buff); - if (!r) - { - LOG_ERROR("Filed to load json from tx_service_attachment in bc_offers_service, body: " << body); - return false; - } - srv_cnt.push_back(obj); - return true; - } - //---------------------------------------------------------------------------------------------------- - template - void extract_market_instructions(t_srv_attachments_container& cnt, const t_tx_attachments_container& raw_att) - { - PROFILE_FUNC("bc_service::extract_market_instructions"); - for (auto& att : raw_att) - { - if (att.type() == typeid(currency::tx_service_attachment)) - { - const currency::tx_service_attachment& sa = boost::get(att); - if (sa.service_id == BC_OFFERS_SERVICE_ID) - { - if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_ADD) - { - extract_type_and_add(sa.body, cnt); - } - else if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_UPD) - { - extract_type_and_add(sa.body, cnt); - } - else if (sa.instruction == BC_OFFERS_SERVICE_INSTRUCTION_DEL) - { - extract_type_and_add(sa.body, cnt); - } - } - } - } - } - - - - -#define OFFER_TYPE_PRIMARY_TO_TARGET 0 -#define OFFER_TYPE_TARGET_TO_PRIMARY 1 -#define OFFER_TYPE_GOODS_TO_PRIMARY 2 -#define OFFER_TYPE_PRIMARY_TO_GOODS 3 - -#define OFFER_TYPE_MASK_PRIMARY_TO_TARGET 0x00000001 -#define OFFER_TYPE_MASK_TARGET_TO_PRIMARY 0x00000002 -#define OFFER_TYPE_MASK_GOODS_TO_PRIMARY 0x00000004 -#define OFFER_TYPE_MASK_PRIMARY_TO_GOODS 0x00000008 - -#define OFFER_TYPE_UNDEFINED 255 - - - struct offer_details_ex_with_hash : public offer_details_ex - { - crypto::hash h; - mutable std::string nxt_offer; //in case of updated offer - }; - - typedef offer_details_ex_with_hash odeh; - - inline crypto::hash extract_id(const odeh& v) { return v.h; } - inline uint64_t extrct_timestamp(const odeh& v) { return v.timestamp; } - inline uint64_t extract_amount_primary(const odeh& v) { return v.amount_primary; } - inline uint64_t extract_amount_target(const odeh& v) { return v.amount_target; } - inline double extract_rate(const odeh& v) { return calculate_offer_rate(v); } - inline size_t extract_payment_types(const odeh& v) { return v.payment_types.size(); } - inline std::string extract_contacts(const odeh& v) { return v.contacts; } - inline std::string extract_location(const odeh& v) { - -#ifndef ANDROID_BUILD - return currency::utf8_to_lower(v.location_country + v.location_city); -#else - return "UNSUPORTED"; -#endif - } - inline std::string extract_name(const odeh& v) { -#ifndef ANDROID_BUILD - return currency::utf8_to_lower(v.target); -#else - return "UNSUPORTED"; -#endif - } - - template - struct sort_id_to_type - {}; - -#define TAG_NAME(tag_name) struct tag_name{}; - TAG_NAME(by_id); - TAG_NAME(by_timestamp); - TAG_NAME(by_amount_primary); - TAG_NAME(by_amount_target); - TAG_NAME(by_rate); - TAG_NAME(by_payment_types); - TAG_NAME(by_contacts); - TAG_NAME(by_location); - TAG_NAME(by_name); -#undef TAG_NAME - - template<> struct sort_id_to_type { typedef by_timestamp index_type; }; - template<> struct sort_id_to_type { typedef by_amount_primary index_type; }; - template<> struct sort_id_to_type { typedef by_amount_target index_type; }; - template<> struct sort_id_to_type { typedef by_rate index_type; }; - template<> struct sort_id_to_type { typedef by_payment_types index_type; }; - template<> struct sort_id_to_type { typedef by_contacts index_type; }; - template<> struct sort_id_to_type { typedef by_location index_type; }; - template<> struct sort_id_to_type { typedef by_name index_type; }; -} diff --git a/src/currency_core/scratchpad_helper.cpp b/src/currency_core/scratchpad_helper.cpp deleted file mode 100644 index b52e967..0000000 --- a/src/currency_core/scratchpad_helper.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project - -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#include "scratchpad_helper.h" -#include "currency_format_utils.h" - - - -namespace currency -{ - scratchpad_keeper::scratchpad_keeper():m_seed(null_hash) - { - - } - //------------------------------------------------------------------------------------ - bool scratchpad_keeper::generate(const crypto::hash& scr_seed, uint64_t height) - { - bool r = false; - CRITICAL_REGION_BEGIN(m_lock); - r = crypto::generate_scratchpad(scr_seed, m_scratchpad, get_scratchpad_size_for_height(height)); - if (r) - m_seed = scr_seed; - CRITICAL_REGION_END(); - return r; - } - //------------------------------------------------------------------------------------ - crypto::hash scratchpad_keeper::get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& scr_seed) - { - CRITICAL_REGION_LOCAL(m_lock); - crypto::hash res_hash = null_hash; - if (scr_seed != m_seed || get_scratchpad_size_for_height(height) != this->size()) - { - bool r = generate(scr_seed, height); - CHECK_AND_ASSERT_THROW_MES(r, "Unable to generate scratchpad"); - } - CHECK_AND_ASSERT_THROW_MES(get_scratchpad_size_for_height(height) == this->size(), "Fatal error on hash calculation: scratchpad_size=" << m_scratchpad.size() << " at height=" << height << ", scr_seed=" << scr_seed << ", m_seed=" << m_seed); - CHECK_AND_ASSERT_THROW_MES(scr_seed == m_seed, "Fatal error on hash calculation: scratchpad_seed missmatch scr_seed=" << scr_seed << ", m_seed=" << m_seed); - - bool res = get_wild_keccak2(bd, res_hash, m_scratchpad); - CHECK_AND_ASSERT_THROW_MES(res, "Fatal error on hash calculation: scratchpad_size=" << m_scratchpad.size()); - return res_hash; - } - //------------------------------------------------------------------------------------ - - //------------------------------------------------------------------------------------ - uint64_t scratchpad_keeper::size() - { - return m_scratchpad.size(); - } - //------------------------------------------------------------------------------------ - crypto::hash scratchpad_light_pool::get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed) - { - CRITICAL_REGION_LOCAL(m_lock); - std::shared_ptr> pscr_light; - if (!m_scratchpad_pools.get(seed, pscr_light)) - { - LOG_PRINT_MAGENTA("Generating scratchpad light for " << seed << "["<< height <<"]", LOG_LEVEL_0); - pscr_light.reset(new std::vector()); - bool r = crypto::generate_scratchpad_light(seed, *pscr_light, currency::get_scratchpad_size_for_height(height)); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate_scratchpad_light"); - m_scratchpad_pools.set(seed, pscr_light); - LOG_PRINT_MAGENTA("Generated ok", LOG_LEVEL_0); - } - CHECK_AND_ASSERT_THROW_MES(pscr_light->size()*10 == currency::get_scratchpad_size_for_height(height), - "Wrong size of cached scratchpad = " << pscr_light->size() << ", expected " << currency::get_scratchpad_size_for_height(height) << " for height " << height); - crypto::hash res = currency::null_hash; - bool r = crypto::get_wild_keccak_light(bd, res, *pscr_light); - CHECK_AND_ASSERT_THROW_MES(r, "Failed to get_wild_keccak_light"); - return res; - } - //------------------------------------------------------------------------------------ -} - diff --git a/src/currency_core/scratchpad_helper.h b/src/currency_core/scratchpad_helper.h deleted file mode 100644 index 515acd5..0000000 --- a/src/currency_core/scratchpad_helper.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "crypto/wild_keccak.h" -#include "currency_protocol/blobdatatype.h" -#include "currency_core/currency_basic.h" -#include "cache_helper.h" -#include "currency_core/currency_format_utils.h" -#include "currency_core/currency_format_utils_blocks.h" - -namespace currency -{ - template - class scratchpad_keeper_base - { - public: - crypto::hash get_pow_hash(const block& b, const crypto::hash& scr_seed) - { - blobdata bl = get_block_hashing_blob(b); - return static_cast(this)->get_pow_hash_from_blob(bl, get_block_height(b), scr_seed); - } - }; - - - class scratchpad_keeper: public scratchpad_keeper_base - { - public: - scratchpad_keeper(); - bool generate(const crypto::hash& seed, uint64_t height); - crypto::hash get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed); - uint64_t size(); - private: - scratchpad_keeper(const scratchpad_keeper&) {} - crypto::hash m_seed; - std::vector m_scratchpad; - std::recursive_mutex m_lock; - }; - - - class scratchpad_light_pool : public scratchpad_keeper_base - { - public: - scratchpad_light_pool() {} - crypto::hash get_pow_hash_from_blob(const blobdata& bd, uint64_t height, const crypto::hash& seed); - private: - //map of seed to - epee::misc_utils::cache_base>, 4> m_scratchpad_pools; - std::recursive_mutex m_lock; - }; - -} \ No newline at end of file diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp deleted file mode 100644 index 7a65990..0000000 --- a/src/currency_core/tx_pool.cpp +++ /dev/null @@ -1,1399 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include -#include - -#include "common/db_backend_selector.h" -#include "tx_pool.h" -#include "currency_boost_serialization.h" -#include "currency_core/currency_config.h" -#include "blockchain_storage.h" -#include "common/boost_serialization_helper.h" -#include "common/int-util.h" -#include "misc_language.h" -#include "warnings.h" -#include "crypto/hash.h" -#include "profile_tools.h" -#include "common/db_backend_selector.h" - -DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated - -#define TRANSACTION_POOL_CONTAINER_TRANSACTIONS "transactions" -#define TRANSACTION_POOL_CONTAINER_BLACK_TX_LIST "black_tx_list" -#define TRANSACTION_POOL_CONTAINER_ALIAS_NAMES "alias_names" -#define TRANSACTION_POOL_CONTAINER_ALIAS_ADDRESSES "alias_addresses" -#define TRANSACTION_POOL_CONTAINER_KEY_IMAGES "key_images" -#define TRANSACTION_POOL_CONTAINER_SOLO_OPTIONS "solo" -#define TRANSACTION_POOL_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 92 // DON'T CHANGE THIS, if you need to resync db! Change TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION instead! -#define TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 1 - - -#define CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL 50 // if there's a conflict in key images between tx in the pool and in the blockchain this much depth in required to remove correspongin tx from pool - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "tx_pool" -ENABLE_CHANNEL_BY_DEFAULT("tx_pool"); - -namespace currency -{ - //--------------------------------------------------------------------------------- - tx_memory_pool::tx_memory_pool(blockchain_storage& bchs, i_currency_protocol* pprotocol) : - m_blockchain(bchs), - m_pprotocol(pprotocol), - m_db(nullptr, m_dummy_rw_lock), - m_db_transactions(m_db), - m_db_black_tx_list(m_db), - m_db_solo_options(m_db), -// m_db_key_images_set(m_db), - m_db_alias_names(m_db), - m_db_alias_addresses(m_db), - m_db_storage_major_compatibility_version(TRANSACTION_POOL_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION, m_db_solo_options) - { - - } - - bool tx_memory_pool::is_valid_contract_finalization_tx(const transaction &tx)const - { - if (tx.vin.size() != 1 || tx.vin[0].type() != typeid(txin_multisig)) - { - return false; - } - - const txin_multisig& ms_in = boost::get(tx.vin[0]); - crypto::hash related_tx_id = null_hash; uint64_t out_no = 0; - if (!m_blockchain.get_multisig_id_details(ms_in.multisig_out_id, related_tx_id, out_no)) - { - LOG_ERROR("Related multisig tx not found, multisig_out_id=" << ms_in.multisig_out_id); - return false; - } - - auto related_tx_ptr = m_blockchain.get_tx_chain_entry(related_tx_id); - if (!related_tx_ptr) - { - LOG_ERROR("Tx " << related_tx_id << " related to multisig id " << ms_in.multisig_out_id - << "(discovered by reviewing tx " << get_transaction_hash(tx) <<") tx not found in blockchain, multisig_out_id=" << ms_in.multisig_out_id); - return false; - } - - if (get_tx_fee(tx) < get_tx_fee(related_tx_ptr->tx)) - { - LOG_ERROR("Tx " << get_transaction_hash(tx) << " fee=" << get_tx_fee(tx) << " less then parent multisig tx " << related_tx_id << " fee= " << get_tx_fee(related_tx_ptr->tx)); - return false; - } - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core) - { - if (!kept_by_block && !from_core && m_blockchain.is_in_checkpoint_zone()) - { - // BCS is in CP zone, tx verification is impossible until it gets synchronized - tvc.m_added_to_pool = false; - tvc.m_should_be_relayed = false; - tvc.m_verification_failed = false; - tvc.m_verification_impossible = true; - return false; - } - - if (!m_blockchain.validate_tx_for_hardfork_specific_terms(tx, id)) - { - // - LOG_ERROR("Transaction " << id <<" doesn't fit current hardfork"); - tvc.m_verification_failed = true; - return false; - } - - TIME_MEASURE_START_PD(tx_processing_time); - TIME_MEASURE_START_PD(check_inputs_types_supported_time); - if(!check_inputs_types_supported(tx)) - { - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(check_inputs_types_supported_time); - - TIME_MEASURE_START_PD(expiration_validate_time); - if (!from_core && !kept_by_block && m_blockchain.is_tx_expired(tx)) - { - uint64_t tx_expiration_time = get_tx_expiration_time(tx); - uint64_t ts_median = m_blockchain.get_tx_expiration_median(); - LOG_PRINT_L0("transaction " << id << " is expired, rejected by tx pool (tx timestamp: " << tx_expiration_time << " - " << TX_EXPIRATION_MEDIAN_SHIFT << " (median shift) = " << - tx_expiration_time - TX_EXPIRATION_MEDIAN_SHIFT << ", blockchain timestamp median: " << ts_median << - ", diff: " << epee::misc_utils::get_time_interval_string(ts_median + TX_EXPIRATION_MEDIAN_SHIFT - tx_expiration_time) << ")"); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(expiration_validate_time); - - TIME_MEASURE_START_PD(validate_amount_time); - uint64_t inputs_amount = 0; - if(!get_inputs_money_amount(tx, inputs_amount)) - { - tvc.m_verification_failed = true; - return false; - } - - CHECK_AND_ASSERT_MES_CUSTOM(tx.vout.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, tvc.m_verification_failed = true, "transaction has too many outs = " << tx.vout.size()); - - uint64_t outputs_amount = get_outs_money_amount(tx); - - if(outputs_amount > inputs_amount) - { - LOG_PRINT_L0("transaction use more money then it has: use " << outputs_amount << ", have " << inputs_amount); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(validate_amount_time); - - TIME_MEASURE_START_PD(validate_alias_time); - if (!from_core && !validate_alias_info(tx, kept_by_block)) - { - LOG_PRINT_RED_L0("validate_alias_info failed"); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(validate_alias_time); - - TIME_MEASURE_START_PD(check_keyimages_ws_ms_time); - //check key images for transaction if it is not kept by block - if(!from_core && !kept_by_block) - { - crypto::key_image spent_ki = AUTO_VAL_INIT(spent_ki); - if(have_tx_keyimges_as_spent(tx, &spent_ki)) - { - LOG_ERROR("Transaction " << id << " uses already spent key image " << spent_ki); - tvc.m_verification_failed = true; - return false; - } - - //transaction spam protection, soft rule - uint64_t tx_fee = inputs_amount - outputs_amount; - if (tx_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee) - { - if (is_valid_contract_finalization_tx(tx)) - { - // that means tx has less fee then allowed by current tx pull rules, but this transaction is actually - // a finalization of contract, and template of this contract finalization tx was prepared actually before - // fee rules had been changed, so it's ok, let it in. - } - else - { - // this tx has no fee - LOG_PRINT_RED_L0("Transaction with id= " << id << " has too small fee: " << tx_fee << ", expected fee: " << m_blockchain.get_core_runtime_config().tx_pool_min_fee); - tvc.m_verification_failed = false; - tvc.m_should_be_relayed = false; - tvc.m_added_to_pool = false; - return true; - } - } - - // check tx multisig inputs/output against tx in the pool and in the blockchain - if (!check_tx_multisig_ins_and_outs(tx, true)) - { - tvc.m_verification_failed = true; - return false; - } - } - TIME_MEASURE_FINISH_PD(check_keyimages_ws_ms_time); - - TIME_MEASURE_START_PD(check_inputs_time); - crypto::hash max_used_block_id = null_hash; - uint64_t max_used_block_height = 0; - bool ch_inp_res = m_blockchain.check_tx_inputs(tx, id, max_used_block_height, max_used_block_id); - if (!ch_inp_res && !kept_by_block && !from_core) - { - LOG_PRINT_L0("tx used wrong inputs, rejected"); - tvc.m_verification_failed = true; - return false; - } - TIME_MEASURE_FINISH_PD(check_inputs_time); - - do_insert_transaction(tx, id, blob_size, kept_by_block, inputs_amount - outputs_amount, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0); - - TIME_MEASURE_FINISH_PD(tx_processing_time); - tvc.m_added_to_pool = true; - tvc.m_should_be_relayed = ch_inp_res; // relay tx only if it has valid inputs (i.e. do not relay kept_by_block tx with wrong inputs) - tvc.m_verification_impossible = !ch_inp_res; // mark 'kept_by_block' tx with wrong inputs as impossible to be verified - tvc.m_verification_failed = false; - //succeed - - LOG_PRINT_L2("[TX_POOL ADD_TX] timing(micsec) : " << print_fixed_decimal_point(tx_processing_time, 3) - << "("<< m_performance_data.check_inputs_types_supported_time.get_last_val() - << "/" << m_performance_data.expiration_validate_time.get_last_val() - << "/" << m_performance_data.validate_amount_time.get_last_val() - << "/" << m_performance_data.validate_alias_time.get_last_val() - << "/" << m_performance_data.check_keyimages_ws_ms_time.get_last_val() - << "/" << m_performance_data.check_inputs_time.get_last_val() - << "/" << m_performance_data.begin_tx_time.get_last_val() - << "/" << m_performance_data.update_db_time.get_last_val() - << "/" << m_performance_data.db_commit_time.get_last_val() << ")" ); - - return true; - } - //--------------------------------------------------------------------------------- -#define LOCAL_READONLY_TRANSACTION() \ - m_db.begin_readonly_transaction(); \ - misc_utils::auto_scope_leave_caller db_tx_closer = misc_utils::create_scope_leave_handler([&]() \ - { \ - m_db.commit_transaction(); \ - }); - - - bool tx_memory_pool::do_insert_transaction(const transaction &tx, const crypto::hash &id, uint64_t blob_size, bool kept_by_block, uint64_t fee, const crypto::hash& max_used_block_id, uint64_t max_used_block_height) - { - TIME_MEASURE_START_PD(begin_tx_time); - m_db.begin_transaction(); - TIME_MEASURE_FINISH_PD(begin_tx_time); - - TIME_MEASURE_START_PD(update_db_time); - misc_utils::auto_scope_leave_caller seh = misc_utils::create_scope_leave_handler([&]() - { - TIME_MEASURE_START_PD(db_commit_time); - m_db.commit_transaction(); - TIME_MEASURE_FINISH_PD(db_commit_time); - - }); - //CHECK_AND_ASSERT_MES_CUSTOM(!m_db_transactions.get(id), false, (tvc.m_added_to_pool = false, tvc.m_verification_failed = true), "internal error: failed to add transaction " << id << " to the pool as it already exists"); - tx_details td = AUTO_VAL_INIT(td); - td.blob_size = blob_size; - td.tx = tx; - td.kept_by_block = kept_by_block; - td.fee = fee; - td.max_used_block_id = max_used_block_id; - td.max_used_block_height = max_used_block_height; - td.last_failed_height = 0; - td.last_failed_id = null_hash; - td.receive_time = get_core_time(); - - m_db_transactions.set(id, td); - on_tx_add(id, tx, kept_by_block); - - TIME_MEASURE_FINISH_PD(update_db_time); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::check_is_taken(const crypto::hash& id) const - { - CRITICAL_REGION_LOCAL(m_taken_txs_lock); - return m_taken_txs.count(id) ? true : false; - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::set_taken(const crypto::hash& id) - { - CRITICAL_REGION_LOCAL(m_taken_txs_lock); - m_taken_txs.insert(id); - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::reset_all_taken() - { - CRITICAL_REGION_LOCAL(m_taken_txs_lock); - m_taken_txs.clear(); - } -//--------------------------------------------------------------------------------- - bool tx_memory_pool::get_aliases_from_tx_pool(std::list& aliases)const - { - - //TODO: OPTIMIZATION put cache here!!!!! - - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx_entry.tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra on unprocess_blockchain_tx_extra"); - if (ei.m_alias.m_alias.size()) - aliases.push_back(ei.m_alias); - - return true; - }); - return true; - - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_aliases_from_tx_pool(std::map& aliases)const - { - std::list aliases_local; - get_aliases_from_tx_pool(aliases_local); - - for (auto& alias_info : aliases_local) - { - ++aliases[alias_info.m_alias]; - } - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::validate_alias_info(const transaction& tx, bool is_in_block) const - { - LOCAL_READONLY_TRANSACTION(); - extra_alias_entry eai = AUTO_VAL_INIT(eai); - - bool r = false; - bool found = handle_2_alternative_types_in_variant_container(tx.extra, [this, &r, &tx, is_in_block](const extra_alias_entry& eai) { - //check in blockchain - extra_alias_entry eai2 = AUTO_VAL_INIT(eai2); - bool already_have_alias_registered = m_blockchain.get_alias_info(eai.m_alias, eai2); - //size_t alias_size = eai.m_alias.size(); - - if (!is_in_block && !eai.m_sign.size() && already_have_alias_registered) - { - LOG_PRINT_L0("Alias \"" << eai.m_alias << "\" already registered in blockchain, transaction rejected"); - r = false; - return false; // stop handling - } - - std::string prev_alias = m_blockchain.get_alias_by_address(eai.m_address); - if (!is_in_block && !eai.m_sign.size() && - prev_alias.size()) - { - LOG_PRINT_L0("Address \"" << get_account_address_as_str(eai.m_address) - << "\" already registered with \""<< prev_alias - << "\" alias in blockchain (new alias: \"" << eai.m_alias << "\"), transaction rejected"); - r = false; - return false; // stop handling - } - - if (!is_in_block) - { - if (m_db_alias_names.get(eai.m_alias)) - { - LOG_PRINT_L0("Alias \"" << eai.m_alias << "\" already in transaction pool, transaction rejected"); - r = false; - return false; // stop handling - } - if (m_db_alias_addresses.get(eai.m_address)) - { - LOG_PRINT_L0("Alias \"" << eai.m_alias << "\" already in transaction pool by it's address(" << get_account_address_as_str(eai.m_address) << ") , transaction rejected"); - r = false; - return false; // stop handling - } - //validate alias reward - if (!m_blockchain.prevalidate_alias_info(tx, eai)) - { - LOG_PRINT_L0("Alias \"" << eai.m_alias << "\" reward validation failed, transaction rejected"); - r = false; - return false; // stop handling - } - } - - r = true; - return true; // continue handling - }); - - return !found || r; // if found, r must be true for success - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const transaction &tx, tx_verification_context& tvc, bool kept_by_block, bool from_core) - { - crypto::hash h = null_hash; - uint64_t blob_size = 0; - - get_transaction_hash(tx, h, blob_size); - return add_tx(tx, h, blob_size, tvc, kept_by_block, from_core); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee) - { - - m_db_transactions.begin_transaction(); - misc_utils::auto_scope_leave_caller seh = misc_utils::create_scope_leave_handler([&](){m_db_transactions.commit_transaction();}); - - auto txe_tr = m_db_transactions.find(id); - if (txe_tr == m_db_transactions.end()) - return false; - - tx = txe_tr->tx; - blob_size = txe_tr->blob_size; - fee = txe_tr->fee; - m_db_transactions.erase(id); - on_tx_remove(id, tx, txe_tr->kept_by_block); - set_taken(id); - return true; - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::on_idle() - { - m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();}); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::remove_stuck_transactions() - { - if (!CRITICAL_SECTION_TRY_LOCK(m_remove_stuck_txs_lock)) - return true; - - CRITICAL_REGION_LOCAL(m_remove_stuck_txs_lock); - CRITICAL_SECTION_UNLOCK(m_remove_stuck_txs_lock);// release try_lock iteration - - m_db_transactions.begin_transaction(); - misc_utils::auto_scope_leave_caller seh = misc_utils::create_scope_leave_handler([&](){m_db_transactions.commit_transaction(); }); - - struct tx_to_delete_entry - { - tx_to_delete_entry(const crypto::hash &hash, const transaction &tx, bool kept_by_block) - : hash(hash), tx(tx), kept_by_block(kept_by_block) - {} - crypto::hash hash; - transaction tx; - bool kept_by_block; - }; - - std::vector to_delete; - - const uint64_t tx_expiration_ts_median = m_blockchain.get_tx_expiration_median(); - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - //never remove transactions which related to alt blocks, - //or we can get network split as a worst case (impossible to switch to - //altchain if it won, and node stuck forever). - if (m_blockchain.is_tx_related_to_altblock(h)) - return true; - - // maximum age check - remove too old - int64_t tx_age = get_core_time() - tx_entry.receive_time; - if ((tx_age > CURRENCY_MEMPOOL_TX_LIVETIME )) - { - LOG_PRINT_L0("tx " << h << " is about to be removed from tx pool, reason: outdated, age: " << tx_age << " = " << misc_utils::get_time_interval_string(tx_age)); - to_delete.push_back(tx_to_delete_entry(h, tx_entry.tx, tx_entry.kept_by_block)); - } - - // expiration time check - remove expired - if (is_tx_expired(tx_entry.tx, tx_expiration_ts_median) ) - { - LOG_PRINT_L0("tx " << h << " is about to be removed from tx pool, reason: expired, expiration time: " << get_tx_expiration_time(tx_entry.tx) << ", blockchain median: " << tx_expiration_ts_median); - to_delete.push_back(tx_to_delete_entry(h, tx_entry.tx, tx_entry.kept_by_block)); - } - - // if a tx has at least one key image already used in blockchain (deep enough) -- remove such tx, as it cannot be added to any block - // although it will be removed by the age check above, we consider desireable - // to remove it from the pool faster in order to unblock related key images used in the same tx - uint64_t should_be_spent_before_height = m_blockchain.get_current_blockchain_size() - 1; - if (should_be_spent_before_height > CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL) - { - should_be_spent_before_height -= CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL; - for (auto& in : tx_entry.tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - // if at least one key image is spent deep enought -- remove such tx - const crypto::key_image& ki = boost::get(in).k_image; - if (m_blockchain.have_tx_keyimg_as_spent(ki, should_be_spent_before_height)) - { - LOG_PRINT_L0("tx " << h << " is about to be removed from tx pool, reason: ki was spent in the blockchain before height " << should_be_spent_before_height << ", tx age: " << misc_utils::get_time_interval_string(tx_age)); - to_delete.push_back(tx_to_delete_entry(h, tx_entry.tx, tx_entry.kept_by_block)); - return true; - } - } - } - } - - - return true; - }); - - for (auto& e : to_delete) - { - m_db_transactions.erase(e.hash); - on_tx_remove(e.hash, e.tx, e.kept_by_block); - } - - - return true; - } - //--------------------------------------------------------------------------------- - size_t tx_memory_pool::get_transactions_count() const - { - return m_db_transactions.size(); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transactions(std::list& txs) const - { - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - txs.push_back(tx_entry.tx); - return true; - }); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_all_transactions_details(std::list& txs) const - { - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - txs.push_back(tx_rpc_extended_info()); - tx_rpc_extended_info& trei = txs.back(); - trei.blob_size = tx_entry.blob_size; - fill_tx_rpc_details(trei, tx_entry.tx, nullptr, h, tx_entry.receive_time, true); - return true; - }); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_all_transactions_brief_details(std::list& txs) const - { - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - txs.push_back(tx_rpc_brief_info()); - tx_rpc_brief_info& trbi = txs.back(); - trbi.id = epee::string_tools::pod_to_hex(h); - trbi.fee = tx_entry.fee; - trbi.sz = tx_entry.blob_size; - trbi.total_amount = get_outs_money_amount(tx_entry.tx); - return true; - }); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_all_transactions_list(std::list& txs)const - { - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - txs.push_back(epee::string_tools::pod_to_hex(h)); - return true; - }); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transactions_details(const std::list& ids, std::list& txs) const - { - for (auto& id_str: ids) - { - crypto::hash id = null_hash; - if (!epee::string_tools::hex_to_pod(id_str, id)) - { - LOG_ERROR("Failed to parse id in list: " << id_str); - return false; - } - - auto ptei = m_db_transactions.get(id); - if (!ptei) - return false; - - txs.push_back(tx_rpc_extended_info()); - tx_rpc_extended_info& trei = txs.back(); - trei.blob_size = ptei->blob_size; - fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false); - } - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transactions_brief_details(const std::list& ids, std::list& txs)const - { - LOCAL_READONLY_TRANSACTION(); - for (auto& id_str : ids) - { - crypto::hash id = null_hash; - if (!epee::string_tools::hex_to_pod(id_str, id)) - { - LOG_ERROR("Failed to parse id in list: " << id_str); - return false; - } - - auto ptei = m_db_transactions.get(id); - if (!ptei) - return false; - - txs.push_back(tx_rpc_brief_info()); - tx_rpc_brief_info& trbi = txs.back(); - trbi.sz = ptei->blob_size; - trbi.id = id_str; - trbi.fee = ptei->fee; - trbi.total_amount = get_outs_money_amount(ptei->tx); - } - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transaction_details(const crypto::hash& id, tx_rpc_extended_info& trei) const - { - auto ptei = m_db_transactions.get(id); - if (!ptei) - return false; - - fill_tx_rpc_details(trei, ptei->tx, nullptr, id, ptei->receive_time, false); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transaction(const crypto::hash& id, transaction& tx) const - { - auto tx_ptr = m_db_transactions.find(id); - if (tx_ptr == m_db_transactions.end()) - return false; - tx = tx_ptr->tx; - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_transaction(const crypto::hash& id, tx_details& txd) const - { - auto tx_ptr = m_db_transactions.find(id); - if (tx_ptr == m_db_transactions.end()) - return false; - txd = *tx_ptr; - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id, const std::list& bsk) - { - - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id) - { - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::on_finalize_db_transaction() - { - reset_all_taken(); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::set_protocol(i_currency_protocol* pprotocol) - { - m_pprotocol = pprotocol; - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::force_relay_pool() const - { - LOG_PRINT_GREEN("Preparing relay message...", LOG_LEVEL_0); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); - - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& k, const tx_details& v) - { - r.txs.push_back(t_serializable_object_to_blob(v.tx)); - return true; - }); - LOG_PRINT_GREEN("Sending....", LOG_LEVEL_0); - CHECK_AND_ASSERT_MES(m_pprotocol, false, "m_pprotocol is not set"); - currency_connection_context fake_context = AUTO_VAL_INIT(fake_context); - m_pprotocol->relay_transactions(r, fake_context); - LOG_PRINT_GREEN("Sent.", LOG_LEVEL_0); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_transaction_to_black_list(const transaction& tx) - { - // atm: - // 1) the only side effect of a tx being blacklisted is the one is just ignored by fill_block_template(), but it still can be added to blockchain/pool - // 2) it's permanent - LOG_PRINT_YELLOW("TX ADDED TO POOL'S BLACKLIST: " << get_transaction_hash(tx), LOG_LEVEL_0); - m_db.begin_transaction(); - m_db_black_tx_list.set(get_transaction_hash(tx), true); - m_db.commit_transaction(); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_tx(const crypto::hash &id) const - { - if(m_db_transactions.get(id)) - return true; - - if (check_is_taken(id)) - return true; - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_tx_keyimges_as_spent(const transaction& tx, crypto::key_image* p_spent_ki /* = nullptr */) const - { - for(const auto& in : tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, true);//should never fail - if (have_tx_keyimg_as_spent(tokey_in.k_image)) - { - if (p_spent_ki) - *p_spent_ki = tokey_in.k_image; - return true; - } - - } - } - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::insert_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block) - { - CRITICAL_REGION_LOCAL(m_key_images_lock); - for(const auto& in : tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - const txin_to_key& tokey_in = boost::get(in); - auto& id_set = m_key_images[tokey_in.k_image]; - size_t sz_before = id_set.size(); - id_set.insert(tx_id); - LOG_PRINT_L2("tx pool: key image added: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size()); - } - } - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block) - { - insert_key_images(tx_id, tx, kept_by_block); - insert_alias_info(tx); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::on_tx_remove(const crypto::hash &id, const transaction& tx, bool kept_by_block) - { - remove_key_images(id, tx, kept_by_block); - remove_alias_info(tx); - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::insert_alias_info(const transaction& tx) - { - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra on unprocess_blockchain_tx_extra"); - if (ei.m_alias.m_alias.size()) - { - m_db_alias_names.set(ei.m_alias.m_alias, true); - m_db_alias_addresses.set(ei.m_alias.m_address, true); - } - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::remove_alias_info(const transaction& tx) - { - - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra on unprocess_blockchain_tx_extra"); - if (ei.m_alias.m_alias.size()) - { - m_db_alias_names.erase(ei.m_alias.m_alias); - m_db_alias_addresses.erase(ei.m_alias.m_address); - } - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block) - { - CRITICAL_REGION_LOCAL(m_key_images_lock); - for(const auto& in : tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - const txin_to_key& tokey_in = boost::get(in); - - auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, tokey_in.k_image); - auto& id_set = it_map->second; - size_t count_before = id_set.size(); - auto it_set = id_set.find(tx_id); - if(it_set != id_set.end()) - id_set.erase(it_set); - - size_t count_after = id_set.size(); - if (id_set.size() == 0) - m_key_images.erase(it_map); - - LOG_PRINT_L2("tx pool: key image removed: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after); - } - } - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::get_key_images_from_tx_pool(key_image_cache& key_images) const - { - - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - for (auto& in : tx_entry.tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - key_images[boost::get(in).k_image].insert(h); - } - } - return true; - }); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_tx_keyimg_as_spent(const crypto::key_image& key_im)const - { - CRITICAL_REGION_LOCAL(m_key_images_lock); - auto it = m_key_images.find(key_im); - if (it != m_key_images.end()) - return true; - return false; - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::lock() - { - CRITICAL_SECTION_LOCK(m_remove_stuck_txs_lock); - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::unlock() - { - CRITICAL_SECTION_UNLOCK(m_remove_stuck_txs_lock); - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::purge_transactions() - { - - m_db.begin_transaction(); - m_db_transactions.clear(); - m_db.commit_transaction(); - // should m_db_black_tx_list be cleared here? - CIRITCAL_OPERATION(m_key_images,clear()); - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::clear() - { - m_db.begin_transaction(); - m_db_transactions.clear(); - m_db_black_tx_list.clear(); - m_db.commit_transaction(); - CIRITCAL_OPERATION(m_key_images,clear()); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::is_transaction_ready_to_go(tx_details& txd, const crypto::hash& id)const - { - //not the best implementation at this time, sorry :( - - if (m_db_black_tx_list.get(get_transaction_hash(txd.tx))) - return false; - - //check is ring_signature already checked ? - if(txd.max_used_block_id == null_hash) - {//not checked, lets try to check - - if(txd.last_failed_id != null_hash && m_blockchain.get_current_blockchain_size() > txd.last_failed_height && txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height)) - return false;//we already sure that this tx is broken for this height - - if(!m_blockchain.check_tx_inputs(txd.tx, id, txd.max_used_block_height, txd.max_used_block_id)) - { - txd.last_failed_height = m_blockchain.get_top_block_height(); - txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); - return false; - } - }else - { - if(txd.max_used_block_height >= m_blockchain.get_current_blockchain_size()) - return false; - if(m_blockchain.get_block_id_by_height(txd.max_used_block_height) != txd.max_used_block_id) - { - //if we already failed on this height and id, skip actual ring signature check - if(txd.last_failed_id == m_blockchain.get_block_id_by_height(txd.last_failed_height)) - return false; - //check ring signature again, it is possible (with very small chance) that this transaction become again valid - if(!m_blockchain.check_tx_inputs(txd.tx, id, txd.max_used_block_height, txd.max_used_block_id)) - { - txd.last_failed_height = m_blockchain.get_top_block_height(); - txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); - return false; - } - } - } - //if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure - if (m_blockchain.have_tx_keyimges_as_spent(txd.tx)) - { - return false; - } - - - if (!check_tx_multisig_ins_and_outs(txd.tx, false)) - return false; - - //transaction is ok. - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction& tx)const - { - LOCAL_READONLY_TRANSACTION(); - for(size_t i = 0; i!= tx.vin.size(); i++) - { - if (tx.vin[i].type() == typeid(txin_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false); - if (k_images.count(itk.k_image)) - return true; - } - } - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction& tx) - { - for(size_t i = 0; i!= tx.vin.size(); i++) - { - if (tx.vin[i].type() == typeid(txin_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false); - auto i_res = k_images.insert(itk.k_image); - CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << itk.k_image); - } - } - return true; - } - //--------------------------------------------------------------------------------- - std::string tx_memory_pool::print_pool(bool short_format)const - { - std::stringstream ss; - if (short_format) - { - std::list> txs; - { - - m_db_transactions.enumerate_items([&txs](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) { txs.push_back(std::make_pair(h, tx_entry)); return true; }); - } - if (txs.empty()) - return "(no transactions, the pool is empty)"; - // sort output by receive time - txs.sort([](const std::pair& lhs, const std::pair& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; }); - ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL; - // 1234 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES - size_t i = 0; - for (auto& tx : txs) - { - auto& txd = tx.second; - ss << std::left - << std::setw(4) << i++ << " " - << tx.first << " " - << std::setw(5) << txd.blob_size << " " - << std::setw(10) << print_money_brief(txd.fee) << " " - << std::setw(4) << txd.tx.vin.size() << " " - << std::setw(4) << txd.tx.vout.size() << " " - << std::right << std::setw(15) << print_money(get_outs_money_amount(txd.tx)) << std::left << " " - << std::setw(14) << epee::misc_utils::get_time_interval_string(get_core_time() - txd.receive_time) << " " - << std::setw(6) << txd.max_used_block_height << " " - << std::setw(9) << print16(txd.max_used_block_id) << " " - << std::setw(6) << txd.last_failed_height << " " - << std::setw(9) << print16(txd.last_failed_id) << " " - << (txd.kept_by_block ? "YES" : "no ") - << ENDL; - } - return ss.str(); - } - - // long format - - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - auto& txd = tx_entry; - ss << "id: " << h << ENDL - << obj_to_json_str(txd.tx) << ENDL - << "blob_size: " << txd.blob_size << ENDL - << "fee: " << txd.fee << ENDL - << "kept_by_block: " << (txd.kept_by_block ? "true" : "false") << ENDL - << "max_used_block_height: " << txd.max_used_block_height << ENDL - << "max_used_block_id: " << txd.max_used_block_id << ENDL - << "last_failed_height: " << txd.last_failed_height << ENDL - << "last_failed_id: " << txd.last_failed_id << ENDL - << "live_time: " << epee::misc_utils::get_time_interval_string(get_core_time() - txd.receive_time) << ENDL; - return true; - }); - - return ss.str(); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::fill_block_template(block &bl, - bool pos, - size_t median_size, - const boost::multiprecision::uint128_t& already_generated_coins, - size_t &total_size, - uint64_t &fee, - uint64_t height, - const std::list& explicit_txs - ) - { - LOCAL_READONLY_TRANSACTION(); - //typedef transactions_container::value_type txv; - typedef std::pair > txv; - - - std::vector txs_v; - txs_v.reserve(m_db_transactions.size()); - std::vector txs; // selected transactions, vector of indices of txs_v - - - //keep getting it as a values cz db items cache will keep it as unserialised object stored by shared ptrs - m_db_transactions.enumerate_keys([&](uint64_t i, crypto::hash& k){txs_v.resize(i + 1); txs_v[i].first = k; return true;}); - txs.resize(txs_v.size(), SIZE_MAX); - - for (uint64_t i = 0; i != txs_v.size(); i++) - { - auto& k = txs_v[i].first; - txs_v[i].second = m_db_transactions.get(k); - if (!txs_v[i].second) - { - LOG_ERROR("Internal tx pool db error: key " << k << " was enumerated as key but couldn't get value"); - return false; - } - txs[i] = i; - } - - - - std::sort(txs.begin(), txs.end(), [&txs_v](size_t a, size_t b) -> bool { - boost::multiprecision::uint128_t a_, b_; - a_ = boost::multiprecision::uint128_t(txs_v[a].second->fee) * txs_v[b].second->blob_size; - b_ = boost::multiprecision::uint128_t(txs_v[b].second->fee) * txs_v[a].second->blob_size; - return a_ > b_; - }); - - - size_t explicit_total_size = get_objects_blobsize(explicit_txs); - size_t current_size = explicit_total_size; - uint64_t current_fee = 0; - uint64_t best_money; - if (!get_block_reward(pos, median_size, CURRENCY_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, best_money, height)) { - LOG_ERROR("Block with just a miner transaction is already too large!"); - return false; - } - size_t best_position = 0; - total_size = 0; - fee = 0; - uint64_t alias_count = 0; - - // scan txs for alias reg requests - if there are such requests, don't process alias updates - bool alias_regs_exist = false; - for (auto txi : txs) - { - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(txs_v[txi].second->tx, ei); - CHECK_AND_ASSERT_MES(r, false, "parse_and_validate_tx_extra failed while looking up the tx pool"); - if (!ei.m_alias.m_alias.empty() && !ei.m_alias.m_sign.size()) { - alias_regs_exist = true; - break; - } - } - - const uint64_t tx_expiration_ts_median = m_blockchain.get_tx_expiration_median(); - - std::unordered_set k_images; - - for (size_t i = 0; i < txs.size(); i++) - { - txv &tx(txs_v[txs[i]]); - - // expiration time check -- skip expired transactions - if (is_tx_expired(tx.second->tx, tx_expiration_ts_median)) - { - txs[i] = SIZE_MAX; - continue; - } - - // alias checks - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx.second->tx, ei); - CHECK_AND_ASSERT_MES(r, false, "failed to validate transaction extra on unprocess_blockchain_tx_extra"); - if (!ei.m_alias.m_alias.empty()) - { - bool update_an_alias = !ei.m_alias.m_sign.empty(); - if ((alias_count >= MAX_ALIAS_PER_BLOCK) || // IF this tx registers/updates an alias AND alias per block threshold exceeded - (update_an_alias && alias_regs_exist)) // OR this tx updates an alias AND there are alias reg requests... - { - txs[i] = SIZE_MAX; // ...skip this tx - continue; - } - } - - //is_transaction_ready_to_go can change tx_details in case of some errors, so we make local copy, - //do check if it's changed and reassign it to db if needed - tx_details local_copy_txd = *(tx.second); - bool is_tx_ready_to_go_result = is_transaction_ready_to_go(local_copy_txd, tx.first); - if (!is_tx_ready_to_go_result && - (local_copy_txd.last_failed_height != tx.second->last_failed_height || local_copy_txd.last_failed_id != tx.second->last_failed_id)) - { - m_db_transactions.begin_transaction(); - m_db_transactions.set(get_transaction_hash(local_copy_txd.tx), local_copy_txd); - m_db_transactions.commit_transaction(); - } - - if (!is_tx_ready_to_go_result || have_key_images(k_images, tx.second->tx)) { - txs[i] = SIZE_MAX; - continue; - } - append_key_images(k_images, tx.second->tx); - - current_size += tx.second->blob_size; - current_fee += tx.second->fee; - - uint64_t current_reward; - if (!get_block_reward(pos, median_size, current_size + CURRENCY_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, current_reward, height)) - { - break; // current block size is too big - } - - if (best_money < current_reward + current_fee) { - best_money = current_reward + current_fee; - best_position = i + 1; - total_size = current_size; - fee = current_fee; - } - - if (!ei.m_alias.m_alias.empty()) - ++alias_count; - } - - for (size_t i = 0; i != txs.size(); i++) - { - if (txs[i] != SIZE_MAX) - { - txv &tx(txs_v[txs[i]]); - if (i < best_position) - { - bl.tx_hashes.push_back(tx.first); - } - else if (have_attachment_service_in_container(tx.second->tx.attachment, BC_OFFERS_SERVICE_ID, BC_OFFERS_SERVICE_INSTRUCTION_DEL)) - { - // BC_OFFERS_SERVICE_INSTRUCTION_DEL transactions has zero fee, so include them here regardless of reward effectiveness - bl.tx_hashes.push_back(tx.first); - total_size += tx.second->blob_size; - } - } - } - // add explicit transactions - for (const auto& tx : explicit_txs) - { - fee += get_tx_fee(tx); - bl.tx_hashes.push_back(get_transaction_hash(tx)); - } - return true; - } - //--------------------------------------------------------------------------------- - void tx_memory_pool::store_db_solo_options_values() - { - m_db.begin_transaction(); - m_db_storage_major_compatibility_version = TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION; - m_db.commit_transaction(); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::init(const std::string& config_folder, const boost::program_options::variables_map& vm) - { - tools::db::db_backend_selector dbbs; - dbbs.init(vm); - auto p_backend = dbbs.create_backend(); - if (!p_backend) - { - LOG_PRINT_RED_L0("Failed to create db engine"); - return false; - } - m_db.reset_backend(p_backend); - LOG_PRINT_L0("DB ENGINE USED BY POOL: " << m_db.get_backend()->name()); - - m_config_folder = config_folder; - - uint64_t cache_size_l1 = CACHE_SIZE; - LOG_PRINT_GREEN("Using pool db file cache size(L1): " << cache_size_l1, LOG_LEVEL_0); - - // remove old incompatible DB - const std::string old_db_folder_path = m_config_folder + "/" CURRENCY_POOLDATA_FOLDERNAME_OLD; - if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(old_db_folder_path))) - { - LOG_PRINT_YELLOW("Removing old DB in " << old_db_folder_path << "...", LOG_LEVEL_0); - boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path)); - } - - const std::string db_folder_path = dbbs.get_pool_db_folder_path(); - - LOG_PRINT_L0("Loading blockchain from " << db_folder_path << "..."); - - bool db_opened_okay = false; - for(size_t loading_attempt_no = 0; loading_attempt_no < 2; ++loading_attempt_no) - { - bool res = m_db.open(db_folder_path, cache_size_l1); - if (!res) - { - // if DB could not be opened -- try to remove the whole folder and re-open DB - LOG_PRINT_YELLOW("Failed to initialize database in folder: " << db_folder_path << ", first attempt", LOG_LEVEL_0); - boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path)); - res = m_db.open(db_folder_path, cache_size_l1); - CHECK_AND_ASSERT_MES(res, false, "Failed to initialize database in folder: " << db_folder_path << ", second attempt"); - } - - res = m_db_transactions.init(TRANSACTION_POOL_CONTAINER_TRANSACTIONS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_black_tx_list.init(TRANSACTION_POOL_CONTAINER_BLACK_TX_LIST); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_alias_names.init(TRANSACTION_POOL_CONTAINER_ALIAS_NAMES); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_alias_addresses.init(TRANSACTION_POOL_CONTAINER_ALIAS_ADDRESSES); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - res = m_db_solo_options.init(TRANSACTION_POOL_CONTAINER_SOLO_OPTIONS); - CHECK_AND_ASSERT_MES(res, false, "Unable to init db container"); - - m_db_transactions.set_cache_size(1000); - m_db_alias_names.set_cache_size(10000); - m_db_alias_addresses.set_cache_size(10000); - m_db_black_tx_list.set_cache_size(1000); - - bool need_reinit = false; - if (m_db_storage_major_compatibility_version > 0 && m_db_storage_major_compatibility_version != TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION) - { - need_reinit = true; - LOG_PRINT_MAGENTA("Tx pool DB needs reinit because it has major compatibility ver is " << m_db_storage_major_compatibility_version << ", expected: " << TRANSACTION_POOL_MAJOR_COMPATIBILITY_VERSION, LOG_LEVEL_0); - } - - if (need_reinit) - { - LOG_PRINT_L1("DB at " << db_folder_path << " is about to be deleted and re-created..."); - m_db_transactions.deinit(); -// m_db_key_images_set.deinit(); - m_db_black_tx_list.deinit(); - m_db_alias_names.deinit(); - m_db_alias_addresses.deinit(); - m_db_solo_options.deinit(); - m_db.close(); - size_t files_removed = boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path)); - LOG_PRINT_L1(files_removed << " files at " << db_folder_path << " removed"); - - // try to re-create DB and re-init containers - continue; - } - - db_opened_okay = true; - break; - } - - CHECK_AND_ASSERT_MES(db_opened_okay, false, "All attempts to open DB at " << db_folder_path << " failed"); - - store_db_solo_options_values(); - - LOG_PRINT_GREEN("tx pool loaded ok from " << db_folder_path << ", loaded " << m_db_transactions.size() << " transactions", LOG_LEVEL_0); - if (epee::log_space::log_singletone::get_log_detalisation_level() >= LOG_LEVEL_2 && m_db_transactions.size() != 0) - { - std::stringstream ss; - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - ss << h << " sz: " << std::setw(5) << tx_entry.blob_size << " rcv: " << misc_utils::get_time_interval_string(time(nullptr) - tx_entry.receive_time) << " ago" << ENDL; - return true; - }); - LOG_PRINT_L2(ss.str()); - } - - load_keyimages_cache(); - - return true; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::load_keyimages_cache() - { - CRITICAL_REGION_LOCAL(m_key_images_lock); - return get_key_images_from_tx_pool(m_key_images); - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::deinit() - { - m_db.close(); - return true; - } - //--------------------------------------------------------------------------------- - uint64_t tx_memory_pool::get_core_time() const - { - return m_blockchain.get_core_runtime_config().get_core_time(); - } - //--------------------------------------------------------------------------------- - namespace - { - struct ms_out_info - { - crypto::hash multisig_id; - size_t input_output_index; - bool is_input; - }; - } - //--------------------------------------------------------------------------------- - void collect_multisig_ids_from_tx(const transaction& tx, std::vector& result) - { - result.reserve(tx.vin.size() + tx.vout.size()); - - size_t idx = 0; - for (const auto& in : tx.vin) - { - if (in.type() == typeid(txin_multisig)) - result.push_back(ms_out_info({ boost::get(in).multisig_out_id, idx, true })); - ++idx; - } - - idx = 0; - for (const auto& out : tx.vout) - { - if (out.target.type() == typeid(txout_multisig)) - result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false })); - ++idx; - } - } - //--------------------------------------------------------------------------------- - bool does_tx_have_given_multisig_id(const transaction& tx, const crypto::hash& multisig_id) - { - for (const auto& in : tx.vin) - { - if (in.type() == typeid(txin_multisig) && boost::get(in).multisig_out_id == multisig_id) - return true; - } - - size_t idx = 0; - for (const auto& out : tx.vout) - { - if (out.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id) - return true; - ++idx; - } - - return false; - } - //--------------------------------------------------------------------------------- - bool tx_memory_pool::check_tx_multisig_ins_and_outs(const transaction& tx, bool check_against_pool_txs) const - { - - LOCAL_READONLY_TRANSACTION(); - std::vector ms_ids; - collect_multisig_ids_from_tx(tx, ms_ids); - - for (auto& el : ms_ids) - { - // check given multisig output against all blockchain's multisig outputs - if (!el.is_input && m_blockchain.has_multisig_output(el.multisig_id)) - { - LOG_PRINT_L0("Transaction " << get_transaction_hash(tx) << " : output #" << el.input_output_index << " has multisig id " << el.multisig_id << " that is already in the blockchain"); - return false; - } - - // check given multisig input/output against all transactions in the pool - if (check_against_pool_txs) - { - bool has_found = false; - m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry) - { - if (does_tx_have_given_multisig_id(tx_entry.tx, el.multisig_id)) - { - has_found = true; - LOG_PRINT_L0("Transaction " << get_transaction_hash(tx) << (el.is_input ? " : input #" : " : output #") << el.input_output_index << " has multisig id " << el.multisig_id << - " that is already in the pool in tx " << get_transaction_hash(tx_entry.tx)); - return false; - } - return true; - }); - if (has_found) - return false; - } - } - - return true; - } -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - - diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h deleted file mode 100644 index 4e660a6..0000000 --- a/src/currency_core/tx_pool.h +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "include_base_utils.h" -using namespace epee; - - -#include -#include -#include -#include -#include - -#include "string_tools.h" -#include "syncobj.h" -#include "math_helper.h" - -#include "common/db_abstract_accessor.h" -#include "common/command_line.h" - -#include "currency_format_utils.h" -#include "verification_context.h" -#include "crypto/hash.h" -#include "common/boost_serialization_helper.h" -#include "currency_protocol/currency_protocol_handler_common.h" - -namespace currency -{ - class blockchain_storage; - /************************************************************************/ - /* */ - /************************************************************************/ - - class tx_memory_pool: boost::noncopyable - { - public: - - struct tx_details - { - transaction tx; - size_t blob_size; - uint64_t fee; - crypto::hash max_used_block_id; - uint64_t max_used_block_height; - bool kept_by_block; - // - uint64_t last_failed_height; - crypto::hash last_failed_id; - time_t receive_time; - - BEGIN_SERIALIZE_OBJECT() - FIELD(tx) - FIELD(blob_size) - FIELD(fee) - FIELD(max_used_block_id) - FIELD(max_used_block_height) - FIELD(kept_by_block) - FIELD(last_failed_height) - FIELD(last_failed_id) - FIELD(receive_time) - END_SERIALIZE() - - }; - - struct performnce_data - { - //tx zone - epee::math_helper::average tx_processing_time; - epee::math_helper::average check_inputs_types_supported_time; - epee::math_helper::average expiration_validate_time; - epee::math_helper::average validate_amount_time; - epee::math_helper::average validate_alias_time; - epee::math_helper::average check_keyimages_ws_ms_time; - epee::math_helper::average check_inputs_time; - epee::math_helper::average begin_tx_time; - epee::math_helper::average update_db_time; - epee::math_helper::average db_commit_time; - }; - - typedef std::unordered_map> key_image_cache; - - tx_memory_pool(blockchain_storage& bchs, i_currency_protocol* pprotocol); - bool add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core = false); - bool add_tx(const transaction &tx, tx_verification_context& tvc, bool kept_by_block, bool from_core = false); - - bool do_insert_transaction(const transaction &tx, const crypto::hash &id, uint64_t blob_size, bool kept_by_block, uint64_t fee, const crypto::hash& max_used_block_id, uint64_t max_used_block_height); - //gets tx and remove it from pool - bool take_tx(const crypto::hash &id, transaction &tx, size_t& blob_size, uint64_t& fee); - - - bool have_tx(const crypto::hash &id)const; - bool have_tx_keyimg_as_spent(const crypto::key_image& key_im)const; - bool have_tx_keyimges_as_spent(const transaction& tx, crypto::key_image* p_spent_ki = nullptr) const; - const performnce_data& get_performnce_data() const { return m_performance_data; } - - - bool check_tx_multisig_ins_and_outs(const transaction& tx, bool check_against_pool_txs)const; - - bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id, const std::list& bsk); - bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id); - bool on_finalize_db_transaction(); - bool add_transaction_to_black_list(const transaction& tx); - bool force_relay_pool() const; - bool set_protocol(i_currency_protocol* pprotocol); - - - void on_idle(); - - void lock(); - void unlock(); - void purge_transactions(); - void clear(); - - // load/store operations - bool init(const std::string& config_folder, const boost::program_options::variables_map& vm); - bool deinit(); - bool fill_block_template(block &bl, bool pos, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height, const std::list& explicit_txs); - bool get_transactions(std::list& txs) const; - bool get_all_transactions_details(std::list& txs)const; - bool get_all_transactions_brief_details(std::list& txs)const; - bool get_all_transactions_list(std::list& txs)const; - bool get_transactions_details(const std::list& ids, std::list& txs)const; - bool get_transactions_brief_details(const std::list& ids, std::list& txs)const; - - bool get_transaction_details(const crypto::hash& id, tx_rpc_extended_info& trei)const; - bool get_transaction(const crypto::hash& h, transaction& tx)const; - bool get_transaction(const crypto::hash& h, tx_details& txd)const; - size_t get_transactions_count() const; - bool have_key_images(const std::unordered_set& kic, const transaction& tx)const; - bool append_key_images(std::unordered_set& kic, const transaction& tx); - std::string print_pool(bool short_format)const; - uint64_t get_core_time() const; - bool get_aliases_from_tx_pool(std::list& aliases)const; - bool get_aliases_from_tx_pool(std::map& aliases)const; - - bool remove_stuck_transactions(); // made public to be called from coretests - - private: - bool on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block); - bool on_tx_remove(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block); - bool insert_key_images(const crypto::hash& tx_id, const transaction& tx, bool kept_by_block); - bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block); - bool insert_alias_info(const transaction& tx); - bool remove_alias_info(const transaction& tx); - - bool is_valid_contract_finalization_tx(const transaction &tx)const; - void store_db_solo_options_values(); - bool is_transaction_ready_to_go(tx_details& txd, const crypto::hash& id)const; - bool validate_alias_info(const transaction& tx, bool is_in_block)const; - bool get_key_images_from_tx_pool(key_image_cache& key_images) const; - bool check_is_taken(const crypto::hash& id) const; - void set_taken(const crypto::hash& id); - void reset_all_taken(); - bool load_keyimages_cache(); - - typedef tools::db::cached_key_value_accessor transactions_container; - typedef tools::db::cached_key_value_accessor hash_container; - typedef tools::db::cached_key_value_accessor solo_options_container; - typedef tools::db::cached_key_value_accessor aliases_container; - typedef tools::db::cached_key_value_accessor address_to_aliases_container; - - - //main accessor - epee::shared_recursive_mutex m_dummy_rw_lock; - tools::db::basic_db_accessor m_db; - //containers - - transactions_container m_db_transactions; - hash_container m_db_black_tx_list; - aliases_container m_db_alias_names; - address_to_aliases_container m_db_alias_addresses; - solo_options_container m_db_solo_options; - tools::db::solo_db_value m_db_storage_major_compatibility_version; - - - epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval; - - performnce_data m_performance_data; - std::string m_config_folder; - blockchain_storage& m_blockchain; - i_currency_protocol* m_pprotocol; - - //in memory containers - mutable epee::critical_section m_taken_txs_lock; - std::unordered_set m_taken_txs; - - mutable epee::critical_section m_key_images_lock; - key_image_cache m_key_images; - mutable epee::critical_section m_remove_stuck_txs_lock; - - }; -} - -namespace boost -{ - namespace serialization - { - template - void serialize(archive_t & ar, currency::tx_memory_pool::tx_details& td, const unsigned int version) - { - ar & td.blob_size; - ar & td.fee; - ar & td.tx; - ar & td.max_used_block_height; - ar & td.max_used_block_id; - ar & td.last_failed_height; - ar & td.last_failed_id; - ar & td.receive_time; - ar & td.kept_by_block; - } - } -} - -BOOST_CLASS_VERSION(currency::tx_memory_pool, CURRENT_MEMPOOL_ARCHIVE_VER) - - - diff --git a/src/currency_core/tx_semantic_validation.cpp b/src/currency_core/tx_semantic_validation.cpp deleted file mode 100644 index 252c60b..0000000 --- a/src/currency_core/tx_semantic_validation.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - - -#include "tx_semantic_validation.h" -#include "currency_format_utils.h" - -namespace currency -{ - //----------------------------------------------------------------------------------------------- - bool check_tx_extra(const transaction& tx) - { - tx_extra_info ei = AUTO_VAL_INIT(ei); - bool r = parse_and_validate_tx_extra(tx, ei); - if (!r) - return false; - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_tx_inputs_keyimages_diff(const transaction& tx) - { - std::unordered_set ki; - BOOST_FOREACH(const auto& in, tx.vin) - { - if (in.type() == typeid(txin_to_key)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - if (!ki.insert(tokey_in.k_image).second) - return false; - } - else if (in.type() == typeid(txin_htlc)) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_htlc, htlc_in, false); - if (!ki.insert(htlc_in.k_image).second) - return false; - } - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool validate_tx_semantic(const transaction& tx, size_t tx_block_size) - { - if (!tx.vin.size()) - { - LOG_PRINT_RED_L0("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx)); - return false; - } - - if (!check_inputs_types_supported(tx)) - { - LOG_PRINT_RED_L0("unsupported input types for tx id= " << get_transaction_hash(tx)); - return false; - } - - if (!check_outs_valid(tx)) - { - LOG_PRINT_RED_L0("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx)); - return false; - } - - if (!check_money_overflow(tx)) - { - LOG_PRINT_RED_L0("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx)); - return false; - } - - uint64_t amount_in = 0; - get_inputs_money_amount(tx, amount_in); - uint64_t amount_out = get_outs_money_amount(tx); - - if (amount_in < amount_out) - { - LOG_PRINT_RED_L0("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx)); - return false; - } - - if (tx_block_size >= CURRENCY_MAX_TRANSACTION_BLOB_SIZE) - { - LOG_PRINT_RED_L0("tx has too big size " << tx_block_size << ", expected no bigger than " << CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE); - return false; - } - - //check if tx use different key images - if (!check_tx_inputs_keyimages_diff(tx)) - { - LOG_PRINT_RED_L0("tx inputs have the same key images"); - return false; - } - - if (!check_tx_extra(tx)) - { - LOG_PRINT_RED_L0("tx has wrong extra, rejected"); - return false; - } - - return true; - } -} \ No newline at end of file diff --git a/src/currency_core/tx_semantic_validation.h b/src/currency_core/tx_semantic_validation.h deleted file mode 100644 index 2e6f479..0000000 --- a/src/currency_core/tx_semantic_validation.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2018-2019 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#include "include_base_utils.h" -#include "currency_format_utils_transactions.h" - - -namespace currency -{ - //check correct values, amounts and all lightweight checks not related with database - bool validate_tx_semantic(const transaction& tx, size_t tx_block_size); -} diff --git a/src/currency_core/verification_context.h b/src/currency_core/verification_context.h deleted file mode 100644 index 85533cc..0000000 --- a/src/currency_core/verification_context.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - -#pragma once -namespace currency -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct tx_verification_context - { - bool m_should_be_relayed; - bool m_verification_failed; //bad tx, should drop connection - bool m_verification_impossible; //the transaction is related to alternative blockchain - bool m_added_to_pool; - }; - - struct block_verification_context - { - bool m_added_to_main_chain; - bool m_verification_failed; //bad block, should drop connection - bool m_marked_as_orphaned; - bool m_already_exists; - bool m_added_to_altchain; - uint64_t m_height_difference; - //this is work like a first-level cache for transactions while block is getting handled. It lets transactions - //associated with the block to get handled directly to core without being handled by tx_pool(which makes full - //inputs validation, including signatures check) - transactions_map m_onboard_transactions; - }; -} diff --git a/src/currency_protocol/blobdatatype.h b/src/currency_protocol/blobdatatype.h deleted file mode 100644 index b3d614a..0000000 --- a/src/currency_protocol/blobdatatype.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -namespace currency -{ - typedef std::string blobdata; -} diff --git a/src/currency_protocol/currency_protocol_defs.h b/src/currency_protocol/currency_protocol_defs.h deleted file mode 100644 index 48f09e2..0000000 --- a/src/currency_protocol/currency_protocol_defs.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include "serialization/keyvalue_serialization.h" -#include "currency_core/currency_basic.h" -#include "currency_core/connection_context.h" -#include "currency_core/blockchain_storage_basic.h" -#include "currency_protocol/blobdatatype.h" -#include "currency_core/basic_kv_structs.h" - -namespace currency -{ - - -#define BC_COMMANDS_POOL_BASE 2000 - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct block_complete_entry - { - blobdata block; - std::list txs; - std::vector coinbase_global_outs; - std::vector > > tx_global_outs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block) - KV_SERIALIZE(txs) - KV_SERIALIZE(coinbase_global_outs) - KV_SERIALIZE(tx_global_outs) - END_KV_SERIALIZE_MAP() - }; - - struct block_direct_data_entry - { - std::shared_ptr block_ptr; - std::shared_ptr coinbase_ptr; - std::list > txs_ptr; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct NOTIFY_NEW_BLOCK - { - const static int ID = BC_COMMANDS_POOL_BASE + 1; - - struct request - { - block_complete_entry b; - uint64_t current_blockchain_height; - uint32_t hop; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(b) - KV_SERIALIZE(current_blockchain_height) - KV_SERIALIZE(hop) - END_KV_SERIALIZE_MAP() - }; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct NOTIFY_NEW_TRANSACTIONS - { - const static int ID = BC_COMMANDS_POOL_BASE + 2; - - struct request - { - std::list txs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() - }; - }; - /************************************************************************/ - /* */ - /************************************************************************/ - struct NOTIFY_REQUEST_GET_OBJECTS - { - const static int ID = BC_COMMANDS_POOL_BASE + 3; - - struct request - { - std::list txs; - std::list blocks; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(txs) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blocks) - END_KV_SERIALIZE_MAP() - }; - }; - - struct NOTIFY_RESPONSE_GET_OBJECTS - { - const static int ID = BC_COMMANDS_POOL_BASE + 4; - - struct request - { - std::list txs; - std::list blocks; - std::list missed_ids; - uint64_t current_blockchain_height; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs) - KV_SERIALIZE(blocks) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(missed_ids) - KV_SERIALIZE(current_blockchain_height) - END_KV_SERIALIZE_MAP() - }; - }; - - struct CORE_SYNC_DATA - { - uint64_t current_height; - crypto::hash top_id; - uint64_t last_checkpoint_height; - uint64_t core_time; - std::string client_version; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_height) - KV_SERIALIZE_VAL_POD_AS_BLOB(top_id) - KV_SERIALIZE(last_checkpoint_height) - KV_SERIALIZE(core_time) - KV_SERIALIZE(client_version) - END_KV_SERIALIZE_MAP() - }; - - struct NOTIFY_REQUEST_CHAIN - { - const static int ID = BC_COMMANDS_POOL_BASE + 6; - - struct request - { - std::list block_ids; /*IDs of the first 10 blocks are sequential, next goes with pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) - END_KV_SERIALIZE_MAP() - }; - }; - - - - struct NOTIFY_RESPONSE_CHAIN_ENTRY - { - const static int ID = BC_COMMANDS_POOL_BASE + 7; - - struct request - { - uint64_t start_height; - uint64_t total_height; - std::list m_block_ids; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(start_height) - KV_SERIALIZE(total_height) - KV_SERIALIZE(m_block_ids) - END_KV_SERIALIZE_MAP() - }; - }; - -} - -#include "currency_protocol_defs_print.h" diff --git a/src/currency_protocol/currency_protocol_defs_print.h b/src/currency_protocol/currency_protocol_defs_print.h deleted file mode 100644 index 68f6fa4..0000000 --- a/src/currency_protocol/currency_protocol_defs_print.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "currency_core/currency_format_utils_abstract.h" -#include "currency_core/currency_format_utils_blocks.h" -#include "storages/portable_storage_to_json.h" - -namespace currency -{ - //------------------------------------------------------------------------------------------------------------------------ - inline std::string print_complete_block_entry_list(const std::list& blocks) - { - std::stringstream ss; - size_t i = 0; - for (const block_complete_entry& block_entry : blocks) - { - ss << "[" << i << "]"; - block b = AUTO_VAL_INIT(b); - if (!parse_and_validate_object_from_blob(block_entry.block, b)) - { - ss << "UNPARSED" << ENDL; - } - ss << get_block_hash(b) << "{....parent: " << b.prev_id << "....}" << ENDL; - - i++; - } - return ss.str(); - } - - template - std::string print_container_of_hashs(const container_t& cont, size_t indent) - { - std::stringstream ss; - std::string indent_str(indent, ' '); - for (const auto& h : cont) - { - ss << indent_str << h << ENDL; - } - return ss.str(); - } - - inline - std::string print_kv_structure(const NOTIFY_REQUEST_GET_OBJECTS::request& v) - { - std::stringstream ss; - ss << "blocks: {" << ENDL << print_container_of_hashs(v.blocks, 2) << ENDL << "}"; - ss << "txs: {" << ENDL << print_container_of_hashs(v.txs, 2) << ENDL << "}"; - return ss.str(); - } - - inline - std::string print_kv_structure(const NOTIFY_RESPONSE_GET_OBJECTS::request& v) - { - std::stringstream ss; - ss << "\"blocks\":{" << ENDL << print_complete_block_entry_list(v.blocks) << ENDL << "}, " << ENDL; - ss << "\"missed_ids\":" << ENDL; - ::epee::serialization::dump_as_json(ss, v.missed_ids, 2); - ss << ENDL << "\"current_blockchain_height\":" << v.current_blockchain_height; - return ss.str(); - } - - inline - std::string print_kv_structure(const NOTIFY_REQUEST_CHAIN::request& v) - { - std::stringstream ss; - ss << "block_ids: {" << ENDL << print_container_of_hashs(v.block_ids, 2) << ENDL << "}"; - return ss.str(); - } - inline - std::string print_kv_structure(const NOTIFY_RESPONSE_CHAIN_ENTRY::request& v) - { - std::stringstream ss; - ss << "start_height:" << v.start_height << ENDL; - ss << "total_height:" << v.total_height << ENDL; - ss << "block_ids: {" << ENDL; - for (const block_context_info& bei : v.m_block_ids) - { - ss << bei.h << ":" << bei.cumul_size << ENDL; - } - ss << "}"; - return ss.str(); - } - - -} \ No newline at end of file diff --git a/src/currency_protocol/currency_protocol_handler.h b/src/currency_protocol/currency_protocol_handler.h deleted file mode 100644 index eaf06bd..0000000 --- a/src/currency_protocol/currency_protocol_handler.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include - -#include "storages/levin_abstract_invoke2.h" -#include "warnings.h" -#include "currency_protocol_defs.h" -#include "currency_protocol_handler_common.h" -#include "currency_core/connection_context.h" -#include "currency_core/currency_stat_info.h" -#include "currency_core/verification_context.h" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "currency_protocol" - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4355) - -#define ASYNC_RELAY_MODE // relay transactions asyncronously via m_relay_que - -namespace currency -{ - - template - class t_currency_protocol_handler: public i_currency_protocol - { - public: - typedef currency_connection_context connection_context; - typedef core_stat_info stat_info; - typedef t_currency_protocol_handler currency_protocol_handler; - typedef CORE_SYNC_DATA payload_type; - typedef std::pair relay_que_entry; - - t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint* p_net_layout); - ~t_currency_protocol_handler(); - - BEGIN_INVOKE_MAP2(currency_protocol_handler) - HANDLE_NOTIFY_T2(NOTIFY_NEW_BLOCK, ¤cy_protocol_handler::handle_notify_new_block) - HANDLE_NOTIFY_T2(NOTIFY_NEW_TRANSACTIONS, ¤cy_protocol_handler::handle_notify_new_transactions) - HANDLE_NOTIFY_T2(NOTIFY_REQUEST_GET_OBJECTS, ¤cy_protocol_handler::handle_request_get_objects) - HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_GET_OBJECTS, ¤cy_protocol_handler::handle_response_get_objects) - HANDLE_NOTIFY_T2(NOTIFY_REQUEST_CHAIN, ¤cy_protocol_handler::handle_request_chain) - HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_CHAIN_ENTRY, ¤cy_protocol_handler::handle_response_chain_entry) - END_INVOKE_MAP2() - - bool on_idle(); - bool init(const boost::program_options::variables_map& vm); - bool deinit(); - void set_p2p_endpoint(nodetool::i_p2p_endpoint* p2p); - //bool process_handshake_data(const blobdata& data, currency_connection_context& context); - bool process_payload_sync_data(const CORE_SYNC_DATA& hshd, currency_connection_context& context, bool is_inital); - bool get_payload_sync_data(blobdata& data); - bool get_payload_sync_data(CORE_SYNC_DATA& hshd); - bool get_stat_info(const core_stat_info::params& pr, core_stat_info& stat_inf); - bool on_callback(currency_connection_context& context); - t_core& get_core(){return m_core;} - virtual bool is_synchronized(){ return m_synchronized; } - void log_connections(); - uint64_t get_core_inital_height(); - uint64_t get_max_seen_height(); - virtual size_t get_synchronized_connections_count(); - virtual size_t get_synchronizing_connections_count(); - - int64_t get_net_time_delta_median(); - bool add_time_delta_and_check_time_sync(int64_t delta); - bool get_last_time_sync_difference(int64_t& last_median2local_time_difference, int64_t& last_ntp2local_time_difference); // returns true if differences in allowed bounds - //----------------------------------------------------------------------------------- - void set_to_debug_mode(uint32_t ip); - - private: - //----------------- commands handlers ---------------------------------------------- - int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& context); - int handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context); - int handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context); - int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context); - int handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context); - int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context); - - - //----------------- i_bc_protocol_layout --------------------------------------- - virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context); - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context); - //---------------------------------------------------------------------------------- - //bool get_payload_sync_data(HANDSHAKE_DATA::request& hshd, currency_connection_context& context); - bool request_missing_objects(currency_connection_context& context, bool check_having_blocks); - bool on_connection_synchronized(); - void relay_que_worker(); - void process_current_relay_que(const std::list& que); - bool check_stop_flag_and_drop_cc(currency_connection_context& context); - - t_core& m_core; - - nodetool::p2p_endpoint_stub m_p2p_stub; - nodetool::i_p2p_endpoint* m_p2p; - std::atomic m_synchronized; - std::atomic m_have_been_synchronized; - std::atomic m_max_height_seen; - std::atomic m_core_inital_height; - - std::unordered_set m_blocks_id_que; - std::recursive_mutex m_blocks_id_que_lock; - - std::list m_relay_que; - std::mutex m_relay_que_lock; - std::condition_variable m_relay_que_cv; - std::thread m_relay_que_thread; - std::atomic m_want_stop; - - std::deque m_time_deltas; - std::mutex m_time_deltas_lock; - int64_t m_last_median2local_time_difference; - int64_t m_last_ntp2local_time_difference; - uint32_t m_debug_ip_address; - - template - bool post_notify(typename t_parametr::request& arg, currency_connection_context& context) - { - LOG_PRINT_L3("[POST]" << typeid(t_parametr).name() << " to " << context); - std::string blob; - epee::serialization::store_t_to_binary(arg, blob); - return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context); - } - - template - bool relay_post_notify(typename t_parametr::request& arg, currency_connection_context& exlude_context) - { - std::string arg_buff; - epee::serialization::store_t_to_binary(arg, arg_buff); - std::list relayed_peers; - bool r = m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context, relayed_peers); - - LOG_PRINT_GREEN("[POST RELAY] " << typeid(t_parametr).name() << " to (" << relayed_peers.size() << "): " << print_connection_context_list(relayed_peers, ", "), LOG_LEVEL_2); - return r; - } - }; -} - - -#include "currency_protocol_handler.inl" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - -POP_VS_WARNINGS diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl deleted file mode 100644 index 39e42a3..0000000 --- a/src/currency_protocol/currency_protocol_handler.inl +++ /dev/null @@ -1,953 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include "currency_core/currency_format_utils.h" -#include "profile_tools.h" -namespace currency -{ - - //----------------------------------------------------------------------------------------------------------------------- - template - t_currency_protocol_handler::t_currency_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint* p_net_layout) - : m_core(rcore) - , m_p2p(p_net_layout) - , m_synchronized(false) - , m_have_been_synchronized(false) - , m_max_height_seen(0) - , m_core_inital_height(0) - , m_want_stop(false) - , m_last_median2local_time_difference(0) - , m_last_ntp2local_time_difference(0) - , m_debug_ip_address(0) - { - if(!m_p2p) - m_p2p = &m_p2p_stub; - } - //----------------------------------------------------------------------------------------------------------------------- - template - t_currency_protocol_handler::~t_currency_protocol_handler() - { - deinit(); - } - //----------------------------------------------------------------------------------------------------------------------- - template - bool t_currency_protocol_handler::init(const boost::program_options::variables_map& vm) - { - m_relay_que_thread = std::thread([this](){relay_que_worker();}); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::deinit() - { - m_want_stop = true; - m_relay_que_cv.notify_all(); - if (m_relay_que_thread.joinable()) - m_relay_que_thread.join(); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - void t_currency_protocol_handler::set_p2p_endpoint(nodetool::i_p2p_endpoint* p2p) - { - if(p2p) - m_p2p = p2p; - else - m_p2p = &m_p2p_stub; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::on_callback(currency_connection_context& context) - { - LOG_PRINT_L3("callback fired"); - CHECK_AND_ASSERT_MES_CC( context.m_priv.m_callback_request_count > 0, false, "false callback fired, but context.m_priv.m_callback_request_count=" << context.m_priv.m_callback_request_count); - --context.m_priv.m_callback_request_count; - - if(context.m_state == currency_connection_context::state_synchronizing) - { - NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); - m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_callback): m_block_ids.size()=" << r.block_ids.size()); - LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_callback): " << ENDL << print_kv_structure(r)); - post_notify(r, context); - } - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::get_stat_info(const core_stat_info::params& pr, core_stat_info& stat_inf) - { - return m_core.get_stat_info(pr, stat_inf); - } - //------------------------------------------------------------------------------------------------------------------------ - template - void t_currency_protocol_handler::log_connections() - { - std::stringstream ss; - - ss << std::setw(29) << std::left << "Remote Host" - << std::setw(20) << "Peer id" - << std::setw(25) << "Recv/Sent (idle,sec)" - << std::setw(25) << "State" - << std::setw(20) << "Livetime" - << std::setw(20) << "Client version" << ENDL; - - size_t incoming_count = 0, outgoing_count = 0; - std::multimap conn_map; - m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id) - { - std::stringstream conn_ss; - time_t livetime = time(NULL) - cntxt.m_started; - conn_ss << std::setw(29) << std::left << std::string(cntxt.m_is_income ? "[INC]":"[OUT]") + - string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port) - << std::setw(20) << std::hex << peer_id - << std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")" - << std::setw(25) << get_protocol_state_string(cntxt.m_state) - << std::setw(20) << epee::misc_utils::get_time_interval_string(livetime) - << std::setw(20) << cntxt.m_remote_version - << ENDL; - conn_map.insert(std::make_pair(livetime, conn_ss.str())); - (cntxt.m_is_income ? incoming_count : outgoing_count) += 1; - return true; - }); - - for(auto it = conn_map.rbegin(); it != conn_map.rend(); ++it) - ss << it->second; - - LOG_PRINT_L0("Connections (" << incoming_count << " in, " << outgoing_count << " out, " << incoming_count + outgoing_count << " total):" << ENDL << ss.str()); - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::process_payload_sync_data(const CORE_SYNC_DATA& hshd, currency_connection_context& context, bool is_inital) - { - - - context.m_remote_version = hshd.client_version; - - if(context.m_state == currency_connection_context::state_befor_handshake && !is_inital) - return true; - - uint64_t local_time = m_core.get_blockchain_storage().get_core_runtime_config().get_core_time(); - context.m_time_delta = local_time - hshd.core_time; - - // for outgoing connections -- check time difference - if (!context.m_is_income) - { - if (!add_time_delta_and_check_time_sync(context.m_time_delta)) - { - // serious time sync problem detected - i_critical_error_handler* ceh(m_core.get_critical_error_handler()); - if (ceh != nullptr && ceh->on_critical_time_sync_error()) - { - // error is handled by a callee, should not be ignored here, stop processing immideately - return true; - } - } - } - - if(context.m_state == currency_connection_context::state_synchronizing) - return true; - - - bool have_in_que = false; - CRITICAL_REGION_BEGIN(m_blocks_id_que_lock); - have_in_que = m_blocks_id_que.find(hshd.top_id) != m_blocks_id_que.end(); - CRITICAL_REGION_END(); - - if(have_in_que || m_core.have_block(hshd.top_id)) - { - - context.m_state = currency_connection_context::state_normal; - if(is_inital) - on_connection_synchronized(); - return true; - } - - int64_t diff = static_cast(hshd.current_height) - static_cast(m_core.get_current_blockchain_size()); - LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, (is_inital ? "Inital ":"Idle ") << "sync data returned unknown top block (" << hshd.top_id << "): " << m_core.get_top_block_height() << " -> " << hshd.current_height - 1 - << " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TOTAL_TARGET ) << " days) " - << (0 <= diff ? std::string("behind") : std::string("ahead")) - << "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0 : LOG_LEVEL_1), (is_inital ? epee::log_space::console_color_yellow : epee::log_space::console_color_magenta)); - LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id); - /*check if current height is in remote's checkpoints zone*/ - if(hshd.last_checkpoint_height - && m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height - && m_core.get_current_blockchain_size() < hshd.last_checkpoint_height ) - { - LOG_PRINT_RED("Remote node has longer checkpoints zone (" << hshd.last_checkpoint_height << ") " << - "than local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << "). " << - "It means that current software is outdated, please updated it! " << - "Current height lays under checkpoints zone on remote host, so it's impossible to validate remote transactions locally, disconnecting.", LOG_LEVEL_0); - return false; - } - else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height) - { - LOG_PRINT_MAGENTA("Remote node has longer checkpoints zone (" << hshd.last_checkpoint_height << ") " << - "than local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << "). " << - "It means that current software is outdated, please updated it!", LOG_LEVEL_0); - } - - context.m_state = currency_connection_context::state_synchronizing; - context.m_remote_blockchain_height = hshd.current_height; - //let the socket to send response to handshake, but request callback, to let send request data after response - LOG_PRINT_L3("requesting callback"); - ++context.m_priv.m_callback_request_count; - m_p2p->request_callback(context); - //update progress vars - if (m_max_height_seen < hshd.current_height) - m_max_height_seen = hshd.current_height; - if (!m_core_inital_height) - m_core_inital_height = m_core.get_current_blockchain_size(); - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - uint64_t t_currency_protocol_handler::get_core_inital_height() - { - return m_core_inital_height; - } - //------------------------------------------------------------------------------------------------------------------------ - template - uint64_t t_currency_protocol_handler::get_max_seen_height() - { - return m_max_height_seen; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::get_payload_sync_data(CORE_SYNC_DATA& hshd) - { - m_core.get_blockchain_top(hshd.current_height, hshd.top_id); - hshd.current_height +=1; - hshd.last_checkpoint_height = m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height(); - hshd.core_time = m_core.get_blockchain_storage().get_core_runtime_config().get_core_time(); - hshd.client_version = PROJECT_VERSION_LONG; - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::get_payload_sync_data(blobdata& data) - { - CORE_SYNC_DATA hsd = AUTO_VAL_INIT(hsd); - get_payload_sync_data(hsd); - epee::serialization::store_t_to_binary(hsd, data); - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - if(context.m_state != currency_connection_context::state_normal) - return 1; - - //check if block already exists - block b = AUTO_VAL_INIT(b); - block_verification_context bvc = AUTO_VAL_INIT(bvc); - if (!m_core.parse_block(arg.b.block, b, bvc)) - { - LOG_PRINT_RED("Block parsing failed, dropping connection", LOG_LEVEL_0); - m_p2p->drop_connection(context); - return 1; - } - - crypto::hash block_id = get_block_hash(b); - LOG_PRINT_GREEN("[HANDLE]NOTIFY_NEW_BLOCK " << block_id << " HEIGHT " << get_block_height(b) << " (hop " << arg.hop << ")", LOG_LEVEL_2); - - CRITICAL_REGION_BEGIN(m_blocks_id_que_lock); - auto it = m_blocks_id_que.find(block_id); - if (it != m_blocks_id_que.end()) - { - //already have this block handler in que - LOG_PRINT("Block " << block_id << " already in processing que", LOG_LEVEL_3); - return 1; - } - else - { - m_blocks_id_que.insert(block_id); - } - CRITICAL_REGION_END(); - auto slh = epee::misc_utils::create_scope_leave_handler([&]() - { - CRITICAL_REGION_LOCAL(m_blocks_id_que_lock); - auto it = m_blocks_id_que.find(block_id); - CHECK_AND_ASSERT_MES_NO_RET(it != m_blocks_id_que.end(), "Internal error, block " << block_id << " not found in m_blocks_id_que"); - m_blocks_id_que.erase(it); - }); - - if (m_core.have_block(block_id)) - { - LOG_PRINT_L3("Block " << block_id << " already in core"); - return 1; - } - - //pre-validate block here, and propagate it to network asap to avoid latency of handling big block (tx flood) - //######################################################## - /* - problem with prevalidation: in case of pre_validate_block() is passed but handle_incoming_tx() is failed - network got spammed with notifications about this broken block and then connections got closed. - temporary disabled to more investigation - bool prevalidate_relayed = false; - if (m_core.pre_validate_block(b, bvc, block_id) && bvc.m_added_to_main_chain) - { - //not alternative block, relay it - ++arg.hop; - relay_block(arg, context); - prevalidate_relayed = true; - } - */ - //######################################################## - - //now actually process block - for(auto tx_blob_it = arg.b.txs.begin(); tx_blob_it!=arg.b.txs.end();tx_blob_it++) - { - if (tx_blob_it->size() > CURRENCY_MAX_TRANSACTION_BLOB_SIZE) - { - LOG_ERROR("WRONG TRANSACTION BLOB, too big size " << tx_blob_it->size() << ", rejected"); - m_p2p->drop_connection(context); - return 1; - } - - crypto::hash tx_hash = null_hash; - transaction tx; - if (!parse_and_validate_tx_from_blob(*tx_blob_it, tx, tx_hash)) - { - LOG_ERROR("WRONG TRANSACTION BLOB, Failed to parse, rejected"); - m_p2p->drop_connection(context); - return 1; - } - bvc.m_onboard_transactions[tx_hash] = tx; - } - - m_core.pause_mine(); - m_core.handle_incoming_block(b, bvc); - m_core.resume_mine(); - if(bvc.m_verification_failed) - { - LOG_PRINT_L0("Block verification failed, dropping connection"); - m_p2p->drop_connection(context); - return 1; - } - LOG_PRINT_GREEN("[HANDLE]NOTIFY_NEW_BLOCK EXTRA " << block_id - << " bvc.m_added_to_main_chain=" << bvc.m_added_to_main_chain - //<< ", prevalidate_result=" << prevalidate_relayed - << ", bvc.added_to_altchain=" << bvc.m_added_to_altchain - << ", bvc.m_marked_as_orphaned=" << bvc.m_marked_as_orphaned, LOG_LEVEL_2); - - if (bvc.m_added_to_main_chain || (bvc.m_added_to_altchain && bvc.m_height_difference < 2)) - { - if (true/*!prevalidate_relayed*/) - { - // pre-validation failed prevoiusly, but complete check was success, not an alternative block - ++arg.hop; - //TODO: Add here announce protocol usage - relay_block(arg, context); - } - }else if(bvc.m_marked_as_orphaned) - { - context.m_state = currency_connection_context::state_synchronizing; - NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); - m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_MAGENTA("State changed to state_synchronizing.", LOG_LEVEL_2); - LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_orphaned): m_block_ids.size()=" << r.block_ids.size() ); - LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN(on_orphaned): " << ENDL << print_kv_structure(r)); - post_notify(r, context); - } - - return 1; - } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - if(context.m_state != currency_connection_context::state_normal) - return 1; - uint64_t inital_tx_count = arg.txs.size(); - TIME_MEASURE_START_MS(new_transactions_handle_time); - for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end();) - { - currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc); - - m_core.handle_incoming_tx(*tx_blob_it, tvc, false); - if(tvc.m_verification_failed) - { - LOG_PRINT_L0("NOTIFY_NEW_TRANSACTIONS: Tx verification failed, dropping connection"); - m_p2p->drop_connection(context); - - return 1; - } - if(tvc.m_should_be_relayed) - ++tx_blob_it; - else - arg.txs.erase(tx_blob_it++); - } - - if(arg.txs.size()) - { - //TODO: add announce usage here - relay_transactions(arg, context); - } - TIME_MEASURE_FINISH_MS(new_transactions_handle_time); - - LOG_PRINT_L2("NOTIFY_NEW_TRANSACTIONS: " << new_transactions_handle_time << "ms (inital_tx_count: " << inital_tx_count << ", relayed_tx_count: " << arg.txs.size() << ")"); - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: arg.blocks.size() = " << arg.blocks.size() << ", arg.txs.size()="<< arg.txs.size()); - LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg)); - - if (arg.blocks.size() > CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT || - arg.txs.size() > CURRENCY_PROTOCOL_MAX_TXS_REQUEST_COUNT) - { - LOG_ERROR_CCONTEXT("Requested objects count is to big (" << arg.blocks.size() <<")expected not more then " << CURRENCY_PROTOCOL_MAX_BLOCKS_REQUEST_COUNT); - m_p2p->drop_connection(context); - } - - NOTIFY_RESPONSE_GET_OBJECTS::request rsp; - if(!m_core.handle_get_objects(arg, rsp, context)) - { - LOG_ERROR_CCONTEXT("failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection"); - m_p2p->drop_connection(context); - } - - LOG_PRINT_L2("[NOTIFY]NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size() - << ", rsp.m_current_blockchain_height=" << rsp.current_blockchain_height << ", missed_ids.size()=" << rsp.missed_ids.size()); - - - LOG_PRINT_L3("[NOTIFY]NOTIFY_RESPONSE_GET_OBJECTS: " << ENDL << currency::print_kv_structure(rsp)); - post_notify(rsp, context); - return 1; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::check_stop_flag_and_drop_cc(currency_connection_context& context) - { - if (m_p2p->is_stop_signal_sent() || m_want_stop) - { - m_p2p->drop_connection(context); - return true; - } - return false; - } - - - - -#define CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(ret_v, msg) if (check_stop_flag_and_drop_cc(context)) { LOG_PRINT_YELLOW("Stop flag detected within NOTIFY_RESPONSE_GET_OBJECTS. " << msg, LOG_LEVEL_0); return ret_v; } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: arg.blocks.size()=" << arg.blocks.size() << ", arg.missed_ids.size()=" << arg.missed_ids.size() << ", arg.txs.size()=" << arg.txs.size()); - LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_GET_OBJECTS: " << ENDL << currency::print_kv_structure(arg)); - if(context.m_last_response_height > arg.current_blockchain_height) - { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height - << " < m_last_response_height=" << context.m_last_response_height << ", dropping connection"); - m_p2p->drop_connection(context); - return 1; - } - - context.m_remote_blockchain_height = arg.current_blockchain_height; - - uint64_t total_blocks_parsing_time = 0; - size_t count = 0; - for (const block_complete_entry& block_entry : arg.blocks) - { - CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Blocks processing interrupted, connection dropped"); - - ++count; - block b; - TIME_MEASURE_START(block_parsing_time); - if(!parse_and_validate_block_from_blob(block_entry.block, b)) - { - LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n" - << string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection"); - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - return 1; - } - TIME_MEASURE_FINISH(block_parsing_time); - total_blocks_parsing_time += block_parsing_time; - - //to avoid concurrency in core between connections, suspend connections which delivered block later then first one - if(count == 2) - { - if(m_core.have_block(get_block_hash(b))) - { - context.m_state = currency_connection_context::state_idle; - context.m_priv.m_needed_objects.clear(); - context.m_priv.m_requested_objects.clear(); - LOG_PRINT_L1("Connection set to idle state."); - return 1; - } - } - - auto req_it = context.m_priv.m_requested_objects.find(get_block_hash(b)); - if(req_it == context.m_priv.m_requested_objects.end()) - { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block)) - << " wasn't requested, dropping connection"); - m_p2p->drop_connection(context); - return 1; - } - if(b.tx_hashes.size() != block_entry.txs.size()) - { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block)) - << ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection"); - m_p2p->drop_connection(context); - return 1; - } - - context.m_priv.m_requested_objects.erase(req_it); - } - - LOG_PRINT_CYAN("Block parsing time avr: " << (count > 0 ? total_blocks_parsing_time / count : 0) << " mcs, total for " << count << " blocks: " << total_blocks_parsing_time / 1000 << " ms", LOG_LEVEL_2); - - if(context.m_priv.m_requested_objects.size()) - { - LOG_PRINT_RED("returned not all requested objects (context.m_priv.m_requested_objects.size()=" - << context.m_priv.m_requested_objects.size() << "), dropping connection", LOG_LEVEL_0); - m_p2p->drop_connection(context); - return 1; - } - - { - m_core.pause_mine(); - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( - boost::bind(&t_core::resume_mine, &m_core)); - size_t count = 0; - for (const block_complete_entry& block_entry : arg.blocks) - { - CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Blocks processing interrupted, connection dropped"); - - block_verification_context bvc = boost::value_initialized(); - //process transactions - TIME_MEASURE_START(transactions_process_time); - for (const auto& tx_blob : block_entry.txs) - { - CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Block txs processing interrupted, connection dropped"); - crypto::hash tx_id = null_hash; - transaction tx = AUTO_VAL_INIT(tx); - if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_id)) - { - LOG_ERROR_CCONTEXT("failed to parse tx: " - << string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection"); - m_p2p->drop_connection(context); - return 1; - } - bvc.m_onboard_transactions[tx_id] = tx; -// tx_verification_context tvc = AUTO_VAL_INIT(tvc); -// m_core.handle_incoming_tx(tx_blob, tvc, true); -// if(tvc.m_verification_failed) -// { -// LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = " -// << string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection"); -// m_p2p->drop_connection(context); -// return 1; -// } - } - TIME_MEASURE_FINISH(transactions_process_time); - - //process block - TIME_MEASURE_START(block_process_time); - - m_core.handle_incoming_block(block_entry.block, bvc, false); - if (count > 2 && bvc.m_already_exists) - { - context.m_state = currency_connection_context::state_idle; - context.m_priv.m_needed_objects.clear(); - context.m_priv.m_requested_objects.clear(); - LOG_PRINT_L1("Connection set to idle state."); - return 1; - } - - if(bvc.m_verification_failed) - { - LOG_PRINT_L0("Block verification failed, dropping connection"); - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - return 1; - } - if(bvc.m_marked_as_orphaned) - { - LOG_PRINT_L0("Block received at sync phase was marked as orphaned, dropping connection, details on response: " << ENDL << print_kv_structure(arg)); - - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - return 1; - } - - TIME_MEASURE_FINISH(block_process_time); - LOG_PRINT_L2("Block process time: " << block_process_time + transactions_process_time << "(" << transactions_process_time << "/" << block_process_time << ")ms"); - ++count; - } - } - uint64_t current_size = m_core.get_blockchain_storage().get_current_blockchain_size(); - LOG_PRINT_YELLOW(">>>>>>>>> sync progress: " << arg.blocks.size() << " blocks added, now have " - << current_size << " of " << context.m_remote_blockchain_height - << " ( " << std::fixed << std::setprecision(2) << current_size * 100.0 / context.m_remote_blockchain_height << "% ) and " - << context.m_remote_blockchain_height - current_size << " blocks left" - , LOG_LEVEL_0); - - request_missing_objects(context, true); - return 1; - } -#undef CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::on_idle() - { - size_t synchronized_connections_count = get_synchronized_connections_count(); - size_t total_connections_count = m_p2p->get_connections_count(); - bool have_enough_synchronized_connections = synchronized_connections_count > total_connections_count / 2; - - if (have_enough_synchronized_connections && !m_synchronized) - { - on_connection_synchronized(); - m_synchronized = true; - LOG_PRINT_MAGENTA("Synchronized set to TRUE (" << synchronized_connections_count << " of " << total_connections_count << " conn. synced)", LOG_LEVEL_0); - } - else if (!have_enough_synchronized_connections && m_synchronized) - { - LOG_PRINT_MAGENTA("Synchronized set to FALSE (" << synchronized_connections_count << " of " << total_connections_count << " conn. synced)", LOG_LEVEL_0); - m_synchronized = false; - } - - return m_core.on_idle(); - } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - LOG_PRINT_L2("[HANDLE]NOTIFY_REQUEST_CHAIN: block_ids.size()=" << arg.block_ids.size()); - LOG_PRINT_L3("[HANDLE]NOTIFY_REQUEST_CHAIN: " << print_kv_structure(arg)); - NOTIFY_RESPONSE_CHAIN_ENTRY::request r; - if(!m_core.find_blockchain_supplement(arg.block_ids, r)) - { - LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN."); - return 1; - } - LOG_PRINT_L2("[NOTIFY]NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size()); - LOG_PRINT_L3("[NOTIFY]NOTIFY_RESPONSE_CHAIN_ENTRY: " << print_kv_structure(r)); - post_notify(r, context); - return 1; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::request_missing_objects(currency_connection_context& context, bool check_having_blocks) - { - if(context.m_priv.m_needed_objects.size()) - { - //we know objects that we need, request this objects - NOTIFY_REQUEST_GET_OBJECTS::request req; - size_t count = 0; - auto it = context.m_priv.m_needed_objects.begin(); - uint64_t requested_cumulative_size = 0; - - while (it != context.m_priv.m_needed_objects.end() && count < BLOCKS_SYNCHRONIZING_DEFAULT_COUNT && requested_cumulative_size < BLOCKS_SYNCHRONIZING_DEFAULT_SIZE) - { - if( !(check_having_blocks && m_core.have_block(it->h))) - { - req.blocks.push_back(it->h); - requested_cumulative_size += it->cumul_size; - ++count; - context.m_priv.m_requested_objects.insert(it->h); - } - context.m_priv.m_needed_objects.erase(it++); - } - - LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_GET_OBJECTS(req_missing): requested_cumulative_size=" << requested_cumulative_size << ", blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size()); - LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_GET_OBJECTS(req_missing): " << ENDL << currency::print_kv_structure(req)); - post_notify(req, context); - }else if(context.m_last_response_height < context.m_remote_blockchain_height-1) - {//we have to fetch more objects ids, request blockchain entry - - NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); - m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_L2("[NOTIFY]NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() ); - LOG_PRINT_L3("[NOTIFY]NOTIFY_REQUEST_CHAIN: " << ENDL << print_kv_structure(r) ); - post_notify(r, context); - }else - { - CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height-1 - && !context.m_priv.m_needed_objects.size() - && !context.m_priv.m_requested_objects.size(), false, "request_missing_blocks final condition failed!" - << "\r\nm_last_response_height=" << context.m_last_response_height - << "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height - << "\r\nm_needed_objects.size()=" << context.m_priv.m_needed_objects.size() - << "\r\nm_requested_objects.size()=" << context.m_priv.m_requested_objects.size() - << "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]"); - - context.m_state = currency_connection_context::state_normal; - LOG_PRINT_GREEN("[REQUEST_MISSING_OBJECTS]: SYNCHRONIZED OK", LOG_LEVEL_0); - on_connection_synchronized(); - } - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::on_connection_synchronized() - { - bool val_expected = false; - if (m_have_been_synchronized.compare_exchange_strong(val_expected, true)) - { - m_core.on_synchronized(); - } - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - void t_currency_protocol_handler::relay_que_worker() - { - while (!m_want_stop) - { - std::list local_que; - { - CRITICAL_REGION_LOCAL(m_relay_que_lock); - local_que.swap(m_relay_que); - } - if (local_que.size()) - process_current_relay_que(local_que); - - epee::misc_utils::sleep_no_w(500); - } - } - //------------------------------------------------------------------------------------------------------------------------ - template - void t_currency_protocol_handler::process_current_relay_que(const std::list& que) - { - if (que.size() > 1){LOG_PRINT_MAGENTA("RELAY_QUE: " << que.size(), LOG_LEVEL_0);} - - TIME_MEASURE_START_MS(ms); - std::stringstream debug_ss; - std::list connections; - m_p2p->get_connections(connections); - for (auto& cc : connections) - { - NOTIFY_NEW_TRANSACTIONS::request req = AUTO_VAL_INIT(req); - for (auto& qe : que) - { - //exclude relaying to original sender - if (qe.second.m_connection_id == cc.m_connection_id) - continue; - req.txs.insert(req.txs.begin(), qe.first.txs.begin(), qe.first.txs.end()); - } - if (req.txs.size()) - { - post_notify(req, cc); - - if (debug_ss.tellp()) - debug_ss << ", "; - debug_ss << cc << ": " << req.txs.size(); - } - } - TIME_MEASURE_FINISH_MS(ms); - LOG_PRINT_GREEN("[POST RELAY] NOTIFY_NEW_TRANSACTIONS relayed (" << ms << "ms) to: " << debug_ss.str(), LOG_LEVEL_2); - } - //------------------------------------------------------------------------------------------------------------------------ - template - size_t t_currency_protocol_handler::get_synchronized_connections_count() - { - size_t count = 0; - m_p2p->for_each_connection([&](currency_connection_context& context, nodetool::peerid_type peer_id)->bool{ - if (context.m_state == currency_connection_context::state_normal) - ++count; - return true; - }); - return count; - } - //------------------------------------------------------------------------------------------------------------------------ - template - size_t t_currency_protocol_handler::get_synchronizing_connections_count() - { - size_t count = 0; - m_p2p->for_each_connection([&](currency_connection_context& context, nodetool::peerid_type peer_id)->bool{ - if (context.m_state == currency_connection_context::state_synchronizing) - ++count; - return true; - }); - return count; - } - //------------------------------------------------------------------------------------------------------------------------ - template - int64_t t_currency_protocol_handler::get_net_time_delta_median() - { - std::vector deltas; - m_p2p->for_each_connection([&](currency_connection_context& context, nodetool::peerid_type peer_id)->bool{ - deltas.push_back(context.m_time_delta); - return true; - }); - - return epee::misc_utils::median(deltas); - } - //------------------------------------------------------------------------------------------------------------------------ - #define TIME_SYNC_DELTA_RING_BUFFER_SIZE 8 - #define TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE (60 * 5) // max acceptable difference between time delta median among peers and local time (seconds) - #define TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE (60 * 5) // max acceptable difference between NTP time and local time (seconds) - - template - bool t_currency_protocol_handler::add_time_delta_and_check_time_sync(int64_t time_delta) - { - CRITICAL_REGION_LOCAL(m_time_deltas_lock); - - auto get_core_time = [this] { return m_core.get_blockchain_storage().get_core_runtime_config().get_core_time(); }; - - m_time_deltas.push_back(time_delta); - while (m_time_deltas.size() > TIME_SYNC_DELTA_RING_BUFFER_SIZE) - m_time_deltas.pop_front(); - - if (m_time_deltas.size() < TIME_SYNC_DELTA_RING_BUFFER_SIZE) - return true; // not enough data - - std::vector time_deltas_copy(m_time_deltas.begin(), m_time_deltas.end()); - - m_last_median2local_time_difference = epee::misc_utils::median(time_deltas_copy); - LOG_PRINT_MAGENTA("TIME: network time difference is " << m_last_median2local_time_difference << " (max is " << TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE << ")", ((m_last_median2local_time_difference >= 3) ? LOG_LEVEL_2 : LOG_LEVEL_3)); - if (std::abs(m_last_median2local_time_difference) > TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE) - { - int64_t ntp_time = tools::get_ntp_time(); - LOG_PRINT_L2("NTP: received time " << ntp_time << " (" << epee::misc_utils::get_time_str_v2(ntp_time) << "), diff: " << std::showpos << get_core_time() - ntp_time); - if (ntp_time == 0) - { - // error geting ntp time - LOG_PRINT_RED("TIME: network time difference is " << m_last_median2local_time_difference << " (max is " << TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE << ") but NTP servers did not respond", LOG_LEVEL_0); - return false; - } - - // got ntp time correctly - // update local time, because getting ntp time could be time consuming - uint64_t local_time_2 = get_core_time(); - m_last_ntp2local_time_difference = local_time_2 - ntp_time; - if (std::abs(m_last_ntp2local_time_difference) > TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE) - { - // local time is out of sync - LOG_PRINT_RED("TIME: network time difference is " << m_last_median2local_time_difference << " (max is " << TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE << "), NTP time difference is " << - m_last_ntp2local_time_difference << " (max is " << TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE << ")", LOG_LEVEL_0); - return false; - } - - // NTP time is OK - LOG_PRINT_YELLOW("TIME: network time difference is " << m_last_median2local_time_difference << " (max is " << TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE << "), NTP time difference is " << - m_last_ntp2local_time_difference << " (max is " << TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE << ")", LOG_LEVEL_1); - } - - return true; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::get_last_time_sync_difference(int64_t& last_median2local_time_difference, int64_t& last_ntp2local_time_difference) - { - CRITICAL_REGION_LOCAL(m_time_deltas_lock); - last_median2local_time_difference = m_last_median2local_time_difference; - last_ntp2local_time_difference = m_last_ntp2local_time_difference; - - return !(std::abs(m_last_median2local_time_difference) > TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE && std::abs(m_last_ntp2local_time_difference) > TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE); - } - template - void t_currency_protocol_handler::set_to_debug_mode(uint32_t ip) - { - m_debug_ip_address = ip; - LOG_PRINT_L0("debug mode is set for IP " << epee::string_tools::get_ip_string_from_int32(m_debug_ip_address)); - } - //------------------------------------------------------------------------------------------------------------------------ - template - int t_currency_protocol_handler::handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, currency_connection_context& context) - { - //do not process requests if it comes from node wich is debugged - if (m_debug_ip_address != 0 && context.m_remote_ip == m_debug_ip_address) - return 1; - - LOG_PRINT_L2("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size() - << ", m_start_height=" << arg.start_height << ", m_total_height=" << arg.total_height); - LOG_PRINT_L3("[HANDLE]NOTIFY_RESPONSE_CHAIN_ENTRY: " << ENDL << currency::print_kv_structure(arg)); - - if(!arg.m_block_ids.size()) - { - LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection"); - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - return 1; - } - - if(!m_core.have_block(arg.m_block_ids.front().h)) - { - LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: " - << string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection"); - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - return 1; - } - - context.m_remote_blockchain_height = arg.total_height; - context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1; - if(context.m_last_response_height > context.m_remote_blockchain_height) - { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with \r\nm_total_height=" << arg.total_height - << "\r\nm_start_height=" << arg.start_height - << "\r\nm_block_ids.size()=" << arg.m_block_ids.size()); - m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); - } - - BOOST_FOREACH(auto& bl_details, arg.m_block_ids) - { - if (!m_core.have_block(bl_details.h)) - context.m_priv.m_needed_objects.push_back(bl_details); - } - - request_missing_objects(context, false); - return 1; - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context) - { - return relay_post_notify(arg, exclude_context); - } - //------------------------------------------------------------------------------------------------------------------------ - template - bool t_currency_protocol_handler::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context) - { -#ifdef ASYNC_RELAY_MODE - { - CRITICAL_REGION_LOCAL(m_relay_que_lock); - m_relay_que.push_back(AUTO_VAL_INIT(relay_que_entry())); - m_relay_que.back().first = arg; - m_relay_que.back().second = exclude_context; - } - //m_relay_que_cv.notify_all(); - return true; -#else - return relay_post_notify(arg, exclude_context); -#endif - } -} diff --git a/src/currency_protocol/currency_protocol_handler_common.h b/src/currency_protocol/currency_protocol_handler_common.h deleted file mode 100644 index 2bff506..0000000 --- a/src/currency_protocol/currency_protocol_handler_common.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "p2p/net_node_common.h" -#include "currency_protocol/currency_protocol_defs.h" -#include "currency_core/connection_context.h" -namespace currency -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_currency_protocol - { - virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, currency_connection_context& exclude_context)=0; - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, currency_connection_context& exclude_context)=0; - //virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, currency_connection_context& context)=0; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct currency_protocol_stub: public i_currency_protocol - { - virtual bool relay_block(NOTIFY_NEW_BLOCK::request& /*arg*/, currency_connection_context& /*exclude_context*/) - { - return false; - } - virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& /*arg*/, currency_connection_context& /*exclude_context*/) - { - return false; - } - - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct i_critical_error_handler - { - // called by currency protocol when the time is critically out of sync - // return true if the error is not ignored and the called should not proceed - virtual bool on_critical_time_sync_error() = 0; - - virtual bool on_critical_low_free_space(uint64_t available, uint64_t required) = 0; - - virtual bool on_immediate_stop_requested() = 0; - }; - - -} diff --git a/src/main.cc b/src/main.cc deleted file mode 100644 index 825857f..0000000 --- a/src/main.cc +++ /dev/null @@ -1,365 +0,0 @@ -//#include -#include -#include -#include -#include -#include -#include -#include "currency_core/currency_basic.h" -#include "currency_core/currency_format_utils.h" -#include "currency_protocol/blobdatatype.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "common/base58.h" -#include "serialization/binary_utils.h" -#include "currency_core/basic_pow_helpers.h" -#include - -#define THROW_ERROR_EXCEPTION(x) Nan::ThrowError(x) - -void callback(char* data, void* hint) { - free(data); -} - -using namespace node; -using namespace v8; -using namespace currency; - -blobdata uint64be_to_blob(uint64_t num) { - blobdata res = " "; - res[0] = num >> 56 & 0xff; - res[1] = num >> 48 & 0xff; - res[2] = num >> 40 & 0xff; - res[3] = num >> 32 & 0xff; - res[4] = num >> 24 & 0xff; - res[5] = num >> 16 & 0xff; - res[6] = num >> 8 & 0xff; - res[7] = num & 0xff; - return res; -} - -const size_t MM_NONCE_SIZE = 1 + 2 + sizeof(crypto::hash); - -NAN_METHOD(get_merged_mining_nonce_size) { - Local returnValue = Nan::New(static_cast(MM_NONCE_SIZE)); - info.GetReturnValue().Set(returnValue); -} - -NAN_METHOD(convert_blob) { - - if (info.Length() < 1) - return THROW_ERROR_EXCEPTION("You must provide one argument."); - - //Local target = info[0]->ToObject(); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - if (!Buffer::HasInstance(target)) - return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); - - blobdata input = std::string(Buffer::Data(target), Buffer::Length(target)); - blobdata output = ""; - - //convert - block b = AUTO_VAL_INIT(b); - if (!parse_and_validate_block_from_blob(input, b)) - return THROW_ERROR_EXCEPTION("Failed to parse block"); - - output = get_block_hashing_blob(b); - - v8::Local returnValue = Nan::CopyBuffer((char*)output.data(), output.size()).ToLocalChecked(); - info.GetReturnValue().Set( - returnValue - ); -} - - -void address_decode(const Nan::FunctionCallbackInfo& info) { - - if (info.Length() < 1) - return THROW_ERROR_EXCEPTION("You must provide one argument."); - - //Local target = info[0]->ToObject(); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - if (!Buffer::HasInstance(target)) - return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); - - blobdata input = std::string(Buffer::Data(target), Buffer::Length(target)); - - blobdata data; - uint64_t prefix; - if (!tools::base58::decode_addr(input, prefix, data)) - { - info.GetReturnValue().Set(Nan::Undefined()); - } - // info.GetReturnValue().Set(Nan::Undefined()); - - - account_public_address adr; - if (!::serialization::parse_binary(data, adr) || !crypto::check_key(adr.spend_public_key) || !crypto::check_key(adr.view_public_key)) - { - if(data.length()) - { - data = uint64be_to_blob(prefix) + data; - } - else - { - info.GetReturnValue().Set(Nan::Undefined()); - } - - v8::Local returnValue = Nan::CopyBuffer((char*)data.data(), data.size()).ToLocalChecked(); - - info.GetReturnValue().Set( returnValue); - - } - else - { - info.GetReturnValue().Set(Nan::New(static_cast(prefix))); - } -} - -/* -Arguments: -1: block_header_hash - 32-byte buffer -2: nonce - 8-byte buffer -2: height - 8-byte buffer -*/ -void get_pow_hash(const Nan::FunctionCallbackInfo& info) { - - if (info.Length() < 3) - return THROW_ERROR_EXCEPTION("You must provide 3 arguments."); - - //Local block_header_hash = args[0]->ToObject(); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local block_header_hash = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - //Local nonce = args[1]->ToObject(); - Local nonce = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - //Local height = args[2]->ToObject(); - Local height = info[2]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - if(!Buffer::HasInstance(block_header_hash)) - return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); - - if(!Buffer::HasInstance(nonce)) - return THROW_ERROR_EXCEPTION("Argument 2 should be a buffer object."); - - if (!Buffer::HasInstance(height)) - return THROW_ERROR_EXCEPTION("Argument 3 should be a buffer object."); - - uint32_t block_header_hash_len = Buffer::Length(block_header_hash); - uint64_t nonce_len = Buffer::Length(nonce); - uint64_t height_len = Buffer::Length(height); - - if(block_header_hash_len != 32) - return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object of 32 bytes long."); - - if (nonce_len != 8) - return THROW_ERROR_EXCEPTION("Argument 2 should be a buffer object of 8 bytes long."); - - if (height_len != 8) - return THROW_ERROR_EXCEPTION("Argument 3 should be a buffer object of 8 bytes long."); - - crypto::hash block_header_hash_val = *(crypto::hash*)Buffer::Data(block_header_hash); - uint64_t nonce_val = *(uint64_t*)Buffer::Data(nonce); - uint64_t height_val = *(uint64_t*)Buffer::Data(height); - - - crypto::hash h = currency::get_block_longhash(height_val, block_header_hash_val, nonce_val); - - //SET_BUFFER_RETURN((const char*)&h, 32); - char *cstr = reinterpret_cast(&h); - v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); - info.GetReturnValue().Set(returnValue); -} - -/* -Arguments: -1: block_template_buffer - n-byte buffer -2: extra_data - n-byte buffer(job identification) -*/ -void get_hash_from_block_template_with_extra(const Nan::FunctionCallbackInfo& info) { - - if (info.Length() < 2) - return THROW_ERROR_EXCEPTION("You must provide 2 arguments."); - - //Local block_template_buffer = args[0]->ToObject(); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - //Local extra_data = args[1]->ToObject(); - Local extra_data = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - - if (!Buffer::HasInstance(block_template_buffer)) - return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); - - if (!Buffer::HasInstance(extra_data)) - return THROW_ERROR_EXCEPTION("Argument 2 should be a buffer object."); - - uint64_t block_template_buffer_len = Buffer::Length(block_template_buffer); - uint64_t extra_data_len = Buffer::Length(extra_data); - - char* block_template_buffer_ptr = Buffer::Data(block_template_buffer); - std::string blob(block_template_buffer_ptr, block_template_buffer_len); - - char* extra_data_ptr = Buffer::Data(extra_data); - std::string extra(extra_data_ptr, extra_data_len); - - currency::block b = AUTO_VAL_INIT(b); - bool res = currency::parse_and_validate_block_from_blob(blob, b); - if (!res) - return THROW_ERROR_EXCEPTION("Unable to parse block"); - - if (extra.size()) - b.miner_tx.extra.push_back(extra); - - crypto::hash h = currency::get_block_header_mining_hash(b); - - //SET_BUFFER_RETURN((const char*)&h, 32); - char *cstr = reinterpret_cast(&h); - v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); - info.GetReturnValue().Set(returnValue); -} - -/* -Arguments: -1: block_template_buffer - n-byte buffer -2: extra_data - n-byte buffer(job identification) -3: nonce - 8-byte buffer - nonce -*/ -void get_blob_from_block_template(const Nan::FunctionCallbackInfo& info) { - - if (info.Length() < 3) - return THROW_ERROR_EXCEPTION("You must provide 3 arguments."); - - //Local block_template_buffer = args[0]->ToObject(); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - //Local extra_data = args[1]->ToObject(); - Local extra_data = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - //Local nonce = args[2]->ToObject(); - Local nonce = info[2]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - - if (!Buffer::HasInstance(block_template_buffer)) - return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); - - if (!Buffer::HasInstance(extra_data)) - return THROW_ERROR_EXCEPTION("Argument 2 should be a buffer object."); - - if (!Buffer::HasInstance(nonce)) - return THROW_ERROR_EXCEPTION("Argument 3 should be a buffer object."); - - uint64_t block_template_buffer_len = Buffer::Length(block_template_buffer); - uint64_t extra_data_len = Buffer::Length(extra_data); - uint64_t nonce_len = Buffer::Length(nonce); - - if (nonce_len != 8) - return THROW_ERROR_EXCEPTION("Argument 3 should be a buffer object of 8 bytes long."); - - char* block_template_buffer_ptr = Buffer::Data(block_template_buffer); - std::string blob(block_template_buffer_ptr, block_template_buffer_len); - - char* extra_data_ptr = Buffer::Data(extra_data); - std::string extra(extra_data_ptr, extra_data_len); - - uint64_t nonce_val = *(uint64_t* )Buffer::Data(nonce); - - currency::block b = AUTO_VAL_INIT(b); - bool res = currency::parse_and_validate_block_from_blob(blob, b); - if (!res) - return THROW_ERROR_EXCEPTION("Unable to parse block"); - - if (extra.size()) - b.miner_tx.extra.push_back(extra); - - b.nonce = nonce_val; - - std::string result_blob = currency::block_to_blob(b); - - crypto::hash h = currency::get_block_hash(b); - - //SET_BUFFER_RETURN(result_blob.data(), result_blob.size()); - v8::Local returnValue = Nan::CopyBuffer((char*)result_blob.data(), result_blob.size()).ToLocalChecked(); - info.GetReturnValue().Set(returnValue); -} - - -void get_id_hash(const Nan::FunctionCallbackInfo& info) { - - if (info.Length() < 1) - return THROW_ERROR_EXCEPTION("You must provide 2 arguments."); - - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local block_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - if (!Buffer::HasInstance(block_buffer)) - return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); - - uint64_t block_buffer_len = Buffer::Length(block_buffer); - - char* block_buffer_ptr = Buffer::Data(block_buffer); - std::string blob(block_buffer_ptr, block_buffer_len); - - currency::block b = AUTO_VAL_INIT(b); - bool res = currency::parse_and_validate_block_from_blob(blob, b); - if (!res) - return THROW_ERROR_EXCEPTION("Unable to parse block"); - - crypto::hash h = currency::get_block_hash(b); - - //SET_BUFFER_RETURN((const char*)&h, 32); - char *cstr = reinterpret_cast(&h); - v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); - info.GetReturnValue().Set(returnValue); -} - - - -void is_address_valid(const Nan::FunctionCallbackInfo& info) -{ - - if (info.Length() < 1) - return THROW_ERROR_EXCEPTION("You must provide one argument."); - - v8::Isolate *isolate = v8::Isolate::GetCurrent(); - Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); - - if (!Buffer::HasInstance(target)) - return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); - - blobdata input = std::string(Buffer::Data(target), Buffer::Length(target)); - - account_public_address adr; - bool r = get_account_address_from_str(adr, input); - if(!r) - { - info.GetReturnValue().Set(Nan::Undefined()); - } - else - { - info.GetReturnValue().Set(Nan::True()); - } -} - - - -NAN_MODULE_INIT(init) { - Nan::Set(target, Nan::New("convert_blob").ToLocalChecked(), Nan::GetFunction(Nan::New(convert_blob)).ToLocalChecked()); - Nan::Set(target, Nan::New("address_decode").ToLocalChecked(), Nan::GetFunction(Nan::New(address_decode)).ToLocalChecked()); - Nan::Set(target, Nan::New("get_pow_hash").ToLocalChecked(), Nan::GetFunction(Nan::New(get_pow_hash)).ToLocalChecked()); - Nan::Set(target, Nan::New("get_hash_from_block_template_with_extra").ToLocalChecked(), Nan::GetFunction(Nan::New(get_hash_from_block_template_with_extra)).ToLocalChecked()); - Nan::Set(target, Nan::New("get_blob_from_block_template").ToLocalChecked(), Nan::GetFunction(Nan::New(get_blob_from_block_template)).ToLocalChecked()); - Nan::Set(target, Nan::New("get_id_hash").ToLocalChecked(), Nan::GetFunction(Nan::New(get_id_hash)).ToLocalChecked()); - Nan::Set(target, Nan::New("is_address_valid").ToLocalChecked(), Nan::GetFunction(Nan::New(is_address_valid)).ToLocalChecked()); - Nan::Set(target, Nan::New("get_merged_mining_nonce_size").ToLocalChecked(), Nan::GetFunction(Nan::New(get_merged_mining_nonce_size)).ToLocalChecked()); - -} - -NODE_MODULE(cryptonote, init) \ No newline at end of file diff --git a/src/p2p/maintainers_info_boost_serialization.h b/src/p2p/maintainers_info_boost_serialization.h deleted file mode 100644 index fafc659..0000000 --- a/src/p2p/maintainers_info_boost_serialization.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "p2p_protocol_defs.h" -#include "common/crypto_boost_serialization.h" - -namespace boost -{ - namespace serialization - { - template - inline void serialize(Archive &a, nodetool::alert_condition& ac, const ver_type ver) - { - a & ac.alert_mode; - a & ac.if_build_less_then; - } - - template - inline void serialize(Archive &a, nodetool::maintainers_info& mi, const ver_type ver) - { - a & mi.timestamp; - a & mi.ver_major; - a & mi.ver_minor; - a & mi.ver_revision; - a & mi.build_no; - a & mi.conditions; - } - - template - inline void serialize(Archive &a, nodetool::maintainers_entry& me, const ver_type ver) - { - a & me.maintainers_info_buff; - a & me.sign; - } - } -} diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h deleted file mode 100644 index 5c0fb12..0000000 --- a/src/p2p/net_node.h +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "warnings.h" -#include "net/levin_server_cp2.h" -#include "p2p_protocol_defs.h" -#include "storages/levin_abstract_invoke2.h" -#include "net_peerlist.h" -#include "p2p_networks.h" -#include "math_helper.h" -#include "net_node_common.h" -#include "maintainers_info_boost_serialization.h" -#include "currency_core/currency_config.h" -using namespace epee; - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "p2p" -ENABLE_CHANNEL_BY_DEFAULT(LOG_DEFAULT_CHANNEL); - -#define CURRENT_P2P_STORAGE_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+13) - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4355) - -namespace nodetool -{ - template - struct p2p_connection_context_t: base_type //t_payload_net_handler::connection_context //public net_utils::connection_context_base - { - peerid_type peer_id; - }; - - template - class node_server: public levin::levin_commands_handler >, - public i_p2p_endpoint, - public net_utils::i_connection_filter - { - struct by_conn_id{}; - struct by_peer_id{}; - struct by_addr{}; - - typedef p2p_connection_context_t p2p_connection_context; - - typedef COMMAND_HANDSHAKE_T COMMAND_HANDSHAKE; - typedef COMMAND_TIMED_SYNC_T COMMAND_TIMED_SYNC; - - public: - typedef t_payload_net_handler payload_net_handler; - // Some code - node_server(t_payload_net_handler& payload_handler):m_payload_handler(payload_handler), - m_allow_local_ip(false), - m_hide_my_port(false), - m_offline_mode(false), - m_alert_mode(0), - m_maintainers_entry_local(AUTO_VAL_INIT(m_maintainers_entry_local)), - m_maintainers_info_local(AUTO_VAL_INIT(m_maintainers_info_local)), - m_startup_time(time(nullptr)), - m_config{}, - m_have_address(false), - m_first_connection_maker_call(false), - m_listenning_port{}, - m_external_port{}, - m_ip_address{}, - m_last_stat_request_time{}, - m_use_only_priority_peers(false), - m_peer_livetime{}, - m_debug_requests_enabled(false), - m_ip_auto_blocking_enabled(false) - {} - - static void init_options(boost::program_options::options_description& desc); - - bool run(bool sync_call = true); - bool init(const boost::program_options::variables_map& vm); - bool deinit(); - bool send_stop_signal(); - bool timed_wait_server_stop(size_t mseconds_wait){ return m_net_server.timed_wait_server_stop(mseconds_wait); } - - uint32_t get_this_peer_port(){return m_listenning_port;} - t_payload_net_handler& get_payload_object(); - - template - void serialize(Archive &a, const t_version_type ver) - { - if(ver < CURRENT_P2P_STORAGE_ARCHIVE_VER) - return; - time_t local_time = time(nullptr); - a & local_time; - if(local_time > time(nullptr)) - { - LOG_PRINT_L0("psp network state file have future time, skipped"); - return; - } - a & m_peerlist; - a & m_maintainers_info_local; - a & m_maintainers_entry_local; - a & m_blocked_ips; - } - // debug functions - bool log_peerlist(); - bool log_connections(); - virtual uint64_t get_connections_count(); - size_t get_outgoing_connections_count(); - peerlist_manager& get_peerlist_manager(){return m_peerlist;} - bool handle_maintainers_entry(const maintainers_entry& me); - bool get_maintainers_info(maintainers_info_external& me); - typedef COMMAND_REQUEST_STAT_INFO_T COMMAND_REQUEST_STAT_INFO; - private: - - - CHAIN_LEVIN_INVOKE_MAP2(p2p_connection_context); //move levin_commands_handler interface invoke(...) callbacks into invoke map - CHAIN_LEVIN_NOTIFY_MAP2(p2p_connection_context); //move levin_commands_handler interface notify(...) callbacks into nothing - - BEGIN_INVOKE_MAP2(node_server) - HANDLE_INVOKE_T2(COMMAND_HANDSHAKE, &node_server::handle_handshake) - HANDLE_INVOKE_T2(COMMAND_TIMED_SYNC, &node_server::handle_timed_sync) - HANDLE_INVOKE_T2(COMMAND_PING, &node_server::handle_ping) -#ifdef ALLOW_DEBUG_COMMANDS - if (m_debug_requests_enabled) - { - HANDLE_INVOKE_T2(COMMAND_REQUEST_STAT_INFO, &node_server::handle_get_stat_info) - HANDLE_INVOKE_T2(COMMAND_REQUEST_NETWORK_STATE, &node_server::handle_get_network_state) - HANDLE_INVOKE_T2(COMMAND_REQUEST_PEER_ID, &node_server::handle_get_peer_id) - HANDLE_INVOKE_T2(COMMAND_REQUEST_LOG, &node_server::handle_request_log) - HANDLE_INVOKE_T2(COMMAND_SET_LOG_LEVEL, &node_server::handle_set_log_level) - } -#endif - CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(m_payload_handler, typename t_payload_net_handler::connection_context&) - END_INVOKE_MAP2() - - //----------------- commands handlers ---------------------------------------------- - int handle_handshake(int command, typename COMMAND_HANDSHAKE::request& arg, typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context); - int handle_timed_sync(int command, typename COMMAND_TIMED_SYNC::request& arg, typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context); - int handle_ping(int command, COMMAND_PING::request& arg, COMMAND_PING::response& rsp, p2p_connection_context& context); -#ifdef ALLOW_DEBUG_COMMANDS - public: - int handle_get_stat_info(int command, typename COMMAND_REQUEST_STAT_INFO::request& arg, typename COMMAND_REQUEST_STAT_INFO::response& rsp, p2p_connection_context& context); - int handle_get_network_state(int command, COMMAND_REQUEST_NETWORK_STATE::request& arg, COMMAND_REQUEST_NETWORK_STATE::response& rsp, p2p_connection_context& context); - int handle_get_peer_id(int command, COMMAND_REQUEST_PEER_ID::request& arg, COMMAND_REQUEST_PEER_ID::response& rsp, p2p_connection_context& context); - int handle_request_log(int command, COMMAND_REQUEST_LOG::request& arg, COMMAND_REQUEST_LOG::response& rsp, p2p_connection_context& context); - int handle_set_log_level(int command, COMMAND_SET_LOG_LEVEL::request& arg, COMMAND_SET_LOG_LEVEL::response& rsp, p2p_connection_context& context); - private: -#endif - bool init_config(); - bool make_default_config(); - bool store_config(); - bool check_trust(const proof_of_trust& tr); - - - //----------------- levin_commands_handler ------------------------------------------------------------- - virtual void on_connection_new(p2p_connection_context& context); - virtual void on_connection_close(p2p_connection_context& context); - virtual void callback(p2p_connection_context& context); - //----------------- i_p2p_endpoint ------------------------------------------------------------- - virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context, std::list& relayed_peers); - virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context); - virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context); - virtual bool drop_connection(const epee::net_utils::connection_context_base& context); - virtual void request_callback(const epee::net_utils::connection_context_base& context); - virtual void get_connections(std::list& connections); - virtual void for_each_connection(std::function f); - virtual bool block_ip(uint32_t adress); - virtual bool add_ip_fail(uint32_t address); - virtual bool is_stop_signal_sent(); - //----------------- i_connection_filter -------------------------------------------------------- - virtual bool is_remote_ip_allowed(uint32_t adress); - //----------------------------------------------------------------------------------------------- - bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr); - bool handle_command_line(const boost::program_options::variables_map& vm); - bool idle_worker(); - bool handle_remote_peerlist(const std::list& peerlist, time_t local_time, const net_utils::connection_context_base& context); - bool get_local_node_data(basic_node_data& node_data); - //bool get_local_handshake_data(handshake_data& hshd); - - bool merge_peerlist_with_local(const std::list& bs); - bool fix_time_delta(std::list& local_peerlist, time_t local_time, int64_t& delta); - - bool connections_maker(); - bool peer_sync_idle_maker(); - bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false); - bool do_peer_timed_sync(const net_utils::connection_context_base& context, peerid_type peer_id); - - bool make_new_connection_from_peerlist(bool use_white_list); - bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, bool white = true); - size_t get_random_index_with_fixed_probability(size_t max_index); - bool is_peer_id_used(const peerid_type id); - bool is_peer_used(const peerlist_entry& peer); - bool is_addr_connected(const net_address& peer); - template - bool try_ping(basic_node_data& node_data, p2p_connection_context& context, const t_callback& cb); - bool make_expected_connections_count(bool white_list, size_t expected_connections); - void cache_connect_fail_info(const net_address& addr); - bool is_addr_recently_failed(const net_address& addr); - bool fill_maintainers_entry(maintainers_entry& me); - bool on_maintainers_entry_update(); - bool handle_alert_conditions(); - /*this code is temporary here(to show regular message if need), until we get normal GUI*/ - bool calm_alert_worker(); - bool urgent_alert_worker(); - bool critical_alert_worker(); - bool remove_dead_connections(); - bool is_ip_good_for_adding_to_peerlist(uint32_t adress); - bool is_ip_in_blacklist(uint32_t adress); - - - //debug functions - std::string print_connections_container(); - - typedef net_utils::boosted_tcp_server > net_server; - - struct config - { - network_config m_net_config; - uint64_t m_peer_id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_net_config) - KV_SERIALIZE(m_peer_id) - END_KV_SERIALIZE_MAP() - }; - - config m_config; - std::string m_config_folder; - - bool m_have_address; - bool m_first_connection_maker_call; - uint32_t m_listenning_port; - uint32_t m_external_port; - uint32_t m_ip_address; - bool m_allow_local_ip; - bool m_hide_my_port; - bool m_offline_mode; - bool m_debug_requests_enabled; - bool m_ip_auto_blocking_enabled; - uint64_t m_startup_time; - - - //critical_section m_connections_lock; - //connections_indexed_container m_connections; - - t_payload_net_handler& m_payload_handler; - peerlist_manager m_peerlist; - - math_helper::once_a_time_seconds m_peer_handshake_idle_maker_interval; - math_helper::once_a_time_seconds<1> m_connections_maker_interval; - math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval; - math_helper::once_a_time_seconds<60> m_remove_dead_conn_interval; - - /*this code is temporary here(to show regular message if need), until we get normal GUI*/ - math_helper::once_a_time_seconds<60, false> m_calm_alert_interval; - math_helper::once_a_time_seconds<10, false> m_urgent_alert_interval; - math_helper::once_a_time_seconds<1, false> m_critical_alert_interval; - - std::string m_bind_ip; - std::string m_port; -#ifdef ALLOW_DEBUG_COMMANDS - int64_t m_last_stat_request_time; -#endif - std::list m_priority_peers; - bool m_use_only_priority_peers; - std::vector m_seed_nodes; - std::list m_command_line_peers; - int64_t m_peer_livetime; - //keep connections to initiate some interactions - net_server m_net_server; - - std::map m_conn_fails_cache; - critical_section m_conn_fails_cache_lock; - crypto::public_key m_maintainers_pub_key; - - maintainers_info m_maintainers_info_local; - maintainers_entry m_maintainers_entry_local; - uint8_t m_alert_mode; - critical_section m_maintainers_local_lock; - - critical_section m_blocked_ips_lock; - std::map m_blocked_ips; - - critical_section m_ip_fails_score_lock; - std::map m_ip_fails_score; - - }; -} - - - - -#include "net_node.inl" - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL - -POP_VS_WARNINGS diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl deleted file mode 100644 index 477d7e8..0000000 --- a/src/p2p/net_node.inl +++ /dev/null @@ -1,1497 +0,0 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include "version.h" -#include "string_tools.h" -#include "common/command_line.h" -#include "common/util.h" -#include "net/net_helper.h" -#include "math_helper.h" -#include "p2p_protocol_defs.h" -#include "net_peerlist_boost_serialization.h" -#include "net/local_ip.h" -#include "crypto/crypto.h" -#include "storages/levin_abstract_invoke2.h" - - -namespace nodetool -{ - //zero network before launch - const static boost::uuids::uuid P2P_NETWORK_ID = { { 0x11, 0x10, 0x01, 0x11, 0x01, 0x01, 0x11, 0x01, 0x10, 0x11, P2P_NETWORK_ID_TESTNET_FLAG, 0x11, 0x01, 0x11, 0x21, P2P_NETWORK_ID_VER} }; - - namespace - { - const command_line::arg_descriptor arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"}; - const command_line::arg_descriptor arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)}; - const command_line::arg_descriptor arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0}; - const command_line::arg_descriptor arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"}; - const command_line::arg_descriptor > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"}; - const command_line::arg_descriptor > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"}; - const command_line::arg_descriptor arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"}; - const command_line::arg_descriptor > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"}; - const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; - const command_line::arg_descriptor arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true }; - const command_line::arg_descriptor arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true }; - const command_line::arg_descriptor arg_p2p_ip_auto_blocking = { "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 0, false }; - } - - //----------------------------------------------------------------------------------- - template - void node_server::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_p2p_bind_ip); - command_line::add_arg(desc, arg_p2p_bind_port); - command_line::add_arg(desc, arg_p2p_external_port); - command_line::add_arg(desc, arg_p2p_allow_local_ip); - command_line::add_arg(desc, arg_p2p_add_peer); - command_line::add_arg(desc, arg_p2p_add_priority_node); - command_line::add_arg(desc, arg_p2p_seed_node); - command_line::add_arg(desc, arg_p2p_hide_my_port); - command_line::add_arg(desc, arg_p2p_offline_mode); - command_line::add_arg(desc, arg_p2p_disable_debug_reqs); - command_line::add_arg(desc, arg_p2p_use_only_priority_nodes); - command_line::add_arg(desc, arg_p2p_ip_auto_blocking); - } - //----------------------------------------------------------------------------------- - template - bool node_server::init_config() - { - // - TRY_ENTRY(); - bool r = string_tools::hex_to_pod(P2P_MAINTAINERS_PUB_KEY, m_maintainers_pub_key); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse P2P_MAINTAINERS_PUB_KEY = " << P2P_MAINTAINERS_PUB_KEY); - - std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME; - boost::system::error_code ec = AUTO_VAL_INIT(ec); - std::time_t last_update_time = boost::filesystem::last_write_time(state_file_path, ec); - //let's assume that if p2p peer list file stored more then 2 weeks ago, - //then it outdated and we need to fetch peerlist from seed nodes - if (!ec && time(nullptr) - last_update_time < 86400 * 14) - { - tools::unserialize_obj_from_file(*this, state_file_path); - } - - //always use new id, to be able differ cloned computers - m_config.m_peer_id = crypto::rand(); - - handle_alert_conditions(); - - //at this moment we have hardcoded config - m_config.m_net_config.handshake_interval = P2P_DEFAULT_HANDSHAKE_INTERVAL; - m_config.m_net_config.connections_count = P2P_DEFAULT_CONNECTIONS_COUNT; - m_config.m_net_config.packet_max_size = P2P_DEFAULT_PACKET_MAX_SIZE; //20 MB limit - m_config.m_net_config.config_id = 0; // initial config - m_config.m_net_config.connection_timeout = P2P_DEFAULT_CONNECTION_TIMEOUT; - m_config.m_net_config.ping_connection_timeout = P2P_DEFAULT_PING_CONNECTION_TIMEOUT; - m_config.m_net_config.send_peerlist_sz = P2P_DEFAULT_PEERS_IN_HANDSHAKE; - - m_first_connection_maker_call = true; - CATCH_ENTRY_L0("node_server::init_config", false); - return true; - } - //----------------------------------------------------------------------------------- - template - void node_server::for_each_connection(std::function f) - { - m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){ - return f(cntx, cntx.peer_id); - }); - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_remote_ip_allowed(uint32_t addr) - { - if (m_offline_mode) - return false; - - if (!m_ip_auto_blocking_enabled) - return true; - - return !is_ip_in_blacklist(addr); - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_ip_good_for_adding_to_peerlist(uint32_t addr) - { - if (m_offline_mode) - return false; - - // even if IP auto blocking is disabled, bad peers should not be added to peerlists and be shared with other nodes - - return !is_ip_in_blacklist(addr); - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_ip_in_blacklist(uint32_t addr) - { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - auto it = m_blocked_ips.find(addr); - if (it == m_blocked_ips.end()) - return false; - - if (time(nullptr) - it->second > P2P_IP_BLOCKTIME) - { - m_blocked_ips.erase(it); - LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " is unblocked due to blocking expiration.", LOG_LEVEL_0); - return false; - } - - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::block_ip(uint32_t addr) - { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - m_blocked_ips[addr] = time(nullptr); - m_peerlist.remove_peers_by_ip_from_all(addr); - LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " blocked and removed from peerlist", LOG_LEVEL_0); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::add_ip_fail(uint32_t address) - { - CRITICAL_REGION_LOCAL(m_ip_fails_score_lock); - uint64_t fails = ++m_ip_fails_score[address]; - if(fails > P2P_IP_FAILS_BEFOR_BLOCK) - { - auto it = m_ip_fails_score.find(address); - CHECK_AND_ASSERT_MES(it != m_ip_fails_score.end(), false, "internal error"); - it->second = P2P_IP_FAILS_BEFOR_BLOCK/2; - block_ip(address); - } - else - { - LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(address) << ": fail recorded, total fails count: " << fails, LOG_LEVEL_2); - } - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_stop_signal_sent() - { - return m_net_server.is_stop_signal_sent(); - } - //----------------------------------------------------------------------------------- - template - bool node_server::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr) - { - return string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr); - } - //----------------------------------------------------------------------------------- - template - bool node_server::handle_command_line(const boost::program_options::variables_map& vm) - { - m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip); - m_port = command_line::get_arg(vm, arg_p2p_bind_port); - m_external_port = command_line::get_arg(vm, arg_p2p_external_port); - m_allow_local_ip = command_line::get_arg(vm, arg_p2p_allow_local_ip); - m_offline_mode = command_line::get_arg(vm, arg_p2p_offline_mode); - m_debug_requests_enabled = !command_line::get_arg(vm, arg_p2p_disable_debug_reqs); - m_ip_auto_blocking_enabled = (command_line::get_arg(vm, arg_p2p_ip_auto_blocking) != 0); - - LOG_PRINT_L0("p2p peers auto-blocking is " << (m_ip_auto_blocking_enabled ? "enabled" : "disabled")); - - if (m_offline_mode) - { - LOG_PRINT_CYAN("Daemon running in offline mode", LOG_LEVEL_0); - } - - if (command_line::has_arg(vm, arg_p2p_add_peer)) - { - std::vector perrs = command_line::get_arg(vm, arg_p2p_add_peer); - for(const std::string& pr_str: perrs) - { - nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe); - pe.id = crypto::rand(); - bool r = parse_peer_from_string(pe.adr, pr_str); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - m_command_line_peers.push_back(pe); - } - } - - if (command_line::has_arg(vm, arg_p2p_add_priority_node)) - { - std::vector perrs = command_line::get_arg(vm, arg_p2p_add_priority_node); - for(const std::string& pr_str: perrs) - { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - m_priority_peers.push_back(na); - } - } - if(command_line::has_arg(vm, arg_p2p_use_only_priority_nodes)) - m_use_only_priority_peers = true; - - - if (command_line::has_arg(vm, arg_p2p_seed_node)) - { - std::vector seed_perrs = command_line::get_arg(vm, arg_p2p_seed_node); - for(const std::string& pr_str: seed_perrs) - { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse seed address from string: " << pr_str); - m_seed_nodes.push_back(na); - } - } - if(command_line::has_arg(vm, arg_p2p_hide_my_port)) - m_hide_my_port = true; - - return true; - } - //----------------------------------------------------------------------------------- - namespace - { - - - - template - bool append_net_address(T& nodes, const std::string& addr) - { - using namespace boost::asio; - - size_t pos = addr.find_last_of(':'); - CHECK_AND_ASSERT_MES(std::string::npos != pos && addr.length() - 1 != pos && 0 != pos, false, "Failed to parse seed address from string: '" << addr << '\''); - std::string host = addr.substr(0, pos); - std::string port = addr.substr(pos + 1); - int iport = 0; - bool r = epee::string_tools::get_xtype_from_string(iport, port); - CHECK_AND_ASSERT_MES(r, false, "wrong port string format"); - return append_net_address(nodes, host, iport); - - } - template - bool append_net_address(T& nodes, const std::string& host, int port) - { - using namespace boost::asio; - - std::string portstr = std::to_string(port); - - io_service io_srv; - ip::tcp::resolver resolver(io_srv); - ip::tcp::resolver::query query(host, portstr); - boost::system::error_code ec; - ip::tcp::resolver::iterator i = resolver.resolve(query, ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to resolve host name '" << host << "': " << ec.message() << ':' << ec.value()); - - ip::tcp::resolver::iterator iend; - for (; i != iend; ++i) - { - ip::tcp::endpoint endpoint = *i; - if (endpoint.address().is_v4()) - { - nodetool::net_address na; - na.ip = boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()); - na.port = endpoint.port(); - nodes.push_back(na); - LOG_PRINT_L4("Added seed node: " << endpoint.address().to_v4().to_string(ec) << ':' << na.port); - } - else - { - LOG_PRINT_L2("IPv6 doesn't supported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); - } - } - - return true; - } - } - - #define ADD_HARDCODED_SEED_NODE(host, port) append_net_address(m_seed_nodes, host, port); - //----------------------------------------------------------------------------------- - template - bool node_server::init(const boost::program_options::variables_map& vm) - { -#ifndef TESTNET - //TODO: - //ADD_HARDCODED_SEED_NODE(std::string("0.0.0.0:") + std::to_string(P2P_DEFAULT_PORT)); - ADD_HARDCODED_SEED_NODE("95.217.43.225", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("94.130.137.230", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("95.217.42.247", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("94.130.160.115", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("195.201.107.230", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("95.217.46.49", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("159.69.76.144", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("144.76.183.143", P2P_DEFAULT_PORT); -#else - //TODO: - ADD_HARDCODED_SEED_NODE("95.217.43.225", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("94.130.137.230", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("95.217.42.247", P2P_DEFAULT_PORT); - ADD_HARDCODED_SEED_NODE("94.130.160.115", P2P_DEFAULT_PORT); -#endif - - bool res = handle_command_line(vm); - CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line"); - m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); - - res = init_config(); - CHECK_AND_ASSERT_MES(res, false, "Failed to init config."); - - res = m_peerlist.init(m_allow_local_ip); - CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist."); - - - for(auto& p: m_command_line_peers) - m_peerlist.append_with_peer_white(p); - - //only in case if we really sure that we have external visible ip - m_have_address = true; - m_ip_address = 0; - m_last_stat_request_time = 0; - - //configure self - m_net_server.set_threads_prefix("P2P"); - m_net_server.get_config_object().m_pcommands_handler = this; - m_net_server.get_config_object().m_invoke_timeout = P2P_DEFAULT_INVOKE_TIMEOUT; - m_net_server.set_connection_filter(this); - - //try to bind - LOG_PRINT_L0("Binding on " << m_bind_ip << ":" << m_port); - res = m_net_server.init_server(m_port, m_bind_ip); - CHECK_AND_ASSERT_MES(res, false, "Failed to bind server"); - - m_listenning_port = m_net_server.get_binded_port(); - LOG_PRINT_GREEN("Net service binded on " << m_bind_ip << ":" << m_listenning_port, LOG_LEVEL_0); - if(m_external_port) - LOG_PRINT_L0("External port defined as " << m_external_port); - return res; - } - //----------------------------------------------------------------------------------- - template - typename node_server::payload_net_handler& node_server::get_payload_object() - { - return m_payload_handler; - } - //----------------------------------------------------------------------------------- - template - bool node_server::run(bool sync_call) - { - //here you can set worker threads count - int thrds_count = 10; - - m_net_server.add_idle_handler(boost::bind(&node_server::idle_worker, this), 1000); - m_net_server.add_idle_handler(boost::bind(&t_payload_net_handler::on_idle, &m_payload_handler), 1000); - - //go to loop - LOG_PRINT("Run net_service loop( " << thrds_count << " threads)...", LOG_LEVEL_0); - if(!m_net_server.run_server(thrds_count, sync_call)) - { - LOG_ERROR("Failed to run net tcp server!"); - } - - if(sync_call) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); - return true; - } - - //----------------------------------------------------------------------------------- - template - uint64_t node_server::get_connections_count() - { - return m_net_server.get_config_object().get_connections_count(); - } - //----------------------------------------------------------------------------------- - template - bool node_server::deinit() - { - m_peerlist.deinit(); - m_net_server.deinit_server(); - return store_config(); - } - //----------------------------------------------------------------------------------- - template - bool node_server::store_config() - { - - TRY_ENTRY(); - if (!tools::create_directories_if_necessary(m_config_folder)) - { - LOG_PRINT_L0("Failed to create data directory: " << m_config_folder); - return false; - } - - std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME; - tools::serialize_obj_to_file(*this, state_file_path); - CATCH_ENTRY_L0("node_server::save", false); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::send_stop_signal() - { - m_net_server.send_stop_signal(); - LOG_PRINT_L0("[node] Stop signal sent"); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::get_maintainers_info(maintainers_info_external& me) - { - me.ver_major = m_maintainers_info_local.ver_major; - me.ver_minor = m_maintainers_info_local.ver_minor; - me.ver_revision = m_maintainers_info_local.ver_revision; - me.build_no = m_maintainers_info_local.build_no; - me.mode = m_alert_mode; - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::on_maintainers_entry_update() - { - LOG_PRINT_CHANNEL_COLOR2(NULL, NULL, "Fresh maintainers info recieved(timestamp: " << m_maintainers_info_local.timestamp << ")", LOG_LEVEL_0, epee::log_space::console_color_magenta); - if(PROJECT_VERSION_BUILD_NO < m_maintainers_info_local.build_no) - { - LOG_PRINT_CHANNEL_COLOR2(NULL, NULL, "Newer version avaliable: " << static_cast(m_maintainers_info_local.ver_major) << - "." << static_cast(m_maintainers_info_local.ver_minor) << - "." << static_cast(m_maintainers_info_local.ver_revision) << - "." << static_cast(m_maintainers_info_local.build_no) << - ", current version: " << PROJECT_VERSION_LONG, LOG_LEVEL_0, epee::log_space::console_color_magenta); - } - handle_alert_conditions(); - - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::handle_maintainers_entry(const maintainers_entry& me) - { - if(me.sign == AUTO_VAL_INIT(me.sign))//todo: make null_sig (and other null_xxx) available out of currency namespace - return true; - - bool r = crypto::check_signature(crypto::cn_fast_hash(me.maintainers_info_buff.data(), me.maintainers_info_buff.size()), m_maintainers_pub_key, me.sign); - CHECK_AND_ASSERT_MES(r, false, "Failed to check signature in maintainers_entry"); - //signature ok, load from blob - maintainers_info mi = AUTO_VAL_INIT(mi); - r = epee::serialization::load_t_from_binary(mi, me.maintainers_info_buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to load maintainers_info from maintainers_entry buff"); - if(mi.timestamp > m_maintainers_info_local.timestamp) - { - //lets update new - CRITICAL_REGION_LOCAL(m_maintainers_local_lock); - m_maintainers_entry_local = me; - m_maintainers_info_local = mi; - on_maintainers_entry_update(); - } - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::fill_maintainers_entry(maintainers_entry& me) - { - me = m_maintainers_entry_local; - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context_, bool just_take_peerlist) - { - typename COMMAND_HANDSHAKE::request arg = AUTO_VAL_INIT(arg); - typename COMMAND_HANDSHAKE::response rsp = AUTO_VAL_INIT(rsp); - get_local_node_data(arg.node_data); - m_payload_handler.get_payload_sync_data(arg.payload_data); - fill_maintainers_entry(arg.maintrs_entry); - - simple_event ev; - std::atomic hsh_result(false); - - bool r = net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(), - [this, &pi, &ev, &hsh_result, &just_take_peerlist](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context) - { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){ev.raise();}); - - if(code < 0) - { - LOG_PRINT_CC_RED(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_0); - return; - } - - if(rsp.node_data.network_id != P2P_NETWORK_ID) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong network!, closing connection."); - return; - } - - if (!tools::check_remote_client_version(rsp.payload_data.client_version)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); - return; - } - - if(!handle_maintainers_entry(rsp.maintrs_entry)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); - return; - } - - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.node_data.local_time, context)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection."); - add_ip_fail(context.m_remote_ip); - return; - } - hsh_result = true; - if(!just_take_peerlist) - { - if(!m_payload_handler.process_payload_sync_data(rsp.payload_data, context, true)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE invoked, but process_payload_sync_data returned false, dropping connection."); - hsh_result = false; - return; - } - - if (is_peer_id_used(rsp.node_data.peer_id)) - { - LOG_PRINT_L0("It seems that peer " << std::hex << rsp.node_data.peer_id << " has already been connected, dropping connection"); - hsh_result = false; - return; - } - - pi = context.peer_id = rsp.node_data.peer_id; - m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_ip, context.m_remote_port); - - if(rsp.node_data.peer_id == m_config.m_peer_id) - { - LOG_PRINT_L0("Connection to self detected, dropping connection"); - hsh_result = false; - return; - } - LOG_PRINT_L1(" COMMAND_HANDSHAKE INVOKED OK"); - }else - { - LOG_PRINT_L0(" COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK"); - //m_net_server.get_config_object().close(context_.m_connection_id); - } - }, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT); - - if(r) - { - ev.wait(); - } - - if(!hsh_result) - { - LOG_PRINT_CC_L0(context_, "COMMAND_HANDSHAKE Failed, closing connection"); - m_net_server.get_config_object().close(context_.m_connection_id); - } - - return hsh_result; - } - //----------------------------------------------------------------------------------- - template - bool node_server::do_peer_timed_sync(const net_utils::connection_context_base& context_, peerid_type peer_id) - { - typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg); - m_payload_handler.get_payload_sync_data(arg.payload_data); - fill_maintainers_entry(arg.maintrs_entry); - - bool r = net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(), - [this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context) - { - if(code < 0) - { - LOG_PRINT_CC_RED(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_1); - return; - } - - if(!handle_maintainers_entry(rsp.maintrs_entry)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); - return; - } - - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.local_time, context)) - { - LOG_ERROR_CCONTEXT("COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection."); - m_net_server.get_config_object().close(context.m_connection_id ); - add_ip_fail(context.m_remote_ip); - } - if(!context.m_is_income) - m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_ip, context.m_remote_port); - m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false); - }); - - if(!r) - { - LOG_PRINT_CC_L2(context_, "COMMAND_TIMED_SYNC Failed"); - return false; - } - return true; - } - //----------------------------------------------------------------------------------- - template - size_t node_server::get_random_index_with_fixed_probability(size_t max_index) - { - //divide by zero workaround - if(!max_index) - return 0; - - size_t x = crypto::rand()%(max_index+1); - size_t res = (x*x*x)/(max_index*max_index); //parabola \/ - LOG_PRINT_L3("Random connection index=" << res << "(x="<< x << ", max_index=" << max_index << ")"); - return res; - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_peer_id_used(const peerid_type id) - { - if (id == m_config.m_peer_id) - return true; // ourself - - bool used = false; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if (id == cntxt.peer_id) - { - used = true; - return false; // stop enumerating - } - return true; - }); - - return used; - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_peer_used(const peerlist_entry& peer) - { - - if(m_config.m_peer_id == peer.id) - return true;//dont make connections to ourself - - bool used = false; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) - { - used = true; - return false;//stop enumerating - } - return true; - }); - - return used; - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_addr_connected(const net_address& peer) - { - bool connected = false; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if(!cntxt.m_is_income && peer.ip == cntxt.m_remote_ip && peer.port == cntxt.m_remote_port) - { - connected = true; - return false;//stop enumerating - } - return true; - }); - - return connected; - } - - //----------------------------------------------------------------------------------- - template - bool node_server::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white) - { - LOG_PRINT_L1("Connecting to " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: " << (last_seen_stamp?misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never" ) << ")..."); - - typename net_server::t_connection_context con = AUTO_VAL_INIT(con); - bool res = m_net_server.connect(string_tools::get_ip_string_from_int32(na.ip), - string_tools::num_to_string_fast(na.port), - m_config.m_net_config.connection_timeout, - con); - if(!res) - { - LOG_PRINT_L1("Connect failed to " - << string_tools::get_ip_string_from_int32(na.ip) - << ":" << string_tools::num_to_string_fast(na.port) - /*<< ", try " << try_count*/); - return false; - } - peerid_type pi = AUTO_VAL_INIT(pi); - res = do_handshake_with_peer(pi, con, just_take_peerlist); - if(!res) - { - LOG_PRINT_CC_L0(con, "Failed to HANDSHAKE with peer " - << string_tools::get_ip_string_from_int32(na.ip) - << ":" << string_tools::num_to_string_fast(na.port) - << ", closing connection"); - m_net_server.get_config_object().close(con.m_connection_id); - return false; - } - - if(just_take_peerlist) - { - m_net_server.get_config_object().close(con.m_connection_id); - LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK AND CLOSED with peer " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port), LOG_LEVEL_2); - return true; - } - - if (is_ip_good_for_adding_to_peerlist(na.ip)) // additional check to avoid IP shown up in peers in the case of non-blocking incoming connections - { - //update last seen and push it to peerlist manager - peerlist_entry pe_local = AUTO_VAL_INIT(pe_local); - pe_local.adr = na; - pe_local.id = pi; - time(&pe_local.last_seen); - m_peerlist.append_with_peer_white(pe_local); - } - - LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK with peer " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port), LOG_LEVEL_2); - return true; - } - //----------------------------------------------------------------------------------- - template - void node_server::cache_connect_fail_info(const net_address& addr) - { - CRITICAL_REGION_LOCAL(m_conn_fails_cache_lock); - m_conn_fails_cache[addr] = time(NULL); - } - //----------------------------------------------------------------------------------- - template - bool node_server::is_addr_recently_failed(const net_address& addr) - { - CRITICAL_REGION_LOCAL(m_conn_fails_cache_lock); - auto it = m_conn_fails_cache.find(addr); - if(it == m_conn_fails_cache.end()) - return false; - - if(time(NULL) - it->second > P2P_FAILED_ADDR_FORGET_SECONDS) - return false; - else - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::make_new_connection_from_peerlist(bool use_white_list) - { - size_t local_peers_count = use_white_list ? m_peerlist.get_white_peers_count():m_peerlist.get_gray_peers_count(); - if(!local_peers_count) - return false;//no peers - - size_t max_random_index = std::min(local_peers_count -1, 50); - - std::set tried_peers; - - size_t try_count = 0; - size_t rand_count = 0; - size_t peer_index = 0; - size_t peers_count = use_white_list ? m_peerlist.get_white_peers_count() : m_peerlist.get_gray_peers_count(); - while (rand_count < (max_random_index + 1) * 3 && try_count < 10 && !m_net_server.is_stop_signal_sent() && peer_index < peers_count) - { - - ++rand_count; - if (peers_count > 15) - peer_index = get_random_index_with_fixed_probability(max_random_index); - - CHECK_AND_ASSERT_MES(peer_index < local_peers_count, false, "random_starter_index < peers_local.size() failed!!"); - - if (tried_peers.count(peer_index)) - { - ++peer_index; - continue; - } - - tried_peers.insert(peer_index); - peerlist_entry pe = AUTO_VAL_INIT(pe); - bool r = use_white_list ? m_peerlist.get_white_peer_by_index(pe, peer_index):m_peerlist.get_gray_peer_by_index(pe, peer_index); - if (!r) return true; - //CHECK_AND_ASSERT_MES(r, false, "Failed to get random peer from peerlist(white:" << use_white_list << ")"); - - ++try_count; - - if (is_peer_used(pe)) - { - ++peer_index; - continue; - } - - if (!is_remote_ip_allowed(pe.adr.ip)) - { - ++peer_index; - continue; - } - - if (is_addr_recently_failed(pe.adr)) - { - ++peer_index; - continue; - } - - LOG_PRINT_L1("Selected peer: " << pe.id << " " << string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast(pe.adr.port) << "[white=" << use_white_list << "] last_seen: " << (pe.last_seen ? misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); - - if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list)) - { - cache_connect_fail_info(pe.adr); - ++peer_index; - continue; - } - - return true; - } - return false; - } - //----------------------------------------------------------------------------------- - template - bool node_server::connections_maker() - { - if (m_offline_mode) - return true; - - if(!m_peerlist.get_white_peers_count() && m_seed_nodes.size() && !m_priority_peers.size()) - { - size_t try_count = 0; - size_t current_index = crypto::rand()%m_seed_nodes.size(); - while(true) - { - if(m_net_server.is_stop_signal_sent()) - return false; - - if(try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true)) - break; - if(++try_count > m_seed_nodes.size()) - { - LOG_PRINT_RED_L0("Failed to connect to any of seed peers, continuing without seeds"); - break; - } - if(++current_index >= m_seed_nodes.size()) - current_index = 0; - } - } - - for(const net_address& na: m_priority_peers) - { - if(m_net_server.is_stop_signal_sent()) - return false; - - if(is_addr_connected(na)) - continue; - if (!try_to_connect_and_handshake_with_new_peer(na)) - { - LOG_PRINT_L0("connection to priority node " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port) << " failed"); - } - } - if(m_use_only_priority_peers) - return true; - - size_t expected_white_connections = (m_config.m_net_config.connections_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100; - - size_t conn_count = get_outgoing_connections_count(); - if(conn_count < m_config.m_net_config.connections_count) - { - if(conn_count < expected_white_connections) - { - //start from white list - if(!make_expected_connections_count(true, expected_white_connections)) - return false; - //and then do grey list - if(!make_expected_connections_count(false, m_config.m_net_config.connections_count)) - return false; - }else - { - //start from grey list - if(!make_expected_connections_count(false, m_config.m_net_config.connections_count)) - return false; - //and then do white list - if(!make_expected_connections_count(true, m_config.m_net_config.connections_count)) - return false; - } - } - - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::make_expected_connections_count(bool white_list, size_t expected_connections) - { - size_t conn_count = get_outgoing_connections_count(); - //add new connections from white peers - while(conn_count < expected_connections) - { - if(m_net_server.is_stop_signal_sent()) - return false; - - if(!make_new_connection_from_peerlist(white_list)) - break; - conn_count = get_outgoing_connections_count(); - } - return true; - } - - //----------------------------------------------------------------------------------- - template - size_t node_server::get_outgoing_connections_count() - { - size_t count = 0; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if(!cntxt.m_is_income) - ++count; - return true; - }); - - return count; - } - //----------------------------------------------------------------------------------- - template - bool node_server::remove_dead_connections() - { - uint64_t curr_time = time(nullptr); - m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){ - if(curr_time - cntx.m_last_recv > P2P_IDLE_CONNECTION_KILL_INTERVAL && curr_time - cntx.m_last_send > P2P_IDLE_CONNECTION_KILL_INTERVAL) - { - LOG_PRINT_CC_L1(cntx, "Connection dropped due to idle"); - m_net_server.get_config_object().close(cntx.m_connection_id); - return true; - } - return true; - }); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::idle_worker() - { - m_peer_handshake_idle_maker_interval.do_call(boost::bind(&node_server::peer_sync_idle_maker, this)); - m_connections_maker_interval.do_call(boost::bind(&node_server::connections_maker, this)); - m_peerlist_store_interval.do_call(boost::bind(&node_server::store_config, this)); - m_remove_dead_conn_interval.do_call([this](){return remove_dead_connections();}); - - m_calm_alert_interval.do_call([&](){return calm_alert_worker();}); - m_urgent_alert_interval.do_call([&](){return urgent_alert_worker();}); - m_critical_alert_interval.do_call([&](){return critical_alert_worker();}); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::calm_alert_worker() - { - if(m_alert_mode != ALERT_TYPE_CALM) - return true; - - LOG_PRINT_CHANNEL2(NULL, NULL, "This software is outdated, please update.", LOG_LEVEL_0); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::urgent_alert_worker() - { - if(m_alert_mode != ALERT_TYPE_URGENT) - return true; - - LOG_PRINT_CHANNEL_COLOR2(NULL, NULL, "[URGENT]:This software is dramatically outdated, please update to latest version.", LOG_LEVEL_0, epee::log_space::console_color_cyan); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::critical_alert_worker() - { - if(m_alert_mode != ALERT_TYPE_CRITICAL) - return true; - - LOG_PRINT_CHANNEL_COLOR2(NULL, NULL, "[CRITICAL]:This software is critically outdated, please update to latest version.", LOG_LEVEL_0, epee::log_space::console_color_red); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::handle_alert_conditions() - { - CRITICAL_REGION_LOCAL(m_maintainers_local_lock); - m_alert_mode = 0; - for(auto c: m_maintainers_info_local.conditions) - { - if(PROJECT_VERSION_BUILD_NO < c.if_build_less_then && c.alert_mode > m_alert_mode) - m_alert_mode = c.alert_mode; - } - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::peer_sync_idle_maker() - { - LOG_PRINT_L2("STARTED PEERLIST IDLE HANDSHAKE"); - typedef std::list > local_connects_type; - local_connects_type cncts; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if(cntxt.peer_id) - cncts.push_back(local_connects_type::value_type(cntxt, cntxt.peer_id));//do idle sync only with handshaked connections - return true; - }); - - std::for_each(cncts.begin(), cncts.end(), [&](const typename local_connects_type::value_type& vl){do_peer_timed_sync(vl.first, vl.second);}); - - LOG_PRINT_L2("FINISHED PEERLIST IDLE HANDSHAKE"); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::fix_time_delta(std::list& local_peerlist, time_t local_time, int64_t& delta) - { - //fix time delta - time_t now = 0; - time(&now); - delta = now - local_time; - - BOOST_FOREACH(peerlist_entry& be, local_peerlist) - { - if(be.last_seen > local_time) - { - LOG_PRINT_RED_L0("FOUND FUTURE peerlist for entry " << string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); - return false; - } - be.last_seen += delta; - } - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::handle_remote_peerlist(const std::list& peerlist, time_t local_time, const net_utils::connection_context_base& context) - { - int64_t delta = 0; - std::list peerlist_ = peerlist; - if(!fix_time_delta(peerlist_, local_time, delta)) - return false; - LOG_PRINT_L2("REMOTE PEERLIST: TIME_DELTA: " << delta << ", remote peerlist size=" << peerlist_.size()); - LOG_PRINT_L3("REMOTE PEERLIST: " << print_peerlist_to_string(peerlist_)); - return m_peerlist.merge_peerlist(peerlist_); - } - //----------------------------------------------------------------------------------- - template - bool node_server::get_local_node_data(basic_node_data& node_data) - { - node_data.local_time = time(NULL); - node_data.peer_id = m_config.m_peer_id; - if(!m_hide_my_port) - node_data.my_port = m_external_port ? m_external_port : m_listenning_port; - else - node_data.my_port = 0; - node_data.network_id = P2P_NETWORK_ID; - return true; - } - //----------------------------------------------------------------------------------- -#ifdef ALLOW_DEBUG_COMMANDS - template - bool node_server::check_trust(const proof_of_trust& tr) - { - int64_t local_time = time(NULL); - int64_t time_delata = local_time > tr.time ? local_time - tr.time: tr.time - local_time; - if(time_delata > 24*60*60 ) - { - LOG_PRINT_L0("check_trust failed to check time conditions, local_time=" << local_time << ", proof_time=" << tr.time); - return false; - } - if(m_last_stat_request_time >= tr.time ) - { - LOG_PRINT_L0("check_trust failed to check time conditions, last_stat_request_time=" << m_last_stat_request_time << ", proof_time=" << tr.time); - return false; - } - if(m_config.m_peer_id != tr.peer_id) - { - LOG_PRINT_L0("check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << m_config.m_peer_id<< ")"); - return false; - } - crypto::public_key pk = AUTO_VAL_INIT(pk); - string_tools::hex_to_pod(P2P_MAINTAINERS_PUB_KEY, pk); - crypto::hash h = tools::get_proof_of_trust_hash(tr); - if(!crypto::check_signature(h, pk, tr.sign)) - { - LOG_ERROR("check_trust failed: sign check failed"); - return false; - } - //update last request time - m_last_stat_request_time = tr.time; - return true; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_get_stat_info(int command, typename COMMAND_REQUEST_STAT_INFO::request& arg, typename COMMAND_REQUEST_STAT_INFO::response& rsp, p2p_connection_context& context) - { - if(!check_trust(arg.tr)) - { - drop_connection(context); - return 1; - } - rsp.connections_count = m_net_server.get_config_object().get_connections_count(); - rsp.incoming_connections_count = rsp.connections_count - get_outgoing_connections_count(); - rsp.version = PROJECT_VERSION_LONG; - rsp.current_log_size = tools::get_log_file_size(); - m_payload_handler.get_stat_info(arg.pr, rsp.payload_info); - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_get_network_state(int command, COMMAND_REQUEST_NETWORK_STATE::request& arg, COMMAND_REQUEST_NETWORK_STATE::response& rsp, p2p_connection_context& context) - { - if(!check_trust(arg.tr)) - { - drop_connection(context); - return 1; - } - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - connection_entry ce; - ce.adr.ip = cntxt.m_remote_ip; - ce.adr.port = cntxt.m_remote_port; - ce.id = cntxt.peer_id; - ce.is_income = cntxt.m_is_income; - ce.time_started = cntxt.m_started; - ce.last_recv = cntxt.m_last_recv; - ce.last_send = cntxt.m_last_send; - size_t len = std::min(sizeof(ce.version) - 1, cntxt.m_remote_version.size()); - std::strncpy(ce.version, cntxt.m_remote_version.c_str(), len); - ce.version[len] = 0; //null terminating just to be sure - rsp.connections_list.push_back(ce); - return true; - }); - - m_peerlist.get_peerlist_full(rsp.local_peerlist_gray, rsp.local_peerlist_white); - rsp.my_id = m_config.m_peer_id; - rsp.local_time = time(NULL); - rsp.up_time = rsp.local_time - m_startup_time; - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_get_peer_id(int command, COMMAND_REQUEST_PEER_ID::request& arg, COMMAND_REQUEST_PEER_ID::response& rsp, p2p_connection_context& context) - { - rsp.my_id = m_config.m_peer_id; - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_request_log(int command, COMMAND_REQUEST_LOG::request& req, COMMAND_REQUEST_LOG::response& rsp, p2p_connection_context& context) - { - if (!check_trust(req.tr)) - { - drop_connection(context); - return 1; - } - - rsp.current_log_level = static_cast(log_space::get_set_log_detalisation_level()); - tools::get_log_chunk_gzipped(req.log_chunk_offset, req.log_chunk_size, rsp.log_chunk, rsp.error); - rsp.current_log_size = tools::get_log_file_size(); - - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_set_log_level(int command, COMMAND_SET_LOG_LEVEL::request& req, COMMAND_SET_LOG_LEVEL::response& rsp, p2p_connection_context& context) - { - if (!check_trust(req.tr)) - { - drop_connection(context); - return 1; - } - - rsp.old_log_level = static_cast(log_space::get_set_log_detalisation_level()); - log_space::get_set_log_detalisation_level(true, static_cast(req.new_log_level)); - rsp.current_log_level = static_cast(log_space::get_set_log_detalisation_level()); - - if (rsp.old_log_level != rsp.current_log_level) - { - LOG_PRINT_CC(context, "log level changed by debug command: " << rsp.old_log_level << " -> " << rsp.current_log_level, LOG_LEVEL_0); - } - - return 1; - } -#endif // #ifdef ALLOW_DEBUG_COMMANDS - //----------------------------------------------------------------------------------- - template - void node_server::request_callback(const epee::net_utils::connection_context_base& context) - { - m_net_server.get_config_object().request_callback(context.m_connection_id); - } - //----------------------------------------------------------------------------------- - template - bool node_server::relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context, std::list& relayed_peers) - { - relayed_peers.clear(); - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - if(cntxt.peer_id && context.m_connection_id != cntxt.m_connection_id) - relayed_peers.push_back(cntxt); - return true; - }); - - BOOST_FOREACH(const auto& cntx, relayed_peers) - { - m_net_server.get_config_object().notify(command, data_buff, cntx.m_connection_id); - } - return true; - } - //----------------------------------------------------------------------------------- - template - void node_server::get_connections(std::list& connections) - { - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - connections.push_back(cntxt); - return true; - }); - } - template - void node_server::callback(p2p_connection_context& context) - { - m_payload_handler.on_callback(context); - } - //----------------------------------------------------------------------------------- - template - bool node_server::invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context) - { - int res = m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id); - return res > 0; - } - //----------------------------------------------------------------------------------- - template - bool node_server::invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context) - { - int res = m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id); - return res > 0; - } - //----------------------------------------------------------------------------------- - template - bool node_server::drop_connection(const epee::net_utils::connection_context_base& context) - { - m_net_server.get_config_object().close(context.m_connection_id); - return true; - } - //----------------------------------------------------------------------------------- - template template - bool node_server::try_ping(basic_node_data& node_data, p2p_connection_context& context, const t_callback& cb) - { - if(!node_data.my_port) - return false; - - uint32_t actual_ip = context.m_remote_ip; - if(!m_peerlist.is_ip_allowed(actual_ip)) - return false; - std::string ip = string_tools::get_ip_string_from_int32(actual_ip); - std::string port = string_tools::num_to_string_fast(node_data.my_port); - peerid_type pr = node_data.peer_id; - bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ ip, port, pr, this]( - const typename net_server::t_connection_context& ping_context, - const boost::system::error_code& ec)->bool - { - if(ec) - { - LOG_PRINT_CC_L2(ping_context, "back ping connect failed to " << ip << ":" << port); - return false; - } - COMMAND_PING::request req; - COMMAND_PING::response rsp; - //vc2010 workaround - /*std::string ip_ = ip; - std::string port_=port; - peerid_type pr_ = pr; - auto cb_ = cb;*/ - bool inv_call_res = net_utils::async_invoke_remote_command2(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(), - [=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context) - { - if(code <= 0) - { - LOG_PRINT_CC_L2(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << levin::get_err_descr(code) << ")"); - m_net_server.get_config_object().close(ping_context.m_connection_id); - return; - } - - if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id) - { - LOG_PRINT_CC_L2(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from " << ip << ":" << port << ", hsh_peer_id=" << pr << ", rsp.peer_id=" << rsp.peer_id); - m_net_server.get_config_object().close(ping_context.m_connection_id); - return; - } - m_net_server.get_config_object().close(ping_context.m_connection_id); - cb(); - }); - - if(!inv_call_res) - { - LOG_PRINT_CC_L2(ping_context, "back ping invoke failed to " << ip << ":" << port); - m_net_server.get_config_object().close(ping_context.m_connection_id); - return false; - } - return true; - }); - if(!r) - { - LOG_ERROR("Failed to call connect_async, network error."); - } - return r; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_timed_sync(int command, typename COMMAND_TIMED_SYNC::request& arg, typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context) - { - if(!handle_maintainers_entry(arg.maintrs_entry)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); - return 1; - } - - if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, false)) - { - LOG_ERROR_CCONTEXT("Failed to process_payload_sync_data(), dropping connection"); - drop_connection(context); - return 1; - } - - //fill response - rsp.local_time = time(NULL); - m_peerlist.get_peerlist_head(rsp.local_peerlist); - m_payload_handler.get_payload_sync_data(rsp.payload_data); - fill_maintainers_entry(rsp.maintrs_entry); - LOG_PRINT_L3("COMMAND_TIMED_SYNC"); - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_handshake(int command, typename COMMAND_HANDSHAKE::request& arg, typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context) - { - if(arg.node_data.network_id != P2P_NETWORK_ID) - { - - LOG_PRINT_L0("WRONG NETWORK AGENT CONNECTED! id=" << string_tools::get_str_from_guid_a(arg.node_data.network_id)); - drop_connection(context); - add_ip_fail(context.m_remote_ip); - return 1; - } - - if(!context.m_is_income) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE came not from incoming connection"); - drop_connection(context); - add_ip_fail(context.m_remote_ip); - return 1; - } - - if(context.peer_id) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE came, but seems that connection already have associated peer_id (double COMMAND_HANDSHAKE?)"); - drop_connection(context); - return 1; - } - - if (is_peer_id_used(arg.node_data.peer_id)) - { - LOG_PRINT_CCONTEXT_L1("COMMAND_HANDSHAKE came, but seems that peer " << std::hex << arg.node_data.peer_id << " has already been connected to this node, dropping connection"); - drop_connection(context); - return 1; - } - - if (!tools::check_remote_client_version(arg.payload_data.client_version)) - { - LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << arg.payload_data.client_version << ", closing connection."); - drop_connection(context); - add_ip_fail(context.m_remote_ip); - return 1; - } - - if(!handle_maintainers_entry(arg.maintrs_entry)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); - return 1; - } - - if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, true)) - { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE came, but process_payload_sync_data returned false, dropping connection."); - drop_connection(context); - return 1; - } - //associate peer_id with this connection - context.peer_id = arg.node_data.peer_id; - - if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port - && is_ip_good_for_adding_to_peerlist(context.m_remote_ip)) - { - peerid_type peer_id_l = arg.node_data.peer_id; - uint32_t port_l = arg.node_data.my_port; - //try ping to be sure that we can add this peer to peer_list - try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]() - { - //called only(!) if success pinged, update local peerlist - peerlist_entry pe; - pe.adr.ip = context.m_remote_ip; - pe.adr.port = port_l; - time(&pe.last_seen); - pe.id = peer_id_l; - this->m_peerlist.append_with_peer_white(pe); - LOG_PRINT_L2("PING SUCCESS " << string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); - }); - } - - //fill response - m_peerlist.get_peerlist_head(rsp.local_peerlist); - get_local_node_data(rsp.node_data); - m_payload_handler.get_payload_sync_data(rsp.payload_data); - fill_maintainers_entry(rsp.maintrs_entry); - LOG_PRINT_GREEN("COMMAND_HANDSHAKE: v" << arg.payload_data.client_version << " top: " << epee::string_tools::pod_to_hex(arg.payload_data.top_id).substr(0, 6) << " @ " << arg.payload_data.current_height - 1, LOG_LEVEL_1); - return 1; - } - //----------------------------------------------------------------------------------- - template - int node_server::handle_ping(int command, COMMAND_PING::request& arg, COMMAND_PING::response& rsp, p2p_connection_context& context) - { - LOG_PRINT_L2("COMMAND_PING"); - rsp.status = PING_OK_RESPONSE_STATUS_TEXT; - rsp.peer_id = m_config.m_peer_id; - return 1; - } - //----------------------------------------------------------------------------------- - template - bool node_server::log_peerlist() - { - std::list pl_wite; - std::list pl_gray; - m_peerlist.get_peerlist_full(pl_gray, pl_wite); - LOG_PRINT_L0(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_wite) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) ); - return true; - } - //----------------------------------------------------------------------------------- - template - bool node_server::log_connections() - { - LOG_PRINT_L0("Connections: \r\n" << print_connections_container() ); - return true; - } - //----------------------------------------------------------------------------------- - template - std::string node_server::print_connections_container() - { - - std::stringstream ss; - m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) - { - ss << string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port - << " \t\tpeer_id " << cntxt.peer_id - << " \t\tconn_id " << string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT") - << std::endl; - return true; - }); - std::string s = ss.str(); - return s; - } - - //----------------------------------------------------------------------------------- - template - void node_server::on_connection_new(p2p_connection_context& context) - { - LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] NEW CONNECTION"); - } - //----------------------------------------------------------------------------------- - template - void node_server::on_connection_close(p2p_connection_context& context) - { - LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] CLOSE CONNECTION"); - } - //----------------------------------------------------------------------------------- -} diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h deleted file mode 100644 index 12fe645..0000000 --- a/src/p2p/net_node_common.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "net/net_utils_base.h" -#include "p2p_protocol_defs.h" - -namespace nodetool -{ - - typedef boost::uuids::uuid uuid; - typedef boost::uuids::uuid net_connection_id; - - template - struct i_p2p_endpoint - { - virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context, std::list& relayed_peers) = 0; - virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0; - virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context)=0; - virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0; - virtual void request_callback(const epee::net_utils::connection_context_base& context)=0; - virtual uint64_t get_connections_count()=0; - virtual void get_connections(std::list& connections) = 0; - virtual void for_each_connection(std::function f)=0; - virtual bool block_ip(uint32_t adress)=0; - virtual bool add_ip_fail(uint32_t adress)=0; - virtual bool is_stop_signal_sent() = 0; - }; - - template - struct p2p_endpoint_stub: public i_p2p_endpoint - { - virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context, std::list& relayed_peers) - { - return false; - } - virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context) - { - return false; - } - virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context) - { - return true; - } - virtual bool drop_connection(const epee::net_utils::connection_context_base& context) - { - return false; - } - virtual void request_callback(const epee::net_utils::connection_context_base& context) - { - - } - virtual void for_each_connection(std::function f) - { - - } - - virtual uint64_t get_connections_count() - { - return false; - } - virtual void get_connections(std::list& connections) - { - - } - virtual bool block_ip(uint32_t adress) - { - return true; - } - virtual bool add_ip_fail(uint32_t adress) - { - return true; - } - virtual bool is_stop_signal_sent() - { - return false; - } - }; -} diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h deleted file mode 100644 index f133683..0000000 --- a/src/p2p/net_peerlist.h +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2014-2021 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -#include "syncobj.h" -#include "net/local_ip.h" -#include "p2p_protocol_defs.h" -#include "currency_core/currency_config.h" -#include "net_peerlist_boost_serialization.h" -#include "common/boost_serialization_helper.h" - -#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER (CURRENCY_FORMATION_VERSION + 7) - -namespace nodetool -{ - - - /************************************************************************/ - /* */ - /************************************************************************/ - class peerlist_manager - { - public: - bool init(bool allow_local_ip); - bool deinit(); - size_t get_white_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_white.size();} - size_t get_gray_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_gray.size();} - bool merge_peerlist(const std::list& outer_bs); - bool get_peerlist_head(std::list& bs_head, uint32_t depth = P2P_DEFAULT_PEERS_IN_HANDSHAKE); - bool get_peerlist_full(std::list& pl_gray, std::list& pl_white); - bool get_white_peer_by_index(peerlist_entry& p, size_t i); - bool get_gray_peer_by_index(peerlist_entry& p, size_t i); - bool append_with_peer_white(const peerlist_entry& pr); - bool append_with_peer_gray(const peerlist_entry& pr); - bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port); - bool set_peer_just_seen(peerid_type peer, const net_address& addr); - bool is_ip_allowed(uint32_t ip); - void trim_white_peerlist(); - void trim_gray_peerlist(); - bool remove_peers_by_ip_from_all(const uint32_t ip); - - - private: - struct by_time{}; - struct by_id{}; - struct by_addr{}; - - struct modify_all_but_id - { - modify_all_but_id(const peerlist_entry& ple):m_ple(ple){} - void operator()(peerlist_entry& e) - { - e.id = m_ple.id; - } - private: - const peerlist_entry& m_ple; - }; - - struct modify_all - { - modify_all(const peerlist_entry& ple):m_ple(ple){} - void operator()(peerlist_entry& e) - { - e = m_ple; - } - private: - const peerlist_entry& m_ple; - }; - - struct modify_last_seen - { - modify_last_seen(time_t last_seen):m_last_seen(last_seen){} - void operator()(peerlist_entry& e) - { - e.last_seen = m_last_seen; - } - private: - time_t m_last_seen; - }; - - - typedef boost::multi_index_container< - peerlist_entry, - boost::multi_index::indexed_by< - // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique, boost::multi_index::member >, - // sort by peerlist_entry::last_seen< - boost::multi_index::ordered_non_unique, boost::multi_index::member > - > - > peers_indexed; - - public: - - template - void serialize(Archive &ar, const t_version_type ver) - { - if(ver < CURRENT_PEERLIST_STORAGE_ARCHIVE_VER) - throw std::runtime_error("not supported storage format"); - CHECK_PROJECT_NAME(); - CRITICAL_REGION_LOCAL(m_peerlist_lock); - ar & m_peers_white; - ar & m_peers_gray; - } - - private: - friend class boost::serialization::access; - epee::critical_section m_peerlist_lock; - std::string m_config_folder; - bool m_allow_local_ip = false; - - - peers_indexed m_peers_gray; - peers_indexed m_peers_white; - }; - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::init(bool allow_local_ip) - { - time_t now = 0; - time(&now); - m_allow_local_ip = allow_local_ip; - - //adjust local time if it somehow was shifted - CRITICAL_REGION_LOCAL(m_peerlist_lock); - peers_indexed::index::type& by_time_index = m_peers_white.get(); - for(auto& v1: by_time_index) - { - if (v1.last_seen > now) - { - LOG_PRINT_L0("Local m_peers_white entries detected in future, cleaning peerlist."); - by_time_index.clear(); - break; - } - } - - peers_indexed::index::type& by_time_index_g = m_peers_gray.get(); - for (auto& v1 : by_time_index_g) - { - if (v1.last_seen > now) - { - LOG_PRINT_L0("Local m_peers_gray entries detected in future, cleaning peerlist."); - by_time_index_g.clear(); - break; - } - } - - - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::deinit() - { - return true; - } - //-------------------------------------------------------------------------------------------------- - inline void peerlist_manager::trim_white_peerlist() - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - while(m_peers_gray.size() > P2P_LOCAL_GRAY_PEERLIST_LIMIT) - { - peers_indexed::index::type& sorted_index=m_peers_gray.get(); - sorted_index.erase(sorted_index.begin()); - } - } - //-------------------------------------------------------------------------------------------------- - inline void peerlist_manager::trim_gray_peerlist() - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - while(m_peers_white.size() > P2P_LOCAL_WHITE_PEERLIST_LIMIT) - { - peers_indexed::index::type& sorted_index=m_peers_white.get(); - sorted_index.erase(sorted_index.begin()); - } - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::merge_peerlist(const std::list& outer_bs) - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - BOOST_FOREACH(const peerlist_entry& be, outer_bs) - { - append_with_peer_gray(be); - } - // delete extra elements - trim_gray_peerlist(); - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::get_white_peer_by_index(peerlist_entry& p, size_t i) - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - if(i >= m_peers_white.size()) - return false; - - peers_indexed::index::type& by_time_index = m_peers_white.get(); - p = *std::prev(--by_time_index.end(), i); - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::get_gray_peer_by_index(peerlist_entry& p, size_t i) - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - if(i >= m_peers_gray.size()) - return false; - - peers_indexed::index::type& by_time_index = m_peers_gray.get(); - p = *std::prev(--by_time_index.end(), i); - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::is_ip_allowed(uint32_t ip) - { - //never allow loopback ip - if(epee::net_utils::is_ip_loopback(ip)) - return false; - - if(!m_allow_local_ip && epee::net_utils::is_ip_local(ip)) - return false; - - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::get_peerlist_head(std::list& bs_head, uint32_t depth) - { - - CRITICAL_REGION_LOCAL(m_peerlist_lock); - peers_indexed::index::type& by_time_index=m_peers_white.get(); - uint32_t cnt = 0; - BOOST_REVERSE_FOREACH(const peers_indexed::value_type& vl, by_time_index) - { - if(!vl.last_seen) - continue; - bs_head.push_back(vl); - if(cnt++ > depth) - break; - } - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::get_peerlist_full(std::list& pl_gray, std::list& pl_white) - { - CRITICAL_REGION_LOCAL(m_peerlist_lock); - peers_indexed::index::type& by_time_index_gr=m_peers_gray.get(); - BOOST_REVERSE_FOREACH(const peers_indexed::value_type& vl, by_time_index_gr) - { - pl_gray.push_back(vl); - } - - peers_indexed::index::type& by_time_index_wt=m_peers_white.get(); - BOOST_REVERSE_FOREACH(const peers_indexed::value_type& vl, by_time_index_wt) - { - pl_white.push_back(vl); - } - - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port) - { - net_address addr; - addr.ip = ip; - addr.port = port; - return set_peer_just_seen(peer, addr); - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, const net_address& addr) - { - TRY_ENTRY(); - CRITICAL_REGION_LOCAL(m_peerlist_lock); - //find in white list - peerlist_entry ple; - ple.adr = addr; - ple.id = peer; - ple.last_seen = time(NULL); - return append_with_peer_white(ple); - CATCH_ENTRY_L0("peerlist_manager::set_peer_just_seen()", false); - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::append_with_peer_white(const peerlist_entry& ple) - { - TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) - return true; - - CRITICAL_REGION_LOCAL(m_peerlist_lock); - //find in white list - auto by_addr_it_wt = m_peers_white.get().find(ple.adr); - if(by_addr_it_wt == m_peers_white.get().end()) - { - //put new record into white list - m_peers_white.insert(ple); - trim_white_peerlist(); - }else - { - //update record in white list - m_peers_white.replace(by_addr_it_wt, ple); - } - //remove from gray list, if need - auto by_addr_it_gr = m_peers_gray.get().find(ple.adr); - if(by_addr_it_gr != m_peers_gray.get().end()) - { - m_peers_gray.erase(by_addr_it_gr); - } - return true; - CATCH_ENTRY_L0("peerlist_manager::append_with_peer_white()", false); - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::append_with_peer_gray(const peerlist_entry& ple) - { - TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) - return true; - - CRITICAL_REGION_LOCAL(m_peerlist_lock); - //find in white list - auto by_addr_it_wt = m_peers_white.get().find(ple.adr); - if(by_addr_it_wt != m_peers_white.get().end()) - return true; - - //update gray list - auto by_addr_it_gr = m_peers_gray.get().find(ple.adr); - if(by_addr_it_gr == m_peers_gray.get().end()) - { - //put new record into white list - m_peers_gray.insert(ple); - trim_gray_peerlist(); - }else - { - //update record in white list - m_peers_gray.replace(by_addr_it_gr, ple); - } - return true; - CATCH_ENTRY_L0("peerlist_manager::append_with_peer_gray()", false); - return true; - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::remove_peers_by_ip_from_all(const uint32_t ip) - { - TRY_ENTRY(); - - CRITICAL_REGION_LOCAL(m_peerlist_lock); - - for (auto it = m_peers_white.begin(); it != m_peers_white.end();) - { - if (it->adr.ip == ip) - it = m_peers_white.erase(it); - else - ++it; - } - - for (auto it = m_peers_gray.begin(); it != m_peers_gray.end();) - { - if (it->adr.ip == ip) - it = m_peers_gray.erase(it); - else - ++it; - } - - return true; - CATCH_ENTRY_L0("peerlist_manager::remove_peers_by_ip_from_all()", false); - } - //-------------------------------------------------------------------------------------------------- -} - -BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER) diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h deleted file mode 100644 index d10370b..0000000 --- a/src/p2p/net_peerlist_boost_serialization.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -namespace boost -{ - namespace serialization - { - //BOOST_CLASS_VERSION(odetool::net_adress, 1) - template - inline void serialize(Archive &a, nodetool::net_address& na, const ver_type ver) - { - a & na.ip; - a & na.port; - } - - - template - inline void serialize(Archive &a, nodetool::peerlist_entry& pl, const ver_type ver) - { - a & pl.adr; - a & pl.id; - a & pl.last_seen; - } - } -} diff --git a/src/p2p/p2p_networks.h b/src/p2p/p2p_networks.h deleted file mode 100644 index 3f278e9..0000000 --- a/src/p2p/p2p_networks.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -/* - -P2P_NETWORK_ID definition moved to net_node.inl - -namespace nodetool -{ -#ifndef TESTNET - const static boost::uuids::uuid P2P_NETWORK_ID = { { 0x11 ,0x10, 0x01, 0x11 , 0x01, 0x20 , 0x01, 0x01, 0x10, 0x11, 0x00, 0x10, 0x11, 0x11, 0x01, 0x10} }; //Bender's nightmare -#else - const static boost::uuids::uuid P2P_NETWORK_ID = { { 0x11 ,0x10, 0x01, 0x11 , 0x01, 0x02 , 0x01, 0x01, 0x10, 0x11, 0x11, 0x10, 0x11, 0x11, 0x01, 0x10} }; //Another Bender's nightmare -#endif -} -*/ diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h deleted file mode 100644 index fe1225f..0000000 --- a/src/p2p/p2p_protocol_defs.h +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include "serialization/keyvalue_serialization.h" -#include "misc_language.h" -#include "currency_core/currency_config.h" -#include "crypto/crypto.h" - -namespace nodetool -{ - typedef boost::uuids::uuid uuid; - typedef uint64_t peerid_type; - typedef std::string blobdata; - -#pragma pack (push, 1) - - struct net_address - { - uint32_t ip; - uint32_t port; - }; - - struct peerlist_entry - { - net_address adr; - peerid_type id; - time_t last_seen; - }; - -#define P2P_CONNECTION_ENTRY_VERSION_MAX_SIZE 50 - - struct connection_entry - { - net_address adr; - peerid_type id; - bool is_income; - uint64_t time_started; - uint64_t last_recv; - uint64_t last_send; - char version[P2P_CONNECTION_ENTRY_VERSION_MAX_SIZE]; - }; - -#pragma pack(pop) - - inline - bool operator < (const net_address& a, const net_address& b) - { - return epee::misc_utils::is_less_as_pod(a, b); - } - - inline - bool operator == (const net_address& a, const net_address& b) - { - return memcmp(&a, &b, sizeof(a)) == 0; - } - inline - std::string print_peerlist_to_string(const std::list& pl) - { - time_t now_time = 0; - time(&now_time); - std::stringstream ss; - ss << std::setfill ('0') << std::setw (8) << std::hex << std::noshowbase; - BOOST_FOREACH(const peerlist_entry& pe, pl) - { - ss << pe.id << "\t" << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast(pe.adr.port) << " \tlast_seen: " << epee::misc_utils::get_time_interval_string(now_time - pe.last_seen) << std::endl; - } - return ss.str(); - } - - - struct network_config - { - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(connections_count) - KV_SERIALIZE(handshake_interval) - KV_SERIALIZE(packet_max_size) - KV_SERIALIZE(config_id) - END_KV_SERIALIZE_MAP() - - uint32_t connections_count; - uint32_t connection_timeout; - uint32_t ping_connection_timeout; - uint32_t handshake_interval; - uint32_t packet_max_size; - uint32_t config_id; - uint32_t send_peerlist_sz; - }; - - struct basic_node_data - { - uuid network_id; - int64_t local_time; - uint32_t my_port; - peerid_type peer_id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(network_id) - KV_SERIALIZE(peer_id) - KV_SERIALIZE(local_time) - KV_SERIALIZE(my_port) - END_KV_SERIALIZE_MAP() - }; - - -#define P2P_COMMANDS_POOL_BASE 1000 - - /************************************************************************/ - /* */ - /************************************************************************/ -#define ALERT_TYPE_CALM 1 -#define ALERT_TYPE_URGENT 2 -#define ALERT_TYPE_CRITICAL 3 - - /* - Don't put any strings into maintainers message: if secret key will - be stolen it can be used maliciously. - */ - struct alert_condition - { - uint32_t if_build_less_then; //apply alert if build less then - uint8_t alert_mode; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_N(if_build_less_then, "build") - KV_SERIALIZE_N(alert_mode, "mode") - END_KV_SERIALIZE_MAP() - }; - - struct maintainers_info - { - uint64_t timestamp; - /*actual version*/ - uint8_t ver_major; - uint8_t ver_minor; - uint8_t ver_revision; - uint32_t build_no; - /*conditions for alerting*/ - std::list conditions; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_N(timestamp, "ts") - KV_SERIALIZE_N(ver_major, "maj") - KV_SERIALIZE_N(ver_minor, "min") - KV_SERIALIZE_N(ver_revision, "rev") - KV_SERIALIZE_N(build_no, "build") - KV_SERIALIZE_N(conditions, "cs") - END_KV_SERIALIZE_MAP() - }; - - struct maintainers_entry - { - blobdata maintainers_info_buff; - crypto::signature sign; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(maintainers_info_buff) - KV_SERIALIZE_VAL_POD_AS_BLOB(sign) - END_KV_SERIALIZE_MAP() - }; - - struct maintainers_info_external - { - uint8_t ver_major; - uint8_t ver_minor; - uint8_t ver_revision; - uint32_t build_no; - uint8_t mode; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(ver_major) - KV_SERIALIZE(ver_minor) - KV_SERIALIZE(ver_revision) - KV_SERIALIZE(build_no) - KV_SERIALIZE(mode) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct COMMAND_HANDSHAKE_T - { - const static int ID = P2P_COMMANDS_POOL_BASE + 1; - - struct request - { - basic_node_data node_data; - t_playload_type payload_data; - maintainers_entry maintrs_entry; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(node_data) - KV_SERIALIZE(payload_data) - KV_SERIALIZE(maintrs_entry) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - basic_node_data node_data; - t_playload_type payload_data; - std::list local_peerlist; - maintainers_entry maintrs_entry; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(node_data) - KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) - KV_SERIALIZE(maintrs_entry) - END_KV_SERIALIZE_MAP() - }; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - template - struct COMMAND_TIMED_SYNC_T - { - const static int ID = P2P_COMMANDS_POOL_BASE + 2; - - struct request - { - t_playload_type payload_data; - maintainers_entry maintrs_entry; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(payload_data) - KV_SERIALIZE(maintrs_entry) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - int64_t local_time; - t_playload_type payload_data; - std::list local_peerlist; - maintainers_entry maintrs_entry; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(local_time) - KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) - KV_SERIALIZE(maintrs_entry) - END_KV_SERIALIZE_MAP() - }; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - - struct COMMAND_PING - { - /* - Used to make "callback" connection, to be sure that opponent node - have accessible connection point. Only other nodes can add peer to peerlist, - and ONLY in case when peer has accepted connection and answered to ping. - */ - const static int ID = P2P_COMMANDS_POOL_BASE + 3; - -#define PING_OK_RESPONSE_STATUS_TEXT "OK" - - struct request - { - /*actually we don't need to send any real data*/ - - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - peerid_type peer_id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(peer_id) - END_KV_SERIALIZE_MAP() - }; - }; - - -#ifdef ALLOW_DEBUG_COMMANDS - //These commands are considered as insecure, and made in debug purposes for a limited lifetime. - //Anyone who feel unsafe with this commands can disable the ALLOW_GET_STAT_COMMAND macro. - - struct proof_of_trust - { - peerid_type peer_id; - int64_t time; - crypto::signature sign; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(peer_id) - KV_SERIALIZE(time) - KV_SERIALIZE_VAL_POD_AS_BLOB(sign) - END_KV_SERIALIZE_MAP() - }; - - - template - struct COMMAND_REQUEST_STAT_INFO_T - { - const static int ID = P2P_COMMANDS_POOL_BASE + 4; - - struct request - { - typename payload_stat_info::params pr; - proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(pr) - KV_SERIALIZE(tr) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string version; - uint64_t connections_count; - uint64_t incoming_connections_count; - uint64_t current_log_size; - payload_stat_info payload_info; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(version) - KV_SERIALIZE(connections_count) - KV_SERIALIZE(incoming_connections_count) - KV_SERIALIZE(current_log_size) - KV_SERIALIZE(payload_info) - END_KV_SERIALIZE_MAP() - }; - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_REQUEST_NETWORK_STATE - { - const static int ID = P2P_COMMANDS_POOL_BASE + 5; - - struct request - { - proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tr) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list local_peerlist_white; - std::list local_peerlist_gray; - std::list connections_list; - peerid_type my_id; - uint64_t local_time; - uint64_t up_time; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_white) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_gray) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(connections_list) - KV_SERIALIZE(my_id) - KV_SERIALIZE(local_time) - KV_SERIALIZE(up_time) - END_KV_SERIALIZE_MAP() - }; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_REQUEST_PEER_ID - { - const static int ID = P2P_COMMANDS_POOL_BASE + 6; - - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - peerid_type my_id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(my_id) - END_KV_SERIALIZE_MAP() - }; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_REQUEST_LOG - { - const static int ID = P2P_COMMANDS_POOL_BASE + 7; - - struct request - { - proof_of_trust tr; - uint64_t log_chunk_offset; - uint64_t log_chunk_size; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tr) - KV_SERIALIZE(log_chunk_offset) - KV_SERIALIZE(log_chunk_size) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - int64_t current_log_level; - uint64_t current_log_size; - std::string error; - std::string log_chunk; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_log_level) - KV_SERIALIZE(current_log_size) - KV_SERIALIZE(error) - KV_SERIALIZE(log_chunk) - END_KV_SERIALIZE_MAP() - }; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - struct COMMAND_SET_LOG_LEVEL - { - const static int ID = P2P_COMMANDS_POOL_BASE + 8; - - struct request - { - proof_of_trust tr; - int64_t new_log_level; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tr) - KV_SERIALIZE(new_log_level) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - int64_t old_log_level; - int64_t current_log_level; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(old_log_level) - KV_SERIALIZE(current_log_level) - END_KV_SERIALIZE_MAP() - }; - }; - -#endif // #ifdef ALLOW_DEBUG_COMMANDS - -} - - - diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp deleted file mode 100644 index c16efca..0000000 --- a/src/rpc/core_rpc_server.cpp +++ /dev/null @@ -1,1370 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "include_base_utils.h" -using namespace epee; - -#include "core_rpc_server.h" -#include "common/command_line.h" -#include "currency_core/currency_format_utils.h" -#include "currency_core/account.h" - -#include "misc_language.h" -#include "crypto/hash.h" -#include "core_rpc_server_error_codes.h" - - - -namespace currency -{ - namespace - { - const command_line::arg_descriptor arg_rpc_bind_ip = {"rpc-bind-ip", "", "127.0.0.1"}; - const command_line::arg_descriptor arg_rpc_bind_port = {"rpc-bind-port", "", std::to_string(RPC_DEFAULT_PORT)}; - const command_line::arg_descriptor arg_rpc_ignore_status = {"rpc-ignore-offline", "Let rpc calls despite online/offline status", false, true }; - } - //----------------------------------------------------------------------------------- - void core_rpc_server::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_rpc_bind_ip); - command_line::add_arg(desc, arg_rpc_bind_port); - command_line::add_arg(desc, arg_rpc_ignore_status); - } - //------------------------------------------------------------------------------------------------------------------------------ - core_rpc_server::core_rpc_server(core& cr, nodetool::node_server >& p2p, - bc_services::bc_offers_service& of - ) :m_core(cr), m_p2p(p2p), m_of(of), m_session_counter(0), m_ignore_status(false) - {} - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::handle_command_line(const boost::program_options::variables_map& vm) - { - m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip); - m_port = command_line::get_arg(vm, arg_rpc_bind_port); - if (command_line::has_arg(vm, arg_rpc_ignore_status)) - { - m_ignore_status = command_line::get_arg(vm, arg_rpc_ignore_status); - } - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::init(const boost::program_options::variables_map& vm) - { - m_net_server.set_threads_prefix("RPC"); - bool r = handle_command_line(vm); - CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server"); - return epee::http_server_impl_base::init(m_port, m_bind_ip); - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::check_core_ready_(const std::string& calling_method) - { -#ifndef TESTNET - if (m_ignore_status) - return true; - if(!m_p2p.get_payload_object().is_synchronized()) - { - LOG_PRINT_L0("[" << calling_method << "]Core busy cz is_synchronized"); - return false; - } - #endif - return true; - } -#define check_core_ready() check_core_ready_(LOCAL_FUNCTION_DEF__) -#define CHECK_CORE_READY() if(!check_core_ready()){res.status = API_RETURN_CODE_BUSY;return true;} - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - res.height = m_core.get_current_blockchain_size(); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx) - { - //unconditional values - res.height = m_core.get_current_blockchain_size(); - res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase - res.tx_pool_size = m_core.get_pool_transactions_count(); - res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); - uint64_t total_conn = m_p2p.get_connections_count(); - res.outgoing_connections_count = m_p2p.get_outgoing_connections_count(); - res.incoming_connections_count = total_conn - res.outgoing_connections_count; - res.synchronized_connections_count = m_p2p.get_payload_object().get_synchronized_connections_count(); - res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); - res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.current_blocks_median = m_core.get_blockchain_storage().get_current_comulative_blocksize_limit() / 2; - res.alias_count = m_core.get_blockchain_storage().get_aliases_count(); - res.current_max_allowed_block_size = m_core.get_blockchain_storage().get_current_comulative_blocksize_limit(); - if (!res.outgoing_connections_count) - res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_connecting; - else if (m_p2p.get_payload_object().is_synchronized()) - res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_online; - else - res.daemon_network_state = COMMAND_RPC_GET_INFO::daemon_network_state_synchronizing; - res.synchronization_start_height = m_p2p.get_payload_object().get_core_inital_height(); - res.max_net_seen_height = m_p2p.get_payload_object().get_max_seen_height(); - m_p2p.get_maintainers_info(res.mi); - res.pos_allowed = m_core.get_blockchain_storage().is_pos_allowed(); - wide_difficulty_type pos_diff = m_core.get_blockchain_storage().get_cached_next_difficulty(true); - res.pos_difficulty = pos_diff.convert_to(); - res.pow_difficulty = m_core.get_blockchain_storage().get_cached_next_difficulty(false).convert_to(); - res.default_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_default_fee; - res.minimum_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_pool_min_fee; - - //conditional values - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_NET_TIME_DELTA_MEDIAN) - { - int64_t last_median2local_time_diff, last_ntp2local_time_diff; - if (!m_p2p.get_payload_object().get_last_time_sync_difference(last_median2local_time_diff, last_ntp2local_time_diff)) - res.net_time_delta_median = 1; - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_50) - res.current_network_hashrate_50 = m_core.get_blockchain_storage().get_current_hashrate(50); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_350) - res.current_network_hashrate_350 = m_core.get_blockchain_storage().get_current_hashrate(350); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_10_BLOCKS) - res.seconds_for_10_blocks = m_core.get_blockchain_storage().get_seconds_between_last_n_block(10); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_30_BLOCKS) - res.seconds_for_30_blocks = m_core.get_blockchain_storage().get_seconds_between_last_n_block(30); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT) - m_core.get_blockchain_storage().get_transactions_daily_stat(res.transactions_cnt_per_day, res.transactions_volume_per_day); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_LAST_POS_TIMESTAMP) - { - auto pos_bl_ptr = m_core.get_blockchain_storage().get_last_block_of_type(true); - if (pos_bl_ptr) - res.last_pos_timestamp = pos_bl_ptr->bl.timestamp; - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_LAST_POW_TIMESTAMP) - { - auto pow_bl_ptr = m_core.get_blockchain_storage().get_last_block_of_type(false); - if (pow_bl_ptr) - res.last_pow_timestamp = pow_bl_ptr->bl.timestamp; - } - boost::multiprecision::uint128_t total_coins = 0; - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS) - { - total_coins = m_core.get_blockchain_storage().total_coins(); - res.total_coins = boost::lexical_cast(total_coins); - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_LAST_BLOCK_SIZE) - { - std::vector sz; - m_core.get_blockchain_storage().get_last_n_blocks_sizes(sz, 1); - res.last_block_size = sz.size() ? sz.back() : 0; - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_TX_COUNT_IN_LAST_BLOCK) - { - currency::block b = AUTO_VAL_INIT(b); - m_core.get_blockchain_storage().get_top_block(b); - res.tx_count_in_last_block = b.tx_hashes.size(); - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_POS_SEQUENCE_FACTOR) - res.pos_sequence_factor = m_core.get_blockchain_storage().get_current_sequence_factor(true); - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_POW_SEQUENCE_FACTOR) - res.pow_sequence_factor = m_core.get_blockchain_storage().get_current_sequence_factor(false); - if (req.flags&(COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY | COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS)) - { - res.block_reward = currency::get_base_block_reward(true, total_coins, res.height); - currency::block b = AUTO_VAL_INIT(b); - m_core.get_blockchain_storage().get_top_block(b); - res.last_block_total_reward = currency::get_reward_from_miner_tx(b.miner_tx); - res.pos_diff_total_coins_rate = (pos_diff / (total_coins - PREMINE_AMOUNT + 1)).convert_to(); - res.last_block_timestamp = b.timestamp; - res.last_block_hash = string_tools::pod_to_hex(get_block_hash(b)); - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_POS_BLOCK_TS_SHIFT_VS_ACTUAL) - { - res.pos_block_ts_shift_vs_actual = 0; - auto last_pos_block_ptr = m_core.get_blockchain_storage().get_last_block_of_type(true); - if (last_pos_block_ptr) - res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_block_datetime(last_pos_block_ptr->bl); - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT) - m_core.get_blockchain_storage().get_outs_index_stat(res.outs_stat); - - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE) - { - currency::blockchain_storage::performnce_data& pd = m_core.get_blockchain_storage().get_performnce_data(); - //block processing zone - res.performance_data.block_processing_time_0 = pd.block_processing_time_0_ms.get_avg()*1000; - res.performance_data.block_processing_time_1 = pd.block_processing_time_1.get_avg(); - res.performance_data.target_calculating_time_2 = pd.target_calculating_time_2.get_avg(); - res.performance_data.longhash_calculating_time_3 = pd.longhash_calculating_time_3.get_avg(); - res.performance_data.all_txs_insert_time_5 = pd.all_txs_insert_time_5.get_avg(); - res.performance_data.etc_stuff_6 = pd.etc_stuff_6.get_avg(); - res.performance_data.insert_time_4 = pd.insert_time_4.get_avg(); - res.performance_data.raise_block_core_event = pd.raise_block_core_event.get_avg(); - res.performance_data.target_calculating_enum_blocks = pd.target_calculating_enum_blocks.get_avg(); - res.performance_data.target_calculating_calc = pd.target_calculating_calc.get_avg(); - //tx processing zone - res.performance_data.tx_check_inputs_time = pd.tx_check_inputs_time.get_avg(); - res.performance_data.tx_add_one_tx_time = pd.tx_add_one_tx_time.get_avg(); - res.performance_data.tx_process_extra = pd.tx_process_extra.get_avg(); - res.performance_data.tx_process_attachment = pd.tx_process_attachment.get_avg(); - res.performance_data.tx_process_inputs = pd.tx_process_inputs.get_avg(); - res.performance_data.tx_push_global_index = pd.tx_push_global_index.get_avg(); - res.performance_data.tx_check_exist = pd.tx_check_exist.get_avg(); - res.performance_data.tx_append_time = pd.tx_append_time.get_avg(); - res.performance_data.tx_append_rl_wait = pd.tx_append_rl_wait.get_avg(); - res.performance_data.tx_append_is_expired = pd.tx_append_is_expired.get_avg(); - res.performance_data.tx_mixin_count = pd.tx_mixin_count.get_avg(); - - - res.performance_data.tx_store_db = pd.tx_store_db.get_avg(); - //db performance count - res.performance_data.map_size = pd.si.map_size; - res.performance_data.tx_count = pd.si.tx_count; - res.performance_data.writer_tx_count = pd.si.write_tx_count; -#define COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(field_name) res.performance_data.field_name = pd.field_name.get_avg(); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_prefix_hash); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_attachment_check); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_kimage_check); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_ch_in_val_sig); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_get_item_size); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_loop); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_loop_find_tx); - COPY_AVG_TO_BLOCK_CHAIN_PERF_DATA(tx_check_inputs_loop_scan_outputkeys_loop_handle_output); - - //tx pool perfromance stat - const currency::tx_memory_pool::performnce_data& pool_pd = m_core.get_tx_pool().get_performnce_data(); -#define COPY_AVG_TO_POOL_PERF_DATA(field_name) res.tx_pool_performance_data.field_name = pool_pd.field_name.get_avg(); - COPY_AVG_TO_POOL_PERF_DATA(tx_processing_time); - COPY_AVG_TO_POOL_PERF_DATA(check_inputs_types_supported_time); - COPY_AVG_TO_POOL_PERF_DATA(expiration_validate_time); - COPY_AVG_TO_POOL_PERF_DATA(validate_amount_time); - COPY_AVG_TO_POOL_PERF_DATA(validate_alias_time); - COPY_AVG_TO_POOL_PERF_DATA(check_keyimages_ws_ms_time); - COPY_AVG_TO_POOL_PERF_DATA(check_inputs_time); - COPY_AVG_TO_POOL_PERF_DATA(begin_tx_time); - COPY_AVG_TO_POOL_PERF_DATA(update_db_time); - COPY_AVG_TO_POOL_PERF_DATA(db_commit_time); - - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE) - { - res.offers_count = m_of.get_offers_container().size(); - } - if (req.flags&COMMAND_RPC_GET_INFO_FLAG_EXPIRATIONS_MEDIAN) - { - res.expiration_median_timestamp = m_core.get_blockchain_storage().get_tx_expiration_median(); - } - - - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - - if (req.block_ids.back() != m_core.get_blockchain_storage().get_block_id_by_height(0)) - { - //genesis mismatch, return specific - res.status = API_RETURN_CODE_GENESIS_MISMATCH; - return true; - } - - if (req.minimum_height >= m_core.get_blockchain_storage().get_current_blockchain_size()) - { - //wrong minimum_height - res.status = API_RETURN_CODE_BAD_ARG; - return true; - } - - blockchain_storage::blocks_direct_container bs; - if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height, req.need_global_indexes)) - { - res.status = API_RETURN_CODE_FAIL; - return false; - } - - for(auto& b: bs) - { - res.blocks.resize(res.blocks.size()+1); - res.blocks.back().block_ptr = b.first; - res.blocks.back().txs_ptr = std::move(b.second); - res.blocks.back().coinbase_ptr = b.third; - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - - if (req.block_ids.back() != m_core.get_blockchain_storage().get_block_id_by_height(0)) - { - //genesis mismatch, return specific - res.status = API_RETURN_CODE_GENESIS_MISMATCH; - return true; - } - - if (req.minimum_height >= m_core.get_blockchain_storage().get_current_blockchain_size()) - { - //wrong minimum_height - res.status = API_RETURN_CODE_BAD_ARG; - return true; - } - - blockchain_storage::blocks_direct_container bs; - if (!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height, req.need_global_indexes)) - { - res.status = API_RETURN_CODE_FAIL; - return false; - } - - for (auto& b : bs) - { - res.blocks.resize(res.blocks.size()+1); - res.blocks.back().block = block_to_blob(b.first->bl); - if (req.need_global_indexes) - { - CHECK_AND_ASSERT_MES(b.third.get(), false, "Internal error on handling COMMAND_RPC_GET_BLOCKS_FAST: b.third is empty, ie coinbase info is not prepared"); - res.blocks.back().coinbase_global_outs = b.third->m_global_output_indexes; - res.blocks.back().tx_global_outs.resize(b.second.size()); - } - size_t i = 0; - - BOOST_FOREACH(auto& t, b.second) - { - res.blocks.back().txs.push_back(tx_to_blob(t->tx)); - if (req.need_global_indexes) - { - res.blocks.back().tx_global_outs[i].v = t->m_global_output_indexes; - } - i++; - } - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - res.status = "Failed"; - if(!m_core.get_random_outs_for_amounts(req, res)) - { - return true; - } - - res.status = API_RETURN_CODE_OK; - std::stringstream ss; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount outs_for_amount; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; - std::for_each(res.outs.begin(), res.outs.end(), [&](outs_for_amount& ofa) - { - ss << "[" << ofa.amount << "]:"; - CHECK_AND_ASSERT_MES(ofa.outs.size(), ;, "internal error: ofa.outs.size() is empty for amount " << ofa.amount); - std::for_each(ofa.outs.begin(), ofa.outs.end(), [&](out_entry& oe) - { - ss << oe.global_amount_index << " "; - }); - ss << ENDL; - }); - std::string s = ss.str(); - LOG_PRINT_L2("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: " << ENDL << s); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - res.tx_global_outs.resize(req.txids.size()); - size_t i = 0; - for (auto& txid : req.txids) - { - bool r = m_core.get_tx_outputs_gindexs(txid, res.tx_global_outs[i].v); - if (!r) - { - res.status = API_RETURN_CODE_FAIL; - return true; - } - i++; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_set_maintainers_info(const COMMAND_RPC_SET_MAINTAINERS_INFO::request& req, COMMAND_RPC_SET_MAINTAINERS_INFO::response& res, connection_context& cntx) - { - if(!m_p2p.handle_maintainers_entry(req)) - { - res.status = "Failed to get call handle_maintainers_entry()"; - return true; - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_tx_pool(const COMMAND_RPC_GET_TX_POOL::request& req, COMMAND_RPC_GET_TX_POOL::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - std::list txs; - if (!m_core.get_pool_transactions(txs)) - { - res.status = "Failed to call get_pool_transactions()"; - return true; - } - - res.tx_expiration_ts_median = m_core.get_blockchain_storage().get_tx_expiration_median(); - - - for(auto& tx: txs) - { - res.txs.push_back(t_serializable_object_to_blob(tx)); - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_scan_pos(const COMMAND_RPC_SCAN_POS::request& req, COMMAND_RPC_SCAN_POS::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - m_core.get_blockchain_storage().scan_pos(req, res); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_check_keyimages(const COMMAND_RPC_CHECK_KEYIMAGES::request& req, COMMAND_RPC_CHECK_KEYIMAGES::response& res, connection_context& cntx) - { - m_core.get_blockchain_storage().check_keyimages(req.images, res.images_stat); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - std::vector vh; - for(const auto& tx_hex_str : req.txs_hashes) - { - blobdata b; - if(!string_tools::parse_hexstr_to_binbuff(tx_hex_str, b)) - { - res.status = "Failed to parse hex representation of transaction hash"; - return true; - } - if(b.size() != sizeof(crypto::hash)) - { - res.status = "Failed, size of data mismatch"; - return true; - } - vh.push_back(*reinterpret_cast(b.data())); - } - std::list missed_txs; - std::list txs; - bool r = m_core.get_transactions(vh, txs, missed_txs); - if(!r) - { - res.status = "Failed"; - return true; - } - - for(auto& tx : txs) - { - blobdata blob = t_serializable_object_to_blob(tx); - res.txs_as_hex.push_back(string_tools::buff_to_hex_nodelimer(blob)); - } - - for(const auto& miss_tx : missed_txs) - { - res.missed_tx.push_back(string_tools::pod_to_hex(miss_tx)); - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_offers_ex(const COMMAND_RPC_GET_OFFERS_EX::request& req, COMMAND_RPC_GET_OFFERS_EX::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - m_of.get_offers_ex(req.filter, res.offers, res.total_offers, m_core.get_blockchain_storage().get_core_runtime_config().get_core_time()); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_pos_mining_details(const COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, COMMAND_RPC_GET_POS_MINING_DETAILS::response& res, connection_context& cntx) - { - if (!m_p2p.get_connections_count()) - { - res.status = API_RETURN_CODE_DISCONNECTED; - return true; - } - res.pos_mining_allowed = m_core.get_blockchain_storage().is_pos_allowed(); - if (!res.pos_mining_allowed) - { - res.status = API_RETURN_CODE_NOT_FOUND; - return true; - } - - res.pos_basic_difficulty = m_core.get_blockchain_storage().get_next_diff_conditional(true).convert_to(); - m_core.get_blockchain_storage().build_stake_modifier(res.sm, blockchain_storage::alt_chain_type(), 0, &res.last_block_hash);// , &res.height); - - //TODO: need atomic operation with build_stake_modifier() - res.starter_timestamp = m_core.get_blockchain_storage().get_last_timestamps_check_window_median(); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_current_core_tx_expiration_median(const COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res, connection_context& cntx) - { - res.expiration_median = m_core.get_blockchain_storage().get_tx_expiration_median(); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_rpc_get_blocks_details(const COMMAND_RPC_GET_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_BLOCKS_DETAILS::response& res, connection_context& cntx) - { - m_core.get_blockchain_storage().get_main_blocks_rpc_details(req.height_start, req.count, req.ignore_transactions, res.blocks); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_tx_details(const COMMAND_RPC_GET_TX_DETAILS::request& req, COMMAND_RPC_GET_TX_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - crypto::hash h = null_hash; - if(!epee::string_tools::hex_to_pod(req.tx_hash, h)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Invalid tx hash given"; - return false; - } - if (!m_core.get_blockchain_storage().get_tx_rpc_details(h, res.tx_info, 0, false)) - { - if (!m_core.get_tx_pool().get_transaction_details(h, res.tx_info)) - { - error_resp.code = CORE_RPC_ERROR_CODE_NOT_FOUND; - error_resp.message = "tx is not found"; - return false; - } - - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_search_by_id(const COMMAND_RPC_SERARCH_BY_ID::request& req, COMMAND_RPC_SERARCH_BY_ID::response& res, connection_context& cntx) - { - crypto::hash id = null_hash; - if (!epee::string_tools::hex_to_pod(req.id, id)) - return false; - - m_core.get_blockchain_storage().search_by_id(id, res.types_found); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_out_info(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::response& res, connection_context& cntx) - { - if (!m_core.get_blockchain_storage().get_global_index_details(req, res)) - res.status = API_RETURN_CODE_NOT_FOUND; - else - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_multisig_info(const COMMAND_RPC_GET_MULTISIG_INFO::request& req, COMMAND_RPC_GET_MULTISIG_INFO::response& res, connection_context& cntx) - { - if (!m_core.get_blockchain_storage().get_multisig_id_details(req, res)) - res.status = API_RETURN_CODE_NOT_FOUND; - else - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_pool_txs_details(const COMMAND_RPC_GET_POOL_TXS_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_DETAILS::response& res, connection_context& cntx) - { - if (!req.ids.size()) - { - m_core.get_tx_pool().get_all_transactions_details(res.txs); - } - else - { - m_core.get_tx_pool().get_transactions_details(req.ids, res.txs); - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_pool_txs_brief_details(const COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::response& res, connection_context& cntx) - { - if (!req.ids.size()) - { - m_core.get_tx_pool().get_all_transactions_brief_details(res.txs); - } - else - { - m_core.get_tx_pool().get_transactions_brief_details(req.ids, res.txs); - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_all_pool_tx_list(const COMMAND_RPC_GET_ALL_POOL_TX_LIST::request& req, COMMAND_RPC_GET_ALL_POOL_TX_LIST::response& res, connection_context& cntx) - { - m_core.get_tx_pool().get_all_transactions_list(res.ids); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_pool_info(const COMMAND_RPC_GET_POOL_INFO::request& req, COMMAND_RPC_GET_POOL_INFO::response& res, connection_context& cntx) - { - std::list al_list; - m_core.get_tx_pool().get_aliases_from_tx_pool(al_list); - for (const auto a : al_list) - { - res.aliases_que.push_back(alias_info_to_rpc_alias_info(a)); - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if (!m_core.get_blockchain_storage().get_main_block_rpc_details(req.id, res.block_details)) - { - error_resp.code = CORE_RPC_ERROR_CODE_NOT_FOUND; - error_resp.message = "the requested block has not been found"; - return false; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_alt_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if (!m_core.get_blockchain_storage().get_alt_block_rpc_details(req.id, res.block_details)) - { - error_resp.code = CORE_RPC_ERROR_CODE_NOT_FOUND; - error_resp.message = "the requested block has not been found"; - return false; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_alt_blocks_details(const COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::response& res, connection_context& cntx) - { - m_core.get_blockchain_storage().get_alt_blocks_rpc_details(req.offset, req.count, res.blocks); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - - std::string tx_blob; - if(!string_tools::parse_hexstr_to_binbuff(req.tx_as_hex, tx_blob)) - { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to parse tx from hexbuff: " << req.tx_as_hex); - res.status = "Failed"; - return true; - } - - if (!m_p2p.get_payload_object().get_synchronized_connections_count()) - { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to send, daemon not connected to net"); - res.status = API_RETURN_CODE_DISCONNECTED; - return true; - } - - currency_connection_context fake_context = AUTO_VAL_INIT(fake_context); - tx_verification_context tvc = AUTO_VAL_INIT(tvc); - if(!m_core.handle_incoming_tx(tx_blob, tvc, false)) - { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx"); - res.status = "Failed"; - return true; - } - - if(tvc.m_verification_failed) - { - LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed"); - res.status = "Failed"; - return true; - } - - if(!tvc.m_should_be_relayed) - { - LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); - res.status = "Not relayed"; - return true; - } - - - NOTIFY_NEW_TRANSACTIONS::request r; - r.txs.push_back(tx_blob); - m_core.get_protocol()->relay_transactions(r, fake_context); - //TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_force_relaey_raw_txs(const COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& req, COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - NOTIFY_NEW_TRANSACTIONS::request r = AUTO_VAL_INIT(r); - - for (const auto& t : req.txs_as_hex) - { - std::string tx_blob; - if (!string_tools::parse_hexstr_to_binbuff(t, tx_blob)) - { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to parse tx from hexbuff: " << t); - res.status = "Failed"; - return true; - } - r.txs.push_back(tx_blob); - } - - currency_connection_context fake_context = AUTO_VAL_INIT(fake_context); - bool call_res = m_core.get_protocol()->relay_transactions(r, fake_context); - if (call_res) - res.status = API_RETURN_CODE_OK; - return call_res; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - account_public_address adr; - if(!get_account_address_from_str(adr, req.miner_address)) - { - res.status = "Failed, wrong address"; - return true; - } - - if(!m_core.get_miner().start(adr, static_cast(req.threads_count))) - { - res.status = "Failed, mining not started"; - return true; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - if(!m_core.get_miner().stop()) - { - res.status = "Failed, mining not stopped"; - return true; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx) - { - CHECK_CORE_READY(); - res.count = m_core.get_current_blockchain_size(); - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy"; - return false; - } - if(req.size() != 1) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Wrong parameters, expected height"; - return false; - } - uint64_t h = req[0]; - if(m_core.get_current_blockchain_size() <= h) - { - error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("To big height: ") + std::to_string(h) + ", current blockchain size = " + std::to_string(m_core.get_current_blockchain_size()); - } - res = string_tools::pod_to_hex(m_core.get_block_id_by_height(h)); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy"; - return false; - } - - if(req.extra_text.size() > 255) - { - error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_RESERVE_SIZE; - error_resp.message = "Extra text size is to big, maximum 255"; - return false; - } - - currency::account_public_address miner_address = AUTO_VAL_INIT(miner_address); - if(!req.wallet_address.size() || !currency::get_account_address_from_str(miner_address, req.wallet_address)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS; - error_resp.message = "Failed to parse wallet address"; - return false; - } - currency::account_public_address stakeholder_address = AUTO_VAL_INIT(stakeholder_address); - if(req.pos_block && (!req.stakeholder_address.size() || !currency::get_account_address_from_str(stakeholder_address, req.stakeholder_address))) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS; - error_resp.message = "Failed to parse stakeholder address"; - return false; - } - - - create_block_template_params params = AUTO_VAL_INIT(params); - params.miner_address = miner_address; - params.stakeholder_address = stakeholder_address; - params.ex_nonce = req.extra_text; - params.pos = req.pos_block; - params.pe.amount = req.pos_amount; - params.pe.index = req.pos_index; - params.pe.stake_unlock_time = req.stake_unlock_time; - //params.pe.keyimage key image will be set in the wallet - //params.pe.wallet_index is not included in serialization map, TODO: refactoring here - params.pcustom_fill_block_template_func = nullptr; - if (req.explicit_transaction.size()) - { - transaction tx = AUTO_VAL_INIT(tx); - if (!parse_and_validate_tx_from_blob(req.explicit_transaction, tx)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Wrong parameters: explicit_transaction is invalid"; - LOG_ERROR("Failed to parse explicit_transaction blob"); - return false; - } - params.explicit_txs.push_back(tx); - } - - create_block_template_response resp = AUTO_VAL_INIT(resp); - if (!m_core.get_block_template(params, resp)) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to create block template"); - return false; - } - - res.difficulty = resp.diffic.convert_to(); - blobdata block_blob = t_serializable_object_to_blob(resp.b); - res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob); - res.prev_hash = string_tools::pod_to_hex(resp.b.prev_id); - res.height = resp.height; - //calculate epoch seed - res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height)); - - res.status = API_RETURN_CODE_OK; - - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - CHECK_CORE_READY(); - if(req.size()!=1) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Wrong param"; - return false; - } - blobdata blockblob; - if(!string_tools::parse_hexstr_to_binbuff(req[0], blockblob)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; - error_resp.message = "Wrong block blob"; - return false; - } - - block b = AUTO_VAL_INIT(b); - if(!parse_and_validate_block_from_blob(blockblob, b)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; - error_resp.message = "Wrong block blob"; - return false; - } - - block_verification_context bvc = AUTO_VAL_INIT(bvc); - if(!m_core.handle_block_found(b, &bvc)) - { - if (bvc.m_added_to_altchain) - { - error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_ADDED_AS_ALTERNATIVE; - error_resp.message = "Block added as alternative"; - return false; - } - error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED; - error_resp.message = "Block not accepted"; - return false; - } - - res.status = "OK"; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_submitblock2(const COMMAND_RPC_SUBMITBLOCK2::request& req, COMMAND_RPC_SUBMITBLOCK2::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - CHECK_CORE_READY(); - - - block b = AUTO_VAL_INIT(b); - if (!parse_and_validate_block_from_blob(req.b, b)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; - error_resp.message = "Wrong block blob"; - return false; - } - - block_verification_context bvc = AUTO_VAL_INIT(bvc); - for (const auto& txblob : req.explicit_txs) - { - - crypto::hash tx_hash = AUTO_VAL_INIT(tx_hash); - transaction tx = AUTO_VAL_INIT(tx); - if (!parse_and_validate_tx_from_blob(txblob.blob, tx, tx_hash)) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; - error_resp.message = "Wrong explicit tx blob"; - return false; - } - bvc.m_onboard_transactions[tx_hash] = tx; - } - - - if (!m_core.handle_block_found(b, &bvc)) - { - if (bvc.m_added_to_altchain) - { - error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_ADDED_AS_ALTERNATIVE; - error_resp.message = "Block added as alternative"; - return false; - } - error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED; - error_resp.message = "Block not accepted"; - return false; - } - - res.status = "OK"; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - uint64_t core_rpc_server::get_block_reward(const block& blk) - { - uint64_t reward = 0; - BOOST_FOREACH(const tx_out& out, blk.miner_tx.vout) - { - reward += out.amount; - } - return reward; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::fill_block_header_response(const block& blk, bool orphan_status, block_header_response& response) - { - response.major_version = blk.major_version; - response.minor_version = blk.minor_version; - response.timestamp = blk.timestamp; - response.prev_hash = string_tools::pod_to_hex(blk.prev_id); - response.nonce = blk.nonce; - response.orphan_status = orphan_status; - response.height = get_block_height(blk); - response.depth = m_core.get_current_blockchain_size() - response.height - 1; - response.hash = string_tools::pod_to_hex(get_block_hash(blk)); - response.difficulty = m_core.get_blockchain_storage().block_difficulty(response.height).convert_to(); - response.reward = get_block_reward(blk); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return false; - } - block last_block = AUTO_VAL_INIT(last_block); - bool have_last_block_hash = m_core.get_blockchain_storage().get_top_block(last_block); - if (!have_last_block_hash) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't get last block hash."; - return false; - } - bool response_filled = fill_block_header_response(last_block, false, res.block_header); - if (!response_filled) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't produce valid response."; - return false; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){ - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return false; - } - crypto::hash block_hash; - bool hash_parsed = parse_hash256(req.hash, block_hash); - if(!hash_parsed) - { - error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; - error_resp.message = "Failed to parse hex representation of block hash. Hex = " + req.hash + '.'; - return false; - } - block blk; - bool have_block = m_core.get_block_by_hash(block_hash, blk); - if (!have_block) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.'; - return false; - } - if (blk.miner_tx.vin.front().type() != typeid(txin_gen)) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: coinbase transaction in the block has the wrong type"; - return false; - } - //uint64_t block_height = boost::get(blk.miner_tx.vin.front()).height; - bool response_filled = fill_block_header_response(blk, false, res.block_header); - if (!response_filled) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't produce valid response."; - return false; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){ - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return false; - } - if(m_core.get_current_blockchain_size() <= req.height) - { - error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("To big height: ") + std::to_string(req.height) + ", current blockchain size = " + std::to_string(m_core.get_current_blockchain_size()); - return false; - } - block blk = AUTO_VAL_INIT(blk); - m_core.get_blockchain_storage().get_block_by_height(req.height, blk); - - bool response_filled = fill_block_header_response(blk, false, res.block_header); - if (!response_filled) - { - error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Internal error: can't produce valid response."; - return false; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_alias_details(const COMMAND_RPC_GET_ALIAS_DETAILS::request& req, COMMAND_RPC_GET_ALIAS_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return true; - } - extra_alias_entry_base aib = AUTO_VAL_INIT(aib); - if(!validate_alias_name(req.alias)) - { - res.status = "Alias have wrong name"; - return true; - } - if(!m_core.get_blockchain_storage().get_alias_info(req.alias, aib)) - { - res.status = API_RETURN_CODE_NOT_FOUND; - return true; - } - res.alias_details.address = currency::get_account_address_as_str(aib.m_address); - res.alias_details.comment = aib.m_text_comment; - if (aib.m_view_key.size()) - res.alias_details.tracking_key = string_tools::pod_to_hex(aib.m_view_key.back()); - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - - bool core_rpc_server::on_get_all_aliases(const COMMAND_RPC_GET_ALL_ALIASES::request& req, COMMAND_RPC_GET_ALL_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return false; - } - - m_core.get_blockchain_storage().enumerate_aliases([&](uint64_t i, const std::string& alias, const extra_alias_entry_base& alias_entry_base) -> bool - { - res.aliases.push_back(alias_rpc_details()); - alias_info_to_rpc_alias_info(alias, alias_entry_base, res.aliases.back()); - return true; - }); - - res.status = API_RETURN_CODE_OK; - return true; - } - - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_aliases(const COMMAND_RPC_GET_ALIASES::request& req, COMMAND_RPC_GET_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if(!check_core_ready()) - { - error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; - error_resp.message = "Core is busy."; - return false; - } - - m_core.get_blockchain_storage().get_aliases([&res](const std::string& alias, const currency::extra_alias_entry_base& ai){ - res.aliases.push_back(alias_rpc_details()); - alias_info_to_rpc_alias_info(alias, ai, res.aliases.back()); - }, req.offset, req.count); - - res.status = API_RETURN_CODE_OK; - return true; - } - - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_current_hi(mining::height_info& hi) - { - block prev_block = AUTO_VAL_INIT(prev_block); - m_core.get_blockchain_storage().get_top_block(prev_block); - hi.block_id = string_tools::pod_to_hex(currency::get_block_hash(prev_block)); - hi.height = get_block_height(prev_block); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - void core_rpc_server::set_session_blob(const std::string& session_id, const currency::block& blob) - { - CRITICAL_REGION_LOCAL(m_session_jobs_lock); - m_session_jobs[session_id] = blob; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_session_blob(const std::string& session_id, currency::block& blob) - { - CRITICAL_REGION_LOCAL(m_session_jobs_lock); - auto it = m_session_jobs.find(session_id); - if(it == m_session_jobs.end()) - return false; - - blob = it->second; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::get_job(const std::string& job_id, mining::job_details& job, epee::json_rpc::error& err, connection_context& cntx) - { - COMMAND_RPC_GETBLOCKTEMPLATE::request bt_req = AUTO_VAL_INIT(bt_req); - COMMAND_RPC_GETBLOCKTEMPLATE::response bt_res = AUTO_VAL_INIT(bt_res); - - // !!!!!!!! SET YOUR WALLET ADDRESS HERE !!!!!!!! - bt_req.wallet_address = "1HNJjUsofq5LYLoXem119dd491yFAb5g4bCHkecV4sPqigmuxw57Ci9am71fEN4CRmA9jgnvo5PDNfaq8QnprWmS5uLqnbq"; - - if(!on_getblocktemplate(bt_req, bt_res, err, cntx)) - return false; - - //patch block blob if you need(bt_res.blocktemplate_blob), and than load block from blob template - //important: you can't change block size, since it could touch reward and block became invalid - - block b = AUTO_VAL_INIT(b); - std::string bin_buff; - bool r = string_tools::parse_hexstr_to_binbuff(bt_res.blocktemplate_blob, bin_buff); - CHECK_AND_ASSERT_MES(r, false, "internal error, failed to parse hex block"); - r = currency::parse_and_validate_block_from_blob(bin_buff, b); - CHECK_AND_ASSERT_MES(r, false, "internal error, failed to parse block"); - - set_session_blob(job_id, b); - job.blob = string_tools::buff_to_hex_nodelimer(currency::get_block_hashing_blob(b)); - //TODO: set up share difficulty here! - job.difficulty = bt_res.difficulty; //difficulty leaved as string field since it will be refactored into 128 bit format - job.job_id = "SOME_JOB_ID"; - get_current_hi(job.prev_hi); - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_login(const mining::COMMAND_RPC_LOGIN::request& req, mining::COMMAND_RPC_LOGIN::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - //TODO: add login information here - - - res.id = std::to_string(m_session_counter++); //session id - - if(req.hi.height) - { - epee::json_rpc::error err = AUTO_VAL_INIT(err); - if(!get_job(res.id, res.job, err, cntx)) - { - res.status = err.message; - return true; - } - } - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_getjob(const mining::COMMAND_RPC_GETJOB::request& req, mining::COMMAND_RPC_GETJOB::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - - - /*epee::json_rpc::error err = AUTO_VAL_INIT(err); - if(!get_job(req.id, res.jd, err, cntx)) - { - res.status = err.message; - return true; - }*/ - - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - - uint64_t default_tx_fee = m_core.get_blockchain_storage().get_core_runtime_config().tx_default_fee; - uint64_t current_median_fee = m_core.get_blockchain_storage().get_tx_fee_median(); - - res.reward = get_alias_coast_from_fee(req.alias, std::max(default_tx_fee, current_median_fee)); - - if (res.reward) - res.status = API_RETURN_CODE_OK; - else - res.status = API_RETURN_CODE_NOT_FOUND; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_est_height_from_date(const COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::request& req, COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::response& res, connection_context& cntx) - { - bool r = m_core.get_blockchain_storage().get_est_height_from_date(req.timestamp, res.h); - - if (r) - res.status = API_RETURN_CODE_OK; - else - res.status = API_RETURN_CODE_NOT_FOUND; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_alias_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - account_public_address addr = AUTO_VAL_INIT(addr); - if (!get_account_address_from_str(addr, req)) - { - res.status = API_RETURN_CODE_FAIL; - return true; - } - //res.alias = m_core.get_blockchain_storage().get_alias_by_address(addr); - COMMAND_RPC_GET_ALIAS_DETAILS::request req2 = AUTO_VAL_INIT(req2); - COMMAND_RPC_GET_ALIAS_DETAILS::response res2 = AUTO_VAL_INIT(res2); - - req2.alias = m_core.get_blockchain_storage().get_alias_by_address(addr); - if (!req2.alias.size()) - { - res.status = API_RETURN_CODE_NOT_FOUND; - return true; - } - - bool r = this->on_get_alias_details(req2, res2, error_resp, cntx); - if (!r || res2.status != API_RETURN_CODE_OK) - { - res.status = API_RETURN_CODE_FAIL; - return true; - } - - res.alias_info.details = res2.alias_details; - res.alias_info.alias = req2.alias; - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_submit(const mining::COMMAND_RPC_SUBMITSHARE::request& req, mining::COMMAND_RPC_SUBMITSHARE::response& res, connection_context& cntx) - { - if(!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - block b = AUTO_VAL_INIT(b); - if(!get_session_blob(req.id, b)) - { - res.status = "Wrong session id"; - return true; - } - - b.nonce = req.nonce; - - if(!m_core.handle_block_found(b)) - { - res.status = "Block not accepted"; - LOG_ERROR("Submited block not accepted"); - return true; - } - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_addendums(const COMMAND_RPC_GET_ADDENDUMS::request& req, COMMAND_RPC_GET_ADDENDUMS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx) - { - if (!check_core_ready()) - { - res.status = API_RETURN_CODE_BUSY; - return true; - } - - - res.status = API_RETURN_CODE_OK; - return true; - } - //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx) - { - m_core.get_tx_pool().purge_transactions(); - res.status = API_RETURN_CODE_OK; - return true; - } -} - - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL \ No newline at end of file diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h deleted file mode 100644 index d95dd52..0000000 --- a/src/rpc/core_rpc_server.h +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - -#include -#include - -#include "net/http_server_impl_base.h" -#include "core_rpc_server_commands_defs.h" -#include "currency_core/currency_core.h" -#include "p2p/net_node.h" -#include "currency_protocol/currency_protocol_handler.h" -#include "mining_protocol_defs.h" -#include "currency_core/bc_offers_service.h" - - - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL "rpc" -ENABLE_CHANNEL_BY_DEFAULT("rpc"); - -namespace currency -{ - /************************************************************************/ - /* */ - /************************************************************************/ - class core_rpc_server: public epee::http_server_impl_base - { - public: - typedef epee::net_utils::connection_context_base connection_context; - - core_rpc_server(core& cr, nodetool::node_server >& p2p, bc_services::bc_offers_service& of); - - static void init_options(boost::program_options::options_description& desc); - bool init(const boost::program_options::variables_map& vm); - - bool on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx); - - - bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx); - bool on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx); - bool on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, connection_context& cntx); - bool on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx); - bool on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res, connection_context& cntx); - bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx); - bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx); - bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx); - bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx); - bool on_set_maintainers_info(const COMMAND_RPC_SET_MAINTAINERS_INFO::request& req, COMMAND_RPC_SET_MAINTAINERS_INFO::response& res, connection_context& cntx); - bool on_get_tx_pool(const COMMAND_RPC_GET_TX_POOL::request& req, COMMAND_RPC_GET_TX_POOL::response& res, connection_context& cntx); - bool on_check_keyimages(const COMMAND_RPC_CHECK_KEYIMAGES::request& req, COMMAND_RPC_CHECK_KEYIMAGES::response& res, connection_context& cntx); - bool on_scan_pos(const COMMAND_RPC_SCAN_POS::request& req, COMMAND_RPC_SCAN_POS::response& res, connection_context& cntx); - bool on_rpc_get_blocks_details(const COMMAND_RPC_GET_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_BLOCKS_DETAILS::response& res, connection_context& cntx); - bool on_force_relaey_raw_txs(const COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& req, COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& res, connection_context& cntx); - bool on_get_offers_ex(const COMMAND_RPC_GET_OFFERS_EX::request& req, COMMAND_RPC_GET_OFFERS_EX::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - - - //json_rpc - bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx); - bool on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_submitblock2(const COMMAND_RPC_SUBMITBLOCK2::request& req, COMMAND_RPC_SUBMITBLOCK2::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_alias_details(const COMMAND_RPC_GET_ALIAS_DETAILS::request& req, COMMAND_RPC_GET_ALIAS_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_all_aliases(const COMMAND_RPC_GET_ALL_ALIASES::request& req, COMMAND_RPC_GET_ALL_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_aliases(const COMMAND_RPC_GET_ALIASES::request& req, COMMAND_RPC_GET_ALIASES::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_alias_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_addendums(const COMMAND_RPC_GET_ADDENDUMS::request& req, COMMAND_RPC_GET_ADDENDUMS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx); - bool on_get_pos_mining_details(const COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, COMMAND_RPC_GET_POS_MINING_DETAILS::response& res, connection_context& cntx); - bool on_get_current_core_tx_expiration_median(const COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res, connection_context& cntx); - bool on_get_tx_details(const COMMAND_RPC_GET_TX_DETAILS::request& req, COMMAND_RPC_GET_TX_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_search_by_id(const COMMAND_RPC_SERARCH_BY_ID::request& req, COMMAND_RPC_SERARCH_BY_ID::response& res, connection_context& cntx); - bool on_get_out_info(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT::response& res, connection_context& cntx); - bool on_get_multisig_info(const COMMAND_RPC_GET_MULTISIG_INFO::request& req, COMMAND_RPC_GET_MULTISIG_INFO::response& res, connection_context& cntx); - bool on_get_pool_txs_details(const COMMAND_RPC_GET_POOL_TXS_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_DETAILS::response& res, connection_context& cntx); - bool on_get_pool_txs_brief_details(const COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::request& req, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS::response& res, connection_context& cntx); - bool on_get_all_pool_tx_list(const COMMAND_RPC_GET_ALL_POOL_TX_LIST::request& req, COMMAND_RPC_GET_ALL_POOL_TX_LIST::response& res, connection_context& cntx); - bool on_get_pool_info(const COMMAND_RPC_GET_POOL_INFO::request& req, COMMAND_RPC_GET_POOL_INFO::response& res, connection_context& cntx); - - bool on_get_main_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_alt_block_details(const COMMAND_RPC_GET_BLOCK_DETAILS::request& req, COMMAND_RPC_GET_BLOCK_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx); - bool on_get_alt_blocks_details(const COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::request& req, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS::response& res, connection_context& cntx); - bool on_get_est_height_from_date(const COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::request& req, COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE::response& res, connection_context& cntx); - - - - - //mining rpc - bool on_login(const mining::COMMAND_RPC_LOGIN::request& req, mining::COMMAND_RPC_LOGIN::response& res, connection_context& cntx); - bool on_getjob(const mining::COMMAND_RPC_GETJOB::request& req, mining::COMMAND_RPC_GETJOB::response& res, connection_context& cntx); - bool on_submit(const mining::COMMAND_RPC_SUBMITSHARE::request& req, mining::COMMAND_RPC_SUBMITSHARE::response& res, connection_context& cntx); - - - - - - CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map - - BEGIN_URI_MAP2() - // legacy JSON-alike RPCs - MAP_URI_AUTO_JON2("/getheight", on_get_height, COMMAND_RPC_GET_HEIGHT) - MAP_URI_AUTO_JON2("/gettransactions", on_get_transactions, COMMAND_RPC_GET_TRANSACTIONS) - MAP_URI_AUTO_JON2("/sendrawtransaction", on_send_raw_tx, COMMAND_RPC_SEND_RAW_TX) - MAP_URI_AUTO_JON2("/force_relay", on_force_relaey_raw_txs, COMMAND_RPC_FORCE_RELAY_RAW_TXS) - MAP_URI_AUTO_JON2("/start_mining", on_start_mining, COMMAND_RPC_START_MINING) - MAP_URI_AUTO_JON2("/stop_mining", on_stop_mining, COMMAND_RPC_STOP_MINING) - MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO) - // binary RPCs - MAP_URI_AUTO_BIN2("/getblocks.bin", on_get_blocks, COMMAND_RPC_GET_BLOCKS_FAST) - MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES) - MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS) - MAP_URI_AUTO_BIN2("/set_maintainers_info.bin", on_set_maintainers_info, COMMAND_RPC_SET_MAINTAINERS_INFO) - MAP_URI_AUTO_BIN2("/get_tx_pool.bin", on_get_tx_pool, COMMAND_RPC_GET_TX_POOL) - MAP_URI_AUTO_BIN2("/check_keyimages.bin", on_check_keyimages, COMMAND_RPC_CHECK_KEYIMAGES) - MAP_URI_AUTO_BIN2("/scan_pos.bin", on_scan_pos, COMMAND_RPC_SCAN_POS) - MAP_URI_AUTO_BIN2("/get_pos_details.bin", on_get_pos_mining_details, COMMAND_RPC_GET_POS_MINING_DETAILS) - // JSON RPCs - BEGIN_JSON_RPC_MAP("/json_rpc") - MAP_JON_RPC ("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) - MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH) - MAP_JON_RPC_WE("getblocktemplate", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE) - MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK) - MAP_JON_RPC_WE("submitblock2", on_submitblock2, COMMAND_RPC_SUBMITBLOCK2) - MAP_JON_RPC_WE("getlastblockheader", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER) - MAP_JON_RPC_WE("getblockheaderbyhash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH) - MAP_JON_RPC_WE("getblockheaderbyheight", on_get_block_header_by_height, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT) - MAP_JON_RPC_WE("get_alias_details", on_get_alias_details, COMMAND_RPC_GET_ALIAS_DETAILS) - MAP_JON_RPC_WE("get_alias_by_address", on_alias_by_address, COMMAND_RPC_GET_ALIASES_BY_ADDRESS) - MAP_JON_RPC_WE("get_alias_reward", on_get_alias_reward, COMMAND_RPC_GET_ALIAS_REWARD) - MAP_JON_RPC ("get_est_height_from_date", on_get_est_height_from_date, COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE) - //block explorer api - MAP_JON_RPC ("get_blocks_details", on_rpc_get_blocks_details, COMMAND_RPC_GET_BLOCKS_DETAILS) - MAP_JON_RPC_WE("get_tx_details", on_get_tx_details, COMMAND_RPC_GET_TX_DETAILS) - MAP_JON_RPC ("search_by_id", on_search_by_id, COMMAND_RPC_SERARCH_BY_ID) - MAP_JON_RPC ("getinfo", on_get_info , COMMAND_RPC_GET_INFO) - MAP_JON_RPC ("get_out_info", on_get_out_info, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT) - MAP_JON_RPC ("get_multisig_info", on_get_multisig_info, COMMAND_RPC_GET_MULTISIG_INFO) - MAP_JON_RPC_WE("get_all_alias_details", on_get_all_aliases, COMMAND_RPC_GET_ALL_ALIASES) - MAP_JON_RPC_WE("get_aliases", on_get_aliases, COMMAND_RPC_GET_ALIASES) - MAP_JON_RPC ("get_pool_txs_details", on_get_pool_txs_details, COMMAND_RPC_GET_POOL_TXS_DETAILS) - MAP_JON_RPC ("get_pool_txs_brief_details", on_get_pool_txs_brief_details, COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS) - MAP_JON_RPC ("get_all_pool_tx_list", on_get_all_pool_tx_list, COMMAND_RPC_GET_ALL_POOL_TX_LIST) - MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO) - - MAP_JON_RPC_WE("get_main_block_details", on_get_main_block_details, COMMAND_RPC_GET_BLOCK_DETAILS) - MAP_JON_RPC_WE("get_alt_block_details", on_get_alt_block_details, COMMAND_RPC_GET_BLOCK_DETAILS) - MAP_JON_RPC ("get_alt_blocks_details", on_get_alt_blocks_details, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS) - // - MAP_JON_RPC ("reset_transaction_pool", on_reset_transaction_pool, COMMAND_RPC_RESET_TX_POOL) - MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN) - // - MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX) - //remote miner rpc - MAP_JON_RPC_N(on_login, mining::COMMAND_RPC_LOGIN) - MAP_JON_RPC_N(on_getjob, mining::COMMAND_RPC_GETJOB) - MAP_JON_RPC_N(on_submit, mining::COMMAND_RPC_SUBMITSHARE) - END_JSON_RPC_MAP() - END_URI_MAP2() - - private: - - //----------------------- - bool handle_command_line(const boost::program_options::variables_map& vm); - bool check_core_ready_(const std::string& calling_method); - bool get_job(const std::string& job_id, mining::job_details& job, epee::json_rpc::error& err, connection_context& cntx); - bool get_current_hi(mining::height_info& hi); - - //utils - uint64_t get_block_reward(const block& blk); - bool fill_block_header_response(const block& blk, bool orphan_status, block_header_response& response); - void set_session_blob(const std::string& session_id, const currency::block& blob); - bool get_session_blob(const std::string& session_id, currency::block& blob); - - core& m_core; - nodetool::node_server >& m_p2p; - bc_services::bc_offers_service& m_of; - std::string m_port; - std::string m_bind_ip; - bool m_ignore_status; - //mining stuff - epee::critical_section m_session_jobs_lock; - std::map m_session_jobs; //session id -> blob - std::atomic m_session_counter; - }; -} - -#undef LOG_DEFAULT_CHANNEL -#define LOG_DEFAULT_CHANNEL NULL diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h deleted file mode 100644 index 531cbe7..0000000 --- a/src/rpc/core_rpc_server_commands_defs.h +++ /dev/null @@ -1,1613 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "serialization/keyvalue_hexemizer.h" -#include "currency_protocol/currency_protocol_defs.h" -#include "currency_core/currency_basic.h" -#include "currency_core/difficulty.h" -#include "crypto/hash.h" -#include "p2p/p2p_protocol_defs.h" -#include "rpc/mining_protocol_defs.h" -#include "storages/portable_storage_base.h" -#include "currency_core/offers_service_basics.h" -#include "currency_core/basic_api_response_codes.h" -#include "common/error_codes.h" -namespace currency -{ - //----------------------------------------------- - - struct alias_rpc_details_base - { - std::string address; - std::string tracking_key; - std::string comment; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(address) - KV_SERIALIZE(tracking_key) - KV_SERIALIZE(comment) - END_KV_SERIALIZE_MAP() - }; - - struct alias_rpc_details - { - std::string alias; - alias_rpc_details_base details; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias) - KV_CHAIN_MAP(details) - END_KV_SERIALIZE_MAP() - }; - - - struct update_alias_rpc_details - { - std::string old_address; - std::string alias; - alias_rpc_details_base details; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(old_address) - KV_SERIALIZE(alias) - KV_SERIALIZE(details) - END_KV_SERIALIZE_MAP() - }; - - - - - struct COMMAND_RPC_GET_POOL_INFO - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::string error_code; - std::list aliases_que; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(error_code) - KV_SERIALIZE(aliases_que) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_HEIGHT - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - uint64_t height; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - template - struct COMMAND_RPC_GET_BLOCKS_FAST_T - { - - struct request - { - bool need_global_indexes; - uint64_t minimum_height; - std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(need_global_indexes) - KV_SERIALIZE(minimum_height) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list blocks; - uint64_t start_height; - uint64_t current_height; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blocks) - KV_SERIALIZE(start_height) - KV_SERIALIZE(current_height) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - typedef COMMAND_RPC_GET_BLOCKS_FAST_T COMMAND_RPC_GET_BLOCKS_FAST; - typedef COMMAND_RPC_GET_BLOCKS_FAST_T COMMAND_RPC_GET_BLOCKS_DIRECT; - - //----------------------------------------------- - struct COMMAND_RPC_GET_TRANSACTIONS - { - struct request - { - std::list txs_hashes; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_hashes) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::list txs_as_hex; //transactions blobs as hex - std::list missed_tx; //not found transactions - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_as_hex) - KV_SERIALIZE(missed_tx) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - //----------------------------------------------- - struct COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE - { - struct request - { - uint64_t timestamp; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(timestamp) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - uint64_t h; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(h) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_GET_TX_POOL - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list txs; //transactions blobs - uint64_t tx_expiration_ts_median; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs) - KV_SERIALIZE(tx_expiration_ts_median) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_CHECK_KEYIMAGES - { - struct request - { - std::list images; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(images) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list images_stat; //true - unspent, false - spent - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(images_stat) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES - { - struct request - { - std::list txids; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(txids) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::vector > > tx_global_outs; - //std::vector o_indexes; - std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_global_outs) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES_BY_AMOUNT - { - struct request - { - uint64_t amount; - uint64_t i; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(i) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - crypto::hash tx_id; - uint64_t out_no; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) - KV_SERIALIZE(out_no) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_MULTISIG_INFO - { - struct request - { - crypto::hash ms_id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(ms_id) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - crypto::hash tx_id; - uint64_t out_no; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(tx_id) - KV_SERIALIZE(out_no) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS - { - struct request - { - std::list amounts; - uint64_t outs_count; - bool use_forced_mix_outs; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amounts) - KV_SERIALIZE(outs_count) - KV_SERIALIZE(use_forced_mix_outs) - END_KV_SERIALIZE_MAP() - }; - -#pragma pack (push, 1) - struct out_entry - { - uint64_t global_amount_index; - crypto::public_key out_key; - }; -#pragma pack(pop) - - struct outs_for_amount - { - uint64_t amount; - std::list outs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::vector outs; - std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(outs) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - //----------------------------------------------- - struct COMMAND_RPC_SET_MAINTAINERS_INFO - { - typedef nodetool::maintainers_entry request; - - struct response - { - std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - //----------------------------------------------- - struct COMMAND_RPC_SEND_RAW_TX - { - struct request - { - std::string tx_as_hex; - - request() {} - explicit request(const transaction &); - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_as_hex) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_FORCE_RELAY_RAW_TXS - { - struct request - { - std::vector txs_as_hex; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(txs_as_hex) - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_START_MINING - { - struct request - { - std::string miner_address; - uint64_t threads_count; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(miner_address) - KV_SERIALIZE(threads_count) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct outs_index_stat - { - uint64_t amount_0_001; - uint64_t amount_0_01; - uint64_t amount_0_1; - uint64_t amount_1; - uint64_t amount_10; - uint64_t amount_100; - uint64_t amount_1000; - uint64_t amount_10000; - uint64_t amount_100000; - uint64_t amount_1000000; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount_0_001) - KV_SERIALIZE(amount_0_01) - KV_SERIALIZE(amount_0_1) - KV_SERIALIZE(amount_1) - KV_SERIALIZE(amount_10) - KV_SERIALIZE(amount_100) - KV_SERIALIZE(amount_1000) - KV_SERIALIZE(amount_10000) - KV_SERIALIZE(amount_100000) - KV_SERIALIZE(amount_1000000) - END_KV_SERIALIZE_MAP() - }; - //----------------------------------------------- - - struct bc_performance_data - { - //block processing zone - uint64_t block_processing_time_0; - uint64_t block_processing_time_1; - uint64_t target_calculating_time_2; - uint64_t longhash_calculating_time_3; - uint64_t all_txs_insert_time_5; - uint64_t etc_stuff_6; - uint64_t insert_time_4; - uint64_t raise_block_core_event; - uint64_t target_calculating_enum_blocks; - uint64_t target_calculating_calc; - - //tx processing zone - uint64_t tx_check_inputs_time; - uint64_t tx_add_one_tx_time; - uint64_t tx_process_extra; - uint64_t tx_process_attachment; - uint64_t tx_process_inputs; - uint64_t tx_push_global_index; - uint64_t tx_check_exist; - uint64_t tx_append_time; - uint64_t tx_append_rl_wait; - uint64_t tx_append_is_expired; - uint64_t tx_print_log; - uint64_t tx_prapare_append; - - uint64_t tx_mixin_count; - - - uint64_t tx_store_db; - - uint64_t tx_check_inputs_prefix_hash; - uint64_t tx_check_inputs_attachment_check; - uint64_t tx_check_inputs_loop; - uint64_t tx_check_inputs_loop_kimage_check; - uint64_t tx_check_inputs_loop_ch_in_val_sig; - uint64_t tx_check_inputs_loop_scan_outputkeys_get_item_size; - uint64_t tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; - uint64_t tx_check_inputs_loop_scan_outputkeys_loop; - uint64_t tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; - uint64_t tx_check_inputs_loop_scan_outputkeys_loop_find_tx; - uint64_t tx_check_inputs_loop_scan_outputkeys_loop_handle_output; - - - //db performance data - uint64_t map_size; - uint64_t tx_count; - uint64_t writer_tx_count; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_processing_time_0) - KV_SERIALIZE(block_processing_time_1) - KV_SERIALIZE(target_calculating_time_2) - KV_SERIALIZE(longhash_calculating_time_3) - KV_SERIALIZE(all_txs_insert_time_5) - KV_SERIALIZE(etc_stuff_6) - KV_SERIALIZE(insert_time_4) - KV_SERIALIZE(raise_block_core_event) - KV_SERIALIZE(target_calculating_enum_blocks) - KV_SERIALIZE(target_calculating_calc) - //tx processing zone - KV_SERIALIZE(tx_check_inputs_time) - KV_SERIALIZE(tx_add_one_tx_time) - KV_SERIALIZE(tx_process_extra) - KV_SERIALIZE(tx_process_attachment) - KV_SERIALIZE(tx_process_inputs) - KV_SERIALIZE(tx_push_global_index) - KV_SERIALIZE(tx_check_exist) - KV_SERIALIZE(tx_append_time) - KV_SERIALIZE(tx_append_rl_wait) - KV_SERIALIZE(tx_append_is_expired) - KV_SERIALIZE(tx_store_db) - KV_SERIALIZE(tx_print_log) - KV_SERIALIZE(tx_prapare_append) - KV_SERIALIZE(tx_mixin_count) - - KV_SERIALIZE(tx_check_inputs_prefix_hash) - KV_SERIALIZE(tx_check_inputs_attachment_check) - KV_SERIALIZE(tx_check_inputs_loop) - KV_SERIALIZE(tx_check_inputs_loop_kimage_check) - KV_SERIALIZE(tx_check_inputs_loop_ch_in_val_sig) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_get_item_size) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_loop) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_loop_find_tx) - KV_SERIALIZE(tx_check_inputs_loop_scan_outputkeys_loop_handle_output) - - //db performace data - KV_SERIALIZE(map_size) - KV_SERIALIZE(tx_count) - KV_SERIALIZE(writer_tx_count) - END_KV_SERIALIZE_MAP() - }; - - struct pool_performance_data - { - uint64_t tx_processing_time; - uint64_t check_inputs_types_supported_time; - uint64_t expiration_validate_time; - uint64_t validate_amount_time; - uint64_t validate_alias_time; - uint64_t check_keyimages_ws_ms_time; - uint64_t check_inputs_time; - uint64_t begin_tx_time; - uint64_t update_db_time; - uint64_t db_commit_time; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_processing_time) - KV_SERIALIZE(check_inputs_types_supported_time) - KV_SERIALIZE(expiration_validate_time) - KV_SERIALIZE(validate_amount_time) - KV_SERIALIZE(validate_alias_time) - KV_SERIALIZE(check_keyimages_ws_ms_time) - KV_SERIALIZE(check_inputs_time) - KV_SERIALIZE(begin_tx_time) - KV_SERIALIZE(update_db_time) - KV_SERIALIZE(db_commit_time) - END_KV_SERIALIZE_MAP() - }; - - - //----------------------------------------------- - -#define COMMAND_RPC_GET_INFO_FLAG_POS_DIFFICULTY 0x0000000000000001LL -#define COMMAND_RPC_GET_INFO_FLAG_POW_DIFFICULTY 0x0000000000000002LL -#define COMMAND_RPC_GET_INFO_FLAG_NET_TIME_DELTA_MEDIAN 0x0000000000000004LL -#define COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_50 0x0000000000000008LL -#define COMMAND_RPC_GET_INFO_FLAG_CURRENT_NETWORK_HASHRATE_350 0x0000000000000010LL -#define COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_10_BLOCKS 0x0000000000000020LL -#define COMMAND_RPC_GET_INFO_FLAG_SECONDS_FOR_30_BLOCKS 0x0000000000000040LL -#define COMMAND_RPC_GET_INFO_FLAG_TRANSACTIONS_DAILY_STAT 0x0000000000000080LL -#define COMMAND_RPC_GET_INFO_FLAG_LAST_POS_TIMESTAMP 0x0000000000000100LL -#define COMMAND_RPC_GET_INFO_FLAG_LAST_POW_TIMESTAMP 0x0000000000000200LL -#define COMMAND_RPC_GET_INFO_FLAG_TOTAL_COINS 0x0000000000000400LL -#define COMMAND_RPC_GET_INFO_FLAG_LAST_BLOCK_SIZE 0x0000000000000800LL -#define COMMAND_RPC_GET_INFO_FLAG_TX_COUNT_IN_LAST_BLOCK 0x0000000000001000LL -#define COMMAND_RPC_GET_INFO_FLAG_POS_SEQUENCE_FACTOR 0x0000000000002000LL -#define COMMAND_RPC_GET_INFO_FLAG_POW_SEQUENCE_FACTOR 0x0000000000004000LL -#define COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT 0x0000000000008000LL -#define COMMAND_RPC_GET_INFO_FLAG_PERFORMANCE 0x0000000000010000LL -#define COMMAND_RPC_GET_INFO_FLAG_POS_BLOCK_TS_SHIFT_VS_ACTUAL 0x0000000000020000LL -#define COMMAND_RPC_GET_INFO_FLAG_MARKET 0x0000000000040000LL -#define COMMAND_RPC_GET_INFO_FLAG_EXPIRATIONS_MEDIAN 0x0000000000080000LL - -#define COMMAND_RPC_GET_INFO_FLAG_ALL_FLAGS 0xffffffffffffffffLL - - - struct COMMAND_RPC_GET_INFO - { - struct request - { - uint64_t flags; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(flags) - END_KV_SERIALIZE_MAP() - }; - - enum - { - daemon_network_state_connecting = 0, - daemon_network_state_synchronizing = 1, - daemon_network_state_online = 2, - daemon_network_state_loading_core = 3, - daemon_network_state_internal_error = 4, - daemon_network_state_unloading_core = 5, - daemon_network_state_downloading_database = 6 - }; - - struct response - { - std::string status; - uint64_t height; - std::string pos_difficulty; - uint64_t pow_difficulty; - uint64_t tx_count; - uint64_t tx_pool_size; - uint64_t alt_blocks_count; - uint64_t outgoing_connections_count; - uint64_t incoming_connections_count; - uint64_t synchronized_connections_count; - int64_t net_time_delta_median; - uint64_t white_peerlist_size; - uint64_t grey_peerlist_size; - uint64_t current_blocks_median; - uint64_t current_network_hashrate_50; - uint64_t current_network_hashrate_350; - uint64_t seconds_for_10_blocks; - uint64_t seconds_for_30_blocks; - uint64_t alias_count; - uint64_t daemon_network_state; - uint64_t synchronization_start_height; - uint64_t max_net_seen_height; - uint64_t transactions_cnt_per_day; - uint64_t transactions_volume_per_day; - nodetool::maintainers_info_external mi; - uint64_t pos_sequence_factor; - uint64_t pow_sequence_factor; - uint64_t last_pow_timestamp; - uint64_t last_pos_timestamp; - std::string total_coins; - uint64_t block_reward; - uint64_t last_block_total_reward; - uint64_t pos_diff_total_coins_rate; - int64_t pos_block_ts_shift_vs_actual; - uint64_t expiration_median_timestamp; - outs_index_stat outs_stat; - bc_performance_data performance_data; - pool_performance_data tx_pool_performance_data; - bool pos_allowed; - uint64_t last_block_size; - uint64_t current_max_allowed_block_size; - uint64_t tx_count_in_last_block; - uint64_t default_fee; - uint64_t minimum_fee; - uint64_t last_block_timestamp; - std::string last_block_hash; - //market - uint64_t offers_count; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(height) - KV_SERIALIZE(pos_difficulty) - KV_SERIALIZE(pow_difficulty) - KV_SERIALIZE(tx_count) - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(alt_blocks_count) - KV_SERIALIZE(outgoing_connections_count) - KV_SERIALIZE(incoming_connections_count) - KV_SERIALIZE(synchronized_connections_count) - KV_SERIALIZE(net_time_delta_median) - KV_SERIALIZE(white_peerlist_size) - KV_SERIALIZE(grey_peerlist_size) - KV_SERIALIZE(current_blocks_median) - KV_SERIALIZE(current_network_hashrate_50) - KV_SERIALIZE(current_network_hashrate_350) - KV_SERIALIZE(alias_count) - KV_SERIALIZE(daemon_network_state) - KV_SERIALIZE(synchronization_start_height) - KV_SERIALIZE(max_net_seen_height) - KV_SERIALIZE(transactions_cnt_per_day) - KV_SERIALIZE(transactions_volume_per_day) - KV_SERIALIZE(mi) - KV_SERIALIZE(pos_sequence_factor) - KV_SERIALIZE(pow_sequence_factor) - KV_SERIALIZE(last_pow_timestamp) - KV_SERIALIZE(last_pos_timestamp) - KV_SERIALIZE(seconds_for_10_blocks) - KV_SERIALIZE(seconds_for_30_blocks) - KV_SERIALIZE(total_coins) - KV_SERIALIZE(block_reward) - KV_SERIALIZE(last_block_total_reward) - KV_SERIALIZE(pos_diff_total_coins_rate) - KV_SERIALIZE(pos_block_ts_shift_vs_actual) - KV_SERIALIZE(expiration_median_timestamp) - KV_SERIALIZE(pos_allowed) - KV_SERIALIZE(outs_stat) - KV_SERIALIZE(performance_data) - KV_SERIALIZE(tx_pool_performance_data) - KV_SERIALIZE(last_block_size) - KV_SERIALIZE(current_max_allowed_block_size) - KV_SERIALIZE(tx_count_in_last_block) - KV_SERIALIZE(default_fee) - KV_SERIALIZE(minimum_fee) - KV_SERIALIZE(last_block_timestamp) - KV_SERIALIZE(last_block_hash) - KV_SERIALIZE(offers_count) - END_KV_SERIALIZE_MAP() - }; - }; - //----------------------------------------------- - struct COMMAND_RPC_STOP_MINING - { - struct request - { - - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - // - struct COMMAND_RPC_GETBLOCKCOUNT - { - typedef std::list request; - - struct response - { - uint64_t count; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(count) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GETBLOCKHASH - { - typedef std::vector request; - - typedef std::string response; - }; - - - struct COMMAND_RPC_GETBLOCKTEMPLATE - { - struct request - { - blobdata explicit_transaction; - std::string extra_text; - std::string wallet_address; - std::string stakeholder_address; - bool pos_block; //is pos block - uint64_t pos_amount; // - uint64_t pos_index; // - uint64_t stake_unlock_time; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction) - KV_SERIALIZE(extra_text) - KV_SERIALIZE(wallet_address) - KV_SERIALIZE(stakeholder_address); - KV_SERIALIZE(pos_block) - KV_SERIALIZE(pos_amount) - KV_SERIALIZE(pos_index) - KV_SERIALIZE(stake_unlock_time) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string difficulty; - uint64_t height; - crypto::hash seed; - blobdata blocktemplate_blob; - std::string prev_hash; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(difficulty) - KV_SERIALIZE(height) - KV_SERIALIZE_POD_AS_HEX_STRING(seed) - KV_SERIALIZE(blocktemplate_blob) - KV_SERIALIZE(prev_hash) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SUBMITBLOCK - { - typedef std::vector request; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SUBMITBLOCK2 - { - struct request - { - std::string b; //hex encoded block blob - std::list explicit_txs; //hex encoded tx blobs - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_BLOB_AS_HEX_STRING(b) - KV_SERIALIZE(explicit_txs) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct block_header_response - { - uint8_t major_version; - uint8_t minor_version; - uint64_t timestamp; - std::string prev_hash; - uint64_t nonce; - bool orphan_status; - uint64_t height; - uint64_t depth; - std::string hash; - std::string difficulty; - uint64_t reward; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(major_version) - KV_SERIALIZE(minor_version) - KV_SERIALIZE(timestamp) - KV_SERIALIZE(prev_hash) - KV_SERIALIZE(nonce) - KV_SERIALIZE(orphan_status) - KV_SERIALIZE(height) - KV_SERIALIZE(depth) - KV_SERIALIZE(hash) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(reward) - END_KV_SERIALIZE_MAP() - }; - - struct COMMAND_RPC_GET_LAST_BLOCK_HEADER - { - typedef std::list request; - - struct response - { - std::string status; - block_header_response block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH - { - struct request - { - std::string hash; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hash) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_header_response block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT - { - struct request - { - uint64_t height; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_header_response block_header; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(block_header) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - - }; - - struct COMMAND_RPC_GET_ALIAS_DETAILS - { - struct request - { - std::string alias; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - alias_rpc_details_base alias_details; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias_details) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_ALIAS_REWARD - { - struct request - { - std::string alias; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - uint64_t reward; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(reward) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_ALL_ALIASES - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list aliases; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(aliases) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_ALIASES - { - struct request - { - uint64_t offset; - uint64_t count; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(offset) - KV_SERIALIZE(count) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::list aliases; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(aliases) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_ALIASES_BY_ADDRESS - { - - typedef std::string request; - - struct response - { - //std::string alias; - alias_rpc_details alias_info; - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(alias_info) - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_ADDENDUMS - { - - typedef mining::height_info request; - - struct response - { - std::string status; - std::list addms; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(addms) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_RESET_TX_POOL - { - - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SCAN_POS - { - struct request - { - std::vector pos_entries; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(pos_entries) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - uint64_t index; - uint64_t block_timestamp; - uint64_t height; - uint64_t starter_timestamp; - crypto::hash last_block_hash; - bool is_pos_allowed; - uint64_t iterations_processed; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(index) - KV_SERIALIZE(block_timestamp) - KV_SERIALIZE(height) - KV_SERIALIZE(is_pos_allowed) - KV_SERIALIZE(iterations_processed) - KV_SERIALIZE(starter_timestamp) - KV_SERIALIZE_VAL_POD_AS_BLOB(last_block_hash); - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_POS_MINING_DETAILS - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - stake_modifier_type sm; - uint64_t starter_timestamp; - std::string pos_basic_difficulty; - std::string status; - crypto::hash last_block_hash; - bool pos_mining_allowed; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB(sm) - KV_SERIALIZE(pos_basic_difficulty) - KV_SERIALIZE(starter_timestamp) - KV_SERIALIZE(pos_mining_allowed) - KV_SERIALIZE(status) - KV_SERIALIZE_VAL_POD_AS_BLOB(last_block_hash) - END_KV_SERIALIZE_MAP() - }; - }; - - struct tx_out_rpc_entry - { - uint64_t amount; - std::list pub_keys; - uint64_t minimum_sigs; - bool is_spent; - uint64_t global_index; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(pub_keys) - KV_SERIALIZE(minimum_sigs) - KV_SERIALIZE(is_spent) - KV_SERIALIZE(global_index) - END_KV_SERIALIZE_MAP() - }; - - struct tx_in_rpc_entry - { - uint64_t amount; - uint64_t multisig_count; - std::string htlc_origin; - std::string kimage_or_ms_id; - std::vector global_indexes; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(amount) - KV_SERIALIZE(htlc_origin) - KV_SERIALIZE(kimage_or_ms_id) - KV_SERIALIZE(global_indexes) - KV_SERIALIZE(multisig_count) - END_KV_SERIALIZE_MAP() - }; - - struct tx_extra_rpc_entry - { - std::string type; - std::string short_view; - std::string datails_view; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(type) - KV_SERIALIZE(short_view) - KV_SERIALIZE(datails_view) - END_KV_SERIALIZE_MAP() - }; - - - struct tx_rpc_extended_info - { - blobdata blob; - uint64_t blob_size; - uint64_t fee; - uint64_t amount; - uint64_t timestamp; - int64_t keeper_block; // signed int, -1 means unconfirmed transaction - std::string id; - std::string pub_key; - std::vector outs; - std::vector ins; - std::vector extra; - std::vector attachments; - std::string object_in_json; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blob) - KV_SERIALIZE(blob_size) - KV_SERIALIZE(timestamp) - KV_SERIALIZE(keeper_block) - KV_SERIALIZE(fee) - KV_SERIALIZE(amount) - KV_SERIALIZE(id) - KV_SERIALIZE(pub_key) - KV_SERIALIZE(outs) - KV_SERIALIZE(ins) - KV_SERIALIZE(extra) - KV_SERIALIZE(attachments) - KV_SERIALIZE(object_in_json) - END_KV_SERIALIZE_MAP() - }; - - struct tx_rpc_brief_info - { - std::string id; - uint64_t fee; - uint64_t total_amount; - uint64_t sz; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - KV_SERIALIZE(fee) - KV_SERIALIZE(total_amount) - KV_SERIALIZE(sz) - END_KV_SERIALIZE_MAP() - }; - - struct block_rpc_extended_info - { - std::string blob; - uint64_t height; - uint64_t timestamp; - uint64_t actual_timestamp; - uint64_t block_cumulative_size; - uint64_t total_txs_size; - uint64_t block_tself_size; - uint64_t base_reward; - uint64_t summary_reward; - uint64_t penalty; - uint64_t total_fee; - std::string id; - std::string cumulative_diff_adjusted; - std::string cumulative_diff_precise; - std::string difficulty; - std::string prev_id; - std::string pow_seed; - uint64_t type; - bool is_orphan; - std::string already_generated_coins; - uint64_t this_block_fee_median; - uint64_t effective_fee_median; - std::list transactions_details; - std::string miner_text_info; - std::string object_in_json; - - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blob) - KV_SERIALIZE(height) - KV_SERIALIZE(timestamp) - KV_SERIALIZE(actual_timestamp) - KV_SERIALIZE(block_cumulative_size) - KV_SERIALIZE(total_txs_size) - KV_SERIALIZE(block_tself_size) - KV_SERIALIZE(base_reward) - KV_SERIALIZE(summary_reward) - KV_SERIALIZE(total_fee) - KV_SERIALIZE(penalty) - KV_SERIALIZE(id) - KV_SERIALIZE(prev_id) - KV_SERIALIZE(pow_seed) - KV_SERIALIZE(cumulative_diff_adjusted) - KV_SERIALIZE(cumulative_diff_precise) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(already_generated_coins) - KV_SERIALIZE(this_block_fee_median) - KV_SERIALIZE(effective_fee_median) - KV_SERIALIZE(transactions_details) - KV_SERIALIZE(type) - KV_SERIALIZE(is_orphan) - KV_SERIALIZE(miner_text_info) - KV_SERIALIZE(object_in_json) - END_KV_SERIALIZE_MAP() - }; - - - - struct COMMAND_RPC_GET_BLOCKS_DETAILS - { - struct request - { - uint64_t height_start; - uint64_t count; - bool ignore_transactions; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height_start) - KV_SERIALIZE(count) - KV_SERIALIZE(ignore_transactions) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list blocks; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(blocks) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_ALT_BLOCKS_DETAILS - { - struct request - { - uint64_t offset; - uint64_t count; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(offset) - KV_SERIALIZE(count) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::vector blocks; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(blocks) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_BLOCK_DETAILS - { - struct request - { - crypto::hash id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_POD_AS_HEX_STRING(id) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - block_rpc_extended_info block_details; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(block_details) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_POOL_TXS_DETAILS - { - struct request - { - std::list ids; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(ids) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list txs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_POOL_TXS_BRIEF_DETAILS - { - struct request - { - std::list ids; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(ids) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list txs; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(txs) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_ALL_POOL_TX_LIST - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list ids; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(ids) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_GLOBAL_INDEX_INFO - { - struct request - { - uint64_t height_start; - uint64_t count; - bool ignore_transactions; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height_start) - KV_SERIALIZE(count) - KV_SERIALIZE(ignore_transactions) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list blocks; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(blocks) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_TX_DETAILS - { - struct request - { - std::string tx_hash; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_hash) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - tx_rpc_extended_info tx_info; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(tx_info) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct search_entry - { - std::string type; - }; - - struct COMMAND_RPC_SERARCH_BY_ID - { - struct request - { - std::string id; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list types_found; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(types_found) - END_KV_SERIALIZE_MAP() - }; - }; - - - struct COMMAND_RPC_GET_OFFERS_EX - { - struct request - { - bc_services::core_offers_filter filter; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(filter) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::list offers; - uint64_t total_offers; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(offers) - KV_SERIALIZE(total_offers) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN - { - struct request - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - uint64_t expiration_median; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(expiration_median) - END_KV_SERIALIZE_MAP() - }; - }; - - struct void_struct - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - -} - diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h deleted file mode 100644 index 38df732..0000000 --- a/src/rpc/core_rpc_server_error_codes.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once - - -#define CORE_RPC_ERROR_CODE_WRONG_PARAM -1 -#define CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT -2 -#define CORE_RPC_ERROR_CODE_TOO_BIG_RESERVE_SIZE -3 -#define CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS -4 -#define CORE_RPC_ERROR_CODE_INTERNAL_ERROR -5 -#define CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB -6 -#define CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED -7 -#define CORE_RPC_ERROR_CODE_CORE_BUSY -9 -#define CORE_RPC_ERROR_CODE_INVALID_ALIAS_NAME -10 -#define CORE_RPC_ERROR_CODE_INVALID_ALIAS_ADDRESS -11 -#define CORE_RPC_ERROR_CODE_ALIAS_COMMENT_TO_LONG -12 -#define CORE_RPC_ERROR_CODE_BLOCK_ADDED_AS_ALTERNATIVE -13 -#define CORE_RPC_ERROR_CODE_NOT_FOUND -14 - diff --git a/src/rpc/mining_protocol_defs.h b/src/rpc/mining_protocol_defs.h deleted file mode 100644 index 4a2c0f2..0000000 --- a/src/rpc/mining_protocol_defs.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2014-2018 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#pragma once -#include "currency_protocol/currency_protocol_defs.h" -#include "currency_core/currency_basic.h" -#include "crypto/hash.h" -#include "net/rpc_method_name.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Seems to be obsolete. Consider removing due to stratum support. -// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -namespace mining -{ - struct height_info - { - uint64_t height; - std::string block_id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(block_id) - END_KV_SERIALIZE_MAP() - }; - - - struct addendum - { - height_info hi; - std::string prev_id; - std::string addm; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hi) - KV_SERIALIZE(prev_id) - KV_SERIALIZE(addm) - END_KV_SERIALIZE_MAP() - }; - - struct job_details - { - std::string blob; - std::string difficulty; - std::string job_id; - height_info prev_hi; - std::list addms; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(blob) - KV_SERIALIZE(difficulty) - KV_SERIALIZE(job_id) - KV_SERIALIZE(prev_hi) - KV_SERIALIZE(addms) - END_KV_SERIALIZE_MAP() - }; - - struct COMMAND_RPC_LOGIN - { - RPC_METHOD_NAME("login"); - - struct request - { - std::string login; - std::string pass; - std::string agent; - height_info hi; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(login) - KV_SERIALIZE(pass) - KV_SERIALIZE(agent) - KV_SERIALIZE(hi) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - std::string id; - job_details job; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_SERIALIZE(id) - KV_SERIALIZE(job) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_GETJOB - { - RPC_METHOD_NAME("getjob"); - - struct request - { - std::string id; - height_info hi; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - KV_SERIALIZE(hi) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - job_details jd; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - KV_CHAIN_MAP(jd) - END_KV_SERIALIZE_MAP() - }; - }; - - struct COMMAND_RPC_SUBMITSHARE - { - RPC_METHOD_NAME("submit"); - - struct request - { - std::string id; - uint64_t nonce; - std::string job_id; - std::string result; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(id) - KV_SERIALIZE(nonce) - KV_SERIALIZE(job_id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string status; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) - END_KV_SERIALIZE_MAP() - }; - }; - -} - diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h deleted file mode 100644 index b951a10..0000000 --- a/src/serialization/binary_archive.h +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2014-2017 The The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/* binary_archive.h - * - * Portable (low-endian) binary archive */ -#pragma once - -#include -#include -#include -#include - -#include "common/varint.h" -#include "warnings.h" - -PUSH_VS_WARNINGS -DISABLE_VS_WARNINGS(4244) -DISABLE_VS_WARNINGS(4100) - -//TODO: fix size_t warning in x32 platform - -template -struct binary_archive_base -{ - typedef Stream stream_type; - typedef binary_archive_base base_type; - typedef boost::mpl::bool_ is_saving; - - typedef uint8_t variant_tag_type; - - explicit binary_archive_base(stream_type &s) : stream_(s) { } - - bool is_saving_arch(){ return IsSaving; } - void tag(const char *) { } - void begin_object() { } - void end_object() { } - void begin_variant() { } - void end_variant() { } - stream_type &stream() { return stream_; } -protected: - stream_type &stream_; -}; - -template -struct binary_archive; - -template <> -struct binary_archive : public binary_archive_base -{ - explicit binary_archive(stream_type &s) : base_type(s) { - stream_type::streampos pos = stream_.tellg(); - stream_.seekg(0, std::ios_base::end); - eof_pos_ = stream_.tellg(); - stream_.seekg(pos); - } - - template - void serialize_int(T &v) - { - serialize_uint(*(typename boost::make_unsigned::type *)&v); - } - - - template - void serialize_uint(T &v, size_t width = sizeof(T)) - { - T ret = 0; - unsigned shift = 0; - for (size_t i = 0; i < width; i++) { - //std::cerr << "tell: " << stream_.tellg() << " value: " << ret << std::endl; - char c; - stream_.get(c); - T b = (unsigned char)c; - ret += (b << shift); - shift += 8; - } - v = ret; - } - void serialize_blob(void *buf, size_t len, const char *delimiter="") { - stream_.read((char *)buf, len); - } - - template - void serialize_varint(T &v) - { - serialize_uvarint(*(typename boost::make_unsigned::type *)(&v)); - } - - template - void serialize_uvarint(T &v) - { - typedef std::istreambuf_iterator it; - tools::read_varint(it(stream_), it(), v); // XXX handle failure - } - void begin_array(size_t &s) - { - serialize_varint(s); - } - void begin_array() { } - - void delimit_array() { } - void end_array() { } - - void begin_string(const char *delimiter="\"") { } - void end_string(const char *delimiter="\"") { } - - void read_variant_tag(variant_tag_type &t) { - serialize_int(t); - } - - size_t remaining_bytes() { - if (!stream_.good()) - return 0; - //std::cerr << "tell: " << stream_.tellg() << std::endl; - assert(stream_.tellg() <= eof_pos_); - return eof_pos_ - stream_.tellg(); - } -protected: - std::streamoff eof_pos_; -}; - -template <> -struct binary_archive : public binary_archive_base -{ - explicit binary_archive(stream_type &s) : base_type(s) { } - - template - void serialize_int(T v) - { - serialize_uint(static_cast::type>(v)); - } - template - void serialize_uint(T v) - { - for (size_t i = 0; i < sizeof(T); i++) { - stream_.put((char)(v & 0xff)); - if (1 < sizeof(T)) { - v >>= 8; - } - } - } - void serialize_blob(void *buf, size_t len, const char *delimiter="") { stream_.write((char *)buf, len); } - - template - void serialize_varint(T &v) - { - serialize_uvarint(*(typename boost::make_unsigned::type *)(&v)); - } - - template - void serialize_uvarint(T &v) - { - typedef std::ostreambuf_iterator it; - tools::write_varint(it(stream_), v); - } - void begin_array(size_t s) - { - serialize_varint(s); - } - void begin_array() { } - void delimit_array() { } - void end_array() { } - - void begin_string(const char *delimiter="\"") { } - void end_string(const char *delimiter="\"") { } - - void write_variant_tag(variant_tag_type t) { - serialize_int(t); - } -}; - -POP_VS_WARNINGS diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h deleted file mode 100644 index c9b5c31..0000000 --- a/src/serialization/binary_utils.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2014-2017 The The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include "binary_archive.h" - -namespace serialization { - -template -bool parse_binary(const std::string &blob, T &v) -{ - std::istringstream istr(blob); - binary_archive iar(istr); - return ::serialization::serialize(iar, v); -} - -template -bool dump_binary(T& v, std::string& blob) -{ - std::stringstream ostr; - binary_archive oar(ostr); - bool success = ::serialization::serialize(oar, v); - blob = ostr.str(); - return success && ostr.good(); -}; - -} // namespace serialization diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h deleted file mode 100644 index c436b46..0000000 --- a/src/serialization/crypto.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2014-2017 The The Louisdor Project -// Copyright (c) 2012-2013 The Cryptonote developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "serialization.h" -#include "debug_archive.h" -#include "crypto/chacha8.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" - -/*// read -template