From ea3bb8363a2a9a734abd2fc330066c52d5638b6d Mon Sep 17 00:00:00 2001 From: Uwe Seimet Date: Tue, 21 Dec 2021 08:53:30 +0100 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 94786aec54c589c080dcec3b18b388a17de64ae3 Author: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Tue Dec 21 08:43:21 2021 +0100 Added support for operation meta data, code cleanup (#534) * Added messages * Comment update * Interface update * Support for localized descriptions * Sort operations * Completed meta data * rasctl -s returns operation meta data * Manpage update * Type update * Comment update * Description updates * Comment update * Added convenience method * Added convenience method * Code cleanup * Comment update * Display permitted values * For completeness sake added permitted boolean values * Added support for default value * Removed redundant message field * Description update * Description upddate * Squashed commit of the following: commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce Author: Uwe Seimet Date: Sat Dec 18 12:43:14 2021 +0100 The data type is implicit commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c Author: Uwe Seimet Date: Sat Dec 18 12:37:49 2021 +0100 Renaming commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089 Author: Uwe Seimet Date: Sat Dec 18 12:29:54 2021 +0100 Comment update commit 5f699aad2f835f72accdb445d1e59f094aeb108f Author: Uwe Seimet Date: Sat Dec 18 12:24:25 2021 +0100 Signature update commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e Author: Uwe Seimet Date: Sat Dec 18 12:22:45 2021 +0100 Signature update commit a8148ef802ca809e5a305d2caa69856c9033d932 Author: Uwe Seimet Date: Sat Dec 18 12:16:46 2021 +0100 Comment update commit ce685a92d4827e131d80d10ecd56e2b3baf173f8 Author: Uwe Seimet Date: Sat Dec 18 12:15:46 2021 +0100 Use map instead of list commit 454c0438f3589904f5dbe5253963dd200ea416dd Author: Uwe Seimet Date: Sat Dec 18 10:47:36 2021 +0100 Updated size check commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2 Author: Uwe Seimet Date: Sat Dec 18 01:23:43 2021 +0100 Initial improvements * Default value update * Comment update * Comment update * Map operations by ordinal * Added safeguard against unknown operations * Added cast * Data type update * Sort map by operation name * Renaming * Code cleanup * Comment update * Renaming * Comment update * Description updates * Fixed typo * Added operation * Logging update * Interface comment update * Fixed typo * Aded operation parameters * Updated handling of mandatory parameters * Updated assertion handling * Added missing condition * Removed duplicate cod3 * Code cleanup * Logging update * Removed duplicate code * Code cleanup * Squashed commit of the following: commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup * Shutdown functionality is only available if started with root permissions * Only restrict shutdown parameters, not everything if not root * Updated operation count check commit 693ade296756ee8e480e75663a873e4a35829034 Author: Daniel Markstedt Date: Mon Dec 20 12:04:23 2021 -0800 Bump Macproxy version to 21.12.2 (#550) commit 958fb95908f2d8cdf13c02d827f2d14f6011170e Author: akuker <34318535+akuker@users.noreply.github.com> Date: Mon Dec 20 12:50:14 2021 -0600 Adjust bus settle delay to match SCSI standard (#544) * Move the GCC v10 compiler flags into makefile instead of easyinstall.sh * #504 - Update the bus settle time to match the SCSI standard Co-authored-by: RaSCSI User commit 200bc7251f2395842df7c7be9b90f2b44940a9d4 Author: Daniel Markstedt Date: Mon Dec 20 06:20:22 2021 -0800 More helpful error message when IP does not resolve for OLED screen (#541) * More helpful error message * Remove confusing fallback IP * Tweak message commit 4ae273ccbd3e2b9bfda6426a9c1f71844b48b2d9 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:30:22 2021 -0600 Loopback tester pcb (#545) commit 46c5c1966f36841419df7c3337990ac941de3c85 Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 22:29:59 2021 -0600 RaSCSI Zero version 1.0 (#546) commit d09df31d67de3470ef4ed3fc74b40da1b181c0bb Author: Daniel Markstedt Date: Sun Dec 19 20:25:23 2021 -0800 Remove redundant code from OLED script (#547) commit d8828da6909a8b87e54f21aada20758607a2a67a Author: akuker <34318535+akuker@users.noreply.github.com> Date: Sun Dec 19 21:02:50 2021 -0600 Added list of sponsors commit bcd7e8396d945f5a051e01080354d3ac7ba63704 Author: Daniel Markstedt Date: Sun Dec 19 15:51:45 2021 -0800 Second attempt at properly creating the manpage dir (#542) commit c887edfc8c9956aa9dcac3764abe6cef16ffb596 Author: Daniel Markstedt Date: Sun Dec 19 15:50:03 2021 -0800 Remove special elevated privileges for the Web Interface (#536) * Use the pi_shutdown method to restart the rascsi service * Use the pi_shutdown method to restart the rascsi service * Remove modifications to sudoers no longer needed * Introduce sleeps attempting to connect to socket; reduce overall number of retries * Remove systemd helped methods and the functionality that depends on it * Attempts to speed up splash code * Remove unneccessary verbosity * Attempt to optimize service definition commit 801aebfb96e968a3bef1575b0301db4bd7625a35 Author: Daniel Markstedt Date: Sun Dec 19 15:47:22 2021 -0800 More readable message when downloading a file (#531) commit 29cf58288f228fe235b7d6fe2f0dd5852cf9a411 Author: Daniel Markstedt Date: Sun Dec 19 15:47:03 2021 -0800 Add a warning notice when ejecting removable media (#526) commit 7efa89523905a6985bea261f1dcf078ec76faf27 Author: Daniel Markstedt Date: Sun Dec 19 15:46:22 2021 -0800 Unzip zipfiles before storing to iso (#525) * Unzip zipfiles before storing to iso * Add helptext * Skip unzip for MacZip format * Should not be an fstring commit 39bc485671fa5163c6fc87860eed53b2966637ca Author: Daniel Markstedt Date: Sun Dec 19 15:28:22 2021 -0800 Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523) * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies * Cleanup --- doc/rasctl.1 | 3 + doc/rasctl_man_page.txt | 2 + easyinstall.sh | 11 +- src/oled_monitor/pi_cmds.py | 2 +- src/oled_monitor/rascsi_oled_monitor.py | 6 +- src/raspberrypi/Makefile | 10 ++ src/raspberrypi/gpiobus.cpp | 8 +- src/raspberrypi/gpiobus.h | 1 - src/raspberrypi/rascsi.cpp | 60 ++++----- src/raspberrypi/rascsi_interface.proto | 55 ++++++-- src/raspberrypi/rascsi_response.cpp | 159 ++++++++++++++++++++++++ src/raspberrypi/rascsi_response.h | 4 + src/raspberrypi/rasctl.cpp | 12 +- src/raspberrypi/rasctl_commands.cpp | 8 ++ src/raspberrypi/rasctl_commands.h | 1 + src/raspberrypi/rasctl_display.cpp | 59 +++++++++ src/raspberrypi/rasctl_display.h | 1 + 17 files changed, 339 insertions(+), 63 deletions(-) diff --git a/doc/rasctl.1 b/doc/rasctl.1 index 52b91aa4..7b9d41bb 100644 --- a/doc/rasctl.1 +++ b/doc/rasctl.1 @@ -83,6 +83,9 @@ List all of the devices that are currently being emulated by RaSCSI, as well as .BR \-m\fI List all file extensions recognized by RaSCSI and the device types they map to. .TP +.BR \-o\fI +Display operation meta data information. +.TP .BR \-R\fI " "\fICURRENT_NAME:NEW_NAME Rename an image file in the default image folder. .TP diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt index 244f4016..956c760e 100644 --- a/doc/rasctl_man_page.txt +++ b/doc/rasctl_man_page.txt @@ -62,6 +62,8 @@ OPTIONS -m List all file extensions recognized by RaSCSI and the device types they map to. + -o Display operation meta data information. + -R CURRENT_NAME:NEW_NAME Rename an image file in the default image folder. diff --git a/easyinstall.sh b/easyinstall.sh index f12ad150..effe3f7c 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -83,15 +83,8 @@ function installPackages() { function compileRaScsi() { cd "$BASE/src/raspberrypi" || exit 1 - # Compiler flags needed for gcc v10 and up - if [[ `gcc --version | awk '/gcc/' | awk -F ' ' '{print $3}' | awk -F '.' '{print $1}'` -ge 10 ]]; then - echo -n "gcc 10 or later detected. Will compile with the following flags: " - COMPILER_FLAGS="-DFMT_HEADER_ONLY" - echo $COMPILER_FLAGS - fi - echo "Compiling with ${CORES:-1} simultaneous cores..." - ( make clean && EXTRA_FLAGS="$COMPILER_FLAGS" make -j "${CORES:-1}" all CONNECT_TYPE="${CONNECT_TYPE:-FULLSPEC}" ) = 10) + +ifeq "$(GCCVERSION10)" "1" + CFLAGS += -DFMT_HEADER_ONLY + CXXFLAGS += -DFMT_HEADER_ONLY +endif + + + ## CONNECT_TYPE=FULLSPEC : Specify the type of RaSCSI board type ## that you are using. The typical options are ## STANDARD or FULLSPEC. The default is FULLSPEC diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index d78c66b1..a931f102 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -840,7 +840,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf) BOOL ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(GPIO_DATA_SETTLING); + SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -874,7 +874,7 @@ int GPIOBUS::CommandHandShake(BYTE *buf) ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(GPIO_DATA_SETTLING); + SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -930,7 +930,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count) ret = WaitSignal(PIN_ACK, TRUE); // Wait until the signal line stabilizes - SysTimer::SleepNsec(GPIO_DATA_SETTLING); + SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); @@ -973,7 +973,7 @@ int GPIOBUS::ReceiveHandShake(BYTE *buf, int count) } // Wait until the signal line stabilizes - SysTimer::SleepNsec(GPIO_DATA_SETTLING); + SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS); // Get data *buf = GetDAT(); diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h index cc1dcfee..46babdce 100644 --- a/src/raspberrypi/gpiobus.h +++ b/src/raspberrypi/gpiobus.h @@ -433,7 +433,6 @@ // Constant declarations (bus control timing) // //--------------------------------------------------------------------------- -#define GPIO_DATA_SETTLING 100 // Data bus stabilization time (ns) // SCSI Bus timings taken from: // https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-05.html #define SCSI_DELAY_ARBITRATION_DELAY_NS 2400 diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index e70f639b..a3f2cb08 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -484,6 +484,8 @@ bool SetLogLevel(const string& log_level) current_log_level = log_level; + LOGINFO("Set log level to '%s'", current_log_level.c_str()); + return true; } @@ -1431,10 +1433,19 @@ static void *MonThread(void *param) } } + if (!PbOperation_IsValid(command.operation())) { + LOGTRACE("Received unknown command %d", command.operation()); + + ReturnStatus(fd, false, "Unknown command", UNKNOWN_OPERATION); + continue; + } + + LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); + + PbResult result; + switch(command.operation()) { case LOG_LEVEL: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - string log_level = GetParam(command, "level"); bool status = SetLogLevel(log_level); if (!status) { @@ -1447,8 +1458,6 @@ static void *MonThread(void *param) } case DEFAULT_FOLDER: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - string folder = GetParam(command, "folder"); if (folder.empty()) { ReturnStatus(fd, false, "Can't set default image folder: Missing folder name"); @@ -1465,28 +1474,18 @@ static void *MonThread(void *param) } case DEVICES_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; rascsi_response.GetDevicesInfo(result, command, devices, UnitNum); SerializeMessage(fd, result); - break; } case DEVICE_TYPES_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_device_types_info(rascsi_response.GetDeviceTypesInfo(result, command)); SerializeMessage(fd, result); break; } case SERVER_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_server_info(rascsi_response.GetServerInfo( result, devices, reserved_ids, current_log_level, GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), scan_depth)); @@ -1495,27 +1494,18 @@ static void *MonThread(void *param) } case VERSION_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_version_info(rascsi_response.GetVersionInfo(result)); SerializeMessage(fd, result); break; } case LOG_LEVEL_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_log_level_info(rascsi_response.GetLogLevelInfo(result, current_log_level)); SerializeMessage(fd, result); break; } case DEFAULT_IMAGE_FILES_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_image_files_info(rascsi_response.GetAvailableImages(result, GetParam(command, "folder_pattern"), GetParam(command, "file_pattern"), scan_depth)); SerializeMessage(fd, result); @@ -1523,14 +1513,11 @@ static void *MonThread(void *param) } case IMAGE_FILE_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - string filename = GetParam(command, "file"); if (filename.empty()) { ReturnStatus(fd, false, "Can't get image file info: Missing filename"); } else { - PbResult result; PbImageFile* image_file = new PbImageFile(); bool status = rascsi_response.GetImageFile(image_file, filename); if (status) { @@ -1546,35 +1533,30 @@ static void *MonThread(void *param) } case NETWORK_INTERFACES_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_network_interfaces_info(rascsi_response.GetNetworkInterfacesInfo(result)); SerializeMessage(fd, result); break; } case MAPPING_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - - PbResult result; result.set_allocated_mapping_info(rascsi_response.GetMappingInfo(result)); SerializeMessage(fd, result); break; } - case RESERVED_IDS_INFO: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); + case OPERATION_INFO: { + result.set_allocated_operation_info(rascsi_response.GetOperationInfo(result)); + SerializeMessage(fd, result); + break; + } - PbResult result; + case RESERVED_IDS_INFO: { result.set_allocated_reserved_ids_info(rascsi_response.GetReservedIds(result, reserved_ids)); SerializeMessage(fd, result); break; } case SHUT_DOWN: { - LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); - ShutDown(fd, GetParam(command, "mode")); break; } @@ -1613,6 +1595,10 @@ int main(int argc, char* argv[]) { GOOGLE_PROTOBUF_VERIFY_VERSION; + // Get temporary operation info, in order to trigger an assertion on startup if the operation list is incomplete + PbResult pb_operation_info_result; + rascsi_response.GetOperationInfo(pb_operation_info_result); + int actid; BUS::phase_t phase; // added setvbuf to override stdout buffering, so logs are written immediately and not when the process exits. diff --git a/src/raspberrypi/rascsi_interface.proto b/src/raspberrypi/rascsi_interface.proto index 8d239796..77671ab4 100644 --- a/src/raspberrypi/rascsi_interface.proto +++ b/src/raspberrypi/rascsi_interface.proto @@ -72,7 +72,7 @@ enum PbOperation { // "file_pattern": Optional filter, only filenames containing the case-insensitive pattern are returned SERVER_INFO = 10; - // Get rascsi version information (PbVersionInfo) + // Get rascsi server version (PbVersionInfo) VERSION_INFO = 11; // Get information on attached devices (PbDevicesInfo) @@ -111,7 +111,7 @@ enum PbOperation { // "folder": The path of the default folder, relative to the user's home folder if relative. DEFAULT_FOLDER = 20; - // Set a new log level. + // Set the log level. // Parameters: // "level": The new log level LOG_LEVEL = 21; @@ -121,7 +121,7 @@ enum PbOperation { // "ids": A comma-separated list of IDs to reserve, or an empty string in order not to reserve any ID. RESERVE_IDS = 22; - // Shut down the rascsi process + // Shut down the rascsi process or shut down/reboot the Raspberry Pi // Parameters: // "mode": The shutdown mode, one of "rascsi", "system", "reboot" SHUT_DOWN = 23; @@ -162,19 +162,54 @@ enum PbOperation { // Parameters: // "file": The filename, relative to the default image folder. It must not contain a slash. UNPROTECT_IMAGE = 29; - - // Check whether an authentication token is valid. A client can use this in operation in order to + + // Check whether an authentication token is valid. A client can use this operation in order to // find out whether rascsi authentication is enable or to use rascsi authentication for securing // client-internal operations. CHECK_AUTHENTICATION = 30; + + // Get operation meta data (PbOperationInfo) + OPERATION_INFO = 31; } -// rascsi special purpose error codes for cases where a textual error message is not sufficient +// The operation parameter meta data. The parameter data type is provided by the protobuf API. +message PbOperationParameter { + string name = 1; + // Optional short localized description, key is the lower case locale (e.g. en, de). + // Falling back to "en" is recommended if a description for a particular language is missing. + map description = 2; + // There is no specific set of permitted values if empty + repeated string permitted_values = 3; + // Optional default value + string default_value = 4; + // True if this parameter is mandatory + bool is_mandatory = 5; +} + +// The list of parameters supported by an operation +message PbOperationMetaData { + // The operation name at the time the server-side protobuf code was generated. + string server_side_name = 1; + // Optional short localized description, key is the lower case locale (e.g. en, de). + // Falling back to "en" is recommended if a description for a particular language is missing. + map description = 2; + repeated PbOperationParameter parameters = 3; +} + +// Mapping of operations to their ordinals +message PbOperationInfo { + map operations = 1; +} + +// rascsi special purpose error codes for cases where a textual error message may not be not sufficient. +// The client may react on this code, e.g. by prompting the user for an authentication token. enum PbErrorCode { // No error code available NO_ERROR_CODE = 0; + // The client sent an operation code not supported by this server + UNKNOWN_OPERATION = 1; // Authentication/Authorization error - UNAUTHORIZED = 1; + UNAUTHORIZED = 2; } // The supported file extensions mapped to their respective device types @@ -327,7 +362,7 @@ message PbResult { // An optional error or information message, depending on the status. A string without trailing CR/LF. string msg = 2; // An optional error code. Only to be used in cases where textual information is not sufficient. - PbErrorCode error_code = 13; + PbErrorCode error_code = 14; // Optional additional result data oneof result { // The result of a SERVER_INFO command @@ -350,6 +385,8 @@ message PbResult { PbMappingInfo mapping_info = 11; // The result of a RESERVED_IDS_INFO command PbReservedIdsInfo reserved_ids_info = 12; + // The result of an OPERATION_INFO command + PbOperationInfo operation_info = 13; } } @@ -371,4 +408,6 @@ message PbServerInfo { PbReservedIdsInfo reserved_ids_info = 7; // The attached devices PbDevicesInfo devices_info = 8; + // The operation meta data + PbOperationInfo operation_info = 9; } diff --git a/src/raspberrypi/rascsi_response.cpp b/src/raspberrypi/rascsi_response.cpp index c803aa42..bf723497 100644 --- a/src/raspberrypi/rascsi_response.cpp +++ b/src/raspberrypi/rascsi_response.cpp @@ -304,6 +304,7 @@ PbServerInfo *RascsiResponse::GetServerInfo(PbResult& result, const vectorset_allocated_mapping_info(GetMappingInfo(result)); GetDevices(*server_info, devices); server_info->set_allocated_reserved_ids_info(GetReservedIds(result, reserved_ids)); + server_info->set_allocated_operation_info(GetOperationInfo(result)); result.set_status(true); @@ -363,3 +364,161 @@ PbMappingInfo *RascsiResponse::GetMappingInfo(PbResult& result) return mapping_info; } + +PbOperationInfo *RascsiResponse::GetOperationInfo(PbResult& result) +{ + PbOperationInfo *operation_info = new PbOperationInfo(); + + PbOperationMetaData *meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "name", "Image file name in case of a mass storage device"); + AddOperationParameter(meta_data, "interfaces", "Comma-separated prioritized network interface list"); + CreateOperation(operation_info, meta_data, ATTACH, "Attach device, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, DETACH, "Detach device, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, DETACH_ALL, "Detach all devices"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, START, "Start device, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, STOP, "Stop device, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + CreateOperation(operation_info, meta_data, INSERT, "Insert medium, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, EJECT, "Eject medium, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, PROTECT, "Protect medium, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, UNPROTECT, "Unprotect medium, device-specific parameters are required"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "filename_pattern", "Pattern for filtering image file names"); + CreateOperation(operation_info, meta_data, SERVER_INFO, "Get rascsi server information"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, VERSION_INFO, "Get rascsi server version"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, DEVICES_INFO, "Get information on attached devices"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, DEVICE_TYPES_INFO, "Get device properties by device type"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "filename_pattern", "Pattern for filtering image file names"); + CreateOperation(operation_info, meta_data, DEFAULT_IMAGE_FILES_INFO, "Get information on available image files"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + CreateOperation(operation_info, meta_data, IMAGE_FILE_INFO, "Get information on image file"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, LOG_LEVEL_INFO, "Get log level information"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, NETWORK_INTERFACES_INFO, "Get the available network interfaces"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, MAPPING_INFO, "Get mapping of extensions to device types"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, RESERVED_IDS_INFO, "Get list of reserved device IDs"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "folder", "Default image file folder name", "", true); + CreateOperation(operation_info, meta_data, DEFAULT_FOLDER, "Set default image file folder"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "level", "New log level", "", true); + CreateOperation(operation_info, meta_data, LOG_LEVEL, "Set log level"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "ids", "Comma-separated device ID list", "", true); + CreateOperation(operation_info, meta_data, RESERVE_IDS, "Reserve device IDs"); + + meta_data = new PbOperationMetaData(); + PbOperationParameter *parameter = AddOperationParameter(meta_data, "mode", "Shutdown mode", "", true); + parameter->add_permitted_values("rascsi"); + // System shutdown/reboot requires root permissions + if (!getuid()) { + parameter->add_permitted_values("system"); + parameter->add_permitted_values("reboot"); + } + CreateOperation(operation_info, meta_data, SHUT_DOWN, "Shut down or reboot"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + AddOperationParameter(meta_data, "size", "Image file size in bytes", "", true); + parameter = AddOperationParameter(meta_data, "read_only", "Read-only flag", "false"); + parameter->add_permitted_values("true"); + parameter->add_permitted_values("false"); + CreateOperation(operation_info, meta_data, CREATE_IMAGE, "Create an image file"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + CreateOperation(operation_info, meta_data, DELETE_IMAGE, "Delete image file"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "from", "Source image file name", "", true); + AddOperationParameter(meta_data, "to", "Destination image file name", "", true); + CreateOperation(operation_info, meta_data, RENAME_IMAGE, "Rename image file"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "from", "Source image file name image file name", "", true); + AddOperationParameter(meta_data, "to", "Destination image file name", "", true); + parameter = AddOperationParameter(meta_data, "read_only", "Read-only flag", "false"); + parameter->add_permitted_values("true"); + parameter->add_permitted_values("false"); + CreateOperation(operation_info, meta_data, COPY_IMAGE, "Copy image file"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + CreateOperation(operation_info, meta_data, PROTECT_IMAGE, "Write-protect image file"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "file", "Image file name", "", true); + CreateOperation(operation_info, meta_data, UNPROTECT_IMAGE, "Make image file writable"); + + meta_data = new PbOperationMetaData(); + AddOperationParameter(meta_data, "token", "Authentication token to be checked", "", true); + CreateOperation(operation_info, meta_data, CHECK_AUTHENTICATION, "Check whether an authentication token is valid"); + + meta_data = new PbOperationMetaData(); + CreateOperation(operation_info, meta_data, OPERATION_INFO, "Get operation meta data"); + + // Ensure that the complete set of operations is covered + assert(operation_info->operations_size() == PbOperation_ARRAYSIZE - 1); + + result.set_status(true); + + return operation_info; +} + +void RascsiResponse::CreateOperation(PbOperationInfo *operation_info, PbOperationMetaData *meta_data, + const PbOperation& operation, const string& description) +{ + meta_data->set_server_side_name(PbOperation_Name(operation)); + (*meta_data->mutable_description())["en"] = description; + int ordinal = PbOperation_descriptor()->FindValueByName(PbOperation_Name(operation))->index(); + (*operation_info->mutable_operations())[ordinal] = *meta_data; +} + +PbOperationParameter *RascsiResponse::AddOperationParameter(PbOperationMetaData *meta_data, const string& name, + const string& description, const string& default_value, bool is_mandatory) +{ + PbOperationParameter *parameter = meta_data->add_parameters(); + parameter->set_name(name); + (*parameter->mutable_description())["en"] = description; + parameter->set_default_value(default_value); + parameter->set_is_mandatory(is_mandatory); + + return parameter; +} diff --git a/src/raspberrypi/rascsi_response.h b/src/raspberrypi/rascsi_response.h index 47ed05d5..7fbcdebe 100644 --- a/src/raspberrypi/rascsi_response.h +++ b/src/raspberrypi/rascsi_response.h @@ -40,6 +40,7 @@ public: PbNetworkInterfacesInfo *GetNetworkInterfacesInfo(PbResult&); PbMappingInfo *GetMappingInfo(PbResult&); PbLogLevelInfo *GetLogLevelInfo(PbResult&, const string&); + PbOperationInfo *GetOperationInfo(PbResult&); private: @@ -54,4 +55,7 @@ private: void GetDeviceTypeProperties(PbDeviceTypesInfo&, PbDeviceType); void GetAvailableImages(PbImageFilesInfo&, const string&, const string&, const string&, const string&, int); void GetAvailableImages(PbResult& result, PbServerInfo&, const string&, const string&, int); + void CreateOperation(PbOperationInfo *, PbOperationMetaData *, const PbOperation&, const string&); + PbOperationParameter *AddOperationParameter(PbOperationMetaData *, const string&, const string&, + const string& = "", bool = false); }; diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp index 1c149476..495d7ab2 100644 --- a/src/raspberrypi/rasctl.cpp +++ b/src/raspberrypi/rasctl.cpp @@ -118,8 +118,8 @@ int main(int argc, char* argv[]) cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl; cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] "; - cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-P TOKEN] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] "; - cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [-O] [-s] [-v] [-V] [-y] [-X]" << endl; + cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] "; + cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [o] [-O] [-s] [-v] [-V] [-y] [-X]" << endl; cerr << " where ID := {0-7}" << endl; cerr << " UNIT := {0-31}, default is 0" << endl; cerr << " CMD := {attach|detach|insert|eject|protect|unprotect|show}" << endl; @@ -259,6 +259,10 @@ int main(int argc, char* argv[]) command.set_operation(LOG_LEVEL_INFO); break; + case 'o': + command.set_operation(OPERATION_INFO); + break; + case 't': device->set_type(ParseType(optarg)); if (device->type() == UNDEFINED) { @@ -436,6 +440,10 @@ int main(int argc, char* argv[]) rasctl_commands.CommandMappingInfo(); break; + case OPERATION_INFO: + rasctl_commands.CommandOperationInfo(); + break; + default: rasctl_commands.SendCommand(); break; diff --git a/src/raspberrypi/rasctl_commands.cpp b/src/raspberrypi/rasctl_commands.cpp index d54de7be..293321e6 100644 --- a/src/raspberrypi/rasctl_commands.cpp +++ b/src/raspberrypi/rasctl_commands.cpp @@ -222,6 +222,7 @@ void RasctlCommands::CommandServerInfo() rasctl_display.DisplayNetworkInterfaces(server_info.network_interfaces_info()); rasctl_display.DisplayDeviceTypesInfo(server_info.device_types_info()); rasctl_display.DisplayReservedIdsInfo(server_info.reserved_ids_info()); + rasctl_display.DisplayOperationInfo(server_info.operation_info()); if (server_info.devices_info().devices_size()) { list sorted_devices = { server_info.devices_info().devices().begin(), server_info.devices_info().devices().end() }; @@ -278,3 +279,10 @@ void RasctlCommands::CommandMappingInfo() rasctl_display.DisplayMappingInfo(result.mapping_info()); } + +void RasctlCommands::CommandOperationInfo() +{ + SendCommand(); + + rasctl_display.DisplayOperationInfo(result.operation_info()); +} diff --git a/src/raspberrypi/rasctl_commands.h b/src/raspberrypi/rasctl_commands.h index b539f7c9..2e35193f 100644 --- a/src/raspberrypi/rasctl_commands.h +++ b/src/raspberrypi/rasctl_commands.h @@ -42,6 +42,7 @@ public: void CommandLogLevelInfo(); void CommandReservedIdsInfo(); void CommandMappingInfo(); + void CommandOperationInfo(); private: diff --git a/src/raspberrypi/rasctl_display.cpp b/src/raspberrypi/rasctl_display.cpp index 6d3e2da3..cf25e403 100644 --- a/src/raspberrypi/rasctl_display.cpp +++ b/src/raspberrypi/rasctl_display.cpp @@ -273,3 +273,62 @@ void RasctlDisplay::DisplayMappingInfo(const PbMappingInfo& mapping_info) cout << " " << mapping.first << "->" << PbDeviceType_Name(mapping.second) << endl; } } + +void RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info) +{ + const map operations = { operation_info.operations().begin(), operation_info.operations().end() }; + + // Copies result into a map sorted by operation name + const PbOperationMetaData *unknown_operation = new PbOperationMetaData(); + map sorted_operations; + for (const auto& operation : operations) { + if (PbOperation_IsValid(static_cast(operation.first))) { + sorted_operations[PbOperation_Name(static_cast(operation.first))] = operation.second; + } + else { + // If the server-side operation is unknown for the client use the server-provided operation name + // No further operation information is available in this case + sorted_operations[operation.second.server_side_name()] = *unknown_operation; + } + } + + cout << "Remote operations supported by rascsi and their parameters:" << endl; + for (const auto& operation : sorted_operations) { + if (!operation.second.server_side_name().empty()) { + cout << " " << operation.first; + if (!operation.second.description().empty()) { + cout << " (" << operation.second.description().at("en") << ")"; + } + cout << endl; + + for (const auto& parameter : operation.second.parameters()) { + cout << " " << parameter.name() << ": " + << (parameter.is_mandatory() ? "mandatory" : "optional"); + if (!parameter.description().empty()) { + cout << " (" << parameter.description().at("en") << ")"; + } + cout << endl; + + if (parameter.permitted_values_size()) { + cout << " Permitted values: "; + bool isFirst = true; + for (const auto& permitted_value : parameter.permitted_values()) { + if (!isFirst) { + cout << ", "; + } + isFirst = false; + cout << permitted_value; + } + cout << endl; + } + + if (!parameter.default_value().empty()) { + cout << " Default value: " << parameter.default_value() << endl; + } + } + } + else { + cout << " " << operation.first << " (Unknown server-side operation)" << endl; + } + } +} diff --git a/src/raspberrypi/rasctl_display.h b/src/raspberrypi/rasctl_display.h index 9957e5fa..864027a4 100644 --- a/src/raspberrypi/rasctl_display.h +++ b/src/raspberrypi/rasctl_display.h @@ -30,4 +30,5 @@ public: void DisplayImageFiles(const PbImageFilesInfo&); void DisplayNetworkInterfaces(const PbNetworkInterfacesInfo&); void DisplayMappingInfo(const PbMappingInfo&); + void DisplayOperationInfo(const PbOperationInfo&); };