diff --git a/src/lib.rs b/src/lib.rs index 452c0b64a63d4e6757cff5b01eaab1051980a589..db1c0ba0df209b8bde73b23a6b3d7726895f06bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![allow(unknown_lints)] +#![allow(non_camel_case_types)] #![allow(clippy::too_many_arguments)] #![allow(clippy::let_and_return)] #![allow(clippy::needless_return)] @@ -324,6 +325,8 @@ fn init_handlers() { "#, ) .expect("pico.cas registration should never fail"); + + forbid_unsupported_iproto_requests(); } /// Sets interactive prompt to display `picodata>`. @@ -1097,3 +1100,46 @@ fn postjoin( Ok(()) } + +::tarantool::define_enum_with_introspection! { + /// IPROTO request types that are forbidden on picodata side + enum ForbiddenIprotoTypes { + // TODO(kbezuglyi): uncomment when vshard's + // bucket distribution and discovery stop + // using IPROTO_SELECT requests + // SELECT = 1, + INSERT = 2, + REPLACE = 3, + UPDATE = 4, + DELETE = 5, + // CALL_16 = 6, - needed + // AUTH = 7, - needed + // EVAL = 8, - needed + UPSERT = 9, + // CALL = 10, - needed + EXECUTE = 11, + NOP = 12, + PREPARE = 13, + BEGIN = 14, + COMMIT = 15, + ROLLBACK = 16, + } +} + +/// Automatically forbids all unsupported IPROTO request types. +#[inline] +fn forbid_unsupported_iproto_requests() { + for iproto_request in ForbiddenIprotoTypes::VARIANTS { + // SAFETY: function is exported properly and + // arguments with argument types are correct + let rc = unsafe { + tarantool::box_iproto_override( + *iproto_request as _, + Some(tarantool::iproto_override_cb), + None, + std::ptr::null_mut(), + ) + }; + assert_eq!(rc, 0); + } +} diff --git a/src/tarantool.rs b/src/tarantool.rs index 02a11ec3cf34e3cce1f4bb5f3f22b220f6b65966..c86bf8fd0ac1eb7416f88fb99a3552909e05b7ee 100644 --- a/src/tarantool.rs +++ b/src/tarantool.rs @@ -432,3 +432,55 @@ extern "C" fn xlog_remove_cb( } }; } + +extern "C" { + /// Sets an IPROTO request handler with the provided + /// context for the given request type. + pub fn box_iproto_override( + req_type: u32, + handler: Option<iproto_handler_t>, + destroy: Option<iproto_handler_destroy_t>, + ctx: *mut (), + ) -> i32; +} + +/// Callback for overwritten handlers of IPROTO requests. +/// Sets diagnostic message and returns and error to register it. +pub extern "C" fn iproto_override_cb( + _header: *const u8, + _header_end: *const u8, + _body: *const u8, + _body_end: *const u8, + _ctx: *mut (), +) -> iproto_handler_status { + ::tarantool::set_error!( + ::tarantool::error::TarantoolErrorCode::Unsupported, + "picodata does not support this IPROTO request type, it was disabled" + ); + iproto_handler_status::IPROTO_HANDLER_ERROR +} + +/// Return codes for IPROTO request handlers. +#[allow(dead_code)] +#[repr(C)] +pub enum IprotoHandlerStatus { + IPROTO_HANDLER_OK = 0, + IPROTO_HANDLER_ERROR = 1, + IPROTO_HANDLER_FALLBACK = 2, +} + +/// Status of handlers of IPROTO requests when +/// request path of handling is overwritten. +type iproto_handler_status = IprotoHandlerStatus; + +/// Type of callback for a IPROTO request handler. +type iproto_handler_t = extern "C" fn( + header: *const u8, + header_end: *const u8, + body: *const u8, + body_end: *const u8, + ctx: *mut (), +) -> iproto_handler_status; + +/// Type of destroy callback for a IPROTO request handler. +type iproto_handler_destroy_t = extern "C" fn(ctx: *mut ());