diff --git a/CHANGES b/CHANGES index 2eee51df69..e4e7ced146 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +8.0.0-dev.53 | 2025-05-07 08:16:46 -0700 + + * Add Storage::is_connected BIF (Tim Wojtulewicz, Corelight) + + * Move cast_handle from storage-async.bif to BackendHandleVal static method (Tim Wojtulewicz, Corelight) + 8.0.0-dev.50 | 2025-05-07 13:21:39 +0200 * cluster/websocket: Stop and wait for reply thread during Terminate() (Arne Welzel, Corelight) diff --git a/VERSION b/VERSION index 89419b4ab7..5d5041ba5a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.0.0-dev.50 +8.0.0-dev.53 diff --git a/src/storage/Backend.cc b/src/storage/Backend.cc index a8d951b0dc..566ad56850 100644 --- a/src/storage/Backend.cc +++ b/src/storage/Backend.cc @@ -164,4 +164,26 @@ bool detail::BackendHandleVal::DoUnserializeData(BrokerDataView) { return false; } +namespace detail { + +zeek::expected BackendHandleVal::CastFromAny(Val* handle) { + // Quick exit by checking the type tag. This should be faster than doing the dynamic + // cast below. + if ( handle->GetType() != detail::backend_opaque ) + return zeek::unexpected( + OperationResult{ReturnCode::OPERATION_FAILED, "Invalid storage handle type"}); + + auto b = dynamic_cast(handle); + + if ( ! b ) + return zeek::unexpected( + OperationResult{ReturnCode::OPERATION_FAILED, "Invalid storage handle type"}); + else if ( ! b->backend->IsOpen() ) + return zeek::unexpected(OperationResult{ReturnCode::NOT_CONNECTED, "Backend is closed"}); + + return b; +} + +} // namespace detail + } // namespace zeek::storage diff --git a/src/storage/Backend.h b/src/storage/Backend.h index 17fb5e33bf..ab4156f44d 100644 --- a/src/storage/Backend.h +++ b/src/storage/Backend.h @@ -309,6 +309,16 @@ public: BackendHandleVal(BackendPtr backend) : OpaqueVal(detail::backend_opaque), backend(std::move(backend)) {} ~BackendHandleVal() override = default; + /** + * Attempts to cast a handle passed from script-land into a BackendHandleVal. Used by + * various BIF methods. + * + * @param handle The handle passed from script-land. + * @return A zeek::expected with either the correctly-casted handle, or an OperationResult + * containing error information. + */ + static zeek::expected CastFromAny(Val*); + BackendPtr backend; protected: diff --git a/src/storage/CMakeLists.txt b/src/storage/CMakeLists.txt index c68b7b1af8..199f351a9b 100644 --- a/src/storage/CMakeLists.txt +++ b/src/storage/CMakeLists.txt @@ -6,6 +6,7 @@ zeek_add_subdir_library( Component.cc ReturnCode.cc BIFS + storage.bif storage-async.bif storage-events.bif storage-sync.bif) diff --git a/src/storage/storage-async.bif b/src/storage/storage-async.bif index fecfcfe341..f31322a800 100644 --- a/src/storage/storage-async.bif +++ b/src/storage/storage-async.bif @@ -33,20 +33,6 @@ static zeek::detail::trigger::TriggerPtr init_trigger(zeek::detail::Frame* frame return {NewRef{}, trigger}; } -// Utility method to cast the handle val passed into BIF methods into a form that can -// be used to start storage operations. The method is also used by the BIFs in sync.bif. -static zeek::expected cast_handle(Val* handle) { - auto b = static_cast(handle); - - if ( ! b ) - return zeek::unexpected( - OperationResult{ReturnCode::OPERATION_FAILED, "Invalid storage handlle"}); - else if ( ! b->backend->IsOpen() ) - return zeek::unexpected(OperationResult{ReturnCode::NOT_CONNECTED, "Backend is closed"}); - - return b; -} - static void handle_async_result(const IntrusivePtr& backend, ResultCallback* cb, const OperationResult& op_result) { if ( op_result.code != ReturnCode::IN_PROGRESS || ! backend->SupportsAsync() ) { @@ -112,7 +98,7 @@ function Storage::Async::__close_backend%(backend: opaque of Storage::BackendHan return nullptr; auto cb = new ResultCallback(trigger, frame->GetTriggerAssoc()); - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) { cb->Complete(b.error()); delete cb; @@ -133,7 +119,7 @@ function Storage::Async::__put%(backend: opaque of Storage::BackendHandle, key: return nullptr; auto cb = new ResultCallback(trigger, frame->GetTriggerAssoc()); - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) { cb->Complete(b.error()); delete cb; @@ -158,7 +144,7 @@ function Storage::Async::__get%(backend: opaque of Storage::BackendHandle, key: return nullptr; auto cb = new ResultCallback(trigger, frame->GetTriggerAssoc()); - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) { cb->Complete(b.error()); delete cb; @@ -179,7 +165,7 @@ function Storage::Async::__erase%(backend: opaque of Storage::BackendHandle, key return nullptr; auto cb = new ResultCallback(trigger, frame->GetTriggerAssoc()); - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) { cb->Complete(b.error()); delete cb; diff --git a/src/storage/storage-sync.bif b/src/storage/storage-sync.bif index 8c20ff4d3b..e4bf87c31c 100644 --- a/src/storage/storage-sync.bif +++ b/src/storage/storage-sync.bif @@ -7,23 +7,6 @@ using namespace zeek; using namespace zeek::storage; - -// Utility method to cast the handle val passed into BIF methods into a form that can -// be used to start storage operations. This is a duplicate of the method in sync.bif -// due to how utility methods are built by bifcl. -/* -static zeek::expected cast_handle(Val* handle) { - auto b = static_cast(handle); - - if ( ! b ) - return zeek::unexpected( - OperationResult{ReturnCode::OPERATION_FAILED, "Invalid storage handlle"}); - else if ( ! b->backend->IsOpen() ) - return zeek::unexpected(OperationResult{ReturnCode::NOT_CONNECTED, "Backend is closed"}); - - return b; -} -*/ %%} module Storage::Sync; @@ -64,7 +47,7 @@ function Storage::Sync::__close_backend%(backend: opaque of Storage::BackendHand %{ OperationResult op_result; - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) op_result = b.error(); else { @@ -89,7 +72,7 @@ function Storage::Sync::__put%(backend: opaque of Storage::BackendHandle, key: a %{ OperationResult op_result; - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) op_result = b.error(); else { @@ -118,7 +101,7 @@ function Storage::Sync::__get%(backend: opaque of Storage::BackendHandle, key: a %{ OperationResult op_result; - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) op_result = b.error(); else { @@ -143,7 +126,7 @@ function Storage::Sync::__erase%(backend: opaque of Storage::BackendHandle, key: %{ OperationResult op_result; - auto b = cast_handle(backend); + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); if ( ! b ) op_result = b.error(); else { diff --git a/src/storage/storage.bif b/src/storage/storage.bif new file mode 100644 index 0000000000..0c6413333f --- /dev/null +++ b/src/storage/storage.bif @@ -0,0 +1,24 @@ +##! Functions related to general storage operations. These are not specific to async or sync. + +%%{ + +#include "zeek/storage/Backend.h" + +using namespace zeek; +using namespace zeek::storage; + +%%} + +module Storage; + +## Checks whether a storage backend is open. +## +## backend: A handle to the backed to check. +## +## Returns: T if the backend is open, F if the backend is not open or if the handle +## is invalid. +function Storage::is_open%(backend: opaque of Storage::BackendHandle%) : bool + %{ + auto b = storage::detail::BackendHandleVal::CastFromAny(backend); + return zeek::val_mgr->Bool(b.has_value()); + %} diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index e08c150e8d..c0a0da839f 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -160,6 +160,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/bloom-filter.bif.zeek build/scripts/base/bif/cardinality-counter.bif.zeek build/scripts/base/bif/top-k.bif.zeek + build/scripts/base/bif/storage.bif.zeek build/scripts/base/bif/storage-async.bif.zeek build/scripts/base/bif/storage-events.bif.zeek build/scripts/base/bif/storage-sync.bif.zeek diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index febd84103a..37a23662ca 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -160,6 +160,7 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/bloom-filter.bif.zeek build/scripts/base/bif/cardinality-counter.bif.zeek build/scripts/base/bif/top-k.bif.zeek + build/scripts/base/bif/storage.bif.zeek build/scripts/base/bif/storage-async.bif.zeek build/scripts/base/bif/storage-events.bif.zeek build/scripts/base/bif/storage-sync.bif.zeek diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 1e97599ebf..fb1a9f61d3 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -509,6 +509,7 @@ 0.000000 MetaHookPost LoadFile(0, ./storage-async.bif.zeek, <...>/storage-async.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./storage-events.bif.zeek, <...>/storage-events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./storage-sync.bif.zeek, <...>/storage-sync.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./storage.bif.zeek, <...>/storage.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./store, <...>/store.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./store.bif.zeek, <...>/store.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./strings.bif.zeek, <...>/strings.bif.zeek) -> -1 @@ -822,6 +823,7 @@ 0.000000 MetaHookPost LoadFileExtended(0, ./storage-async.bif.zeek, <...>/storage-async.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./storage-events.bif.zeek, <...>/storage-events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./storage-sync.bif.zeek, <...>/storage-sync.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./storage.bif.zeek, <...>/storage.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./store, <...>/store.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./store.bif.zeek, <...>/store.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./strings.bif.zeek, <...>/strings.bif.zeek) -> (-1, ) @@ -1469,6 +1471,7 @@ 0.000000 MetaHookPre LoadFile(0, ./storage-async.bif.zeek, <...>/storage-async.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./storage-events.bif.zeek, <...>/storage-events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./storage-sync.bif.zeek, <...>/storage-sync.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./storage.bif.zeek, <...>/storage.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./store, <...>/store.zeek) 0.000000 MetaHookPre LoadFile(0, ./store.bif.zeek, <...>/store.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./strings.bif.zeek, <...>/strings.bif.zeek) @@ -1782,6 +1785,7 @@ 0.000000 MetaHookPre LoadFileExtended(0, ./storage-async.bif.zeek, <...>/storage-async.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./storage-events.bif.zeek, <...>/storage-events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./storage-sync.bif.zeek, <...>/storage-sync.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./storage.bif.zeek, <...>/storage.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./store, <...>/store.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./store.bif.zeek, <...>/store.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./strings.bif.zeek, <...>/strings.bif.zeek) @@ -2440,6 +2444,7 @@ 0.000000 | HookLoadFile ./storage-async.bif.zeek <...>/storage-async.bif.zeek 0.000000 | HookLoadFile ./storage-events.bif.zeek <...>/storage-events.bif.zeek 0.000000 | HookLoadFile ./storage-sync.bif.zeek <...>/storage-sync.bif.zeek +0.000000 | HookLoadFile ./storage.bif.zeek <...>/storage.bif.zeek 0.000000 | HookLoadFile ./store <...>/store.zeek 0.000000 | HookLoadFile ./store.bif.zeek <...>/store.bif.zeek 0.000000 | HookLoadFile ./strings.bif.zeek <...>/strings.bif.zeek @@ -2753,6 +2758,7 @@ 0.000000 | HookLoadFileExtended ./storage-async.bif.zeek <...>/storage-async.bif.zeek 0.000000 | HookLoadFileExtended ./storage-events.bif.zeek <...>/storage-events.bif.zeek 0.000000 | HookLoadFileExtended ./storage-sync.bif.zeek <...>/storage-sync.bif.zeek +0.000000 | HookLoadFileExtended ./storage.bif.zeek <...>/storage.bif.zeek 0.000000 | HookLoadFileExtended ./store <...>/store.zeek 0.000000 | HookLoadFileExtended ./store.bif.zeek <...>/store.bif.zeek 0.000000 | HookLoadFileExtended ./strings.bif.zeek <...>/strings.bif.zeek diff --git a/testing/btest/Baseline/scripts.base.frameworks.storage.sqlite-error-handling/out b/testing/btest/Baseline/scripts.base.frameworks.storage.sqlite-error-handling/out index b295efbe65..69e51a9087 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.storage.sqlite-error-handling/out +++ b/testing/btest/Baseline/scripts.base.frameworks.storage.sqlite-error-handling/out @@ -1,5 +1,7 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. Open result, [code=Storage::OPERATION_FAILED, error_str=Failed to open backend Storage::STORAGE_BACKEND_SQLITE: SQLite call failed: unable to open database file, value=] Open result 2, [code=Storage::SUCCESS, error_str=, value=] +Opened handle is open, T Put result with bad key type, [code=Storage::KEY_TYPE_MISMATCH, error_str=, value=] +Closed backend is open, F Put result on closed handle, [code=Storage::NOT_CONNECTED, error_str=Backend is closed, value=] diff --git a/testing/btest/opt/ZAM-bif-tracking.zeek b/testing/btest/opt/ZAM-bif-tracking.zeek index 80dcbdbd1e..dc43f6d5fa 100644 --- a/testing/btest/opt/ZAM-bif-tracking.zeek +++ b/testing/btest/opt/ZAM-bif-tracking.zeek @@ -178,6 +178,7 @@ global known_BiFs = set( "Reporter::warning", "Spicy::__resource_usage", "Spicy::__toggle_analyzer", + "Storage::is_open", "Storage::Async::__close_backend", "Storage::Async::__erase", "Storage::Async::__get", diff --git a/testing/btest/scripts/base/frameworks/storage/sqlite-error-handling.zeek b/testing/btest/scripts/base/frameworks/storage/sqlite-error-handling.zeek index 0c216405c1..352b3d54f7 100644 --- a/testing/btest/scripts/base/frameworks/storage/sqlite-error-handling.zeek +++ b/testing/btest/scripts/base/frameworks/storage/sqlite-error-handling.zeek @@ -24,6 +24,8 @@ event zeek_init() { local b = open_res$value; + print "Opened handle is open", Storage::is_open(b); + local bad_key: count = 12345; local value = "abcde"; local res = Storage::Sync::put(b, [$key=bad_key, $value=value]); @@ -31,6 +33,10 @@ event zeek_init() { # Close the backend and then attempt to use the closed handle Storage::Sync::close_backend(b); + + # Test if the now-closed backend is open. + print "Closed backend is open", Storage::is_open(b); + local res2 = Storage::Sync::put(b, [$key="a", $value="b"]); print "Put result on closed handle", res2; }