~bregma/geis/lp-785321

« back to all changes in this revision

Viewing changes to libutouch-geis/backend/dbus/geis_dbus_client.c

  • Committer: Stephen M. Webb
  • Date: 2011-10-18 20:30:02 UTC
  • mfrom: (158.1.42 client-arch)
  • Revision ID: stephen.webb@canonical.com-20111018203002-ne8h3n25fbey3fqr
Merged client-arch branch.

Provided a new DBus-client back end and a dbus-server facility.  Included a test driver for the server.  Made the DBus client the default back-end with an automatic fall back to the XCB back end for seamless support of existing client software.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file geis_dbus_client.c
 
3
 * @brief Implementations of the GEIS DBus client.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright 2011 Canonical Ltd.
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or modify it under
 
10
 * the terms of the GNU Lesser General Public License as published by the Free
 
11
 * Software Foundation; either version 3 of the License, or (at your option) any
 
12
 * later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful, but WITHOUT
 
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
16
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 
17
 * details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
 */
 
22
#include "geis_config.h"
 
23
#include "geis_dbus_client.h"
 
24
 
 
25
#include "geis_dbus.h"
 
26
#include "geis_dbus_class.h"
 
27
#include "geis_dbus_device.h"
 
28
#include "geis_dbus_gesture_event.h"
 
29
#include "geis_dbus_locator.h"
 
30
#include "geis_dbus_region.h"
 
31
#include "geis_dbus_subscription.h"
 
32
#include "geis_event.h"
 
33
#include "geis_logging.h"
 
34
#include "geis_private.h"
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
 
 
38
 
 
39
typedef enum GeisDBusClientState
 
40
{
 
41
  GEIS_DBUS_CLIENT_DISCONNECTED,   /* no server available */
 
42
  GEIS_DBUS_CLIENT_INITIALIZING,   /* server connected, client initializing */
 
43
  GEIS_DBUS_CLIENT_CONNECTING,     /* server connected, not initialized */
 
44
  GEIS_DBUS_CLIENT_CONNECTED       /* server connected, all systems go */
 
45
} GeisDBusClientState;
 
46
 
 
47
 
 
48
struct GeisDBusClient
 
49
{
 
50
  Geis                geis;
 
51
  GeisDBusDispatcher  dispatcher;
 
52
  GeisDBusLocator     locator;
 
53
  GeisDBusClientState state;
 
54
  DBusConnection     *connection;
 
55
  GeisSubBag          subscription_bag;
 
56
};
 
57
 
 
58
 
 
59
/**
 
60
 * Handles a device-available message from the server.
 
61
 *
 
62
 * @param[in] client  A %GeisDBusClient.
 
63
 * @param[in] message The %DBusMessage.
 
64
 */
 
65
static void
 
66
_client_device_available(GeisDBusClient client, DBusMessage *message)
 
67
{
 
68
  GeisDevice device = geis_dbus_device_device_from_available_message(message);
 
69
  if (device)
 
70
  {
 
71
    geis_register_device(client->geis, device, 0, NULL);
 
72
  }
 
73
  else
 
74
  {
 
75
    geis_error("no device received from remote back end");
 
76
  }
 
77
}
 
78
 
 
79
 
 
80
/**
 
81
 * Handles a device-unavailable message from the server.
 
82
 *
 
83
 * @param[in] client  A %GeisDBusClient.
 
84
 * @param[in] message The %DBusMessage.
 
85
 */
 
86
static void
 
87
_client_device_unavailable(GeisDBusClient client, DBusMessage *message)
 
88
{
 
89
  GeisDevice device = geis_dbus_device_device_from_unavailable_message(message);
 
90
  if (device)
 
91
  {
 
92
    geis_unregister_device(client->geis, device);
 
93
  }
 
94
  else
 
95
  {
 
96
    geis_error("no device received from remote back end");
 
97
  }
 
98
}
 
99
 
 
100
 
 
101
/**
 
102
 * Handles a class-available message from the server.
 
103
 *
 
104
 * @param[in] client  A %GeisDBusClient.
 
105
 * @param[in] message The %DBusMessage.
 
106
 */
 
107
static void
 
108
_client_class_available(GeisDBusClient client, DBusMessage *message)
 
109
{
 
110
  GeisGestureClass gesture_class;
 
111
 
 
112
  gesture_class = geis_dbus_class_class_from_available_message(message);
 
113
  if (gesture_class)
 
114
  {
 
115
    geis_register_gesture_class(client->geis, gesture_class, 0, NULL);
 
116
  }
 
117
  else
 
118
  {
 
119
    geis_error("no gesture class received from remote back end");
 
120
  }
 
121
}
 
