|
D-Bus
1.8.20
|
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_try_to_authenticate (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_try_to_authenticate (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 00260 if (bytes_read > 0) 00261 { 00262 _dbus_verbose (" read %d bytes in auth phase\n", bytes_read); 00263 00264 return TRUE; 00265 } 00266 else if (bytes_read < 0) 00267 { 00268 /* EINTR already handled for us */ 00269 00270 if (_dbus_get_is_errno_enomem ()) 00271 { 00272 *oom = TRUE; 00273 } 00274 else if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00275 ; /* do nothing, just return FALSE below */ 00276 else 00277 { 00278 _dbus_verbose ("Error reading from remote app: %s\n", 00279 _dbus_strerror_from_errno ()); 00280 do_io_error (transport); 00281 } 00282 00283 return FALSE; 00284 } 00285 else 00286 { 00287 _dbus_assert (bytes_read == 0); 00288 00289 _dbus_verbose ("Disconnected from remote app\n"); 00290 do_io_error (transport); 00291 00292 return FALSE; 00293 } 00294 } 00295 00296 /* Return value is whether we successfully wrote any bytes */ 00297 static dbus_bool_t 00298 write_data_from_auth (DBusTransport *transport) 00299 { 00300 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00301 int bytes_written; 00302 const DBusString *buffer; 00303 00304 if (!_dbus_auth_get_bytes_to_send (transport->auth, 00305 &buffer)) 00306 return FALSE; 00307 00308 bytes_written = _dbus_write_socket (socket_transport->fd, 00309 buffer, 00310 0, _dbus_string_get_length (buffer)); 00311 00312 if (bytes_written > 0) 00313 { 00314 _dbus_auth_bytes_sent (transport->auth, bytes_written); 00315 return TRUE; 00316 } 00317 else if (bytes_written < 0) 00318 { 00319 /* EINTR already handled for us */ 00320 00321 if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00322 ; 00323 else 00324 { 00325 _dbus_verbose ("Error writing to remote app: %s\n", 00326 _dbus_strerror_from_errno ()); 00327 do_io_error (transport); 00328 } 00329 } 00330 00331 return FALSE; 00332 } 00333 00334 /* FALSE on OOM */ 00335 static dbus_bool_t 00336 exchange_credentials (DBusTransport *transport, 00337 dbus_bool_t do_reading, 00338 dbus_bool_t do_writing) 00339 { 00340 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00341 DBusError error = DBUS_ERROR_INIT; 00342 00343 _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n", 00344 do_reading, do_writing); 00345 00346 if (do_writing && transport->send_credentials_pending) 00347 { 00348 if (_dbus_send_credentials_socket (socket_transport->fd, 00349 &error)) 00350 { 00351 transport->send_credentials_pending = FALSE; 00352 } 00353 else 00354 { 00355 _dbus_verbose ("Failed to write credentials: %s\n", error.message); 00356 dbus_error_free (&error); 00357 do_io_error (transport); 00358 } 00359 } 00360 00361 if (do_reading && transport->receive_credentials_pending) 00362 { 00363 /* FIXME this can fail due to IO error _or_ OOM, broken 00364 * (somewhat tricky to fix since the OOM error can be set after 00365 * we already read the credentials byte, so basically we need to 00366 * separate reading the byte and storing it in the 00367 * transport->credentials). Does not really matter for now 00368 * because storing in credentials never actually fails on unix. 00369 */ 00370 if (_dbus_read_credentials_socket (socket_transport->fd, 00371 transport->credentials, 00372 &error)) 00373 { 00374 transport->receive_credentials_pending = FALSE; 00375 } 00376 else 00377 { 00378 _dbus_verbose ("Failed to read credentials %s\n", error.message); 00379 dbus_error_free (&error); 00380 do_io_error (transport); 00381 } 00382 } 00383 00384 if (!(transport->send_credentials_pending || 00385 transport->receive_credentials_pending)) 00386 { 00387 if (!_dbus_auth_set_credentials (transport->auth, 00388 transport->credentials)) 00389 return FALSE; 00390 } 00391 00392 return TRUE; 00393 } 00394 00395 static dbus_bool_t 00396 do_authentication (DBusTransport *transport, 00397 dbus_bool_t do_reading, 00398 dbus_bool_t do_writing, 00399 dbus_bool_t *auth_completed) 00400 { 00401 dbus_bool_t oom; 00402 dbus_bool_t orig_auth_state; 00403 00404 oom = FALSE; 00405 00406 orig_auth_state = _dbus_transport_try_to_authenticate (transport); 00407 00408 /* This is essential to avoid the check_write_watch() at the end, 00409 * we don't want to add a write watch in do_iteration before 00410 * we try writing and get EAGAIN 00411 */ 00412 if (orig_auth_state) 00413 { 00414 if (auth_completed) 00415 *auth_completed = FALSE; 00416 return TRUE; 00417 } 00418 00419 _dbus_transport_ref (transport); 00420 00421 while (!_dbus_transport_try_to_authenticate (transport) && 00422 _dbus_transport_get_is_connected (transport)) 00423 { 00424 if (!exchange_credentials (transport, do_reading, do_writing)) 00425 { 00426 /* OOM */ 00427 oom = TRUE; 00428 goto out; 00429 } 00430 00431 if (transport->send_credentials_pending || 00432 transport->receive_credentials_pending) 00433 { 00434 _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n", 00435 transport->send_credentials_pending, 00436 transport->receive_credentials_pending); 00437 goto out; 00438 } 00439 00440 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client") 00441 switch (_dbus_auth_do_work (transport->auth)) 00442 { 00443 case DBUS_AUTH_STATE_WAITING_FOR_INPUT: 00444 _dbus_verbose (" %s auth state: waiting for input\n", 00445 TRANSPORT_SIDE (transport)); 00446 if (!do_reading || !read_data_into_auth (transport, &oom)) 00447 goto out; 00448 break; 00449 00450 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: 00451 _dbus_verbose (" %s auth state: waiting for memory\n", 00452 TRANSPORT_SIDE (transport)); 00453 oom = TRUE; 00454 goto out; 00455 break; 00456 00457 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND: 00458 _dbus_verbose (" %s auth state: bytes to send\n", 00459 TRANSPORT_SIDE (transport)); 00460 if (!do_writing || !write_data_from_auth (transport)) 00461 goto out; 00462 break; 00463 00464 case DBUS_AUTH_STATE_NEED_DISCONNECT: 00465 _dbus_verbose (" %s auth state: need to disconnect\n", 00466 TRANSPORT_SIDE (transport)); 00467 do_io_error (transport); 00468 break; 00469 00470 case DBUS_AUTH_STATE_AUTHENTICATED: 00471 _dbus_verbose (" %s auth state: authenticated\n", 00472 TRANSPORT_SIDE (transport)); 00473 break; 00474 } 00475 } 00476 00477 out: 00478 if (auth_completed) 00479 *auth_completed = (orig_auth_state != _dbus_transport_try_to_authenticate (transport)); 00480 00481 check_read_watch (transport); 00482 check_write_watch (transport); 00483 _dbus_transport_unref (transport); 00484 00485 if (oom) 00486 return FALSE; 00487 else 00488 return TRUE; 00489 } 00490 00491 /* returns false on oom */ 00492 static dbus_bool_t 00493 do_writing (DBusTransport *transport) 00494 { 00495 int total; 00496 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00497 dbus_bool_t oom; 00498 00499 /* No messages without authentication! */ 00500 if (!_dbus_transport_try_to_authenticate (transport)) 00501 { 00502 _dbus_verbose ("Not authenticated, not writing anything\n"); 00503 return TRUE; 00504 } 00505 00506 if (transport->disconnected) 00507 { 00508 _dbus_verbose ("Not connected, not writing anything\n"); 00509 return TRUE; 00510 } 00511 00512 #if 1 00513 _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n", 00514 _dbus_connection_has_messages_to_send_unlocked (transport->connection), 00515 socket_transport->fd); 00516 #endif 00517 00518 oom = FALSE; 00519 total = 0; 00520 00521 while (!transport->disconnected && 00522 _dbus_connection_has_messages_to_send_unlocked (transport->connection)) 00523 { 00524 int bytes_written; 00525 DBusMessage *message; 00526 const DBusString *header; 00527 const DBusString *body; 00528 int header_len, body_len; 00529 int total_bytes_to_write; 00530 00531 if (total > socket_transport->max_bytes_written_per_iteration) 00532 { 00533 _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n", 00534 total, socket_transport->max_bytes_written_per_iteration); 00535 goto out; 00536 } 00537 00538 message = _dbus_connection_get_message_to_send (transport->connection); 00539 _dbus_assert (message != NULL); 00540 dbus_message_lock (message); 00541 00542 #if 0 00543 _dbus_verbose ("writing message %p\n", message); 00544 #endif 00545 00546 _dbus_message_get_network_data (message, 00547 &header, &body); 00548 00549 header_len = _dbus_string_get_length (header); 00550 body_len = _dbus_string_get_length (body); 00551 00552 if (_dbus_auth_needs_encoding (transport->auth)) 00553 { 00554 /* Does fd passing even make sense with encoded data? */ 00555 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); 00556 00557 if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0) 00558 { 00559 if (!_dbus_auth_encode_data (transport->auth, 00560 header, &socket_transport->encoded_outgoing)) 00561 { 00562 oom = TRUE; 00563 goto out; 00564 } 00565 00566 if (!_dbus_auth_encode_data (transport->auth, 00567 body, &socket_transport->encoded_outgoing)) 00568 { 00569 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00570 oom = TRUE; 00571 goto out; 00572 } 00573 } 00574 00575 total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing); 00576 00577 #if 0 00578 _dbus_verbose ("encoded message is %d bytes\n", 00579 total_bytes_to_write); 00580 #endif 00581 00582 bytes_written = 00583 _dbus_write_socket (socket_transport->fd, 00584 &socket_transport->encoded_outgoing, 00585 socket_transport->message_bytes_written, 00586 total_bytes_to_write - socket_transport->message_bytes_written); 00587 } 00588 else 00589 { 00590 total_bytes_to_write = header_len + body_len; 00591 00592 #if 0 00593 _dbus_verbose ("message is %d bytes\n", 00594 total_bytes_to_write); 00595 #endif 00596 00597 #ifdef HAVE_UNIX_FD_PASSING 00598 if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) 00599 { 00600 /* Send the fds along with the first byte of the message */ 00601 const int *unix_fds; 00602 unsigned n; 00603 00604 _dbus_message_get_unix_fds(message, &unix_fds, &n); 00605 00606 bytes_written = 00607 _dbus_write_socket_with_unix_fds_two (socket_transport->fd, 00608 header, 00609 socket_transport->message_bytes_written, 00610 header_len - socket_transport->message_bytes_written, 00611 body, 00612 0, body_len, 00613 unix_fds, 00614 n); 00615 00616 if (bytes_written > 0 && n > 0) 00617 _dbus_verbose("Wrote %i unix fds\n", n); 00618 } 00619 else 00620 #endif 00621 { 00622 if (socket_transport->message_bytes_written < header_len) 00623 { 00624 bytes_written = 00625 _dbus_write_socket_two (socket_transport->fd, 00626 header, 00627 socket_transport->message_bytes_written, 00628 header_len - socket_transport->message_bytes_written, 00629 body, 00630 0, body_len); 00631 } 00632 else 00633 { 00634 bytes_written = 00635 _dbus_write_socket (socket_transport->fd, 00636 body, 00637 (socket_transport->message_bytes_written - header_len), 00638 body_len - 00639 (socket_transport->message_bytes_written - header_len)); 00640 } 00641 } 00642 } 00643 00644 if (bytes_written < 0) 00645 { 00646 /* EINTR already handled for us */ 00647 00648 /* If the other end closed the socket with close() or shutdown(), we 00649 * receive EPIPE here but we must not close the socket yet: there 00650 * might still be some data to read. See: 00651 * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html 00652 */ 00653 00654 if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ()) 00655 goto out; 00656 00657 /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg() 00658 * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd 00659 * mechanism (SCM_RIGHTS) is used recursively with a recursion level 00660 * of maximum 4. The kernel does not have an API to check whether 00661 * the passed fds can be forwarded and it can change asynchronously. 00662 * See: 00663 * https://bugs.freedesktop.org/show_bug.cgi?id=80163 00664 */ 00665 00666 else if (_dbus_get_is_errno_etoomanyrefs ()) 00667 { 00668 /* We only send fds in the first byte of the message. 00669 * ETOOMANYREFS cannot happen after. 00670 */ 00671 _dbus_assert (socket_transport->message_bytes_written == 0); 00672 00673 _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n", 00674 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 /* The message was not actually sent but it needs to be removed 00681 * from the outgoing queue 00682 */ 00683 _dbus_connection_message_sent_unlocked (transport->connection, 00684 message); 00685 } 00686 else 00687 { 00688 _dbus_verbose ("Error writing to remote app: %s\n", 00689 _dbus_strerror_from_errno ()); 00690 do_io_error (transport); 00691 goto out; 00692 } 00693 } 00694 else 00695 { 00696 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written, 00697 total_bytes_to_write); 00698 00699 total += bytes_written; 00700 socket_transport->message_bytes_written += bytes_written; 00701 00702 _dbus_assert (socket_transport->message_bytes_written <= 00703 total_bytes_to_write); 00704 00705 if (socket_transport->message_bytes_written == total_bytes_to_write) 00706 { 00707 socket_transport->message_bytes_written = 0; 00708 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); 00709 _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); 00710 00711 _dbus_connection_message_sent_unlocked (transport->connection, 00712 message); 00713 } 00714 } 00715 } 00716 00717 out: 00718 if (oom) 00719 return FALSE; 00720 else 00721 return TRUE; 00722 } 00723 00724 /* returns false on out-of-memory */ 00725 static dbus_bool_t 00726 do_reading (DBusTransport *transport) 00727 { 00728 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00729 DBusString *buffer; 00730 int bytes_read; 00731 int total; 00732 dbus_bool_t oom; 00733 00734 _dbus_verbose ("fd = %d\n",socket_transport->fd); 00735 00736 /* No messages without authentication! */ 00737 if (!_dbus_transport_try_to_authenticate (transport)) 00738 return TRUE; 00739 00740 oom = FALSE; 00741 00742 total = 0; 00743 00744 again: 00745 00746 /* See if we've exceeded max messages and need to disable reading */ 00747 check_read_watch (transport); 00748 00749 if (total > socket_transport->max_bytes_read_per_iteration) 00750 { 00751 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n", 00752 total, socket_transport->max_bytes_read_per_iteration); 00753 goto out; 00754 } 00755 00756 _dbus_assert (socket_transport->read_watch != NULL || 00757 transport->disconnected); 00758 00759 if (transport->disconnected) 00760 goto out; 00761 00762 if (!dbus_watch_get_enabled (socket_transport->read_watch)) 00763 return TRUE; 00764 00765 if (_dbus_auth_needs_decoding (transport->auth)) 00766 { 00767 /* Does fd passing even make sense with encoded data? */ 00768 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); 00769 00770 if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0) 00771 bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming); 00772 else 00773 bytes_read = _dbus_read_socket (socket_transport->fd, 00774 &socket_transport->encoded_incoming, 00775 socket_transport->max_bytes_read_per_iteration); 00776 00777 _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) == 00778 bytes_read); 00779 00780 if (bytes_read > 0) 00781 { 00782 _dbus_message_loader_get_buffer (transport->loader, 00783 &buffer); 00784 00785 if (!_dbus_auth_decode_data (transport->auth, 00786 &socket_transport->encoded_incoming, 00787 buffer)) 00788 { 00789 _dbus_verbose ("Out of memory decoding incoming data\n"); 00790 _dbus_message_loader_return_buffer (transport->loader, 00791 buffer); 00792 00793 oom = TRUE; 00794 goto out; 00795 } 00796 00797 _dbus_message_loader_return_buffer (transport->loader, 00798 buffer); 00799 00800 _dbus_string_set_length (&socket_transport->encoded_incoming, 0); 00801 _dbus_string_compact (&socket_transport->encoded_incoming, 2048); 00802 } 00803 } 00804 else 00805 { 00806 _dbus_message_loader_get_buffer (transport->loader, 00807 &buffer); 00808 00809 #ifdef HAVE_UNIX_FD_PASSING 00810 if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) 00811 { 00812 int *fds, n_fds; 00813 00814 if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds)) 00815 { 00816 _dbus_verbose ("Out of memory reading file descriptors\n"); 00817 _dbus_message_loader_return_buffer (transport->loader, buffer); 00818 oom = TRUE; 00819 goto out; 00820 } 00821 00822 bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd, 00823 buffer, 00824 socket_transport->max_bytes_read_per_iteration, 00825 fds, &n_fds); 00826 00827 if (bytes_read >= 0 && n_fds > 0) 00828 _dbus_verbose("Read %i unix fds\n", n_fds); 00829 00830 _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds); 00831 } 00832 else 00833 #endif 00834 { 00835 bytes_read = _dbus_read_socket (socket_transport->fd, 00836 buffer, socket_transport->max_bytes_read_per_iteration); 00837 } 00838 00839 _dbus_message_loader_return_buffer (transport->loader, 00840 buffer); 00841 } 00842 00843 if (bytes_read < 0) 00844 { 00845 /* EINTR already handled for us */ 00846 00847 if (_dbus_get_is_errno_enomem ()) 00848 { 00849 _dbus_verbose ("Out of memory in read()/do_reading()\n"); 00850 oom = TRUE; 00851 goto out; 00852 } 00853 else if (_dbus_get_is_errno_eagain_or_ewouldblock ()) 00854 goto out; 00855 else 00856 { 00857 _dbus_verbose ("Error reading from remote app: %s\n", 00858 _dbus_strerror_from_errno ()); 00859 do_io_error (transport); 00860 goto out; 00861 } 00862 } 00863 else if (bytes_read == 0) 00864 { 00865 _dbus_verbose ("Disconnected from remote app\n"); 00866 do_io_error (transport); 00867 goto out; 00868 } 00869 else 00870 { 00871 _dbus_verbose (" read %d bytes\n", bytes_read); 00872 00873 total += bytes_read; 00874 00875 if (!_dbus_transport_queue_messages (transport)) 00876 { 00877 oom = TRUE; 00878 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n"); 00879 goto out; 00880 } 00881 00882 /* Try reading more data until we get EAGAIN and return, or 00883 * exceed max bytes per iteration. If in blocking mode of 00884 * course we'll block instead of returning. 00885 */ 00886 goto again; 00887 } 00888 00889 out: 00890 if (oom) 00891 return FALSE; 00892 else 00893 return TRUE; 00894 } 00895 00896 static dbus_bool_t 00897 unix_error_with_read_to_come (DBusTransport *itransport, 00898 DBusWatch *watch, 00899 unsigned int flags) 00900 { 00901 DBusTransportSocket *transport = (DBusTransportSocket *) itransport; 00902 00903 if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR)) 00904 return FALSE; 00905 00906 /* If we have a read watch enabled ... 00907 we -might have data incoming ... => handle the HANGUP there */ 00908 if (watch != transport->read_watch && 00909 _dbus_watch_get_enabled (transport->read_watch)) 00910 return FALSE; 00911 00912 return TRUE; 00913 } 00914 00915 static dbus_bool_t 00916 socket_handle_watch (DBusTransport *transport, 00917 DBusWatch *watch, 00918 unsigned int flags) 00919 { 00920 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 00921 00922 _dbus_assert (watch == socket_transport->read_watch || 00923 watch == socket_transport->write_watch); 00924 _dbus_assert (watch != NULL); 00925 00926 /* If we hit an error here on a write watch, don't disconnect the transport yet because data can 00927 * still be in the buffer and do_reading may need several iteration to read 00928 * it all (because of its max_bytes_read_per_iteration limit). 00929 */ 00930 if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags)) 00931 { 00932 _dbus_verbose ("Hang up or error on watch\n"); 00933 _dbus_transport_disconnect (transport); 00934 return TRUE; 00935 } 00936 00937 if (watch == socket_transport->read_watch && 00938 (flags & DBUS_WATCH_READABLE)) 00939 { 00940 dbus_bool_t auth_finished; 00941 #if 1 00942 _dbus_verbose ("handling read watch %p flags = %x\n", 00943 watch, flags); 00944 #endif 00945 if (!do_authentication (transport, TRUE, FALSE, &auth_finished)) 00946 return FALSE; 00947 00948 /* We don't want to do a read immediately following 00949 * a successful authentication. This is so we 00950 * have a chance to propagate the authentication 00951 * state further up. Specifically, we need to 00952 * process any pending data from the auth object. 00953 */ 00954 if (!auth_finished) 00955 { 00956 if (!do_reading (transport)) 00957 { 00958 _dbus_verbose ("no memory to read\n"); 00959 return FALSE; 00960 } 00961 } 00962 else 00963 { 00964 _dbus_verbose ("Not reading anything since we just completed the authentication\n"); 00965 } 00966 } 00967 else if (watch == socket_transport->write_watch && 00968 (flags & DBUS_WATCH_WRITABLE)) 00969 { 00970 #if 1 00971 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n", 00972 _dbus_connection_has_messages_to_send_unlocked (transport->connection)); 00973 #endif 00974 if (!do_authentication (transport, FALSE, TRUE, NULL)) 00975 return FALSE; 00976 00977 if (!do_writing (transport)) 00978 { 00979 _dbus_verbose ("no memory to write\n"); 00980 return FALSE; 00981 } 00982 00983 /* See if we still need the write watch */ 00984 check_write_watch (transport); 00985 } 00986 #ifdef DBUS_ENABLE_VERBOSE_MODE 00987 else 00988 { 00989 if (watch == socket_transport->read_watch) 00990 _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n", 00991 flags); 00992 else if (watch == socket_transport->write_watch) 00993 _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n", 00994 flags); 00995 else 00996 _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n", 00997 watch, dbus_watch_get_socket (watch)); 00998 } 00999 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 01000 01001 return TRUE; 01002 } 01003 01004 static void 01005 socket_disconnect (DBusTransport *transport) 01006 { 01007 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01008 01009 _dbus_verbose ("\n"); 01010 01011 free_watches (transport); 01012 01013 _dbus_close_socket (socket_transport->fd, NULL); 01014 socket_transport->fd = -1; 01015 } 01016 01017 static dbus_bool_t 01018 socket_connection_set (DBusTransport *transport) 01019 { 01020 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01021 01022 _dbus_watch_set_handler (socket_transport->write_watch, 01023 _dbus_connection_handle_watch, 01024 transport->connection, NULL); 01025 01026 _dbus_watch_set_handler (socket_transport->read_watch, 01027 _dbus_connection_handle_watch, 01028 transport->connection, NULL); 01029 01030 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01031 socket_transport->write_watch)) 01032 return FALSE; 01033 01034 if (!_dbus_connection_add_watch_unlocked (transport->connection, 01035 socket_transport->read_watch)) 01036 { 01037 _dbus_connection_remove_watch_unlocked (transport->connection, 01038 socket_transport->write_watch); 01039 return FALSE; 01040 } 01041 01042 check_read_watch (transport); 01043 check_write_watch (transport); 01044 01045 return TRUE; 01046 } 01047 01055 static void 01056 socket_do_iteration (DBusTransport *transport, 01057 unsigned int flags, 01058 int timeout_milliseconds) 01059 { 01060 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01061 DBusPollFD poll_fd; 01062 int poll_res; 01063 int poll_timeout; 01064 01065 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n", 01066 flags & DBUS_ITERATION_DO_READING ? "read" : "", 01067 flags & DBUS_ITERATION_DO_WRITING ? "write" : "", 01068 timeout_milliseconds, 01069 socket_transport->read_watch, 01070 socket_transport->write_watch, 01071 socket_transport->fd); 01072 01073 /* the passed in DO_READING/DO_WRITING flags indicate whether to 01074 * read/write messages, but regardless of those we may need to block 01075 * for reading/writing to do auth. But if we do reading for auth, 01076 * we don't want to read any messages yet if not given DO_READING. 01077 */ 01078 01079 poll_fd.fd = socket_transport->fd; 01080 poll_fd.events = 0; 01081 01082 if (_dbus_transport_try_to_authenticate (transport)) 01083 { 01084 /* This is kind of a hack; if we have stuff to write, then try 01085 * to avoid the poll. This is probably about a 5% speedup on an 01086 * echo client/server. 01087 * 01088 * If both reading and writing were requested, we want to avoid this 01089 * since it could have funky effects: 01090 * - both ends spinning waiting for the other one to read 01091 * data so they can finish writing 01092 * - prioritizing all writing ahead of reading 01093 */ 01094 if ((flags & DBUS_ITERATION_DO_WRITING) && 01095 !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) && 01096 !transport->disconnected && 01097 _dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01098 { 01099 do_writing (transport); 01100 01101 if (transport->disconnected || 01102 !_dbus_connection_has_messages_to_send_unlocked (transport->connection)) 01103 goto out; 01104 } 01105 01106 /* If we get here, we decided to do the poll() after all */ 01107 _dbus_assert (socket_transport->read_watch); 01108 if (flags & DBUS_ITERATION_DO_READING) 01109 poll_fd.events |= _DBUS_POLLIN; 01110 01111 _dbus_assert (socket_transport->write_watch); 01112 if (flags & DBUS_ITERATION_DO_WRITING) 01113 poll_fd.events |= _DBUS_POLLOUT; 01114 } 01115 else 01116 { 01117 DBusAuthState auth_state; 01118 01119 auth_state = _dbus_auth_do_work (transport->auth); 01120 01121 if (transport->receive_credentials_pending || 01122 auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT) 01123 poll_fd.events |= _DBUS_POLLIN; 01124 01125 if (transport->send_credentials_pending || 01126 auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) 01127 poll_fd.events |= _DBUS_POLLOUT; 01128 } 01129 01130 if (poll_fd.events) 01131 { 01132 if (flags & DBUS_ITERATION_BLOCK) 01133 poll_timeout = timeout_milliseconds; 01134 else 01135 poll_timeout = 0; 01136 01137 /* For blocking selects we drop the connection lock here 01138 * to avoid blocking out connection access during a potentially 01139 * indefinite blocking call. The io path is still protected 01140 * by the io_path_cond condvar, so we won't reenter this. 01141 */ 01142 if (flags & DBUS_ITERATION_BLOCK) 01143 { 01144 _dbus_verbose ("unlock pre poll\n"); 01145 _dbus_connection_unlock (transport->connection); 01146 } 01147 01148 again: 01149 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout); 01150 01151 if (poll_res < 0 && _dbus_get_is_errno_eintr ()) 01152 goto again; 01153 01154 if (flags & DBUS_ITERATION_BLOCK) 01155 { 01156 _dbus_verbose ("lock post poll\n"); 01157 _dbus_connection_lock (transport->connection); 01158 } 01159 01160 if (poll_res >= 0) 01161 { 01162 if (poll_res == 0) 01163 poll_fd.revents = 0; /* some concern that posix does not guarantee this; 01164 * valgrind flags it as an error. though it probably 01165 * is guaranteed on linux at least. 01166 */ 01167 01168 if (poll_fd.revents & _DBUS_POLLERR) 01169 do_io_error (transport); 01170 else 01171 { 01172 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0; 01173 dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0; 01174 dbus_bool_t authentication_completed; 01175 01176 _dbus_verbose ("in iteration, need_read=%d need_write=%d\n", 01177 need_read, need_write); 01178 do_authentication (transport, need_read, need_write, 01179 &authentication_completed); 01180 01181 /* See comment in socket_handle_watch. */ 01182 if (authentication_completed) 01183 goto out; 01184 01185 if (need_read && (flags & DBUS_ITERATION_DO_READING)) 01186 do_reading (transport); 01187 if (need_write && (flags & DBUS_ITERATION_DO_WRITING)) 01188 do_writing (transport); 01189 } 01190 } 01191 else 01192 { 01193 _dbus_verbose ("Error from _dbus_poll(): %s\n", 01194 _dbus_strerror_from_errno ()); 01195 } 01196 } 01197 01198 01199 out: 01200 /* We need to install the write watch only if we did not 01201 * successfully write everything. Note we need to be careful that we 01202 * don't call check_write_watch *before* do_writing, since it's 01203 * inefficient to add the write watch, and we can avoid it most of 01204 * the time since we can write immediately. 01205 * 01206 * However, we MUST always call check_write_watch(); DBusConnection code 01207 * relies on the fact that running an iteration will notice that 01208 * messages are pending. 01209 */ 01210 check_write_watch (transport); 01211 01212 _dbus_verbose (" ... leaving do_iteration()\n"); 01213 } 01214 01215 static void 01216 socket_live_messages_changed (DBusTransport *transport) 01217 { 01218 /* See if we should look for incoming messages again */ 01219 check_read_watch (transport); 01220 } 01221 01222 01223 static dbus_bool_t 01224 socket_get_socket_fd (DBusTransport *transport, 01225 int *fd_p) 01226 { 01227 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; 01228 01229 *fd_p = socket_transport->fd; 01230 01231 return TRUE; 01232 } 01233 01234 static const DBusTransportVTable socket_vtable = { 01235 socket_finalize, 01236 socket_handle_watch, 01237 socket_disconnect, 01238 socket_connection_set, 01239 socket_do_iteration, 01240 socket_live_messages_changed, 01241 socket_get_socket_fd 01242 }; 01243 01255 DBusTransport* 01256 _dbus_transport_new_for_socket (int fd, 01257 const DBusString *server_guid, 01258 const DBusString *address) 01259 { 01260 DBusTransportSocket *socket_transport; 01261 01262 socket_transport = dbus_new0 (DBusTransportSocket, 1); 01263 if (socket_transport == NULL) 01264 return NULL; 01265 01266 if (!_dbus_string_init (&socket_transport->encoded_outgoing)) 01267 goto failed_0; 01268 01269 if (!_dbus_string_init (&socket_transport->encoded_incoming)) 01270 goto failed_1; 01271 01272 socket_transport->write_watch = _dbus_watch_new (fd, 01273 DBUS_WATCH_WRITABLE, 01274 FALSE, 01275 NULL, NULL, NULL); 01276 if (socket_transport->write_watch == NULL) 01277 goto failed_2; 01278 01279 socket_transport->read_watch = _dbus_watch_new (fd, 01280 DBUS_WATCH_READABLE, 01281 FALSE, 01282 NULL, NULL, NULL); 01283 if (socket_transport->read_watch == NULL) 01284 goto failed_3; 01285 01286 if (!_dbus_transport_init_base (&socket_transport->base, 01287 &socket_vtable, 01288 server_guid, address)) 01289 goto failed_4; 01290 01291 #ifdef HAVE_UNIX_FD_PASSING 01292 _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); 01293 #endif 01294 01295 socket_transport->fd = fd; 01296 socket_transport->message_bytes_written = 0; 01297 01298 /* These values should probably be tunable or something. */ 01299 socket_transport->max_bytes_read_per_iteration = 2048; 01300 socket_transport->max_bytes_written_per_iteration = 2048; 01301 01302 return (DBusTransport*) socket_transport; 01303 01304 failed_4: 01305 _dbus_watch_invalidate (socket_transport->read_watch); 01306 _dbus_watch_unref (socket_transport->read_watch); 01307 failed_3: 01308 _dbus_watch_invalidate (socket_transport->write_watch); 01309 _dbus_watch_unref (socket_transport->write_watch); 01310 failed_2: 01311 _dbus_string_free (&socket_transport->encoded_incoming); 01312 failed_1: 01313 _dbus_string_free (&socket_transport->encoded_outgoing); 01314 failed_0: 01315 dbus_free (socket_transport); 01316 return NULL; 01317 } 01318 01330 DBusTransport* 01331 _dbus_transport_new_for_tcp_socket (const char *host, 01332 const char *port, 01333 const char *family, 01334 const char *noncefile, 01335 DBusError *error) 01336 { 01337 int fd; 01338 DBusTransport *transport; 01339 DBusString address; 01340 01341 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01342 01343 if (!_dbus_string_init (&address)) 01344 { 01345 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01346 return NULL; 01347 } 01348 01349 if (host == NULL) 01350 host = "localhost"; 01351 01352 if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:")) 01353 goto error; 01354 01355 if (!_dbus_string_append (&address, "host=") || 01356 !_dbus_string_append (&address, host)) 01357 goto error; 01358 01359 if (!_dbus_string_append (&address, ",port=") || 01360 !_dbus_string_append (&address, port)) 01361 goto error; 01362 01363 if (family != NULL && 01364 (!_dbus_string_append (&address, ",family=") || 01365 !_dbus_string_append (&address, family))) 01366 goto error; 01367 01368 if (noncefile != NULL && 01369 (!_dbus_string_append (&address, ",noncefile=") || 01370 !_dbus_string_append (&address, noncefile))) 01371 goto error; 01372 01373 fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error); 01374 if (fd < 0) 01375 { 01376 _DBUS_ASSERT_ERROR_IS_SET (error); 01377 _dbus_string_free (&address); 01378 return NULL; 01379 } 01380 01381 _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", 01382 host, port); 01383 01384 transport = _dbus_transport_new_for_socket (fd, NULL, &address); 01385 _dbus_string_free (&address); 01386 if (transport == NULL) 01387 { 01388 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01389 _dbus_close_socket (fd, NULL); 01390 fd = -1; 01391 } 01392 01393 return transport; 01394 01395 error: 01396 _dbus_string_free (&address); 01397 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01398 return NULL; 01399 } 01400 01409 DBusTransportOpenResult 01410 _dbus_transport_open_socket(DBusAddressEntry *entry, 01411 DBusTransport **transport_p, 01412 DBusError *error) 01413 { 01414 const char *method; 01415 dbus_bool_t isTcp; 01416 dbus_bool_t isNonceTcp; 01417 01418 method = dbus_address_entry_get_method (entry); 01419 _dbus_assert (method != NULL); 01420 01421 isTcp = strcmp (method, "tcp") == 0; 01422 isNonceTcp = strcmp (method, "nonce-tcp") == 0; 01423 01424 if (isTcp || isNonceTcp) 01425 { 01426 const char *host = dbus_address_entry_get_value (entry, "host"); 01427 const char *port = dbus_address_entry_get_value (entry, "port"); 01428 const char *family = dbus_address_entry_get_value (entry, "family"); 01429 const char *noncefile = dbus_address_entry_get_value (entry, "noncefile"); 01430 01431 if ((isNonceTcp == TRUE) != (noncefile != NULL)) { 01432 _dbus_set_bad_address (error, method, "noncefile", NULL); 01433 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01434 } 01435 01436 if (port == NULL) 01437 { 01438 _dbus_set_bad_address (error, method, "port", NULL); 01439 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; 01440 } 01441 01442 *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error); 01443 if (*transport_p == NULL) 01444 { 01445 _DBUS_ASSERT_ERROR_IS_SET (error); 01446 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT; 01447 } 01448 else 01449 { 01450 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01451 return DBUS_TRANSPORT_OPEN_OK; 01452 } 01453 } 01454 else 01455 { 01456 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01457 return DBUS_TRANSPORT_OPEN_NOT_HANDLED; 01458 } 01459 } 01460
1.7.6.1