Author: lslezak Date: Tue Jul 15 13:37:47 2008 New Revision: 49096 URL: http://svn.opensuse.org/viewcvs/yast?rev=49096&view=rev Log: - pass YCPValues in STRUCT (bsv) b = nil flag (true -> the value is nil), s = YCP type as a string, v = variant with the raw YCP value This allows to pass nil value and properly pass YCPValues which do not have any DBus equivalent (like YCPPath, YCPSymbol, ...) Modified: branches/tmp/lslezak/workshop/core/libscr/src/SCR.cc branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.cc branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.h branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc Modified: branches/tmp/lslezak/workshop/core/libscr/src/SCR.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/libscr/src/SCR.cc?rev=49096&r1=49095&r2=49096&view=diff ============================================================================== --- branches/tmp/lslezak/workshop/core/libscr/src/SCR.cc (original) +++ branches/tmp/lslezak/workshop/core/libscr/src/SCR.cc Tue Jul 15 13:37:47 2008 @@ -55,6 +55,9 @@ static YCPValue CallDBus(const char *method, const YCPPath &path = YCPNull(), const YCPValue &args = YCPNull (), const YCPValue &opt = YCPNull ()) { + + y2milestone("Calling DBus method %s: path: %s, args: %s, opt: %s", method, path.isNull() ? "NULL" : path->toString().c_str(), args.isNull() ? "NULL" : args->toString().c_str(), opt.isNull() ? "NULL" : opt->toString().c_str()); + DBusMsg msg; // TODO create constants for these strings msg.createCall("org.opensuse.yast.SCR", "/SCR", "org.opensuse.yast.SCR.Methods", method); Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.cc?rev=49096&r1=49095&r2=49096&view=diff ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.cc Tue Jul 15 13:37:47 2008 @@ -215,30 +215,17 @@ DBusMessageIter it; dbus_message_iter_init_append(msg, &it); - // create sub iterator for VARIANT container - DBusMessageIter sub; - - // open container - dbus_message_iter_open_container(&it, DBUS_TYPE_VARIANT, typeStr(val), &sub); - - bool ret = addYCPValue(val, &sub); - // close container - dbus_message_iter_close_container(&it, &sub); + // add the value + bool ret = addYCPValue(val, &it); return ret; } - -bool DBusMsg::addYCPValue(const YCPValue &val, DBusMessageIter *i) +bool DBusMsg::addYCPValueRaw(const YCPValue &val, DBusMessageIter *i) { int type = typeInt(val); - if (val.isNull()) - { - y2warning("Ignoring NULL YCPValue"); - return false; - } - else if (val->isInteger()) + if (val->isInteger()) { dbus_int64_t i64 = val->asInteger()->value(); addValue(type, &i64, i); @@ -255,13 +242,14 @@ } else if (val->isBoolean()) { - bool b = val->asBoolean()->value(); + dbus_bool_t b = val->asBoolean()->value(); addValue(type, &b, i); } // add term, path and symbol as string else if (val->isTerm() || val->isPath() || val->isSymbol()) { - const char * str = val->toString().c_str(); + std::string val_str = val->toString(); + const char *str = val_str.c_str(); // add path as a string addValue(type, &str, i); } @@ -275,65 +263,47 @@ // open array container y2milestone("Opening array container"); - dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, DBUS_TYPE_VARIANT_AS_STRING, &array_it); + dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(bsv)", &array_it); while(index < sz) { - YCPValue item = lst->value(index); - - // open variant container for each item - DBusMessageIter variant_it; - y2milestone("Opening variant container"); - dbus_message_iter_open_container(&array_it, DBUS_TYPE_VARIANT, typeStr(item), &variant_it); - + y2milestone("Adding YCP value at index %d", index); // add an item - addYCPValue(lst->value(index), &variant_it); - - // close variant container - dbus_message_iter_close_container(&array_it, &variant_it); + addYCPValue(lst->value(index), &array_it); index++; } // close array container + y2milestone("Closing array container"); dbus_message_iter_close_container(i, &array_it); } else if (val->isMap()) { YCPMap map = val->asMap(); - // get key type, use string as a fallback for an empty map - std::string key_type((map.size() > 0) ? typeStr(map.begin().key()) : "s"); - DBusMessageIter array_it; // open array container - y2milestone("Opening dict container"); - dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, (std::string(DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING) + - + key_type.c_str() + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING).c_str(), - &array_it); + y2milestone("Opening DICT container"); + dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "{(bsv)(bsv)}", &array_it); - for(YCPMapIterator it = map.begin(); it != map.end() ; ++it) + for(YCPMapIterator mit = map.begin(); mit != map.end() ; ++mit) { - YCPValue key = it.key(); - YCPValue val = it.value(); + YCPValue key = mit.key(); + YCPValue val = mit.value(); DBusMessageIter map_item_it; y2milestone("Opening map item container"); dbus_message_iter_open_container(&array_it, DBUS_TYPE_DICT_ENTRY, 0, &map_item_it); - // add the key - addYCPValue(key, &map_item_it); - + // key of the DBus DICT struct must be a basic type, omit the struct header + // see http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-sig... + addYCPValueRaw(key, &map_item_it); // add the value - DBusMessageIter val_item_it; - // open variant container for value - dbus_message_iter_open_container(&map_item_it, DBUS_TYPE_VARIANT, typeStr(val), &val_item_it); - addYCPValue(val, &val_item_it); - // close variant container - dbus_message_iter_close_container(&map_item_it, &val_item_it); + addYCPValue(val, &map_item_it); - // close dict entry + // close map item dbus_message_iter_close_container(&array_it, &map_item_it); } @@ -344,12 +314,61 @@ { y2error("Unsupported type %s, value: %s", Type::vt2type(val->valuetype())->toString().c_str(), val->toString().c_str()); - return false; + + // TODO add as string? } return true; } +bool DBusMsg::addYCPValue(const YCPValue &val, DBusMessageIter *i) +{ + // create sub iterator for STRUCT container + DBusMessageIter sub; + + y2milestone("Opening STRUCT container"); + // open container + dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub); + + // add nil flag + dbus_bool_t nil_flag = val.isNull() || val->isVoid(); + dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &nil_flag); + + y2milestone("Added nil flag: %s", nil_flag ? "true" : "false"); + + if (nil_flag) + { + // FIXME: can we omit the other values?? + dbus_message_iter_close_container(i, &sub); + return true; + } + + // add variable type + std::string vt(Type::vt2type(val->valuetype())->toString()); + const char *ycp_type = vt.c_str(); + + dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &ycp_type); + y2milestone("Adding variable type %s: %s", ycp_type, val->toString().c_str()); + + y2milestone("Opening VARIANT container with type %s", typeStr(val)); + + // add VARIANT container + DBusMessageIter var_it; + dbus_message_iter_open_container(&sub, DBUS_TYPE_VARIANT, typeStr(val), &var_it); + + // add the raw YCP value + addYCPValueRaw(val, &var_it); + + y2milestone("Closing VARIANT container"); + dbus_message_iter_close_container(&sub, &var_it); + + y2milestone("Closing STRUCT container"); + // close container + dbus_message_iter_close_container(i, &sub); + + return true; +} + int DBusMsg::arguments() const { int ret = 0; @@ -381,12 +400,11 @@ } -YCPValue DBusMsg::getYCPValue(DBusMessageIter *it) +YCPValue DBusMsg::getYCPValueRaw(DBusMessageIter *it, const std::string &ycp_type) { YCPValue ret; int type = dbus_message_iter_get_arg_type(it); - y2milestone("Found DBus type: %d (%c)", type, (char)type); // TODO support more types if (type == DBUS_TYPE_BOOLEAN) @@ -399,66 +417,73 @@ { const char *s; dbus_message_iter_get_basic(it, &s); - ret = YCPString(s); - } - else if (type == DBUS_TYPE_VARIANT) - { - DBusMessageIter sub; - dbus_message_iter_recurse(it, &sub); - // recurse into the variant iterator - return getYCPValue(&sub); + // use ycp_type to return the correct type + if (ycp_type == "symbol") + ret = YCPSymbol(s); + if (ycp_type == "term") + ret = YCPTerm(s); + if (ycp_type == "path") + ret = YCPPath(s); + else + // default is YCPString + ret = YCPString(s); } else if (type == DBUS_TYPE_ARRAY) { - YCPList lst; - YCPMap map; - - bool list_container = true; - DBusMessageIter sub; dbus_message_iter_recurse(it, &sub); - while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) + // DBUS_TYPE_ARRAY is used for YCPList and YCPMap + if (ycp_type == "list") { - // is it a map or a list? - if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY) + y2milestone("Found YCPList container"); + YCPList lst; + + while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) { - DBusMessageIter mapit; - dbus_message_iter_recurse(&sub, &mapit); + YCPValue list_val = getYCPValue(&sub); + lst->add(list_val); - // it's a map - list_container = false; + dbus_message_iter_next(&sub); + } - // read the key - YCPValue key = getYCPValue(&mapit); + ret = lst; + } + else if (ycp_type == "map") + { + y2milestone("Found YCPMap container"); + YCPMap map; + + while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) + { + // is it a map or a list? + if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY) + { + DBusMessageIter mapit; + dbus_message_iter_recurse(&sub, &mapit); - dbus_message_iter_next(&mapit); + // read the key without the header + YCPValue key = getYCPValueRaw(&mapit); - // read the value - YCPValue val = getYCPValue(&mapit); + dbus_message_iter_next(&mapit); - map->add(key, val); - } - else - { - // it's a list - YCPValue item = getYCPValue(&sub); + // read the value + YCPValue val = getYCPValue(&mapit); - if (!item.isNull()) - { - lst->add(item); + map->add(key, val); } + + dbus_message_iter_next(&sub); } - dbus_message_iter_next(&sub); + ret = map; } - - // return the correct result - if (list_container) - return lst; else - return map; + { + y2error("Unknown container type for DBUS_TYPE_ARRAY: %s", ycp_type.c_str()); + ret = YCPVoid(); + } } else if (type == DBUS_TYPE_DOUBLE) { @@ -505,12 +530,85 @@ } else { - y2error("Unsupported Dbus type: %d (%c)", type, (char)type); + y2error("Unsupported DBus type: %d (%c)", type, (char)type); } return ret; } +YCPValue DBusMsg::getYCPValue(DBusMessageIter *it) +{ + YCPValue ret; + + int type = dbus_message_iter_get_arg_type(it); + y2milestone("Found DBus type: %d (%c)", type, (char)type); + + if (type != DBUS_TYPE_STRUCT) + { + y2error("Expecting Struct container in the Dbus message"); + return YCPVoid(); + } + + DBusMessageIter struct_iter; + dbus_message_iter_recurse(it, &struct_iter); + + type = dbus_message_iter_get_arg_type(&struct_iter); + + // read the nil flag at the beginning + if (type == DBUS_TYPE_BOOLEAN) + { + dbus_bool_t b; + dbus_message_iter_get_basic(&struct_iter, &b); + + y2milestone("Nil flag: %s", b ? "true" : "false"); + + if (b) + { + y2milestone("HEADER: Received nil value"); + return YCPVoid(); + } + } + else + { + y2error("Missing nil flag in the response"); + return YCPVoid(); + } + + // read the data type in the header + dbus_message_iter_next(&struct_iter); + + std::string ycp_type; + type = dbus_message_iter_get_arg_type(&struct_iter); + if (type == DBUS_TYPE_STRING) + { + const char *str; + dbus_message_iter_get_basic(&struct_iter, &str); + y2milestone("HEADER: type: %s", str); + ycp_type = str; + } + else + { + y2error("Missing datatype flag in the response"); + return YCPVoid(); + } + + // read the YCP value in the variant container + dbus_message_iter_next(&struct_iter); + + type = dbus_message_iter_get_arg_type(&struct_iter); + + if (type != DBUS_TYPE_VARIANT) + { + y2error("Expecting VARIANT type in the response"); + return YCPVoid(); + } + + DBusMessageIter variant_iter; + dbus_message_iter_recurse(&struct_iter, &variant_iter); + + return getYCPValueRaw(&variant_iter, ycp_type); +} + YCPValue DBusMsg::getYCPValue(int index) { YCPValue ret = YCPNull(); @@ -610,8 +708,7 @@ } else if (val->isList()) { - return DBUS_TYPE_ARRAY_AS_STRING\ - DBUS_TYPE_VARIANT_AS_STRING; + return "a(bsv)"; } else if (val->isMap()) { @@ -620,8 +717,10 @@ // get key type, use string as a fallback for an empty map std::string key_type((map.size() > 0) ? typeStr(map.begin().key()) : "s"); + // key of the DBus DICT struct must be a basic type + // see http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-sig... return (std::string(DBUS_TYPE_ARRAY_AS_STRING) + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + - + key_type.c_str() + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING).c_str(); + + key_type.c_str() + "(bsv)" + DBUS_DICT_ENTRY_END_CHAR_AS_STRING).c_str(); } y2error("Unsupported type %s, value: %s", Type::vt2type(val->valuetype())->toString().c_str(), Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.h URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.h?rev=49096&r1=49095&r2=49096&view=diff ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.h (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusMsg.h Tue Jul 15 13:37:47 2008 @@ -63,6 +63,7 @@ bool addValue(int type, void* data); bool addValue(int type, void* data, DBusMessageIter *i); bool addYCPValue(const YCPValue &val, DBusMessageIter *i); + bool addYCPValueRaw(const YCPValue &val, DBusMessageIter *i); void release(); DBusMessage *msg; @@ -70,6 +71,7 @@ const char * typeStr(const YCPValue &val) const; YCPValue getYCPValue(DBusMessageIter *it); + YCPValue getYCPValueRaw(DBusMessageIter *it, const std::string &ycp_type = std::string()); }; #endif Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc?rev=49096&r1=49095&r2=49096&view=diff ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc Tue Jul 15 13:37:47 2008 @@ -78,10 +78,12 @@ { YCPValue arg0 = request.getYCPValue(0); - if (!arg0.isNull() && arg0->isString()) + if (!arg0.isNull() && arg0->isPath()) { + YCPPath pth = arg0->asPath(); + // DBus doesn't support YCPPath type, string is used as a workaround - std::string path_str(arg0->asString()->value()); + std::string path_str(pth->toString()); if (path_str.empty()) { @@ -98,6 +100,8 @@ { YCPValue arg = request.getYCPValue(1); YCPValue opt = request.getYCPValue(2); + +#ifdef HAVE_POLKIT std::string caller(request.sender()), arg_str, opt_str; if (!arg.isNull()) @@ -110,7 +114,6 @@ opt_str = opt->toString(); } -#ifdef HAVE_POLKIT // PolicyKit check if (!isActionAllowed(caller, path_str, method, arg_str, opt_str)) { @@ -120,7 +123,6 @@ else #endif { - YCPPath pth(path_str); YCPValue ret; if (method == "Read") @@ -164,7 +166,7 @@ } else { - reply.createError(request, "First argument must be a string", DBUS_ERROR_INVALID_ARGS); + reply.createError(request, "First argument must be a path", DBUS_ERROR_INVALID_ARGS); } } } @@ -190,49 +192,49 @@ "<node>" " <interface name='org.opensuse.yast.SCR.Methods'>" " <method name='Read'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='arg' type='v' direction='in'/>" -" <arg name='opt' type='v' direction='in'/>" -" <arg name='ret' type='v' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='arg' type='(bsv)' direction='in'/>" +" <arg name='opt' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='Write'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='arg' type='v' direction='in'/>" -" <arg name='opt' type='v' direction='in'/>" -" <arg name='ret' type='v' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='arg' type='(bsv)' direction='in'/>" +" <arg name='opt' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='Execute'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='arg' type='v' direction='in'/>" -" <arg name='opt' type='v' direction='in'/>" -" <arg name='ret' type='v' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='arg' type='(bsv)' direction='in'/>" +" <arg name='opt' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='Dir'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='ret' type='av' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='Error'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='ret' type='av' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='UnregisterAgent'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='ret' type='b' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='UnregisterAllAgents'>" -" <arg name='ret' type='b' direction='out'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='RegisterNewAgents'>" -" <arg name='ret' type='b' direction='out'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='RegisterAgent'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='arg' type='v' direction='in'/>" -" <arg name='ret' type='b' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='arg' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <method name='UnmountAgent'>" -" <arg name='path' type='s' direction='in'/>" -" <arg name='ret' type='b' direction='out'/>" +" <arg name='path' type='(bsv)' direction='in'/>" +" <arg name='ret' type='(bsv)' direction='out'/>" " </method>" " <interface name='org.freedesktop.DBus.Introspectable'>" " <method name='Introspect'>" -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org