X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-transport-socket.c;h=bd19f9b558d2b29a83b61349b8aab8517a63b2fd;hb=a0be921da79a78e2c0484d99aac9002a1de1d0cf;hp=f6d0e9c2665505f12e4c3ab91862a7248ea82abd;hpb=8c6b0ab3f7e437362112eeaf83a566475b85d27c;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index f6d0e9c..bd19f9b 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -17,18 +17,19 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-internals.h" #include "dbus-connection-internal.h" +#include "dbus-nonce.h" #include "dbus-transport-socket.h" #include "dbus-transport-protected.h" #include "dbus-watch.h" #include "dbus-credentials.h" - /** * @defgroup DBusTransportSocket DBusTransport implementations for sockets * @ingroup DBusInternals @@ -72,7 +73,7 @@ free_watches (DBusTransport *transport) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; - _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("start\n"); if (socket_transport->read_watch) { @@ -94,7 +95,7 @@ free_watches (DBusTransport *transport) socket_transport->write_watch = NULL; } - _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("end\n"); } static void @@ -102,7 +103,7 @@ socket_finalize (DBusTransport *transport) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; - _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("\n"); free_watches (transport); @@ -134,7 +135,7 @@ check_write_watch (DBusTransport *transport) _dbus_transport_ref (transport); - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); else { @@ -176,8 +177,7 @@ check_read_watch (DBusTransport *transport) DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; dbus_bool_t need_read_watch; - _dbus_verbose ("%s: fd = %d\n", - _DBUS_FUNCTION_NAME, socket_transport->fd); + _dbus_verbose ("fd = %d\n",socket_transport->fd); if (transport->connection == NULL) return; @@ -190,9 +190,10 @@ check_read_watch (DBusTransport *transport) _dbus_transport_ref (transport); - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) need_read_watch = - _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size; + (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) && + (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds); else { if (transport->receive_credentials_pending) @@ -338,12 +339,11 @@ exchange_credentials (DBusTransport *transport, dbus_bool_t do_writing) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; - DBusError error; + DBusError error = DBUS_ERROR_INIT; _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n", do_reading, do_writing); - dbus_error_init (&error); if (do_writing && transport->send_credentials_pending) { if (_dbus_send_credentials_socket (socket_transport->fd, @@ -404,7 +404,7 @@ do_authentication (DBusTransport *transport, oom = FALSE; - orig_auth_state = _dbus_transport_get_is_authenticated (transport); + orig_auth_state = _dbus_transport_try_to_authenticate (transport); /* This is essential to avoid the check_write_watch() at the end, * we don't want to add a write watch in do_iteration before @@ -419,7 +419,7 @@ do_authentication (DBusTransport *transport, _dbus_transport_ref (transport); - while (!_dbus_transport_get_is_authenticated (transport) && + while (!_dbus_transport_try_to_authenticate (transport) && _dbus_transport_get_is_connected (transport)) { if (!exchange_credentials (transport, do_reading, do_writing)) @@ -477,7 +477,7 @@ do_authentication (DBusTransport *transport, out: if (auth_completed) - *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport)); + *auth_completed = (orig_auth_state != _dbus_transport_try_to_authenticate (transport)); check_read_watch (transport); check_write_watch (transport); @@ -498,7 +498,7 @@ do_writing (DBusTransport *transport) dbus_bool_t oom; /* No messages without authentication! */ - if (!_dbus_transport_get_is_authenticated (transport)) + if (!_dbus_transport_try_to_authenticate (transport)) { _dbus_verbose ("Not authenticated, not writing anything\n"); return TRUE; @@ -538,7 +538,7 @@ do_writing (DBusTransport *transport) message = _dbus_connection_get_message_to_send (transport->connection); _dbus_assert (message != NULL); - _dbus_message_lock (message); + dbus_message_lock (message); #if 0 _dbus_verbose ("writing message %p\n", message); @@ -552,6 +552,9 @@ do_writing (DBusTransport *transport) if (_dbus_auth_needs_encoding (transport->auth)) { + /* Does fd passing even make sense with encoded data? */ + _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); + if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0) { if (!_dbus_auth_encode_data (transport->auth, @@ -589,27 +592,53 @@ do_writing (DBusTransport *transport) #if 0 _dbus_verbose ("message is %d bytes\n", - total_bytes_to_write); + total_bytes_to_write); #endif - - if (socket_transport->message_bytes_written < header_len) + +#ifdef HAVE_UNIX_FD_PASSING + if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) { + /* Send the fds along with the first byte of the message */ + const int *unix_fds; + unsigned n; + + _dbus_message_get_unix_fds(message, &unix_fds, &n); + bytes_written = - _dbus_write_socket_two (socket_transport->fd, - header, - socket_transport->message_bytes_written, - header_len - socket_transport->message_bytes_written, - body, - 0, body_len); + _dbus_write_socket_with_unix_fds_two (socket_transport->fd, + header, + socket_transport->message_bytes_written, + header_len - socket_transport->message_bytes_written, + body, + 0, body_len, + unix_fds, + n); + + if (bytes_written > 0 && n > 0) + _dbus_verbose("Wrote %i unix fds\n", n); } else +#endif { - bytes_written = - _dbus_write_socket (socket_transport->fd, - body, - (socket_transport->message_bytes_written - header_len), - body_len - - (socket_transport->message_bytes_written - header_len)); + if (socket_transport->message_bytes_written < header_len) + { + bytes_written = + _dbus_write_socket_two (socket_transport->fd, + header, + socket_transport->message_bytes_written, + header_len - socket_transport->message_bytes_written, + body, + 0, body_len); + } + else + { + bytes_written = + _dbus_write_socket (socket_transport->fd, + body, + (socket_transport->message_bytes_written - header_len), + body_len - + (socket_transport->message_bytes_written - header_len)); + } } } @@ -617,7 +646,11 @@ do_writing (DBusTransport *transport) { /* EINTR already handled for us */ - if (_dbus_get_is_errno_eagain_or_ewouldblock ()) + /* For some discussion of why we also ignore EPIPE here, see + * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html + */ + + if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ()) goto out; else { @@ -644,8 +677,8 @@ do_writing (DBusTransport *transport) _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); - _dbus_connection_message_sent (transport->connection, - message); + _dbus_connection_message_sent_unlocked (transport->connection, + message); } } } @@ -667,11 +700,10 @@ do_reading (DBusTransport *transport) int total; dbus_bool_t oom; - _dbus_verbose ("%s: fd = %d\n", _DBUS_FUNCTION_NAME, - socket_transport->fd); + _dbus_verbose ("fd = %d\n",socket_transport->fd); /* No messages without authentication! */ - if (!_dbus_transport_get_is_authenticated (transport)) + if (!_dbus_transport_try_to_authenticate (transport)) return TRUE; oom = FALSE; @@ -701,6 +733,9 @@ do_reading (DBusTransport *transport) if (_dbus_auth_needs_decoding (transport->auth)) { + /* Does fd passing even make sense with encoded data? */ + _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)); + if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0) bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming); else @@ -725,6 +760,10 @@ do_reading (DBusTransport *transport) buffer)) { _dbus_verbose ("Out of memory decoding incoming data\n"); + _dbus_message_loader_return_buffer (transport->loader, + buffer, + _dbus_string_get_length (buffer) - orig_len); + oom = TRUE; goto out; } @@ -741,15 +780,42 @@ do_reading (DBusTransport *transport) { _dbus_message_loader_get_buffer (transport->loader, &buffer); - - bytes_read = _dbus_read_socket (socket_transport->fd, - buffer, socket_transport->max_bytes_read_per_iteration); - + +#ifdef HAVE_UNIX_FD_PASSING + if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport)) + { + int *fds, n_fds; + + if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds)) + { + _dbus_verbose ("Out of memory reading file descriptors\n"); + _dbus_message_loader_return_buffer (transport->loader, buffer, 0); + oom = TRUE; + goto out; + } + + bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd, + buffer, + socket_transport->max_bytes_read_per_iteration, + fds, &n_fds); + + if (bytes_read >= 0 && n_fds > 0) + _dbus_verbose("Read %i unix fds\n", n_fds); + + _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds); + } + else +#endif + { + bytes_read = _dbus_read_socket (socket_transport->fd, + buffer, socket_transport->max_bytes_read_per_iteration); + } + _dbus_message_loader_return_buffer (transport->loader, buffer, bytes_read < 0 ? 0 : bytes_read); } - + if (bytes_read < 0) { /* EINTR already handled for us */ @@ -804,6 +870,25 @@ do_reading (DBusTransport *transport) } static dbus_bool_t +unix_error_with_read_to_come (DBusTransport *itransport, + DBusWatch *watch, + unsigned int flags) +{ + DBusTransportSocket *transport = (DBusTransportSocket *) itransport; + + if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR)) + return FALSE; + + /* If we have a read watch enabled ... + we -might have data incoming ... => handle the HANGUP there */ + if (watch != transport->read_watch && + _dbus_watch_get_enabled (transport->read_watch)) + return FALSE; + + return TRUE; +} + +static dbus_bool_t socket_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int flags) @@ -814,14 +899,11 @@ socket_handle_watch (DBusTransport *transport, watch == socket_transport->write_watch); _dbus_assert (watch != NULL); - /* Disconnect in case of an error. In case of hangup do not - * disconnect the transport because data can still be in the buffer - * and do_reading may need several iteration to read it all (because - * of its max_bytes_read_per_iteration limit). The condition where - * flags == HANGUP (without READABLE) probably never happen in fact. + /* If we hit an error here on a write watch, don't disconnect the transport yet because data can + * still be in the buffer and do_reading may need several iteration to read + * it all (because of its max_bytes_read_per_iteration limit). */ - if ((flags & DBUS_WATCH_ERROR) || - ((flags & DBUS_WATCH_HANGUP) && !(flags & DBUS_WATCH_READABLE))) + if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags)) { _dbus_verbose ("Hang up or error on watch\n"); _dbus_transport_disconnect (transport); @@ -900,7 +982,7 @@ socket_disconnect (DBusTransport *transport) { DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport; - _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("\n"); free_watches (transport); @@ -973,7 +1055,7 @@ socket_do_iteration (DBusTransport *transport, poll_fd.fd = socket_transport->fd; poll_fd.events = 0; - if (_dbus_transport_get_is_authenticated (transport)) + if (_dbus_transport_try_to_authenticate (transport)) { /* This is kind of a hack; if we have stuff to write, then try * to avoid the poll. This is probably about a 5% speedup on an @@ -1035,7 +1117,7 @@ socket_do_iteration (DBusTransport *transport, */ if (flags & DBUS_ITERATION_BLOCK) { - _dbus_verbose ("unlock %s pre poll\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("unlock pre poll\n"); _dbus_connection_unlock (transport->connection); } @@ -1047,7 +1129,7 @@ socket_do_iteration (DBusTransport *transport, if (flags & DBUS_ITERATION_BLOCK) { - _dbus_verbose ("lock %s post poll\n", _DBUS_FUNCTION_NAME); + _dbus_verbose ("lock post poll\n"); _dbus_connection_lock (transport->connection); } @@ -1181,7 +1263,11 @@ _dbus_transport_new_for_socket (int fd, &socket_vtable, server_guid, address)) goto failed_4; - + +#ifdef HAVE_UNIX_FD_PASSING + _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); +#endif + socket_transport->fd = fd; socket_transport->message_bytes_written = 0; @@ -1192,8 +1278,10 @@ _dbus_transport_new_for_socket (int fd, return (DBusTransport*) socket_transport; failed_4: + _dbus_watch_invalidate (socket_transport->read_watch); _dbus_watch_unref (socket_transport->read_watch); failed_3: + _dbus_watch_invalidate (socket_transport->write_watch); _dbus_watch_unref (socket_transport->write_watch); failed_2: _dbus_string_free (&socket_transport->encoded_incoming); @@ -1211,6 +1299,7 @@ _dbus_transport_new_for_socket (int fd, * @param host the host to connect to * @param port the port to connect to * @param family the address family to connect to + * @param noncefile path to nonce file * @param error location to store reason for failure. * @returns a new transport, or #NULL on failure. */ @@ -1218,6 +1307,7 @@ DBusTransport* _dbus_transport_new_for_tcp_socket (const char *host, const char *port, const char *family, + const char *noncefile, DBusError *error) { int fd; @@ -1235,7 +1325,7 @@ _dbus_transport_new_for_tcp_socket (const char *host, if (host == NULL) host = "localhost"; - if (!_dbus_string_append (&address, "tcp:")) + if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:")) goto error; if (!_dbus_string_append (&address, "host=") || @@ -1247,11 +1337,16 @@ _dbus_transport_new_for_tcp_socket (const char *host, goto error; if (family != NULL && - (!_dbus_string_append (&address, "family=") || + (!_dbus_string_append (&address, ",family=") || !_dbus_string_append (&address, family))) goto error; - fd = _dbus_connect_tcp_socket (host, port, family, error); + if (noncefile != NULL && + (!_dbus_string_append (&address, ",noncefile=") || + !_dbus_string_append (&address, noncefile))) + goto error; + + fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error); if (fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); @@ -1259,22 +1354,18 @@ _dbus_transport_new_for_tcp_socket (const char *host, return NULL; } - _dbus_fd_set_close_on_exec (fd); - _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", host, port); transport = _dbus_transport_new_for_socket (fd, NULL, &address); + _dbus_string_free (&address); if (transport == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_close_socket (fd, NULL); - _dbus_string_free (&address); fd = -1; } - _dbus_string_free (&address); - return transport; error: @@ -1297,23 +1388,34 @@ _dbus_transport_open_socket(DBusAddressEntry *entry, DBusError *error) { const char *method; + dbus_bool_t isTcp; + dbus_bool_t isNonceTcp; method = dbus_address_entry_get_method (entry); _dbus_assert (method != NULL); - if (strcmp (method, "tcp") == 0) + isTcp = strcmp (method, "tcp") == 0; + isNonceTcp = strcmp (method, "nonce-tcp") == 0; + + if (isTcp || isNonceTcp) { const char *host = dbus_address_entry_get_value (entry, "host"); const char *port = dbus_address_entry_get_value (entry, "port"); const char *family = dbus_address_entry_get_value (entry, "family"); + const char *noncefile = dbus_address_entry_get_value (entry, "noncefile"); + + if ((isNonceTcp == TRUE) != (noncefile != NULL)) { + _dbus_set_bad_address (error, method, "noncefile", NULL); + return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; + } if (port == NULL) { - _dbus_set_bad_address (error, "tcp", "port", NULL); + _dbus_set_bad_address (error, method, "port", NULL); return DBUS_TRANSPORT_OPEN_BAD_ADDRESS; } - *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, error); + *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error); if (*transport_p == NULL) { _DBUS_ASSERT_ERROR_IS_SET (error);