From: Luca Bruno Date: Sat, 29 May 2010 14:12:20 +0000 (+0200) Subject: D-Bus: Support no-reply methods in static libdbus clients X-Git-Tag: 0.9.2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7514c9d7c19e91d304ce9de09e2831bb28ce0239;p=thirdparty%2Fvala.git D-Bus: Support no-reply methods in static libdbus clients Fixes bug 618892. --- diff --git a/codegen/valadbusclientmodule.vala b/codegen/valadbusclientmodule.vala index f6e39ee24..e0477852a 100644 --- a/codegen/valadbusclientmodule.vala +++ b/codegen/valadbusclientmodule.vala @@ -57,6 +57,17 @@ public class Vala.DBusClientModule : DBusModule { return new CCodeConstant (timeout.to_string ()); } + public static bool is_dbus_no_reply (CodeNode node) { + var dbus_attribute = node.get_attribute ("DBus"); + if (dbus_attribute != null + && dbus_attribute.has_argument ("no_reply") + && dbus_attribute.get_bool ("no_reply")) { + return true; + } + + return false; + } + bool has_dbus_error (List error_types) { foreach (DataType error_type in error_types) { if (((ErrorType) error_type).error_domain.get_full_name () == "DBus.Error") { @@ -942,7 +953,12 @@ public class Vala.DBusClientModule : DBusModule { foreach (Method m in iface.get_methods ()) { var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name); - if (!m.coroutine) { + if (is_dbus_no_reply (m)) { + if (m.coroutine) { + Report.error (m.source_reference, "No-reply DBus methods must not be async"); + } + iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_noreply_dbus_proxy_method (main_iface, iface, m))))); + } else if (!m.coroutine) { iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m))))); } else { iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m))))); @@ -1629,6 +1645,8 @@ public class Vala.DBusClientModule : DBusModule { void generate_marshalling (Method m, string dbus_iface_name, CCodeFragment prefragment, CCodeFragment postfragment) { CCodeDeclaration cdecl; + var no_reply = is_dbus_no_reply (m); + var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name")); destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*")); var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path")); @@ -1641,15 +1659,24 @@ public class Vala.DBusClientModule : DBusModule { msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m)))); prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall))); + if (no_reply) { + var noreplycall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_set_no_reply")); + noreplycall.add_argument (new CCodeIdentifier ("_message")); + noreplycall.add_argument (new CCodeConstant ("TRUE")); + prefragment.append (new CCodeExpressionStatement (noreplycall)); + } + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); iter_call.add_argument (new CCodeIdentifier ("_message")); iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); prefragment.append (new CCodeExpressionStatement (iter_call)); - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); - iter_call.add_argument (new CCodeIdentifier ("_reply")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); - postfragment.append (new CCodeExpressionStatement (iter_call)); + if (!no_reply) { + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); + iter_call.add_argument (new CCodeIdentifier ("_reply")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + } foreach (FormalParameter param in m.get_parameters ()) { if (param.direction == ParameterDirection.IN) { @@ -1664,6 +1691,10 @@ public class Vala.DBusClientModule : DBusModule { } write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr); } else { + if (no_reply) { + Report.error (param.source_reference, "No-reply DBus methods must not have out parameters"); + break; + } cdecl = new CCodeDeclaration (param.parameter_type.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator ("_" + param.name)); postfragment.append (cdecl); @@ -1697,6 +1728,9 @@ public class Vala.DBusClientModule : DBusModule { } if (!(m.return_type is VoidType)) { + if (no_reply) { + Report.error (m.return_type.source_reference, "No-reply DBus methods must return void"); + } if (m.return_type.is_real_non_null_struct_type ()) { var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target); @@ -1736,6 +1770,10 @@ public class Vala.DBusClientModule : DBusModule { Report.error (m.source_reference, "D-Bus methods must throw DBus.Error"); return; } + if (is_dbus_no_reply (m)) { + // no-reply messages throw no error + return; + } var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error")); @@ -1882,6 +1920,101 @@ public class Vala.DBusClientModule : DBusModule { return proxy_name; } + string generate_noreply_dbus_proxy_method (Interface main_iface, Interface iface, Method m) { + string proxy_name = "%sdbus_proxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name); + + string dbus_iface_name = get_dbus_name (iface); + + CCodeDeclaration cdecl; + + var function = new CCodeFunction (proxy_name); + function.modifiers = CCodeModifiers.STATIC; + + var cparam_map = new HashMap (direct_hash, direct_equal); + + generate_cparameters (m, source_declarations, cparam_map, function); + + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + var postfragment = new CCodeFragment (); + + // throw error and return if proxy is disposed + var dispose_return_block = new CCodeBlock (); + if (m.get_error_types ().size > 0) { + var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error")); + set_error_call.add_argument (new CCodeIdentifier ("error")); + set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR")); + set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_DISCONNECTED")); + set_error_call.add_argument (new CCodeConstant ("\"%s\"")); + set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\"")); + dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call)); + dispose_return_block.add_statement (new CCodeReturnStatement ()); + } + block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block)); + + cdecl = new CCodeDeclaration ("DBusGConnection"); + cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessage"); + cdecl.add_declarator (new CCodeVariableDeclarator ("*_message")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_iter")); + block.add_statement (cdecl); + + block.add_statement (prefragment); + + generate_marshalling (m, dbus_iface_name, prefragment, postfragment); + + var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get")); + gconnection.add_argument (new CCodeIdentifier ("self")); + gconnection.add_argument (new CCodeConstant ("\"connection\"")); + gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection"))); + gconnection.add_argument (new CCodeConstant ("NULL")); + block.add_statement (new CCodeExpressionStatement (gconnection)); + + var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection")); + connection.add_argument (new CCodeIdentifier ("_connection")); + + var oom_return_block = new CCodeBlock (); + if (m.get_error_types ().size > 0) { + var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error")); + set_error_call.add_argument (new CCodeIdentifier ("error")); + set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR")); + set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_NO_MEMORY")); + set_error_call.add_argument (new CCodeConstant ("\"%s\"")); + set_error_call.add_argument (new CCodeConstant ("\"Out of memory\"")); + oom_return_block.add_statement (new CCodeExpressionStatement (set_error_call)); + oom_return_block.add_statement (new CCodeReturnStatement ()); + } + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send")); + ccall.add_argument (connection); + ccall.add_argument (new CCodeIdentifier ("_message")); + ccall.add_argument (new CCodeConstant ("NULL")); + block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccall), oom_return_block)); + + var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref")); + conn_unref.add_argument (new CCodeIdentifier ("_connection")); + block.add_statement (new CCodeExpressionStatement (conn_unref)); + + var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref")); + message_unref.add_argument (new CCodeIdentifier ("_message")); + block.add_statement (new CCodeExpressionStatement (message_unref)); + + check_error_reply (m, block); + + block.add_statement (postfragment); + + source_declarations.add_type_member_declaration (function.copy ()); + function.block = block; + source_type_member_definition.append (function); + + return proxy_name; + } + void generate_client_error_cases (CCodeBlock error_block, List error_types, CCodeExpression dbus_error_name, CCodeExpression result_edomain, CCodeExpression result_ecode) { CCodeStatement if_else_if = null; CCodeIfStatement last_statement = null;