diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2013-12-02 13:20:40 +0100 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2013-12-02 16:24:01 +0200 |
commit | 454cdd7a7250a8a8fa607074539a94d01591cca1 (patch) | |
tree | a1e9e95c56bf6999dc2c877a7956e5151f0a4111 /android/ipc.c | |
parent | 32b31f91b8f2990995c52c9279a85919718956e0 (diff) | |
download | bluez-454cdd7a7250a8a8fa607074539a94d01591cca1.tar.gz |
android: Add initial code for IPC message handlers
This will allow to register and unregister handlers for IPC messages
Basic sanity check will be done in common code. Commands with variable
length will be verified against minimum size only.
Diffstat (limited to 'android/ipc.c')
-rw-r--r-- | android/ipc.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/android/ipc.c b/android/ipc.c index 64b0db518..56f328bd5 100644 --- a/android/ipc.c +++ b/android/ipc.c @@ -30,12 +30,20 @@ #include <stdint.h> #include <string.h> #include <signal.h> +#include <stdbool.h> #include <sys/socket.h> #include "hal-msg.h" #include "ipc.h" #include "log.h" +struct service_handler { + const struct ipc_handler *handler; + uint8_t size; +}; + +static struct service_handler services[HAL_SERVICE_ID_MAX + 1]; + static int cmd_sk = -1; static int notif_sk = -1; @@ -124,3 +132,73 @@ void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len, ipc_send(notif_sk, service_id, opcode, len, param, -1); } + +void ipc_register(uint8_t service, const struct ipc_handler *handlers, + uint8_t size) +{ + services[service].handler = handlers; + services[service].size = size; +} + +void ipc_unregister(uint8_t service) +{ + services[service].handler = NULL; + services[service].size = 0; +} + +void ipc_handle_msg(const void *buf, ssize_t len) +{ + const struct hal_hdr *msg = buf; + const struct ipc_handler *handler; + + if (len < (ssize_t) sizeof(*msg)) { + error("IPC: message too small (%zd bytes), terminating", len); + raise(SIGTERM); + return; + } + + if (len != (ssize_t) (sizeof(*msg) + msg->len)) { + error("IPC: message malformed (%zd bytes), terminating", len); + raise(SIGTERM); + return; + } + + /* if service is valid */ + if (msg->service_id > HAL_SERVICE_ID_MAX) { + error("IPC: unknown service (0x%x), terminating", + msg->service_id); + raise(SIGTERM); + return; + } + + /* if service is registered */ + if (!services[msg->service_id].handler) { + error("IPC: unregistered service (0x%x), terminating", + msg->service_id); + raise(SIGTERM); + return; + } + + /* if opcode is valid */ + if (msg->opcode == HAL_OP_STATUS || + msg->opcode > services[msg->service_id].size) { + error("IPC: invalid opcode 0x%x for service 0x%x, terminating", + msg->opcode, msg->service_id); + raise(SIGTERM); + return; + } + + /* opcode is table offset + 1 */ + handler = &services[msg->service_id].handler[msg->opcode - 1]; + + /* if payload size is valid */ + if ((handler->var_len && handler->data_len > msg->len) || + (!handler->var_len && handler->data_len != msg->len)) { + error("IPC: size invalid opcode 0x%x service 0x%x, terminating", + msg->service_id, msg->opcode); + raise(SIGTERM); + return; + } + + handler->handler(msg->payload, msg->len); +} |