Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-transport-unix.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 00024 #include "dbus-internals.h" 00025 #include "dbus-connection-internal.h" 00026 #include "dbus-transport-unix.h" 00027 #include "dbus-transport-protected.h" 00028 #include "dbus-watch.h" 00029 00030 00042 typedef struct DBusTransportUnix DBusTransportUnix; 00043 00047 struct DBusTransportUnix 00048 { 00049 DBusTransport base; 00050 int fd; 00051 DBusWatch *read_watch; 00052 DBusWatch *write_watch; 00054 int max_bytes_read_per_iteration; 00055 int max_bytes_written_per_iteration; 00057 int message_bytes_written; 00061 DBusString encoded_outgoing; 00064 DBusString encoded_incoming; 00067 }; 00068 00069 static void 00070 free_watches (DBusTransport *transport) 00071 { 00072 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00073 00074 if (unix_transport->read_watch) 00075 { 00076 if (transport->connection) 00077 _dbus_connection_remove_watch (transport->connection, 00078 unix_transport->read_watch); 00079 _dbus_watch_invalidate (unix_transport->read_watch); 00080 _dbus_watch_unref (unix_transport->read_watch); 00081 unix_transport->read_watch = NULL; 00082 } 00083 00084 if (unix_transport->write_watch) 00085 { 00086 if (transport->connection) 00087 _dbus_connection_remove_watch (transport->connection, 00088 unix_transport->write_watch); 00089 _dbus_watch_invalidate (unix_transport->write_watch); 00090 _dbus_watch_unref (unix_transport->write_watch); 00091 unix_transport->write_watch = NULL; 00092 } 00093 } 00094 00095 static void 00096 unix_finalize (DBusTransport *transport) 00097 { 00098 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00099 00100 free_watches (transport); 00101 00102 _dbus_string_free (&unix_transport->encoded_outgoing); 00103 _dbus_string_free (&unix_transport->encoded_incoming); 00104 00105 _dbus_transport_finalize_base (transport); 00106 00107 _dbus_assert (unix_transport->read_watch == NULL); 00108 _dbus_assert (unix_transport->write_watch == NULL); 00109 00110 dbus_free (transport); 00111 } 00112 00113 static void 00114 check_write_watch (DBusTransport *transport) 00115 { 00116 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00117 dbus_bool_t need_write_watch; 00118 00119 if (transport->connection == NULL) 00120 return; 00121 00122 if (transport->disconnected) 00123 { 00124 _dbus_assert (unix_transport->write_watch == NULL); 00125 return; 00126 } 00127 00128 _dbus_transport_ref (transport); 00129 00130 if (_dbus_transport_get_is_authenticated (transport)) 00131 need_write_watch = transport->messages_need_sending; 00132 else 00133 need_write_watch = transport->send_credentials_pending || 00134 _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; 00135 00136 _dbus_connection_toggle_watch (transport->connection, 00137 unix_transport->write_watch, 00138 need_write_watch); 00139 00140 _dbus_transport_unref (transport); 00141 } 00142 00143 static void 00144 check_read_watch (DBusTransport *transport) 00145 { 00146 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00147 dbus_bool_t need_read_watch; 00148 00149 if (transport->connection == NULL) 00150 return; 00151 00152 if (transport->disconnected) 00153 { 00154 _dbus_assert (unix_transport->read_watch == NULL); 00155 return; 00156 } 00157 00158 _dbus_transport_ref (transport); 00159 00160 if (_dbus_transport_get_is_authenticated (transport)) 00161 need_read_watch = 00162 _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size; 00163 else 00164 need_read_watch = transport->receive_credentials_pending || 00165 _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT; 00166 00167 _dbus_connection_toggle_watch (transport->connection, 00168 unix_transport->read_watch, 00169 need_read_watch); 00170 00171 _dbus_transport_unref (transport); 00172 } 00173 00174 static void 00175 do_io_error (DBusTransport *transport) 00176 { 00177 _dbus_transport_ref (transport); 00178 _dbus_transport_disconnect (transport); 00179 _dbus_transport_unref (transport); 00180 } 00181 00182 /* return value is whether we successfully read any new data. */ 00183 static dbus_bool_t 00184 read_data_into_auth (DBusTransport *transport, 00185 dbus_bool_t *oom) 00186 { 00187 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00188 DBusString *buffer; 00189 int bytes_read; 00190 00191 *oom = FALSE; 00192 00193 _dbus_auth_get_buffer (transport->auth, &buffer); 00194 00195 bytes_read = _dbus_read (unix_transport->fd, 00196 buffer, unix_transport->max_bytes_read_per_iteration); 00197 00198 _dbus_auth_return_buffer (transport->auth, buffer, 00199 bytes_read > 0 ? bytes_read : 0); 00200 00201 if (bytes_read > 0) 00202 { 00203 _dbus_verbose (" read %d bytes in auth phase\n", bytes_read); 00204 00205 return TRUE; 00206 } 00207 else if (bytes_read < 0) 00208 { 00209 /* EINTR already handled for us */ 00210 00211 if (errno == ENOMEM) 00212 { 00213 *oom = TRUE; 00214 } 00215 else if (errno == EAGAIN || 00216 errno == EWOULDBLOCK) 00217 ; /* do nothing, just return FALSE below */ 00218 else 00219 { 00220 _dbus_verbose ("Error reading from remote app: %s\n", 00221 _dbus_strerror (errno)); 00222 do_io_error (transport); 00223 } 00224 00225 return FALSE; 00226 } 00227 else 00228 { 00229 _dbus_assert (bytes_read == 0); 00230 00231 _dbus_verbose ("Disconnected from remote app\n"); 00232 do_io_error (transport); 00233 00234 return FALSE; 00235 } 00236 } 00237 00238 /* Return value is whether we successfully wrote any bytes */ 00239 static dbus_bool_t 00240 write_data_from_auth (DBusTransport *transport) 00241 { 00242 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00243 int bytes_written; 00244 const DBusString *buffer; 00245 00246 if (!_dbus_auth_get_bytes_to_send (transport->auth, 00247 &buffer)) 00248 return FALSE; 00249 00250 bytes_written = _dbus_write (unix_transport->fd, 00251 buffer, 00252 0, _dbus_string_get_length (buffer)); 00253 00254 if (bytes_written > 0) 00255 { 00256 _dbus_auth_bytes_sent (transport->auth, bytes_written); 00257 return TRUE; 00258 } 00259 else if (bytes_written < 0) 00260 { 00261 /* EINTR already handled for us */ 00262 00263 if (errno == EAGAIN || 00264 errno == EWOULDBLOCK) 00265 ; 00266 else 00267 { 00268 _dbus_verbose ("Error writing to remote app: %s\n", 00269 _dbus_strerror (errno)); 00270 do_io_error (transport); 00271 } 00272 } 00273 00274 return FALSE; 00275 } 00276 00277 static void 00278 exchange_credentials (DBusTransport *transport, 00279 dbus_bool_t do_reading, 00280 dbus_bool_t do_writing) 00281 { 00282 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00283 00284 if (do_writing && transport->send_credentials_pending) 00285 { 00286 if (_dbus_send_credentials_unix_socket (unix_transport->fd, 00287 NULL)) 00288 { 00289 transport->send_credentials_pending = FALSE; 00290 } 00291 else 00292 { 00293 _dbus_verbose ("Failed to write credentials\n"); 00294 do_io_error (transport); 00295 } 00296 } 00297 00298 if (do_reading && transport->receive_credentials_pending) 00299 { 00300 if (_dbus_read_credentials_unix_socket (unix_transport->fd, 00301 &transport->credentials, 00302 NULL)) 00303 { 00304 transport->receive_credentials_pending = FALSE; 00305 } 00306 else 00307 { 00308 _dbus_verbose ("Failed to read credentials\n"); 00309 do_io_error (transport); 00310 } 00311 } 00312 00313 if (!(transport->send_credentials_pending || 00314 transport->receive_credentials_pending)) 00315 { 00316 _dbus_auth_set_credentials (transport->auth, 00317 &transport->credentials); 00318 } 00319 } 00320 00321 static dbus_bool_t 00322 do_authentication (DBusTransport *transport, 00323 dbus_bool_t do_reading, 00324 dbus_bool_t do_writing) 00325 { 00326 dbus_bool_t oom; 00327 00328 _dbus_transport_ref (transport); 00329 00330 oom = FALSE; 00331 00332 while (!_dbus_transport_get_is_authenticated (transport) && 00333 _dbus_transport_get_is_connected (transport)) 00334 { 00335 exchange_credentials (transport, do_reading, do_writing); 00336 00337 if (transport->send_credentials_pending || 00338 transport->receive_credentials_pending) 00339 { 00340 _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n", 00341 transport->send_credentials_pending, 00342 transport->receive_credentials_pending); 00343 goto out; 00344 } 00345 00346 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client") 00347 switch (_dbus_auth_do_work (transport->auth)) 00348 { 00349 case DBUS_AUTH_STATE_WAITING_FOR_INPUT: 00350 _dbus_verbose (" %s auth state: waiting for input\n", 00351 TRANSPORT_SIDE (transport)); 00352 if (!do_reading || !read_data_into_auth (transport, &oom)) 00353 goto out; 00354 break; 00355 00356 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: 00357 _dbus_verbose (" %s auth state: waiting for memory\n", 00358 TRANSPORT_SIDE (transport)); 00359 oom = TRUE; 00360 goto out; 00361 break; 00362 00363 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND: 00364 _dbus_verbose (" %s auth state: bytes to send\n", 00365 TRANSPORT_SIDE (transport)); 00366 if (!do_writing || !write_data_from_auth (transport)) 00367 goto out; 00368 break; 00369 00370 case DBUS_AUTH_STATE_NEED_DISCONNECT: 00371 _dbus_verbose (" %s auth state: need to disconnect\n", 00372 TRANSPORT_SIDE (transport)); 00373 do_io_error (transport); 00374 break; 00375 00376 case DBUS_AUTH_STATE_AUTHENTICATED: 00377 _dbus_verbose (" %s auth state: authenticated\n", 00378 TRANSPORT_SIDE (transport)); 00379 break; 00380 } 00381 } 00382 00383 out: 00384 check_read_watch (transport); 00385 check_write_watch (transport); 00386 _dbus_transport_unref (transport); 00387 00388 if (oom) 00389 return FALSE; 00390 else 00391 return TRUE; 00392 } 00393 00394 /* returns false on oom */ 00395 static dbus_bool_t 00396 do_writing (DBusTransport *transport) 00397 { 00398 int total; 00399 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00400 dbus_bool_t oom; 00401 00402 /* No messages without authentication! */ 00403 if (!_dbus_transport_get_is_authenticated (transport)) 00404 { 00405 _dbus_verbose ("Not authenticated, not writing anything\n"); 00406 return TRUE; 00407 } 00408 00409 if (transport->disconnected) 00410 { 00411 _dbus_verbose ("Not connected, not writing anything\n"); 00412 return TRUE; 00413 } 00414 00415 #if 0 00416 _dbus_verbose ("do_writing(), have_messages = %d\n", 00417 _dbus_connection_have_messages_to_send (transport->connection)); 00418 #endif 00419 00420 oom = FALSE; 00421 total = 0; 00422 00423 while (!transport->disconnected && 00424 _dbus_connection_have_messages_to_send (transport->connection)) 00425 { 00426 int bytes_written; 00427 DBusMessage *message; 00428 const DBusString *header; 00429 const DBusString *body; 00430 int header_len, body_len; 00431 int total_bytes_to_write; 00432 00433 if (total > unix_transport->max_bytes_written_per_iteration) 00434 { 00435 _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n", 00436 total, unix_transport->max_bytes_written_per_iteration); 00437 goto out; 00438 } 00439 00440 if (!dbus_watch_get_enabled (unix_transport->write_watch)) 00441 { 00442 _dbus_verbose ("write watch disabled, not writing more stuff\n"); 00443 goto out; 00444 } 00445 00446 message = _dbus_connection_get_message_to_send (transport->connection); 00447 _dbus_assert (message != NULL); 00448 _dbus_message_lock (message); 00449 00450 #if 0 00451 _dbus_verbose ("writing message %p\n", message); 00452 #endif 00453 00454 _dbus_message_get_network_data (message, 00455 &header, &body); 00456 00457 header_len = _dbus_string_get_length (header); 00458 body_len = _dbus_string_get_length (body); 00459 00460 if (_dbus_auth_needs_encoding (transport->auth)) 00461 { 00462 if (_dbus_string_get_length (&unix_transport->encoded_outgoing) == 0) 00463 { 00464 if (!_dbus_auth_encode_data (transport->auth, 00465 header, &unix_transport->encoded_outgoing)) 00466 { 00467 oom = TRUE; 00468 goto out; 00469 } 00470 00471 if (!_dbus_auth_encode_data (transport->auth, 00472 body, &unix_transport->encoded_outgoing)) 00473 { 00474 _dbus_string_set_length (&unix_transport->encoded_outgoing, 0); 00475 oom = TRUE; 00476 goto out; 00477 } 00478 } 00479 00480 total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_outgoing); 00481 00482 #if 0 00483 _dbus_verbose ("encoded message is %d bytes\n", 00484 total_bytes_to_write); 00485 #endif 00486 00487 bytes_written = 00488 _dbus_write (unix_transport->fd, 00489 &unix_transport->encoded_outgoing, 00490 unix_transport->message_bytes_written, 00491 total_bytes_to_write - unix_transport->message_bytes_written); 00492 } 00493 else 00494 { 00495 total_bytes_to_write = header_len + body_len; 00496 00497 #if 0 00498 _dbus_verbose ("message is %d bytes\n", 00499 total_bytes_to_write); 00500 #endif 00501 00502 if (unix_transport->message_bytes_written < header_len) 00503 { 00504 bytes_written = 00505 _dbus_write_two (unix_transport->fd, 00506 header, 00507 unix_transport->message_bytes_written, 00508 header_len - unix_transport->message_bytes_written, 00509 body, 00510 0, body_len); 00511 } 00512 else 00513 { 00514 bytes_written = 00515 _dbus_write (unix_transport->fd, 00516 body, 00517 (unix_transport->message_bytes_written - header_len), 00518 body_len - 00519 (unix_transport->message_bytes_written - header_len)); 00520 } 00521 } 00522 00523 if (bytes_written < 0) 00524 { 00525 /* EINTR already handled for us */ 00526 00527 if (errno == EAGAIN || 00528 errno == EWOULDBLOCK) 00529 goto out; 00530 else 00531 { 00532 _dbus_verbose ("Error writing to remote app: %s\n", 00533 _dbus_strerror (errno)); 00534 do_io_error (transport); 00535 goto out; 00536 } 00537 } 00538 else 00539 { 00540 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written, 00541 total_bytes_to_write); 00542 00543 total += bytes_written; 00544 unix_transport->message_bytes_written += bytes_written; 00545 00546 _dbus_assert (unix_transport->message_bytes_written <= 00547 total_bytes_to_write); 00548 00549 if (unix_transport->message_bytes_written == total_bytes_to_write) 00550 { 00551 unix_transport->message_bytes_written = 0; 00552 _dbus_string_set_length (&unix_transport->encoded_outgoing, 0); 00553 00554 _dbus_connection_message_sent (transport->connection, 00555 message); 00556 } 00557 } 00558 } 00559 00560 out: 00561 if (oom) 00562 return FALSE; 00563 else 00564 return TRUE; 00565 } 00566 00567 /* returns false on out-of-memory */ 00568 static dbus_bool_t 00569 do_reading (DBusTransport *transport) 00570 { 00571 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00572 DBusString *buffer; 00573 int bytes_read; 00574 int total; 00575 dbus_bool_t oom; 00576 00577 /* No messages without authentication! */ 00578 if (!_dbus_transport_get_is_authenticated (transport)) 00579 return TRUE; 00580 00581 oom = FALSE; 00582 00583 total = 0; 00584 00585 again: 00586 00587 /* See if we've exceeded max messages and need to disable reading */ 00588 check_read_watch (transport); 00589 00590 if (total > unix_transport->max_bytes_read_per_iteration) 00591 { 00592 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n", 00593 total, unix_transport->max_bytes_read_per_iteration); 00594 goto out; 00595 } 00596 00597 _dbus_assert (unix_transport->read_watch != NULL || 00598 transport->disconnected); 00599 00600 if (transport->disconnected) 00601 goto out; 00602 00603 if (!dbus_watch_get_enabled (unix_transport->read_watch)) 00604 return TRUE; 00605 00606 if (_dbus_auth_needs_decoding (transport->auth)) 00607 { 00608 if (_dbus_string_get_length (&unix_transport->encoded_incoming) > 0) 00609 bytes_read = _dbus_string_get_length (&unix_transport->encoded_incoming); 00610 else 00611 bytes_read = _dbus_read (unix_transport->fd, 00612 &unix_transport->encoded_incoming, 00613 unix_transport->max_bytes_read_per_iteration); 00614 00615 _dbus_assert (_dbus_string_get_length (&unix_transport->encoded_incoming) == 00616 bytes_read); 00617 00618 if (bytes_read > 0) 00619 { 00620 int orig_len; 00621 00622 _dbus_message_loader_get_buffer (transport->loader, 00623 &buffer); 00624 00625 orig_len = _dbus_string_get_length (buffer); 00626 00627 if (!_dbus_auth_decode_data (transport->auth, 00628 &unix_transport->encoded_incoming, 00629 buffer)) 00630 { 00631 _dbus_verbose ("Out of memory decoding incoming data\n"); 00632 oom = TRUE; 00633 goto out; 00634 } 00635 00636 _dbus_message_loader_return_buffer (transport->loader, 00637 buffer, 00638 _dbus_string_get_length (buffer) - orig_len); 00639 00640 _dbus_string_set_length (&unix_transport->encoded_incoming, 0); 00641 } 00642 } 00643 else 00644 { 00645 _dbus_message_loader_get_buffer (transport->loader, 00646 &buffer); 00647 00648 bytes_read = _dbus_read (unix_transport->fd, 00649 buffer, unix_transport->max_bytes_read_per_iteration); 00650 00651 _dbus_message_loader_return_buffer (transport->loader, 00652 buffer, 00653 bytes_read < 0 ? 0 : bytes_read); 00654 } 00655 00656 if (bytes_read < 0) 00657 { 00658 /* EINTR already handled for us */ 00659 00660 if (errno == ENOMEM) 00661 { 00662 _dbus_verbose ("Out of memory in read()/do_reading()\n"); 00663 oom = TRUE; 00664 goto out; 00665 } 00666 else if (errno == EAGAIN || 00667 errno == EWOULDBLOCK) 00668 goto out; 00669 else 00670 { 00671 _dbus_verbose ("Error reading from remote app: %s\n", 00672 _dbus_strerror (errno)); 00673 do_io_error (transport); 00674 goto out; 00675 } 00676 } 00677 else if (bytes_read == 0) 00678 { 00679 _dbus_verbose ("Disconnected from remote app\n"); 00680 do_io_error (transport); 00681 goto out; 00682 } 00683 else 00684 { 00685 _dbus_verbose (" read %d bytes\n", bytes_read); 00686 00687 total += bytes_read; 00688 00689 if (!_dbus_transport_queue_messages (transport)) 00690 { 00691 oom = TRUE; 00692 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n"); 00693 goto out; 00694 } 00695 00696 /* Try reading more data until we get EAGAIN and return, or 00697 * exceed max bytes per iteration. If in blocking mode of 00698 * course we'll block instead of returning. 00699 */ 00700 goto again; 00701 } 00702 00703 out: 00704 if (oom) 00705 return FALSE; 00706 else 00707 return TRUE; 00708 } 00709 00710 static dbus_bool_t 00711 unix_handle_watch (DBusTransport *transport, 00712 DBusWatch *watch, 00713 unsigned int flags) 00714 { 00715 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00716 00717 _dbus_assert (watch == unix_transport->read_watch || 00718 watch == unix_transport->write_watch); 00719 00720 /* Disconnect in case of an error. In case of hangup do not 00721 * disconnect the transport because data can still be in the buffer 00722 * and do_reading may need several iteration to read it all (because 00723 * of its max_bytes_read_per_iteration limit). The condition where 00724 * flags == HANGUP (without READABLE) probably never happen in fact. 00725 */ 00726 if ((flags & DBUS_WATCH_ERROR) || 00727 ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE))) 00728 { 00729 _dbus_verbose ("Hang up or error on watch\n"); 00730 _dbus_transport_disconnect (transport); 00731 return TRUE; 00732 } 00733 00734 if (watch == unix_transport->read_watch && 00735 (flags & DBUS_WATCH_READABLE)) 00736 { 00737 #if 0 00738 _dbus_verbose ("handling read watch (%x)\n", flags); 00739 #endif 00740 if (!do_authentication (transport, TRUE, FALSE)) 00741 return FALSE; 00742 00743 if (!do_reading (transport)) 00744 { 00745 _dbus_verbose ("no memory to read\n"); 00746 return FALSE; 00747 } 00748 } 00749 else if (watch == unix_transport->write_watch && 00750 (flags & DBUS_WATCH_WRITABLE)) 00751 { 00752 #if 0 00753 _dbus_verbose ("handling write watch, messages_need_sending = %d\n", 00754 transport->messages_need_sending); 00755 #endif 00756 if (!do_authentication (transport, FALSE, TRUE)) 00757 return FALSE; 00758 00759 if (!do_writing (transport)) 00760 { 00761 _dbus_verbose ("no memory to write\n"); 00762 return FALSE; 00763 } 00764 } 00765 #ifdef DBUS_ENABLE_VERBOSE_MODE 00766 else 00767 { 00768 if (watch == unix_transport->read_watch) 00769 _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n", 00770 flags); 00771 else if (watch == unix_transport->write_watch) 00772 _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n", 00773 flags); 00774 else 00775 _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n", 00776 watch, dbus_watch_get_fd (watch)); 00777 } 00778 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 00779 00780 return TRUE; 00781 } 00782 00783 static void 00784 unix_disconnect (DBusTransport *transport) 00785 { 00786 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00787 00788 free_watches (transport); 00789 00790 _dbus_close (unix_transport->fd, NULL); 00791 unix_transport->fd = -1; 00792 } 00793 00794 static dbus_bool_t 00795 unix_connection_set (DBusTransport *transport) 00796 { 00797 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00798 00799 _dbus_watch_set_handler (unix_transport->write_watch, 00800 _dbus_connection_handle_watch, 00801 transport->connection, NULL); 00802 00803 _dbus_watch_set_handler (unix_transport->read_watch, 00804 _dbus_connection_handle_watch, 00805 transport->connection, NULL); 00806 00807 if (!_dbus_connection_add_watch (transport->connection, 00808 unix_transport->write_watch)) 00809 return FALSE; 00810 00811 if (!_dbus_connection_add_watch (transport->connection, 00812 unix_transport->read_watch)) 00813 { 00814 _dbus_connection_remove_watch (transport->connection, 00815 unix_transport->write_watch); 00816 return FALSE; 00817 } 00818 00819 check_read_watch (transport); 00820 check_write_watch (transport); 00821 00822 return TRUE; 00823 } 00824 00825 static void 00826 unix_messages_pending (DBusTransport *transport, 00827 int messages_pending) 00828 { 00829 check_write_watch (transport); 00830 } 00831 00839 static void 00840 unix_do_iteration (DBusTransport *transport, 00841 unsigned int flags, 00842 int timeout_milliseconds) 00843 { 00844 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00845 DBusPollFD poll_fd; 00846 int poll_res; 00847 int poll_timeout; 00848 00849 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p\n", 00850 flags & DBUS_ITERATION_DO_READING ? "read" : "", 00851 flags & DBUS_ITERATION_DO_WRITING ? "write" : "", 00852 timeout_milliseconds, 00853 unix_transport->read_watch, 00854 unix_transport->write_watch); 00855 00856 /* the passed in DO_READING/DO_WRITING flags indicate whether to 00857 * read/write messages, but regardless of those we may need to block 00858 * for reading/writing to do auth. But if we do reading for auth, 00859 * we don't want to read any messages yet if not given DO_READING. 00860 * 00861 * Also, if read_watch == NULL or write_watch == NULL, we don't 00862 * want to read/write so don't. 00863 */ 00864 00865 poll_fd.fd = unix_transport->fd; 00866 poll_fd.events = 0; 00867 00868 if (_dbus_transport_get_is_authenticated (transport)) 00869 { 00870 if (unix_transport->read_watch && 00871 (flags & DBUS_ITERATION_DO_READING)) 00872 poll_fd.events |= _DBUS_POLLIN; 00873 00874 if (unix_transport->write_watch && 00875 (flags & DBUS_ITERATION_DO_WRITING)) 00876 poll_fd.events |= _DBUS_POLLOUT; 00877 } 00878 else 00879 { 00880 DBusAuthState auth_state; 00881 00882 auth_state = _dbus_auth_do_work (transport->auth); 00883 00884 if (transport->receive_credentials_pending || 00885 auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT) 00886 poll_fd.events |= _DBUS_POLLIN; 00887 00888 if (transport->send_credentials_pending || 00889 auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) 00890 poll_fd.events |= _DBUS_POLLOUT; 00891 } 00892 00893 if (poll_fd.events) 00894 { 00895 if (flags & DBUS_ITERATION_BLOCK) 00896 poll_timeout = timeout_milliseconds; 00897 else 00898 poll_timeout = 0; 00899 00900 /* For blocking selects we drop the connection lock here 00901 * to avoid blocking out connection access during a potentially 00902 * indefinite blocking call. The io path is still protected 00903 * by the io_path_cond condvar, so we won't reenter this. 00904 */ 00905 if (flags & DBUS_ITERATION_BLOCK) 00906 _dbus_connection_unlock (transport->connection); 00907 00908 again: 00909 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout); 00910 00911 if (poll_res < 0 && errno == EINTR) 00912 goto again; 00913 00914 if (flags & DBUS_ITERATION_BLOCK) 00915 _dbus_connection_lock (transport->connection); 00916 00917 if (poll_res >= 0) 00918 { 00919 if (poll_fd.revents & _DBUS_POLLERR) 00920 do_io_error (transport); 00921 else 00922 { 00923 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0; 00924 dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0; 00925 00926 _dbus_verbose ("in iteration, need_read=%d need_write=%d\n", 00927 need_read, need_write); 00928 do_authentication (transport, need_read, need_write); 00929 00930 if (need_read && (flags & DBUS_ITERATION_DO_READING)) 00931 do_reading (transport); 00932 if (need_write && (flags & DBUS_ITERATION_DO_WRITING)) 00933 do_writing (transport); 00934 } 00935 } 00936 else 00937 { 00938 _dbus_verbose ("Error from _dbus_poll(): %s\n", 00939 _dbus_strerror (errno)); 00940 } 00941 } 00942 } 00943 00944 static void 00945 unix_live_messages_changed (DBusTransport *transport) 00946 { 00947 /* See if we should look for incoming messages again */ 00948 check_read_watch (transport); 00949 } 00950 00951 00952 static dbus_bool_t 00953 unix_get_unix_fd (DBusTransport *transport, 00954 int *fd_p) 00955 { 00956 DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; 00957 00958 *fd_p = unix_transport->fd; 00959 00960 return TRUE; 00961 } 00962 00963 static DBusTransportVTable unix_vtable = { 00964 unix_finalize, 00965 unix_handle_watch, 00966 unix_disconnect, 00967 unix_connection_set, 00968 unix_messages_pending, 00969 unix_do_iteration, 00970 unix_live_messages_changed, 00971 unix_get_unix_fd 00972 }; 00973 00985 DBusTransport* 00986 _dbus_transport_new_for_fd (int fd, 00987 dbus_bool_t server, 00988 const DBusString *address) 00989 { 00990 DBusTransportUnix *unix_transport; 00991 00992 unix_transport = dbus_new0 (DBusTransportUnix, 1); 00993 if (unix_transport == NULL) 00994 return NULL; 00995 00996 if (!_dbus_string_init (&unix_transport->encoded_outgoing)) 00997 goto failed_0; 00998 00999 if (!_dbus_string_init (&unix_transport->encoded_incoming)) 01000 goto failed_1; 01001 01002 unix_transport->write_watch = _dbus_watch_new (fd, 01003 DBUS_WATCH_WRITABLE, 01004 FALSE, 01005 NULL, NULL, NULL); 01006 if (unix_transport->write_watch == NULL) 01007 goto failed_2; 01008 01009 unix_transport->read_watch = _dbus_watch_new (fd, 01010 DBUS_WATCH_READABLE, 01011 FALSE, 01012 NULL, NULL, NULL); 01013 if (unix_transport->read_watch == NULL) 01014 goto failed_3; 01015 01016 if (!_dbus_transport_init_base (&unix_transport->base, 01017 &unix_vtable, 01018 server, address)) 01019 goto failed_4; 01020 01021 unix_transport->fd = fd; 01022 unix_transport->message_bytes_written = 0; 01023 01024 /* These values should probably be tunable or something. */ 01025 unix_transport->max_bytes_read_per_iteration = 2048; 01026 unix_transport->max_bytes_written_per_iteration = 2048; 01027 01028 return (DBusTransport*) unix_transport; 01029 01030 failed_4: 01031 _dbus_watch_unref (unix_transport->read_watch); 01032 failed_3: 01033 _dbus_watch_unref (unix_transport->write_watch); 01034 failed_2: 01035 _dbus_string_free (&unix_transport->encoded_incoming); 01036 failed_1: 01037 _dbus_string_free (&unix_transport->encoded_outgoing); 01038 failed_0: 01039 dbus_free (unix_transport); 01040 return NULL; 01041 } 01042 01055 DBusTransport* 01056 _dbus_transport_new_for_domain_socket (const char *path, 01057 dbus_bool_t abstract, 01058 DBusError *error) 01059 { 01060 int fd; 01061 DBusTransport *transport; 01062 DBusString address; 01063 01064 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01065 01066 if (!_dbus_string_init (&address)) 01067 { 01068 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01069 return NULL; 01070 } 01071 01072 fd = -1; 01073 01074 if ((abstract && 01075 !_dbus_string_append (&address, "unix:abstract=")) || 01076 (!abstract && 01077 !_dbus_string_append (&address, "unix:path=")) || 01078 !_dbus_string_append (&address, path)) 01079 { 01080 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01081 goto failed_0; 01082 } 01083 01084 fd = _dbus_connect_unix_socket (path, abstract, error); 01085 if (fd < 0) 01086 { 01087 _DBUS_ASSERT_ERROR_IS_SET (error); 01088 goto failed_0; 01089 } 01090 01091 _dbus_fd_set_close_on_exec (fd); 01092 01093 _dbus_verbose ("Successfully connected to unix socket %s\n", 01094 path); 01095 01096 transport = _dbus_transport_new_for_fd (fd, FALSE, &address); 01097 if (transport == NULL) 01098 { 01099 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01100 goto failed_1; 01101 } 01102 01103 _dbus_string_free (&address); 01104 01105 return transport; 01106 01107 failed_1: 01108 _dbus_close (fd, NULL); 01109 failed_0: 01110 _dbus_string_free (&address); 01111 return NULL; 01112 } 01113 01122 DBusTransport* 01123 _dbus_transport_new_for_tcp_socket (const char *host, 01124 dbus_int32_t port, 01125 DBusError *error) 01126 { 01127 int fd; 01128 DBusTransport *transport; 01129 DBusString address; 01130 01131 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01132 01133 if (!_dbus_string_init (&address)) 01134 { 01135 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01136 return NULL; 01137 } 01138 01139 if (!_dbus_string_append (&address, "tcp:host=") || 01140 !_dbus_string_append (&address, host) || 01141 !_dbus_string_append (&address, ",port=") || 01142 !_dbus_string_append_int (&address, port)) 01143 { 01144 _dbus_string_free (&address); 01145 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01146 return NULL; 01147 } 01148 01149 fd = _dbus_connect_tcp_socket (host, port, error); 01150 if (fd < 0) 01151 { 01152 _DBUS_ASSERT_ERROR_IS_SET (error); 01153 _dbus_string_free (&address); 01154 return NULL; 01155 } 01156 01157 _dbus_fd_set_close_on_exec (fd); 01158 01159 _dbus_verbose ("Successfully connected to tcp socket %s:%d\n", 01160 host, port); 01161 01162 transport = _dbus_transport_new_for_fd (fd, FALSE, &address); 01163 if (transport == NULL) 01164 { 01165 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01166 _dbus_close (fd, NULL); 01167 _dbus_string_free (&address); 01168 fd = -1; 01169 } 01170 01171 _dbus_string_free (&address); 01172 01173 return transport; 01174 } 01175

Generated on Mon Aug 16 17:40:11 2004 for D-BUS by doxygen 1.3.8