122
 
 
123
 
 
124
/**
 
125
 * Handles a region-available message from the server.
 
126
 *
 
127
 * @param[in] client  A %GeisDBusClient.
 
128
 * @param[in] message The %DBusMessage.
 
129
 */
 
130
static void
 
131
_client_region_available(GeisDBusClient client, DBusMessage *message)
 
132
{
 
133
  GeisFilterableAttribute attr;
 
134
 
 
135
  attr = geis_dbus_region_from_region_available_message(message);
 
136
  if (attr)
 
137
  {
 
138
    attr->add_term_callback = 0;
 
139
    attr->add_term_context = 0;
 
140
    geis_register_region(client->geis, NULL, 1, attr);
 
141
  }
 
142
  else
 
143
  {
 
144
    geis_error("no region attr received from remote back end");
 
145
  }
 
146
}
 
147
 
 
148
 
 
149
/**
 
150
 * Handles a class-unavailable message from the server.
 
151
 *
 
152
 * @param[in] client  A %GeisDBusClient.
 
153
 * @param[in] message The %DBusMessage.
 
154
 */
 
155
static void
 
156
_client_gesture_event(GeisDBusClient client, DBusMessage *message)
 
157
{
 
158
  GeisEvent event = geis_dbus_gesture_event_from_message(client->geis, message);
 
159
  if (!event)
 
160
  {
 
161
    geis_error("no gesture event received from remote back end");
 
162
  }
 
163
  else
 
164
  {
 
165
    geis_post_event(client->geis, event);
 
166
  }
 
167
}
 
168
 
 
169
 
 
170
/**
 
171
 * Processes an subscription-activate reply from the server.
 
172
 *
 
173
 * @param[in] pending    A DBusPendingCall object.
 
174
 * @param[in] user_data  The %GeisDBusClient object.
 
175
 */
 
176
static void
 
177
_geis_dbus_client_activate_reply(DBusPendingCall *pending, void *user_data)
 
178
{
 
179
  GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data;
 
180
  DBusMessage *reply = dbus_pending_call_steal_reply(pending);
 
181
 
 
182
  if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
 
183
  {
 
184
    const char *s = NULL;
 
185
    dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
 
186
    geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
 
187
  }
 
188
}
 
189
 
 
190
 
 
191
/**
 
192
 * Processes a subscription-create reply from the server.
 
193
 *
 
194
 * @param[in] pending    A DBusPendingCall object.
 
195
 * @param[in] user_data  The %GeisDBusClient object.
 
196
 */
 
197
static void
 
198
_geis_dbus_client_subscribe_reply(DBusPendingCall *pending, void *user_data)
 
199
{
 
200
  GeisDBusClient client = (GeisDBusClient)user_data;
 
201
  DBusMessage *reply = dbus_pending_call_steal_reply(pending);
 
202
 
 
203
  if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
 
204
  {
 
205
    const char *s = NULL;
 
206
    dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
 
207
    geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
 
208
  }
 
209
  else
 
210
  {
 
211
    DBusMessage *msg;
 
212
    DBusPendingCall *pending;
 
213
    DBusError error = DBUS_ERROR_INIT;
 
214
    dbus_int32_t client_sub_id;
 
215
    dbus_int32_t server_sub_id;
 
216
    GeisSubscription subscription;
 
217
 
 
218
    dbus_message_get_args(reply,
 
219
                          &error,
 
220
                          DBUS_TYPE_INT32, &client_sub_id,
 
221
                          DBUS_TYPE_INT32, &server_sub_id,
 
222
                          DBUS_TYPE_INVALID);
 
223
    if (dbus_error_is_set(&error))
 
224
    {
 
225
      geis_error("error %s: %s", error.name, error.message);
 
226
      dbus_error_free(&error);
 
227
    }
 
228
 
 
229
    subscription = geis_subscription_bag_find(client->subscription_bag,
 
230
                                              client_sub_id);
 
231
    if (!subscription)
 
232
    {
 
233
      geis_error("invalid client subcription id %d returned from server",
 
234
                 client_sub_id);
 
235
    }
 
236
    else
 
237
    {
 
238
      geis_subscription_set_pdata(subscription, (GeisPointer)(intptr_t)server_sub_id);
 
239
 
 
240
      msg = geis_dbus_subscription_activate_call_message(subscription);
 
241
      dbus_connection_send_with_reply(client->connection, msg, &pending, -1);
 
242
      dbus_message_unref(msg);
 
243
      if (!pending)
 
244
      {
 
245
        geis_error("error sending DBus CreateSubscription method call");
 
246
      }
 
247
      else
 
248
      {
 
249
        dbus_pending_call_set_notify(pending,
 
250
                                     _geis_dbus_client_activate_reply,
 
251
                                     client, 0);
 
252
      }
 
253
    }
 
254
  }
 
255
 
 
256
  dbus_message_unref(reply);
 
257
  dbus_pending_call_unref(pending);
 
258
}
 
