dbus: Split message_handler() into readable helper functions
This commit is contained in:
parent
612bb5163d
commit
5a464ff86e
1 changed files with 186 additions and 159 deletions
|
@ -997,6 +997,174 @@ static int is_signature_correct(DBusMessage *message,
|
|||
}
|
||||
|
||||
|
||||
static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
|
||||
return get_all_properties(message, interface,
|
||||
obj_dsc->properties);
|
||||
}
|
||||
|
||||
|
||||
static DBusMessage * properties_get(DBusMessage *message,
|
||||
struct wpa_dbus_property_desc *dsc)
|
||||
{
|
||||
if (os_strcmp(dbus_message_get_signature(message), "ss"))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
|
||||
if (dsc->access != W && dsc->getter)
|
||||
return dsc->getter(message, dsc->user_data);
|
||||
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Property is write-only");
|
||||
}
|
||||
|
||||
|
||||
static DBusMessage * properties_set(DBusMessage *message,
|
||||
struct wpa_dbus_property_desc *dsc)
|
||||
{
|
||||
if (os_strcmp(dbus_message_get_signature(message), "ssv"))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
|
||||
if (dsc->access != R && dsc->setter)
|
||||
return dsc->setter(message, dsc->user_data);
|
||||
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Property is read-only");
|
||||
}
|
||||
|
||||
|
||||
static DBusMessage *
|
||||
properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
|
||||
char *interface,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
struct wpa_dbus_property_desc *property_dsc;
|
||||
char *property;
|
||||
const char *method;
|
||||
|
||||
method = dbus_message_get_member(message);
|
||||
property_dsc = obj_dsc->properties;
|
||||
|
||||
/* Second argument: property name (DBUS_TYPE_STRING) */
|
||||
if (!dbus_message_iter_next(iter) ||
|
||||
dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
}
|
||||
dbus_message_iter_get_basic(iter, &property);
|
||||
|
||||
while (property_dsc) {
|
||||
/* compare property names and
|
||||
* interfaces */
|
||||
if (!os_strncmp(property_dsc->dbus_property, property,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
||||
!os_strncmp(property_dsc->dbus_interface, interface,
|
||||
WPAS_DBUS_INTERFACE_MAX))
|
||||
break;
|
||||
|
||||
property_dsc = property_dsc->next;
|
||||
}
|
||||
if (property_dsc == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
|
||||
interface, property,
|
||||
dbus_message_get_path(message));
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"No such property");
|
||||
}
|
||||
|
||||
if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
|
||||
return properties_get(message, property_dsc);
|
||||
|
||||
return properties_set(message, property_dsc);
|
||||
}
|
||||
|
||||
|
||||
static DBusMessage * properties_handler(DBusMessage *message,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
char *interface;
|
||||
const char *method;
|
||||
|
||||
method = dbus_message_get_member(message);
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
|
||||
!os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
|
||||
!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
|
||||
/* First argument: interface name (DBUS_TYPE_STRING) */
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
{
|
||||
return dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
}
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &interface);
|
||||
|
||||
if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
|
||||
/* GetAll */
|
||||
return properties_get_all(message, interface, obj_dsc);
|
||||
}
|
||||
/* Get or Set */
|
||||
return properties_get_or_set(message, &iter, interface,
|
||||
obj_dsc);
|
||||
}
|
||||
return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static DBusMessage * msg_method_handler(DBusMessage *message,
|
||||
struct wpa_dbus_object_desc *obj_dsc)
|
||||
{
|
||||
struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
|
||||
const char *method;
|
||||
const char *msg_interface;
|
||||
|
||||
method = dbus_message_get_member(message);
|
||||
msg_interface = dbus_message_get_interface(message);
|
||||
|
||||
/* try match call to any registered method */
|
||||
while (method_dsc) {
|
||||
/* compare method names and interfaces */
|
||||
if (!os_strncmp(method_dsc->dbus_method, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
||||
!os_strncmp(method_dsc->dbus_interface, msg_interface,
|
||||
WPAS_DBUS_INTERFACE_MAX))
|
||||
break;
|
||||
|
||||
method_dsc = method_dsc->next;
|
||||
}
|
||||
if (method_dsc == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
|
||||
msg_interface, method,
|
||||
dbus_message_get_path(message));
|
||||
return dbus_message_new_error(message,
|
||||
DBUS_ERROR_UNKNOWN_METHOD, NULL);
|
||||
}
|
||||
|
||||
if (!is_signature_correct(message, method_dsc)) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return method_dsc->method_handler(message,
|
||||
method_dsc->handler_argument);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* message_handler - Handles incoming DBus messages
|
||||
* @connection: DBus connection on which message was received
|
||||
|
@ -1008,8 +1176,8 @@ static int is_signature_correct(DBusMessage *message,
|
|||
* of the special cases i.e. introspection call or properties get/getall/set
|
||||
* methods and handles it. Else it iterates over registered methods list
|
||||
* and tries to match method's name and interface to those read from message
|
||||
* If appropriate method was found it's handler function is called and
|
||||
* response is sent. Otherwise the DBUS_ERROR_UNKNOWN_METHOD error message
|
||||
* If appropriate method was found its handler function is called and
|
||||
* response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
|
||||
* will be sent.
|
||||
*/
|
||||
static DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
|
@ -1019,17 +1187,15 @@ static DBusHandlerResult message_handler(DBusConnection *connection,
|
|||
const char *method;
|
||||
const char *path;
|
||||
const char *msg_interface;
|
||||
|
||||
#define MESSAGE_UNHANDLED (DBusMessage *) 1
|
||||
|
||||
DBusMessage *reply = MESSAGE_UNHANDLED;
|
||||
DBusMessage *reply;
|
||||
|
||||
/* get method, interface and path the message is addressed to */
|
||||
method = dbus_message_get_member(message);
|
||||
path = dbus_message_get_path(message);
|
||||
msg_interface = dbus_message_get_interface(message);
|
||||
if (!method || !path || !msg_interface)
|
||||
goto out;
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
|
||||
msg_interface, method, path);
|
||||
|
||||
|
@ -1039,162 +1205,23 @@ static DBusHandlerResult message_handler(DBusConnection *connection,
|
|||
!os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
|
||||
WPAS_DBUS_INTERFACE_MAX))
|
||||
reply = introspect(message, obj_dsc);
|
||||
else if (!strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
|
||||
WPAS_DBUS_INTERFACE_MAX)) {
|
||||
else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
|
||||
WPAS_DBUS_INTERFACE_MAX)) {
|
||||
/* if message is properties method call */
|
||||
DBusMessageIter iter;
|
||||
char *interface;
|
||||
char *property;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
|
||||
!os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
|
||||
!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
|
||||
/* First argument: interface name (DBUS_TYPE_STRING) */
|
||||
if (dbus_message_iter_get_arg_type(&iter) !=
|
||||
DBUS_TYPE_STRING) {
|
||||
reply = dbus_message_new_error(
|
||||
message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &interface);
|
||||
|
||||
/* GetAll */
|
||||
if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
|
||||
if (os_strcmp(dbus_message_get_signature(
|
||||
message), "s"))
|
||||
reply = dbus_message_new_error(
|
||||
message,
|
||||
DBUS_ERROR_INVALID_ARGS, NULL);
|
||||
else
|
||||
reply = get_all_properties(
|
||||
message, interface,
|
||||
obj_dsc->properties);
|
||||
} else {
|
||||
/* Get or Set */
|
||||
struct wpa_dbus_property_desc *property_dsc;
|
||||
property_dsc = obj_dsc->properties;
|
||||
|
||||
/* Second argument: property name
|
||||
* (DBUS_TYPE_STRING) */
|
||||
if (!dbus_message_iter_next(&iter) ||
|
||||
dbus_message_iter_get_arg_type(&iter) !=
|
||||
DBUS_TYPE_STRING) {
|
||||
reply = dbus_message_new_error(
|
||||
message,
|
||||
DBUS_ERROR_INVALID_ARGS, NULL);
|
||||
goto out;
|
||||
}
|
||||
dbus_message_iter_get_basic(&iter, &property);
|
||||
|
||||
while (property_dsc) {
|
||||
/* compare property names and
|
||||
* interfaces */
|
||||
if (!os_strncmp(property_dsc->dbus_property,
|
||||
property,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
||||
!os_strncmp(property_dsc->dbus_interface, interface,
|
||||
WPAS_DBUS_INTERFACE_MAX))
|
||||
break;
|
||||
|
||||
property_dsc = property_dsc->next;
|
||||
}
|
||||
if (property_dsc) {
|
||||
/* Get */
|
||||
if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
|
||||
if (os_strcmp(dbus_message_get_signature(message), "ss"))
|
||||
reply = dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS, NULL);
|
||||
else if (property_dsc->access != W &&
|
||||
property_dsc->getter)
|
||||
reply = property_dsc->getter(message,
|
||||
property_dsc->user_data);
|
||||
else
|
||||
reply = dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
"Property is write-only");
|
||||
} else {
|
||||
/* Set */
|
||||
if (os_strcmp(dbus_message_get_signature(message), "ssv"))
|
||||
reply = dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS, NULL);
|
||||
else if (property_dsc->access != R &&
|
||||
property_dsc->setter) {
|
||||
reply = property_dsc->setter
|
||||
(message, property_dsc->user_data);
|
||||
} else {
|
||||
reply = dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
"Property is read-only");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "no property handler for %s.%s\n"
|
||||
"on %s", interface, property, path);
|
||||
reply = dbus_message_new_error(message,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
"No such property");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reply = dbus_message_new_error(
|
||||
message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
|
||||
goto out;
|
||||
}
|
||||
reply = properties_handler(message, obj_dsc);
|
||||
} else {
|
||||
struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
|
||||
|
||||
/* try match call to any registered method */
|
||||
while (method_dsc) {
|
||||
/* compare method names and interfaces */
|
||||
if (!os_strncmp(method_dsc->dbus_method, method,
|
||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
||||
!os_strncmp(method_dsc->dbus_interface,
|
||||
msg_interface,
|
||||
WPAS_DBUS_INTERFACE_MAX))
|
||||
break;
|
||||
|
||||
method_dsc = method_dsc->next;
|
||||
}
|
||||
if (method_dsc) {
|
||||
if (is_signature_correct(message, method_dsc)) {
|
||||
reply = method_dsc->method_handler(
|
||||
message, method_dsc->handler_argument);
|
||||
} else {
|
||||
reply = dbus_message_new_error(
|
||||
message, DBUS_ERROR_INVALID_ARGS,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "no method handler for %s.%s "
|
||||
"on %s", msg_interface, method, path);
|
||||
reply = dbus_message_new_error(
|
||||
message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
|
||||
}
|
||||
reply = msg_method_handler(message, obj_dsc);
|
||||
}
|
||||
|
||||
out:
|
||||
/* If the message was handled, send back the reply */
|
||||
if (reply != MESSAGE_UNHANDLED) {
|
||||
/* If handler succeed returning NULL, reply empty message */
|
||||
if (!reply)
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (reply) {
|
||||
if (!dbus_message_get_no_reply(message))
|
||||
dbus_connection_send(connection, reply, NULL);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
} else
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
/* If handler succeed returning NULL, reply empty message */
|
||||
if (!reply)
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (reply) {
|
||||
if (!dbus_message_get_no_reply(message))
|
||||
dbus_connection_send(connection, reply, NULL);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue