D-Bus 1.4.10
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-transport-socket.c Socket subclasses of DBusTransport 00003 * 00004 * Copyright (C) 2002, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-internals.h" 00026 #include "dbus-connection-internal.h" 00027 #include "dbus-nonce.h" 00028 #include "dbus-transport-socket.h" 00029 #include "dbus-transport-protected.h" 00030 #include "dbus-watch.h" 00031 #include "dbus-credentials.h" 00032 00044 typedef struct DBusTransportSocket DBusTransportSocket; 00045 00049 struct DBusTransportSocket 00050 { 00051 DBusTransport base; 00052 int fd; 00053 DBusWatch *read_watch; 00054 DBusWatch *write_watch; 00056 int max_bytes_read_per_iteration; 00057 int max_bytes_written_per_iteration; 00059 int message_bytes_written; 00063 DBusString encoded_outgoing; 00066 DBusString encoded_incoming; 00069 }; 00070 00071 static void 00072 free_watches (DBusTransport *transport) 00073 { 00074 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00075 00076 _dbus_verbose ("start\n"); 00077 00078 if (socket_transport->read_watch) 00079 { 00080 if (transport->connection) 00081 _dbus_connection_remove_watch_unlocked (transport->connection, 00082 socket_transport->read_watch); 00083 _dbus_watch_invalidate (socket_transport->read_watch); 00084 _dbus_watch_unref (socket_transport->read_watch); 00085 socket_transport->read_watch = NULL; 00086 } 00087 00088 if (socket_transport->write_watch) 00089 { 00090 if (transport->connection) 00091 _dbus_connection_remove_watch_unlocked (transport->connection, 00092 socket_transport->write_watch); 00093 _dbus_watch_invalidate (socket_transport->write_watch); 00094 _dbus_watch_unref (socket_transport->write_watch); 00095 socket_transport->write_watch = NULL; 00096 } 00097 00098 _dbus_verbose ("end\n"); 00099 } 00100 00101 static void 00102 socket_finalize (DBusTransport *transport) 00103 { 00104 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00105 00106 _dbus_verbose ("\n"); 00107 00108 free_watches (transport); 00109 00110 _dbus_string_free (&socket_transport->encoded_outgoing); 00111 _dbus_string_free (&socket_transport->encoded_incoming); 00112 00113 _dbus_transport_finalize_base (transport); 00114 00115 _dbus_assert (socket_transport->read_watch == NULL); 00116 _dbus_assert (socket_transport->write_watch == NULL); 00117 00118 dbus_free (transport); 00119 } 00120 00121 static void 00122 check_write_watch (DBusTransport *transport) 00123 { 00124 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00125 dbus_bool_t needed; 00126 00127 if (transport->connection == NULL) 00128 return; 00129 00130 if (transport->disconnected) 00131 { 00132 _dbus_assert (socket_transport->write_watch == NULL); 00133 return; 00134 } 00135 00136 _dbus_transport_ref (transport); 00137 00138 if (_dbus_transport_get_is_authenticated (transport)) 00139 needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); 00140 else 00141 { 00142 if (transport->send_credentials_pending) 00143 needed = TRUE; 00144 else 00145 { 00146 DBusAuthState auth_state; 00147 00148 auth_state = _dbus_auth_do_work (transport->auth); 00149 00150 /* If we need memory we install the write watch just in case, 00151 * if there's no need for it, it will get de-installed 00152 * next time we try reading. 00153 */ 00154 if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND || 00155 auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY) 00156 needed = TRUE; 00157 else 00158 needed = FALSE; 00159 } 00160 } 00161 00162 _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n", 00163 needed, transport->connection, socket_transport->write_watch, 00164 socket_transport->fd, 00165 _dbus_connection_has_messages_to_send_unlocked (transport->connection)); 00166 00167 _dbus_connection_toggle_watch_unlocked (transport->connection, 00168 socket_transport->write_watch, 00169 needed); 00170 00171 _dbus_transport_unref (transport); 00172 } 00173 00174 static void 00175 check_read_watch (DBusTransport *transport) 00176 { 00177 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00178 dbus_bool_t need_read_watch; 00179 00180 _dbus_verbose ("fd = %d\n",socket_transport->fd); 00181 00182 if (transport->connection == NULL) 00183 return; 00184 00185 if (transport->disconnected) 00186 { 00187 _dbus_assert (socket_transport->read_watch == NULL); 00188 return; 00189 } 00190 00191 _dbus_transport_ref (transport); 00192 00193 if (_dbus_transport_get_is_authenticated (transport)) 00194 need_read_watch = 00195 (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) && 00196 (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds); 00197 else 00198 { 00199 if (transport->receive_credentials_pending) 00200 need_read_watch = TRUE; 00201 else 00202 { 00203 /* The reason to disable need_read_watch when not WAITING_FOR_INPUT 00204 * is to avoid spinning on the file descriptor when we're waiting 00205 * to write or for some other part of the auth process 00206 */ 00207 DBusAuthState auth_state; 00208 00209 auth_state = _dbus_auth_do_work (transport->auth); 00210 00211 /* If we need memory we install the read watch just in case, 00212 * if there's no need for it, it will get de-installed 00213 * next time we try reading. If we're authenticated we 00214 * install it since we normally have it installed while 00215 * authenticated. 00216 */ 00217 if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT || 00218 auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY || 00219 auth_state == DBUS_AUTH_STATE_AUTHENTICATED) 00220 need_read_watch = TRUE; 00221 else 00222 need_read_watch = FALSE; 00223 } 00224 } 00225 00226 _dbus_verbose (" setting read watch enabled = %d\n", need_read_watch); 00227 _dbus_connection_toggle_watch_unlocked (transport->connection, 00228 socket_transport->read_watch, 00229 need_read_watch); 00230 00231 _dbus_transport_unref (transport); 00232 } 00233 00234 static void 00235 do_io_error (DBusTransport *transport) 00236 { 00237 _dbus_transport_ref (transport); 00238 _dbus_transport_disconnect (transport); 00239 _dbus_transport_unref (transport); 00240 } 00241 00242 /* return value is whether we successfully read any new data. */ 00243 static dbus_bool_t 00244 read_data_into_auth (DBusTransport *transport, 00245 dbus_bool_t *oom) 00246 { 00247 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00248 DBusString *buffer; 00249 int bytes_read; 00250 00251 *oom = FALSE; 00252 00253 _dbus_auth_get_buffer (transport->auth, &buffer); 00254 00255 bytes_read = _dbus_read_socket (socket_transport->fd, 00256 buffer, socket_transport->max_bytes_read_per_iteration); 00257 00258 _dbus_auth_return_buffer (transport->auth, buffer, 00259 bytes_read > 0 ? bytes_read : 0); 00260 00261 if (bytes_read > 0) 00262 { 00263 _dbus_verbose (" read %d bytes in auth phase\n", bytes_read); 00264 00265 return TRUE; 00266 } 00267 else if (bytes_read < 0) 00268 { 00269 /* EINTR already handled for us */ 00270 00271 if (_dbus_get_is_errno_enomem ()) 00272 { 00273 *oom = TRUE; 00274 } 00275 else if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00276 ; /* do nothing, just return FALSE below */ 00277 else 00278 { 00279 _dbus_verbose ("Error reading from remote app: %s\n", 00280 _dbus_strerror_from_errno ()); 00281 do_io_error (transport); 00282 } 00283 00284 return FALSE; 00285 } 00286 else 00287 { 00288 _dbus_assert (bytes_read == 0); 00289 00290 _dbus_verbose ("Disconnected from remote app\n"); 00291 do_io_error (transport); 00292 00293 return FALSE; 00294 } 00295 } 00296 00297 /* Return value is whether we successfully wrote any bytes */ 00298 static dbus_bool_t 00299 write_data_from_auth (DBusTransport *transport) 00300 { 00301 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00302 int bytes_written; 00303 const DBusString *buffer; 00304 00305 if (!_dbus_auth_get_bytes_to_send (transport->auth, 00306 &buffer)) 00307 return FALSE; 00308 00309 bytes_written = _dbus_write_socket (socket_transport->fd, 00310 buffer, 00311 0, _dbus_string_get_length (buffer)); 00312 00313 if (bytes_written > 0) 00314 { 00315 _dbus_auth_bytes_sent (transport->auth, bytes_written); 00316 return TRUE; 00317 } 00318 else if (bytes_written < 0) 00319 { 00320 /* EINTR already handled for us */ 00321 00322 if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00323 ; 00324 else 00325 { 00326 _dbus_verbose ("Error writing to remote app: %s\n", 00327 _dbus_strerror_from_errno ()); 00328 do_io_error (transport); 00329 } 00330 } 00331 00332 return FALSE; 00333 } 00334 00335 /* FALSE on OOM */ 00336 static dbus_bool_t 00337 exchange_credentials (DBusTransport *transport, 00338 dbus_bool_t do_reading, 00339 dbus_bool_t do_writing) 00340 { 00341 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00342 DBusError error = DBUS_ERROR_INIT; 00343 00344 _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n", 00345 do_reading, do_writing); 00346 00347 if (do_writing && transport->send_credentials_pending) 00348 { 00349 if (_dbus_send_credentials_socket (socket_transport->fd, 00350 &error)) 00351 { 00352 transport->send_credentials_pending = FALSE; 00353 } 00354 else 00355 { 00356 _dbus_verbose ("Failed to write credentials: %s\n", error.message); 00357 dbus_error_free (&error); 00358 do_io_error (transport); 00359 } 00360 } 00361 00362 if (do_reading && transport->receive_credentials_pending) 00363 { 00364 /* FIXME this can fail due to IO error _or_ OOM, broken 00365 * (somewhat tricky to fix since the OOM error can be set after 00366 * we already read the credentials byte, so basically we need to 00367 * separate reading the byte and storing it in the 00368 * transport->credentials). Does not really matter for now 00369 * because storing in credentials never actually fails on unix. 00370 */ 00371 if (_dbus_read_credentials_socket (socket_transport->fd, 00372 transport->credentials, 00373 &error)) 00374 { 00375 transport->receive_credentials_pending = FALSE; 00376 } 00377 else 00378 { 00379 _dbus_verbose ("Failed to read credentials %s\n", error.message); 00380 dbus_error_free (&error); 00381 do_io_error (transport); 00382 } 00383 } 00384 00385 if (!(transport->send_credentials_pending || 00386 transport->receive_credentials_pending)) 00387 { 00388 if (!_dbus_auth_set_credentials (transport->auth, 00389 transport->credentials)) 00390 return FALSE; 00391 } 00392 00393 return TRUE; 00394 } 00395 00396 static dbus_bool_t 00397 do_authentication (DBusTransport *transport, 00398 dbus_bool_t do_reading, 00399 dbus_bool_t do_writing, 00400 dbus_bool_t *auth_completed) 00401 { 00402 dbus_bool_t oom; 00403 dbus_bool_t orig_auth_state; 00404 00405 oom = FALSE; 00406 00407 orig_auth_state = _dbus_transport_get_is_authenticated (transport); 00408 00409 /* This is essential to avoid the check_write_watch() at the end, 00410 * we don't want to add a write watch in do_iteration before 00411 * we try writing and get EAGAIN 00412 */ 00413 if (orig_auth_state) 00414 { 00415 if (auth_completed) 00416 *auth_completed = FALSE; 00417 return TRUE; 00418 } 00419 00420 _dbus_transport_ref (transport); 00421 00422 while (!_dbus_transport_get_is_authenticated (transport) && 00423 _dbus_transport_get_is_connected (transport)) 00424 { 00425 if (!exchange_credentials (transport, do_reading, do_writing)) 00426 { 00427 /* OOM */ 00428 oom = TRUE; 00429 goto out; 00430 } 00431 00432 if (transport->send_credentials_pending || 00433 transport->receive_credentials_pending) 00434 { 00435 _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n", 00436 transport->send_credentials_pending, 00437 transport->receive_credentials_pending); 00438 goto out; 00439 } 00440 00441 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client") 00442 switch (_dbus_auth_do_work (transport->auth)) 00443 { 00444 case DBUS_AUTH_STATE_WAITING_FOR_INPUT: 00445 _dbus_verbose (" %s auth state: waiting for input\n", 00446 TRANSPORT_SIDE (transport)); 00447 if (!do_reading || !read_data_into_auth (transport, &oom)) 00448 goto out; 00449 break; 00450 00451 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: 00452 _dbus_verbose (" %s auth state: waiting for memory\n", 00453 TRANSPORT_SIDE (transport)); 00454 oom = TRUE; 00455 goto out; 00456 break; 00457 00458 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND: 00459 _dbus_verbose (" %s auth state: bytes to send\n", 00460 TRANSPORT_SIDE (transport)); 00461 if (!do_writing || !write_data_from_auth (transport)) 00462 goto out; 00463 break; 00464 00465 case DBUS_AUTH_STATE_NEED_DISCONNECT: 00466 _dbus_verbose (" %s auth state: need to disconnect\n", 00467 TRANSPORT_SIDE (transport)); 00468 do_io_error (transport); 00469 break; 00470 00471 case DBUS_AUTH_STATE_AUTHENTICATED: 00472 _dbus_verbose (" %s auth state: authenticated\n", 00473 TRANSPORT_SIDE (transport)); 00474 break; 00475 } 00476 } 00477 00478 out: 00479 if (auth_completed) 00480 *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport)); 00481 00482 check_read_watch (transport); 00483 check_write_watch (transport); 00484 _dbus_transport_unref (transport); 00485 00486 if (oom) 00487 return FALSE; 00488 else 00489 return TRUE; 00490 } 00491 00492 /* returns false on oom */ 00493 static dbus_bool_t 00494 do_writing (DBusTransport *transport) 00495 { 00496 int total; 00497 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00498 dbus_bool_t oom; 00499 00500 /* No messages without authentication! */ 00501 if (!_dbus_transport_get_is_authenticated (transport)) 00502 { 00503 _dbus_verbose ("Not authenticated, not writing anything\n"); 00504 return TRUE; 00505 } 00506 00507 if (transport->disconnected) 00508 { 00509 _dbus_verbose ("Not connected, not writing anything\n"); 00510 return TRUE; 00511 } 00512 00513 #if 1 00514 _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n", 00515 _dbus_connection_has_messages_to_send_unlocked (transport->connection), 00516 socket_transport->fd); 00517 #endif 00518 00519 oom = FALSE; 00520 total = 0; 00521 00522 while (!transport->disconnected && 00523 _dbus_connection_has_messages_to_send_unlocked (transport->connection)) 00524 { 00525 int bytes_written; 00526 DBusMessage *message; 00527 const DBusString *header; 00528 const DBusString *body; 00529 int header_len, body_len; 00530 int total_bytes_to_write; 00531 00532 if (total > socket_transport->max_bytes_written_per_iteration) 00533 { 00534 _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n", 00535 total, socket_transport->max_bytes_written_per_iteration); 00536 goto out; 00537 } 00538 00539 message = _dbus_connection_get_message_to_send (transport->connection); 00540 _dbus_assert (message != NULL); 00541 dbus_message_lock (message); 00542 00543 #if 0 00544 _dbus_verbose ("writing message %p\n", message); 00545 #endif 00546 00547 _dbus_message_get_network_data (message, 00548 &header, &body); 00549 00550 header_len = _dbus_string_get_length (header); 00551 body_len = _dbus_string_get_length (body); 00552 00553 if (_dbus_auth_needs_encoding (transport->auth)) 00554 { 00555 /* Does fd passing even make sense with encoded data? */ 00556 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); 00557 00558 if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0) 00559 { 00560 if (!_dbus_auth_encode_data (transport->auth, 00561 header, &socket_transport->encoded_outgoing)) 00562 { 00563 oom = TRUE; 00564 goto out; 00565 } 00566 00567 if (!_dbus_auth_encode_data (transport->auth, 00568 body, &socket_transport->encoded_outgoing)) 00569 { 00570 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00571 oom = TRUE; 00572 goto out; 00573 } 00574 } 00575 00576 total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing); 00577 00578 #if 0 00579 _dbus_verbose ("encoded message is %d bytes\n", 00580 total_bytes_to_write); 00581 #endif 00582 00583 bytes_written = 00584 _dbus_write_socket (socket_transport->fd, 00585 &socket_transport->encoded_outgoing, 00586 socket_transport->message_bytes_written, 00587 total_bytes_to_write - socket_transport->message_bytes_written); 00588 } 00589 else 00590 { 00591 total_bytes_to_write = header_len + body_len; 00592 00593 #if 0 00594 _dbus_verbose ("message is %d bytes\n", 00595 total_bytes_to_write); 00596 #endif 00597 00598 #ifdef HAVE_UNIX_FD_PASSING 00599 if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) 00600 { 00601 /* Send the fds along with the first byte of the message */ 00602 const int *unix_fds; 00603 unsigned n; 00604 00605 _dbus_message_get_unix_fds(message, &unix_fds, &n); 00606 00607 bytes_written = 00608 _dbus_write_socket_with_unix_fds_two (socket_transport->fd, 00609 header, 00610 socket_transport->message_bytes_written, 00611 header_len - socket_transport->message_bytes_written, 00612 body, 00613 0, body_len, 00614 unix_fds, 00615 n); 00616 00617 if (bytes_written > 0 && n > 0) 00618 _dbus_verbose("Wrote %i unix fds\n", n); 00619 } 00620 else 00621 #endif 00622 { 00623 if (socket_transport->message_bytes_written < header_len) 00624 { 00625 bytes_written = 00626 _dbus_write_socket_two (socket_transport->fd, 00627 header, 00628 socket_transport->message_bytes_written, 00629 header_len - socket_transport->message_bytes_written, 00630 body, 00631 0, body_len); 00632 } 00633 else 00634 { 00635 bytes_written = 00636 _dbus_write_socket (socket_transport->fd, 00637 body, 00638 (socket_transport->message_bytes_written - header_len), 00639 body_len - 00640 (socket_transport->message_bytes_written - header_len)); 00641 } 00642 } 00643 } 00644 00645 if (bytes_written < 0) 00646 { 00647 /* EINTR already handled for us */ 00648 00649 /* For some discussion of why we also ignore EPIPE here, see 00650 * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html 00651 */ 00652 00653 if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ()) 00654 goto out; 00655 else 00656 { 00657 _dbus_verbose ("Error writing to remote app: %s\n", 00658 _dbus_strerror_from_errno ()); 00659 do_io_error (transport); 00660 goto out; 00661 } 00662 } 00663 else 00664 { 00665 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written, 00666 total_bytes_to_write); 00667 00668 total += bytes_written; 00669 socket_transport->message_bytes_written += bytes_written; 00670 00671 _dbus_assert (socket_transport->message_bytes_written <= 00672 total_bytes_to_write); 00673 00674 if (socket_transport->message_bytes_written == total_bytes_to_write) 00675 { 00676 socket_transport->message_bytes_written = 0; 00677 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00678 _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); 00679 00680 _dbus_connection_message_sent (transport->connection, 00681 message); 00682 } 00683 } 00684 } 00685 00686 out: 00687 if (oom) 00688 return FALSE; 00689 else 00690 return TRUE; 00691 } 00692 00693 /* returns false on out-of-memory */ 00694 static dbus_bool_t 00695 do_reading (DBusTransport *transport) 00696 { 00697 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00698 DBusString *buffer; 00699 int bytes_read; 00700 int total; 00701 dbus_bool_t oom; 00702 00703 _dbus_verbose ("fd = %d\n",socket_transport->fd); 00704 00705 /* No messages without authentication! */ 00706 if (!_dbus_transport_get_is_authenticated (transport)) 00707 return TRUE; 00708 00709 oom = FALSE; 00710 00711 total = 0; 00712 00713 again: 00714 00715 /* See if we've exceeded max messages and need to disable reading */ 00716 check_read_watch (transport); 00717 00718 if (total > socket_transport->max_bytes_read_per_iteration) 00719 { 00720 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n", 00721 total, socket_transport->max_bytes_read_per_iteration); 00722 goto out; 00723 } 00724 00725 _dbus_assert (socket_transport->read_watch != NULL || 00726 transport->disconnected); 00727 00728 if (transport->disconnected) 00729 goto out; 00730 00731 if (!dbus_watch_get_enabled (socket_transport->read_watch)) 00732 return TRUE; 00733 00734 if (_dbus_auth_needs_decoding (transport->auth)) 00735 { 00736 /* Does fd passing even make sense with encoded data? */ 00737 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); 00738 00739 if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0) 00740 bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming); 00741 else 00742 bytes_read = _dbus_read_socket (socket_transport->fd, 00743 &socket_transport->encoded_incoming, 00744 socket_transport->max_bytes_read_per_iteration); 00745 00746 _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) == 00747 bytes_read); 00748 00749 if (bytes_read > 0) 00750 { 00751 int orig_len; 00752 00753 _dbus_message_loader_get_buffer (transport->loader, 00754 &buffer); 00755 00756 orig_len = _dbus_string_get_length (buffer); 00757 00758 if (!_dbus_auth_decode_data (transport->auth, 00759 &socket_transport->encoded_incoming, 00760 buffer)) 00761 { 00762 _dbus_verbose ("Out of memory decoding incoming data\n"); 00763 _dbus_message_loader_return_buffer (transport->loader, 00764 buffer, 00765 _dbus_string_get_length (buffer) - orig_len); 00766 00767 oom = TRUE; 00768 goto out; 00769 } 00770 00771 _dbus_message_loader_return_buffer (transport->loader, 00772 buffer, 00773 _dbus_string_get_length (buffer) - orig_len); 00774 00775 _dbus_string_set_length (&socket_transport->encoded_incoming, 0); 00776 _dbus_string_compact (&socket_transport->encoded_incoming, 2048); 00777 } 00778 } 00779 else 00780 { 00781 _dbus_message_loader_get_buffer (transport->loader, 00782 &buffer); 00783 00784 #ifdef HAVE_UNIX_FD_PASSING 00785 if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) 00786 { 00787 int *fds, n_fds; 00788 00789 if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds)) 00790 { 00791 _dbus_verbose ("Out of memory reading file descriptors\n"); 00792 _dbus_message_loader_return_buffer (transport->loader, buffer, 0); 00793 oom = TRUE; 00794 goto out; 00795 } 00796 00797 bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd, 00798 buffer, 00799 socket_transport->max_bytes_read_per_iteration, 00800 fds, &n_fds); 00801 00802 if (bytes_read >= 0 && n_fds > 0) 00803 _dbus_verbose("Read %i unix fds\n", n_fds); 00804 00805 _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds); 00806 } 00807 else 00808 #endif 00809 { 00810 bytes_read = _dbus_read_socket (socket_transport->fd, 00811 buffer, socket_transport->max_bytes_read_per_iteration); 00812 } 00813 00814 _dbus_message_loader_return_buffer (transport->loader, 00815 buffer, 00816 bytes_read < 0 ? 0 : bytes_read); 00817 } 00818 00819 if (bytes_read < 0) 00820 { 00821 /* EINTR already handled for us */ 00822 00823 if (_dbus_get_is_errno_enomem ()) 00824 { 00825 _dbus_verbose ("Out of memory in read()/do_reading()\n"); 00826 oom = TRUE; 00827 goto out; 00828 } 00829 else if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00830 goto out; 00831 else 00832 { 00833 _dbus_verbose ("Error reading from remote app: %s\n", 00834 _dbus_strerror_from_errno ()); 00835 do_io_error (transport); 00836 goto out; 00837 } 00838 } 00839 else if (bytes_read == 0) 00840 { 00841 _dbus_verbose ("Disconnected from remote app\n"); 00842 do_io_error (transport); 00843 goto out; 00844 } 00845 else 00846 { 00847 _dbus_verbose (" read %d bytes\n", bytes_read); 00848 00849 total += bytes_read; 00850 00851 if (!_dbus_transport_queue_messages (transport)) 00852 { 00853 oom = TRUE; 00854 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n"); 00855 goto out; 00856 } 00857 00858 /* Try reading more data until we get EAGAIN and return, or 00859 * exceed max bytes per iteration. If in blocking mode of 00860 * course we'll block instead of returning. 00861 */ 00862 goto again; 00863 } 00864 00865 out: 00866 if (oom) 00867 return FALSE; 00868 else 00869 return TRUE; 00870 } 00871 00872 static dbus_bool_t 00873 unix_error_with_read_to_come (DBusTransport *itransport, 00874 DBusWatch *watch, 00875 unsigned int flags) 00876 { 00877 DBusTransportSocket *transport = (DBusTransportSocket *) itransport; 00878 00879 if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR)) 00880 return FALSE; 00881 00882 /* If we have a read watch enabled ... 00883 we -might have data incoming ... => handle the HANGUP there */ 00884 if (watch != transport->read_watch && 00885 _dbus_watch_get_enabled (transport->read_watch)) 00886 return FALSE; 00887 00888 return TRUE; 00889 } 00890 00891 static dbus_bool_t 00892 socket_handle_watch (DBusTransport *transport, 00893 DBusWatch *watch, 00894 unsigned int flags) 00895 { 00896 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00897 00898 _dbus_assert (watch == socket_transport->read_watch || 00899 watch == socket_transport->write_watch); 00900 _dbus_assert (watch != NULL); 00901 00902 /* If we hit an error here on a write watch, don't disconnect the transport yet because data can 00903 * still be in the buffer and do_reading may need several iteration to read 00904 * it all (because of its max_bytes_read_per_iteration limit). 00905 */ 00906 if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags)) 00907 { 00908 _dbus_verbose ("Hang up or error on watch\n"); 00909 _dbus_transport_disconnect (transport); 00910 return TRUE; 00911 } 00912 00913 if (watch == socket_transport->read_watch && 00914 (flags & DBUS_WATCH_READABLE)) 00915 { 00916 dbus_bool_t auth_finished; 00917 #if 1 00918 _dbus_verbose ("handling read watch %p flags = %x\n", 00919 watch, flags); 00920 #endif 00921 if (!do_authentication (transport, TRUE, FALSE, &auth_finished)) 00922 return FALSE; 00923 00924 /* We don't want to do a read immediately following 00925 * a successful authentication. This is so we 00926 * have a chance to propagate the authentication 00927 * state further up. Specifically, we need to 00928 * process any pending data from the auth object. 00929 */ 00930 if (!auth_finished) 00931 { 00932 if (!do_reading (transport)) 00933 { 00934 _dbus_verbose ("no memory to read\n"); 00935 return FALSE; 00936 } 00937 } 00938 else 00939 { 00940 _dbus_verbose ("Not reading anything since we just completed the authentication\n"); 00941 } 00942 } 00943 else if (watch == socket_transport->write_watch && 00944 (flags & DBUS_WATCH_WRITABLE)) 00945 { 00946 #if 1 00947 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n", 00948 _dbus_connection_has_messages_to_send_unlocked (transport->connection)); 00949 #endif 00950 if (!do_authentication (transport, FALSE, TRUE, NULL)) 00951 return FALSE; 00952 00953 if (!do_writing (transport)) 00954 { 00955 _dbus_verbose ("no memory to write\n"); 00956 return FALSE; 00957 } 00958 00959 /* See if we still need the write watch */ 00960 check_write_watch (transport); 00961 } 00962 #ifdef DBUS_ENABLE_VERBOSE_MODE 00963 else 00964 { 00965 if (watch == socket_transport->read_watch) 00966 _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n", 00967 flags); 00968 else if (watch == socket_transport->write_watch) 00969 _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n", 00970 flags); 00971 else 00972 _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n", 00973 watch, dbus_watch_get_socket (watch)); 00974 } 00975 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 00976 00977 return TRUE; 00978 } 00979 00980 static void 00981 socket_disconnect (DBusTransport *transport) 00982 { 00983 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00984 00985 _dbus_verbose ("\n"); 00986 00987 free_watches (transport); 00988 00989 _dbus_close_socket (socket_transport->fd, NULL); 00990 socket_transport->fd = -1; 00991 } 00992 00993 static dbus_bool_t 00994 socket_connection_set (DBusTransport *transport) 00995 { 00996 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00997 00998 _dbus_watch_set_handler (socket_transport->write_watch, 00999 _dbus_connection_handle_watch, 01000 transport->connection, NULL); 01001 01002 _dbus_watch_set_handler (socket_transport->read_watch, 01003 _dbus_connection_handle_watch, 01004 transport->connection, NULL); 01005 01006 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01007 socket_transport->write_watch)) 01008 return FALSE; 01009 01010 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01011 socket_transport->read_watch)) 01012 { 01013 _dbus_connection_remove_watch_unlocked (transport->connection, 01014 socket_transport->write_watch); 01015 return FALSE; 01016 } 01017 01018 check_read_watch (transport); 01019 check_write_watch (transport); 01020 01021 return TRUE; 01022 } 01023 01031 static void 01032 socket_do_iteration (DBusTransport *transport, 01033 unsigned int flags, 01034 int timeout_milliseconds) 01035 { 01036 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01037 DBusPollFD poll_fd; 01038 int poll_res; 01039 int poll_timeout; 01040 01041 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n", 01042 flags & DBUS_ITERATION_DO_READING ? "read" : "", 01043 flags & DBUS_ITERATION_DO_WRITING ? "write" : "", 01044 timeout_milliseconds, 01045 socket_transport->read_watch, 01046 socket_transport->write_watch, 01047 socket_transport->fd); 01048 01049 /* the passed in DO_READING/DO_WRITING flags indicate whether to 01050 * read/write messages, but regardless of those we may need to block 01051 * for reading/writing to do auth. But if we do reading for auth, 01052 * we don't want to read any messages yet if not given DO_READING. 01053 */ 01054 01055 poll_fd.fd = socket_transport->fd; 01056 poll_fd.events = 0; 01057 01058 if (_dbus_transport_get_is_authenticated (transport)) 01059 { 01060 /* This is kind of a hack; if we have stuff to write, then try 01061 * to avoid the poll. This is probably about a 5% speedup on an 01062 * echo client/server. 01063 * 01064 * If both reading and writing were requested, we want to avoid this 01065 * since it could have funky effects: 01066 * - both ends spinning waiting for the other one to read 01067 * data so they can finish writing 01068 * - prioritizing all writing ahead of reading 01069 */ 01070 if ((flags & DBUS_ITERATION_DO_WRITING) && 01071 !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) && 01072 !transport->disconnected && 01073 _dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01074 { 01075 do_writing (transport); 01076 01077 if (transport->disconnected || 01078 !_dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01079 goto out; 01080 } 01081 01082 /* If we get here, we decided to do the poll() after all */ 01083 _dbus_assert (socket_transport->read_watch); 01084 if (flags & DBUS_ITERATION_DO_READING) 01085 poll_fd.events |= _DBUS_POLLIN; 01086 01087 _dbus_assert (socket_transport->write_watch); 01088 if (flags & DBUS_ITERATION_DO_WRITING) 01089 poll_fd.events |= _DBUS_POLLOUT; 01090 } 01091 else 01092 { 01093 DBusAuthState auth_state; 01094 01095 auth_state = _dbus_auth_do_work (transport->auth); 01096 01097 if (transport->receive_credentials_pending || 01098 auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT) 01099 poll_fd.events |= _DBUS_POLLIN; 01100 01101 if (transport->send_credentials_pending || 01102 auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) 01103 poll_fd.events |= _DBUS_POLLOUT; 01104 } 01105 01106 if (poll_fd.events) 01107 { 01108 if (flags & DBUS_ITERATION_BLOCK) 01109 poll_timeout = timeout_milliseconds; 01110 else 01111 poll_timeout = 0; 01112 01113 /* For blocking selects we drop the connection lock here 01114 * to avoid blocking out connection access during a potentially 01115 * indefinite blocking call. The io path is still protected 01116 * by the io_path_cond condvar, so we won't reenter this. 01117 */ 01118 if (flags & DBUS_ITERATION_BLOCK) 01119 { 01120 _dbus_verbose ("unlock pre poll\n"); 01121 _dbus_connection_unlock (transport->connection); 01122 } 01123 01124 again: 01125 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout); 01126 01127 if (poll_res < 0 && _dbus_get_is_errno_eintr ()) 01128 goto again; 01129 01130 if (flags & DBUS_ITERATION_BLOCK) 01131 { 01132 _dbus_verbose ("lock post poll\n"); 01133 _dbus_connection_lock (transport->connection); 01134 } 01135 01136 if (poll_res >= 0) 01137 { 01138 if (poll_res == 0) 01139 poll_fd.revents = 0; /* some concern that posix does not guarantee this; 01140 * valgrind flags it as an error. though it probably 01141 * is guaranteed on linux at least. 01142 */ 01143 01144 if (poll_fd.revents & _DBUS_POLLERR) 01145 do_io_error (transport); 01146 else 01147 { 01148 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0; 01149 dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0; 01150 dbus_bool_t authentication_completed; 01151 01152 _dbus_verbose ("in iteration, need_read=%d need_write=%d\n", 01153 need_read, need_write); 01154 do_authentication (transport, need_read, need_write, 01155 &authentication_completed); 01156 01157 /* See comment in socket_handle_watch. */ 01158 if (authentication_completed) 01159 goto out; 01160 01161 if (need_read && (flags & DBUS_ITERATION_DO_READING)) 01162 do_reading (transport); 01163 if (need_write && (flags & DBUS_ITERATION_DO_WRITING)) 01164 do_writing (transport); 01165 } 01166 } 01167 else 01168 { 01169 _dbus_verbose ("Error from _dbus_poll(): %s\n", 01170 _dbus_strerror_from_errno ()); 01171 } 01172 } 01173 01174 01175 out: 01176 /* We need to install the write watch only if we did not 01177 * successfully write everything. Note we need to be careful that we 01178 * don't call check_write_watch *before* do_writing, since it's 01179 * inefficient to add the write watch, and we can avoid it most of 01180 * the time since we can write immediately. 01181 * 01182 * However, we MUST always call check_write_watch(); DBusConnection code 01183 * relies on the fact that running an iteration will notice that 01184 * messages are pending. 01185 */ 01186 check_write_watch (transport); 01187 01188 _dbus_verbose (" ... leaving do_iteration()\n"); 01189 } 01190 01191 static void 01192 socket_live_messages_changed (DBusTransport *transport) 01193 { 01194 /* See if we should look for incoming messages again */ 01195 check_read_watch (transport); 01196 } 01197 01198 01199 static dbus_bool_t 01200 socket_get_socket_fd (DBusTransport *transport, 01201 int *fd_p) 01202 { 01203 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01204 01205 *fd_p = socket_transport->fd; 01206 01207 return TRUE; 01208 } 01209 01210 static const DBusTransportVTable socket_vtable = { 01211 socket_finalize, 01212 socket_handle_watch, 01213 socket_disconnect, 01214 socket_connection_set, 01215 socket_do_iteration, 01216 socket_live_messages_changed, 01217 socket_get_socket_fd 01218 }; 01219 01231 DBusTransport* 01232 _dbus_transport_new_for_socket (int fd, 01233 const DBusString *server_guid, 01234 const DBusString *address) 01235 { 01236 DBusTransportSocket *socket_transport; 01237 01238 socket_transport = dbus_new0 (DBusTransportSocket, 1); 01239 if (socket_transport == NULL) 01240 return NULL; 01241 01242 if (!_dbus_string_init (&socket_transport->encoded_outgoing)) 01243 goto failed_0; 01244 01245 if (!_dbus_string_init (&socket_transport->encoded_incoming)) 01246 goto failed_1; 01247 01248 socket_transport->write_watch = _dbus_watch_new (fd, 01249 DBUS_WATCH_WRITABLE, 01250 FALSE, 01251 NULL, NULL, NULL); 01252 if (socket_transport->write_watch == NULL) 01253 goto failed_2; 01254 01255 socket_transport->read_watch = _dbus_watch_new (fd, 01256 DBUS_WATCH_READABLE, 01257 FALSE, 01258 NULL, NULL, NULL); 01259 if (socket_transport->read_watch == NULL) 01260 goto failed_3; 01261 01262 if (!_dbus_transport_init_base (&socket_transport->base, 01263 &socket_vtable, 01264 server_guid, address)) 01265 goto failed_4; 01266 01267 #ifdef HAVE_UNIX_FD_PASSING 01268 _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); 01269 #endif 01270 01271 socket_transport->fd = fd; 01272 socket_transport->message_bytes_written = 0; 01273 01274 /* These values should probably be tunable or something. */ 01275 socket_transport->max_bytes_read_per_iteration = 2048; 01276 socket_transport->max_bytes_written_per_iteration = 2048; 01277 01278 return (DBusTransport*) socket_transport; 01279 01280 failed_4: 01281 _dbus_watch_unref (socket_transport->read_watch); 01282 failed_3: 01283 _dbus_watch_unref (socket_transport->write_watch); 01284 failed_2: 01285 _dbus_string_free (&socket_transport->encoded_incoming); 01286 failed_1: 01287 _dbus_string_free (&socket_transport->encoded_outgoing); 01288 failed_0: 01289 dbus_free (socket_transport); 01290 return NULL; 01291 } 01292 01304 DBusTransport* 01305 _dbus_transport_new_for_tcp_socket (const char *host, 01306 const char *port, 01307 const char *family, 01308 const char *noncefile, 01309 DBusError *error) 01310 { 01311 int fd; 01312 DBusTransport *transport; 01313 DBusString address; 01314 01315 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01316 01317 if (!_dbus_string_init (&address)) 01318 { 01319 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01320 return NULL; 01321 } 01322 01323 if (host == NULL) 01324 host = "localhost"; 01325 01326 if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:")) 01327 goto error; 01328 01329 if (!_dbus_string_append (&address, "host=") || 01330 !_dbus_string_append (&address, host)) 01331 goto error; 01332 01333 if (!_dbus_string_append (&address, ",port=") || 01334 !_dbus_string_append (&address, port)) 01335 goto error; 01336 01337 if (family != NULL && 01338 (!_dbus_string_append (&address, "family=") || 01339 !_dbus_string_append (&address, family))) 01340 goto error; 01341 01342 if (noncefile != NULL && 01343 (!_dbus_string_append (&address, "noncefile=") || 01344 !_dbus_string_append (&address, noncefile))) 01345 goto error; 01346 01347 fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error); 01348 if (fd < 0) 01349 { 01350 _DBUS_ASSERT_ERROR_IS_SET (error); 01351 _dbus_string_free (&address); 01352 return NULL; 01353 } 01354 01355 _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", 01356 host, port); 01357 01358 transport = _dbus_transport_new_for_socket (fd, NULL, &address); 01359 _dbus_string_free (&address); 01360 if (transport == NULL) 01361 { 01362 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01363 _dbus_close_socket (fd, NULL); 01364 fd = -1; 01365 } 01366 01367 return transport; 01368 01369 error: 01370 _dbus_string_free (&address); 01371 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01372 return NULL; 01373 } 01374 01383 DBusTransportOpenResult 01384 _dbus_transport_open_socket(DBusAddressEntry *entry, 01385 DBusTransport **transport_p, 01386 DBusError *error) 01387 { 01388 const char *method; 01389 dbus_bool_t isTcp; 01390 dbus_bool_t isNonceTcp; 01391 01392 method = dbus_address_entry_get_method (entry); 01393 _dbus_assert (method != NULL); 01394 01395 isTcp = strcmp (method, "tcp") == 0; 01396 isNonceTcp = strcmp (method, "nonce-tcp") == 0; 01397 01398 if (isTcp || isNonceTcp) 01399 { 01400 const char *host = dbus_address_entry_get_value (entry, "host"); 01401 const char *port = dbus_address_entry_get_value (entry, "port"); 01402 const char *family = dbus_address_entry_get_value (entry, "family"); 01403 const char *noncefile = dbus_address_entry_get_value (entry, "noncefile"); 01404 01405 if ((isNonceTcp == TRUE) != (noncefile != NULL)) { 01406 _dbus_set_bad_address (error, method, "noncefile", NULL); 01407 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01408 } 01409 01410 if (port == NULL) 01411 { 01412 _dbus_set_bad_address (error, method, "port", NULL); 01413 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01414 } 01415 01416 *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error); 01417 if (*transport_p == NULL) 01418 { 01419 _DBUS_ASSERT_ERROR_IS_SET (error); 01420 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 01421 } 01422 else 01423 { 01424 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01425 return DBUS_TRANSPORT_OPEN_OK; 01426 } 01427 } 01428 else 01429 { 01430 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01431 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 01432 } 01433 } 01434