259
 
 
260
 
 
261
/**
 
262
 * Processes a deactivate-subscription reply from the server.
 
263
 *
 
264
 * @param[in] pending    A DBusPendingCall object.
 
265
 * @param[in] user_data  The %GeisDBusClient object.
 
266
 */
 
267
static void
 
268
_geis_dbus_client_unsubscribe_reply(DBusPendingCall *pending, void *user_data)
 
269
{
 
270
  GeisDBusClient client GEIS_UNUSED = (GeisDBusClient)user_data;
 
271
  DBusMessage *reply = dbus_pending_call_steal_reply(pending);
 
272
 
 
273
  if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(reply))
 
274
  {
 
275
    const char *s = NULL;
 
276
    dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID);
 
277
    geis_error("error %s: %s", dbus_message_get_error_name(reply), s);
 
278
  }
 
279
  else
 
280
  {
 
281
    geis_warning("signature=\"%s\"", dbus_message_get_signature(reply));
 
282
    geis_warning("path=\"%s\"", dbus_message_get_path(reply));
 
283
    geis_warning("interface=\"%s\"", dbus_message_get_interface(reply));
 
284
    geis_warning("member=\"%s\"", dbus_message_get_member(reply));
 
285
  }
 
286
 
 
287
  dbus_message_unref(reply);
 
288
  dbus_pending_call_unref(pending);
 
289
}
 
290
 
 
291
 
 
292
/**
 
293
 * Creates a remote subscription.
 
294
 */
 
295
void
 
296
_dbus_client_subscribe(GeisDBusClient   client,
 
297
                       GeisSubscription subscription)
 
298
{
 
299
  DBusPendingCall *pending_return;
 
300
 
 
301
  GeisSubscription sub = geis_subscription_bag_find(client->subscription_bag,
 
302
                                 geis_subscription_id(subscription));
 
303
  if (sub && geis_subscription_pdata(sub))
 
304
  {
 
305
    geis_warning("subscription already activated!");
 
306
  }
 
307
  else
 
308
  {
 
309
    DBusMessage *msg = geis_dbus_subscription_create_call_message(subscription);
 
310
    dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1);
 
311
    dbus_message_unref(msg);
 
312
    if (!pending_return)
 
313
    {
 
314
      geis_error("error sending DBus CreateSubscription method call");
 
315
    }
 
316
    else
 
317
    {
 
318
      dbus_pending_call_set_notify(pending_return,
 
319
                                   _geis_dbus_client_subscribe_reply,
 
320
                                   client, 0);
 
321
    }
 
322
  }
 
323
}
 
324
 
 
325
 
 
326
/**
 
327
 * Re-subscribes all existing sibscriptions when the server appears or
 
328
 * reappears.
 
329
 */
 
330
void
 
331
_dbus_client_resubscribe_all(GeisDBusClient client)
 
332
{
 
333
  GeisSubBagIterator it;
 
334
  for (it = geis_subscription_bag_begin(client->subscription_bag);
 
335
       it != geis_subscription_bag_end(client->subscription_bag);
 
336
       it = geis_subscription_bag_iterator_next(client->subscription_bag, it))
 
337
  {
 
338
    geis_subscription_set_pdata(*it, 0);
 
339
    _dbus_client_subscribe(client, *it);
 
340
  }
 
341
}
 
342
 
 
343
 
 
344
/**
 
345
 * The DBus message dispatch function for the GEIS DBus client.
 
346
 *
 
347
 * @param[in] connection  The %GeisDBusClient DBus connection.
 
348
 * @param[in] message     The DBus message received.
 
349
 * @param[in] user_data   The %GeisDBusClient.
 
350
 */
 
351
static DBusHandlerResult
 
