Rabbitmq-c Library: How to get 'method' returned by the broker - c

I'm using the rabbitmq-c library to connect to a RabbitMQ server (GNU/Linux build environment).
At one point when I use "amqp_channel_open(...)", I'm getting an error from the server which I want to debug.
I call "amqp_get_rpc_reply(...)" as per the examples. It returns an amqp_rpc_reply_t which I assign to a variable "my_reply".
my_reply.reply_type is AMQP_RESPONSE_SERVER_EXCEPTION, which is why I think it's an error from the server.
HOWEVER, here are the docs for the amqp_rpc_reply_t type.
For my_reply.reply: "in case of AMQP_RESPONSE_SERVER_EXCEPTION this field will be set to the method returned from the broker"
So my_reply.reply is an amqp_method_t in this case. But when I look at the docs for amqp_method_t, it has two fields: id ("the method id number", ??) and decoded.
For decoded, it's a void *:
"pointer to the decoded method, cast to the appropriate type to use"
I am stuck at this point, because I have no idea what to cast **decoded* to. It should be some kind of data structure containing the information returned by the server (the AMQP method), but I can't find any reference to what type I should cast it to.
[Edited for clarity]

I dug around a bit in the examples, and found something helpful.
When my_reply.reply_type is AMQP_RESPONSE_SERVER_EXCEPTION, the field my_reply.reply.id contains one of the AMQP_xxxxxx_METHOD constants which are defined by macros in amqp_framing.h - see here and scroll down a bit.
Each of these method IDs has an associated type which follows the same naming convention - e.g. for AMQP_CONNECTION_CLOSE_METHOD (which I was getting) there is amqp_connection_close_t. See here for a list of data structures / types.
Knowing which type to cast my_reply.reply.decoded to, it's pretty easy to then extract the useful information - e.g. (from examples, assuming my_reply.reply.id is AMQP_CONNECTION_CLOSE_METHOD):
amqp_connection_close_t *m = (amqp_connection_close_t *)my_reply.reply.decoded;
printf( "Server connection error %d, message: %.*s\n",
m->reply_code,
(int) m->reply_text.len,
(char *) m->reply_text.bytes);

Related

When writing a Lua-facing function in C, what's a good way to check if an argument supports table-like lookups?

Here's a potential pattern that can check if an argument is a table:
int my_fn(lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
// .. do stuff with the table ..
}
This works whenever the first argument is a table. However, other Lua types support table lookups, such as a userdata, and in luajit, a cdata.
Is there a nice way to check if a table lookup, such as via lua_getfield, will succeed before I call it? I mean without restricting the type to tables. Relatedly, are tables, userdata, and cdata the only types in luajit that support indexed lookups?
I'm most interested in answers restricted to the Lua 5.1 C API because I'm using LuaJIT which currently works with this version.
Clarification
The advantage of the luaL_checkXXX functions is that, in one line, they:
throw an informative, user-friendly error message if the type is wrong, and
provide a C-friendly return value that can be used immediately.
I'm looking for something similar for tables. I don't expect a C-friendly hash-table return value, but I do want the same quality of error message to the user if the argument in question is not indexable.
I'm embracing the philosophy of duck typing. If I write a function that simply wants to index some keys from an argument, then I don't care if that argument is truly a table, or just a userdata that supports __index lookups. I want to accept either one.
In general, just tables have lookups because it's the only type which defines this property. Userdata are opaque, just the host knows what to do with it or adds a metatable (which can be analyzed) for specific behaviour. CData are part of Lua compiling with LuaJIT, i never used this type with C API (is it even supported?). At the end you have to check the type/metatable for possible lookups and request a field to check for setting, there's no way around lua_getfield (but raw access should be faster, see lua_rawget). The exception would be to check for table array length by lua_objlen.
Furthermore a cheaper solution for type checking would be lua_is*** functions.
Here's one way to do it:
// If the value at index narg is not indexable, this function does not return and
// provides a user-friendly error message; otherwise the stack is unchanged.
static void luaL_checkindexable(lua_State *L, int narg) {
if (lua_istable(L, narg)) return; // tables are indexable.
if (!luaL_getmetafield(L, narg, "__index")) {
// This function will show the user narg and the Lua-visible function name.
luaL_argerror(L, narg, "expected an indexable value such as a table");
}
lua_pop(L, 1); // Pop the value of getmetable(narg).__index.
}
This works for tables and any value with an __index value on its metatable.
It provides a standard-format error given by luaL_argerror. Here's an example error message:
a_file.lua:7: bad argument #1 to 'fn' (expected an indexable value such as a table)
You can use it like this:
// This Lua-facing function expects an indexable 1st argument.
int my_fn(lua_State *L) {
luaL_checkindexable(L, 1);
lua_getfield(L, 1, "key"); // --> arg1.key or nil is now on top of stack.
// .. your fn ..
}

