WvStreams
wvdbusmarshal.cc
1/* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004-2006 Net Integration Technologies, Inc.
4 *
5 * Wrapper code for marshalling/demarshalling WvDBusMsg objects. This is
6 * in a separate file from WvDBusMsg in case you want to use a WvDBusMsg
7 * but not our special/gross marshalling code from wvdbusmarshal_c.c.
8 *
9 */
10#include "wvdbusmsg.h"
11#undef interface // windows
12#include <dbus/dbus.h>
13
14
15static int wvdbus_message_length(const char *buf, size_t len)
16{
17 int msglen = dbus_message_demarshal_bytes_needed(buf, len);
18 if (msglen > 0)
19 return msglen;
20 else if (msglen == 0)
21 return DBUS_MINIMUM_HEADER_SIZE;
22
23 return 0;
24}
25
26
28{
29 // to make sure bytes are aligned (as required by d-bus), copy them into a
30 // new buffer (not very efficient, but what can you do without reworking
31 // our buffer implementation)
32 WvDynBuf alignedbuf;
33 size_t buflen = buf.used();
34 alignedbuf.put(buf.peek(0, buflen), buflen);
35
36 // first get size of message to demarshal. if too little or bad length,
37 // return NULL (possibly after consuming the bad data)
38 size_t messagelen = wvdbus_message_length((const char *)
39 alignedbuf.peek(0, buflen),
40 buflen);
41 if (messagelen == 0) // invalid message data
42 {
43 buf.get(buflen); // clear invalid crap - the best we can do
44 return NULL;
45 }
46 else if (messagelen > buflen) // not enough data
47 return NULL;
48
49 // Assuming that worked and we can demarshal a message, try to do so
50 DBusError error;
51 dbus_error_init(&error);
52 DBusMessage *_msg = dbus_message_demarshal((const char *)
53 alignedbuf.peek(0, buflen),
54 messagelen, &error);
55 if (dbus_error_is_set(&error))
56 dbus_error_free (&error);
57 buf.get(messagelen);
58
59 if (_msg)
60 {
61 WvDBusMsg *msg = new WvDBusMsg(_msg);
62 dbus_message_unref(_msg);
63 return msg;
64 }
65 else
66 return NULL;
67}
68
69
71{
72 // to make sure bytes are aligned (as required by d-bus), copy them into a
73 // new buffer (not very efficient, but what can you do without reworking
74 // our buffer implementation)
75 WvDynBuf alignedbuf;
76 size_t used = buf.used();
77 alignedbuf.put(buf.peek(0, used), used);
78
79 return wvdbus_message_length((const char *)alignedbuf.peek(0, used), used);
80}
81
82
83void WvDBusMsg::marshal(WvBuf &buf)
84{
85 DBusMessage *msg = *this;
86
87 static uint32_t global_serial = 1000;
88 if (!dbus_message_get_serial(msg))
89 {
90 dbus_message_set_serial(msg, ++global_serial);
91 }
92
93 dbus_message_lock (msg);
94 char *cbuf;
95 int len;
96 dbus_message_marshal(msg, &cbuf, &len);
97 buf.put(cbuf, len);
98 free(cbuf);
99}
void put(const T *data, size_t count)
Writes the specified number of elements from the specified storage location into the buffer at its ta...
const T * peek(int offset, size_t count)
Returns a const pointer into the buffer at the specified offset to the specified number of elements w...
size_t used() const
Returns the number of elements in the buffer currently available for reading.
static WvDBusMsg * demarshal(WvBuf &buf)
Demarshals a new WvDBusMsg from a buffer containing its binary DBus protocol representation.
static size_t demarshal_bytes_needed(WvBuf &buf)
Given a buffer containing what might be the header of a DBus message, checks how many bytes need to b...
void marshal(WvBuf &buf)
Locks this message, encodes it in DBus binary protocol format, and adds it to the given buffer.