* dbus/dbus-pending-call.c: Add some checks so we don't crash on
[platform/upstream/dbus.git] / dbus / dbus-pending-call.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-pending-call.c Object representing a call in progress.
3  *
4  * Copyright (C) 2002, 2003 Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-connection-internal.h"
26 #include "dbus-pending-call-internal.h"
27 #include "dbus-pending-call.h"
28 #include "dbus-list.h"
29 #include "dbus-threads.h"
30 #include "dbus-test.h"
31
32 /**
33  * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
34  * @ingroup DBusInternals
35  * @brief DBusPendingCall private implementation details.
36  *
37  * The guts of DBusPendingCall and its methods.
38  *
39  * @{
40  */
41
42 /**
43  * @brief Internals of DBusPendingCall
44  *
45  * Opaque object representing a reply message that we're waiting for.
46  */
47 #define CONNECTION_LOCK(connection)   _dbus_connection_lock(connection)
48 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock(connection)
49
50 struct DBusPendingCall
51 {
52   DBusAtomic refcount;                            /**< reference count */
53
54   DBusDataSlotList slot_list;                     /**< Data stored by allocated integer ID */
55   
56   DBusPendingCallNotifyFunction function;         /**< Notifier when reply arrives. */
57
58   DBusConnection *connection;                     /**< Connections we're associated with */
59   DBusMessage *reply;                             /**< Reply (after we've received it) */
60   DBusTimeout *timeout;                           /**< Timeout */
61
62   DBusList *timeout_link;                         /**< Preallocated timeout response */
63   
64   dbus_uint32_t reply_serial;                     /**< Expected serial of reply */
65
66   unsigned int completed : 1;                     /**< TRUE if completed */
67   unsigned int timeout_added : 1;                 /**< Have added the timeout */
68 };
69
70 static dbus_int32_t notify_user_data_slot = -1;
71
72 /**
73  * Creates a new pending reply object.
74  *
75  * @param connection connection where reply will arrive
76  * @param timeout_milliseconds length of timeout, -1 for default
77  * @param timeout_handler timeout handler, takes pending call as data
78  * @returns a new #DBusPendingCall or #NULL if no memory.
79  */
80 DBusPendingCall*
81 _dbus_pending_call_new_unlocked (DBusConnection    *connection,
82                                  int                timeout_milliseconds,
83                                  DBusTimeoutHandler timeout_handler)
84 {
85   DBusPendingCall *pending;
86   DBusTimeout *timeout;
87
88   _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
89  
90   if (timeout_milliseconds == -1)
91     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
92
93   /* it would probably seem logical to pass in _DBUS_INT_MAX for
94    * infinite timeout, but then math in
95    * _dbus_connection_block_for_reply would get all overflow-prone, so
96    * smack that down.
97    */
98   if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
99     timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
100   
101   if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
102     return NULL;
103   
104   pending = dbus_new0 (DBusPendingCall, 1);
105   
106   if (pending == NULL)
107     {
108       dbus_pending_call_free_data_slot (&notify_user_data_slot);
109       return NULL;
110     }
111
112   timeout = _dbus_timeout_new (timeout_milliseconds,
113                                timeout_handler,
114                                pending, NULL);  
115
116   if (timeout == NULL)
117     {
118       dbus_pending_call_free_data_slot (&notify_user_data_slot);
119       dbus_free (pending);
120       return NULL;
121     }
122   
123   pending->refcount.value = 1;
124   pending->connection = connection;
125   _dbus_connection_ref_unlocked (pending->connection);
126
127   pending->timeout = timeout;
128
129
130   _dbus_data_slot_list_init (&pending->slot_list);
131   
132   return pending;
133 }
134
135 /**
136  * Sets the reply of a pending call with the given message,
137  * or if the message is #NULL, by timing out the pending call.
138  * 
139  * @param pending the pending call
140  * @param message the message to complete the call with, or #NULL
141  *  to time out the call
142  */
143 void
144 _dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
145                                        DBusMessage     *message)
146 {
147   if (message == NULL)
148     {
149       message = pending->timeout_link->data;
150       _dbus_list_clear (&pending->timeout_link);
151     }
152   else
153     dbus_message_ref (message);
154
155   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
156                  message,
157                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
158                  "method return" :
159                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
160                  "error" : "other type",
161                  pending->reply_serial);
162   
163   _dbus_assert (pending->reply == NULL);
164   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
165   pending->reply = message;
166 }
167
168 /**
169  * Calls notifier function for the pending call
170  * and sets the call to completed.
171  *
172  * @param pending the pending call
173  * 
174  */
175 void
176 _dbus_pending_call_complete (DBusPendingCall *pending)
177 {
178   _dbus_assert (!pending->completed);
179   
180   pending->completed = TRUE;
181
182   if (pending->function)
183     {
184       void *user_data;
185       user_data = dbus_pending_call_get_data (pending,
186                                               notify_user_data_slot);
187       
188       (* pending->function) (pending, user_data);
189     }
190 }
191
192 void
193 _dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall *pending, 
194                                                  DBusConnection  *connection)
195 {
196   _dbus_assert (connection == pending->connection);
197   
198   if (pending->timeout_link)
199     {
200       _dbus_connection_queue_synthesized_message_link (connection,
201                                                        pending->timeout_link);
202       pending->timeout_link = NULL;
203     }
204 }
205
206 /**
207  * Checks to see if a timeout has been added
208  *
209  * @param pending the pending_call
210  * @returns #TRUE if there is a timeout or #FALSE if not
211  */
212 dbus_bool_t 
213 _dbus_pending_call_is_timeout_added_unlocked (DBusPendingCall  *pending)
214 {
215   _dbus_assert (pending != NULL);
216
217   return pending->timeout_added;
218 }
219
220
221 /**
222  * Sets wether the timeout has been added
223  *
224  * @param pending the pending_call
225  * @param is_added whether or not a timeout is added
226  */
227 void
228 _dbus_pending_call_set_timeout_added_unlocked (DBusPendingCall  *pending,
229                                                dbus_bool_t       is_added)
230 {
231   _dbus_assert (pending != NULL);
232
233   pending->timeout_added = is_added;
234 }
235
236
237 /**
238  * Retrives the timeout
239  *
240  * @param pending the pending_call
241  * @returns a timeout object 
242  */
243 DBusTimeout *
244 _dbus_pending_call_get_timeout_unlocked (DBusPendingCall  *pending)
245 {
246   _dbus_assert (pending != NULL);
247
248   return pending->timeout;
249 }
250
251 /**
252  * Gets the reply's serial number
253  *
254  * @param pending the pending_call
255  * @returns a serial number for the reply or 0 
256  */
257 dbus_uint32_t 
258 _dbus_pending_call_get_reply_serial_unlocked (DBusPendingCall  *pending)
259 {
260   _dbus_assert (pending != NULL);
261
262   return pending->reply_serial;
263 }
264
265 /**
266  * Sets the reply's serial number
267  *
268  * @param pending the pending_call
269  * @param serial the serial number 
270  */
271 void
272 _dbus_pending_call_set_reply_serial_unlocked  (DBusPendingCall *pending,
273                                                dbus_uint32_t serial)
274 {
275   _dbus_assert (pending != NULL);
276   _dbus_assert (pending->reply_serial == 0);
277
278   pending->reply_serial = serial;
279 }
280
281 /**
282  * Gets the connection associated with this pending call.
283  *
284  * @param pending the pending_call
285  * @returns the connection associated with the pending call
286  */
287 DBusConnection *
288 _dbus_pending_call_get_connection_and_lock (DBusPendingCall *pending)
289 {
290   _dbus_assert (pending != NULL);
291  
292   CONNECTION_LOCK (pending->connection);
293   return pending->connection;
294 }
295
296 /**
297  * Gets the connection associated with this pending call.
298  *
299  * @param pending the pending_call
300  * @returns the connection associated with the pending call
301  */
302 DBusConnection *
303 _dbus_pending_call_get_connection_unlocked (DBusPendingCall *pending)
304 {
305   _dbus_assert (pending != NULL);
306  
307   return pending->connection;
308 }
309
310 /**
311  * Sets the reply message associated with the pending call to a timeout error
312  *
313  * @param pending the pending_call
314  * @param message the message we are sending the error reply to 
315  * @param serial serial number for the reply
316  * @return #FALSE on OOM
317  */
318 dbus_bool_t
319 _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending,
320                                                DBusMessage     *message,
321                                                dbus_uint32_t    serial)
322
323   DBusList *reply_link;
324   DBusMessage *reply;
325
326   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
327                                   "Did not receive a reply. Possible causes include: "
328                                   "the remote application did not send a reply, "
329                                   "the message bus security policy blocked the reply, "
330                                   "the reply timeout expired, or "
331                                   "the network connection was broken.");
332   if (reply == NULL)
333     return FALSE;
334
335   reply_link = _dbus_list_alloc_link (reply);
336   if (reply_link == NULL)
337     {
338       dbus_message_unref (reply);
339       return FALSE;
340     }
341
342   pending->timeout_link = reply_link;
343
344   _dbus_pending_call_set_reply_serial_unlocked (pending, serial);
345   
346   return TRUE;
347 }
348
349 /** @} */
350
351 /**
352  * @defgroup DBusPendingCall DBusPendingCall
353  * @ingroup  DBus
354  * @brief Pending reply to a method call message
355  *
356  * A DBusPendingCall is an object representing an
357  * expected reply. A #DBusPendingCall can be created
358  * when you send a message that should have a reply.
359  *
360  * @{
361  */
362
363 /**
364  * @typedef DBusPendingCall
365  *
366  * Opaque data type representing a message pending.
367  */
368
369 /**
370  * Increments the reference count on a pending call,
371  * while the lock on its connection is already held.
372  *
373  * @param pending the pending call object
374  * @returns the pending call object
375  */
376 DBusPendingCall *
377 _dbus_pending_call_ref_unlocked (DBusPendingCall *pending)
378 {
379   pending->refcount.value += 1;
380   
381   return pending;
382 }
383
384 /**
385  * Increments the reference count on a pending call.
386  *
387  * @param pending the pending call object
388  * @returns the pending call object
389  */
390 DBusPendingCall *
391 dbus_pending_call_ref (DBusPendingCall *pending)
392 {
393   _dbus_return_val_if_fail (pending != NULL, NULL);
394
395   /* The connection lock is better than the global
396    * lock in the atomic increment fallback
397    */
398 #ifdef DBUS_HAVE_ATOMIC_INT
399   _dbus_atomic_inc (&pending->refcount);
400 #else
401   CONNECTION_LOCK (pending->connection);
402   _dbus_assert (pending->refcount.value > 0);
403
404   pending->refcount.value += 1;
405   CONNECTION_UNLOCK (pending->connection);
406 #endif
407   
408   return pending;
409 }
410
411 static void
412 _dbus_pending_call_last_unref (DBusPendingCall *pending)
413 {
414   DBusConnection *connection;
415   
416   /* If we get here, we should be already detached
417    * from the connection, or never attached.
418    */
419   _dbus_assert (!pending->timeout_added);  
420
421   connection = pending->connection;
422
423   /* this assumes we aren't holding connection lock... */
424   _dbus_data_slot_list_free (&pending->slot_list);
425
426   if (pending->timeout != NULL)
427     _dbus_timeout_unref (pending->timeout);
428       
429   if (pending->timeout_link)
430     {
431       dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
432       _dbus_list_free_link (pending->timeout_link);
433       pending->timeout_link = NULL;
434     }
435
436   if (pending->reply)
437     {
438       dbus_message_unref (pending->reply);
439       pending->reply = NULL;
440     }
441       
442   dbus_free (pending);
443
444   dbus_pending_call_free_data_slot (&notify_user_data_slot);
445
446   /* connection lock should not be held. */
447   /* Free the connection last to avoid a weird state while
448    * calling out to application code where the pending exists
449    * but not the connection.
450    */
451   dbus_connection_unref (connection);
452 }
453
454 /**
455  * Decrements the reference count on a pending call,
456  * freeing it if the count reaches 0. Assumes
457  * connection lock is already held.
458  *
459  * @param pending the pending call object
460  */
461 void
462 _dbus_pending_call_unref_and_unlock (DBusPendingCall *pending)
463 {
464   dbus_bool_t last_unref;
465   
466   _dbus_assert (pending->refcount.value > 0);
467
468   pending->refcount.value -= 1;
469   last_unref = pending->refcount.value == 0;
470
471   CONNECTION_UNLOCK (pending->connection);
472   if (last_unref)
473     _dbus_pending_call_last_unref (pending);
474 }
475
476 /**
477  * Decrements the reference count on a pending call,
478  * freeing it if the count reaches 0.
479  *
480  * @param pending the pending call object
481  */
482 void
483 dbus_pending_call_unref (DBusPendingCall *pending)
484 {
485   dbus_bool_t last_unref;
486
487   _dbus_return_if_fail (pending != NULL);
488
489   /* More efficient to use the connection lock instead of atomic
490    * int fallback if we lack atomic int decrement
491    */
492 #ifdef DBUS_HAVE_ATOMIC_INT
493   last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
494 #else
495   CONNECTION_LOCK (pending->connection);
496   _dbus_assert (pending->refcount.value > 0);
497   pending->refcount.value -= 1;
498   last_unref = pending->refcount.value == 0;
499   CONNECTION_UNLOCK (pending->connection);
500 #endif
501   
502   if (last_unref)
503     _dbus_pending_call_last_unref(pending);
504 }
505
506 /**
507  * Sets a notification function to be called when the reply is
508  * received or the pending call times out.
509  *
510  * @param pending the pending call
511  * @param function notifier function
512  * @param user_data data to pass to notifier function
513  * @param free_user_data function to free the user data
514  * @returns #FALSE if not enough memory
515  */
516 dbus_bool_t
517 dbus_pending_call_set_notify (DBusPendingCall              *pending,
518                               DBusPendingCallNotifyFunction function,
519                               void                         *user_data,
520                               DBusFreeFunction              free_user_data)
521 {
522   _dbus_return_val_if_fail (pending != NULL, FALSE);
523
524   CONNECTION_LOCK (pending->connection);
525   
526   /* could invoke application code! */
527   if (!_dbus_pending_call_set_data_unlocked (pending, notify_user_data_slot,
528                                              user_data, free_user_data))
529     return FALSE;
530   
531   pending->function = function;
532
533   CONNECTION_UNLOCK (pending->connection);
534   
535   return TRUE;
536 }
537
538 /**
539  * Cancels the pending call, such that any reply or error received
540  * will just be ignored.  Drops the dbus library's internal reference
541  * to the #DBusPendingCall so will free the call if nobody else is
542  * holding a reference. However you usually get a reference
543  * from dbus_connection_send() so probably your app owns a ref also.
544  * 
545  * @param pending the pending call
546  */
547 void
548 dbus_pending_call_cancel (DBusPendingCall *pending)
549 {
550   _dbus_return_if_fail (pending != NULL);
551
552   _dbus_connection_remove_pending_call (pending->connection,
553                                         pending);
554 }
555
556 /**
557  * Checks whether the pending call has received a reply
558  * yet, or not. Assumes connection lock is held.
559  *
560  * @param pending the pending call
561  * @returns #TRUE if a reply has been received
562  */
563 dbus_bool_t
564 _dbus_pending_call_get_completed_unlocked (DBusPendingCall    *pending)
565 {
566   return pending->completed;
567 }
568
569 /**
570  * Checks whether the pending call has received a reply
571  * yet, or not.
572  *
573  * @param pending the pending call
574  * @returns #TRUE if a reply has been received
575  */
576 dbus_bool_t
577 dbus_pending_call_get_completed (DBusPendingCall *pending)
578 {
579   dbus_bool_t completed;
580   
581   _dbus_return_val_if_fail (pending != NULL, FALSE);
582
583   CONNECTION_LOCK (pending->connection);
584   completed = pending->completed;
585   CONNECTION_UNLOCK (pending->connection);
586
587   return completed;
588 }
589
590 /**
591  * Gets the reply, or returns #NULL if none has been received
592  * yet. Ownership of the reply message passes to the caller. This
593  * function can only be called once per pending call, since the reply
594  * message is tranferred to the caller.
595  * 
596  * @param pending the pending call
597  * @returns the reply message or #NULL.
598  */
599 DBusMessage*
600 dbus_pending_call_steal_reply (DBusPendingCall *pending)
601 {
602   DBusMessage *message;
603   
604   _dbus_return_val_if_fail (pending != NULL, NULL);
605   _dbus_return_val_if_fail (pending->completed, NULL);
606   _dbus_return_val_if_fail (pending->reply != NULL, NULL);
607
608   CONNECTION_LOCK (pending->connection);
609   
610   message = pending->reply;
611   pending->reply = NULL;
612
613   CONNECTION_UNLOCK (pending->connection);
614   
615   return message;
616 }
617
618 /**
619  * Block until the pending call is completed.  The blocking is as with
620  * dbus_connection_send_with_reply_and_block(); it does not enter the
621  * main loop or process other messages, it simply waits for the reply
622  * in question.
623  *
624  * If the pending call is already completed, this function returns
625  * immediately.
626  *
627  * @todo when you start blocking, the timeout is reset, but it should
628  * really only use time remaining since the pending call was created.
629  *
630  * @param pending the pending call
631  */
632 void
633 dbus_pending_call_block (DBusPendingCall *pending)
634 {
635   _dbus_return_if_fail (pending != NULL);
636
637   _dbus_connection_block_pending_call (pending);
638 }
639
640 static DBusDataSlotAllocator slot_allocator;
641 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
642
643 /**
644  * Allocates an integer ID to be used for storing application-specific
645  * data on any DBusPendingCall. The allocated ID may then be used
646  * with dbus_pending_call_set_data() and dbus_pending_call_get_data().
647  * The passed-in slot must be initialized to -1, and is filled in
648  * with the slot ID. If the passed-in slot is not -1, it's assumed
649  * to be already allocated, and its refcount is incremented.
650  * 
651  * The allocated slot is global, i.e. all DBusPendingCall objects will
652  * have a slot with the given integer ID reserved.
653  *
654  * @param slot_p address of a global variable storing the slot
655  * @returns #FALSE on failure (no memory)
656  */
657 dbus_bool_t
658 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
659 {
660   _dbus_return_val_if_fail (slot_p != NULL, FALSE);
661
662   return _dbus_data_slot_allocator_alloc (&slot_allocator,
663                                           &_DBUS_LOCK_NAME (pending_call_slots),
664                                           slot_p);
665 }
666
667 /**
668  * Deallocates a global ID for #DBusPendingCall data slots.
669  * dbus_pending_call_get_data() and dbus_pending_call_set_data() may
670  * no longer be used with this slot.  Existing data stored on existing
671  * DBusPendingCall objects will be freed when the #DBusPendingCall is
672  * finalized, but may not be retrieved (and may only be replaced if
673  * someone else reallocates the slot).  When the refcount on the
674  * passed-in slot reaches 0, it is set to -1.
675  *
676  * @param slot_p address storing the slot to deallocate
677  */
678 void
679 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
680 {
681   _dbus_return_if_fail (slot_p != NULL);
682   _dbus_return_if_fail (*slot_p >= 0);
683
684   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
685 }
686
687 /**
688  * Stores a pointer on a #DBusPendingCall, along
689  * with an optional function to be used for freeing
690  * the data when the data is set again, or when
691  * the pending call is finalized. The slot number
692  * must have been allocated with dbus_pending_call_allocate_data_slot().
693  *
694  * @param pending the pending_call
695  * @param slot the slot number
696  * @param data the data to store
697  * @param free_data_func finalizer function for the data
698  * @returns #TRUE if there was enough memory to store the data
699  */
700 dbus_bool_t
701 _dbus_pending_call_set_data_unlocked (DBusPendingCall  *pending,
702                                      dbus_int32_t      slot,
703                                      void             *data,
704                                      DBusFreeFunction  free_data_func)
705 {
706   DBusFreeFunction old_free_func;
707   void *old_data;
708   dbus_bool_t retval;
709
710   retval = _dbus_data_slot_list_set (&slot_allocator,
711                                      &pending->slot_list,
712                                      slot, data, free_data_func,
713                                      &old_free_func, &old_data);
714
715   /* Drop locks to call out to app code */
716   CONNECTION_UNLOCK (pending->connection);
717   
718   if (retval)
719     {
720       if (old_free_func)
721         (* old_free_func) (old_data);
722     }
723
724   CONNECTION_LOCK (pending->connection);
725   
726   return retval;
727 }
728
729 /**
730  * Stores a pointer on a #DBusPendingCall, along
731  * with an optional function to be used for freeing
732  * the data when the data is set again, or when
733  * the pending call is finalized. The slot number
734  * must have been allocated with dbus_pending_call_allocate_data_slot().
735  *
736  * @param pending the pending_call
737  * @param slot the slot number
738  * @param data the data to store
739  * @param free_data_func finalizer function for the data
740  * @returns #TRUE if there was enough memory to store the data
741  */
742 dbus_bool_t
743 dbus_pending_call_set_data (DBusPendingCall  *pending,
744                             dbus_int32_t      slot,
745                             void             *data,
746                             DBusFreeFunction  free_data_func)
747 {
748   dbus_bool_t retval;
749   
750   _dbus_return_val_if_fail (pending != NULL, FALSE);
751   _dbus_return_val_if_fail (slot >= 0, FALSE);
752
753   
754   CONNECTION_LOCK (pending->connection);
755   retval = _dbus_pending_call_set_data_unlocked (pending, slot, data, free_data_func);
756   CONNECTION_UNLOCK (pending->connection);
757   return retval;
758 }
759
760 /**
761  * Retrieves data previously set with dbus_pending_call_set_data().
762  * The slot must still be allocated (must not have been freed).
763  *
764  * @param pending the pending_call
765  * @param slot the slot to get data from
766  * @returns the data, or #NULL if not found
767  */
768 void*
769 dbus_pending_call_get_data (DBusPendingCall   *pending,
770                             dbus_int32_t       slot)
771 {
772   void *res;
773
774   _dbus_return_val_if_fail (pending != NULL, NULL);
775
776   CONNECTION_LOCK (pending->connection);
777   res = _dbus_data_slot_list_get (&slot_allocator,
778                                   &pending->slot_list,
779                                   slot);
780   CONNECTION_UNLOCK (pending->connection);
781
782   return res;
783 }
784
785 /** @} */
786
787 #ifdef DBUS_BUILD_TESTS
788
789 /**
790  * @ingroup DBusPendingCallInternals
791  * Unit test for DBusPendingCall.
792  *
793  * @returns #TRUE on success.
794  */
795 dbus_bool_t
796 _dbus_pending_call_test (const char *test_data_dir)
797 {  
798
799   return TRUE;
800 }
801 #endif /* DBUS_BUILD_TESTS */