mrp_log_error("%s: failed to send reply", plugin->instance);
}
-static void reply_with_error(client_t *client, mrp_msg_t *msg, int16_t err)
+static void reply_with_status(client_t *client, mrp_msg_t *msg, int16_t err)
{
if (!mrp_msg_append(msg,MRP_MSG_TAG_SINT16(RESPROTO_REQUEST_STATUS,err)) ||
!mrp_transport_send(client->transp, msg))
}
}
+
+static bool write_attributes(mrp_msg_t *msg, mrp_attr_t *attrs)
+{
+#define PUSH(m, tag, typ, val) \
+ mrp_msg_append(m, MRP_MSG_TAG_##typ(RESPROTO_##tag, val))
+
+ mrp_attr_t *a;
+ bool ok;
+
+ if (attrs) {
+ for (a = attrs; a->name; a++) {
+ if (!PUSH(msg, ATTRIBUTE_NAME, STRING, a->name))
+ return false;;
+
+ switch (a->type) {
+ case mqi_string:
+ ok = PUSH(msg, ATTRIBUTE_VALUE, STRING, a->value.string);
+ break;
+ case mqi_integer:
+ ok = PUSH(msg, ATTRIBUTE_VALUE, SINT32, a->value.integer);
+ break;
+ case mqi_unsignd:
+ ok = PUSH(msg, ATTRIBUTE_VALUE, UINT32, a->value.unsignd);
+ break;
+ case mqi_floating:
+ ok = PUSH(msg, ATTRIBUTE_VALUE, DOUBLE, a->value.floating);
+ break;
+ default:
+ ok = false;
+ break;
+ }
+
+ if (!ok)
+ return false;
+ }
+ }
+
+ if (!PUSH(msg, SECTION_END, UINT8, 0))
+ return false;
+
+ return true;
+
+#undef PUSH
+}
+
+
static void query_resources_request(client_t *client, mrp_msg_t *req)
{
- const char **names = mrp_resource_definition_get_all_names(0, NULL);
+#define PUSH(m, tag, typ, val) \
+ mrp_msg_append(m, MRP_MSG_TAG_##typ(RESPROTO_##tag, val))
- if (!names)
- reply_with_error(client, req, ENOMEM);
+
+ resource_data_t *data = client->data;
+ mrp_plugin_t *plugin = data->plugin;
+ const char **names;
+ mrp_attr_t *attrs;
+ mrp_attr_t buf[ATTRIBUTE_MAX];
+ uint32_t resid;
+
+ if (!(names = mrp_resource_definition_get_all_names(0, NULL)))
+ reply_with_status(client, req, ENOMEM);
else {
- reply_with_array(client, req, RESPROTO_RESOURCE_NAME, names);
- mrp_free(names);
+ if (!PUSH(req, REQUEST_STATUS, SINT16, 0))
+ goto failed;
+ else {
+ for (resid = 0; names[resid]; resid++) {
+ attrs = mrp_resource_definition_read_all_attributes(
+ resid, ATTRIBUTE_MAX, buf);
+
+ if (!PUSH(req, RESOURCE_NAME, STRING, names[resid]) ||
+ !write_attributes(req, attrs))
+ goto failed;
+ }
+
+ if (!mrp_transport_send(client->transp, req))
+ mrp_log_error("%s: failed to send reply", plugin->instance);
+
+ mrp_free(names);
+ }
}
+
+ return;
+
+ failed:
+ mrp_log_error("%s: can't build recource query reply message",
+ plugin->instance);
+ mrp_free(names);
+
+
+#undef PUSH
}
static void query_classes_request(client_t *client, mrp_msg_t *req)
const char **names = mrp_application_class_get_all_names(0, NULL);
if (!names)
- reply_with_error(client, req, ENOMEM);
+ reply_with_status(client, req, ENOMEM);
else {
reply_with_array(client, req, RESPROTO_CLASS_NAME, names);
mrp_free(names);
const char **names = mrp_zone_get_all_names(0, NULL);
if (!names)
- reply_with_error(client, req, ENOMEM);
+ reply_with_status(client, req, ENOMEM);
else {
reply_with_array(client, req, RESPROTO_ZONE_NAME, names);
mrp_free(names);
}
}
-static int add_attribute(mrp_msg_t *req, mrp_attr_t *attr, void *pcurs)
+static int read_attribute(mrp_msg_t *req, mrp_attr_t *attr, void **pcurs)
{
uint16_t tag;
uint16_t type;
}
-static int add_resource(mrp_resource_set_t *rset, mrp_msg_t *req, void *pcurs)
+static int read_resource(mrp_resource_set_t *rset, mrp_msg_t *req,void **pcurs)
{
uint16_t tag;
uint16_t type;
mand?"mandatory":"optional ", shared?"shared":"exclusive");
for (i = 0, arst = 0; i < ATTRIBUTE_MAX && arst == 0; i++)
- arst = add_attribute(req, attrs + i, pcurs);
+ arst = read_attribute(req, attrs + i, pcurs);
memset(attrs + i, 0, sizeof(mrp_attr_t));
return arst;
}
+
static void create_resource_set_request(client_t *client, mrp_msg_t *req,
- uint32_t seqno, void *pcurs)
+ uint32_t seqno, void **pcurs)
{
static uint16_t reqtyp = RESPROTO_CREATE_RESOURCE_SET;
rsid = mrp_get_resource_set_id(rset);
- while ((arst = add_resource(rset, req, pcurs)) == 0)
+ while ((arst = read_resource(rset, req, pcurs)) == 0)
;
if (arst > 0) {
if (status != 0)
mrp_resource_set_destroy(rset);
- else {
- /* we need to register the id to the client */
+}
+
+static void destroy_resource_set_request(client_t *client, mrp_msg_t *req,
+ void **pcurs)
+{
+ uint16_t tag;
+ uint16_t type;
+ size_t size;
+ mrp_msg_value_t value;
+ uint32_t rset_id;
+ mrp_resource_set_t *rset;
+
+ MRP_ASSERT(client, "invalid argument");
+ MRP_ASSERT(client->rscli, "confused with data structures");
+
+ if (!mrp_msg_iterate(req, pcurs, &tag, &type, &value, &size) ||
+ tag != RESPROTO_RESOURCE_SET_ID || type != MRP_MSG_FIELD_UINT32)
+ {
+ reply_with_status(client, req, EINVAL);
+ return;
+ }
+
+ rset_id = value.u32;
+
+ if (!(rset = mrp_resource_client_find_set(client->rscli, rset_id))) {
+ reply_with_status(client, req, ENOENT);
+ return;
}
+
+ reply_with_status(client, req, 0);
+
+ mrp_resource_set_destroy(rset);
}
+static void acquire_resource_set_request(client_t *client, mrp_msg_t *req,
+ uint32_t seqno, bool acquire,
+ void **pcurs)
+{
+ uint16_t tag;
+ uint16_t type;
+ size_t size;
+ mrp_msg_value_t value;
+ uint32_t rset_id;
+ mrp_resource_set_t *rset;
+
+ MRP_ASSERT(client, "invalid argument");
+ MRP_ASSERT(client->rscli, "confused with data structures");
+
+ if (!mrp_msg_iterate(req, pcurs, &tag, &type, &value, &size) ||
+ tag != RESPROTO_RESOURCE_SET_ID || type != MRP_MSG_FIELD_UINT32)
+ {
+ reply_with_status(client, req, EINVAL);
+ return;
+ }
+
+ rset_id = value.u32;
+
+ if (!(rset = mrp_resource_client_find_set(client->rscli, rset_id))) {
+ reply_with_status(client, req, ENOENT);
+ return;
+ }
+
+ reply_with_status(client, req, 0);
+
+ if (acquire)
+ mrp_resource_set_acquire(rset, seqno);
+ else
+ mrp_resource_set_release(rset, seqno);
+}
+
static void connection_evt(mrp_transport_t *listen, void *user_data)
{
static uint32_t id;
create_resource_set_request(client, msg, seqno, &cursor);
break;
+ case RESPROTO_DESTROY_RESOURCE_SET:
+ destroy_resource_set_request(client, msg, &cursor);
+ break;
+
+ case RESPROTO_ACQUIRE_RESOURCE_SET:
+ acquire_resource_set_request(client, msg, seqno, true, &cursor);
+ break;
+
+ case RESPROTO_RELEASE_RESOURCE_SET:
+ acquire_resource_set_request(client, msg, seqno, false, &cursor);
+ break;
+
default:
mrp_log_warning("%s: unsupported request type %d",
plugin->instance, reqtyp);
static void resource_event_handler(uint32_t reqid, mrp_resource_set_t *rset,
void *userdata)
{
- client_t *client = (client_t *)userdata;
+#define FIELD(tag, typ, val) \
+ RESPROTO_##tag, MRP_MSG_FIELD_##typ, val
+#define PUSH(m, tag, typ, val) \
+ mrp_msg_append(m, MRP_MSG_TAG_##typ(RESPROTO_##tag, val))
+
+ client_t *client = (client_t *)userdata;
+ resource_data_t *data = client->data;
+ mrp_plugin_t *plugin = data->plugin;
+ uint16_t reqtyp;
+ uint16_t state;
+ mrp_resource_mask_t grant;
+ mrp_resource_mask_t advice;
+ mrp_resource_mask_t mask;
+ mrp_resource_mask_t all;
+ mrp_msg_t *msg;
+ mrp_resource_t *res;
+ uint32_t id;
+ const char *name;
+ void *curs;
+ mrp_attr_t attrs[ATTRIBUTE_MAX + 1];
+
+ MRP_ASSERT(rset && client, "invalid argument");
+
+ reqtyp = RESPROTO_RESOURCES_EVENT;
+ id = mrp_get_resource_set_id(rset);
+ grant = mrp_get_resource_set_grant(rset);
+ advice = mrp_get_resource_set_advice(rset);
+
+ if (mrp_get_resource_set_state(rset) == mrp_resource_acquire)
+ state = RESPROTO_ACQUIRE;
+ else
+ state = RESPROTO_RELEASE;
+
+ msg = mrp_msg_create(FIELD( SEQUENCE_NO , UINT32, reqid ),
+ FIELD( REQUEST_TYPE , UINT16, reqtyp ),
+ FIELD( RESOURCE_SET_ID, UINT32, id ),
+ FIELD( RESOURCE_STATE , UINT16, state ),
+ FIELD( RESOURCE_GRANT , UINT32, grant ),
+ FIELD( RESOURCE_ADVICE, UINT32, advice ),
+ RESPROTO_MESSAGE_END );
+
+ if (!msg)
+ goto failed;
+
+ all = grant | advice;
+ curs = NULL;
+
+ while ((res = mrp_resource_set_iterate_resources(rset, &curs))) {
+ mask = mrp_resource_get_mask(res);
+
+ if (!(all & mask))
+ continue;
+
+ id = mrp_resource_get_id(res);
+ name = mrp_resource_get_name(res);
+
+ if (!PUSH(msg, RESOURCE_ID , UINT32, id ) ||
+ !PUSH(msg, RESOURCE_NAME, STRING, name) )
+ goto failed;
+
+ if (!mrp_resource_read_all_attributes(res, ATTRIBUTE_MAX + 1, attrs))
+ goto failed;
+
+ if (!write_attributes(msg, attrs))
+ goto failed;
+ }
+
+ if (!mrp_transport_send(client->transp, msg))
+ goto failed;
+
+ mrp_msg_unref(msg);
+
+ return;
+
+ failed:
+ mrp_log_error("%s: failed to build/send message for resource event",
+ plugin->instance);
+ mrp_msg_unref(msg);
+
+#undef PUSH
+#undef FIELD
}
#include <murphy/common/msg.h>
-#define RESPROTO_BIT(n) ((uint32_t)1 << (n))
+#define RESPROTO_BIT(n) ((uint32_t)1 << (n))
-#define RESPROTO_RESFLAG_MANDATORY RESPROTO_BIT(0)
-#define RESPROTO_RESFLAG_SHARED RESPROTO_BIT(1)
+#define RESPROTO_RESFLAG_MANDATORY RESPROTO_BIT(0)
+#define RESPROTO_RESFLAG_SHARED RESPROTO_BIT(1)
-#define RESPROTO_TAG(x) ((uint16_t)(x))
+#define RESPROTO_TAG(x) ((uint16_t)(x))
-#define RESPROTO_MESSAGE_END MRP_MSG_FIELD_END
-#define RESPROTO_SECTION_END RESPROTO_TAG(1)
-#define RESPROTO_ARRAY_DIMENSION RESPROTO_TAG(2)
-#define RESPROTO_SEQUENCE_NO RESPROTO_TAG(3)
-#define RESPROTO_REQUEST_TYPE RESPROTO_TAG(4)
-#define RESPROTO_REQUEST_STATUS RESPROTO_TAG(5)
-#define RESPROTO_RESOURCE_NAME RESPROTO_TAG(6)
-#define RESPROTO_RESOURCE_FLAGS RESPROTO_TAG(7)
-#define RESPROTO_RESOURCE_SET_ID RESPROTO_TAG(8)
-#define RESPROTO_RESOURCE_PRIORITY RESPROTO_TAG(9)
-#define RESPROTO_RESOURCE_GRANT RESPROTO_TAG(10)
-#define RESPROTO_RESOURCE_ADVICE RESPROTO_TAG(11)
-#define RESPROTO_CLASS_NAME RESPROTO_TAG(12)
-#define RESPROTO_ZONE_NAME RESPROTO_TAG(13)
-#define RESPROTO_ATTRIBUTE_INDEX RESPROTO_TAG(14)
-#define RESPROTO_ATTRIBUTE_NAME RESPROTO_TAG(15)
-#define RESPROTO_ATTRIBUTE_VALUE RESPROTO_TAG(16)
+#define RESPROTO_MESSAGE_END MRP_MSG_FIELD_END
+#define RESPROTO_SECTION_END RESPROTO_TAG(1)
+#define RESPROTO_ARRAY_DIMENSION RESPROTO_TAG(2)
+#define RESPROTO_SEQUENCE_NO RESPROTO_TAG(3)
+#define RESPROTO_REQUEST_TYPE RESPROTO_TAG(4)
+#define RESPROTO_REQUEST_STATUS RESPROTO_TAG(5)
+#define RESPROTO_RESOURCE_SET_ID RESPROTO_TAG(6)
+#define RESPROTO_RESOURCE_STATE RESPROTO_TAG(7)
+#define RESPROTO_RESOURCE_GRANT RESPROTO_TAG(8)
+#define RESPROTO_RESOURCE_ADVICE RESPROTO_TAG(9)
+#define RESPROTO_RESOURCE_ID RESPROTO_TAG(10)
+#define RESPROTO_RESOURCE_NAME RESPROTO_TAG(11)
+#define RESPROTO_RESOURCE_FLAGS RESPROTO_TAG(12)
+#define RESPROTO_RESOURCE_PRIORITY RESPROTO_TAG(13)
+#define RESPROTO_CLASS_NAME RESPROTO_TAG(14)
+#define RESPROTO_ZONE_NAME RESPROTO_TAG(15)
+#define RESPROTO_ATTRIBUTE_INDEX RESPROTO_TAG(16)
+#define RESPROTO_ATTRIBUTE_NAME RESPROTO_TAG(17)
+#define RESPROTO_ATTRIBUTE_VALUE RESPROTO_TAG(18)
typedef enum {
RESPROTO_QUERY_RESOURCES,
RESPROTO_QUERY_CLASSES,
RESPROTO_QUERY_ZONES,
RESPROTO_CREATE_RESOURCE_SET,
+ RESPROTO_DESTROY_RESOURCE_SET,
+ RESPROTO_ACQUIRE_RESOURCE_SET,
+ RESPROTO_RELEASE_RESOURCE_SET,
+ RESPROTO_RESOURCES_EVENT,
} mrp_resproto_request_t;
+typedef enum {
+ RESPROTO_RELEASE,
+ RESPROTO_ACQUIRE,
+} mrp_resproto_state_t;
+
#endif /* __MURPHY_RESOURCE_PROTOCOL_H__ */