1#include <config.h>
2
3#include "test-utils.h"
4#ifdef HAVE_UNISTD_H
5#include <unistd.h>
6#endif
7
8static DBusLoop *loop;
9static dbus_bool_t already_quit = FALSE;
10static dbus_bool_t hello_from_self_reply_received = FALSE;
11
12static void
13quit (void)
14{
15  if (!already_quit)
16    {
17      _dbus_loop_quit (loop);
18      already_quit = TRUE;
19    }
20}
21
22static void
23die (const char *message)
24{
25  fprintf (stderr, "*** test-service: %s", message);
26  exit (1);
27}
28
29static void
30check_hello_from_self_reply (DBusPendingCall *pcall,
31                             void *user_data)
32{
33  DBusMessage *reply;
34  DBusMessage *echo_message, *echo_reply = NULL;
35  DBusError error;
36  DBusConnection *connection;
37
38  int type;
39
40  dbus_error_init (&error);
41
42  connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
43  if (connection == NULL)
44    {
45      fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
46               error.message);
47      dbus_error_free (&error);
48      die("no memory");
49    }
50
51
52  echo_message = (DBusMessage *)user_data;
53
54  reply = dbus_pending_call_steal_reply (pcall);
55
56  type = dbus_message_get_type (reply);
57
58  if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
59    {
60      const char *s;
61      printf ("Reply from HelloFromSelf received\n");
62
63      if (!dbus_message_get_args (echo_message,
64                              &error,
65                              DBUS_TYPE_STRING, &s,
66                              DBUS_TYPE_INVALID))
67        {
68            echo_reply = dbus_message_new_error (echo_message,
69                                      error.name,
70                                      error.message);
71
72            if (echo_reply == NULL)
73              die ("No memory\n");
74
75        }
76      else
77        {
78          echo_reply = dbus_message_new_method_return (echo_message);
79          if (echo_reply == NULL)
80            die ("No memory\n");
81
82          if (!dbus_message_append_args (echo_reply,
83                                 DBUS_TYPE_STRING, &s,
84                                 DBUS_TYPE_INVALID))
85            die ("No memory");
86        }
87
88      if (!dbus_connection_send (connection, echo_reply, NULL))
89        die ("No memory\n");
90
91      dbus_message_unref (echo_reply);
92    }
93  else if (type == DBUS_MESSAGE_TYPE_ERROR)
94    {
95      dbus_set_error_from_message (&error, reply);
96      printf ("Error type in reply: %s\n", error.message);
97
98      if (strcmp (error.name, DBUS_ERROR_NO_MEMORY) != 0)
99        {
100            echo_reply = dbus_message_new_error (echo_reply,
101                                      error.name,
102                                      error.message);
103
104            if (echo_reply == NULL)
105              die ("No memory\n");
106
107            if (!dbus_connection_send (connection, echo_reply, NULL))
108              die ("No memory\n");
109
110            dbus_message_unref (echo_reply);
111        }
112      dbus_error_free (&error);
113    }
114  else
115     _dbus_assert_not_reached ("Unexpected message received\n");
116
117  hello_from_self_reply_received = TRUE;
118
119  dbus_message_unref (reply);
120  dbus_message_unref (echo_message);
121  dbus_pending_call_unref (pcall);
122  dbus_connection_unref (connection);
123}
124
125static DBusHandlerResult
126handle_run_hello_from_self (DBusConnection     *connection,
127                                               DBusMessage        *message)
128{
129  DBusError error;
130  DBusMessage *reply, *self_message;
131  DBusPendingCall *pcall;
132  char *s;
133
134  _dbus_verbose ("sending reply to Echo method\n");
135
136  dbus_error_init (&error);
137
138  if (!dbus_message_get_args (message,
139                              &error,
140                              DBUS_TYPE_STRING, &s,
141                              DBUS_TYPE_INVALID))
142    {
143      reply = dbus_message_new_error (message,
144                                      error.name,
145                                      error.message);
146
147      if (reply == NULL)
148        die ("No memory\n");
149
150      if (!dbus_connection_send (connection, reply, NULL))
151        die ("No memory\n");
152
153      dbus_message_unref (reply);
154
155      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
156    }
157    printf ("Sending HelloFromSelf\n");
158
159 _dbus_verbose ("*** Sending message to self\n");
160 self_message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
161                                          "/org/freedesktop/TestSuite",
162                                          "org.freedesktop.TestSuite",
163                                          "HelloFromSelf");
164
165  if (self_message == NULL)
166    die ("No memory");
167
168  if (!dbus_connection_send_with_reply (connection, self_message, &pcall, -1))
169    die("No memory");
170
171  dbus_message_ref (message);
172  if (!dbus_pending_call_set_notify (pcall, check_hello_from_self_reply, (void *)message, NULL))
173    die("No memory");
174
175  printf ("Sent HelloFromSelf\n");
176  return DBUS_HANDLER_RESULT_HANDLED;
177}
178
179static DBusHandlerResult
180handle_echo (DBusConnection     *connection,
181             DBusMessage        *message)
182{
183  DBusError error;
184  DBusMessage *reply;
185  char *s;
186
187  _dbus_verbose ("sending reply to Echo method\n");
188
189  dbus_error_init (&error);
190
191  if (!dbus_message_get_args (message,
192                              &error,
193                              DBUS_TYPE_STRING, &s,
194                              DBUS_TYPE_INVALID))
195    {
196      reply = dbus_message_new_error (message,
197                                      error.name,
198                                      error.message);
199
200      if (reply == NULL)
201        die ("No memory\n");
202
203      if (!dbus_connection_send (connection, reply, NULL))
204        die ("No memory\n");
205
206      dbus_message_unref (reply);
207
208      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
209    }
210
211  reply = dbus_message_new_method_return (message);
212  if (reply == NULL)
213    die ("No memory\n");
214
215  if (!dbus_message_append_args (reply,
216                                 DBUS_TYPE_STRING, &s,
217                                 DBUS_TYPE_INVALID))
218    die ("No memory");
219
220  if (!dbus_connection_send (connection, reply, NULL))
221    die ("No memory\n");
222
223  fprintf (stderr, "Echo service echoed string: \"%s\"\n", s);
224
225  dbus_message_unref (reply);
226
227  return DBUS_HANDLER_RESULT_HANDLED;
228}
229
230static DBusHandlerResult
231handle_delay_echo (DBusConnection     *connection,
232                   DBusMessage        *message)
233{
234  DBusError error;
235  DBusMessage *reply;
236  char *s;
237
238  _dbus_verbose ("sleeping for a short time\n");
239
240  _dbus_sleep_milliseconds (50);
241
242  _dbus_verbose ("sending reply to DelayEcho method\n");
243
244  dbus_error_init (&error);
245
246  if (!dbus_message_get_args (message,
247                              &error,
248                              DBUS_TYPE_STRING, &s,
249                              DBUS_TYPE_INVALID))
250    {
251      reply = dbus_message_new_error (message,
252                                      error.name,
253                                      error.message);
254
255      if (reply == NULL)
256        die ("No memory\n");
257
258      if (!dbus_connection_send (connection, reply, NULL))
259        die ("No memory\n");
260
261      dbus_message_unref (reply);
262
263      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
264    }
265
266  reply = dbus_message_new_method_return (message);
267  if (reply == NULL)
268    die ("No memory\n");
269
270  if (!dbus_message_append_args (reply,
271                                 DBUS_TYPE_STRING, &s,
272                                 DBUS_TYPE_INVALID))
273    die ("No memory");
274
275  if (!dbus_connection_send (connection, reply, NULL))
276    die ("No memory\n");
277
278  fprintf (stderr, "DelayEcho service echoed string: \"%s\"\n", s);
279
280  dbus_message_unref (reply);
281
282  return DBUS_HANDLER_RESULT_HANDLED;
283}
284
285
286static void
287path_unregistered_func (DBusConnection  *connection,
288                        void            *user_data)
289{
290  /* connection was finalized */
291}
292
293static DBusHandlerResult
294path_message_func (DBusConnection  *connection,
295                   DBusMessage     *message,
296                   void            *user_data)
297{
298  if (dbus_message_is_method_call (message,
299                                   "org.freedesktop.TestSuite",
300                                   "Echo"))
301    return handle_echo (connection, message);
302  else if (dbus_message_is_method_call (message,
303                                        "org.freedesktop.TestSuite",
304                                        "DelayEcho"))
305    return handle_delay_echo (connection, message);
306  else if (dbus_message_is_method_call (message,
307                                        "org.freedesktop.TestSuite",
308                                        "Exit"))
309    {
310      quit ();
311      return DBUS_HANDLER_RESULT_HANDLED;
312    }
313  else if (dbus_message_is_method_call (message,
314                                        "org.freedesktop.TestSuite",
315                                        "EmitFoo"))
316    {
317      /* Emit the Foo signal */
318      DBusMessage *signal;
319      double v_DOUBLE;
320
321      _dbus_verbose ("emitting signal Foo\n");
322
323      signal = dbus_message_new_signal ("/org/freedesktop/TestSuite",
324                                        "org.freedesktop.TestSuite",
325                                        "Foo");
326      if (signal == NULL)
327        die ("No memory\n");
328
329      v_DOUBLE = 42.6;
330      if (!dbus_message_append_args (signal,
331                                     DBUS_TYPE_DOUBLE, &v_DOUBLE,
332                                     DBUS_TYPE_INVALID))
333        die ("No memory");
334
335      if (!dbus_connection_send (connection, signal, NULL))
336        die ("No memory\n");
337
338      return DBUS_HANDLER_RESULT_HANDLED;
339    }
340
341  else if (dbus_message_is_method_call (message,
342                                   "org.freedesktop.TestSuite",
343                                   "RunHelloFromSelf"))
344    {
345      return handle_run_hello_from_self (connection, message);
346    }
347  else if (dbus_message_is_method_call (message,
348                                        "org.freedesktop.TestSuite",
349                                        "HelloFromSelf"))
350    {
351        DBusMessage *reply;
352        printf ("Received the HelloFromSelf message\n");
353
354        reply = dbus_message_new_method_return (message);
355        if (reply == NULL)
356          die ("No memory");
357
358        if (!dbus_connection_send (connection, reply, NULL))
359          die ("No memory");
360
361        return DBUS_HANDLER_RESULT_HANDLED;
362    }
363  else
364    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
365}
366
367static DBusObjectPathVTable
368echo_vtable = {
369  path_unregistered_func,
370  path_message_func,
371  NULL,
372};
373
374
375static const char* echo_path = "/org/freedesktop/TestSuite" ;
376
377static DBusHandlerResult
378filter_func (DBusConnection     *connection,
379             DBusMessage        *message,
380             void               *user_data)
381{
382  if (dbus_message_is_signal (message,
383                              DBUS_INTERFACE_LOCAL,
384                              "Disconnected"))
385    {
386      quit ();
387      return DBUS_HANDLER_RESULT_HANDLED;
388    }
389  else
390    {
391      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
392    }
393}
394
395int
396main (int    argc,
397      char **argv)
398{
399  DBusError error;
400  int result;
401  DBusConnection *connection;
402  const char *name;
403  dbus_bool_t do_fork;
404
405  if (argc != 3)
406    {
407      name = "org.freedesktop.DBus.TestSuiteEchoService";
408      do_fork = FALSE;
409    }
410  else
411    {
412      name = argv[1];
413#ifndef DBUS_WIN
414      do_fork = strcmp (argv[2], "fork") == 0;
415#else
416      do_fork = FALSE;
417#endif
418    }
419
420  /* The bare minimum for simulating a program "daemonizing"; the intent
421   * is to test services which move from being legacy init scripts to
422   * activated services.
423   * https://bugzilla.redhat.com/show_bug.cgi?id=545267
424   */
425#ifndef DBUS_WIN
426   if (do_fork)
427    {
428      pid_t pid = fork ();
429      if (pid != 0)
430        exit (0);
431      sleep (1);
432    }
433#endif
434
435  dbus_error_init (&error);
436  connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
437  if (connection == NULL)
438    {
439      fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
440               error.message);
441      dbus_error_free (&error);
442      return 1;
443    }
444
445  loop = _dbus_loop_new ();
446  if (loop == NULL)
447    die ("No memory\n");
448
449  if (!test_connection_setup (loop, connection))
450    die ("No memory\n");
451
452  if (!dbus_connection_add_filter (connection,
453                                   filter_func, NULL, NULL))
454    die ("No memory");
455
456  if (!dbus_connection_register_object_path (connection,
457                                             echo_path,
458                                             &echo_vtable,
459                                             (void*) 0xdeadbeef))
460    die ("No memory");
461
462  {
463    void *d;
464    if (!dbus_connection_get_object_path_data (connection, echo_path, &d))
465      die ("No memory");
466    if (d != (void*) 0xdeadbeef)
467      die ("dbus_connection_get_object_path_data() doesn't seem to work right\n");
468  }
469
470  result = dbus_bus_request_name (connection, name,
471                                  0, &error);
472  if (dbus_error_is_set (&error))
473    {
474      fprintf (stderr, "Error %s\n", error.message);
475      _dbus_verbose ("*** Failed to acquire service: %s\n",
476                     error.message);
477      dbus_error_free (&error);
478      exit (1);
479    }
480
481  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
482    {
483      fprintf (stderr, "Unable to acquire service: code %d\n", result);
484      _dbus_verbose ("*** Failed to acquire service: %d\n", result);
485      exit (1);
486    }
487
488  _dbus_verbose ("*** Test service entering main loop\n");
489  _dbus_loop_run (loop);
490
491  test_connection_shutdown (loop, connection);
492
493  dbus_connection_remove_filter (connection, filter_func, NULL);
494
495  dbus_connection_unref (connection);
496
497  _dbus_loop_unref (loop);
498  loop = NULL;
499
500  dbus_shutdown ();
501
502  _dbus_verbose ("*** Test service exiting\n");
503
504  return 0;
505}
506