2002-11-24 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / test / watch.c
1 #include "watch.h"
2 #include <stdio.h>
3
4 #define DBUS_COMPILATION /* cheat and use DBusList */
5 #include <dbus/dbus-list.h>
6 #undef DBUS_COMPILATION
7
8 /* Cheesy main loop used in test programs.  Any real app would use the
9  * GLib or Qt or other non-sucky main loops.
10  */ 
11
12 #undef  MAX
13 #define MAX(a, b)  (((a) > (b)) ? (a) : (b))
14
15 static DBusList *watches = NULL;
16 static dbus_bool_t exited = FALSE;
17 static DBusList *connections = NULL;
18
19 typedef enum
20 {
21   WATCH_CONNECTION,
22   WATCH_SERVER
23 } WatchType;
24
25 typedef struct
26 {
27   WatchType type;
28   void *data;
29 } WatchData;
30
31 static void
32 add_connection_watch (DBusWatch      *watch,
33                       DBusConnection *connection)
34 {
35   WatchData *wd;
36
37   wd = dbus_new0 (WatchData, 1);
38   wd->type = WATCH_CONNECTION;
39   wd->data = connection;
40   
41   _dbus_list_append (&watches, watch);
42   dbus_watch_set_data (watch, wd, dbus_free);
43 }
44
45 static void
46 remove_connection_watch (DBusWatch      *watch,
47                          DBusConnection *connection)
48 {
49   _dbus_list_remove (&watches, watch);
50   dbus_watch_set_data (watch, NULL, NULL);
51 }
52
53 static void
54 add_server_watch (DBusWatch      *watch,
55                   DBusServer     *server)
56 {
57   WatchData *wd;
58   
59   wd = dbus_new0 (WatchData, 1);
60   wd->type = WATCH_SERVER;
61   wd->data = server;
62   
63   _dbus_list_append (&watches, watch);
64
65   dbus_watch_set_data (watch, wd, dbus_free);
66 }
67
68 static void
69 remove_server_watch (DBusWatch      *watch,
70                      DBusServer     *server)
71 {
72   _dbus_list_remove (&watches, watch);
73   dbus_watch_set_data (watch, NULL, NULL);
74 }
75
76 static int count = 0;
77
78 static void
79 check_messages (void)
80 {
81   DBusList *link;
82   
83   link = _dbus_list_get_first_link (&connections);
84   while (link != NULL)
85     {
86       DBusList *next = _dbus_list_get_next_link (&connections, link);
87       DBusConnection *connection = link->data;
88       DBusMessage *message;
89       
90       while ((message = dbus_connection_pop_message (connection)))
91         {
92           DBusMessage *reply;
93
94           printf ("Received message %d, sending reply\n", count);
95           
96           reply = dbus_message_new ();
97           dbus_connection_send_message (connection,
98                                         reply,
99                                         NULL);
100           dbus_message_unref (reply);
101
102           dbus_message_unref (message);
103
104           count += 1;
105           if (count > 100)
106             {
107               printf ("Saw %d messages, exiting\n", count);
108               quit_mainloop ();
109             }
110         }
111       
112       link = next;
113     }
114 }
115
116 void
117 do_mainloop (void)
118 {
119   /* Of course with any real app you'd use GMainLoop or
120    * QSocketNotifier and not have to see all this crap.
121    */
122   
123   while (!exited && watches != NULL)
124     {
125       fd_set read_set;
126       fd_set write_set;
127       fd_set err_set;
128       int max_fd;
129       DBusList *link;
130
131       check_messages ();
132       
133       FD_ZERO (&read_set);
134       FD_ZERO (&write_set);
135       FD_ZERO (&err_set);
136
137       max_fd = -1;
138
139       link = _dbus_list_get_first_link (&watches);
140       while (link != NULL)
141         {
142           DBusList *next = _dbus_list_get_next_link (&watches, link);
143           int fd;
144           DBusWatch *watch;
145           unsigned int flags;
146           
147           watch = link->data;
148           
149           fd = dbus_watch_get_fd (watch);
150           flags = dbus_watch_get_flags (watch);
151           
152           max_fd = MAX (max_fd, fd);
153           
154           if (flags & DBUS_WATCH_READABLE)
155             FD_SET (fd, &read_set);
156
157           if (flags & DBUS_WATCH_WRITABLE)
158             FD_SET (fd, &write_set);
159
160           FD_SET (fd, &err_set);
161           
162           link = next;
163         }
164
165       select (max_fd + 1, &read_set, &write_set, &err_set, NULL);
166
167       link = _dbus_list_get_first_link (&watches);
168       while (link != NULL)
169         {
170           DBusList *next = _dbus_list_get_next_link (&watches, link);
171           int fd;
172           DBusWatch *watch;
173           unsigned int flags;
174           unsigned int condition;
175           
176           watch = link->data;
177           
178           fd = dbus_watch_get_fd (watch);
179           flags = dbus_watch_get_flags (watch);
180
181           condition = 0;
182           
183           if ((flags & DBUS_WATCH_READABLE) &&
184               FD_ISSET (fd, &read_set))
185             condition |= DBUS_WATCH_READABLE;
186
187           if ((flags & DBUS_WATCH_WRITABLE) &&
188               FD_ISSET (fd, &write_set))
189             condition |= DBUS_WATCH_WRITABLE;
190
191           if (FD_ISSET (fd, &err_set))
192             condition |= DBUS_WATCH_ERROR;
193
194           if (condition != 0)
195             {
196               WatchData *wd;
197
198               wd = dbus_watch_get_data (watch);
199
200               if (wd->type == WATCH_CONNECTION)
201                 {
202                   DBusConnection *connection = wd->data;
203
204                   dbus_connection_handle_watch (connection,
205                                                 watch,
206                                                 condition);
207                 }
208               else if (wd->type == WATCH_SERVER)
209                 {
210                   DBusServer *server = wd->data;
211                   
212                   dbus_server_handle_watch (server,
213                                             watch,
214                                             condition);
215                 }
216             }
217           
218           link = next;
219         }
220     }
221 }
222
223 void
224 quit_mainloop (void)
225 {
226   exited = TRUE;
227 }
228
229 static void
230 error_handler (DBusConnection *connection,
231                DBusResultCode  error_code,
232                void           *data)
233 {
234   fprintf (stderr,
235            "Error on connection: %s\n",
236            dbus_result_to_string (error_code));
237
238   _dbus_list_remove (&connections, connection);
239   dbus_connection_unref (connection);
240   quit_mainloop ();
241 }
242
243 void
244 setup_connection (DBusConnection *connection)
245 {
246   dbus_connection_set_watch_functions (connection,
247                                        (DBusAddWatchFunction) add_connection_watch,
248                                        (DBusRemoveWatchFunction) remove_connection_watch,
249                                        connection,
250                                        NULL);
251
252   dbus_connection_set_error_function (connection,
253                                       error_handler,
254                                       NULL, NULL);
255
256   dbus_connection_ref (connection);
257   _dbus_list_append (&connections, connection);
258 }
259
260 void
261 setup_server (DBusServer *server)
262 {
263   dbus_server_set_watch_functions (server,
264                                    (DBusAddWatchFunction) add_server_watch,
265                                    (DBusRemoveWatchFunction) remove_server_watch,
266                                    server,
267                                    NULL);
268 }