1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport-socket.c Socket subclasses of DBusTransport
4 * Copyright (C) 2002, 2003, 2004, 2006 Red Hat Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "dbus-internals.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-nonce.h"
28 #include "dbus-transport-socket.h"
29 #include "dbus-transport-protected.h"
30 #include "dbus-watch.h"
31 #include "dbus-credentials.h"
32 #include <stdio.h> //todo to remove
36 * @defgroup DBusTransportSocket DBusTransport implementations for sockets
37 * @ingroup DBusInternals
38 * @brief Implementation details of DBusTransport on sockets
44 * Opaque object representing a socket file descriptor transport.
46 typedef struct DBusTransportSocket DBusTransportSocket;
49 * Implementation details of DBusTransportSocket. All members are private.
51 struct DBusTransportSocket
53 DBusTransport base; /**< Parent instance */
54 int fd; /**< File descriptor. */
55 DBusWatch *read_watch; /**< Watch for readability. */
56 DBusWatch *write_watch; /**< Watch for writability. */
58 int max_bytes_read_per_iteration; /**< To avoid blocking too long. */
59 int max_bytes_written_per_iteration; /**< To avoid blocking too long. */
61 int message_bytes_written; /**< Number of bytes of current
62 * outgoing message that have
65 DBusString encoded_outgoing; /**< Encoded version of current
68 DBusString encoded_incoming; /**< Encoded version of current
74 free_watches (DBusTransport *transport)
76 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
78 _dbus_verbose ("start\n");
80 if (socket_transport->read_watch)
82 if (transport->connection)
83 _dbus_connection_remove_watch_unlocked (transport->connection,
84 socket_transport->read_watch);
85 _dbus_watch_invalidate (socket_transport->read_watch);
86 _dbus_watch_unref (socket_transport->read_watch);
87 socket_transport->read_watch = NULL;
90 if (socket_transport->write_watch)
92 if (transport->connection)
93 _dbus_connection_remove_watch_unlocked (transport->connection,
94 socket_transport->write_watch);
95 _dbus_watch_invalidate (socket_transport->write_watch);
96 _dbus_watch_unref (socket_transport->write_watch);
97 socket_transport->write_watch = NULL;
100 _dbus_verbose ("end\n");
104 socket_finalize (DBusTransport *transport)
106 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
108 _dbus_verbose ("\n");
110 free_watches (transport);
112 _dbus_string_free (&socket_transport->encoded_outgoing);
113 _dbus_string_free (&socket_transport->encoded_incoming);
115 _dbus_transport_finalize_base (transport);
117 _dbus_assert (socket_transport->read_watch == NULL);
118 _dbus_assert (socket_transport->write_watch == NULL);
120 dbus_free (transport);
124 check_write_watch (DBusTransport *transport)
126 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
129 if (transport->connection == NULL)
132 if (transport->disconnected)
134 _dbus_assert (socket_transport->write_watch == NULL);
138 _dbus_transport_ref (transport);
140 if (_dbus_transport_get_is_authenticated (transport))
141 needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
144 if (transport->send_credentials_pending)
148 DBusAuthState auth_state;
150 auth_state = _dbus_auth_do_work (transport->auth);
152 /* If we need memory we install the write watch just in case,
153 * if there's no need for it, it will get de-installed
154 * next time we try reading.
156 if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
157 auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
164 _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
165 needed, transport->connection, socket_transport->write_watch,
166 socket_transport->fd,
167 _dbus_connection_has_messages_to_send_unlocked (transport->connection));
169 _dbus_connection_toggle_watch_unlocked (transport->connection,
170 socket_transport->write_watch,
173 _dbus_transport_unref (transport);
177 check_read_watch (DBusTransport *transport)
179 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
180 dbus_bool_t need_read_watch;
182 _dbus_verbose ("fd = %d\n",socket_transport->fd);
184 if (transport->connection == NULL)
187 if (transport->disconnected)
189 _dbus_assert (socket_transport->read_watch == NULL);
193 _dbus_transport_ref (transport);
195 if (_dbus_transport_get_is_authenticated (transport))
197 (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
198 (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
201 if (transport->receive_credentials_pending)
202 need_read_watch = TRUE;
205 /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
206 * is to avoid spinning on the file descriptor when we're waiting
207 * to write or for some other part of the auth process
209 DBusAuthState auth_state;
211 auth_state = _dbus_auth_do_work (transport->auth);
213 /* If we need memory we install the read watch just in case,
214 * if there's no need for it, it will get de-installed
215 * next time we try reading. If we're authenticated we
216 * install it since we normally have it installed while
219 if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
220 auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
221 auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
222 need_read_watch = TRUE;
224 need_read_watch = FALSE;
228 _dbus_verbose (" setting read watch enabled = %d\n", need_read_watch);
229 _dbus_connection_toggle_watch_unlocked (transport->connection,
230 socket_transport->read_watch,
233 _dbus_transport_unref (transport);
237 do_io_error (DBusTransport *transport)
239 _dbus_transport_ref (transport);
240 _dbus_transport_disconnect (transport);
241 _dbus_transport_unref (transport);
244 /* return value is whether we successfully read any new data. */
246 read_data_into_auth (DBusTransport *transport,
249 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
255 _dbus_auth_get_buffer (transport->auth, &buffer);
257 bytes_read = _dbus_read_socket (socket_transport->fd,
258 buffer, socket_transport->max_bytes_read_per_iteration);
260 _dbus_auth_return_buffer (transport->auth, buffer,
261 bytes_read > 0 ? bytes_read : 0);
265 _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
269 else if (bytes_read < 0)
271 /* EINTR already handled for us */
273 if (_dbus_get_is_errno_enomem ())
277 else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
278 ; /* do nothing, just return FALSE below */
281 _dbus_verbose ("Error reading from remote app: %s\n",
282 _dbus_strerror_from_errno ());
283 do_io_error (transport);
290 _dbus_assert (bytes_read == 0);
292 _dbus_verbose ("Disconnected from remote app\n");
293 do_io_error (transport);
299 /* Return value is whether we successfully wrote any bytes */
301 write_data_from_auth (DBusTransport *transport)
303 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
305 const DBusString *buffer;
307 if (!_dbus_auth_get_bytes_to_send (transport->auth,
311 bytes_written = _dbus_write_socket (socket_transport->fd,
313 0, _dbus_string_get_length (buffer));
315 if (bytes_written > 0)
317 _dbus_auth_bytes_sent (transport->auth, bytes_written);
320 else if (bytes_written < 0)
322 /* EINTR already handled for us */
324 if (_dbus_get_is_errno_eagain_or_ewouldblock ())
328 _dbus_verbose ("Error writing to remote app: %s\n",
329 _dbus_strerror_from_errno ());
330 do_io_error (transport);
339 exchange_credentials (DBusTransport *transport,
340 dbus_bool_t do_reading,
341 dbus_bool_t do_writing)
343 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
344 DBusError error = DBUS_ERROR_INIT;
346 _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
347 do_reading, do_writing);
349 if (do_writing && transport->send_credentials_pending)
351 if (_dbus_send_credentials_socket (socket_transport->fd,
354 transport->send_credentials_pending = FALSE;
358 _dbus_verbose ("Failed to write credentials: %s\n", error.message);
359 dbus_error_free (&error);
360 do_io_error (transport);
364 if (do_reading && transport->receive_credentials_pending)
366 /* FIXME this can fail due to IO error _or_ OOM, broken
367 * (somewhat tricky to fix since the OOM error can be set after
368 * we already read the credentials byte, so basically we need to
369 * separate reading the byte and storing it in the
370 * transport->credentials). Does not really matter for now
371 * because storing in credentials never actually fails on unix.
373 if (_dbus_read_credentials_socket (socket_transport->fd,
374 transport->credentials,
377 transport->receive_credentials_pending = FALSE;
381 _dbus_verbose ("Failed to read credentials %s\n", error.message);
382 dbus_error_free (&error);
383 do_io_error (transport);
387 if (!(transport->send_credentials_pending ||
388 transport->receive_credentials_pending))
390 if (!_dbus_auth_set_credentials (transport->auth,
391 transport->credentials))
399 do_authentication (DBusTransport *transport,
400 dbus_bool_t do_reading,
401 dbus_bool_t do_writing,
402 dbus_bool_t *auth_completed)
405 dbus_bool_t orig_auth_state;
409 orig_auth_state = _dbus_transport_get_is_authenticated (transport);
411 /* This is essential to avoid the check_write_watch() at the end,
412 * we don't want to add a write watch in do_iteration before
413 * we try writing and get EAGAIN
418 *auth_completed = FALSE;
422 _dbus_transport_ref (transport);
424 while (!_dbus_transport_get_is_authenticated (transport) &&
425 _dbus_transport_get_is_connected (transport))
427 if (!exchange_credentials (transport, do_reading, do_writing))
434 if (transport->send_credentials_pending ||
435 transport->receive_credentials_pending)
437 _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
438 transport->send_credentials_pending,
439 transport->receive_credentials_pending);
443 #define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
444 switch (_dbus_auth_do_work (transport->auth))
446 case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
447 _dbus_verbose (" %s auth state: waiting for input\n",
448 TRANSPORT_SIDE (transport));
449 if (!do_reading || !read_data_into_auth (transport, &oom))
453 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
454 _dbus_verbose (" %s auth state: waiting for memory\n",
455 TRANSPORT_SIDE (transport));
460 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
461 _dbus_verbose (" %s auth state: bytes to send\n",
462 TRANSPORT_SIDE (transport));
463 if (!do_writing || !write_data_from_auth (transport))
467 case DBUS_AUTH_STATE_NEED_DISCONNECT:
468 _dbus_verbose (" %s auth state: need to disconnect\n",
469 TRANSPORT_SIDE (transport));
470 do_io_error (transport);
473 case DBUS_AUTH_STATE_AUTHENTICATED:
474 _dbus_verbose (" %s auth state: authenticated\n",
475 TRANSPORT_SIDE (transport));
482 *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
484 check_read_watch (transport);
485 check_write_watch (transport);
486 _dbus_transport_unref (transport);
494 /* returns false on oom */
496 do_writing (DBusTransport *transport)
499 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
502 /* No messages without authentication! */
503 if (!_dbus_transport_get_is_authenticated (transport))
505 _dbus_verbose ("Not authenticated, not writing anything\n");
509 if (transport->disconnected)
511 _dbus_verbose ("Not connected, not writing anything\n");
516 _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
517 _dbus_connection_has_messages_to_send_unlocked (transport->connection),
518 socket_transport->fd);
524 while (!transport->disconnected &&
525 _dbus_connection_has_messages_to_send_unlocked (transport->connection))
528 DBusMessage *message;
529 const DBusString *header;
530 const DBusString *body;
531 int header_len, body_len;
532 int total_bytes_to_write;
536 if (total > socket_transport->max_bytes_written_per_iteration)
538 _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
539 total, socket_transport->max_bytes_written_per_iteration);
543 message = _dbus_connection_get_message_to_send (transport->connection);
544 _dbus_assert (message != NULL);
545 dbus_message_lock (message);
548 _dbus_verbose ("writing message %p\n", message);
551 _dbus_message_get_network_data (message,
554 header_len = _dbus_string_get_length (header);
555 body_len = _dbus_string_get_length (body);
557 /* fprintf (stderr, "\nheader:\n"); //todo for test - to remove together wit int i declaration above
558 for(i=0; i < header_len; i++)
560 fprintf (stderr, "%02x", _dbus_string_get_byte(header,i));
562 fprintf (stderr,"\n");
563 for(i=0; i < header_len; i++)
565 fprintf (stderr, "%c", _dbus_string_get_byte(header,i));
567 fprintf (stderr, "\nret size: %u, i: %u\n", header_len, i);
570 fprintf (stderr, "\nbody:\n");
571 for(i=0; i < body_len; i++)
573 fprintf (stderr, "%02x", _dbus_string_get_byte(body,i));
575 fprintf (stderr, "\nret size: %u, i: %u\n", body_len, i);
576 fprintf (stderr,"\n");
577 for(i=0; i < body_len; i++)
579 fprintf (stderr, "%c", _dbus_string_get_byte(body,i));
581 fprintf (stderr, "\nret size: %u, i: %u\n", body_len, i);*/
583 if (_dbus_auth_needs_encoding (transport->auth))
585 /* Does fd passing even make sense with encoded data? */
586 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
588 if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
590 if (!_dbus_auth_encode_data (transport->auth,
591 header, &socket_transport->encoded_outgoing))
597 if (!_dbus_auth_encode_data (transport->auth,
598 body, &socket_transport->encoded_outgoing))
600 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
606 total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
609 _dbus_verbose ("encoded message is %d bytes\n",
610 total_bytes_to_write);
614 _dbus_write_socket (socket_transport->fd,
615 &socket_transport->encoded_outgoing,
616 socket_transport->message_bytes_written,
617 total_bytes_to_write - socket_transport->message_bytes_written);
621 total_bytes_to_write = header_len + body_len;
624 _dbus_verbose ("message is %d bytes\n",
625 total_bytes_to_write);
628 #ifdef HAVE_UNIX_FD_PASSING
629 if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
631 /* Send the fds along with the first byte of the message */
635 _dbus_message_get_unix_fds(message, &unix_fds, &n);
638 _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
640 socket_transport->message_bytes_written,
641 header_len - socket_transport->message_bytes_written,
647 if (bytes_written > 0 && n > 0)
648 _dbus_verbose("Wrote %i unix fds\n", n);
653 if (socket_transport->message_bytes_written < header_len)
656 _dbus_write_socket_two (socket_transport->fd,
658 socket_transport->message_bytes_written,
659 header_len - socket_transport->message_bytes_written,
666 _dbus_write_socket (socket_transport->fd,
668 (socket_transport->message_bytes_written - header_len),
670 (socket_transport->message_bytes_written - header_len));
675 if (bytes_written < 0)
677 /* EINTR already handled for us */
679 /* For some discussion of why we also ignore EPIPE here, see
680 * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
683 if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
687 _dbus_verbose ("Error writing to remote app: %s\n",
688 _dbus_strerror_from_errno ());
689 do_io_error (transport);
695 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
696 total_bytes_to_write);
698 total += bytes_written;
699 socket_transport->message_bytes_written += bytes_written;
701 _dbus_assert (socket_transport->message_bytes_written <=
702 total_bytes_to_write);
704 if (socket_transport->message_bytes_written == total_bytes_to_write)
706 socket_transport->message_bytes_written = 0;
707 _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
708 _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
710 _dbus_connection_message_sent_unlocked (transport->connection,
723 /* returns false on out-of-memory */
725 do_reading (DBusTransport *transport)
727 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
733 _dbus_verbose ("fd = %d\n",socket_transport->fd);
735 /* No messages without authentication! */
736 if (!_dbus_transport_get_is_authenticated (transport))
745 /* See if we've exceeded max messages and need to disable reading */
746 check_read_watch (transport);
748 if (total > socket_transport->max_bytes_read_per_iteration)
750 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
751 total, socket_transport->max_bytes_read_per_iteration);
755 _dbus_assert (socket_transport->read_watch != NULL ||
756 transport->disconnected);
758 if (transport->disconnected)
761 if (!dbus_watch_get_enabled (socket_transport->read_watch))
764 if (_dbus_auth_needs_decoding (transport->auth))
766 /* Does fd passing even make sense with encoded data? */
767 _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
769 if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
770 bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
772 bytes_read = _dbus_read_socket (socket_transport->fd,
773 &socket_transport->encoded_incoming,
774 socket_transport->max_bytes_read_per_iteration);
776 _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
783 _dbus_message_loader_get_buffer (transport->loader,
786 orig_len = _dbus_string_get_length (buffer);
788 if (!_dbus_auth_decode_data (transport->auth,
789 &socket_transport->encoded_incoming,
792 _dbus_verbose ("Out of memory decoding incoming data\n");
793 _dbus_message_loader_return_buffer (transport->loader,
795 _dbus_string_get_length (buffer) - orig_len);
801 _dbus_message_loader_return_buffer (transport->loader,
803 _dbus_string_get_length (buffer) - orig_len);
805 _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
806 _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
811 _dbus_message_loader_get_buffer (transport->loader,
814 #ifdef HAVE_UNIX_FD_PASSING
815 if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
819 if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
821 _dbus_verbose ("Out of memory reading file descriptors\n");
822 _dbus_message_loader_return_buffer (transport->loader, buffer, 0);
827 bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
829 socket_transport->max_bytes_read_per_iteration,
832 if (bytes_read >= 0 && n_fds > 0)
833 _dbus_verbose("Read %i unix fds\n", n_fds);
835 _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
840 bytes_read = _dbus_read_socket (socket_transport->fd,
841 buffer, socket_transport->max_bytes_read_per_iteration);
844 _dbus_message_loader_return_buffer (transport->loader,
846 bytes_read < 0 ? 0 : bytes_read);
851 /* EINTR already handled for us */
853 if (_dbus_get_is_errno_enomem ())
855 _dbus_verbose ("Out of memory in read()/do_reading()\n");
859 else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
863 _dbus_verbose ("Error reading from remote app: %s\n",
864 _dbus_strerror_from_errno ());
865 do_io_error (transport);
869 else if (bytes_read == 0)
871 _dbus_verbose ("Disconnected from remote app\n");
872 do_io_error (transport);
877 _dbus_verbose (" read %d bytes\n", bytes_read);
881 if (!_dbus_transport_queue_messages (transport))
884 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
888 /* Try reading more data until we get EAGAIN and return, or
889 * exceed max bytes per iteration. If in blocking mode of
890 * course we'll block instead of returning.
903 unix_error_with_read_to_come (DBusTransport *itransport,
907 DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
909 if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
912 /* If we have a read watch enabled ...
913 we -might have data incoming ... => handle the HANGUP there */
914 if (watch != transport->read_watch &&
915 _dbus_watch_get_enabled (transport->read_watch))
922 socket_handle_watch (DBusTransport *transport,
926 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
928 _dbus_assert (watch == socket_transport->read_watch ||
929 watch == socket_transport->write_watch);
930 _dbus_assert (watch != NULL);
932 /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
933 * still be in the buffer and do_reading may need several iteration to read
934 * it all (because of its max_bytes_read_per_iteration limit).
936 if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
938 _dbus_verbose ("Hang up or error on watch\n");
939 _dbus_transport_disconnect (transport);
943 if (watch == socket_transport->read_watch &&
944 (flags & DBUS_WATCH_READABLE))
946 dbus_bool_t auth_finished;
948 _dbus_verbose ("handling read watch %p flags = %x\n",
951 if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
954 /* We don't want to do a read immediately following
955 * a successful authentication. This is so we
956 * have a chance to propagate the authentication
957 * state further up. Specifically, we need to
958 * process any pending data from the auth object.
962 if (!do_reading (transport))
964 _dbus_verbose ("no memory to read\n");
970 _dbus_verbose ("Not reading anything since we just completed the authentication\n");
973 else if (watch == socket_transport->write_watch &&
974 (flags & DBUS_WATCH_WRITABLE))
977 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
978 _dbus_connection_has_messages_to_send_unlocked (transport->connection));
980 if (!do_authentication (transport, FALSE, TRUE, NULL))
983 if (!do_writing (transport))
985 _dbus_verbose ("no memory to write\n");
989 /* See if we still need the write watch */
990 check_write_watch (transport);
992 #ifdef DBUS_ENABLE_VERBOSE_MODE
995 if (watch == socket_transport->read_watch)
996 _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
998 else if (watch == socket_transport->write_watch)
999 _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
1002 _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
1003 watch, dbus_watch_get_socket (watch));
1005 #endif /* DBUS_ENABLE_VERBOSE_MODE */
1011 socket_disconnect (DBusTransport *transport)
1013 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1015 _dbus_verbose ("\n");
1017 free_watches (transport);
1019 _dbus_close_socket (socket_transport->fd, NULL);
1020 socket_transport->fd = -1;
1024 socket_connection_set (DBusTransport *transport)
1026 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1028 _dbus_watch_set_handler (socket_transport->write_watch,
1029 _dbus_connection_handle_watch,
1030 transport->connection, NULL);
1032 _dbus_watch_set_handler (socket_transport->read_watch,
1033 _dbus_connection_handle_watch,
1034 transport->connection, NULL);
1036 if (!_dbus_connection_add_watch_unlocked (transport->connection,
1037 socket_transport->write_watch))
1040 if (!_dbus_connection_add_watch_unlocked (transport->connection,
1041 socket_transport->read_watch))
1043 _dbus_connection_remove_watch_unlocked (transport->connection,
1044 socket_transport->write_watch);
1048 check_read_watch (transport);
1049 check_write_watch (transport);
1055 * @todo We need to have a way to wake up the select sleep if
1056 * a new iteration request comes in with a flag (read/write) that
1057 * we're not currently serving. Otherwise a call that just reads
1058 * could block a write call forever (if there are no incoming
1062 socket_do_iteration (DBusTransport *transport,
1064 int timeout_milliseconds)
1066 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1071 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
1072 flags & DBUS_ITERATION_DO_READING ? "read" : "",
1073 flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
1074 timeout_milliseconds,
1075 socket_transport->read_watch,
1076 socket_transport->write_watch,
1077 socket_transport->fd);
1079 /* the passed in DO_READING/DO_WRITING flags indicate whether to
1080 * read/write messages, but regardless of those we may need to block
1081 * for reading/writing to do auth. But if we do reading for auth,
1082 * we don't want to read any messages yet if not given DO_READING.
1085 poll_fd.fd = socket_transport->fd;
1088 if (_dbus_transport_get_is_authenticated (transport))
1090 /* This is kind of a hack; if we have stuff to write, then try
1091 * to avoid the poll. This is probably about a 5% speedup on an
1092 * echo client/server.
1094 * If both reading and writing were requested, we want to avoid this
1095 * since it could have funky effects:
1096 * - both ends spinning waiting for the other one to read
1097 * data so they can finish writing
1098 * - prioritizing all writing ahead of reading
1100 if ((flags & DBUS_ITERATION_DO_WRITING) &&
1101 !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
1102 !transport->disconnected &&
1103 _dbus_connection_has_messages_to_send_unlocked (transport->connection))
1105 do_writing (transport);
1107 if (transport->disconnected ||
1108 !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
1112 /* If we get here, we decided to do the poll() after all */
1113 _dbus_assert (socket_transport->read_watch);
1114 if (flags & DBUS_ITERATION_DO_READING)
1115 poll_fd.events |= _DBUS_POLLIN;
1117 _dbus_assert (socket_transport->write_watch);
1118 if (flags & DBUS_ITERATION_DO_WRITING)
1119 poll_fd.events |= _DBUS_POLLOUT;
1123 DBusAuthState auth_state;
1125 auth_state = _dbus_auth_do_work (transport->auth);
1127 if (transport->receive_credentials_pending ||
1128 auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
1129 poll_fd.events |= _DBUS_POLLIN;
1131 if (transport->send_credentials_pending ||
1132 auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
1133 poll_fd.events |= _DBUS_POLLOUT;
1138 if (flags & DBUS_ITERATION_BLOCK)
1139 poll_timeout = timeout_milliseconds;
1143 /* For blocking selects we drop the connection lock here
1144 * to avoid blocking out connection access during a potentially
1145 * indefinite blocking call. The io path is still protected
1146 * by the io_path_cond condvar, so we won't reenter this.
1148 if (flags & DBUS_ITERATION_BLOCK)
1150 _dbus_verbose ("unlock pre poll\n");
1151 _dbus_connection_unlock (transport->connection);
1155 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
1157 if (poll_res < 0 && _dbus_get_is_errno_eintr ())
1160 if (flags & DBUS_ITERATION_BLOCK)
1162 _dbus_verbose ("lock post poll\n");
1163 _dbus_connection_lock (transport->connection);
1169 poll_fd.revents = 0; /* some concern that posix does not guarantee this;
1170 * valgrind flags it as an error. though it probably
1171 * is guaranteed on linux at least.
1174 if (poll_fd.revents & _DBUS_POLLERR)
1175 do_io_error (transport);
1178 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
1179 dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
1180 dbus_bool_t authentication_completed;
1182 _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
1183 need_read, need_write);
1184 do_authentication (transport, need_read, need_write,
1185 &authentication_completed);
1187 /* See comment in socket_handle_watch. */
1188 if (authentication_completed)
1191 if (need_read && (flags & DBUS_ITERATION_DO_READING))
1192 do_reading (transport);
1193 if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
1194 do_writing (transport);
1199 _dbus_verbose ("Error from _dbus_poll(): %s\n",
1200 _dbus_strerror_from_errno ());
1206 /* We need to install the write watch only if we did not
1207 * successfully write everything. Note we need to be careful that we
1208 * don't call check_write_watch *before* do_writing, since it's
1209 * inefficient to add the write watch, and we can avoid it most of
1210 * the time since we can write immediately.
1212 * However, we MUST always call check_write_watch(); DBusConnection code
1213 * relies on the fact that running an iteration will notice that
1214 * messages are pending.
1216 check_write_watch (transport);
1218 _dbus_verbose (" ... leaving do_iteration()\n");
1222 socket_live_messages_changed (DBusTransport *transport)
1224 /* See if we should look for incoming messages again */
1225 check_read_watch (transport);
1230 socket_get_socket_fd (DBusTransport *transport,
1233 DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
1235 *fd_p = socket_transport->fd;
1240 static const DBusTransportVTable socket_vtable = {
1242 socket_handle_watch,
1244 socket_connection_set,
1245 socket_do_iteration,
1246 socket_live_messages_changed,
1247 socket_get_socket_fd
1251 * Creates a new transport for the given socket file descriptor. The file
1252 * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
1253 * make it so). This function is shared by various transports that
1254 * boil down to a full duplex file descriptor.
1256 * @param fd the file descriptor.
1257 * @param server_guid non-#NULL if this transport is on the server side of a connection
1258 * @param address the transport's address
1259 * @returns the new transport, or #NULL if no memory.
1262 _dbus_transport_new_for_socket (int fd,
1263 const DBusString *server_guid,
1264 const DBusString *address)
1266 DBusTransportSocket *socket_transport;
1268 socket_transport = dbus_new0 (DBusTransportSocket, 1);
1269 if (socket_transport == NULL)
1272 if (!_dbus_string_init (&socket_transport->encoded_outgoing))
1275 if (!_dbus_string_init (&socket_transport->encoded_incoming))
1278 socket_transport->write_watch = _dbus_watch_new (fd,
1279 DBUS_WATCH_WRITABLE,
1282 if (socket_transport->write_watch == NULL)
1285 socket_transport->read_watch = _dbus_watch_new (fd,
1286 DBUS_WATCH_READABLE,
1289 if (socket_transport->read_watch == NULL)
1292 if (!_dbus_transport_init_base (&socket_transport->base,
1294 server_guid, address))
1297 #ifdef HAVE_UNIX_FD_PASSING
1298 _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
1301 socket_transport->fd = fd;
1302 socket_transport->message_bytes_written = 0;
1304 /* These values should probably be tunable or something. */
1305 socket_transport->max_bytes_read_per_iteration = 2048;
1306 socket_transport->max_bytes_written_per_iteration = 2048;
1308 return (DBusTransport*) socket_transport;
1311 _dbus_watch_invalidate (socket_transport->read_watch);
1312 _dbus_watch_unref (socket_transport->read_watch);
1314 _dbus_watch_invalidate (socket_transport->write_watch);
1315 _dbus_watch_unref (socket_transport->write_watch);
1317 _dbus_string_free (&socket_transport->encoded_incoming);
1319 _dbus_string_free (&socket_transport->encoded_outgoing);
1321 dbus_free (socket_transport);
1326 * Creates a new transport for the given hostname and port.
1327 * If host is NULL, it will default to localhost
1329 * @param host the host to connect to
1330 * @param port the port to connect to
1331 * @param family the address family to connect to
1332 * @param path to nonce file
1333 * @param error location to store reason for failure.
1334 * @returns a new transport, or #NULL on failure.
1337 _dbus_transport_new_for_tcp_socket (const char *host,
1340 const char *noncefile,
1344 DBusTransport *transport;
1347 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1349 if (!_dbus_string_init (&address))
1351 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1358 if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
1361 if (!_dbus_string_append (&address, "host=") ||
1362 !_dbus_string_append (&address, host))
1365 if (!_dbus_string_append (&address, ",port=") ||
1366 !_dbus_string_append (&address, port))
1369 if (family != NULL &&
1370 (!_dbus_string_append (&address, ",family=") ||
1371 !_dbus_string_append (&address, family)))
1374 if (noncefile != NULL &&
1375 (!_dbus_string_append (&address, ",noncefile=") ||
1376 !_dbus_string_append (&address, noncefile)))
1379 fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
1382 _DBUS_ASSERT_ERROR_IS_SET (error);
1383 _dbus_string_free (&address);
1387 _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
1390 transport = _dbus_transport_new_for_socket (fd, NULL, &address);
1391 _dbus_string_free (&address);
1392 if (transport == NULL)
1394 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1395 _dbus_close_socket (fd, NULL);
1402 _dbus_string_free (&address);
1403 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1408 * Opens a TCP socket transport.
1410 * @param entry the address entry to try opening as a tcp transport.
1411 * @param transport_p return location for the opened transport
1412 * @param error error to be set
1413 * @returns result of the attempt
1415 DBusTransportOpenResult
1416 _dbus_transport_open_socket(DBusAddressEntry *entry,
1417 DBusTransport **transport_p,
1422 dbus_bool_t isNonceTcp;
1424 method = dbus_address_entry_get_method (entry);
1425 _dbus_assert (method != NULL);
1427 isTcp = strcmp (method, "tcp") == 0;
1428 isNonceTcp = strcmp (method, "nonce-tcp") == 0;
1430 if (isTcp || isNonceTcp)
1432 const char *host = dbus_address_entry_get_value (entry, "host");
1433 const char *port = dbus_address_entry_get_value (entry, "port");
1434 const char *family = dbus_address_entry_get_value (entry, "family");
1435 const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
1437 if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
1438 _dbus_set_bad_address (error, method, "noncefile", NULL);
1439 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1444 _dbus_set_bad_address (error, method, "port", NULL);
1445 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
1448 *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
1449 if (*transport_p == NULL)
1451 _DBUS_ASSERT_ERROR_IS_SET (error);
1452 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
1456 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1457 return DBUS_TRANSPORT_OPEN_OK;
1462 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1463 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;