D-Bus
1.4.18
|
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 /* If the other end closed the socket with close() or shutdown(), we 00650 * receive EPIPE here but we must not close the socket yet: there 00651 * might still be some data to read. See: 00652 * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html 00653 */ 00654 00655 if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ()) 00656 goto out; 00657 00658 /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg() 00659 * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd 00660 * mechanism (SCM_RIGHTS) is used recursively with a recursion level 00661 * of maximum 4. The kernel does not have an API to check whether 00662 * the passed fds can be forwarded and it can change asynchronously. 00663 * See: 00664 * https://bugs.freedesktop.org/show_bug.cgi?id=80163 00665 */ 00666 00667 else if (_dbus_get_is_errno_etoomanyrefs ()) 00668 { 00669 /* We only send fds in the first byte of the message. 00670 * ETOOMANYREFS cannot happen after. 00671 */ 00672 _dbus_assert (socket_transport->message_bytes_written == 0); 00673 00674 _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n", 00675 total_bytes_to_write); 00676 00677 socket_transport->message_bytes_written = 0; 00678 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00679 _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); 00680 00681 /* The message was not actually sent but it needs to be removed 00682 * from the outgoing queue 00683 */ 00684 _dbus_connection_message_sent (transport->connection, 00685 message); 00686 } 00687 else 00688 { 00689 _dbus_verbose ("Error writing to remote app: %s\n", 00690 _dbus_strerror_from_errno ()); 00691 do_io_error (transport); 00692 goto out; 00693 } 00694 } 00695 else 00696 { 00697 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written, 00698 total_bytes_to_write); 00699 00700 total += bytes_written; 00701 socket_transport->message_bytes_written += bytes_written; 00702 00703 _dbus_assert (socket_transport->message_bytes_written <= 00704 total_bytes_to_write); 00705 00706 if (socket_transport->message_bytes_written == total_bytes_to_write) 00707 { 00708 socket_transport->message_bytes_written = 0; 00709 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00710 _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); 00711 00712 _dbus_connection_message_sent (transport->connection, 00713 message); 00714 } 00715 } 00716 } 00717 00718 out: 00719 if (oom) 00720 return FALSE; 00721 else 00722 return TRUE; 00723 } 00724 00725 /* returns false on out-of-memory */ 00726 static dbus_bool_t 00727 do_reading (DBusTransport *transport) 00728 { 00729 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00730 DBusString *buffer; 00731 int bytes_read; 00732 int total; 00733 dbus_bool_t oom; 00734 00735 _dbus_verbose ("fd = %d\n",socket_transport->fd); 00736 00737 /* No messages without authentication! */ 00738 if (!_dbus_transport_get_is_authenticated (transport)) 00739 return TRUE; 00740 00741 oom = FALSE; 00742 00743 total = 0; 00744 00745 again: 00746 00747 /* See if we've exceeded max messages and need to disable reading */ 00748 check_read_watch (transport); 00749 00750 if (total > socket_transport->max_bytes_read_per_iteration) 00751 { 00752 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n", 00753 total, socket_transport->max_bytes_read_per_iteration); 00754 goto out; 00755 } 00756 00757 _dbus_assert (socket_transport->read_watch != NULL || 00758 transport->disconnected); 00759 00760 if (transport->disconnected) 00761 goto out; 00762 00763 if (!dbus_watch_get_enabled (socket_transport->read_watch)) 00764 return TRUE; 00765 00766 if (_dbus_auth_needs_decoding (transport->auth)) 00767 { 00768 /* Does fd passing even make sense with encoded data? */ 00769 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); 00770 00771 if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0) 00772 bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming); 00773 else 00774 bytes_read = _dbus_read_socket (socket_transport->fd, 00775 &socket_transport->encoded_incoming, 00776 socket_transport->max_bytes_read_per_iteration); 00777 00778 _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) == 00779 bytes_read); 00780 00781 if (bytes_read > 0) 00782 { 00783 int orig_len; 00784 00785 _dbus_message_loader_get_buffer (transport->loader, 00786 &buffer); 00787 00788 orig_len = _dbus_string_get_length (buffer); 00789 00790 if (!_dbus_auth_decode_data (transport->auth, 00791 &socket_transport->encoded_incoming, 00792 buffer)) 00793 { 00794 _dbus_verbose ("Out of memory decoding incoming data\n"); 00795 _dbus_message_loader_return_buffer (transport->loader, 00796 buffer, 00797 _dbus_string_get_length (buffer) - orig_len); 00798 00799 oom = TRUE; 00800 goto out; 00801 } 00802 00803 _dbus_message_loader_return_buffer (transport->loader, 00804 buffer, 00805 _dbus_string_get_length (buffer) - orig_len); 00806 00807 _dbus_string_set_length (&socket_transport->encoded_incoming, 0); 00808 _dbus_string_compact (&socket_transport->encoded_incoming, 2048); 00809 } 00810 } 00811 else 00812 { 00813 _dbus_message_loader_get_buffer (transport->loader, 00814 &buffer); 00815 00816 #ifdef HAVE_UNIX_FD_PASSING 00817 if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) 00818 { 00819 int *fds, n_fds; 00820 00821 if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds)) 00822 { 00823 _dbus_verbose ("Out of memory reading file descriptors\n"); 00824 _dbus_message_loader_return_buffer (transport->loader, buffer, 0); 00825 oom = TRUE; 00826 goto out; 00827 } 00828 00829 bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd, 00830 buffer, 00831 socket_transport->max_bytes_read_per_iteration, 00832 fds, &n_fds); 00833 00834 if (bytes_read >= 0 && n_fds > 0) 00835 _dbus_verbose("Read %i unix fds\n", n_fds); 00836 00837 _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds); 00838 } 00839 else 00840 #endif 00841 { 00842 bytes_read = _dbus_read_socket (socket_transport->fd, 00843 buffer, socket_transport->max_bytes_read_per_iteration); 00844 } 00845 00846 _dbus_message_loader_return_buffer (transport->loader, 00847 buffer, 00848 bytes_read < 0 ? 0 : bytes_read); 00849 } 00850 00851 if (bytes_read < 0) 00852 { 00853 /* EINTR already handled for us */ 00854 00855 if (_dbus_get_is_errno_enomem ()) 00856 { 00857 _dbus_verbose ("Out of memory in read()/do_reading()\n"); 00858 oom = TRUE; 00859 goto out; 00860 } 00861 else if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00862 goto out; 00863 else 00864 { 00865 _dbus_verbose ("Error reading from remote app: %s\n", 00866 _dbus_strerror_from_errno ()); 00867 do_io_error (transport); 00868 goto out; 00869 } 00870 } 00871 else if (bytes_read == 0) 00872 { 00873 _dbus_verbose ("Disconnected from remote app\n"); 00874 do_io_error (transport); 00875 goto out; 00876 } 00877 else 00878 { 00879 _dbus_verbose (" read %d bytes\n", bytes_read); 00880 00881 total += bytes_read; 00882 00883 if (!_dbus_transport_queue_messages (transport)) 00884 { 00885 oom = TRUE; 00886 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n"); 00887 goto out; 00888 } 00889 00890 /* Try reading more data until we get EAGAIN and return, or 00891 * exceed max bytes per iteration. If in blocking mode of 00892 * course we'll block instead of returning. 00893 */ 00894 goto again; 00895 } 00896 00897 out: 00898 if (oom) 00899 return FALSE; 00900 else 00901 return TRUE; 00902 } 00903 00904 static dbus_bool_t 00905 unix_error_with_read_to_come (DBusTransport *itransport, 00906 DBusWatch *watch, 00907 unsigned int flags) 00908 { 00909 DBusTransportSocket *transport = (DBusTransportSocket *) itransport; 00910 00911 if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR)) 00912 return FALSE; 00913 00914 /* If we have a read watch enabled ... 00915 we -might have data incoming ... => handle the HANGUP there */ 00916 if (watch != transport->read_watch && 00917 _dbus_watch_get_enabled (transport->read_watch)) 00918 return FALSE; 00919 00920 return TRUE; 00921 } 00922 00923 static dbus_bool_t 00924 socket_handle_watch (DBusTransport *transport, 00925 DBusWatch *watch, 00926 unsigned int flags) 00927 { 00928 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00929 00930 _dbus_assert (watch == socket_transport->read_watch || 00931 watch == socket_transport->write_watch); 00932 _dbus_assert (watch != NULL); 00933 00934 /* If we hit an error here on a write watch, don't disconnect the transport yet because data can 00935 * still be in the buffer and do_reading may need several iteration to read 00936 * it all (because of its max_bytes_read_per_iteration limit). 00937 */ 00938 if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags)) 00939 { 00940 _dbus_verbose ("Hang up or error on watch\n"); 00941 _dbus_transport_disconnect (transport); 00942 return TRUE; 00943 } 00944 00945 if (watch == socket_transport->read_watch && 00946 (flags & DBUS_WATCH_READABLE)) 00947 { 00948 dbus_bool_t auth_finished; 00949 #if 1 00950 _dbus_verbose ("handling read watch %p flags = %x\n", 00951 watch, flags); 00952 #endif 00953 if (!do_authentication (transport, TRUE, FALSE, &auth_finished)) 00954 return FALSE; 00955 00956 /* We don't want to do a read immediately following 00957 * a successful authentication. This is so we 00958 * have a chance to propagate the authentication 00959 * state further up. Specifically, we need to 00960 * process any pending data from the auth object. 00961 */ 00962 if (!auth_finished) 00963 { 00964 if (!do_reading (transport)) 00965 { 00966 _dbus_verbose ("no memory to read\n"); 00967 return FALSE; 00968 } 00969 } 00970 else 00971 { 00972 _dbus_verbose ("Not reading anything since we just completed the authentication\n"); 00973 } 00974 } 00975 else if (watch == socket_transport->write_watch && 00976 (flags & DBUS_WATCH_WRITABLE)) 00977 { 00978 #if 1 00979 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n", 00980 _dbus_connection_has_messages_to_send_unlocked (transport->connection)); 00981 #endif 00982 if (!do_authentication (transport, FALSE, TRUE, NULL)) 00983 return FALSE; 00984 00985 if (!do_writing (transport)) 00986 { 00987 _dbus_verbose ("no memory to write\n"); 00988 return FALSE; 00989 } 00990 00991 /* See if we still need the write watch */ 00992 check_write_watch (transport); 00993 } 00994 #ifdef DBUS_ENABLE_VERBOSE_MODE 00995 else 00996 { 00997 if (watch == socket_transport->read_watch) 00998 _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n", 00999 flags); 01000 else if (watch == socket_transport->write_watch) 01001 _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n", 01002 flags); 01003 else 01004 _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n", 01005 watch, dbus_watch_get_socket (watch)); 01006 } 01007 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 01008 01009 return TRUE; 01010 } 01011 01012 static void 01013 socket_disconnect (DBusTransport *transport) 01014 { 01015 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01016 01017 _dbus_verbose ("\n"); 01018 01019 free_watches (transport); 01020 01021 _dbus_close_socket (socket_transport->fd, NULL); 01022 socket_transport->fd = -1; 01023 } 01024 01025 static dbus_bool_t 01026 socket_connection_set (DBusTransport *transport) 01027 { 01028 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01029 01030 _dbus_watch_set_handler (socket_transport->write_watch, 01031 _dbus_connection_handle_watch, 01032 transport->connection, NULL); 01033 01034 _dbus_watch_set_handler (socket_transport->read_watch, 01035 _dbus_connection_handle_watch, 01036 transport->connection, NULL); 01037 01038 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01039 socket_transport->write_watch)) 01040 return FALSE; 01041 01042 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01043 socket_transport->read_watch)) 01044 { 01045 _dbus_connection_remove_watch_unlocked (transport->connection, 01046 socket_transport->write_watch); 01047 return FALSE; 01048 } 01049 01050 check_read_watch (transport); 01051 check_write_watch (transport); 01052 01053 return TRUE; 01054 } 01055 01063 static void 01064 socket_do_iteration (DBusTransport *transport, 01065 unsigned int flags, 01066 int timeout_milliseconds) 01067 { 01068 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01069 DBusPollFD poll_fd; 01070 int poll_res; 01071 int poll_timeout; 01072 01073 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n", 01074 flags & DBUS_ITERATION_DO_READING ? "read" : "", 01075 flags & DBUS_ITERATION_DO_WRITING ? "write" : "", 01076 timeout_milliseconds, 01077 socket_transport->read_watch, 01078 socket_transport->write_watch, 01079 socket_transport->fd); 01080 01081 /* the passed in DO_READING/DO_WRITING flags indicate whether to 01082 * read/write messages, but regardless of those we may need to block 01083 * for reading/writing to do auth. But if we do reading for auth, 01084 * we don't want to read any messages yet if not given DO_READING. 01085 */ 01086 01087 poll_fd.fd = socket_transport->fd; 01088 poll_fd.events = 0; 01089 01090 if (_dbus_transport_get_is_authenticated (transport)) 01091 { 01092 /* This is kind of a hack; if we have stuff to write, then try 01093 * to avoid the poll. This is probably about a 5% speedup on an 01094 * echo client/server. 01095 * 01096 * If both reading and writing were requested, we want to avoid this 01097 * since it could have funky effects: 01098 * - both ends spinning waiting for the other one to read 01099 * data so they can finish writing 01100 * - prioritizing all writing ahead of reading 01101 */ 01102 if ((flags & DBUS_ITERATION_DO_WRITING) && 01103 !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) && 01104 !transport->disconnected && 01105 _dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01106 { 01107 do_writing (transport); 01108 01109 if (transport->disconnected || 01110 !_dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01111 goto out; 01112 } 01113 01114 /* If we get here, we decided to do the poll() after all */ 01115 _dbus_assert (socket_transport->read_watch); 01116 if (flags & DBUS_ITERATION_DO_READING) 01117 poll_fd.events |= _DBUS_POLLIN; 01118 01119 _dbus_assert (socket_transport->write_watch); 01120 if (flags & DBUS_ITERATION_DO_WRITING) 01121 poll_fd.events |= _DBUS_POLLOUT; 01122 } 01123 else 01124 { 01125 DBusAuthState auth_state; 01126 01127 auth_state = _dbus_auth_do_work (transport->auth); 01128 01129 if (transport->receive_credentials_pending || 01130 auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT) 01131 poll_fd.events |= _DBUS_POLLIN; 01132 01133 if (transport->send_credentials_pending || 01134 auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) 01135 poll_fd.events |= _DBUS_POLLOUT; 01136 } 01137 01138 if (poll_fd.events) 01139 { 01140 if (flags & DBUS_ITERATION_BLOCK) 01141 poll_timeout = timeout_milliseconds; 01142 else 01143 poll_timeout = 0; 01144 01145 /* For blocking selects we drop the connection lock here 01146 * to avoid blocking out connection access during a potentially 01147 * indefinite blocking call. The io path is still protected 01148 * by the io_path_cond condvar, so we won't reenter this. 01149 */ 01150 if (flags & DBUS_ITERATION_BLOCK) 01151 { 01152 _dbus_verbose ("unlock pre poll\n"); 01153 _dbus_connection_unlock (transport->connection); 01154 } 01155 01156 again: 01157 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout); 01158 01159 if (poll_res < 0 && _dbus_get_is_errno_eintr ()) 01160 goto again; 01161 01162 if (flags & DBUS_ITERATION_BLOCK) 01163 { 01164 _dbus_verbose ("lock post poll\n"); 01165 _dbus_connection_lock (transport->connection); 01166 } 01167 01168 if (poll_res >= 0) 01169 { 01170 if (poll_res == 0) 01171 poll_fd.revents = 0; /* some concern that posix does not guarantee this; 01172 * valgrind flags it as an error. though it probably 01173 * is guaranteed on linux at least. 01174 */ 01175 01176 if (poll_fd.revents & _DBUS_POLLERR) 01177 do_io_error (transport); 01178 else 01179 { 01180 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0; 01181 dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0; 01182 dbus_bool_t authentication_completed; 01183 01184 _dbus_verbose ("in iteration, need_read=%d need_write=%d\n", 01185 need_read, need_write); 01186 do_authentication (transport, need_read, need_write, 01187 &authentication_completed); 01188 01189 /* See comment in socket_handle_watch. */ 01190 if (authentication_completed) 01191 goto out; 01192 01193 if (need_read && (flags & DBUS_ITERATION_DO_READING)) 01194 do_reading (transport); 01195 if (need_write && (flags & DBUS_ITERATION_DO_WRITING)) 01196 do_writing (transport); 01197 } 01198 } 01199 else 01200 { 01201 _dbus_verbose ("Error from _dbus_poll(): %s\n", 01202 _dbus_strerror_from_errno ()); 01203 } 01204 } 01205 01206 01207 out: 01208 /* We need to install the write watch only if we did not 01209 * successfully write everything. Note we need to be careful that we 01210 * don't call check_write_watch *before* do_writing, since it's 01211 * inefficient to add the write watch, and we can avoid it most of 01212 * the time since we can write immediately. 01213 * 01214 * However, we MUST always call check_write_watch(); DBusConnection code 01215 * relies on the fact that running an iteration will notice that 01216 * messages are pending. 01217 */ 01218 check_write_watch (transport); 01219 01220 _dbus_verbose (" ... leaving do_iteration()\n"); 01221 } 01222 01223 static void 01224 socket_live_messages_changed (DBusTransport *transport) 01225 { 01226 /* See if we should look for incoming messages again */ 01227 check_read_watch (transport); 01228 } 01229 01230 01231 static dbus_bool_t 01232 socket_get_socket_fd (DBusTransport *transport, 01233 int *fd_p) 01234 { 01235 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01236 01237 *fd_p = socket_transport->fd; 01238 01239 return TRUE; 01240 } 01241 01242 static const DBusTransportVTable socket_vtable = { 01243 socket_finalize, 01244 socket_handle_watch, 01245 socket_disconnect, 01246 socket_connection_set, 01247 socket_do_iteration, 01248 socket_live_messages_changed, 01249 socket_get_socket_fd 01250 }; 01251 01263 DBusTransport* 01264 _dbus_transport_new_for_socket (int fd, 01265 const DBusString *server_guid, 01266 const DBusString *address) 01267 { 01268 DBusTransportSocket *socket_transport; 01269 01270 socket_transport = dbus_new0 (DBusTransportSocket, 1); 01271 if (socket_transport == NULL) 01272 return NULL; 01273 01274 if (!_dbus_string_init (&socket_transport->encoded_outgoing)) 01275 goto failed_0; 01276 01277 if (!_dbus_string_init (&socket_transport->encoded_incoming)) 01278 goto failed_1; 01279 01280 socket_transport->write_watch = _dbus_watch_new (fd, 01281 DBUS_WATCH_WRITABLE, 01282 FALSE, 01283 NULL, NULL, NULL); 01284 if (socket_transport->write_watch == NULL) 01285 goto failed_2; 01286 01287 socket_transport->read_watch = _dbus_watch_new (fd, 01288 DBUS_WATCH_READABLE, 01289 FALSE, 01290 NULL, NULL, NULL); 01291 if (socket_transport->read_watch == NULL) 01292 goto failed_3; 01293 01294 if (!_dbus_transport_init_base (&socket_transport->base, 01295 &socket_vtable, 01296 server_guid, address)) 01297 goto failed_4; 01298 01299 #ifdef HAVE_UNIX_FD_PASSING 01300 _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); 01301 #endif 01302 01303 socket_transport->fd = fd; 01304 socket_transport->message_bytes_written = 0; 01305 01306 /* These values should probably be tunable or something. */ 01307 socket_transport->max_bytes_read_per_iteration = 2048; 01308 socket_transport->max_bytes_written_per_iteration = 2048; 01309 01310 return (DBusTransport*) socket_transport; 01311 01312 failed_4: 01313 _dbus_watch_unref (socket_transport->read_watch); 01314 failed_3: 01315 _dbus_watch_unref (socket_transport->write_watch); 01316 failed_2: 01317 _dbus_string_free (&socket_transport->encoded_incoming); 01318 failed_1: 01319 _dbus_string_free (&socket_transport->encoded_outgoing); 01320 failed_0: 01321 dbus_free (socket_transport); 01322 return NULL; 01323 } 01324 01336 DBusTransport* 01337 _dbus_transport_new_for_tcp_socket (const char *host, 01338 const char *port, 01339 const char *family, 01340 const char *noncefile, 01341 DBusError *error) 01342 { 01343 int fd; 01344 DBusTransport *transport; 01345 DBusString address; 01346 01347 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01348 01349 if (!_dbus_string_init (&address)) 01350 { 01351 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01352 return NULL; 01353 } 01354 01355 if (host == NULL) 01356 host = "localhost"; 01357 01358 if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:")) 01359 goto error; 01360 01361 if (!_dbus_string_append (&address, "host=") || 01362 !_dbus_string_append (&address, host)) 01363 goto error; 01364 01365 if (!_dbus_string_append (&address, ",port=") || 01366 !_dbus_string_append (&address, port)) 01367 goto error; 01368 01369 if (family != NULL && 01370 (!_dbus_string_append (&address, "family=") || 01371 !_dbus_string_append (&address, family))) 01372 goto error; 01373 01374 if (noncefile != NULL && 01375 (!_dbus_string_append (&address, "noncefile=") || 01376 !_dbus_string_append (&address, noncefile))) 01377 goto error; 01378 01379 fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error); 01380 if (fd < 0) 01381 { 01382 _DBUS_ASSERT_ERROR_IS_SET (error); 01383 _dbus_string_free (&address); 01384 return NULL; 01385 } 01386 01387 _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", 01388 host, port); 01389 01390 transport = _dbus_transport_new_for_socket (fd, NULL, &address); 01391 _dbus_string_free (&address); 01392 if (transport == NULL) 01393 { 01394 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01395 _dbus_close_socket (fd, NULL); 01396 fd = -1; 01397 } 01398 01399 return transport; 01400 01401 error: 01402 _dbus_string_free (&address); 01403 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01404 return NULL; 01405 } 01406 01415 DBusTransportOpenResult 01416 _dbus_transport_open_socket(DBusAddressEntry *entry, 01417 DBusTransport **transport_p, 01418 DBusError *error) 01419 { 01420 const char *method; 01421 dbus_bool_t isTcp; 01422 dbus_bool_t isNonceTcp; 01423 01424 method = dbus_address_entry_get_method (entry); 01425 _dbus_assert (method != NULL); 01426 01427 isTcp = strcmp (method, "tcp") == 0; 01428 isNonceTcp = strcmp (method, "nonce-tcp") == 0; 01429 01430 if (isTcp || isNonceTcp) 01431 { 01432 const char *host = dbus_address_entry_get_value (entry, "host"); 01433 const char *port = dbus_address_entry_get_value (entry, "port"); 01434 const char *family = dbus_address_entry_get_value (entry, "family"); 01435 const char *noncefile = dbus_address_entry_get_value (entry, "noncefile"); 01436 01437 if ((isNonceTcp == TRUE) != (noncefile != NULL)) { 01438 _dbus_set_bad_address (error, method, "noncefile", NULL); 01439 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01440 } 01441 01442 if (port == NULL) 01443 { 01444 _dbus_set_bad_address (error, method, "port", NULL); 01445 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01446 } 01447 01448 *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error); 01449 if (*transport_p == NULL) 01450 { 01451 _DBUS_ASSERT_ERROR_IS_SET (error); 01452 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 01453 } 01454 else 01455 { 01456 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01457 return DBUS_TRANSPORT_OPEN_OK; 01458 } 01459 } 01460 else 01461 { 01462 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01463 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 01464 } 01465 } 01466