<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>connection.c Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.2.15 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="modules.html">Modules</a> <a class="qindex" href="annotated.html">Data Structures</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Data Fields</a> <a class="qindex" href="pages.html">Related Pages</a> </center> <hr><h1>connection.c</h1><div class="fragment"><pre>00001 <font class="comment">/* -*- mode: C; c-file-style: "gnu" -*- */</font> 00002 <font class="comment">/* connection.c Client connections</font> 00003 <font class="comment"> *</font> 00004 <font class="comment"> * Copyright (C) 2003 Red Hat, Inc.</font> 00005 <font class="comment"> *</font> 00006 <font class="comment"> * Licensed under the Academic Free License version 1.2</font> 00007 <font class="comment"> * </font> 00008 <font class="comment"> * This program is free software; you can redistribute it and/or modify</font> 00009 <font class="comment"> * it under the terms of the GNU General Public License as published by</font> 00010 <font class="comment"> * the Free Software Foundation; either version 2 of the License, or</font> 00011 <font class="comment"> * (at your option) any later version.</font> 00012 <font class="comment"> *</font> 00013 <font class="comment"> * This program is distributed in the hope that it will be useful,</font> 00014 <font class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font> 00015 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</font> 00016 <font class="comment"> * GNU General Public License for more details.</font> 00017 <font class="comment"> * </font> 00018 <font class="comment"> * You should have received a copy of the GNU General Public License</font> 00019 <font class="comment"> * along with this program; if not, write to the Free Software</font> 00020 <font class="comment"> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</font> 00021 <font class="comment"> *</font> 00022 <font class="comment"> */</font> 00023 <font class="preprocessor">#include "connection.h"</font> 00024 <font class="preprocessor">#include "dispatch.h"</font> 00025 <font class="preprocessor">#include "policy.h"</font> 00026 <font class="preprocessor">#include "services.h"</font> 00027 <font class="preprocessor">#include "utils.h"</font> 00028 <font class="preprocessor">#include "signals.h"</font> 00029 <font class="preprocessor">#include <dbus/dbus-list.h></font> 00030 <font class="preprocessor">#include <dbus/dbus-hash.h></font> 00031 <font class="preprocessor">#include <dbus/dbus-timeout.h></font> 00032 00033 <font class="keyword">static</font> <font class="keywordtype">void</font> bus_connection_remove_transactions (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection); 00034 00035 <font class="keyword">struct </font>BusConnections 00036 { 00037 <font class="keywordtype">int</font> refcount; 00038 <a class="code" href="structDBusList.html">DBusList</a> *completed; 00039 <font class="keywordtype">int</font> n_completed; 00040 <a class="code" href="structDBusList.html">DBusList</a> *incomplete; 00041 <font class="keywordtype">int</font> n_incomplete; 00042 BusContext *context; 00043 <a class="code" href="structDBusHashTable.html">DBusHashTable</a> *completed_by_user; 00044 <a class="code" href="structDBusTimeout.html">DBusTimeout</a> *expire_timeout; 00045 <font class="keywordtype">int</font> stamp; 00046 }; 00047 00048 <font class="keyword">static</font> dbus_int32_t connection_data_slot = -1; 00049 00050 <font class="keyword">typedef</font> <font class="keyword">struct</font> 00051 <font class="keyword"></font>{ 00052 BusConnections *connections; 00053 <a class="code" href="structDBusList.html">DBusList</a> *link_in_connection_list; 00054 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection; 00055 <a class="code" href="structDBusList.html">DBusList</a> *services_owned; 00056 <font class="keywordtype">int</font> n_services_owned; 00057 <a class="code" href="structDBusList.html">DBusList</a> *match_rules; 00058 <font class="keywordtype">int</font> n_match_rules; 00059 <font class="keywordtype">char</font> *name; 00060 <a class="code" href="structDBusList.html">DBusList</a> *transaction_messages; 00061 <a class="code" href="structDBusMessage.html">DBusMessage</a> *oom_message; 00062 <a class="code" href="structDBusPreallocatedSend.html">DBusPreallocatedSend</a> *oom_preallocated; 00063 BusClientPolicy *policy; 00064 00065 <font class="keywordtype">long</font> connection_tv_sec; 00066 <font class="keywordtype">long</font> connection_tv_usec; 00067 <font class="keywordtype">int</font> stamp; 00068 } BusConnectionData; 00069 00070 <font class="keyword">static</font> dbus_bool_t expire_incomplete_timeout (<font class="keywordtype">void</font> *data); 00071 00072 <font class="preprocessor">#define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))</font> 00073 <font class="preprocessor"></font> 00074 <font class="keyword">static</font> DBusLoop* 00075 connection_get_loop (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00076 { 00077 BusConnectionData *d; 00078 00079 d = BUS_CONNECTION_DATA (connection); 00080 00081 <font class="keywordflow">return</font> bus_context_get_loop (d->connections->context); 00082 } 00083 00084 00085 <font class="keyword">static</font> <font class="keywordtype">int</font> 00086 get_connections_for_uid (BusConnections *connections, 00087 dbus_uid_t uid) 00088 { 00089 <font class="keywordtype">void</font> *val; 00090 <font class="keywordtype">int</font> current_count; 00091 00092 <font class="comment">/* val is NULL is 0 when it isn't in the hash yet */</font> 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 <font class="keywordflow">return</font> current_count; 00100 } 00101 00102 <font class="keyword">static</font> dbus_bool_t 00103 adjust_connections_for_uid (BusConnections *connections, 00104 dbus_uid_t uid, 00105 <font class="keywordtype">int</font> adjustment) 00106 { 00107 <font class="keywordtype">int</font> current_count; 00108 00109 current_count = get_connections_for_uid (connections, uid); 00110 00111 _dbus_verbose (<font class="stringliteral">"Adjusting connection count for UID "</font> DBUS_UID_FORMAT 00112 <font class="stringliteral">": was %d adjustment %d making %d\n"</font>, 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 <font class="keywordflow">if</font> (current_count == 0) 00122 { 00123 _dbus_hash_table_remove_ulong (connections->completed_by_user, uid); 00124 <font class="keywordflow">return</font> TRUE; 00125 } 00126 <font class="keywordflow">else</font> 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 <font class="comment">/* only positive adjustment can fail as otherwise</font> 00134 <font class="comment"> * a hash entry should already exist</font> 00135 <font class="comment"> */</font> 00136 _dbus_assert (adjustment > 0 || 00137 (adjustment <= 0 && retval)); 00138 00139 <font class="keywordflow">return</font> retval; 00140 } 00141 } 00142 00143 <font class="keywordtype">void</font> 00144 bus_connection_disconnected (<a class="code" href="structDBusConnection.html">DBusConnection</a> *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 (<font class="stringliteral">"%s disconnected, dropping all service ownership and releasing\n"</font>, 00154 d->name ? d->name : <font class="stringliteral">"(inactive)"</font>); 00155 00156 <font class="comment">/* Delete our match rules */</font> 00157 <font class="keywordflow">if</font> (d->n_match_rules > 0) 00158 { 00159 matchmaker = bus_context_get_matchmaker (d->connections->context); 00160 bus_matchmaker_disconnected (matchmaker, connection); 00161 } 00162 00163 <font class="comment">/* Drop any service ownership. FIXME Unfortunately, this requires</font> 00164 <font class="comment"> * memory allocation and there doesn't seem to be a good way to</font> 00165 <font class="comment"> * handle it other than sleeping; we can't "fail" the operation of</font> 00166 <font class="comment"> * disconnecting a client, and preallocating a broadcast "service is</font> 00167 <font class="comment"> * now gone" message for every client-service pair seems kind of</font> 00168 <font class="comment"> * involved. Probably we need to do that though.</font> 00169 <font class="comment"> */</font> 00170 <font class="keywordflow">while</font> ((service = _dbus_list_get_last (&d->services_owned))) 00171 { 00172 BusTransaction *transaction; 00173 <a class="code" href="structDBusError.html">DBusError</a> error; 00174 00175 retry: 00176 00177 dbus_error_init (&error); 00178 00179 transaction = NULL; 00180 <font class="keywordflow">while</font> (transaction == NULL) 00181 { 00182 transaction = bus_transaction_new (d->connections->context); 00183 _dbus_wait_for_memory (); 00184 } 00185 00186 <font class="keywordflow">if</font> (!bus_service_remove_owner (service, connection, 00187 transaction, &error)) 00188 { 00189 _DBUS_ASSERT_ERROR_IS_SET (&error); 00190 00191 <font class="keywordflow">if</font> (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 <font class="keywordflow">goto</font> retry; 00197 } 00198 <font class="keywordflow">else</font> 00199 { 00200 _dbus_verbose (<font class="stringliteral">"Failed to remove service owner: %s %s\n"</font>, 00201 error.<a class="code" href="structDBusError.html#m0">name</a>, error.<a class="code" href="structDBusError.html#m1">message</a>); 00202 _dbus_assert_not_reached (<font class="stringliteral">"Removing service owner failed for non-memory-related reason"</font>); 00203 } 00204 } 00205 00206 bus_transaction_execute_and_free (transaction); 00207 } 00208 00209 bus_dispatch_remove_connection (connection); 00210 00211 <font class="comment">/* no more watching */</font> 00212 <font class="keywordflow">if</font> (!dbus_connection_set_watch_functions (connection, 00213 NULL, NULL, NULL, 00214 connection, 00215 NULL)) 00216 _dbus_assert_not_reached (<font class="stringliteral">"setting watch functions to NULL failed"</font>); 00217 00218 <font class="keywordflow">if</font> (!dbus_connection_set_timeout_functions (connection, 00219 NULL, NULL, NULL, 00220 connection, 00221 NULL)) 00222 _dbus_assert_not_reached (<font class="stringliteral">"setting timeout functions to NULL failed"</font>); 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 <font class="keywordflow">if</font> (d->link_in_connection_list != NULL) 00233 { 00234 <font class="keywordflow">if</font> (d->name != NULL) 00235 { 00236 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> 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 <font class="keywordflow">if</font> (dbus_connection_get_unix_user (connection, &uid)) 00243 { 00244 <font class="keywordflow">if</font> (!adjust_connections_for_uid (d->connections, 00245 uid, -1)) 00246 _dbus_assert_not_reached (<font class="stringliteral">"adjusting downward should never fail"</font>); 00247 } 00248 } 00249 <font class="keywordflow">else</font> 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 <font class="comment">/* frees "d" as side effect */</font> 00261 dbus_connection_set_data (connection, 00262 connection_data_slot, 00263 NULL, NULL); 00264 00265 dbus_connection_unref (connection); 00266 } 00267 00268 <font class="keyword">static</font> dbus_bool_t 00269 connection_watch_callback (<a class="code" href="structDBusWatch.html">DBusWatch</a> *watch, 00270 <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> condition, 00271 <font class="keywordtype">void</font> *data) 00272 { 00273 <font class="comment">/* FIXME this can be done in dbus-mainloop.c</font> 00274 <font class="comment"> * if the code in activation.c for the babysitter</font> 00275 <font class="comment"> * watch handler is fixed.</font> 00276 <font class="comment"> */</font> 00277 00278 <font class="preprocessor">#if 0</font> 00279 <font class="preprocessor"></font> _dbus_verbose (<font class="stringliteral">"Calling handle_watch\n"</font>); 00280 <font class="preprocessor">#endif</font> 00281 <font class="preprocessor"></font> <font class="keywordflow">return</font> dbus_watch_handle (watch, condition); 00282 } 00283 00284 <font class="keyword">static</font> dbus_bool_t 00285 add_connection_watch (<a class="code" href="structDBusWatch.html">DBusWatch</a> *watch, 00286 <font class="keywordtype">void</font> *data) 00287 { 00288 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = data; 00289 00290 <font class="keywordflow">return</font> _dbus_loop_add_watch (connection_get_loop (connection), 00291 watch, connection_watch_callback, connection, 00292 NULL); 00293 } 00294 00295 <font class="keyword">static</font> <font class="keywordtype">void</font> 00296 remove_connection_watch (<a class="code" href="structDBusWatch.html">DBusWatch</a> *watch, 00297 <font class="keywordtype">void</font> *data) 00298 { 00299 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = data; 00300 00301 _dbus_loop_remove_watch (connection_get_loop (connection), 00302 watch, connection_watch_callback, connection); 00303 } 00304 00305 <font class="keyword">static</font> <font class="keywordtype">void</font> 00306 connection_timeout_callback (<a class="code" href="structDBusTimeout.html">DBusTimeout</a> *timeout, 00307 <font class="keywordtype">void</font> *data) 00308 { 00309 <font class="comment">/* DBusConnection *connection = data; */</font> 00310 00311 <font class="comment">/* can return FALSE on OOM but we just let it fire again later */</font> 00312 dbus_timeout_handle (timeout); 00313 } 00314 00315 <font class="keyword">static</font> dbus_bool_t 00316 add_connection_timeout (<a class="code" href="structDBusTimeout.html">DBusTimeout</a> *timeout, 00317 <font class="keywordtype">void</font> *data) 00318 { 00319 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = data; 00320 00321 <font class="keywordflow">return</font> _dbus_loop_add_timeout (connection_get_loop (connection), 00322 timeout, connection_timeout_callback, connection, NULL); 00323 } 00324 00325 <font class="keyword">static</font> <font class="keywordtype">void</font> 00326 remove_connection_timeout (<a class="code" href="structDBusTimeout.html">DBusTimeout</a> *timeout, 00327 <font class="keywordtype">void</font> *data) 00328 { 00329 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = data; 00330 00331 _dbus_loop_remove_timeout (connection_get_loop (connection), 00332 timeout, connection_timeout_callback, connection); 00333 } 00334 00335 <font class="keyword">static</font> <font class="keywordtype">void</font> 00336 dispatch_status_function (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 00337 DBusDispatchStatus new_status, 00338 <font class="keywordtype">void</font> *data) 00339 { 00340 DBusLoop *loop = data; 00341 00342 <font class="keywordflow">if</font> (new_status != DBUS_DISPATCH_COMPLETE) 00343 { 00344 <font class="keywordflow">while</font> (!_dbus_loop_queue_dispatch (loop, connection)) 00345 _dbus_wait_for_memory (); 00346 } 00347 } 00348 00349 <font class="keyword">static</font> dbus_bool_t 00350 allow_user_function (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 00351 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> uid, 00352 <font class="keywordtype">void</font> *data) 00353 { 00354 BusConnectionData *d; 00355 00356 d = BUS_CONNECTION_DATA (connection); 00357 00358 _dbus_assert (d != NULL); 00359 00360 <font class="keywordflow">return</font> bus_context_allow_user (d->connections->context, uid); 00361 } 00362 00363 <font class="keyword">static</font> <font class="keywordtype">void</font> 00364 free_connection_data (<font class="keywordtype">void</font> *data) 00365 { 00366 BusConnectionData *d = data; 00367 00368 <font class="comment">/* services_owned should be NULL since we should be disconnected */</font> 00369 _dbus_assert (d->services_owned == NULL); 00370 _dbus_assert (d->n_services_owned == 0); 00371 <font class="comment">/* similarly */</font> 00372 _dbus_assert (d->transaction_messages == NULL); 00373 00374 <font class="keywordflow">if</font> (d->oom_preallocated) 00375 dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated); 00376 00377 <font class="keywordflow">if</font> (d->oom_message) 00378 dbus_message_unref (d->oom_message); 00379 00380 <font class="keywordflow">if</font> (d->policy) 00381 bus_client_policy_unref (d->policy); 00382 00383 dbus_free (d->name); 00384 00385 dbus_free (d); 00386 } 00387 00388 <font class="keyword">static</font> <font class="keywordtype">void</font> 00389 call_timeout_callback (<a class="code" href="structDBusTimeout.html">DBusTimeout</a> *timeout, 00390 <font class="keywordtype">void</font> *data) 00391 { 00392 <font class="comment">/* can return FALSE on OOM but we just let it fire again later */</font> 00393 dbus_timeout_handle (timeout); 00394 } 00395 00396 BusConnections* 00397 bus_connections_new (BusContext *context) 00398 { 00399 BusConnections *connections; 00400 00401 <font class="keywordflow">if</font> (!dbus_connection_allocate_data_slot (&connection_data_slot)) 00402 <font class="keywordflow">goto</font> failed_0; 00403 00404 connections = dbus_new0 (BusConnections, 1); 00405 <font class="keywordflow">if</font> (connections == NULL) 00406 <font class="keywordflow">goto</font> failed_1; 00407 00408 connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG, 00409 NULL, NULL); 00410 <font class="keywordflow">if</font> (connections->completed_by_user == NULL) 00411 <font class="keywordflow">goto</font> failed_2; 00412 00413 connections->expire_timeout = _dbus_timeout_new (100, <font class="comment">/* irrelevant */</font> 00414 expire_incomplete_timeout, 00415 connections, NULL); 00416 <font class="keywordflow">if</font> (connections->expire_timeout == NULL) 00417 <font class="keywordflow">goto</font> failed_3; 00418 00419 _dbus_timeout_set_enabled (connections->expire_timeout, FALSE); 00420 00421 <font class="keywordflow">if</font> (!_dbus_loop_add_timeout (bus_context_get_loop (context), 00422 connections->expire_timeout, 00423 call_timeout_callback, NULL, NULL)) 00424 <font class="keywordflow">goto</font> failed_4; 00425 00426 connections->refcount = 1; 00427 connections->context = context; 00428 00429 <font class="keywordflow">return</font> 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 <font class="keywordflow">return</font> NULL; 00441 } 00442 00443 <font class="keywordtype">void</font> 00444 bus_connections_ref (BusConnections *connections) 00445 { 00446 _dbus_assert (connections->refcount > 0); 00447 connections->refcount += 1; 00448 } 00449 00450 <font class="keywordtype">void</font> 00451 bus_connections_unref (BusConnections *connections) 00452 { 00453 _dbus_assert (connections->refcount > 0); 00454 connections->refcount -= 1; 00455 <font class="keywordflow">if</font> (connections->refcount == 0) 00456 { 00457 <font class="comment">/* drop all incomplete */</font> 00458 <font class="keywordflow">while</font> (connections->incomplete != NULL) 00459 { 00460 <a class="code" href="structDBusConnection.html">DBusConnection</a> *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 <font class="comment">/* drop all real connections */</font> 00473 <font class="keywordflow">while</font> (connections->completed != NULL) 00474 { 00475 <a class="code" href="structDBusConnection.html">DBusConnection</a> *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 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00504 { 00505 BusConnectionData *d; 00506 dbus_bool_t retval; 00507 00508 d = dbus_new0 (BusConnectionData, 1); 00509 00510 <font class="keywordflow">if</font> (d == NULL) 00511 <font class="keywordflow">return</font> 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 <font class="keywordflow">if</font> (!dbus_connection_set_data (connection, 00522 connection_data_slot, 00523 d, free_connection_data)) 00524 { 00525 dbus_free (d); 00526 <font class="keywordflow">return</font> FALSE; 00527 } 00528 00529 retval = FALSE; 00530 00531 <font class="keywordflow">if</font> (!dbus_connection_set_watch_functions (connection, 00532 add_connection_watch, 00533 remove_connection_watch, 00534 NULL, 00535 connection, 00536 NULL)) 00537 <font class="keywordflow">goto</font> out; 00538 00539 <font class="keywordflow">if</font> (!dbus_connection_set_timeout_functions (connection, 00540 add_connection_timeout, 00541 remove_connection_timeout, 00542 NULL, 00543 connection, NULL)) 00544 <font class="keywordflow">goto</font> 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 <font class="keywordflow">if</font> (d->link_in_connection_list == NULL) 00557 <font class="keywordflow">goto</font> out; 00558 00559 <font class="comment">/* Setup the connection with the dispatcher */</font> 00560 <font class="keywordflow">if</font> (!bus_dispatch_add_connection (connection)) 00561 <font class="keywordflow">goto</font> out; 00562 00563 <font class="keywordflow">if</font> (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE) 00564 { 00565 <font class="keywordflow">if</font> (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection)) 00566 { 00567 bus_dispatch_remove_connection (connection); 00568 <font class="keywordflow">goto</font> 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 <font class="comment">/* Note that we might disconnect ourselves here, but it only takes</font> 00578 <font class="comment"> * effect on return to the main loop. We call this to free up</font> 00579 <font class="comment"> * expired connections if possible, and to queue the timeout for our</font> 00580 <font class="comment"> * own expiration.</font> 00581 <font class="comment"> */</font> 00582 bus_connections_expire_incomplete (connections); 00583 00584 <font class="comment">/* And we might also disconnect ourselves here, but again it</font> 00585 <font class="comment"> * only takes effect on return to main loop.</font> 00586 <font class="comment"> */</font> 00587 <font class="keywordflow">if</font> (connections->n_incomplete > 00588 bus_context_get_max_incomplete_connections (connections->context)) 00589 { 00590 _dbus_verbose (<font class="stringliteral">"Number of incomplete connections exceeds max, dropping oldest one\n"</font>); 00591 00592 _dbus_assert (connections->incomplete != NULL); 00593 <font class="comment">/* Disconnect the oldest unauthenticated connection. FIXME</font> 00594 <font class="comment"> * would it be more secure to drop a *random* connection? This</font> 00595 <font class="comment"> * algorithm seems to mean that if someone can create new</font> 00596 <font class="comment"> * connections quickly enough, they can keep anyone else from</font> 00597 <font class="comment"> * completing authentication. But random may or may not really</font> 00598 <font class="comment"> * help with that, a more elaborate solution might be required.</font> 00599 <font class="comment"> */</font> 00600 dbus_connection_disconnect (connections->incomplete->data); 00601 } 00602 00603 retval = TRUE; 00604 00605 out: 00606 <font class="keywordflow">if</font> (!retval) 00607 { 00608 <font class="keywordflow">if</font> (!dbus_connection_set_watch_functions (connection, 00609 NULL, NULL, NULL, 00610 connection, 00611 NULL)) 00612 _dbus_assert_not_reached (<font class="stringliteral">"setting watch functions to NULL failed"</font>); 00613 00614 <font class="keywordflow">if</font> (!dbus_connection_set_timeout_functions (connection, 00615 NULL, NULL, NULL, 00616 connection, 00617 NULL)) 00618 _dbus_assert_not_reached (<font class="stringliteral">"setting timeout functions to NULL failed"</font>); 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 <font class="keywordflow">if</font> (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 <font class="keywordflow">if</font> (!dbus_connection_set_data (connection, 00635 connection_data_slot, 00636 NULL, NULL)) 00637 _dbus_assert_not_reached (<font class="stringliteral">"failed to set connection data to null"</font>); 00638 00639 <font class="comment">/* "d" has now been freed */</font> 00640 } 00641 00642 <font class="keywordflow">return</font> retval; 00643 } 00644 00645 <font class="keywordtype">void</font> 00646 bus_connections_expire_incomplete (BusConnections *connections) 00647 { 00648 <font class="keywordtype">int</font> next_interval; 00649 00650 next_interval = -1; 00651 00652 <font class="keywordflow">if</font> (connections->incomplete != NULL) 00653 { 00654 <font class="keywordtype">long</font> tv_sec, tv_usec; 00655 <a class="code" href="structDBusList.html">DBusList</a> *link; 00656 <font class="keywordtype">int</font> 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 <font class="keywordflow">while</font> (link != NULL) 00663 { 00664 <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&connections->incomplete, link); 00665 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection; 00666 BusConnectionData *d; 00667 <font class="keywordtype">double</font> elapsed; 00668 00669 connection = link-><a class="code" href="structDBusList.html#m2">data</a>; 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 <font class="keywordflow">if</font> (elapsed >= (double) auth_timeout) 00679 { 00680 _dbus_verbose (<font class="stringliteral">"Timing out authentication for connection %p\n"</font>, connection); 00681 dbus_connection_disconnect (connection); 00682 } 00683 <font class="keywordflow">else</font> 00684 { 00685 <font class="comment">/* We can end the loop, since the connections are in oldest-first order */</font> 00686 next_interval = ((double)auth_timeout) - elapsed; 00687 _dbus_verbose (<font class="stringliteral">"Connection %p authentication expires in %d milliseconds\n"</font>, 00688 connection, next_interval); 00689 00690 <font class="keywordflow">break</font>; 00691 } 00692 00693 link = next; 00694 } 00695 } 00696 00697 <font class="keywordflow">if</font> (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 (<font class="stringliteral">"Enabled incomplete connections timeout with interval %d, %d incomplete connections\n"</font>, 00704 next_interval, connections->n_incomplete); 00705 } 00706 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (dbus_timeout_get_enabled (connections->expire_timeout)) 00707 { 00708 _dbus_timeout_set_enabled (connections->expire_timeout, FALSE); 00709 00710 _dbus_verbose (<font class="stringliteral">"Disabled incomplete connections timeout, %d incomplete connections\n"</font>, 00711 connections->n_incomplete); 00712 } 00713 <font class="keywordflow">else</font> 00714 _dbus_verbose (<font class="stringliteral">"No need to disable incomplete connections timeout\n"</font>); 00715 } 00716 00717 <font class="keyword">static</font> dbus_bool_t 00718 expire_incomplete_timeout (<font class="keywordtype">void</font> *data) 00719 { 00720 BusConnections *connections = data; 00721 00722 _dbus_verbose (<font class="stringliteral">"Running %s\n"</font>, _DBUS_FUNCTION_NAME); 00723 00724 <font class="comment">/* note that this may remove the timeout */</font> 00725 bus_connections_expire_incomplete (connections); 00726 00727 <font class="keywordflow">return</font> TRUE; 00728 } 00729 00730 dbus_bool_t 00731 bus_connection_get_groups (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 00732 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> **groups, 00733 <font class="keywordtype">int</font> *n_groups, 00734 <a class="code" href="structDBusError.html">DBusError</a> *error) 00735 { 00736 BusConnectionData *d; 00737 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> uid; 00738 <a class="code" href="structDBusUserDatabase.html">DBusUserDatabase</a> *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 <font class="keywordflow">if</font> (dbus_connection_get_unix_user (connection, &uid)) 00750 { 00751 <font class="keywordflow">if</font> (!_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 (<font class="stringliteral">"Did not get any groups for UID %lu\n"</font>, 00757 uid); 00758 <font class="keywordflow">return</font> FALSE; 00759 } 00760 <font class="keywordflow">else</font> 00761 { 00762 _dbus_verbose (<font class="stringliteral">"Got %d groups for UID %lu\n"</font>, 00763 *n_groups, uid); 00764 <font class="keywordflow">return</font> TRUE; 00765 } 00766 } 00767 <font class="keywordflow">else</font> 00768 <font class="keywordflow">return</font> TRUE; <font class="comment">/* successfully got 0 groups */</font> 00769 } 00770 00771 dbus_bool_t 00772 bus_connection_is_in_group (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 00773 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> gid) 00774 { 00775 <font class="keywordtype">int</font> i; 00776 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> *group_ids; 00777 <font class="keywordtype">int</font> n_group_ids; 00778 00779 <font class="keywordflow">if</font> (!bus_connection_get_groups (connection, &group_ids, &n_group_ids, 00780 NULL)) 00781 <font class="keywordflow">return</font> FALSE; 00782 00783 i = 0; 00784 <font class="keywordflow">while</font> (i < n_group_ids) 00785 { 00786 <font class="keywordflow">if</font> (group_ids[i] == gid) 00787 { 00788 dbus_free (group_ids); 00789 <font class="keywordflow">return</font> TRUE; 00790 } 00791 ++i; 00792 } 00793 00794 dbus_free (group_ids); 00795 <font class="keywordflow">return</font> FALSE; 00796 } 00797 00798 BusClientPolicy* 00799 bus_connection_get_policy (<a class="code" href="structDBusConnection.html">DBusConnection</a> *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 <font class="keywordflow">return</font> d->policy; 00809 } 00810 00811 <font class="keyword">static</font> dbus_bool_t 00812 foreach_active (BusConnections *connections, 00813 BusConnectionForeachFunction function, 00814 <font class="keywordtype">void</font> *data) 00815 { 00816 <a class="code" href="structDBusList.html">DBusList</a> *link; 00817 00818 link = _dbus_list_get_first_link (&connections->completed); 00819 <font class="keywordflow">while</font> (link != NULL) 00820 { 00821 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = link-><a class="code" href="structDBusList.html#m2">data</a>; 00822 <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&connections->completed, link); 00823 00824 <font class="keywordflow">if</font> (!(* function) (connection, data)) 00825 <font class="keywordflow">return</font> FALSE; 00826 00827 link = next; 00828 } 00829 00830 <font class="keywordflow">return</font> TRUE; 00831 } 00832 00833 <font class="keyword">static</font> dbus_bool_t 00834 foreach_inactive (BusConnections *connections, 00835 BusConnectionForeachFunction function, 00836 <font class="keywordtype">void</font> *data) 00837 { 00838 <a class="code" href="structDBusList.html">DBusList</a> *link; 00839 00840 link = _dbus_list_get_first_link (&connections->incomplete); 00841 <font class="keywordflow">while</font> (link != NULL) 00842 { 00843 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection = link-><a class="code" href="structDBusList.html#m2">data</a>; 00844 <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&connections->incomplete, link); 00845 00846 <font class="keywordflow">if</font> (!(* function) (connection, data)) 00847 <font class="keywordflow">return</font> FALSE; 00848 00849 link = next; 00850 } 00851 00852 <font class="keywordflow">return</font> TRUE; 00853 } 00854 00864 <font class="keywordtype">void</font> 00865 bus_connections_foreach_active (BusConnections *connections, 00866 BusConnectionForeachFunction function, 00867 <font class="keywordtype">void</font> *data) 00868 { 00869 foreach_active (connections, function, data); 00870 } 00871 00880 <font class="keywordtype">void</font> 00881 bus_connections_foreach (BusConnections *connections, 00882 BusConnectionForeachFunction function, 00883 <font class="keywordtype">void</font> *data) 00884 { 00885 <font class="keywordflow">if</font> (!foreach_active (connections, function, data)) 00886 <font class="keywordflow">return</font>; 00887 00888 foreach_inactive (connections, function, data); 00889 } 00890 00891 BusContext* 00892 bus_connections_get_context (BusConnections *connections) 00893 { 00894 <font class="keywordflow">return</font> connections->context; 00895 } 00896 00897 <font class="comment">/*</font> 00898 <font class="comment"> * This is used to avoid covering the same connection twice when</font> 00899 <font class="comment"> * traversing connections. Note that it assumes we will</font> 00900 <font class="comment"> * bus_connection_mark_stamp() each connection at least once per</font> 00901 <font class="comment"> * INT_MAX increments of the global stamp, or wraparound would break</font> 00902 <font class="comment"> * things.</font> 00903 <font class="comment"> */</font> 00904 <font class="keywordtype">void</font> 00905 bus_connections_increment_stamp (BusConnections *connections) 00906 { 00907 connections->stamp += 1; 00908 } 00909 00910 <font class="comment">/* Mark connection with current stamp, return TRUE if it</font> 00911 <font class="comment"> * didn't already have that stamp</font> 00912 <font class="comment"> */</font> 00913 dbus_bool_t 00914 bus_connection_mark_stamp (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00915 { 00916 BusConnectionData *d; 00917 00918 d = BUS_CONNECTION_DATA (connection); 00919 00920 _dbus_assert (d != NULL); 00921 00922 <font class="keywordflow">if</font> (d->stamp == d->connections->stamp) 00923 <font class="keywordflow">return</font> FALSE; 00924 <font class="keywordflow">else</font> 00925 { 00926 d->stamp = d->connections->stamp; 00927 <font class="keywordflow">return</font> TRUE; 00928 } 00929 } 00930 00931 BusContext* 00932 bus_connection_get_context (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00933 { 00934 BusConnectionData *d; 00935 00936 d = BUS_CONNECTION_DATA (connection); 00937 00938 _dbus_assert (d != NULL); 00939 00940 <font class="keywordflow">return</font> d->connections->context; 00941 } 00942 00943 BusConnections* 00944 bus_connection_get_connections (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00945 { 00946 BusConnectionData *d; 00947 00948 d = BUS_CONNECTION_DATA (connection); 00949 00950 _dbus_assert (d != NULL); 00951 00952 <font class="keywordflow">return</font> d->connections; 00953 } 00954 00955 BusRegistry* 00956 bus_connection_get_registry (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00957 { 00958 BusConnectionData *d; 00959 00960 d = BUS_CONNECTION_DATA (connection); 00961 00962 _dbus_assert (d != NULL); 00963 00964 <font class="keywordflow">return</font> bus_context_get_registry (d->connections->context); 00965 } 00966 00967 BusActivation* 00968 bus_connection_get_activation (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00969 { 00970 BusConnectionData *d; 00971 00972 d = BUS_CONNECTION_DATA (connection); 00973 00974 _dbus_assert (d != NULL); 00975 00976 <font class="keywordflow">return</font> bus_context_get_activation (d->connections->context); 00977 } 00978 00979 BusMatchmaker* 00980 bus_connection_get_matchmaker (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00981 { 00982 BusConnectionData *d; 00983 00984 d = BUS_CONNECTION_DATA (connection); 00985 00986 _dbus_assert (d != NULL); 00987 00988 <font class="keywordflow">return</font> bus_context_get_matchmaker (d->connections->context); 00989 } 00990 00997 dbus_bool_t 00998 bus_connection_is_active (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 00999 { 01000 BusConnectionData *d; 01001 01002 d = BUS_CONNECTION_DATA (connection); 01003 01004 <font class="keywordflow">return</font> d != NULL && d->name != NULL; 01005 } 01006 01007 dbus_bool_t 01008 bus_connection_preallocate_oom_error (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 01009 { 01010 <a class="code" href="structDBusMessage.html">DBusMessage</a> *message; 01011 <a class="code" href="structDBusPreallocatedSend.html">DBusPreallocatedSend</a> *preallocated; 01012 BusConnectionData *d; 01013 01014 d = BUS_CONNECTION_DATA (connection); 01015 01016 _dbus_assert (d != NULL); 01017 01018 <font class="keywordflow">if</font> (d->oom_preallocated != NULL) 01019 <font class="keywordflow">return</font> TRUE; 01020 01021 preallocated = dbus_connection_preallocate_send (connection); 01022 <font class="keywordflow">if</font> (preallocated == NULL) 01023 <font class="keywordflow">return</font> FALSE; 01024 01025 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 01026 01027 <font class="keywordflow">if</font> (message == NULL) 01028 { 01029 dbus_connection_free_preallocated_send (connection, preallocated); 01030 <font class="keywordflow">return</font> FALSE; 01031 } 01032 01033 <font class="comment">/* d->name may be NULL, but that is OK */</font> 01034 <font class="keywordflow">if</font> (!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 <font class="keywordflow">return</font> FALSE; 01042 } 01043 01044 <font class="comment">/* set reply serial to placeholder value just so space is already allocated</font> 01045 <font class="comment"> * for it.</font> 01046 <font class="comment"> */</font> 01047 <font class="keywordflow">if</font> (!dbus_message_set_reply_serial (message, 14)) 01048 { 01049 dbus_connection_free_preallocated_send (connection, preallocated); 01050 dbus_message_unref (message); 01051 <font class="keywordflow">return</font> FALSE; 01052 } 01053 01054 d->oom_message = message; 01055 d->oom_preallocated = preallocated; 01056 01057 <font class="keywordflow">return</font> TRUE; 01058 } 01059 01060 <font class="keywordtype">void</font> 01061 bus_connection_send_oom_error (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01062 <a class="code" href="structDBusMessage.html">DBusMessage</a> *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 <font class="comment">/* should always succeed since we set it to a placeholder earlier */</font> 01072 <font class="keywordflow">if</font> (!dbus_message_set_reply_serial (d->oom_message, 01073 dbus_message_get_serial (in_reply_to))) 01074 _dbus_assert_not_reached (<font class="stringliteral">"Failed to set reply serial for preallocated oom message"</font>); 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 <font class="keywordtype">void</font> 01087 bus_connection_add_match_rule_link (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01088 <a class="code" href="structDBusList.html">DBusList</a> *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 (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01102 BusMatchRule *rule) 01103 { 01104 <a class="code" href="structDBusList.html">DBusList</a> *link; 01105 01106 link = _dbus_list_alloc_link (rule); 01107 01108 <font class="keywordflow">if</font> (link == NULL) 01109 <font class="keywordflow">return</font> FALSE; 01110 01111 bus_connection_add_match_rule_link (connection, link); 01112 01113 <font class="keywordflow">return</font> TRUE; 01114 } 01115 01116 <font class="keywordtype">void</font> 01117 bus_connection_remove_match_rule (<a class="code" href="structDBusConnection.html">DBusConnection</a> *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 <font class="keywordtype">int</font> 01132 bus_connection_get_n_match_rules (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 01133 { 01134 BusConnectionData *d; 01135 01136 d = BUS_CONNECTION_DATA (connection); 01137 _dbus_assert (d != NULL); 01138 01139 <font class="keywordflow">return</font> d->n_match_rules; 01140 } 01141 01142 <font class="keywordtype">void</font> 01143 bus_connection_add_owned_service_link (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01144 <a class="code" href="structDBusList.html">DBusList</a> *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 (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01158 BusService *service) 01159 { 01160 <a class="code" href="structDBusList.html">DBusList</a> *link; 01161 01162 link = _dbus_list_alloc_link (service); 01163 01164 <font class="keywordflow">if</font> (link == NULL) 01165 <font class="keywordflow">return</font> FALSE; 01166 01167 bus_connection_add_owned_service_link (connection, link); 01168 01169 <font class="keywordflow">return</font> TRUE; 01170 } 01171 01172 <font class="keywordtype">void</font> 01173 bus_connection_remove_owned_service (<a class="code" href="structDBusConnection.html">DBusConnection</a> *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 <font class="keywordtype">int</font> 01188 bus_connection_get_n_services_owned (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 01189 { 01190 BusConnectionData *d; 01191 01192 d = BUS_CONNECTION_DATA (connection); 01193 _dbus_assert (d != NULL); 01194 01195 <font class="keywordflow">return</font> d->n_services_owned; 01196 } 01197 01198 dbus_bool_t 01199 bus_connection_complete (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01200 <font class="keyword">const</font> <a class="code" href="structDBusString.html">DBusString</a> *name, 01201 <a class="code" href="structDBusError.html">DBusError</a> *error) 01202 { 01203 BusConnectionData *d; 01204 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> 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 <font class="keywordflow">if</font> (!_dbus_string_copy_data (name, &d->name)) 01214 { 01215 BUS_SET_OOM (error); 01216 <font class="keywordflow">return</font> FALSE; 01217 } 01218 01219 _dbus_assert (d->name != NULL); 01220 01221 _dbus_verbose (<font class="stringliteral">"Name %s assigned to %p\n"</font>, d->name, connection); 01222 01223 d->policy = bus_context_create_client_policy (d->connections->context, 01224 connection, 01225 error); 01226 01227 <font class="comment">/* we may have a NULL policy on OOM or error getting list of</font> 01228 <font class="comment"> * groups for a user. In the latter case we don't handle it so</font> 01229 <font class="comment"> * well currently, as it will just keep failing over and over.</font> 01230 <font class="comment"> */</font> 01231 01232 <font class="keywordflow">if</font> (d->policy == NULL) 01233 { 01234 _dbus_verbose (<font class="stringliteral">"Failed to create security policy for connection %p\n"</font>, 01235 connection); 01236 _DBUS_ASSERT_ERROR_IS_SET (error); 01237 dbus_free (d->name); 01238 d->name = NULL; 01239 <font class="keywordflow">return</font> FALSE; 01240 } 01241 01242 <font class="keywordflow">if</font> (dbus_connection_get_unix_user (connection, &uid)) 01243 { 01244 <font class="keywordflow">if</font> (!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 <font class="keywordflow">return</font> FALSE; 01251 } 01252 } 01253 01254 <font class="comment">/* Now the connection is active, move it between lists */</font> 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 <font class="comment">/* See if we can remove the timeout */</font> 01266 bus_connections_expire_incomplete (d->connections); 01267 01268 _dbus_assert (bus_connection_is_active (connection)); 01269 01270 <font class="keywordflow">return</font> TRUE; 01271 } 01272 01273 <font class="keyword">const</font> <font class="keywordtype">char</font> * 01274 bus_connection_get_name (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 01275 { 01276 BusConnectionData *d; 01277 01278 d = BUS_CONNECTION_DATA (connection); 01279 _dbus_assert (d != NULL); 01280 01281 <font class="keywordflow">return</font> d->name; 01282 } 01283 01288 dbus_bool_t 01289 bus_connections_check_limits (BusConnections *connections, 01290 <a class="code" href="structDBusConnection.html">DBusConnection</a> *requesting_completion, 01291 <a class="code" href="structDBusError.html">DBusError</a> *error) 01292 { 01293 BusConnectionData *d; 01294 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> uid; 01295 01296 d = BUS_CONNECTION_DATA (requesting_completion); 01297 _dbus_assert (d != NULL); 01298 01299 _dbus_assert (d->name == NULL); 01300 01301 <font class="keywordflow">if</font> (connections->n_completed >= 01302 bus_context_get_max_completed_connections (connections->context)) 01303 { 01304 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 01305 <font class="stringliteral">"The maximum number of active connections has been reached"</font>); 01306 <font class="keywordflow">return</font> FALSE; 01307 } 01308 01309 <font class="keywordflow">if</font> (dbus_connection_get_unix_user (requesting_completion, &uid)) 01310 { 01311 <font class="keywordflow">if</font> (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 <font class="stringliteral">"The maximum number of active connections for UID %lu has been reached"</font>, 01316 uid); 01317 <font class="keywordflow">return</font> FALSE; 01318 } 01319 } 01320 01321 <font class="keywordflow">return</font> TRUE; 01322 } 01323 01324 01325 <font class="comment">/*</font> 01326 <font class="comment"> * Transactions</font> 01327 <font class="comment"> *</font> 01328 <font class="comment"> * Note that this is fairly fragile; in particular, don't try to use</font> 01329 <font class="comment"> * one transaction across any main loop iterations.</font> 01330 <font class="comment"> */</font> 01331 01332 <font class="keyword">typedef</font> <font class="keyword">struct</font> 01333 <font class="keyword"></font>{ 01334 BusTransaction *transaction; 01335 <a class="code" href="structDBusMessage.html">DBusMessage</a> *message; 01336 <a class="code" href="structDBusPreallocatedSend.html">DBusPreallocatedSend</a> *preallocated; 01337 } MessageToSend; 01338 01339 <font class="keyword">typedef</font> <font class="keyword">struct</font> 01340 <font class="keyword"></font>{ 01341 BusTransactionCancelFunction cancel_function; 01342 DBusFreeFunction free_data_function; 01343 <font class="keywordtype">void</font> *data; 01344 } CancelHook; 01345 01346 <font class="keyword">struct </font>BusTransaction 01347 { 01348 <a class="code" href="structDBusList.html">DBusList</a> *connections; 01349 BusContext *context; 01350 <a class="code" href="structDBusList.html">DBusList</a> *cancel_hooks; 01351 }; 01352 01353 <font class="keyword">static</font> <font class="keywordtype">void</font> 01354 message_to_send_free (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01355 MessageToSend *to_send) 01356 { 01357 <font class="keywordflow">if</font> (to_send->message) 01358 dbus_message_unref (to_send->message); 01359 01360 <font class="keywordflow">if</font> (to_send->preallocated) 01361 dbus_connection_free_preallocated_send (connection, to_send->preallocated); 01362 01363 dbus_free (to_send); 01364 } 01365 01366 <font class="keyword">static</font> <font class="keywordtype">void</font> 01367 cancel_hook_cancel (<font class="keywordtype">void</font> *element, 01368 <font class="keywordtype">void</font> *data) 01369 { 01370 CancelHook *ch = element; 01371 01372 _dbus_verbose (<font class="stringliteral">"Running transaction cancel hook\n"</font>); 01373 01374 <font class="keywordflow">if</font> (ch->cancel_function) 01375 (* ch->cancel_function) (ch->data); 01376 } 01377 01378 <font class="keyword">static</font> <font class="keywordtype">void</font> 01379 cancel_hook_free (<font class="keywordtype">void</font> *element, 01380 <font class="keywordtype">void</font> *data) 01381 { 01382 CancelHook *ch = element; 01383 01384 <font class="keywordflow">if</font> (ch->free_data_function) 01385 (* ch->free_data_function) (ch->data); 01386 01387 dbus_free (ch); 01388 } 01389 01390 <font class="keyword">static</font> <font class="keywordtype">void</font> 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 <font class="keywordflow">if</font> (transaction == NULL) 01406 <font class="keywordflow">return</font> NULL; 01407 01408 transaction->context = context; 01409 01410 <font class="keywordflow">return</font> transaction; 01411 } 01412 01413 BusContext* 01414 bus_transaction_get_context (BusTransaction *transaction) 01415 { 01416 <font class="keywordflow">return</font> transaction->context; 01417 } 01418 01419 BusConnections* 01420 bus_transaction_get_connections (BusTransaction *transaction) 01421 { 01422 <font class="keywordflow">return</font> bus_context_get_connections (transaction->context); 01423 } 01424 01425 dbus_bool_t 01426 bus_transaction_send_from_driver (BusTransaction *transaction, 01427 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01428 <a class="code" href="structDBusMessage.html">DBusMessage</a> *message) 01429 { 01430 <font class="comment">/* We have to set the sender to the driver, and have</font> 01431 <font class="comment"> * to check security policy since it was not done in</font> 01432 <font class="comment"> * dispatch.c</font> 01433 <font class="comment"> */</font> 01434 _dbus_verbose (<font class="stringliteral">"Sending %s %s %s from driver\n"</font>, 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 <font class="keywordflow">if</font> (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS)) 01443 <font class="keywordflow">return</font> FALSE; 01444 01445 <font class="comment">/* If security policy doesn't allow the message, we silently</font> 01446 <font class="comment"> * eat it; the driver doesn't care about getting a reply.</font> 01447 <font class="comment"> */</font> 01448 <font class="keywordflow">if</font> (!bus_context_check_security_policy (bus_transaction_get_context (transaction), 01449 NULL, connection, connection, message, NULL)) 01450 <font class="keywordflow">return</font> TRUE; 01451 01452 <font class="keywordflow">return</font> bus_transaction_send (transaction, connection, message); 01453 } 01454 01455 dbus_bool_t 01456 bus_transaction_send (BusTransaction *transaction, 01457 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01458 <a class="code" href="structDBusMessage.html">DBusMessage</a> *message) 01459 { 01460 MessageToSend *to_send; 01461 BusConnectionData *d; 01462 <a class="code" href="structDBusList.html">DBusList</a> *link; 01463 01464 _dbus_verbose (<font class="stringliteral">" trying to add %s interface=%s member=%s error=%s to transaction%s\n"</font>, 01465 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? <font class="stringliteral">"error"</font> : 01466 dbus_message_get_reply_serial (message) != 0 ? <font class="stringliteral">"reply"</font> : 01467 <font class="stringliteral">"message"</font>, 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 <font class="keywordflow">if</font> (!dbus_connection_get_is_connected (connection)) 01480 <font class="keywordflow">return</font> TRUE; <font class="comment">/* silently ignore disconnected connections */</font> 01481 01482 d = BUS_CONNECTION_DATA (connection); 01483 _dbus_assert (d != NULL); 01484 01485 to_send = dbus_new (MessageToSend, 1); 01486 <font class="keywordflow">if</font> (to_send == NULL) 01487 { 01488 <font class="keywordflow">return</font> FALSE; 01489 } 01490 01491 to_send->preallocated = dbus_connection_preallocate_send (connection); 01492 <font class="keywordflow">if</font> (to_send->preallocated == NULL) 01493 { 01494 dbus_free (to_send); 01495 <font class="keywordflow">return</font> FALSE; 01496 } 01497 01498 dbus_message_ref (message); 01499 to_send->message = message; 01500 to_send->transaction = transaction; 01501 01502 _dbus_verbose (<font class="stringliteral">"about to prepend message\n"</font>); 01503 01504 <font class="keywordflow">if</font> (!_dbus_list_prepend (&d->transaction_messages, to_send)) 01505 { 01506 message_to_send_free (connection, to_send); 01507 <font class="keywordflow">return</font> FALSE; 01508 } 01509 01510 _dbus_verbose (<font class="stringliteral">"prepended message\n"</font>); 01511 01512 <font class="comment">/* See if we already had this connection in the list</font> 01513 <font class="comment"> * for this transaction. If we have a pending message,</font> 01514 <font class="comment"> * then we should already be in transaction->connections</font> 01515 <font class="comment"> */</font> 01516 link = _dbus_list_get_first_link (&d->transaction_messages); 01517 _dbus_assert (link-><a class="code" href="structDBusList.html#m2">data</a> == to_send); 01518 link = _dbus_list_get_next_link (&d->transaction_messages, link); 01519 <font class="keywordflow">while</font> (link != NULL) 01520 { 01521 MessageToSend *m = link-><a class="code" href="structDBusList.html#m2">data</a>; 01522 <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&d->transaction_messages, link); 01523 01524 <font class="keywordflow">if</font> (m->transaction == transaction) 01525 <font class="keywordflow">break</font>; 01526 01527 link = next; 01528 } 01529 01530 <font class="keywordflow">if</font> (link == NULL) 01531 { 01532 <font class="keywordflow">if</font> (!_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 <font class="keywordflow">return</font> FALSE; 01537 } 01538 } 01539 01540 <font class="keywordflow">return</font> TRUE; 01541 } 01542 01543 <font class="keyword">static</font> <font class="keywordtype">void</font> 01544 connection_cancel_transaction (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01545 BusTransaction *transaction) 01546 { 01547 <a class="code" href="structDBusList.html">DBusList</a> *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 <font class="keywordflow">while</font> (link != NULL) 01555 { 01556 MessageToSend *m = link-><a class="code" href="structDBusList.html#m2">data</a>; 01557 <a class="code" href="structDBusList.html">DBusList</a> *next = _dbus_list_get_next_link (&d->transaction_messages, link); 01558 01559 <font class="keywordflow">if</font> (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 <font class="keywordtype">void</font> 01572 bus_transaction_cancel_and_free (BusTransaction *transaction) 01573 { 01574 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection; 01575 01576 _dbus_verbose (<font class="stringliteral">"TRANSACTION: cancelled\n"</font>); 01577 01578 <font class="keywordflow">while</font> ((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 <font class="keyword">static</font> <font class="keywordtype">void</font> 01592 connection_execute_transaction (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01593 BusTransaction *transaction) 01594 { 01595 <a class="code" href="structDBusList.html">DBusList</a> *link; 01596 BusConnectionData *d; 01597 01598 d = BUS_CONNECTION_DATA (connection); 01599 _dbus_assert (d != NULL); 01600 01601 <font class="comment">/* Send the queue in order (FIFO) */</font> 01602 link = _dbus_list_get_last_link (&d->transaction_messages); 01603 <font class="keywordflow">while</font> (link != NULL) 01604 { 01605 MessageToSend *m = link-><a class="code" href="structDBusList.html#m2">data</a>; 01606 <a class="code" href="structDBusList.html">DBusList</a> *prev = _dbus_list_get_prev_link (&d->transaction_messages, link); 01607 01608 <font class="keywordflow">if</font> (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; <font class="comment">/* so we don't double-free it */</font> 01621 01622 message_to_send_free (connection, m); 01623 } 01624 01625 link = prev; 01626 } 01627 } 01628 01629 <font class="keywordtype">void</font> 01630 bus_transaction_execute_and_free (BusTransaction *transaction) 01631 { 01632 <font class="comment">/* For each connection in transaction->connections</font> 01633 <font class="comment"> * send the messages</font> 01634 <font class="comment"> */</font> 01635 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection; 01636 01637 _dbus_verbose (<font class="stringliteral">"TRANSACTION: executing\n"</font>); 01638 01639 <font class="keywordflow">while</font> ((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 <font class="keyword">static</font> <font class="keywordtype">void</font> 01650 bus_connection_remove_transactions (<a class="code" href="structDBusConnection.html">DBusConnection</a> *connection) 01651 { 01652 MessageToSend *to_send; 01653 BusConnectionData *d; 01654 01655 d = BUS_CONNECTION_DATA (connection); 01656 _dbus_assert (d != NULL); 01657 01658 <font class="keywordflow">while</font> ((to_send = _dbus_list_get_first (&d->transaction_messages))) 01659 { 01660 <font class="comment">/* only has an effect for the first MessageToSend listing this transaction */</font> 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 <a class="code" href="structDBusConnection.html">DBusConnection</a> *connection, 01675 <font class="keyword">const</font> <a class="code" href="structDBusError.html">DBusError</a> *error, 01676 <a class="code" href="structDBusMessage.html">DBusMessage</a> *in_reply_to) 01677 { 01678 <a class="code" href="structDBusMessage.html">DBusMessage</a> *reply; 01679 01680 _dbus_assert (error != NULL); 01681 _DBUS_ASSERT_ERROR_IS_SET (error); 01682 01683 _dbus_verbose (<font class="stringliteral">"Sending error reply %s \"%s\"\n"</font>, 01684 error-><a class="code" href="structDBusError.html#m0">name</a>, error-><a class="code" href="structDBusError.html#m1">message</a>); 01685 01686 reply = dbus_message_new_error (in_reply_to, 01687 error-><a class="code" href="structDBusError.html#m0">name</a>, 01688 error-><a class="code" href="structDBusError.html#m1">message</a>); 01689 <font class="keywordflow">if</font> (reply == NULL) 01690 <font class="keywordflow">return</font> FALSE; 01691 01692 <font class="keywordflow">if</font> (!bus_transaction_send_from_driver (transaction, connection, reply)) 01693 { 01694 dbus_message_unref (reply); 01695 <font class="keywordflow">return</font> FALSE; 01696 } 01697 01698 dbus_message_unref (reply); 01699 01700 <font class="keywordflow">return</font> TRUE; 01701 } 01702 01703 dbus_bool_t 01704 bus_transaction_add_cancel_hook (BusTransaction *transaction, 01705 BusTransactionCancelFunction cancel_function, 01706 <font class="keywordtype">void</font> *data, 01707 DBusFreeFunction free_data_function) 01708 { 01709 CancelHook *ch; 01710 01711 ch = dbus_new (CancelHook, 1); 01712 <font class="keywordflow">if</font> (ch == NULL) 01713 <font class="keywordflow">return</font> FALSE; 01714 01715 ch->cancel_function = cancel_function; 01716 ch->data = data; 01717 ch->free_data_function = free_data_function; 01718 01719 <font class="comment">/* It's important that the hooks get run in reverse order that they</font> 01720 <font class="comment"> * were added</font> 01721 <font class="comment"> */</font> 01722 <font class="keywordflow">if</font> (!_dbus_list_prepend (&transaction->cancel_hooks, ch)) 01723 { 01724 dbus_free (ch); 01725 <font class="keywordflow">return</font> FALSE; 01726 } 01727 01728 <font class="keywordflow">return</font> TRUE; 01729 } </pre></div><hr><address align="right"><small>Generated on Mon Sep 29 21:30:59 2003 for D-BUS by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.15 </small></address> </body> </html>