352
_geis_dbus_client_message_handler(DBusConnection *connection GEIS_UNUSED,
 
353
                                  DBusMessage    *message,
 
354
                                  void           *user_data)
 
355
{
 
356
  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
357
  GeisDBusClient client = (GeisDBusClient)user_data;
 
358
  int type = dbus_message_get_type(message);
 
359
 
 
360
  if (dbus_message_is_signal(message,
 
361
                             DBUS_INTERFACE_LOCAL,
 
362
                             "Disconnected"))
 
363
  {
 
364
    geis_warning("server disconnected?");
 
365
    result = DBUS_HANDLER_RESULT_HANDLED;
 
366
  }
 
367
  else if (dbus_message_is_signal(message,
 
368
                                  GEIS_DBUS_SERVICE_INTERFACE,
 
369
                                  GEIS_DBUS_DEVICE_AVAILABLE))
 
370
  {
 
371
    _client_device_available(client, message);
 
372
    result = DBUS_HANDLER_RESULT_HANDLED;
 
373
  }
 
374
  else if (dbus_message_is_signal(message,
 
375
                                  GEIS_DBUS_SERVICE_INTERFACE,
 
376
                                  GEIS_DBUS_DEVICE_UNAVAILABLE))
 
377
 
 
378
  {
 
379
    _client_device_unavailable(client, message);
 
380
    result = DBUS_HANDLER_RESULT_HANDLED;
 
381
  }
 
382
  else if (dbus_message_is_signal(message,
 
383
                                  GEIS_DBUS_SERVICE_INTERFACE,
 
384
                                  GEIS_DBUS_CLASS_AVAILABLE))
 
385
  {
 
386
    _client_class_available(client, message);
 
387
    result = DBUS_HANDLER_RESULT_HANDLED;
 
388
  }
 
389
  else if (dbus_message_is_signal(message,
 
390
                                  GEIS_DBUS_SERVICE_INTERFACE,
 
391
                                  GEIS_DBUS_REGION_AVAILABLE))
 
392
  {
 
393
    _client_region_available(client, message);
 
394
    result = DBUS_HANDLER_RESULT_HANDLED;
 
395
  }
 
396
  else if (dbus_message_is_signal(message,
 
397
                                  GEIS_DBUS_SERVICE_INTERFACE,
 
398
                                  GEIS_DBUS_INIT_COMPLETE))
 
399
  {
 
400
    if (client->state == GEIS_DBUS_CLIENT_INITIALIZING)
 
401
    {
 
402
      geis_post_event(client->geis, geis_event_new(GEIS_EVENT_INIT_COMPLETE));
 
403
    }
 
404
    client->state = GEIS_DBUS_CLIENT_CONNECTED;
 
405
    _dbus_client_resubscribe_all(client);
 
406
    result = DBUS_HANDLER_RESULT_HANDLED;
 
407
  }
 
408
  else if (geis_dbus_message_is_gesture_event(message))
 
409
  {
 
410
    _client_gesture_event(client, message);
 
411
    result = DBUS_HANDLER_RESULT_HANDLED;
 
412
  }
 
413
  else if (type == DBUS_MESSAGE_TYPE_ERROR)
 
414
  {
 
415
    const char *str = NULL;
 
416
    dbus_message_get_args(message, NULL,
 
417
                          DBUS_TYPE_STRING, &str,
 
418
                          DBUS_TYPE_INVALID);
 
419
    geis_warning("error %s: %s", dbus_message_get_error_name(message), str);
 
420
  }
 
421
  else 
 
422
  {
 
423
    geis_warning("unhandled DBus %s received:",
 
424
                 dbus_message_type_to_string(dbus_message_get_type(message)));
 
425
    geis_warning("  signature=\"%s\"", dbus_message_get_signature(message));
 
426
    geis_warning("  sender=\"%s\"", dbus_message_get_sender(message));
 
427
    geis_warning("  path=\"%s\"",
 
428
                 dbus_message_get_path(message) ?
 
429
                 dbus_message_get_path(message) :
 
430
                 "(no path)");
 
431
    geis_warning("  interface=\"%s\"",
 
432
                 dbus_message_get_interface(message) ?
 
433
                 dbus_message_get_interface(message) :
 
434
                 "(no interface)");
 
435
    geis_warning("  member=\"%s\"",
 
436
                 dbus_message_get_member(message) ?
 
437
                 dbus_message_get_member(message) :
 
438
                 "(no member)");
 
439
  }
 
440
  return result;
 
441
}
 
