WvStreams
wvdbusmarshal_c.c
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2004-2006 Net Integration Technologies, Inc.
00004  *
00005  * Ugly routines that call directly into DBus internals for marshalling and
00006  * demarshalling DBusMessage objects into data buffers.
00007  * 
00008  * We separate this into a separate file mostly so we don't mix DBus
00009  * internal header files with other WvStreams header files.
00010  */ 
00011 #include <inttypes.h>
00012 #define DBUS_COMPILATION
00013 //#undef PACKAGE_BUGREPORT
00014 //#undef PACKAGE_NAME
00015 //#undef PACKAGE_STRING
00016 //#undef PACKAGE_TARNAME
00017 //#undef PACKAGE_VERSION
00018 #undef interface
00019 #include <dbus/dbus.h>
00020 #include <dbus-upstream/dbus/dbus-marshal-header.h>
00021 #include <dbus-upstream/dbus/dbus-internals.h>
00022 #include <dbus-upstream/dbus/dbus-string.h>
00023 #include <dbus-upstream/dbus/dbus-message-private.h>
00024 
00025 int wvdbus_marshal(DBusMessage *msg, char **cbuf, size_t *len)
00026 {
00027     static uint32_t global_serial = 1000;
00028     DBusString tmp;
00029     
00030     if (!_dbus_string_init (&tmp))
00031         return 0;
00032     
00033     if (!dbus_message_get_serial(msg))
00034         _dbus_message_set_serial(msg, ++global_serial);
00035     
00036     _dbus_message_lock(msg);
00037     _dbus_string_copy(&msg->header.data, 0, &tmp, 0);
00038     *len = _dbus_string_get_length(&tmp);
00039     _dbus_string_copy(&msg->body, 0, &tmp, *len);
00040     *len = _dbus_string_get_length(&tmp);
00041     
00042     _dbus_string_steal_data(&tmp, cbuf);
00043     _dbus_string_free(&tmp);
00044     return 1;
00045 }
00046 
00047 
00048 size_t wvdbus_message_length(const void *buf, size_t len)
00049 {
00050     if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
00051         return DBUS_MINIMUM_HEADER_SIZE;
00052     
00053     // doesn't copy - no need to free
00054     DBusString buftmp;
00055     _dbus_string_init_const_len(&buftmp, (const char *)buf, len);
00056     
00057     int byte_order, fields_array_len, header_len, body_len;
00058     DBusValidity validity = DBUS_VALID;
00059     int have_message
00060         = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
00061                                               &validity, &byte_order,
00062                                               &fields_array_len,
00063                                               &header_len,
00064                                               &body_len,
00065                                               &buftmp, 0,
00066                                               len);
00067     if (have_message || validity == DBUS_VALID)
00068         return header_len + body_len;
00069     else
00070         return 0; // broken!
00071 }
00072 
00073 
00074 DBusMessage *wvdbus_demarshal(const void *buf, size_t len, size_t *used)
00075 {
00076     DBusMessageLoader *loader;
00077     DBusString *lbuf;
00078     DBusMessage *msg;
00079     
00080     if (!buf)
00081     {
00082         *used = 0;
00083         return NULL;
00084     }
00085     
00086     size_t real_len = wvdbus_message_length(buf, len);
00087     if (real_len == 0) // invalid message data
00088     {
00089         *used = len; // clear invalid crap - the best we can do
00090         return NULL;
00091     }
00092     else if (real_len > len) // not enough data
00093     {
00094         *used = 0;
00095         return NULL;
00096     }
00097     
00098     loader = _dbus_message_loader_new();
00099     if (!loader)
00100         return NULL;
00101     
00102     _dbus_message_loader_get_buffer(loader, &lbuf);
00103     _dbus_string_append_len(lbuf, (const char *)buf, real_len);
00104     _dbus_message_loader_return_buffer(loader, lbuf, real_len);
00105     
00106     if (!_dbus_message_loader_queue_messages(loader))
00107         goto fail;
00108     
00109     if (_dbus_message_loader_get_is_corrupted(loader))
00110         goto fail;
00111     
00112     msg = _dbus_message_loader_pop_message(loader);
00113     if (!msg)
00114         goto fail;
00115     
00116     _dbus_message_loader_unref(loader);
00117     *used = real_len;
00118     return msg;
00119     
00120 fail:
00121     _dbus_message_loader_unref(loader);
00122     *used = real_len ? real_len : len;
00123     return NULL;
00124 }