00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "connection.h"
00024 #include "dispatch.h"
00025 #include "policy.h"
00026 #include "services.h"
00027 #include "utils.h"
00028 #include <dbus/dbus-list.h>
00029 #include <dbus/dbus-hash.h>
00030 #include <dbus/dbus-timeout.h>
00031
00032 static void bus_connection_remove_transactions (DBusConnection *connection);
00033
00034 struct BusConnections
00035 {
00036 int refcount;
00037 DBusList *completed;
00038 int n_completed;
00039 DBusList *incomplete;
00040 int n_incomplete;
00041 BusContext *context;
00042 DBusHashTable *completed_by_user;
00043 DBusTimeout *expire_timeout;
00044 };
00045
00046 static dbus_int32_t connection_data_slot = -1;
00047
00048 typedef struct
00049 {
00050 BusConnections *connections;
00051 DBusList *link_in_connection_list;
00052 DBusConnection *connection;
00053 DBusList *services_owned;
00054 int n_services_owned;
00055 char *name;
00056 DBusList *transaction_messages;
00057 DBusMessage *oom_message;
00058 DBusPreallocatedSend *oom_preallocated;
00059 BusClientPolicy *policy;
00060
00061 long connection_tv_sec;
00062 long connection_tv_usec;
00063 } BusConnectionData;
00064
00065 static dbus_bool_t expire_incomplete_timeout (void *data);
00066
00067 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
00068
00069 static DBusLoop*
00070 connection_get_loop (DBusConnection *connection)
00071 {
00072 BusConnectionData *d;
00073
00074 d = BUS_CONNECTION_DATA (connection);
00075
00076 return bus_context_get_loop (d->connections->context);
00077 }
00078
00079
00080 static int
00081 get_connections_for_uid (BusConnections *connections,
00082 dbus_uid_t uid)
00083 {
00084 void *val;
00085 int current_count;
00086
00087
00088
00089 val = _dbus_hash_table_lookup_ulong (connections->completed_by_user,
00090 uid);
00091
00092 current_count = _DBUS_POINTER_TO_INT (val);
00093
00094 return current_count;
00095 }
00096
00097 static dbus_bool_t
00098 adjust_connections_for_uid (BusConnections *connections,
00099 dbus_uid_t uid,
00100 int adjustment)
00101 {
00102 int current_count;
00103
00104 current_count = get_connections_for_uid (connections, uid);
00105
00106 _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
00107 ": was %d adjustment %d making %d\n",
00108 uid, current_count, adjustment, current_count + adjustment);
00109
00110 _dbus_assert (current_count >= 0);
00111
00112 current_count += adjustment;
00113
00114 _dbus_assert (current_count >= 0);
00115
00116 if (current_count == 0)
00117 {
00118 _dbus_hash_table_remove_ulong (connections->completed_by_user, uid);
00119 return TRUE;
00120 }
00121 else
00122 {
00123 dbus_bool_t retval;
00124
00125 retval = _dbus_hash_table_insert_ulong (connections->completed_by_user,
00126 uid, _DBUS_INT_TO_POINTER (current_count));
00127
00128
00129
00130
00131 _dbus_assert (adjustment > 0 ||
00132 (adjustment <= 0 && retval));
00133
00134 return retval;
00135 }
00136 }
00137
00138 void
00139 bus_connection_disconnected (DBusConnection *connection)
00140 {
00141 BusConnectionData *d;
00142 BusService *service;
00143
00144 d = BUS_CONNECTION_DATA (connection);
00145 _dbus_assert (d != NULL);
00146
00147 _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
00148 d->name ? d->name : "(inactive)");
00149
00150
00151
00152
00153
00154
00155
00156
00157 while ((service = _dbus_list_get_last (&d->services_owned)))
00158 {
00159 BusTransaction *transaction;
00160 DBusError error;
00161
00162 retry:
00163
00164 dbus_error_init (&error);
00165
00166 transaction = NULL;
00167 while (transaction == NULL)
00168 {
00169 transaction = bus_transaction_new (d->connections->context);
00170 _dbus_wait_for_memory ();
00171 }
00172
00173 if (!bus_service_remove_owner (service, connection,
00174 transaction, &error))
00175 {
00176 _DBUS_ASSERT_ERROR_IS_SET (&error);
00177
00178 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00179 {
00180 dbus_error_free (&error);
00181 bus_transaction_cancel_and_free (transaction);
00182 _dbus_wait_for_memory ();
00183 goto retry;
00184 }
00185 else
00186 {
00187 _dbus_verbose ("Failed to remove service owner: %s %s\n",
00188 error.name, error.message);
00189 _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
00190 }
00191 }
00192
00193 bus_transaction_execute_and_free (transaction);
00194 }
00195
00196 bus_dispatch_remove_connection (connection);
00197
00198
00199 if (!dbus_connection_set_watch_functions (connection,
00200 NULL, NULL, NULL,
00201 connection,
00202 NULL))
00203 _dbus_assert_not_reached ("setting watch functions to NULL failed");
00204
00205 if (!dbus_connection_set_timeout_functions (connection,
00206 NULL, NULL, NULL,
00207 connection,
00208 NULL))
00209 _dbus_assert_not_reached ("setting timeout functions to NULL failed");
00210
00211 dbus_connection_set_unix_user_function (connection,
00212 NULL, NULL, NULL);
00213
00214 dbus_connection_set_dispatch_status_function (connection,
00215 NULL, NULL, NULL);
00216
00217 bus_connection_remove_transactions (connection);
00218
00219 if (d->link_in_connection_list != NULL)
00220 {
00221 if (d->name != NULL)
00222 {
00223 unsigned long uid;
00224
00225 _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
00226 d->link_in_connection_list = NULL;
00227 d->connections->n_completed -= 1;
00228
00229 if (dbus_connection_get_unix_user (connection, &uid))
00230 {
00231 if (!adjust_connections_for_uid (d->connections,
00232 uid, -1))
00233 _dbus_assert_not_reached ("adjusting downward should never fail");
00234 }
00235 }
00236 else
00237 {
00238 _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
00239 d->link_in_connection_list = NULL;
00240 d->connections->n_incomplete -= 1;
00241 }
00242
00243 _dbus_assert (d->connections->n_incomplete >= 0);
00244 _dbus_assert (d->connections->n_completed >= 0);
00245 }
00246
00247
00248 dbus_connection_set_data (connection,
00249 connection_data_slot,
00250 NULL, NULL);
00251
00252 dbus_connection_unref (connection);
00253 }
00254
00255 static dbus_bool_t
00256 connection_watch_callback (DBusWatch *watch,
00257 unsigned int condition,
00258 void *data)
00259 {
00260
00261
00262
00263
00264
00265 #if 0
00266 _dbus_verbose ("Calling handle_watch\n");
00267 #endif
00268 return dbus_watch_handle (watch, condition);
00269 }
00270
00271 static dbus_bool_t
00272 add_connection_watch (DBusWatch *watch,
00273 void *data)
00274 {
00275 DBusConnection *connection = data;
00276
00277 return _dbus_loop_add_watch (connection_get_loop (connection),
00278 watch, connection_watch_callback, connection,
00279 NULL);
00280 }
00281
00282 static void
00283 remove_connection_watch (DBusWatch *watch,
00284 void *data)
00285 {
00286 DBusConnection *connection = data;
00287
00288 _dbus_loop_remove_watch (connection_get_loop (connection),
00289 watch, connection_watch_callback, connection);
00290 }
00291
00292 static void
00293 connection_timeout_callback (DBusTimeout *timeout,
00294 void *data)
00295 {
00296
00297
00298
00299 dbus_timeout_handle (timeout);
00300 }
00301
00302 static dbus_bool_t
00303 add_connection_timeout (DBusTimeout *timeout,
00304 void *data)
00305 {
00306 DBusConnection *connection = data;
00307
00308 return _dbus_loop_add_timeout (connection_get_loop (connection),
00309 timeout, connection_timeout_callback, connection, NULL);
00310 }
00311
00312 static void
00313 remove_connection_timeout (DBusTimeout *timeout,
00314 void *data)
00315 {
00316 DBusConnection *connection = data;
00317
00318 _dbus_loop_remove_timeout (connection_get_loop (connection),
00319 timeout, connection_timeout_callback, connection);
00320 }
00321
00322 static void
00323 dispatch_status_function (DBusConnection *connection,
00324 DBusDispatchStatus new_status,
00325 void *data)
00326 {
00327 DBusLoop *loop = data;
00328
00329 if (new_status != DBUS_DISPATCH_COMPLETE)
00330 {
00331 while (!_dbus_loop_queue_dispatch (loop, connection))
00332 _dbus_wait_for_memory ();
00333 }
00334 }
00335
00336 static dbus_bool_t
00337 allow_user_function (DBusConnection *connection,
00338 unsigned long uid,
00339 void *data)
00340 {
00341 BusConnectionData *d;
00342
00343 d = BUS_CONNECTION_DATA (connection);
00344
00345 _dbus_assert (d != NULL);
00346
00347 return bus_context_allow_user (d->connections->context, uid);
00348 }
00349
00350 static void
00351 free_connection_data (void *data)
00352 {
00353 BusConnectionData *d = data;
00354
00355
00356 _dbus_assert (d->services_owned == NULL);
00357 _dbus_assert (d->n_services_owned == 0);
00358
00359 _dbus_assert (d->transaction_messages == NULL);
00360
00361 if (d->oom_preallocated)
00362 dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
00363
00364 if (d->oom_message)
00365 dbus_message_unref (d->oom_message);
00366
00367 if (d->policy)
00368 bus_client_policy_unref (d->policy);
00369
00370 dbus_free (d->name);
00371
00372 dbus_free (d);
00373 }
00374
00375 static void
00376 call_timeout_callback (DBusTimeout *timeout,
00377 void *data)
00378 {
00379
00380 dbus_timeout_handle (timeout);
00381 }
00382
00383 BusConnections*
00384 bus_connections_new (BusContext *context)
00385 {
00386 BusConnections *connections;
00387
00388 if (!dbus_connection_allocate_data_slot (&connection_data_slot))
00389 goto failed_0;
00390
00391 connections = dbus_new0 (BusConnections, 1);
00392 if (connections == NULL)
00393 goto failed_1;
00394
00395 connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
00396 NULL, NULL);
00397 if (connections->completed_by_user == NULL)
00398 goto failed_2;
00399
00400 connections->expire_timeout = _dbus_timeout_new (100,
00401 expire_incomplete_timeout,
00402 connections, NULL);
00403 if (connections->expire_timeout == NULL)
00404 goto failed_3;
00405
00406 _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
00407
00408 if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
00409 connections->expire_timeout,
00410 call_timeout_callback, NULL, NULL))
00411 goto failed_4;
00412
00413 connections->refcount = 1;
00414 connections->context = context;
00415
00416 return connections;
00417
00418 failed_4:
00419 _dbus_timeout_unref (connections->expire_timeout);
00420 failed_3:
00421 _dbus_hash_table_unref (connections->completed_by_user);
00422 failed_2:
00423 dbus_free (connections);
00424 failed_1:
00425 dbus_connection_free_data_slot (&connection_data_slot);
00426 failed_0:
00427 return NULL;
00428 }
00429
00430 void
00431 bus_connections_ref (BusConnections *connections)
00432 {
00433 _dbus_assert (connections->refcount > 0);
00434 connections->refcount += 1;
00435 }
00436
00437 void
00438 bus_connections_unref (BusConnections *connections)
00439 {
00440 _dbus_assert (connections->refcount > 0);
00441 connections->refcount -= 1;
00442 if (connections->refcount == 0)
00443 {
00444
00445 while (connections->incomplete != NULL)
00446 {
00447 DBusConnection *connection;
00448
00449 connection = connections->incomplete->data;
00450
00451 dbus_connection_ref (connection);
00452 dbus_connection_disconnect (connection);
00453 bus_connection_disconnected (connection);
00454 dbus_connection_unref (connection);
00455 }
00456
00457 _dbus_assert (connections->n_incomplete == 0);
00458
00459
00460 while (connections->completed != NULL)
00461 {
00462 DBusConnection *connection;
00463
00464 connection = connections->completed->data;
00465
00466 dbus_connection_ref (connection);
00467 dbus_connection_disconnect (connection);
00468 bus_connection_disconnected (connection);
00469 dbus_connection_unref (connection);
00470 }
00471
00472 _dbus_assert (connections->n_completed == 0);
00473
00474 _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
00475 connections->expire_timeout,
00476 call_timeout_callback, NULL);
00477
00478 _dbus_timeout_unref (connections->expire_timeout);
00479
00480 _dbus_hash_table_unref (connections->completed_by_user);
00481
00482 dbus_free (connections);
00483
00484 dbus_connection_free_data_slot (&connection_data_slot);
00485 }
00486 }
00487
00488 dbus_bool_t
00489 bus_connections_setup_connection (BusConnections *connections,
00490 DBusConnection *connection)
00491 {
00492 BusConnectionData *d;
00493 dbus_bool_t retval;
00494
00495 d = dbus_new0 (BusConnectionData, 1);
00496
00497 if (d == NULL)
00498 return FALSE;
00499
00500 d->connections = connections;
00501 d->connection = connection;
00502
00503 _dbus_get_current_time (&d->connection_tv_sec,
00504 &d->connection_tv_usec);
00505
00506 _dbus_assert (connection_data_slot >= 0);
00507
00508 if (!dbus_connection_set_data (connection,
00509 connection_data_slot,
00510 d, free_connection_data))
00511 {
00512 dbus_free (d);
00513 return FALSE;
00514 }
00515
00516 retval = FALSE;
00517
00518 if (!dbus_connection_set_watch_functions (connection,
00519 add_connection_watch,
00520 remove_connection_watch,
00521 NULL,
00522 connection,
00523 NULL))
00524 goto out;
00525
00526 if (!dbus_connection_set_timeout_functions (connection,
00527 add_connection_timeout,
00528 remove_connection_timeout,
00529 NULL,
00530 connection, NULL))
00531 goto out;
00532
00533 dbus_connection_set_unix_user_function (connection,
00534 allow_user_function,
00535 NULL, NULL);
00536
00537 dbus_connection_set_dispatch_status_function (connection,
00538 dispatch_status_function,
00539 bus_context_get_loop (connections->context),
00540 NULL);
00541
00542 d->link_in_connection_list = _dbus_list_alloc_link (connection);
00543 if (d->link_in_connection_list == NULL)
00544 goto out;
00545
00546
00547 if (!bus_dispatch_add_connection (connection))
00548 goto out;
00549
00550 if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
00551 {
00552 if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
00553 {
00554 bus_dispatch_remove_connection (connection);
00555 goto out;
00556 }
00557 }
00558
00559 _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
00560 connections->n_incomplete += 1;
00561
00562 dbus_connection_ref (connection);
00563
00564
00565
00566
00567
00568
00569 bus_connections_expire_incomplete (connections);
00570
00571
00572
00573
00574 if (connections->n_incomplete >
00575 bus_context_get_max_incomplete_connections (connections->context))
00576 {
00577 _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
00578
00579 _dbus_assert (connections->incomplete != NULL);
00580
00581
00582
00583
00584
00585
00586
00587 dbus_connection_disconnect (connections->incomplete->data);
00588 }
00589
00590 retval = TRUE;
00591
00592 out:
00593 if (!retval)
00594 {
00595 if (!dbus_connection_set_watch_functions (connection,
00596 NULL, NULL, NULL,
00597 connection,
00598 NULL))
00599 _dbus_assert_not_reached ("setting watch functions to NULL failed");
00600
00601 if (!dbus_connection_set_timeout_functions (connection,
00602 NULL, NULL, NULL,
00603 connection,
00604 NULL))
00605 _dbus_assert_not_reached ("setting timeout functions to NULL failed");
00606
00607 dbus_connection_set_unix_user_function (connection,
00608 NULL, NULL, NULL);
00609
00610 dbus_connection_set_dispatch_status_function (connection,
00611 NULL, NULL, NULL);
00612
00613 if (d->link_in_connection_list != NULL)
00614 {
00615 _dbus_assert (d->link_in_connection_list->next == NULL);
00616 _dbus_assert (d->link_in_connection_list->prev == NULL);
00617 _dbus_list_free_link (d->link_in_connection_list);
00618 d->link_in_connection_list = NULL;
00619 }
00620
00621 if (!dbus_connection_set_data (connection,
00622 connection_data_slot,
00623 NULL, NULL))
00624 _dbus_assert_not_reached ("failed to set connection data to null");
00625
00626
00627 }
00628
00629 return retval;
00630 }
00631
00632 void
00633 bus_connections_expire_incomplete (BusConnections *connections)
00634 {
00635 int next_interval;
00636
00637 next_interval = -1;
00638
00639 if (connections->incomplete != NULL)
00640 {
00641 long tv_sec, tv_usec;
00642 DBusList *link;
00643 int auth_timeout;
00644
00645 _dbus_get_current_time (&tv_sec, &tv_usec);
00646 auth_timeout = bus_context_get_auth_timeout (connections->context);
00647
00648 link = _dbus_list_get_first_link (&connections->incomplete);
00649 while (link != NULL)
00650 {
00651 DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
00652 DBusConnection *connection;
00653 BusConnectionData *d;
00654 double elapsed;
00655
00656 connection = link->data;
00657
00658 d = BUS_CONNECTION_DATA (connection);
00659
00660 _dbus_assert (d != NULL);
00661
00662 elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 +
00663 ((double) tv_usec - (double) d->connection_tv_usec) / 1000.0;
00664
00665 if (elapsed >= (double) auth_timeout)
00666 {
00667 _dbus_verbose ("Timing out authentication for connection %p\n", connection);
00668 dbus_connection_disconnect (connection);
00669 }
00670 else
00671 {
00672
00673 next_interval = ((double)auth_timeout) - elapsed;
00674 _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
00675 connection, next_interval);
00676
00677 break;
00678 }
00679
00680 link = next;
00681 }
00682 }
00683
00684 if (next_interval >= 0)
00685 {
00686 _dbus_timeout_set_interval (connections->expire_timeout,
00687 next_interval);
00688 _dbus_timeout_set_enabled (connections->expire_timeout, TRUE);
00689
00690 _dbus_verbose ("Enabled incomplete connections timeout with interval %d, %d incomplete connections\n",
00691 next_interval, connections->n_incomplete);
00692 }
00693 else if (dbus_timeout_get_enabled (connections->expire_timeout))
00694 {
00695 _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
00696
00697 _dbus_verbose ("Disabled incomplete connections timeout, %d incomplete connections\n",
00698 connections->n_incomplete);
00699 }
00700 else
00701 _dbus_verbose ("No need to disable incomplete connections timeout\n");
00702 }
00703
00704 static dbus_bool_t
00705 expire_incomplete_timeout (void *data)
00706 {
00707 BusConnections *connections = data;
00708
00709 _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME);
00710
00711
00712 bus_connections_expire_incomplete (connections);
00713
00714 return TRUE;
00715 }
00716
00717 dbus_bool_t
00718 bus_connection_get_groups (DBusConnection *connection,
00719 unsigned long **groups,
00720 int *n_groups,
00721 DBusError *error)
00722 {
00723 BusConnectionData *d;
00724 unsigned long uid;
00725 DBusUserDatabase *user_database;
00726
00727 d = BUS_CONNECTION_DATA (connection);
00728
00729 _dbus_assert (d != NULL);
00730
00731 user_database = bus_context_get_user_database (d->connections->context);
00732
00733 *groups = NULL;
00734 *n_groups = 0;
00735
00736 if (dbus_connection_get_unix_user (connection, &uid))
00737 {
00738 if (!_dbus_user_database_get_groups (user_database,
00739 uid, groups, n_groups,
00740 error))
00741 {
00742 _DBUS_ASSERT_ERROR_IS_SET (error);
00743 _dbus_verbose ("Did not get any groups for UID %lu\n",
00744 uid);
00745 return FALSE;
00746 }
00747 else
00748 {
00749 _dbus_verbose ("Got %d groups for UID %lu\n",
00750 *n_groups, uid);
00751 return TRUE;
00752 }
00753 }
00754 else
00755 return TRUE;
00756 }
00757
00758 dbus_bool_t
00759 bus_connection_is_in_group (DBusConnection *connection,
00760 unsigned long gid)
00761 {
00762 int i;
00763 unsigned long *group_ids;
00764 int n_group_ids;
00765
00766 if (!bus_connection_get_groups (connection, &group_ids, &n_group_ids,
00767 NULL))
00768 return FALSE;
00769
00770 i = 0;
00771 while (i < n_group_ids)
00772 {
00773 if (group_ids[i] == gid)
00774 {
00775 dbus_free (group_ids);
00776 return TRUE;
00777 }
00778 ++i;
00779 }
00780
00781 dbus_free (group_ids);
00782 return FALSE;
00783 }
00784
00785 BusClientPolicy*
00786 bus_connection_get_policy (DBusConnection *connection)
00787 {
00788 BusConnectionData *d;
00789
00790 d = BUS_CONNECTION_DATA (connection);
00791
00792 _dbus_assert (d != NULL);
00793 _dbus_assert (d->policy != NULL);
00794
00795 return d->policy;
00796 }
00797
00798 static dbus_bool_t
00799 foreach_active (BusConnections *connections,
00800 BusConnectionForeachFunction function,
00801 void *data)
00802 {
00803 DBusList *link;
00804
00805 link = _dbus_list_get_first_link (&connections->completed);
00806 while (link != NULL)
00807 {
00808 DBusConnection *connection = link->data;
00809 DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
00810
00811 if (!(* function) (connection, data))
00812 return FALSE;
00813
00814 link = next;
00815 }
00816
00817 return TRUE;
00818 }
00819
00820 static dbus_bool_t
00821 foreach_inactive (BusConnections *connections,
00822 BusConnectionForeachFunction function,
00823 void *data)
00824 {
00825 DBusList *link;
00826
00827 link = _dbus_list_get_first_link (&connections->incomplete);
00828 while (link != NULL)
00829 {
00830 DBusConnection *connection = link->data;
00831 DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
00832
00833 if (!(* function) (connection, data))
00834 return FALSE;
00835
00836 link = next;
00837 }
00838
00839 return TRUE;
00840 }
00841
00851 void
00852 bus_connections_foreach_active (BusConnections *connections,
00853 BusConnectionForeachFunction function,
00854 void *data)
00855 {
00856 foreach_active (connections, function, data);
00857 }
00858
00867 void
00868 bus_connections_foreach (BusConnections *connections,
00869 BusConnectionForeachFunction function,
00870 void *data)
00871 {
00872 if (!foreach_active (connections, function, data))
00873 return;
00874
00875 foreach_inactive (connections, function, data);
00876 }
00877
00878 BusContext*
00879 bus_connections_get_context (BusConnections *connections)
00880 {
00881 return connections->context;
00882 }
00883
00884 BusContext*
00885 bus_connection_get_context (DBusConnection *connection)
00886 {
00887 BusConnectionData *d;
00888
00889 d = BUS_CONNECTION_DATA (connection);
00890
00891 _dbus_assert (d != NULL);
00892
00893 return d->connections->context;
00894 }
00895
00896 BusConnections*
00897 bus_connection_get_connections (DBusConnection *connection)
00898 {
00899 BusConnectionData *d;
00900
00901 d = BUS_CONNECTION_DATA (connection);
00902
00903 _dbus_assert (d != NULL);
00904
00905 return d->connections;
00906 }
00907
00908 BusRegistry*
00909 bus_connection_get_registry (DBusConnection *connection)
00910 {
00911 BusConnectionData *d;
00912
00913 d = BUS_CONNECTION_DATA (connection);
00914
00915 _dbus_assert (d != NULL);
00916
00917 return bus_context_get_registry (d->connections->context);
00918 }
00919
00920 BusActivation*
00921 bus_connection_get_activation (DBusConnection *connection)
00922 {
00923 BusConnectionData *d;
00924
00925 d = BUS_CONNECTION_DATA (connection);
00926
00927 _dbus_assert (d != NULL);
00928
00929 return bus_context_get_activation (d->connections->context);
00930 }
00931
00938 dbus_bool_t
00939 bus_connection_is_active (DBusConnection *connection)
00940 {
00941 BusConnectionData *d;
00942
00943 d = BUS_CONNECTION_DATA (connection);
00944
00945 return d != NULL && d->name != NULL;
00946 }
00947
00948 dbus_bool_t
00949 bus_connection_preallocate_oom_error (DBusConnection *connection)
00950 {
00951 DBusMessage *message;
00952 DBusPreallocatedSend *preallocated;
00953 BusConnectionData *d;
00954
00955 d = BUS_CONNECTION_DATA (connection);
00956
00957 _dbus_assert (d != NULL);
00958
00959 if (d->oom_preallocated != NULL)
00960 return TRUE;
00961
00962 preallocated = dbus_connection_preallocate_send (connection);
00963 if (preallocated == NULL)
00964 return FALSE;
00965
00966
00967 message = dbus_message_new (DBUS_ERROR_NO_MEMORY,
00968 d->name);
00969 if (message == NULL)
00970 {
00971 dbus_connection_free_preallocated_send (connection, preallocated);
00972 return FALSE;
00973 }
00974
00975 dbus_message_set_is_error (message, TRUE);
00976
00977 if (!dbus_message_set_sender (message,
00978 DBUS_SERVICE_DBUS))
00979 {
00980 dbus_connection_free_preallocated_send (connection, preallocated);
00981 dbus_message_unref (message);
00982 return FALSE;
00983 }
00984
00985
00986
00987
00988 if (!dbus_message_set_reply_serial (message, 14))
00989 {
00990 dbus_connection_free_preallocated_send (connection, preallocated);
00991 dbus_message_unref (message);
00992 return FALSE;
00993 }
00994
00995 d->oom_message = message;
00996 d->oom_preallocated = preallocated;
00997
00998 return TRUE;
00999 }
01000
01001 void
01002 bus_connection_send_oom_error (DBusConnection *connection,
01003 DBusMessage *in_reply_to)
01004 {
01005 BusConnectionData *d;
01006
01007 d = BUS_CONNECTION_DATA (connection);
01008
01009 _dbus_assert (d != NULL);
01010 _dbus_assert (d->oom_message != NULL);
01011
01012
01013 if (!dbus_message_set_reply_serial (d->oom_message,
01014 dbus_message_get_serial (in_reply_to)))
01015 _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
01016
01017 _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
01018
01019 dbus_connection_send_preallocated (connection, d->oom_preallocated,
01020 d->oom_message, NULL);
01021
01022 dbus_message_unref (d->oom_message);
01023 d->oom_message = NULL;
01024 d->oom_preallocated = NULL;
01025 }
01026
01027 void
01028 bus_connection_add_owned_service_link (DBusConnection *connection,
01029 DBusList *link)
01030 {
01031 BusConnectionData *d;
01032
01033 d = BUS_CONNECTION_DATA (connection);
01034 _dbus_assert (d != NULL);
01035
01036 _dbus_list_append_link (&d->services_owned, link);
01037
01038 d->n_services_owned += 1;
01039 }
01040
01041 dbus_bool_t
01042 bus_connection_add_owned_service (DBusConnection *connection,
01043 BusService *service)
01044 {
01045 DBusList *link;
01046
01047 link = _dbus_list_alloc_link (service);
01048
01049 if (link == NULL)
01050 return FALSE;
01051
01052 bus_connection_add_owned_service_link (connection, link);
01053
01054 return TRUE;
01055 }
01056
01057 void
01058 bus_connection_remove_owned_service (DBusConnection *connection,
01059 BusService *service)
01060 {
01061 BusConnectionData *d;
01062
01063 d = BUS_CONNECTION_DATA (connection);
01064 _dbus_assert (d != NULL);
01065
01066 _dbus_list_remove_last (&d->services_owned, service);
01067
01068 d->n_services_owned -= 1;
01069 _dbus_assert (d->n_services_owned >= 0);
01070 }
01071
01072 int
01073 bus_connection_get_n_services_owned (DBusConnection *connection)
01074 {
01075 BusConnectionData *d;
01076
01077 d = BUS_CONNECTION_DATA (connection);
01078 _dbus_assert (d != NULL);
01079
01080 return d->n_services_owned;
01081 }
01082
01083 dbus_bool_t
01084 bus_connection_complete (DBusConnection *connection,
01085 const DBusString *name,
01086 DBusError *error)
01087 {
01088 BusConnectionData *d;
01089 unsigned long uid;
01090
01091 d = BUS_CONNECTION_DATA (connection);
01092 _dbus_assert (d != NULL);
01093 _dbus_assert (d->name == NULL);
01094 _dbus_assert (d->policy == NULL);
01095
01096 if (!_dbus_string_copy_data (name, &d->name))
01097 {
01098 BUS_SET_OOM (error);
01099 return FALSE;
01100 }
01101
01102 _dbus_assert (d->name != NULL);
01103
01104 _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
01105
01106 d->policy = bus_context_create_client_policy (d->connections->context,
01107 connection,
01108 error);
01109
01110
01111
01112
01113
01114
01115 if (d->policy == NULL)
01116 {
01117 _dbus_verbose ("Failed to create security policy for connection %p\n",
01118 connection);
01119 _DBUS_ASSERT_ERROR_IS_SET (error);
01120 dbus_free (d->name);
01121 d->name = NULL;
01122 return FALSE;
01123 }
01124
01125 if (dbus_connection_get_unix_user (connection, &uid))
01126 {
01127 if (!adjust_connections_for_uid (d->connections,
01128 uid, 1))
01129 {
01130 BUS_SET_OOM (error);
01131 dbus_free (d->name);
01132 d->name = NULL;
01133 return FALSE;
01134 }
01135 }
01136
01137
01138 _dbus_list_unlink (&d->connections->incomplete,
01139 d->link_in_connection_list);
01140 d->connections->n_incomplete -= 1;
01141 _dbus_list_append_link (&d->connections->completed,
01142 d->link_in_connection_list);
01143 d->connections->n_completed += 1;
01144
01145 _dbus_assert (d->connections->n_incomplete >= 0);
01146 _dbus_assert (d->connections->n_completed > 0);
01147
01148
01149 bus_connections_expire_incomplete (d->connections);
01150
01151 return TRUE;
01152 }
01153
01154 const char *
01155 bus_connection_get_name (DBusConnection *connection)
01156 {
01157 BusConnectionData *d;
01158
01159 d = BUS_CONNECTION_DATA (connection);
01160 _dbus_assert (d != NULL);
01161
01162 return d->name;
01163 }
01164
01169 dbus_bool_t
01170 bus_connections_check_limits (BusConnections *connections,
01171 DBusConnection *requesting_completion,
01172 DBusError *error)
01173 {
01174 BusConnectionData *d;
01175 unsigned long uid;
01176
01177 d = BUS_CONNECTION_DATA (requesting_completion);
01178 _dbus_assert (d != NULL);
01179
01180 _dbus_assert (d->name == NULL);
01181
01182 if (connections->n_completed >=
01183 bus_context_get_max_completed_connections (connections->context))
01184 {
01185 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
01186 "The maximum number of active connections has been reached");
01187 return FALSE;
01188 }
01189
01190 if (dbus_connection_get_unix_user (requesting_completion, &uid))
01191 {
01192 if (get_connections_for_uid (connections, uid) >=
01193 bus_context_get_max_connections_per_user (connections->context))
01194 {
01195 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
01196 "The maximum number of active connections for UID %lu has been reached",
01197 uid);
01198 return FALSE;
01199 }
01200 }
01201
01202 return TRUE;
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 typedef struct
01214 {
01215 BusTransaction *transaction;
01216 DBusMessage *message;
01217 DBusPreallocatedSend *preallocated;
01218 } MessageToSend;
01219
01220 typedef struct
01221 {
01222 BusTransactionCancelFunction cancel_function;
01223 DBusFreeFunction free_data_function;
01224 void *data;
01225 } CancelHook;
01226
01227 struct BusTransaction
01228 {
01229 DBusList *connections;
01230 BusContext *context;
01231 DBusList *cancel_hooks;
01232 };
01233
01234 static void
01235 message_to_send_free (DBusConnection *connection,
01236 MessageToSend *to_send)
01237 {
01238 if (to_send->message)
01239 dbus_message_unref (to_send->message);
01240
01241 if (to_send->preallocated)
01242 dbus_connection_free_preallocated_send (connection, to_send->preallocated);
01243
01244 dbus_free (to_send);
01245 }
01246
01247 static void
01248 cancel_hook_cancel (void *element,
01249 void *data)
01250 {
01251 CancelHook *ch = element;
01252
01253 _dbus_verbose ("Running transaction cancel hook\n");
01254
01255 if (ch->cancel_function)
01256 (* ch->cancel_function) (ch->data);
01257 }
01258
01259 static void
01260 cancel_hook_free (void *element,
01261 void *data)
01262 {
01263 CancelHook *ch = element;
01264
01265 if (ch->free_data_function)
01266 (* ch->free_data_function) (ch->data);
01267
01268 dbus_free (ch);
01269 }
01270
01271 static void
01272 free_cancel_hooks (BusTransaction *transaction)
01273 {
01274 _dbus_list_foreach (&transaction->cancel_hooks,
01275 cancel_hook_free, NULL);
01276
01277 _dbus_list_clear (&transaction->cancel_hooks);
01278 }
01279
01280 BusTransaction*
01281 bus_transaction_new (BusContext *context)
01282 {
01283 BusTransaction *transaction;
01284
01285 transaction = dbus_new0 (BusTransaction, 1);
01286 if (transaction == NULL)
01287 return NULL;
01288
01289 transaction->context = context;
01290
01291 return transaction;
01292 }
01293
01294 BusContext*
01295 bus_transaction_get_context (BusTransaction *transaction)
01296 {
01297 return transaction->context;
01298 }
01299
01300 BusConnections*
01301 bus_transaction_get_connections (BusTransaction *transaction)
01302 {
01303 return bus_context_get_connections (transaction->context);
01304 }
01305
01306 dbus_bool_t
01307 bus_transaction_send_from_driver (BusTransaction *transaction,
01308 DBusConnection *connection,
01309 DBusMessage *message)
01310 {
01311
01312
01313
01314
01315 _dbus_verbose ("Sending %s from driver\n",
01316 dbus_message_get_name (message));
01317
01318 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
01319 return FALSE;
01320
01321
01322
01323
01324 if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
01325 NULL, connection, message, NULL))
01326 return TRUE;
01327
01328 return bus_transaction_send (transaction, connection, message);
01329 }
01330
01331 dbus_bool_t
01332 bus_transaction_send (BusTransaction *transaction,
01333 DBusConnection *connection,
01334 DBusMessage *message)
01335 {
01336 MessageToSend *to_send;
01337 BusConnectionData *d;
01338 DBusList *link;
01339
01340 _dbus_verbose (" trying to add %s %s to transaction%s\n",
01341 dbus_message_get_is_error (message) ? "error" :
01342 dbus_message_get_reply_serial (message) != 0 ? "reply" :
01343 "message",
01344 dbus_message_get_name (message),
01345 dbus_connection_get_is_connected (connection) ?
01346 "" : " (disconnected)");
01347
01348 _dbus_assert (dbus_message_get_sender (message) != NULL);
01349
01350 if (!dbus_connection_get_is_connected (connection))
01351 return TRUE;
01352
01353 d = BUS_CONNECTION_DATA (connection);
01354 _dbus_assert (d != NULL);
01355
01356 to_send = dbus_new (MessageToSend, 1);
01357 if (to_send == NULL)
01358 {
01359 return FALSE;
01360 }
01361
01362 to_send->preallocated = dbus_connection_preallocate_send (connection);
01363 if (to_send->preallocated == NULL)
01364 {
01365 dbus_free (to_send);
01366 return FALSE;
01367 }
01368
01369 dbus_message_ref (message);
01370 to_send->message = message;
01371 to_send->transaction = transaction;
01372
01373 _dbus_verbose ("about to prepend message\n");
01374
01375 if (!_dbus_list_prepend (&d->transaction_messages, to_send))
01376 {
01377 message_to_send_free (connection, to_send);
01378 return FALSE;
01379 }
01380
01381 _dbus_verbose ("prepended message\n");
01382
01383
01384
01385
01386
01387 link = _dbus_list_get_first_link (&d->transaction_messages);
01388 _dbus_assert (link->data == to_send);
01389 link = _dbus_list_get_next_link (&d->transaction_messages, link);
01390 while (link != NULL)
01391 {
01392 MessageToSend *m = link->data;
01393 DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
01394
01395 if (m->transaction == transaction)
01396 break;
01397
01398 link = next;
01399 }
01400
01401 if (link == NULL)
01402 {
01403 if (!_dbus_list_prepend (&transaction->connections, connection))
01404 {
01405 _dbus_list_remove (&d->transaction_messages, to_send);
01406 message_to_send_free (connection, to_send);
01407 return FALSE;
01408 }
01409 }
01410
01411 return TRUE;
01412 }
01413
01414 static void
01415 connection_cancel_transaction (DBusConnection *connection,
01416 BusTransaction *transaction)
01417 {
01418 DBusList *link;
01419 BusConnectionData *d;
01420
01421 d = BUS_CONNECTION_DATA (connection);
01422 _dbus_assert (d != NULL);
01423
01424 link = _dbus_list_get_first_link (&d->transaction_messages);
01425 while (link != NULL)
01426 {
01427 MessageToSend *m = link->data;
01428 DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
01429
01430 if (m->transaction == transaction)
01431 {
01432 _dbus_list_remove_link (&d->transaction_messages,
01433 link);
01434
01435 message_to_send_free (connection, m);
01436 }
01437
01438 link = next;
01439 }
01440 }
01441
01442 void
01443 bus_transaction_cancel_and_free (BusTransaction *transaction)
01444 {
01445 DBusConnection *connection;
01446
01447 _dbus_verbose ("TRANSACTION: cancelled\n");
01448
01449 while ((connection = _dbus_list_pop_first (&transaction->connections)))
01450 connection_cancel_transaction (connection, transaction);
01451
01452 _dbus_assert (transaction->connections == NULL);
01453
01454 _dbus_list_foreach (&transaction->cancel_hooks,
01455 cancel_hook_cancel, NULL);
01456
01457 free_cancel_hooks (transaction);
01458
01459 dbus_free (transaction);
01460 }
01461
01462 static void
01463 connection_execute_transaction (DBusConnection *connection,
01464 BusTransaction *transaction)
01465 {
01466 DBusList *link;
01467 BusConnectionData *d;
01468
01469 d = BUS_CONNECTION_DATA (connection);
01470 _dbus_assert (d != NULL);
01471
01472
01473 link = _dbus_list_get_last_link (&d->transaction_messages);
01474 while (link != NULL)
01475 {
01476 MessageToSend *m = link->data;
01477 DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
01478
01479 if (m->transaction == transaction)
01480 {
01481 _dbus_list_remove_link (&d->transaction_messages,
01482 link);
01483
01484 _dbus_assert (dbus_message_get_sender (m->message) != NULL);
01485
01486 dbus_connection_send_preallocated (connection,
01487 m->preallocated,
01488 m->message,
01489 NULL);
01490
01491 m->preallocated = NULL;
01492
01493 message_to_send_free (connection, m);
01494 }
01495
01496 link = prev;
01497 }
01498 }
01499
01500 void
01501 bus_transaction_execute_and_free (BusTransaction *transaction)
01502 {
01503
01504
01505
01506 DBusConnection *connection;
01507
01508 _dbus_verbose ("TRANSACTION: executing\n");
01509
01510 while ((connection = _dbus_list_pop_first (&transaction->connections)))
01511 connection_execute_transaction (connection, transaction);
01512
01513 _dbus_assert (transaction->connections == NULL);
01514
01515 free_cancel_hooks (transaction);
01516
01517 dbus_free (transaction);
01518 }
01519
01520 static void
01521 bus_connection_remove_transactions (DBusConnection *connection)
01522 {
01523 MessageToSend *to_send;
01524 BusConnectionData *d;
01525
01526 d = BUS_CONNECTION_DATA (connection);
01527 _dbus_assert (d != NULL);
01528
01529 while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
01530 {
01531
01532 _dbus_list_remove (&to_send->transaction->connections,
01533 connection);
01534
01535 _dbus_list_remove (&d->transaction_messages, to_send);
01536 message_to_send_free (connection, to_send);
01537 }
01538 }
01539
01543 dbus_bool_t
01544 bus_transaction_send_error_reply (BusTransaction *transaction,
01545 DBusConnection *connection,
01546 const DBusError *error,
01547 DBusMessage *in_reply_to)
01548 {
01549 DBusMessage *reply;
01550
01551 _dbus_assert (error != NULL);
01552 _DBUS_ASSERT_ERROR_IS_SET (error);
01553
01554 _dbus_verbose ("Sending error reply %s \"%s\"\n",
01555 error->name, error->message);
01556
01557 reply = dbus_message_new_error_reply (in_reply_to,
01558 error->name,
01559 error->message);
01560 if (reply == NULL)
01561 return FALSE;
01562
01563 if (!bus_transaction_send_from_driver (transaction, connection, reply))
01564 {
01565 dbus_message_unref (reply);
01566 return FALSE;
01567 }
01568
01569 dbus_message_unref (reply);
01570
01571 return TRUE;
01572 }
01573
01574 dbus_bool_t
01575 bus_transaction_add_cancel_hook (BusTransaction *transaction,
01576 BusTransactionCancelFunction cancel_function,
01577 void *data,
01578 DBusFreeFunction free_data_function)
01579 {
01580 CancelHook *ch;
01581
01582 ch = dbus_new (CancelHook, 1);
01583 if (ch == NULL)
01584 return FALSE;
01585
01586 ch->cancel_function = cancel_function;
01587 ch->data = data;
01588 ch->free_data_function = free_data_function;
01589
01590
01591
01592
01593 if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
01594 {
01595 dbus_free (ch);
01596 return FALSE;
01597 }
01598
01599 return TRUE;
01600 }