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