WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2004-2006 Net Integration Technologies, Inc. 00004 * 00005 * Wrapper code for marshalling/demarshalling WvDBusMsg objects. This is 00006 * in a separate file from WvDBusMsg in case you want to use a WvDBusMsg 00007 * but not our special/gross marshalling code from wvdbusmarshal_c.c. 00008 * 00009 */ 00010 #include "wvdbusmsg.h" 00011 #undef interface // windows 00012 #include <dbus/dbus.h> 00013 00014 00015 static int wvdbus_message_length(const char *buf, size_t len) 00016 { 00017 int msglen = dbus_message_demarshal_bytes_needed(buf, len); 00018 if (msglen > 0) 00019 return msglen; 00020 else if (msglen == 0) 00021 return DBUS_MINIMUM_HEADER_SIZE; 00022 00023 return 0; 00024 } 00025 00026 00027 WvDBusMsg *WvDBusMsg::demarshal(WvBuf &buf) 00028 { 00029 // to make sure bytes are aligned (as required by d-bus), copy them into a 00030 // new buffer (not very efficient, but what can you do without reworking 00031 // our buffer implementation) 00032 WvDynBuf alignedbuf; 00033 size_t buflen = buf.used(); 00034 alignedbuf.put(buf.peek(0, buflen), buflen); 00035 00036 // first get size of message to demarshal. if too little or bad length, 00037 // return NULL (possibly after consuming the bad data) 00038 size_t messagelen = wvdbus_message_length((const char *) 00039 alignedbuf.peek(0, buflen), 00040 buflen); 00041 if (messagelen == 0) // invalid message data 00042 { 00043 buf.get(buflen); // clear invalid crap - the best we can do 00044 return NULL; 00045 } 00046 else if (messagelen > buflen) // not enough data 00047 return NULL; 00048 00049 // Assuming that worked and we can demarshal a message, try to do so 00050 DBusError error; 00051 dbus_error_init(&error); 00052 DBusMessage *_msg = dbus_message_demarshal((const char *) 00053 alignedbuf.peek(0, buflen), 00054 messagelen, &error); 00055 if (dbus_error_is_set(&error)) 00056 dbus_error_free (&error); 00057 buf.get(messagelen); 00058 00059 if (_msg) 00060 { 00061 WvDBusMsg *msg = new WvDBusMsg(_msg); 00062 dbus_message_unref(_msg); 00063 return msg; 00064 } 00065 else 00066 return NULL; 00067 } 00068 00069 00070 size_t WvDBusMsg::demarshal_bytes_needed(WvBuf &buf) 00071 { 00072 // to make sure bytes are aligned (as required by d-bus), copy them into a 00073 // new buffer (not very efficient, but what can you do without reworking 00074 // our buffer implementation) 00075 WvDynBuf alignedbuf; 00076 size_t used = buf.used(); 00077 alignedbuf.put(buf.peek(0, used), used); 00078 00079 return wvdbus_message_length((const char *)alignedbuf.peek(0, used), used); 00080 } 00081 00082 00083 void WvDBusMsg::marshal(WvBuf &buf) 00084 { 00085 DBusMessage *msg = *this; 00086 00087 static uint32_t global_serial = 1000; 00088 if (!dbus_message_get_serial(msg)) 00089 { 00090 dbus_message_set_serial(msg, ++global_serial); 00091 } 00092 00093 dbus_message_lock (msg); 00094 char *cbuf; 00095 int len; 00096 dbus_message_marshal(msg, &cbuf, &len); 00097 buf.put(cbuf, len); 00098 free(cbuf); 00099 }