summaryrefslogtreecommitdiff
path: root/android/ipc.c
diff options
context:
space:
mode:
authorSzymon Janc <szymon.janc@tieto.com>2013-12-02 13:20:40 +0100
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2013-12-02 16:24:01 +0200
commit454cdd7a7250a8a8fa607074539a94d01591cca1 (patch)
treea1e9e95c56bf6999dc2c877a7956e5151f0a4111 /android/ipc.c
parent32b31f91b8f2990995c52c9279a85919718956e0 (diff)
downloadbluez-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.c78
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);
+}