442
 
 
443
 
 
444
/**
 
445
 * Adds the client watches to the dispatcher watch list.
 
446
 *
 
447
 * @param[in] watch  A %DBusWatch.
 
448
 * @param[in] data   The %GeisDBusClientProxy.
 
449
 */
 
450
static dbus_bool_t
 
451
_client_add_watch(DBusWatch *watch, void *data)
 
452
{
 
453
  dbus_bool_t status = TRUE;
 
454
  GeisDBusClient client = (GeisDBusClient)data;
 
455
 
 
456
  geis_dbus_dispatcher_register(client->dispatcher, client->connection, watch);
 
457
  return status;
 
458
}
 
459
 
 
460
 
 
461
/**
 
462
 * Toggles the enabled/disabled status of the client watches.
 
463
 *
 
464
 * @param[in] watch  A %DBusWatch.
 
465
 * @param[in] data   The %GeisDBusClientProxy.
 
466
 */
 
467
static void
 
468
_client_toggle_watch(DBusWatch *watch, void *data)
 
469
{
 
470
  GeisDBusClient client = (GeisDBusClient)data;
 
471
 
 
472
  geis_dbus_dispatcher_toggle_watch(client->dispatcher, watch);
 
473
}
 
474
 
 
475
 
 
476
/**
 
477
 * Removes the client watches from the dispatcher watch list.
 
478
 *
 
479
 * @param[in] watch  A %DBusWatch.
 
480
 * @param[in] data   The %GeisDBusClientProxy.
 
481
 */
 
482
static void
 
483
_client_remove_watch(DBusWatch *watch, void *data)
 
484
{
 
485
  GeisDBusClient client = (GeisDBusClient)data;
 
486
 
 
487
  geis_dbus_dispatcher_unregister(client->dispatcher, watch);
 
488
}
 
489
 
 
490
 
 
491
/**
 
492
 * Connects to the GEIS server once an address is located.
 
493
 *
 
494
 * @param[in] client  A %GeisDBusClient object.
 
495
 * @param[in] address The address of the server.
 
496
 */
 
497
static void
 
498
_client_connect(GeisDBusClient client, const char *address)
 
499
{
 
500
  geis_debug("server address=\"%s\"", address);
 
501
  DBusError error = DBUS_ERROR_INIT;
 
502
  client->connection = dbus_connection_open(address, &error);
 
503
  if (!client->connection || dbus_error_is_set(&error))
 
504
  {
 
505
    char msg[512];
 
506
    snprintf(msg, sizeof(msg), "error %s connecting to server at address %s: %s",
 
507
            error.name, address, error.message);
 
508
    geis_error("%s", msg);
 
509
    dbus_error_free(&error);
 
510
    goto final_exit;
 
511
  }
 
512
 
 
513
  /* Integrate with the app event loop via the GEIS multiplexor. */
 
514
  dbus_connection_set_watch_functions(client->connection,
 
515
                                      _client_add_watch,
 
516
                                      _client_remove_watch,
 
517
                                      _client_toggle_watch,
 
518
                                      client, 0);
 
519
 
 
520
  /* Install a handler for any and all messages. */
 
521
  dbus_connection_add_filter(client->connection,
 
522
                             _geis_dbus_client_message_handler,
 
523
                             client, 0);
 
524
  if (client->state != GEIS_DBUS_CLIENT_INITIALIZING)
 
525
  {
 
526
    client->state = GEIS_DBUS_CLIENT_CONNECTING;
 
527
  }
 
528
 
 
529
final_exit:
 
530
  return;
 
531
}
 
532
 
 
533
 
 
534
/*
 
535
 * Creates a new GeisDBusClient.
 
536
 */
 
537
GeisDBusClient
 
538
geis_dbus_client_new(Geis geis)
 
