core/cmd_interface/cmd_interface_multi_handler.c (100 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #include <stddef.h> #include <string.h> #include "cmd_interface_multi_handler.h" #include "common/unused.h" /** * Find the command handler for a specified message type. * * @param handler The multi-message handler to search for the message type. * @param message_type Identifier for the message type that needs a handler. * * @return The command handler for the message type or null if the message type is not supported. */ static const struct cmd_interface* cmd_interface_multi_handler_find_message_type ( const struct cmd_interface_multi_handler *handler, uint32_t message_type) { size_t i; for (i = 0; i < handler->type_count; i++) { if (handler->msg_types[i].type_id == message_type) { return handler->msg_types[i].handler; } } return NULL; } int cmd_interface_multi_handler_process_request (const struct cmd_interface *intf, struct cmd_interface_msg *request) { const struct cmd_interface_multi_handler *handler = (const struct cmd_interface_multi_handler*) intf; uint32_t message_type; const struct cmd_interface *msg_handler = NULL; int status; if ((handler == NULL) || (request == NULL)) { return CMD_HANDLER_INVALID_ARGUMENT; } status = handler->protocol->parse_message (handler->protocol, request, &message_type); if (status != 0) { /* Return success if an error response has already been generated for the request. */ if (status == CMD_HANDLER_PROTO_ERROR_RESPONSE) { status = 0; } /* Since the message could not be parsed or handled here, return the error for handling at * a different protocol layer. */ return status; } msg_handler = cmd_interface_multi_handler_find_message_type (handler, message_type); if (msg_handler != NULL) { status = msg_handler->process_request (msg_handler, request); } else { status = CMD_HANDLER_UNKNOWN_MESSAGE_TYPE; } /* Post-processing the response is optional, based on the the requirements of the protocol. */ if (handler->protocol->handle_request_result != NULL) { status = handler->protocol->handle_request_result (handler->protocol, status, message_type, request); } return status; } int cmd_interface_multi_handler_process_response (const struct cmd_interface *intf, struct cmd_interface_msg *response) { UNUSED (intf); UNUSED (response); /* No need to support response processing through this interface, as this functionality will * likely be handled differently and removed from the command handler interface. */ return CMD_HANDLER_UNSUPPORTED_OPERATION; } int cmd_interface_multi_handler_is_message_type_supported ( const struct cmd_interface_multi_handler *intf, uint32_t message_type) { if (intf == NULL) { return CMD_HANDLER_INVALID_ARGUMENT; } if (cmd_interface_multi_handler_find_message_type (intf, message_type) != NULL) { return 0; } else { return CMD_HANDLER_UNKNOWN_MESSAGE_TYPE; } } /** * Initialize the handler descriptor for a single message type. * * @param msg_type The descriptor to initialize. * @param type_id Identifier for the message type. This must match the message type output from the * {@link cmd_interface_protocol.parse_message} call. * @param handler The command handler to use for processing this type of message. * * @return 0 if the descriptor was initialized successfully or an error code. */ int cmd_interface_multi_handler_msg_type_init ( struct cmd_interface_multi_handler_msg_type *msg_type, uint32_t type_id, const struct cmd_interface *handler) { if ((msg_type == NULL) || (handler == NULL)) { return CMD_HANDLER_INVALID_ARGUMENT; } memset (msg_type, 0, sizeof (struct cmd_interface_multi_handler_msg_type)); msg_type->type_id = type_id; msg_type->handler = handler; return 0; } /** * Initialize a command handler for a protocol that wraps multiple different types of messages * that have different processing requirements. * * @param intf The multi-message command handler to initialize. * @param protocol Handler for protocol specific details common to all message types. * @param msg_types A list of command handlers for the different message types that are supported. * @param type_count The number of supported message types in the list. * * @return 0 if the command handler was successfully initialized or an error code. */ int cmd_interface_multi_handler_init (struct cmd_interface_multi_handler *intf, const struct cmd_interface_protocol *protocol, const struct cmd_interface_multi_handler_msg_type *msg_types, size_t type_count) { if ((intf == NULL) || (protocol == NULL) || (msg_types == NULL) || (type_count == 0)) { return CMD_HANDLER_INVALID_ARGUMENT; } memset (intf, 0, sizeof (struct cmd_interface_multi_handler)); intf->base.process_request = cmd_interface_multi_handler_process_request; #ifdef CMD_ENABLE_ISSUE_REQUEST intf->base.process_response = cmd_interface_multi_handler_process_response; #endif intf->is_message_type_supported = cmd_interface_multi_handler_is_message_type_supported; intf->protocol = protocol; intf->msg_types = msg_types; intf->type_count = type_count; return 0; } /** * Release the resources used by a multi-message type command handler. * * @param intf The command handler to release. */ void cmd_interface_multi_handler_release (const struct cmd_interface_multi_handler *intf) { UNUSED (intf); }