D-Bus how to create and send a Dict?

I have a process which exposes a method to DBus with one of the arguments taking the following type signature a{sv}:
Dict of {String, Variant}
The libDBus documentation for dbus_message_append_args fails to provide adequate reference for this. Some information appears in the specification under container-types, specifically:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
On attempting to append a dict I receive the following error message:
type dict_entry isn't supported yet in dbus_message_append_args_valist
Although I'm actually using dbus_message_append_args(I guess the error message is somewhat off).
There are two other alternatives to dbus_message_append_args() using either:
dbus_message_iter_append_basic()
and
dbus_message_iter_append_fixed_array()
While I can create an empty Dict container with the following:
const char * container_d_sig = "{sv}";
DBusMessageIter iter, sub;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
dbus_message_iter_close_container(&iter, &sub);
Neither of the append methods appear to support adding a struct. Not sure what to try here...
First, about D-Bus libraries: you talk about dbus-glib in several places but the functions you refer to are not part of dbus-glib but libdbus. If you are still trying to find the best way to use D-Bus, I suggest you forget both of these: libdbus is very low-level (it's documentation even starts with "If you use this low-level API directly, you're signing up for some pain") and dbus-glib is deprecated. The best D-Bus API currently is GDBus which is part of GLib GIO: it's a far better designed API than either of the other two, well tested and supported.
Now, as for the actual question, documentation for dbus_message_append_args() does say it quite clearly:
To append variable-length basic types, or any more complex value, you
have to use an iterator rather than this function.
In other words you should use dbus_message_iter_open_container() to prepare the iterator until it is pointing to somewhere where you can use dbus_message_iter_append_basic(). Note that in your example the dictionary is a container, the dictionary entry is a container and the variant is a container... In other words it gets pretty complex quite fast. If you really want to do it, look at e.g. Connman code for examples.
As I mentioned, the sane route is GDBus. There creating even much more complex signatures is pretty easy as you can use the GVariantBuilder API:
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
/* Now use the builder results with g_dbus_connection_call()
or g_dbus_proxy_call() */
I know this question was asked awhile ago, but I had a very similar question recently, and after several hours of trial and error this is some code I came up with that works for me. Hopefully it helps someone else...
DBusMessage* testMessage()
{
DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
DBusMessageIter iter, aIter;
dbus_message_iter_init_append(mssg, &iter);
if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
return nullptr;
DBusMessageIter eIter;
if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
const char* key = "test key";
dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
DBusMessageIter vIter;
if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
dbus_int32_t val = 42;
dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
dbus_message_iter_close_container(&eIter, &vIter);
dbus_message_iter_close_container(&aIter, &eIter);
dbus_message_iter_close_container(&iter, &aIter);
return mssg;
}
This is C++ but should be pretty easy to adapt for C. The returned message has a signature of a{sv}. The dbus docs are helpful-ish.

ldap_init and ldap_set_option questions

I got some questions below using some wldap32.lib functions.
Code
#include "winldap.h"
LDAP Connect;
Connect = *(ldap_init(...));
1) Is it legal ? Seems so, coz my structure is equial to structure I got using this code
LDAP *pConnect;
Connect = ldap_init(...);
2)so next
ldap_set_option(&Connect, LDAP_OPT_PROTOCOL_VERSION, (void*)&version));
returns 89 code.
but using
ldap_set_option(pConnect, LDAP_OPT_PROTOCOL_VERSION, (void*)&version));
Succesed
For (1), it's valid C, it's just not valid for use with the API.
The LDAP structure exposed in the winldap.h is just the user observable elements of the LDAP structure. The library is perfectly entitled to return a pointer to a structure that is significantly larger than the one that's exposed to the user. As a result when you perform the struct assignment only the elements that you know about would get copied, and the rest of this memory would be lost.
So when you attempt to use this, now truncated, copy of the structure you get the 89 error code.
In addition, you would have no way of knowing if the ldap_init function failed - when it fails it returns a NULL pointer and your program would just die in that case

AD returns Objectsid as String and SecurityIdentifier is failing interprete this

Usually AD returns 'Objectsid' as a byte[]. So I type cast the value returned by AD in to byte[]. This procedure worked against several AD but not in one case. In this AD environment, I get following exception.
Exception: Unable to cast object of type 'System.String' to type 'System.Byte[]'. (System.InvalidCastException)
To debug this I started checking data-type of the value returned by AD, and it was system.string not byte[]. I printed this string and it was garbage. Then I passed this string to SecurityIdentifier() and I got exception again.
Exception: Value was invalid. Parameter name: sddlForm (System.ArgumentException)
Code:
//Using System.DirectoryServices.Protocols objects
object s = objSrEc[k1].Attributes[(string)obj3.Current][0];
string x = s.GetType().FullName;
if (x.ToLower() == "system.byte[]")
{
byte[] bSID = ((byte[])s);
if (bSID != null)
{
SecurityIdentifier SID = new SecurityIdentifier(bSID, 0);
String ObjectSID = SID.Value;
}
}
else if (x.ToLower() == "system.string")
{
SecurityIdentifier SID = new SecurityIdentifier((String)s); //ssdl excception
String ObjectSID = SID.Value;
}
This is the first time I am seeing AD return string data for ObjectSID. I have run my code against many AD servers. I am planning to check the data-type of ObjectSID in AD schema.
Do any one come across this behavior? Should I call the Win32 api ConvertByteToStringSid()?
Thanks
Ramesh
Sorry for reviving a graveyard post, but I had the same issue a year or so ago, managed to find out why and I figured I'd at least share the reason behind this behavior.
When using the System.DirectoryServices.Protocols namespace, all attribute values should be either a) a byte array, or b) a UTF-8 string. Thing is, the developers at Microsoft figured that they should help people by returning a string when the byte array returned from the underlying LDAP API can be formatted as one, and the byte array itself when the UTF-8 conversion fails. However, this is only true for the indexer of the DirectoryAttribute class, and not for the iterator (which always returns the byte array) or the GetValues method.
The safest way to always get a byte array when you want the SID is, as previously mentioned by others, the GetValues method.
I came through the same. Found this behavior normal when deal with ForeignSecurityPrincipals, however recently found this when translate attributes of built-in groups from some old Win 2K3 domains.
I don't like this as can't just ask the result attribute to tell me via GetType() what type are you and what should I do with you ( GetValues(Attribute.GetType()) ). One of the solutions was reading all attributes definition from AD schema, but this part might be a bit heavy (depends what you're looking for) although it was only a small part of overall AD processing the solution was performing.
Cheers,
Greg

How to retrieve field name in case of unmarshalling error in CXF?

Precondition: service based on CXF receives request/response with data, which violates XSD restriction.
Actual behavior:
In this case CXF returns fault with message like:
cvc-maxLength-valid: Value 'string_length_violated_value' with length = '28' is not facet-valid with respect to maxLength '13' for type 'XSDStringTypeWithLengthRestriction'
Goal:
return fault to consumer with name of field which contains invalid data. F.e. something like this:
Response from provider contains invalid data. Value 'string_length_violated_value' of field 'field_name' is not facet-valid with respect to maxLength '13'.
I'm wondering if it is possible and if so, then how to determine (where to retrieve from) this field name?
I'm not sure if this will completely work, but you can give it a try:
You can create a JAXB ValidationEventHandler and register that on your endpoint.
The ValidationEvent that it gets has the basic string (that you see above) and other information. I would put a breakpoint in there and dig into the event to see if ANY additional and useful information is available.

Resources