* dbus/dbus-sysdeps.c: Make tcp socket connection error somewhat more
[platform/upstream/dbus.git] / qt / qdbusmessage.cpp
1 /* qdbusmessage.cpp
2  *
3  * Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
4  * Copyright (C) 2006 Trolltech AS. All rights reserved.
5  *    Author: Thiago Macieira <thiago.macieira@trolltech.com>
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "qdbusmessage.h"
26
27 #include <qdebug.h>
28 #include <qstringlist.h>
29
30 #include <dbus/dbus.h>
31
32 #include "qdbuserror.h"
33 #include "qdbusmarshall_p.h"
34 #include "qdbusmessage_p.h"
35 #include "qdbustypehelper_p.h"
36
37 QDBusMessagePrivate::QDBusMessagePrivate()
38     : connection(QString()), msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
39       timeout(-1), ref(1), repliedTo(false)
40 {
41 }
42
43 QDBusMessagePrivate::~QDBusMessagePrivate()
44 {
45     if (msg)
46         dbus_message_unref(msg);
47     if (reply)
48         dbus_message_unref(reply);
49 }
50
51 ///////////////
52 /*!
53     \class QDBusMessage
54     \brief Represents one message sent or received over the DBus bus.
55
56     This object can represent any of four different types of messages possible on the bus
57     (see MessageType)
58     \list
59       \o Method calls
60       \o Method return values
61       \o Signal emissions
62       \o Error codes
63     \endlist
64
65     Objects of this type are created with the four static functions signal, methodCall,
66     methodReply and error.
67 */
68
69 /*!
70     \enum QDBusMessage::MessageType
71     The possible message types:
72
73     \value MethodCallMessage    a message representing an outgoing or incoming method call
74     \value SignalMessage        a message representing an outgoing or incoming signal emission
75     \value ReplyMessage         a message representing the return values of a method call
76     \value ErrorMessage         a message representing an error condition in response to a method call
77     \value InvalidMessage       an invalid message: this is never set on messages received from D-Bus
78 */
79
80 /*!
81     Constructs a new DBus message representing a signal emission. A DBus signal is emitted
82     from one application and is received by all applications that are listening for that signal
83     from that interface.
84
85     The signal will be constructed to represent a signal coming from the path \a path, interface \a
86     interface and signal name \a name.
87
88     The QDBusMessage object that is returned can be sent with QDBusConnection::send().
89 */
90 QDBusMessage QDBusMessage::signal(const QString &path, const QString &interface,
91                                   const QString &name)
92 {
93     QDBusMessage message;
94     message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
95     message.d_ptr->path = path;
96     message.d_ptr->interface = interface;
97     message.d_ptr->name = name;
98
99     return message;
100 }
101
102 /*!
103     Constructs a new DBus message representing a method call. A method call always informs
104     its destination address (\a service, \a path, \a interface and \a method).
105
106     The DBus bus allows calling a method on a given remote object without specifying the
107     destination interface, if the method name is unique. However, if two interfaces on the
108     remote object export the same method name, the result is undefined (one of the two may be
109     called or an error may be returned).
110
111     When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
112     optional.
113
114     The QDBusObject and QDBusInterface classes provide a simpler abstraction to synchronous
115     method calling.
116
117     This function returns a QDBusMessage object that can be sent with QDBusConnection::send(),
118     QDBusConnection::sendWithReply(), or QDBusConnection::sendWithReplyAsync().
119 */
120 QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &path,
121                                       const QString &interface, const QString &method)
122 {
123     QDBusMessage message;
124     message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
125     message.d_ptr->service = service;
126     message.d_ptr->path = path;
127     message.d_ptr->interface = interface;
128     message.d_ptr->name = method;
129
130     return message;
131 }
132
133 /*!
134     Constructs a new DBus message representing the return values from a called method. The \a other
135     variable represents the method call that the reply will be for.
136     
137     This function returns a QDBusMessage object that can be sent with QDBusConnection::send().
138 */
139 QDBusMessage QDBusMessage::methodReply(const QDBusMessage &other)
140 {
141     Q_ASSERT(other.d_ptr->msg);
142
143     QDBusMessage message;
144     message.d_ptr->connection = other.d_ptr->connection;
145     message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
146     message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
147     other.d_ptr->repliedTo = true;
148
149     return message;
150 }
151
152 /*!
153     Constructs a DBus message representing an error condition described by the \a name
154     parameter. The \a msg parameter is optional and may contain a human-readable description of the
155     error. The \a other variable represents the method call that this error relates to.
156
157     This function returns a QDBusMessage object that can be sent with QDBusMessage::send().
158 */
159 QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QString &name,
160                                  const QString &msg)
161 {
162     Q_ASSERT(other.d_ptr->msg);
163
164     QDBusMessage message;
165     message.d_ptr->connection = other.d_ptr->connection;
166     message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
167     message.d_ptr->name = name;
168     message.d_ptr->message = msg;
169     message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
170     other.d_ptr->repliedTo = true;
171
172     return message;
173 }
174
175 /*!
176     \overload
177     Constructs a DBus message representing an error, where \a other is the method call that
178     generated this error and \a error is the error code.
179 */
180 QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QDBusError &error)
181 {
182     Q_ASSERT(other.d_ptr->msg);
183
184     QDBusMessage message;
185     message.d_ptr->connection = other.d_ptr->connection;
186     message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
187     message.d_ptr->name = error.name();
188     message.d_ptr->message = error.message();
189     message.d_ptr->reply = dbus_message_ref(other.d_ptr->msg);
190     other.d_ptr->repliedTo = true;
191
192     return message;
193 }
194
195 /*!
196     Constructs an empty, invalid QDBusMessage object.
197
198     \sa methodCall(), methodReply(), signal(), error()
199 */
200 QDBusMessage::QDBusMessage()
201 {
202     d_ptr = new QDBusMessagePrivate;
203 }
204
205 /*!
206     Constructs a copy of the object given by \a other.
207 */
208 QDBusMessage::QDBusMessage(const QDBusMessage &other)
209     : QList<QVariant>(other)
210 {
211     d_ptr = other.d_ptr;
212     d_ptr->ref.ref();
213 }
214
215 /*!
216     Disposes of the object and frees any resources that were being held.
217 */
218 QDBusMessage::~QDBusMessage()
219 {
220     if (!d_ptr->ref.deref())
221         delete d_ptr;
222 }
223
224 /*!
225     Copies the contents of the object given by \a other.
226 */
227 QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
228 {
229     QList<QVariant>::operator=(other);
230     qAtomicAssign(d_ptr, other.d_ptr);
231     return *this;
232 }
233
234 static inline const char *data(const QByteArray &arr)
235 {
236     return arr.isEmpty() ? 0 : arr.constData();
237 }
238
239 /*!
240     \internal
241     Constructs a DBusMessage object from this object. The returned value must be de-referenced
242     with dbus_message_unref.
243 */
244 DBusMessage *QDBusMessage::toDBusMessage() const
245 {
246     DBusMessage *msg = 0;
247     
248     switch (d_ptr->type) {
249     case DBUS_MESSAGE_TYPE_METHOD_CALL:
250         msg = dbus_message_new_method_call(data(d_ptr->service.toUtf8()), data(d_ptr->path.toUtf8()),
251                                            data(d_ptr->interface.toUtf8()), data(d_ptr->name.toUtf8()));
252         break;
253     case DBUS_MESSAGE_TYPE_SIGNAL:
254         msg = dbus_message_new_signal(data(d_ptr->path.toUtf8()), data(d_ptr->interface.toUtf8()),
255                                       data(d_ptr->name.toUtf8()));
256         break;
257     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
258         msg = dbus_message_new_method_return(d_ptr->reply);
259         break;
260     case DBUS_MESSAGE_TYPE_ERROR:
261         msg = dbus_message_new_error(d_ptr->reply, data(d_ptr->name.toUtf8()), data(d_ptr->message.toUtf8()));
262         break;
263     }
264     if (!msg)
265         return 0;
266
267     QDBusMarshall::listToMessage(*this, msg, d_ptr->signature);
268     return msg;
269 }
270
271 /*!
272     \internal
273     Constructs a QDBusMessage by parsing the given DBusMessage object.
274 */
275 QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg, const QDBusConnection &connection)
276 {
277     QDBusMessage message;
278     if (!dmsg)
279         return message;
280
281     message.d_ptr->connection = connection;
282     message.d_ptr->type = dbus_message_get_type(dmsg);
283     message.d_ptr->path = QString::fromUtf8(dbus_message_get_path(dmsg));
284     message.d_ptr->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
285     message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
286                       QString::fromUtf8(dbus_message_get_error_name(dmsg)) :
287                       QString::fromUtf8(dbus_message_get_member(dmsg));
288     message.d_ptr->service = QString::fromUtf8(dbus_message_get_sender(dmsg));
289     message.d_ptr->signature = QString::fromUtf8(dbus_message_get_signature(dmsg));
290     message.d_ptr->msg = dbus_message_ref(dmsg);
291
292     QDBusMarshall::messageToList(message, dmsg);
293     return message;
294 }
295
296 /*!
297     Creates a QDBusMessage that represents the same error as the QDBusError object.
298 */
299 QDBusMessage QDBusMessage::fromError(const QDBusError &error)
300 {
301     QDBusMessage message;
302     message.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
303     message.d_ptr->name = error.name();
304     message << error.message();
305     return message;
306 }
307
308 /*!
309     Returns the path of the object that this message is being sent to (in the case of a
310     method call) or being received from (for a signal).
311 */
312 QString QDBusMessage::path() const
313 {
314     return d_ptr->path;
315 }
316
317 /*!
318     Returns the interface of the method being called (in the case of a method call) or of
319     the signal being received from.
320 */
321 QString QDBusMessage::interface() const
322 {
323     return d_ptr->interface;
324 }
325
326 /*!
327     Returns the name of the signal that was emitted or the name of the error that was
328     received.
329     \sa member()
330 */
331 QString QDBusMessage::name() const
332 {
333     return d_ptr->name;
334 }
335
336 /*!
337     \fn QDBusMessage::member() const
338     Returns the name of the method being called.
339 */
340
341 /*!
342     \fn QDBusMessage::method() const
343     \overload
344     Returns the name of the method being called.
345 */
346
347 /*!
348     Returns the name of the service or the bus address of the remote method call.
349 */
350 QString QDBusMessage::service() const
351 {
352     return d_ptr->service;
353 }
354
355 /*!
356     \fn QDBusMessage::sender() const
357     Returns the unique name of the remote sender.
358 */
359
360 /*!
361     Returns the timeout (in milliseconds) for this message to be processed.
362 */
363 int QDBusMessage::timeout() const
364 {
365     return d_ptr->timeout;
366 }
367
368 /*!
369     Sets the timeout for this message to be processed, given by \a ms, in milliseconds.
370 */
371 void QDBusMessage::setTimeout(int ms)
372 {
373     qAtomicDetach(d_ptr);
374     d_ptr->timeout = ms;
375 }
376
377 /*!
378     Returns the flag that indicates if this message should see a reply or not. This is only
379     meaningful for MethodCall messages: any other kind of message cannot have replies and this
380     function will always return false for them.
381 */
382 bool QDBusMessage::noReply() const
383 {
384     if (!d_ptr->msg)
385         return false;
386     return dbus_message_get_no_reply(d_ptr->msg);
387 }
388
389 /*!
390     Returns the unique serial number assigned to this message
391     or 0 if the message was not sent yet.
392  */
393 int QDBusMessage::serialNumber() const
394 {
395     if (!d_ptr->msg)
396         return 0;
397     return dbus_message_get_serial(d_ptr->msg);
398 }
399
400 /*!
401     Returns the unique serial number assigned to the message
402     that triggered this reply message.
403
404     If this message is not a reply to another message, 0
405     is returned.
406
407  */
408 int QDBusMessage::replySerialNumber() const
409 {
410     if (!d_ptr->msg)
411         return 0;
412     return dbus_message_get_reply_serial(d_ptr->msg);
413 }
414
415 /*!
416     Returns true if this is a MethodCall message and a reply for it has been generated using
417     QDBusMessage::methodReply or QDBusMessage::error.
418 */
419 bool QDBusMessage::wasRepliedTo() const
420 {
421     return d_ptr->repliedTo;
422 }
423
424 /*!
425     Returns the signature of the signal that was received or for the output arguments
426     of a method call.
427 */
428 QString QDBusMessage::signature() const
429 {
430     return d_ptr->signature;
431 }
432
433 /*!
434     Sets the signature for the output arguments of this method call to be the value of \a
435     signature. This function has no meaning in other types of messages or when dealing with received
436     method calls.
437
438     A message's signature indicate the type of the parameters to
439     be marshalled over the bus. If there are more arguments than entries in the signature, the
440     tailing arguments will be silently dropped and not sent. If there are less arguments,
441     default values will be inserted (default values are those created by QVariant::convert
442     when a variant of type QVariant::Invalid is converted to the type).
443
444 */
445 void QDBusMessage::setSignature(const QString &signature)
446 {
447     qAtomicDetach(d_ptr);
448     d_ptr->signature = signature;
449 }
450
451 /*!
452     Returns the connection this message was received on or an unconnected QDBusConnection object if
453     this isn't a message that has been received.
454 */
455 QDBusConnection QDBusMessage::connection() const
456 {
457     return d_ptr->connection;
458 }
459
460 /*!
461     Returns the message type.
462 */
463 QDBusMessage::MessageType QDBusMessage::type() const
464 {
465     switch (d_ptr->type) {
466     case DBUS_MESSAGE_TYPE_METHOD_CALL:
467         return MethodCallMessage;
468     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
469         return ReplyMessage;
470     case DBUS_MESSAGE_TYPE_ERROR:
471         return ErrorMessage;
472     case DBUS_MESSAGE_TYPE_SIGNAL:
473         return SignalMessage;
474     default:
475         return InvalidMessage;
476     }
477 }
478
479 // Document QDBusReply here
480 /*!
481     \class QDBusReply
482     \brief The reply for a method call to a remote object.
483
484     A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
485     reply. It contains only the first output argument or the error code and is used by
486     QDBusInterface-derived classes to allow returning the error code as the function's return
487     argument.
488
489     It can be used in the following manner:
490     \code
491         QDBusReply<QString> reply = interface->call("RemoteMethod");
492         if (reply.isSuccess())
493             // use the returned value
494             useValue(reply.value());
495         else
496             // call failed. Show an error condition.
497             showError(reply.error());
498     \endcode
499
500     If the remote method call cannot fail, you can skip the error checking:
501     \code
502         QString reply = interface->call("RemoteMethod");
503     \endcode
504
505     However, if it does fail under those conditions, the value returned by QDBusReply::value() is
506     undefined. It may be undistinguishable from a valid return value.
507
508     QDBusReply objects are used for remote calls that have no output arguments or return values
509     (i.e., they have a "void" return type). In this case, you can only test if the reply succeeded
510     or not, by calling isError() and isSuccess(), and inspecting the error condition by calling
511     error(). You cannot call value().
512
513     \sa QDBusMessage, QDBusInterface
514 */
515
516 /*!
517     \fn QDBusReply::QDBusReply(const QDBusMessage &reply)
518     Automatically construct a QDBusReply object from the reply message \a reply, extracting the
519     first return value from it if it is a success reply.
520 */
521
522 /*!
523     \fn QDBusReply::QDBusReply(const QDBusError &error)
524     Constructs an error reply from the D-Bus error code given by \a error.
525 */
526
527 /*!
528     \fn QDBusReply::isError() const
529     Returns true if this reply is an error reply. You can extract the error contents using the
530     error() function.
531 */
532
533 /*!
534     \fn QDBusReply::isSuccess() const
535     Returns true if this reply is a normal error reply (not an error). You can extract the returned
536     value with value()
537 */
538
539 /*!
540     \fn QDBusReply::error()
541     Returns the error code that was returned from the remote function call. If the remote call did
542     not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
543     not be a valid error code (QDBusError::isValid() will return false).
544 */
545
546 /*!
547     \fn QDBusReply::value()
548     Returns the remote function's calls return value. If the remote call returned with an error,
549     the return value of this function is undefined and may be undistinguishable from a valid return
550     value.
551
552     This function is not available if the remote call returns \c void.
553 */
554
555 /*!
556     \fn QDBusReply::operator Type()
557     Returns the same as value().
558     
559     This function is not available if the remote call returns \c void.
560 */
561
562 /*!
563     \internal
564     \fn QDBusReply::fromVariant(const QDBusReply<QVariant> &variantReply)
565     Converts the QDBusReply<QVariant> object to this type by converting the variant contained in
566     \a variantReply to the template's type and copying the error condition.
567
568     If the QVariant in variantReply is not convertible to this type, it will assume an undefined
569     value.
570 */
571
572 #ifndef QT_NO_DEBUG
573 QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
574 {
575     switch (t)
576     {
577     case QDBusMessage::MethodCallMessage:
578         return dbg << "MethodCall";        
579     case QDBusMessage::ReplyMessage:
580         return dbg << "MethodReturn";
581     case QDBusMessage::SignalMessage:
582         return dbg << "Signal";
583     case QDBusMessage::ErrorMessage:
584         return dbg << "Error";
585     default:
586         return dbg << "Invalid";
587     }
588 }
589
590 static void debugVariantList(QDebug dbg, const QVariantList &list);
591 static void debugVariantMap(QDebug dbg, const QVariantMap &map);
592
593 static void debugVariant(QDebug dbg, const QVariant &v)
594 {
595     dbg.nospace() << v.typeName() << "(";
596     switch (v.userType())
597     {
598     case QVariant::Bool:
599         dbg.nospace() << v.toBool();
600         break;
601     case QMetaType::UChar:
602         dbg.nospace() << qvariant_cast<uchar>(v);
603         break;
604     case QMetaType::Short:
605         dbg.nospace() << qvariant_cast<short>(v);
606         break;
607     case QMetaType::UShort:
608         dbg.nospace() << qvariant_cast<ushort>(v);
609         break;
610     case QVariant::Int:
611         dbg.nospace() << v.toInt();
612         break;
613     case QVariant::UInt:
614         dbg.nospace() << v.toUInt();
615         break;
616     case QVariant::LongLong:
617         dbg.nospace() << v.toLongLong();
618         break;
619     case QVariant::ULongLong:
620         dbg.nospace() << v.toULongLong();
621         break;
622     case QVariant::Double:
623         dbg.nospace() << v.toDouble();
624         break;
625     case QVariant::String:
626         dbg.nospace() << v.toString();
627         break;
628     case QVariant::ByteArray:
629         dbg.nospace() << v.toByteArray();
630         break;
631     case QVariant::StringList:
632         dbg.nospace() << v.toStringList();
633         break;
634     case QVariant::List:
635         debugVariantList(dbg, v.toList());
636         break;
637     case QVariant::Map:
638         debugVariantMap(dbg, v.toMap());
639         break;
640
641     default: {
642         int id = v.userType();
643         if (id == QDBusTypeHelper<QVariant>::id())
644             debugVariant(dbg, QDBusTypeHelper<QVariant>::fromVariant(v));
645         else if (id == QDBusTypeHelper<bool>::listId())
646             dbg.nospace() << QDBusTypeHelper<QList<bool> >::fromVariant(v);
647         else if (id == QDBusTypeHelper<short>::listId())
648             dbg.nospace() << QDBusTypeHelper<QList<short> >::fromVariant(v);
649         else if (id == QDBusTypeHelper<ushort>::listId())
650             dbg.nospace() << QDBusTypeHelper<QList<ushort> >::fromVariant(v);
651         else if (id == QDBusTypeHelper<int>::listId())
652             dbg.nospace() << QDBusTypeHelper<QList<int> >::fromVariant(v);
653         else if (id == QDBusTypeHelper<uint>::listId())
654             dbg.nospace() << QDBusTypeHelper<QList<uint> >::fromVariant(v);
655         else if (id == QDBusTypeHelper<qlonglong>::listId())
656             dbg.nospace() << QDBusTypeHelper<QList<qlonglong> >::fromVariant(v);
657         else if (id == QDBusTypeHelper<qulonglong>::listId())
658             dbg.nospace() << QDBusTypeHelper<QList<qulonglong> >::fromVariant(v);
659         else if (id == QDBusTypeHelper<double>::listId())
660             dbg.nospace() << QDBusTypeHelper<QList<double> >::fromVariant(v);
661         else
662             dbg.nospace() << "unknown";
663     }
664     }
665     dbg.nospace() << ")";
666 }    
667
668 static void debugVariantList(QDebug dbg, const QVariantList &list)
669 {
670     bool first = true;
671     QVariantList::ConstIterator it = list.constBegin();
672     QVariantList::ConstIterator end = list.constEnd();
673     for ( ; it != end; ++it) {
674         if (!first)
675             dbg.nospace() << ", ";
676         debugVariant(dbg, *it);
677         first = false;
678     }
679 }
680
681 static void debugVariantMap(QDebug dbg, const QVariantMap &map)
682 {
683     QVariantMap::ConstIterator it = map.constBegin();
684     QVariantMap::ConstIterator end = map.constEnd();
685     for ( ; it != end; ++it) {
686         dbg << "(" << it.key() << ", ";
687         debugVariant(dbg, it.value());
688         dbg << ") ";
689     }
690 }        
691
692 QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
693 {
694     dbg.nospace() << "QDBusMessage(type=" << msg.type()
695                   << ", service=" << msg.service()
696                   << ", path=" << msg.path()
697                   << ", interface=" << msg.interface()
698                   << ", name=" << msg.name()
699                   << ", signature=" << msg.signature()
700                   << ", contents=(";
701     debugVariantList(dbg, msg);
702     dbg.nospace() << " ) )";
703     return dbg.space();
704 }
705 #endif
706