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 
15 static 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 
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 }