dbus: Split message_handler() into readable helper functions

This commit is contained in:
Jouni Malinen 2009-12-26 21:26:56 +02:00
parent 612bb5163d
commit 5a464ff86e

View file

@ -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;
}