539
{
 
540
  GeisDBusClient client = calloc(1, sizeof(struct GeisDBusClient));
 
541
  if (!client)
 
542
  {
 
543
    goto final_exit;
 
544
  }
 
545
 
 
546
  client->geis = geis;
 
547
  client->state = GEIS_DBUS_CLIENT_INITIALIZING;
 
548
 
 
549
  client->dispatcher = geis_dbus_dispatcher_new(geis);
 
550
  if (!client->dispatcher)
 
551
  {
 
552
    goto unwind_client;
 
553
  }
 
554
 
 
555
  client->locator = geis_dbus_locator_new(client);
 
556
  if (!client->locator)
 
557
  {
 
558
    goto unwind_dispatcher;
 
559
  }
 
560
 
 
561
  client->subscription_bag = geis_subscription_bag_new(1);
 
562
  if (!client->subscription_bag)
 
563
  {
 
564
    goto unwind_locator;
 
565
  }
 
566
 
 
567
  goto final_exit;
 
568
 
 
569
unwind_locator:
 
570
  geis_dbus_locator_delete(client->locator);
 
571
unwind_dispatcher:
 
572
  geis_dbus_dispatcher_delete(client->dispatcher);
 
573
unwind_client:
 
574
  free(client);
 
575
  client = NULL;
 
576
final_exit:
 
577
  return client;
 
578
}
 
579
 
 
580
 
 
581
/*
 
582
 * Destroys a GeisDBusClient.
 
583
 */
 
584
void
 
585
geis_dbus_client_delete(GeisDBusClient client)
 
586
{
 
587
  geis_subscription_bag_delete(client->subscription_bag);
 
588
  geis_dbus_locator_delete(client->locator);
 
589
  if (client->connection)
 
590
  {
 
591
    dbus_connection_unref(client->connection);
 
592
  }
 
593
  geis_dbus_dispatcher_delete(client->dispatcher);
 
594
  free(client);
 
595
}
 
596
 
 
597
 
 
598
/*
 
599
 * Gets the client dispatcher.
 
600
 */
 
601
GeisDBusDispatcher
 
602
geis_dbus_client_dispatcher(GeisDBusClient client)
 
603
{
 
604
  return client->dispatcher;
 
605
}
 
606
 
 
607
 
 
608
/*
 
609
 * Signals the client the server has been located.
 
610
 */
 
611
void
 
612
geis_dbus_client_server_located(GeisDBusClient client)
 
613
{
 
614
  _client_connect(client, geis_dbus_locator_server_address(client->locator));
 
615
}
 
616
 
 
617
 
 
618
/*
 
619
 * Signals the client the server has been dislocated.
 
620
 */
 
621
void
 
622
geis_dbus_client_server_dislocated(GeisDBusClient client)
 
623
{
 
624
  GeisEvent event =  geis_event_new(GEIS_EVENT_ERROR);
 
625
  client->state = GEIS_DBUS_CLIENT_DISCONNECTED;
 
626
  geis_post_event(client->geis, event);
 
627
}
 
628
 
 
629
 
 
630
/*
 
631
 * Requests a subscription on the remote end.
 
632
 */
 
633
GeisStatus
 
634
geis_dbus_client_subscribe(GeisDBusClient   client,
 
635
                           GeisSubscription subscription)
 
636
{
 
637
  GeisStatus status = GEIS_STATUS_SUCCESS;
 
638
 
 
639
  if (client->state == GEIS_DBUS_CLIENT_CONNECTED)
 
640
  {
 
641
    _dbus_client_subscribe(client, subscription);
 
642
  }
 
643
  geis_subscription_bag_insert(client->subscription_bag, subscription);
 
644
 
 
645
  return status;
 
646
}
 
647
 
 
648
 
 
649
/*
 
650
 * Destroys a subscription on the remote end.
 
651
 */
 
652
GeisStatus
 
653
geis_dbus_client_unsubscribe(GeisDBusClient   client,
 
654
                             GeisSubscription subscription)
 
655
{
 
656
  GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
 
657
  if (geis_subscription_bag_find(client->subscription_bag,
 
658
                                 geis_subscription_id(subscription)))
 
659
  {
 
660
    DBusMessage *msg;
 
661
    DBusPendingCall *pending_return;
 
662
 
 
663
    msg = geis_dbus_subscription_destroy_call_message(subscription);
 
664
    dbus_connection_send_with_reply(client->connection, msg, &pending_return, -1);
 
665
    dbus_message_unref(msg);
 
666
    if (!pending_return)
 
667
    {
 
668
      geis_error("error sending DBus CreateSubscription method call");
 
669
      goto final_exit;
 
670
    }
 
671
 
 
672
    dbus_pending_call_set_notify(pending_return,
 
673
                                 _geis_dbus_client_unsubscribe_reply,
 
674
                                 client, 0);
 
675
    geis_subscription_bag_remove(client->subscription_bag, subscription);
 
676
    status = GEIS_STATUS_SUCCESS;
 
677
  }
 
678
 
 
679
final_exit:
 
680
  return status;
 
681
}
 
682
 
 
683
 
 
684
 
 
685